// Macd // // macd // // Moving Average Convergence Divergence // // MACD = EMA(fast) - EMA(slow), Signal = EMA(MACD) // // Inputs: 1 // Outputs: 3 // Constants: 3 #include #include "ts.h" typedef struct { fp_t fast_k; fp_t slow_k; fp_t signal_k; } ts_macd_params_t; ts_parameter_t const ts_macd_p = { .n_inputs = 1, .n_outputs = 3, .n_constants = 3, .params_size = sizeof(ts_macd_params_t) }; uint_t ts_macd_offset( ts_constant_t const *c ) { ( void )c; return ( c ? (uint_t)(((ts_macd_params_t *)c)->slow_k + ((ts_macd_params_t *)c)->signal_k - 2) : 0 ); } int ts_macd( 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_macd_p ); if ( !c ) return -1; TS_CHECK_INPUT(x, x_n, n); fp_t fast_k = ((ts_macd_params_t *)c)->fast_k; fp_t slow_k = ((ts_macd_params_t *)c)->slow_k; fp_t signal_k = ((ts_macd_params_t *)c)->signal_k; if (fast_k < 1 || slow_k < 1 || signal_k < 1) return -1; if (isnan(fast_k) || isnan(slow_k) || isnan(signal_k)) return -1; if (n == 0) return -1; fp_t fast_a = 2.0 / (fast_k + 1.0); fp_t slow_a = 2.0 / (slow_k + 1.0); fp_t signal_a = 2.0 / (signal_k + 1.0); fp_t fast_ema = x[0][0]; fp_t slow_ema = x[0][0]; uint_t total_offset = (uint_t)(slow_k + signal_k - 2); if (n <= total_offset) return -1; // Compute EMAs up to total_offset for( uint_t i = 1; i <= total_offset; ++i ) { fast_ema = fast_ema + fast_a * ( x[0][i] - fast_ema ); slow_ema = slow_ema + slow_a * ( x[0][i] - slow_ema ); } fp_t macd_line = fast_ema - slow_ema; fp_t signal_ema = macd_line; y[0][total_offset] = macd_line; y[1][total_offset] = signal_ema; y[2][total_offset] = 0; for( uint_t i = total_offset + 1; i < n; ++i ) { fast_ema = fast_ema + fast_a * ( x[0][i] - fast_ema ); slow_ema = slow_ema + slow_a * ( x[0][i] - slow_ema ); macd_line = fast_ema - slow_ema; signal_ema = signal_ema + signal_a * ( macd_line - signal_ema ); y[0][i] = macd_line; y[1][i] = signal_ema; y[2][i] = macd_line - signal_ema; } return 0; }