// ATR Trailing Stops // // atr_trailing_stops - ATR stops // // Upper stop: max(prev, (H+L)/2 + mult*ATR) // Lower stop: min(prev, (H+L)/2 - mult*ATR) // // Inputs: 4 (OHLC) // Outputs: 2 (Upper Stop, Lower Stop) // Constants: 2 (period, multiplier) #include #include "ts.h" typedef struct { uint_t k; fp_t mult; } ts_atr_trailing_stops_params_t; ts_parameter_t const ts_atr_trailing_stops_p = { .n_inputs = 4, .n_outputs = 2, .n_constants = 2, .params_size = sizeof(ts_atr_trailing_stops_params_t) }; uint_t ts_atr_trailing_stops_offset( ts_constant_t const *c ) { ( void )c; return ( c ? ((ts_atr_trailing_stops_params_t *)c)->k : 0 ); } int ts_atr_trailing_stops( 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_atr_trailing_stops_p ); if ( !c ) return -1; uint_t k = ((ts_atr_trailing_stops_params_t *)c)->k; if (k == 0) return -1; if (n < k + 1) return -1; fp_t mult = ((ts_atr_trailing_stops_params_t *)c)->mult; fp_t tr_sum = 0; fp_t atr = 0; for( uint_t i = 1; i < n; ++i ) { fp_t tr = fmax( ts_h( x, i ) - ts_l( x, i ), fmax( fabs( ts_h( x, i ) - ts_c( x, i - 1 ) ), fabs( ts_l( x, i ) - ts_c( x, i - 1 ) ) ) ); if( i < k ) { tr_sum += tr; atr = tr_sum / (fp_t)i; } else if( i == k ) { tr_sum += tr; atr = tr_sum / (fp_t)k; } else { atr = ( atr * ( k - 1 ) + tr ) / k; } if( i >= k ) { fp_t mid = ( ts_h( x, i ) + ts_l( x, i ) ) / 2.0; fp_t calc_upper = mid + mult * atr; fp_t calc_lower = mid - mult * atr; if( i == k ) { y[0][i] = calc_upper; y[1][i] = calc_lower; } else { y[0][i] = fmax( y[0][i - 1], calc_upper ); y[1][i] = fmin( y[1][i - 1], calc_lower ); } } } return 0; }