diff options
Diffstat (limited to 'lib/supertrend.c')
| -rw-r--r-- | lib/supertrend.c | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/lib/supertrend.c b/lib/supertrend.c new file mode 100644 index 0000000..4487e96 --- /dev/null +++ b/lib/supertrend.c @@ -0,0 +1,118 @@ +// Supertrend +// +// supertrend +// +// SuperTrend Indicator +// +// +// +// Inputs: 4 +// Outputs: 2 +// Constants: 2 + + +#include <math.h> +#include "ts.h" + +typedef struct { + uint_t k; + fp_t mult; +} ts_supertrend_params_t; + +ts_parameter_t const ts_supertrend_p = { .n_inputs = 4, .n_outputs = 2, .n_constants = 2, .params_size = sizeof(ts_supertrend_params_t) }; + +uint_t ts_supertrend_offset( ts_constant_t const *c ) +{ + ( void )c; + return ( c ? ((ts_supertrend_params_t *)c)->k : 0 ); +} + +int ts_supertrend( + 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_supertrend_p ); + if ( !c ) return -1; + TS_CHECK_INPUT(x, x_n, n); + uint_t k = ((ts_supertrend_params_t *)c)->k; + fp_t mult = ((ts_supertrend_params_t *)c)->mult; + if (k == 0 || n <= k) return -1; + + 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 = 2; i <= k; ++i ) + { + 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; + atr = atr + (tr - atr) / k; + } + + fp_t median = ( ts_h( x, k ) + ts_l( x, k ) ) / 2.0; + fp_t raw_upper = median + mult * atr; + fp_t raw_lower = median - mult * atr; + + fp_t final_upper = raw_upper; + fp_t final_lower = raw_lower; + int_t trend = 1; + + if( ts_c( x, k ) > raw_lower ) + { + trend = 1; + } + else + { + trend = -1; + } + + y[0][k] = trend == 1 ? final_lower : final_upper; + y[1][k] = trend; + + for( uint_t i = k + 1; i < n; ++i ) + { + 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; + atr = atr + (tr - atr) / k; + + median = ( ts_h( x, i ) + ts_l( x, i ) ) / 2.0; + raw_upper = median + mult * atr; + raw_lower = median - mult * atr; + + if( raw_upper < final_upper || ts_c( x, i - 1 ) > final_upper ) + final_upper = raw_upper; + + if( raw_lower > final_lower || ts_c( x, i - 1 ) < final_lower ) + final_lower = raw_lower; + + int_t new_trend = trend; + + if( trend == 1 ) + { + if( ts_c( x, i ) < final_lower ) + new_trend = -1; + } + else + { + if( ts_c( x, i ) > final_upper ) + new_trend = 1; + } + + trend = new_trend; + y[0][i] = trend == 1 ? final_lower : final_upper; + y[1][i] = trend; + } + return 0; +} + |