summaryrefslogtreecommitdiffstats
path: root/lib/stochastic_momentum_index.c
blob: 5491c305907c01ae53a2c0a77300dae0254c7acb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// Stochastic Momentum Index
//
// stochastic_momentum_index
//
// Stochastic Momentum Index
//
// 
//
// Inputs:    4
// Outputs:   2
// Constants: 3


#include <stdlib.h>
#include <math.h>
#include "ts.h"

typedef struct {
    uint_t k1;
    uint_t k2;
    uint_t signal_period;
} ts_stochastic_momentum_index_params_t;

ts_parameter_t const ts_stochastic_momentum_index_p = { .n_inputs = 4, .n_outputs = 2, .n_constants = 3, .params_size = sizeof(ts_stochastic_momentum_index_params_t) };

uint_t ts_stochastic_momentum_index_offset( ts_constant_t const *c )
{
	( void )c;
	return ( c ? ((ts_stochastic_momentum_index_params_t *)c)->k1 + ((ts_stochastic_momentum_index_params_t *)c)->k2 : 0 );
}

int ts_stochastic_momentum_index(
	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_stochastic_momentum_index_p );
	if ( !c ) return -1;
    uint_t k1 = ((ts_stochastic_momentum_index_params_t *)c)->k1;
    uint_t k2 = ((ts_stochastic_momentum_index_params_t *)c)->k2;
    uint_t signal_period = ((ts_stochastic_momentum_index_params_t *)c)->signal_period;
    if (k1 == 0 || k2 == 0) return -1;

    fp_t *midpoint = calloc(n, sizeof(fp_t));
    fp_t *deviation = calloc(n, sizeof(fp_t));
    if (!midpoint || !deviation) { free(midpoint); free(deviation); return -1; }

    for( uint_t i = 0; i < n; ++i )
    {
        midpoint[i] = (ts_h(x, i) + ts_l(x, i)) / 2.0;
        deviation[i] = ts_c(x, i) - midpoint[i];
    }

    fp_t *sma_dev = calloc(n, sizeof(fp_t));
    fp_t *sma_high = calloc(n, sizeof(fp_t));
    if (!sma_dev || !sma_high) { free(midpoint); free(deviation); free(sma_dev); free(sma_high); return -1; }

    uint_t start = k1 - 1;

    for( uint_t i = start; i < n; ++i )
    {
        fp_t sum_dev = 0;
        fp_t sum_high = 0;

        for( uint_t j = 0; j < k1; ++j )
        {
            sum_dev += deviation[i - j];
            fp_t abs_dev = fabs(deviation[i - j]);
            if( abs_dev > sum_high ) sum_high = abs_dev;
        }

        sma_dev[i] = sum_dev / k1;
        sma_high[i] = sum_high;
    }

    uint_t start2 = start + k2 - 1;

    fp_t *smi = calloc(n, sizeof(fp_t));
    if (!smi) { free(midpoint); free(deviation); free(sma_dev); free(sma_high); free(smi); return -1; }

    for( uint_t i = start2; i < n; ++i )
    {
        fp_t sum_sma_dev = 0;
        fp_t sum_sma_high = 0;

        for( uint_t j = 0; j < k2; ++j )
        {
            sum_sma_dev += sma_dev[i - j];
            sum_sma_high += sma_high[i - j];
        }

        sum_sma_dev /= k2;
        sum_sma_high /= k2;

        if( sum_sma_high == 0 )
            smi[i] = 0;
        else
            smi[i] = (sum_sma_dev / sum_sma_high) * 100;
    }

    fp_t sig_a = 2.0 / (signal_period + 1);
    fp_t signal_ema = 0;
    uint_t signal_init = 0;

    for (uint_t j = 0; j < n && j < start2; ++j) { y[0][j] = 0; y[1][j] = 0; }
    for( uint_t i = start2; i < n; ++i )
    {
        y[0][i] = smi[i];

        if( !signal_init )
        {
            signal_ema = smi[i];
            signal_init = 1;
        }
        else
        {
            signal_ema = signal_ema + sig_a * (smi[i] - signal_ema);
        }
        y[1][i] = signal_ema;
    }

    free(midpoint);
    free(deviation);
    free(sma_dev);
    free(sma_high);
    free(smi);
	return 0;
}