// Hurst Exponent // // hurst_exponent // // Hurst exponent via R/S analysis // // H = slope of linear regression of log(R/S) vs log(n) // // Inputs: 1 // Outputs: 1 // Constants: 1 #include #include "ts.h" typedef struct { uint_t k; } ts_hurst_exponent_params_t; ts_parameter_t const ts_hurst_exponent_p = { .n_inputs = 1, .n_outputs = 1, .n_constants = 1, .params_size = sizeof(ts_hurst_exponent_params_t) }; uint_t ts_hurst_exponent_offset( ts_constant_t const *c ) { ( void )c; return ( 0 ); } int ts_hurst_exponent( fp_t * const *y, uint_t y_n, fp_t const * const *x, uint_t x_n, uint_t n, ts_constant_t const *c ) { TS_PROLOGUE( ts_hurst_exponent_p ); if ( !c ) return -1; uint_t k = ((ts_hurst_exponent_params_t *)c)->k; if (k == 0 || k > n) return -1; for ( uint_t i = 0; i < n; ++i ) { if (i + 1 < k) { y[0][i] = 0; continue; } uint_t data_len = i + 1; uint_t num_lags = 0; fp_t sum_log_s = 0; fp_t sum_log_rs = 0; fp_t sum_log_s2 = 0; fp_t sum_log_s_log_rs = 0; for ( uint_t s = 2; s <= k && s <= data_len / 2; ++s ) { uint_t ns = data_len / s; if (ns == 0) continue; fp_t total_log_rs = 0; uint_t valid_segs = 0; for ( uint_t seg = 0; seg < ns; ++seg ) { uint_t start = seg * s; uint_t end = start + s; if (end > data_len) break; fp_t mean = 0; for ( uint_t p = start; p < end; ++p ) mean += x[0][p]; mean /= (fp_t)s; fp_t cumsum = 0; fp_t max_dev = 0, min_dev = 0; for ( uint_t p = start; p < end; ++p ) { cumsum += x[0][p] - mean; if (cumsum > max_dev) max_dev = cumsum; if (cumsum < min_dev) min_dev = cumsum; } fp_t r = max_dev - min_dev; fp_t std = 0; for ( uint_t p = start; p < end; ++p ) { fp_t d = x[0][p] - mean; std += d * d; } std = sqrt(std / (fp_t)s); if (std > 0 && r > 0) { total_log_rs += log(r / std); valid_segs++; } } if (valid_segs > 0) { fp_t log_s = log((fp_t)s); fp_t mean_log_rs = total_log_rs / (fp_t)valid_segs; sum_log_s += log_s; sum_log_rs += mean_log_rs; sum_log_s2 += log_s * log_s; sum_log_s_log_rs += log_s * mean_log_rs; num_lags++; } } if (num_lags >= 2) { fp_t denom = (fp_t)num_lags * sum_log_s2 - sum_log_s * sum_log_s; if (fabs(denom) > 1e-300) { fp_t h = ((fp_t)num_lags * sum_log_s_log_rs - sum_log_s * sum_log_rs) / denom; y[0][i] = h; } else { y[0][i] = 0; } } else { y[0][i] = 0; } } return 0; }