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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
|
// Schaff Trend Cycle
//
// schaff_trend_cycle
//
// Schaff Trend Cycle
//
//
//
// Inputs: 1
// Outputs: 2
// Constants: 1
#include <stdlib.h>
#include <math.h>
#include "ts.h"
typedef struct {
uint_t period;
} ts_schaff_trend_cycle_params_t;
ts_parameter_t const ts_schaff_trend_cycle_p = { .n_inputs = 1, .n_outputs = 2, .n_constants = 1, .params_size = sizeof(ts_schaff_trend_cycle_params_t) };
uint_t ts_schaff_trend_cycle_offset( ts_constant_t const *c )
{
( void )c;
return ( 52 );
}
int ts_schaff_trend_cycle(
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_schaff_trend_cycle_p );
if ( !c ) return -1;
uint_t period = ((ts_schaff_trend_cycle_params_t const *)c)->period;
if (period == 0) period = 3;
if (period > n) { for (uint_t j = 0; j < n; ++j) { y[0][j] = 0; y[1][j] = 0; } return 0; }
uint_t fast = 10;
uint_t slow = 21;
uint_t rsi_period = 13;
fp_t ema_fast = x[0][0];
fp_t ema_slow = x[0][0];
fp_t a_fast = 2.0 / (fast + 1);
fp_t a_slow = 2.0 / (slow + 1);
fp_t *macd_line = calloc(n, sizeof(fp_t));
if (!macd_line) return -1;
for( uint_t i = 1; i < n; ++i )
{
ema_fast = ema_fast + a_fast * (x[0][i] - ema_fast);
ema_slow = ema_slow + a_slow * (x[0][i] - ema_slow);
macd_line[i] = ema_fast - ema_slow;
}
fp_t *rsi1 = calloc(n, sizeof(fp_t));
fp_t *rsi2 = calloc(n, sizeof(fp_t));
if (!rsi1 || !rsi2) { free(macd_line); free(rsi1); free(rsi2); return -1; }
{
fp_t avg_up = 0, avg_down = 0;
for( uint_t i = 1; i <= rsi_period; ++i )
{
fp_t change = macd_line[i] - macd_line[i - 1];
if( change > 0 ) avg_up += change;
else avg_down += (-change);
}
avg_up /= rsi_period;
avg_down /= rsi_period;
rsi1[rsi_period] = (avg_down == 0) ? 100 : 100 - 100 / (1 + avg_up / avg_down);
for( uint_t i = rsi_period + 1; i < n; ++i )
{
fp_t change = macd_line[i] - macd_line[i - 1];
fp_t gain = change > 0 ? change : 0;
fp_t loss = change < 0 ? (-change) : 0;
avg_up = (avg_up * (rsi_period - 1) + gain) / rsi_period;
avg_down = (avg_down * (rsi_period - 1) + loss) / rsi_period;
rsi1[i] = (avg_down == 0) ? 100 : 100 - 100 / (1 + avg_up / avg_down);
}
}
{
fp_t avg_up = 0, avg_down = 0;
for( uint_t i = rsi_period + 1; i <= rsi_period * 2; ++i )
{
fp_t change = rsi1[i] - rsi1[i - 1];
if( change > 0 ) avg_up += change;
else avg_down += (-change);
}
avg_up /= rsi_period;
avg_down /= rsi_period;
rsi2[rsi_period * 2] = (avg_down == 0) ? 100 : 100 - 100 / (1 + avg_up / avg_down);
for( uint_t i = rsi_period * 2 + 1; i < n; ++i )
{
fp_t change = rsi1[i] - rsi1[i - 1];
fp_t gain = change > 0 ? change : 0;
fp_t loss = change < 0 ? (-change) : 0;
avg_up = (avg_up * (rsi_period - 1) + gain) / rsi_period;
avg_down = (avg_down * (rsi_period - 1) + loss) / rsi_period;
rsi2[i] = (avg_down == 0) ? 100 : 100 - 100 / (1 + avg_up / avg_down);
}
}
uint_t offset = slow + rsi_period * 2;
fp_t sig_a = 1.0 / (fp_t)period;
fp_t signal_ema = 0;
uint_t active = 0;
uint_t count = 0;
for (uint_t j = 0; j < n && j < offset; ++j) { y[0][j] = 0; y[1][j] = 0; }
for( uint_t i = offset; i < n; ++i )
{
fp_t hist = macd_line[i] - macd_line[i - 1];
fp_t hist_prev = (i > 1) ? macd_line[i - 1] - macd_line[i - 2] : 0;
int prev_above = hist_prev > 0.5;
int curr_above = hist > 0.5;
fp_t stc = 0;
if( !prev_above && curr_above )
{
active = 1;
count = 0;
}
if( active )
{
stc = 100;
count++;
if( count >= period )
active = 0;
}
y[0][i] = stc;
signal_ema = signal_ema + sig_a * (stc - signal_ema);
y[1][i] = signal_ema;
}
free(macd_line);
free(rsi1);
free(rsi2);
return 0;
}
|