// Keltner Channel // // keltner_channel // // Keltner Channel // // Middle: EMA, Upper/Lower: EMA ± mult*ATR // // Inputs: 4 // Outputs: 3 // Constants: 1 #include #include "ts.h" typedef struct { uint_t k; } ts_keltner_channel_params_t; ts_parameter_t const ts_keltner_channel_p = { .n_inputs = 4, .n_outputs = 3, .n_constants = 1, .params_size = sizeof(ts_keltner_channel_params_t) }; uint_t ts_keltner_channel_offset( ts_constant_t const *c ) { ( void )c; return ( c ? ((ts_keltner_channel_params_t const *)c)->k : 0 ); } int ts_keltner_channel( 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_keltner_channel_p ); if ( !c ) return -1; uint_t k = ((ts_keltner_channel_params_t const *)c)->k; if (k == 0 || n <= k) return -1; fp_t a = 2.0 / ((fp_t)k + 1.0); fp_t ema_tp = ( ts_h( x, 0 ) + ts_l( x, 0 ) + ts_c( x, 0 ) ) / 3.0; fp_t tr = ts_h( x, 1 ) - ts_l( x, 1 ); fp_t tr2 = fabs( ts_h( x, 1 ) - ts_c( x, 0 ) ); fp_t tr3 = fabs( ts_l( x, 1 ) - ts_c( x, 0 ) ); if( tr2 > tr ) tr = tr2; if( tr3 > tr ) tr = tr3; fp_t atr = tr; for (uint_t i = 0; i < k; ++i) { y[0][i] = 0; y[1][i] = 0; y[2][i] = 0; } for( uint_t i = 1; i < n; ++i ) { fp_t tp = ( ts_h( x, i ) + ts_l( x, i ) + ts_c( x, i ) ) / 3.0; ema_tp = ema_tp + a * ( tp - ema_tp ); tr = ts_h( x, i ) - ts_l( x, i ); tr2 = fabs( ts_h( x, i ) - ts_c( x, i - 1 ) ); tr3 = fabs( ts_l( x, i ) - ts_c( x, i - 1 ) ); if( tr2 > tr ) tr = tr2; if( tr3 > tr ) tr = tr3; if( i >= 2 ) atr = atr + (tr - atr) / k; if( i >= k ) { y[0][i] = ema_tp; y[1][i] = ema_tp + 2.0 * atr; y[2][i] = ema_tp - 2.0 * atr; } } return 0; }