diff options
| author | Ethan Werner <mail@ethanwerner.com> | 2026-07-01 09:42:39 +0400 |
|---|---|---|
| committer | Ethan Werner <mail@ethanwerner.com> | 2026-07-01 09:42:39 +0400 |
| commit | 07e18043145f3d91c8ea7ec3ad41b3c905585277 (patch) | |
| tree | 2bdeae46973f4bdfce263679a4008ac768011f28 /lib/adx.c | |
initial commit: ts time series analysis library v0.1.0
- 354 financial and mathematical time-series indicators
- Uniform C11 API with consistent function signatures
- 349 passing tests with -Werror
- Static and shared library builds
- pkg-config integration
- Python bindings
- Fuzzing and sanitizer support
- Security hardening flags
Diffstat (limited to 'lib/adx.c')
| -rw-r--r-- | lib/adx.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/lib/adx.c b/lib/adx.c new file mode 100644 index 0000000..505732b --- /dev/null +++ b/lib/adx.c @@ -0,0 +1,84 @@ +// Adx +// +// adx +// +// Time series function +// +// See implementation +// +// Inputs: 4 +// Outputs: 4 +// Constants: 1 + + +#include <math.h> +#include <stdint.h> +#include "ts.h" + +typedef struct { + uint_t k; +} ts_adx_params_t; + +ts_parameter_t const ts_adx_p = { .n_inputs = 4, .n_outputs = 4, .n_constants = 1, .params_size = sizeof(ts_adx_params_t) }; + +uint_t ts_adx_offset( ts_constant_t const *c ) +{ + ( void )c; + return ( c ? ((ts_adx_params_t *)c)->k + 1 : 0 ); +} + +int ts_adx( + 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_adx_p ); + if ( !c ) return -1; + TS_CHECK_INPUT(x, x_n, n); + uint_t k = ((ts_adx_params_t *)c)->k; + if (k == 0) return -1; + + fp_t ema_plus = 0, ema_minus = 0, ema_tr = 0; + fp_t prev_dx = 0; + + for( uint_t i = 1; i < n; ++i ) + { + fp_t hdmd = ts_h( x, i ) - ts_h( x, i - 1 ); + fp_t ldml = ts_l( x, i - 1 ) - ts_l( x, i ); + + fp_t plus_dm = hdmd > ldml && hdmd > 0 ? hdmd : 0; + fp_t minus_dm = ldml > hdmd && ldml > 0 ? ldml : 0; + + 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 ) ) ) ); + + ema_plus = i == 1 ? plus_dm + : ema_plus + ( 1.0 / k ) * ( plus_dm - ema_plus ); + ema_minus = i == 1 ? minus_dm + : ema_minus + ( 1.0 / k ) * ( minus_dm - ema_minus ); + ema_tr = i == 1 ? tr + : ema_tr + ( 1.0 / k ) * ( tr - ema_tr ); + + if( i > k ) + { + fp_t di_plus = ema_tr != 0 ? 100.0 * ema_plus / ema_tr : 0; + fp_t di_minus = ema_tr != 0 ? 100.0 * ema_minus / ema_tr : 0; + + y[0][i] = di_plus; + y[1][i] = di_minus; + + fp_t sum = di_plus + di_minus; + fp_t dx = sum != 0 ? 100.0 * fabs( di_plus - di_minus ) / sum : 0; + + y[2][i] = dx; + y[3][i] = i == k + 1 ? dx + : prev_dx + ( 1.0 / k ) * ( dx - prev_dx ); + prev_dx = y[3][i]; + } + } + + return 0; +} + |