hikyuu 2.2.3__py3-none-win_amd64.whl → 2.3.0__py3-none-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. hikyuu/cpp/boost_date_time-mt.dll +0 -0
  2. hikyuu/cpp/boost_serialization-mt.dll +0 -0
  3. hikyuu/cpp/boost_wserialization-mt.dll +0 -0
  4. hikyuu/cpp/core310.pyd +0 -0
  5. hikyuu/cpp/core311.pyd +0 -0
  6. hikyuu/cpp/core312.pyd +0 -0
  7. hikyuu/cpp/core313.pyd +0 -0
  8. hikyuu/cpp/core38.pyd +0 -0
  9. hikyuu/cpp/core39.pyd +0 -0
  10. hikyuu/cpp/hikyuu.dll +0 -0
  11. hikyuu/cpp/hikyuu.lib +0 -0
  12. hikyuu/data/mysql_upgrade/0024.sql +2 -0
  13. hikyuu/draw/__init__.py +12 -6
  14. hikyuu/draw/drawplot/__init__.py +7 -1
  15. hikyuu/draw/drawplot/icon/1.png +0 -0
  16. hikyuu/draw/drawplot/icon/10.png +0 -0
  17. hikyuu/draw/drawplot/icon/11.png +0 -0
  18. hikyuu/draw/drawplot/icon/12.png +0 -0
  19. hikyuu/draw/drawplot/icon/13.png +0 -0
  20. hikyuu/draw/drawplot/icon/14.png +0 -0
  21. hikyuu/draw/drawplot/icon/15.png +0 -0
  22. hikyuu/draw/drawplot/icon/16.png +0 -0
  23. hikyuu/draw/drawplot/icon/17.png +0 -0
  24. hikyuu/draw/drawplot/icon/18.png +0 -0
  25. hikyuu/draw/drawplot/icon/19.png +0 -0
  26. hikyuu/draw/drawplot/icon/2.png +0 -0
  27. hikyuu/draw/drawplot/icon/20.png +0 -0
  28. hikyuu/draw/drawplot/icon/21.png +0 -0
  29. hikyuu/draw/drawplot/icon/22.png +0 -0
  30. hikyuu/draw/drawplot/icon/23.png +0 -0
  31. hikyuu/draw/drawplot/icon/24.png +0 -0
  32. hikyuu/draw/drawplot/icon/25.png +0 -0
  33. hikyuu/draw/drawplot/icon/26.png +0 -0
  34. hikyuu/draw/drawplot/icon/27.png +0 -0
  35. hikyuu/draw/drawplot/icon/28.png +0 -0
  36. hikyuu/draw/drawplot/icon/29.png +0 -0
  37. hikyuu/draw/drawplot/icon/3.png +0 -0
  38. hikyuu/draw/drawplot/icon/30.png +0 -0
  39. hikyuu/draw/drawplot/icon/31.png +0 -0
  40. hikyuu/draw/drawplot/icon/32.png +0 -0
  41. hikyuu/draw/drawplot/icon/33.png +0 -0
  42. hikyuu/draw/drawplot/icon/34.png +0 -0
  43. hikyuu/draw/drawplot/icon/35.png +0 -0
  44. hikyuu/draw/drawplot/icon/36.png +0 -0
  45. hikyuu/draw/drawplot/icon/37.png +0 -0
  46. hikyuu/draw/drawplot/icon/38.png +0 -0
  47. hikyuu/draw/drawplot/icon/39.png +0 -0
  48. hikyuu/draw/drawplot/icon/4.png +0 -0
  49. hikyuu/draw/drawplot/icon/40.png +0 -0
  50. hikyuu/draw/drawplot/icon/41.png +0 -0
  51. hikyuu/draw/drawplot/icon/42.png +0 -0
  52. hikyuu/draw/drawplot/icon/43.png +0 -0
  53. hikyuu/draw/drawplot/icon/44.png +0 -0
  54. hikyuu/draw/drawplot/icon/45.png +0 -0
  55. hikyuu/draw/drawplot/icon/46.png +0 -0
  56. hikyuu/draw/drawplot/icon/47.png +0 -0
  57. hikyuu/draw/drawplot/icon/48.png +0 -0
  58. hikyuu/draw/drawplot/icon/49.png +0 -0
  59. hikyuu/draw/drawplot/icon/5.png +0 -0
  60. hikyuu/draw/drawplot/icon/6.png +0 -0
  61. hikyuu/draw/drawplot/icon/7.png +0 -0
  62. hikyuu/draw/drawplot/icon/8.png +0 -0
  63. hikyuu/draw/drawplot/icon/9.png +0 -0
  64. hikyuu/draw/drawplot/icon/__init__.py +0 -0
  65. hikyuu/draw/drawplot/matplotlib_draw.py +553 -4
  66. hikyuu/examples/notebook/Demo/Demo1.ipynb +85 -84
  67. hikyuu/gui/HikyuuTDX.py +19 -16
  68. hikyuu/gui/data/MainWindow.py +14 -11
  69. hikyuu/gui/hikyuu_small.png +0 -0
  70. hikyuu/hub.py +4 -4
  71. hikyuu/include/hikyuu/DataType.h +3 -1
  72. hikyuu/include/hikyuu/StockManager.h +10 -0
  73. hikyuu/include/hikyuu/config.h +3 -0
  74. hikyuu/include/hikyuu/data_driver/BlockInfoDriver.h +15 -1
  75. hikyuu/include/hikyuu/data_driver/block_info/mysql/MySQLBlockInfoDriver.h +8 -1
  76. hikyuu/include/hikyuu/data_driver/block_info/qianlong/QLBlockInfoDriver.h +3 -1
  77. hikyuu/include/hikyuu/data_driver/block_info/sqlite/SQLiteBlockInfoDriver.h +8 -1
  78. hikyuu/include/hikyuu/indicator/Indicator.h +4 -4
  79. hikyuu/include/hikyuu/indicator/IndicatorImp.h +11 -8
  80. hikyuu/include/hikyuu/indicator/build_in.h +3 -0
  81. hikyuu/include/hikyuu/indicator/crt/CONTEXT.h +30 -0
  82. hikyuu/include/hikyuu/indicator/crt/CORR.h +1 -1
  83. hikyuu/include/hikyuu/indicator/crt/ISLASTBAR.h +30 -0
  84. hikyuu/include/hikyuu/indicator/crt/SPEARMAN.h +2 -2
  85. hikyuu/include/hikyuu/indicator/crt/WMA.h +46 -0
  86. hikyuu/include/hikyuu/indicator/imp/IContext.h +44 -0
  87. hikyuu/include/hikyuu/indicator/imp/ICorr.h +0 -1
  88. hikyuu/include/hikyuu/indicator/imp/IIsLastBar.h +27 -0
  89. hikyuu/include/hikyuu/indicator/imp/ISpearman.h +0 -1
  90. hikyuu/include/hikyuu/indicator/imp/IWma.h +30 -0
  91. hikyuu/include/hikyuu/indicator_talib/__init__.py +1 -0
  92. hikyuu/include/hikyuu/indicator_talib/imp/TaAdosc.h +26 -0
  93. hikyuu/include/hikyuu/indicator_talib/imp/TaApo.h +24 -0
  94. hikyuu/include/hikyuu/indicator_talib/imp/TaBbands.h +24 -0
  95. hikyuu/include/hikyuu/indicator_talib/imp/TaMa.h +24 -0
  96. hikyuu/include/hikyuu/indicator_talib/imp/TaMacd.h +24 -0
  97. hikyuu/include/hikyuu/indicator_talib/imp/TaMacdext.h +24 -0
  98. hikyuu/include/hikyuu/indicator_talib/imp/TaMama.h +24 -0
  99. hikyuu/include/hikyuu/indicator_talib/imp/TaMavp.h +41 -0
  100. hikyuu/include/hikyuu/indicator_talib/imp/TaPpo.h +24 -0
  101. hikyuu/include/hikyuu/indicator_talib/imp/TaSar.h +26 -0
  102. hikyuu/include/hikyuu/indicator_talib/imp/TaSarext.h +31 -0
  103. hikyuu/include/hikyuu/indicator_talib/imp/TaStddev.h +24 -0
  104. hikyuu/include/hikyuu/indicator_talib/imp/TaStoch.h +27 -0
  105. hikyuu/include/hikyuu/indicator_talib/imp/TaStochf.h +26 -0
  106. hikyuu/include/hikyuu/indicator_talib/imp/TaStochrsi.h +24 -0
  107. hikyuu/include/hikyuu/indicator_talib/imp/TaT3.h +24 -0
  108. hikyuu/include/hikyuu/indicator_talib/imp/TaUltosc.h +26 -0
  109. hikyuu/include/hikyuu/indicator_talib/imp/TaVar.h +24 -0
  110. hikyuu/include/hikyuu/indicator_talib/imp/__init__.py +1 -0
  111. hikyuu/include/hikyuu/indicator_talib/imp/ta_defines.h +288 -0
  112. hikyuu/include/hikyuu/indicator_talib/imp/ta_imp.h +1364 -0
  113. hikyuu/include/hikyuu/indicator_talib/ta_crt.h +320 -0
  114. hikyuu/include/hikyuu/trade_manage/OrderBrokerBase.h +25 -0
  115. hikyuu/include/hikyuu/trade_manage/TradeManagerBase.h +0 -4
  116. hikyuu/include/hikyuu/trade_sys/selector/imp/optimal/PerformanceOptimalSelector.h +1 -1
  117. hikyuu/include/hikyuu/utilities/Null.h +33 -0
  118. hikyuu/include/hikyuu/utilities/Parameter.h +9 -9
  119. hikyuu/include/hikyuu/utilities/db_connect/mysql/MySQLStatement.h +1 -0
  120. hikyuu/include/hikyuu/version.h +5 -5
  121. hikyuu/indicator/talib_wrap.py +424 -415
  122. hikyuu/test/Datetime.py +12 -12
  123. hikyuu/test/Indicator.py +36 -36
  124. hikyuu/test/KData.py +11 -11
  125. hikyuu/test/Stock.py +10 -10
  126. {hikyuu-2.2.3.dist-info → hikyuu-2.3.0.dist-info}/METADATA +26 -3
  127. {hikyuu-2.2.3.dist-info → hikyuu-2.3.0.dist-info}/RECORD +131 -52
  128. {hikyuu-2.2.3.dist-info → hikyuu-2.3.0.dist-info}/top_level.txt +3 -0
  129. hikyuu/sqlite3.dll +0 -0
  130. hikyuu/vcruntime140.dll +0 -0
  131. hikyuu/vcruntime140_1.dll +0 -0
  132. {hikyuu-2.2.3.dist-info → hikyuu-2.3.0.dist-info}/LICENSE +0 -0
  133. {hikyuu-2.2.3.dist-info → hikyuu-2.3.0.dist-info}/WHEEL +0 -0
  134. {hikyuu-2.2.3.dist-info → hikyuu-2.3.0.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,1364 @@
1
+ /*
2
+ * Copyright (c) 2024 hikyuu.org
3
+ *
4
+ * Created on: 2024-12-20
5
+ * Author: fasiondog
6
+ */
7
+
8
+ #pragma once
9
+
10
+ #define EXPOERT_TA_FUNC(func) BOOST_CLASS_EXPORT(hku::Cls_##func)
11
+
12
+ #define TA_IN1_OUT1_IMP(func, func_lookback) \
13
+ Cls_##func::Cls_##func() : IndicatorImp(#func, 1) {} \
14
+ Cls_##func::~Cls_##func() {} \
15
+ \
16
+ void Cls_##func::_calculate(const Indicator &data) { \
17
+ int lookback = func_lookback(); \
18
+ size_t total = data.size(); \
19
+ if (lookback < 0) { \
20
+ m_discard = total; \
21
+ return; \
22
+ } \
23
+ m_discard = data.discard() + lookback; \
24
+ if (m_discard >= total) { \
25
+ m_discard = total; \
26
+ return; \
27
+ } \
28
+ \
29
+ auto const *src = data.data(); \
30
+ auto *dst = this->data(); \
31
+ int outBegIdx; \
32
+ int outNbElement; \
33
+ func(m_discard, total - 1, src, &outBegIdx, &outNbElement, dst + m_discard); \
34
+ HKU_ASSERT((outBegIdx == m_discard) && (outBegIdx + outNbElement) <= total); \
35
+ } \
36
+ \
37
+ Indicator HKU_API func() { \
38
+ return Indicator(make_shared<Cls_##func>()); \
39
+ }
40
+
41
+ #define TA_IN1_OUT1_INT_IMP(func, func_lookback) \
42
+ Cls_##func::Cls_##func() : IndicatorImp(#func, 1) {} \
43
+ Cls_##func::~Cls_##func() {} \
44
+ \
45
+ void Cls_##func::_calculate(const Indicator &data) { \
46
+ int lookback = func_lookback(); \
47
+ size_t total = data.size(); \
48
+ if (lookback < 0) { \
49
+ m_discard = total; \
50
+ return; \
51
+ } \
52
+ \
53
+ m_discard = data.discard() + lookback; \
54
+ if (m_discard >= total) { \
55
+ m_discard = total; \
56
+ return; \
57
+ } \
58
+ \
59
+ auto const *src = data.data(); \
60
+ std::unique_ptr<int[]> buf = std::make_unique<int[]>(total); \
61
+ int outBegIdx; \
62
+ int outNbElement; \
63
+ func(m_discard, total - 1, src, &outBegIdx, &outNbElement, buf.get()); \
64
+ HKU_ASSERT((outBegIdx == m_discard) && (outBegIdx + outNbElement) <= total); \
65
+ m_discard = outBegIdx; \
66
+ auto *dst = this->data(); \
67
+ dst = dst + outBegIdx; \
68
+ for (int i = 0; i < outNbElement; ++i) { \
69
+ dst[i] = buf[i]; \
70
+ } \
71
+ } \
72
+ \
73
+ Indicator HKU_API func() { \
74
+ return Indicator(make_shared<Cls_##func>()); \
75
+ }
76
+
77
+ #define TA_IN1_OUT1_N_IMP(func, func_lookback, period, period_min, period_max) \
78
+ Cls_##func::Cls_##func() : IndicatorImp(#func, 1) { \
79
+ setParam<int>("n", period); \
80
+ } \
81
+ Cls_##func::~Cls_##func() {} \
82
+ \
83
+ void Cls_##func::_checkParam(const string &name) const { \
84
+ if (name == "n") { \
85
+ int n = getParam<int>("n"); \
86
+ HKU_ASSERT(n >= period_min && n <= period_max); \
87
+ } \
88
+ } \
89
+ \
90
+ void Cls_##func::_calculate(const Indicator &data) { \
91
+ int n = getParam<int>("n"); \
92
+ int lookback = func_lookback(n); \
93
+ size_t total = data.size(); \
94
+ if (lookback < 0) { \
95
+ m_discard = total; \
96
+ return; \
97
+ } \
98
+ \
99
+ m_discard = data.discard() + lookback; \
100
+ if (m_discard >= total) { \
101
+ m_discard = total; \
102
+ return; \
103
+ } \
104
+ \
105
+ auto const *src = data.data(); \
106
+ auto *dst = this->data(); \
107
+ \
108
+ int outBegIdx; \
109
+ int outNbElement; \
110
+ func(m_discard, total - 1, src, n, &outBegIdx, &outNbElement, dst + m_discard); \
111
+ HKU_ASSERT((outBegIdx == m_discard) && (outBegIdx + outNbElement) <= total); \
112
+ } \
113
+ \
114
+ void Cls_##func::_dyn_run_one_step(const Indicator &ind, size_t curPos, size_t step) { \
115
+ int back = func_lookback(step); \
116
+ HKU_IF_RETURN(back<0 || back + ind.discard()> curPos, void()); \
117
+ \
118
+ std::unique_ptr<double[]> buf = std::make_unique<double[]>(curPos); \
119
+ auto const *src = ind.data(); \
120
+ int outBegIdx; \
121
+ int outNbElement; \
122
+ func(ind.discard(), curPos, src, step, &outBegIdx, &outNbElement, buf.get()); \
123
+ if (outNbElement >= 1) { \
124
+ _set(buf.get()[outNbElement - 1], curPos); \
125
+ } \
126
+ } \
127
+ \
128
+ Indicator HKU_API func(int n) { \
129
+ auto p = make_shared<Cls_##func>(); \
130
+ p->setParam<int>("n", n); \
131
+ return Indicator(p); \
132
+ } \
133
+ \
134
+ Indicator HKU_API func(const IndParam &n) { \
135
+ IndicatorImpPtr p = make_shared<Cls_##func>(); \
136
+ p->setIndParam("n", n); \
137
+ return Indicator(p); \
138
+ }
139
+
140
+ #define TA_IN1_OUT1_INT_N_IMP(func, func_lookback, period, period_min, period_max) \
141
+ Cls_##func::Cls_##func() : IndicatorImp(#func, 1) { \
142
+ setParam<int>("n", period); \
143
+ } \
144
+ Cls_##func::~Cls_##func() {} \
145
+ \
146
+ void Cls_##func::_checkParam(const string &name) const { \
147
+ if (name == "n") { \
148
+ int n = getParam<int>("n"); \
149
+ HKU_ASSERT(n >= period_min && n <= period_max); \
150
+ } \
151
+ } \
152
+ \
153
+ void Cls_##func::_calculate(const Indicator &data) { \
154
+ int n = getParam<int>("n"); \
155
+ int lookback = func_lookback(n); \
156
+ size_t total = data.size(); \
157
+ if (lookback < 0) { \
158
+ m_discard = total; \
159
+ return; \
160
+ } \
161
+ \
162
+ m_discard = data.discard() + lookback; \
163
+ if (m_discard >= total) { \
164
+ m_discard = total; \
165
+ return; \
166
+ } \
167
+ \
168
+ auto const *src = data.data(); \
169
+ std::unique_ptr<int[]> buf = std::make_unique<int[]>(total); \
170
+ int outBegIdx; \
171
+ int outNbElement; \
172
+ func(m_discard, total - 1, src, n, &outBegIdx, &outNbElement, buf.get()); \
173
+ HKU_ASSERT((outBegIdx == m_discard) && (outBegIdx + outNbElement) <= total); \
174
+ m_discard = outBegIdx; \
175
+ auto *dst = this->data(); \
176
+ dst = dst + outBegIdx; \
177
+ for (int i = 0; i < outNbElement; ++i) { \
178
+ dst[i] = buf[i]; \
179
+ } \
180
+ } \
181
+ \
182
+ void Cls_##func::_dyn_run_one_step(const Indicator &ind, size_t curPos, size_t step) { \
183
+ int back = func_lookback(step); \
184
+ HKU_IF_RETURN(back<0 || back + ind.discard()> curPos, void()); \
185
+ \
186
+ std::unique_ptr<int[]> buf = std::make_unique<int[]>(curPos); \
187
+ auto const *src = ind.data(); \
188
+ int outBegIdx; \
189
+ int outNbElement; \
190
+ func(ind.discard(), curPos, src, step, &outBegIdx, &outNbElement, buf.get()); \
191
+ if (outNbElement >= 1) { \
192
+ _set(buf.get()[outNbElement - 1], curPos); \
193
+ } \
194
+ } \
195
+ \
196
+ Indicator HKU_API func(int n) { \
197
+ auto p = make_shared<Cls_##func>(); \
198
+ p->setParam<int>("n", n); \
199
+ return Indicator(p); \
200
+ } \
201
+ \
202
+ Indicator HKU_API func(const IndParam &n) { \
203
+ IndicatorImpPtr p = make_shared<Cls_##func>(); \
204
+ p->setIndParam("n", n); \
205
+ return Indicator(p); \
206
+ }
207
+
208
+ #define TA_IN1_OUT2_IMP(func, func_lookback) \
209
+ Cls_##func::Cls_##func() : IndicatorImp(#func, 2) {} \
210
+ Cls_##func::~Cls_##func() {} \
211
+ void Cls_##func::_calculate(const Indicator &data) { \
212
+ size_t total = data.size(); \
213
+ int lookback = func_lookback(); \
214
+ if (lookback < 0) { \
215
+ m_discard = total; \
216
+ return; \
217
+ } \
218
+ m_discard = data.discard() + lookback; \
219
+ if (m_discard >= total) { \
220
+ m_discard = total; \
221
+ return; \
222
+ } \
223
+ \
224
+ auto const *src = data.data(); \
225
+ auto *dst0 = this->data(0); \
226
+ auto *dst1 = this->data(1); \
227
+ \
228
+ int outBegIdx; \
229
+ int outNbElement; \
230
+ func(m_discard, total - 1, src, &outBegIdx, &outNbElement, dst0 + m_discard, \
231
+ dst1 + m_discard); \
232
+ HKU_ASSERT(outBegIdx == m_discard && (outBegIdx + outNbElement) <= total); \
233
+ } \
234
+ \
235
+ Indicator HKU_API func() { \
236
+ return Indicator(make_shared<Cls_##func>()); \
237
+ }
238
+
239
+ #define TA_IN1_OUT2_INT_N_IMP(func, func_lookback, period, period_min, period_max) \
240
+ Cls_##func::Cls_##func() : IndicatorImp(#func, 2) { \
241
+ setParam<int>("n", period); \
242
+ } \
243
+ Cls_##func::~Cls_##func() {} \
244
+ \
245
+ void Cls_##func::_checkParam(const string &name) const { \
246
+ if (name == "n") { \
247
+ int n = getParam<int>("n"); \
248
+ HKU_ASSERT(n >= period_min && n <= period_max); \
249
+ } \
250
+ } \
251
+ \
252
+ void Cls_##func::_calculate(const Indicator &data) { \
253
+ int n = getParam<int>("n"); \
254
+ int lookback = func_lookback(n); \
255
+ size_t total = data.size(); \
256
+ if (lookback < 0) { \
257
+ m_discard = total; \
258
+ return; \
259
+ } \
260
+ \
261
+ m_discard = data.discard() + lookback; \
262
+ if (m_discard >= total) { \
263
+ m_discard = total; \
264
+ return; \
265
+ } \
266
+ \
267
+ auto const *src = data.data(); \
268
+ std::unique_ptr<int[]> buf = std::make_unique<int[]>(2 * (total)); \
269
+ int *buf0 = buf.get(); \
270
+ int *buf1 = buf0 + total; \
271
+ int outBegIdx; \
272
+ int outNbElement; \
273
+ func(m_discard, total - 1, src, n, &outBegIdx, &outNbElement, buf0, buf1); \
274
+ HKU_ASSERT((outBegIdx == m_discard) && (outBegIdx + outNbElement) <= total); \
275
+ m_discard = outBegIdx; \
276
+ auto *dst0 = this->data(0) + outBegIdx; \
277
+ auto *dst1 = this->data(1) + outBegIdx; \
278
+ for (int i = 0; i < outNbElement; ++i) { \
279
+ dst0[i] = buf0[i]; \
280
+ dst1[i] = buf1[i]; \
281
+ } \
282
+ } \
283
+ \
284
+ void Cls_##func::_dyn_run_one_step(const Indicator &ind, size_t curPos, size_t step) { \
285
+ int back = func_lookback(step); \
286
+ HKU_IF_RETURN(back<0 || back + ind.discard()> curPos, void()); \
287
+ \
288
+ std::unique_ptr<int[]> buf = std::make_unique<int[]>(2 * curPos); \
289
+ int *buf0 = buf.get(); \
290
+ int *buf1 = buf0 + curPos; \
291
+ auto const *src = ind.data(); \
292
+ int outBegIdx; \
293
+ int outNbElement; \
294
+ func(ind.discard(), curPos, src, step, &outBegIdx, &outNbElement, buf0, buf1); \
295
+ if (outNbElement >= 1) { \
296
+ _set(buf0[outNbElement - 1], curPos, 0); \
297
+ _set(buf1[outNbElement - 1], curPos, 1); \
298
+ } \
299
+ } \
300
+ \
301
+ Indicator HKU_API func(int n) { \
302
+ auto p = make_shared<Cls_##func>(); \
303
+ p->setParam<int>("n", n); \
304
+ return Indicator(p); \
305
+ } \
306
+ \
307
+ Indicator HKU_API func(const IndParam &n) { \
308
+ IndicatorImpPtr p = make_shared<Cls_##func>(); \
309
+ p->setIndParam("n", n); \
310
+ return Indicator(p); \
311
+ }
312
+
313
+ #define TA_IN1_OUT2_N_IMP(func, func_lookback, period, period_min, period_max) \
314
+ Cls_##func::Cls_##func() : IndicatorImp(#func, 2) { \
315
+ setParam<int>("n", period); \
316
+ } \
317
+ Cls_##func::~Cls_##func() {} \
318
+ \
319
+ void Cls_##func::_checkParam(const string &name) const { \
320
+ if (name == "n") { \
321
+ int n = getParam<int>("n"); \
322
+ HKU_ASSERT(n >= period_min && n <= period_max); \
323
+ } \
324
+ } \
325
+ \
326
+ void Cls_##func::_calculate(const Indicator &data) { \
327
+ int n = getParam<int>("n"); \
328
+ size_t total = data.size(); \
329
+ int lookback = func_lookback(n); \
330
+ if (lookback < 0) { \
331
+ m_discard = total; \
332
+ return; \
333
+ } \
334
+ m_discard = data.discard() + lookback; \
335
+ if (m_discard >= total) { \
336
+ m_discard = total; \
337
+ return; \
338
+ } \
339
+ \
340
+ auto const *src = data.data(); \
341
+ auto *dst0 = this->data(0); \
342
+ auto *dst1 = this->data(1); \
343
+ \
344
+ int outBegIdx; \
345
+ int outNbElement; \
346
+ func(m_discard, total - 1, src, n, &outBegIdx, &outNbElement, dst0 + m_discard, \
347
+ dst1 + m_discard); \
348
+ HKU_ASSERT((outBegIdx == m_discard) && (outBegIdx + outNbElement) <= total); \
349
+ } \
350
+ \
351
+ void Cls_##func::_dyn_run_one_step(const Indicator &ind, size_t curPos, size_t step) { \
352
+ int back = func_lookback(step); \
353
+ HKU_IF_RETURN(back<0 || back + ind.discard()> curPos, void()); \
354
+ \
355
+ std::unique_ptr<double[]> buf = std::make_unique<double[]>(2 * curPos); \
356
+ double *dst0 = buf.get(); \
357
+ double *ds1 = dst0 + curPos; \
358
+ auto const *src = ind.data(); \
359
+ int outBegIdx; \
360
+ int outNbElement; \
361
+ func(ind.discard(), curPos, src, step, &outBegIdx, &outNbElement, dst0, ds1); \
362
+ if (outNbElement >= 1) { \
363
+ _set(dst0[outNbElement - 1], curPos, 0); \
364
+ _set(ds1[outNbElement - 1], curPos, 1); \
365
+ } \
366
+ } \
367
+ \
368
+ Indicator HKU_API func(int n) { \
369
+ auto p = make_shared<Cls_##func>(); \
370
+ p->setParam<int>("n", n); \
371
+ return Indicator(p); \
372
+ } \
373
+ \
374
+ Indicator HKU_API func(const IndParam &n) { \
375
+ IndicatorImpPtr p = make_shared<Cls_##func>(); \
376
+ p->setIndParam("n", n); \
377
+ return Indicator(p); \
378
+ }
379
+
380
+ #define TA_IN1_OUT3_N_IMP(func, func_lookback, period, period_min, period_max) \
381
+ Cls_##func::Cls_##func() : IndicatorImp(#func, 3) { \
382
+ setParam<int>("n", period); \
383
+ } \
384
+ Cls_##func::~Cls_##func() {} \
385
+ \
386
+ void Cls_##func::_checkParam(const string &name) const { \
387
+ if (name == "n") { \
388
+ int n = getParam<int>("n"); \
389
+ HKU_ASSERT(n >= period_min && n <= period_max); \
390
+ } \
391
+ } \
392
+ \
393
+ void Cls_##func::_calculate(const Indicator &data) { \
394
+ int n = getParam<int>("n"); \
395
+ size_t total = data.size(); \
396
+ int lookback = func_lookback(n); \
397
+ if (lookback < 0) { \
398
+ m_discard = total; \
399
+ return; \
400
+ } \
401
+ m_discard = data.discard() + lookback; \
402
+ if (m_discard >= total) { \
403
+ m_discard = total; \
404
+ return; \
405
+ } \
406
+ \
407
+ auto const *src = data.data(); \
408
+ auto *dst0 = this->data(0); \
409
+ auto *dst1 = this->data(1); \
410
+ auto *dst2 = this->data(2); \
411
+ \
412
+ int outBegIdx; \
413
+ int outNbElement; \
414
+ func(m_discard, total - 1, src, n, &outBegIdx, &outNbElement, dst0 + m_discard, \
415
+ dst1 + m_discard, dst2 + m_discard); \
416
+ HKU_ASSERT((outBegIdx == m_discard) && (outBegIdx + outNbElement) <= total); \
417
+ } \
418
+ \
419
+ void Cls_##func::_dyn_run_one_step(const Indicator &ind, size_t curPos, size_t step) { \
420
+ int back = func_lookback(step); \
421
+ HKU_IF_RETURN(back<0 || back + ind.discard()> curPos, void()); \
422
+ \
423
+ std::unique_ptr<double[]> buf = std::make_unique<double[]>(3 * curPos); \
424
+ double *dst0 = buf.get(); \
425
+ double *ds1 = dst0 + curPos; \
426
+ double *ds2 = ds1 + curPos; \
427
+ auto const *src = ind.data(); \
428
+ int outBegIdx; \
429
+ int outNbElement; \
430
+ func(ind.discard(), curPos, src, step, &outBegIdx, &outNbElement, dst0, ds1, ds2); \
431
+ if (outNbElement >= 1) { \
432
+ _set(dst0[outNbElement - 1], curPos, 0); \
433
+ _set(ds1[outNbElement - 1], curPos, 1); \
434
+ _set(ds2[outNbElement - 1], curPos, 2); \
435
+ } \
436
+ } \
437
+ \
438
+ Indicator HKU_API func(int n) { \
439
+ auto p = make_shared<Cls_##func>(); \
440
+ p->setParam<int>("n", n); \
441
+ return Indicator(p); \
442
+ } \
443
+ \
444
+ Indicator HKU_API func(const IndParam &n) { \
445
+ IndicatorImpPtr p = make_shared<Cls_##func>(); \
446
+ p->setIndParam("n", n); \
447
+ return Indicator(p); \
448
+ }
449
+
450
+ #define TA_IN2_OUT1_IMP(func, func_lookback) \
451
+ Cls_##func::Cls_##func() : IndicatorImp(#func, 1) {} \
452
+ Cls_##func::Cls_##func(const Indicator &ref_ind) \
453
+ : IndicatorImp(#func, 1), m_ref_ind(ref_ind) {} \
454
+ Cls_##func::~Cls_##func() {} \
455
+ IndicatorImpPtr Cls_##func::_clone() { \
456
+ auto p = make_shared<Cls_##func>(); \
457
+ p->m_ref_ind = m_ref_ind.clone(); \
458
+ return p; \
459
+ } \
460
+ \
461
+ void Cls_##func::_calculate(const Indicator &ind) { \
462
+ size_t total = ind.size(); \
463
+ HKU_IF_RETURN(total == 0, void()); \
464
+ \
465
+ _readyBuffer(total, 1); \
466
+ \
467
+ auto k = getContext(); \
468
+ m_ref_ind.setContext(k); \
469
+ Indicator ref = m_ref_ind; \
470
+ auto dates = ref.getDatetimeList(); \
471
+ if (dates.empty()) { \
472
+ if (ref.size() > ind.size()) { \
473
+ ref = SLICE(ref, ref.size() - ind.size(), ref.size()); \
474
+ } else if (ref.size() < ind.size()) { \
475
+ ref = CVAL(ind, 0.) + ref; \
476
+ } \
477
+ } else if (m_ref_ind.size() != ind.size()) { \
478
+ ref = ALIGN(m_ref_ind, ind); \
479
+ } \
480
+ \
481
+ int lookback = func_lookback(); \
482
+ if (lookback < 0) { \
483
+ m_discard = total; \
484
+ return; \
485
+ } \
486
+ \
487
+ size_t in_discard = std::max(ind.discard(), ref.discard()); \
488
+ m_discard = lookback + in_discard; \
489
+ if (m_discard >= total) { \
490
+ m_discard = total; \
491
+ return; \
492
+ } \
493
+ \
494
+ const auto *src0 = ind.data(); \
495
+ const auto *src1 = ref.data(); \
496
+ auto *dst = this->data(); \
497
+ int outBegIdx; \
498
+ int outNbElement; \
499
+ func(m_discard, total - 1, src0, src1, &outBegIdx, &outNbElement, dst + m_discard); \
500
+ HKU_ASSERT((outBegIdx == m_discard) && (outBegIdx + outNbElement) <= total); \
501
+ } \
502
+ \
503
+ Indicator HKU_API func() { \
504
+ return Indicator(make_shared<Cls_##func>()); \
505
+ } \
506
+ \
507
+ Indicator HKU_API func(const Indicator &ind1, const Indicator &ind2) { \
508
+ auto p = make_shared<Cls_##func>(ind2); \
509
+ Indicator result(p); \
510
+ return result(ind1); \
511
+ }
512
+
513
+ #define TA_IN2_OUT1_N_IMP(func, func_lookback, period, period_min, period_max) \
514
+ Cls_##func::Cls_##func() : IndicatorImp(#func, 1) { \
515
+ setParam<int>("n", period); \
516
+ } \
517
+ \
518
+ Cls_##func::Cls_##func(int n) : IndicatorImp(#func, 1) { \
519
+ setParam<int>("n", n); \
520
+ } \
521
+ \
522
+ Cls_##func::Cls_##func(const Indicator &ref_ind, int n) \
523
+ : IndicatorImp(#func, 1), m_ref_ind(ref_ind) { \
524
+ setParam<int>("n", n); \
525
+ } \
526
+ \
527
+ Cls_##func::~Cls_##func() {} \
528
+ \
529
+ void Cls_##func::_checkParam(const string &name) const { \
530
+ if ("n" == name) { \
531
+ int n = getParam<int>("n"); \
532
+ HKU_ASSERT(n >= period_min && n <= period_max); \
533
+ } \
534
+ } \
535
+ \
536
+ IndicatorImpPtr Cls_##func::_clone() { \
537
+ auto p = make_shared<Cls_##func>(); \
538
+ p->m_ref_ind = m_ref_ind.clone(); \
539
+ return p; \
540
+ } \
541
+ \
542
+ void Cls_##func::_calculate(const Indicator &ind) { \
543
+ size_t total = ind.size(); \
544
+ HKU_IF_RETURN(total == 0, void()); \
545
+ \
546
+ _readyBuffer(total, 1); \
547
+ \
548
+ auto k = getContext(); \
549
+ m_ref_ind.setContext(k); \
550
+ Indicator ref = m_ref_ind; \
551
+ auto dates = ref.getDatetimeList(); \
552
+ if (dates.empty()) { \
553
+ if (ref.size() > ind.size()) { \
554
+ ref = SLICE(ref, ref.size() - ind.size(), ref.size()); \
555
+ } else if (ref.size() < ind.size()) { \
556
+ ref = CVAL(ind, 0.) + ref; \
557
+ } \
558
+ } else if (m_ref_ind.size() != ind.size()) { \
559
+ ref = ALIGN(m_ref_ind, ind); \
560
+ } \
561
+ \
562
+ int n = getParam<int>("n"); \
563
+ int lookback = func_lookback(n); \
564
+ if (lookback < 0) { \
565
+ m_discard = total; \
566
+ return; \
567
+ } \
568
+ \
569
+ size_t in_discard = std::max(ind.discard(), ref.discard()); \
570
+ m_discard = lookback + in_discard; \
571
+ if (m_discard >= total) { \
572
+ m_discard = total; \
573
+ return; \
574
+ } \
575
+ \
576
+ const auto *src0 = ind.data(); \
577
+ const auto *src1 = ref.data(); \
578
+ auto *dst = this->data(); \
579
+ int outBegIdx; \
580
+ int outNbElement; \
581
+ func(m_discard, total - 1, src0, src1, n, &outBegIdx, &outNbElement, dst + m_discard); \
582
+ HKU_ASSERT((outBegIdx == m_discard) && (outBegIdx + outNbElement) <= total); \
583
+ } \
584
+ \
585
+ Indicator HKU_API func(int n) { \
586
+ return Indicator(make_shared<Cls_##func>(n)); \
587
+ } \
588
+ \
589
+ Indicator HKU_API func(const Indicator &ind1, const Indicator &ind2, int n) { \
590
+ auto p = make_shared<Cls_##func>(ind2, n); \
591
+ HKU_WARN_IF(ind2.size() == 0, "The lenght of ind2 is zero!"); \
592
+ Indicator result(p); \
593
+ return result(ind1); \
594
+ }
595
+
596
+ #define TA_OHLC_OUT1_IMP(func, func_lookback) \
597
+ Cls_##func::Cls_##func() : IndicatorImp(#func, 1) {} \
598
+ \
599
+ Cls_##func::Cls_##func(const KData &k) : IndicatorImp(#func, 1) { \
600
+ setParam<KData>("kdata", k); \
601
+ Cls_##func::_calculate(Indicator()); \
602
+ } \
603
+ \
604
+ void Cls_##func::_calculate(const Indicator &data) { \
605
+ HKU_WARN_IF(!isLeaf() && !data.empty(), \
606
+ "The input is ignored because {} depends on the context!", m_name); \
607
+ \
608
+ KData k = getContext(); \
609
+ size_t total = k.size(); \
610
+ HKU_IF_RETURN(total == 0, void()); \
611
+ \
612
+ _readyBuffer(total, 1); \
613
+ int lookback = func_lookback(); \
614
+ if (lookback < 0 || lookback >= total) { \
615
+ m_discard = total; \
616
+ return; \
617
+ } \
618
+ \
619
+ const KRecord *kptr = k.data(); \
620
+ std::unique_ptr<double[]> buf = std::make_unique<double[]>(4 * total); \
621
+ double *open = buf.get(); \
622
+ double *high = open + total; \
623
+ double *low = high + total; \
624
+ double *close = low + total; \
625
+ for (size_t i = 0; i < total; ++i) { \
626
+ open[i] = kptr[i].openPrice; \
627
+ high[i] = kptr[i].highPrice; \
628
+ low[i] = kptr[i].lowPrice; \
629
+ close[i] = kptr[i].closePrice; \
630
+ } \
631
+ \
632
+ m_discard = lookback; \
633
+ auto *dst = this->data(); \
634
+ int outBegIdx; \
635
+ int outNbElement; \
636
+ func(m_discard, total - 1, open, high, low, close, &outBegIdx, &outNbElement, \
637
+ dst + m_discard); \
638
+ HKU_ASSERT((outBegIdx == m_discard) && (outBegIdx + outNbElement) <= total); \
639
+ } \
640
+ \
641
+ Indicator HKU_API func() { \
642
+ return make_shared<Cls_##func>()->calculate(); \
643
+ } \
644
+ \
645
+ Indicator HKU_API func(const KData &k) { \
646
+ return Indicator(make_shared<Cls_##func>(k)); \
647
+ }
648
+
649
+ #define TA_OHLC_OUT1_INT_IMP(func, func_lookback) \
650
+ Cls_##func::Cls_##func() : IndicatorImp(#func, 1) {} \
651
+ \
652
+ Cls_##func::Cls_##func(const KData &k) : IndicatorImp(#func, 1) { \
653
+ setParam<KData>("kdata", k); \
654
+ Cls_##func::_calculate(Indicator()); \
655
+ } \
656
+ \
657
+ void Cls_##func::_calculate(const Indicator &data) { \
658
+ HKU_WARN_IF(!isLeaf() && !data.empty(), \
659
+ "The input is ignored because {} depends on the context!", m_name); \
660
+ \
661
+ KData k = getContext(); \
662
+ size_t total = k.size(); \
663
+ HKU_IF_RETURN(total == 0, void()); \
664
+ \
665
+ _readyBuffer(total, 1); \
666
+ \
667
+ int lookback = func_lookback(); \
668
+ if (lookback < 0 || lookback >= total) { \
669
+ m_discard = total; \
670
+ return; \
671
+ } \
672
+ \
673
+ const KRecord *kptr = k.data(); \
674
+ std::unique_ptr<double[]> buf = std::make_unique<double[]>(4 * total); \
675
+ double *open = buf.get(); \
676
+ double *high = open + total; \
677
+ double *low = high + total; \
678
+ double *close = low + total; \
679
+ for (size_t i = 0; i < total; ++i) { \
680
+ open[i] = kptr[i].openPrice; \
681
+ high[i] = kptr[i].highPrice; \
682
+ low[i] = kptr[i].lowPrice; \
683
+ close[i] = kptr[i].closePrice; \
684
+ } \
685
+ \
686
+ std::unique_ptr<int[]> outbuf = std::make_unique<int[]>(total); \
687
+ int outBegIdx; \
688
+ int outNbElement; \
689
+ m_discard = lookback; \
690
+ func(m_discard, total - 1, open, high, low, close, &outBegIdx, &outNbElement, \
691
+ outbuf.get()); \
692
+ HKU_ASSERT((outBegIdx == m_discard) && (outBegIdx + outNbElement) <= total); \
693
+ auto *dst = this->data() + outBegIdx; \
694
+ for (size_t i = 0; i < outNbElement; ++i) { \
695
+ dst[i] = outbuf[i]; \
696
+ } \
697
+ } \
698
+ \
699
+ Indicator HKU_API func() { \
700
+ return make_shared<Cls_##func>()->calculate(); \
701
+ } \
702
+ \
703
+ Indicator HKU_API func(const KData &k) { \
704
+ return Indicator(make_shared<Cls_##func>(k)); \
705
+ }
706
+
707
+ #define TA_OHLC_OUT1_INT_P1_D_IMP(func, func_lookback, param1, param1_value, param1_min, \
708
+ param1_max) \
709
+ Cls_##func::Cls_##func() : IndicatorImp(#func, 1) { \
710
+ setParam<double>(#param1, param1_value); \
711
+ } \
712
+ \
713
+ Cls_##func::Cls_##func(const KData &k, double p) : IndicatorImp(#func, 1) { \
714
+ setParam<KData>("kdata", k); \
715
+ setParam<double>(#param1, p); \
716
+ Cls_##func::_calculate(Indicator()); \
717
+ } \
718
+ \
719
+ void Cls_##func::_checkParam(const string &name) const { \
720
+ if (name == #param1) { \
721
+ double p = getParam<double>(#param1); \
722
+ HKU_ASSERT(p >= param1_min && p <= param1_max); \
723
+ } \
724
+ } \
725
+ \
726
+ void Cls_##func::_calculate(const Indicator &data) { \
727
+ HKU_WARN_IF(!isLeaf() && !data.empty(), \
728
+ "The input is ignored because {} depends on the context!", m_name); \
729
+ \
730
+ KData k = getContext(); \
731
+ size_t total = k.size(); \
732
+ HKU_IF_RETURN(total == 0, void()); \
733
+ \
734
+ _readyBuffer(total, 1); \
735
+ \
736
+ int lookback = func_lookback(param1_value); \
737
+ if (lookback < 0 || lookback >= total) { \
738
+ m_discard = total; \
739
+ return; \
740
+ } \
741
+ \
742
+ const KRecord *kptr = k.data(); \
743
+ std::unique_ptr<double[]> buf = std::make_unique<double[]>(4 * total); \
744
+ double *open = buf.get(); \
745
+ double *high = open + total; \
746
+ double *low = high + total; \
747
+ double *close = low + total; \
748
+ for (size_t i = 0; i < total; ++i) { \
749
+ open[i] = kptr[i].openPrice; \
750
+ high[i] = kptr[i].highPrice; \
751
+ low[i] = kptr[i].lowPrice; \
752
+ close[i] = kptr[i].closePrice; \
753
+ } \
754
+ \
755
+ std::unique_ptr<int[]> outbuf = std::make_unique<int[]>(total); \
756
+ int outBegIdx; \
757
+ int outNbElement; \
758
+ m_discard = lookback; \
759
+ func(m_discard, total - 1, open, high, low, close, getParam<double>(#param1), &outBegIdx, \
760
+ &outNbElement, outbuf.get()); \
761
+ HKU_ASSERT((outBegIdx == m_discard) && (outBegIdx + outNbElement) <= total); \
762
+ auto *dst = this->data() + outBegIdx; \
763
+ for (size_t i = 0; i < outNbElement; ++i) { \
764
+ dst[i] = outbuf[i]; \
765
+ } \
766
+ } \
767
+ \
768
+ Indicator HKU_API func(double p) { \
769
+ auto ptr = make_shared<Cls_##func>(); \
770
+ ptr->setParam<double>(#param1, p); \
771
+ ptr->calculate(); \
772
+ return Indicator(ptr); \
773
+ } \
774
+ \
775
+ Indicator HKU_API func(const KData &k, double p) { \
776
+ return Indicator(make_shared<Cls_##func>(k, p)); \
777
+ }
778
+
779
+ #define TA_HLCV_OUT1_IMP(func, func_lookback) \
780
+ Cls_##func::Cls_##func() : IndicatorImp(#func, 1) {} \
781
+ \
782
+ Cls_##func::Cls_##func(const KData &k) : IndicatorImp(#func, 1) { \
783
+ setParam<KData>("kdata", k); \
784
+ Cls_##func::_calculate(Indicator()); \
785
+ } \
786
+ \
787
+ void Cls_##func::_calculate(const Indicator &data) { \
788
+ HKU_WARN_IF(!isLeaf() && !data.empty(), \
789
+ "The input is ignored because {} depends on the context!", m_name); \
790
+ \
791
+ KData k = getContext(); \
792
+ size_t total = k.size(); \
793
+ HKU_IF_RETURN(total == 0, void()); \
794
+ \
795
+ _readyBuffer(total, 1); \
796
+ int lookback = func_lookback(); \
797
+ if (lookback < 0 || lookback >= total) { \
798
+ m_discard = total; \
799
+ return; \
800
+ } \
801
+ \
802
+ const KRecord *kptr = k.data(); \
803
+ std::unique_ptr<double[]> buf = std::make_unique<double[]>(4 * total); \
804
+ double *high = buf.get(); \
805
+ double *low = high + total; \
806
+ double *close = low + total; \
807
+ double *vol = close + total; \
808
+ for (size_t i = 0; i < total; ++i) { \
809
+ high[i] = kptr[i].highPrice; \
810
+ low[i] = kptr[i].lowPrice; \
811
+ close[i] = kptr[i].closePrice; \
812
+ vol[i] = kptr[i].transCount; \
813
+ } \
814
+ \
815
+ auto *dst = this->data(); \
816
+ int outBegIdx; \
817
+ int outNbElement; \
818
+ m_discard = lookback; \
819
+ func(m_discard, total - 1, high, low, close, vol, &outBegIdx, &outNbElement, \
820
+ dst + m_discard); \
821
+ HKU_ASSERT((outBegIdx == m_discard) && (outBegIdx + outNbElement) <= total); \
822
+ } \
823
+ \
824
+ Indicator HKU_API func() { \
825
+ return make_shared<Cls_##func>()->calculate(); \
826
+ } \
827
+ \
828
+ Indicator HKU_API func(const KData &k) { \
829
+ return Indicator(make_shared<Cls_##func>(k)); \
830
+ }
831
+
832
+ #define TA_HL_OUT1_IMP(func, func_lookback) \
833
+ Cls_##func::Cls_##func() : IndicatorImp(#func, 1) {} \
834
+ \
835
+ Cls_##func::Cls_##func(const KData &k) : IndicatorImp(#func, 1) { \
836
+ setParam<KData>("kdata", k); \
837
+ Cls_##func::_calculate(Indicator()); \
838
+ } \
839
+ \
840
+ void Cls_##func::_calculate(const Indicator &data) { \
841
+ HKU_WARN_IF(!isLeaf() && !data.empty(), \
842
+ "The input is ignored because {} depends on the context!", m_name); \
843
+ \
844
+ KData k = getContext(); \
845
+ size_t total = k.size(); \
846
+ HKU_IF_RETURN(total == 0, void()); \
847
+ \
848
+ _readyBuffer(total, 1); \
849
+ int lookback = func_lookback(); \
850
+ if (lookback < 0 || lookback >= total) { \
851
+ m_discard = total; \
852
+ return; \
853
+ } \
854
+ \
855
+ const KRecord *kptr = k.data(); \
856
+ std::unique_ptr<double[]> buf = std::make_unique<double[]>(2 * total); \
857
+ double *high = buf.get(); \
858
+ double *low = high + total; \
859
+ for (size_t i = 0; i < total; ++i) { \
860
+ high[i] = kptr[i].highPrice; \
861
+ low[i] = kptr[i].lowPrice; \
862
+ } \
863
+ \
864
+ auto *dst = this->data(); \
865
+ int outBegIdx; \
866
+ int outNbElement; \
867
+ m_discard = lookback; \
868
+ func(m_discard, total - 1, high, low, &outBegIdx, &outNbElement, dst + m_discard); \
869
+ HKU_ASSERT((outBegIdx == m_discard) && (outBegIdx + outNbElement) <= total); \
870
+ } \
871
+ \
872
+ Indicator HKU_API func() { \
873
+ return make_shared<Cls_##func>()->calculate(); \
874
+ } \
875
+ \
876
+ Indicator HKU_API func(const KData &k) { \
877
+ return Indicator(make_shared<Cls_##func>(k)); \
878
+ }
879
+
880
+ #define TA_CV_OUT1_IMP(func, func_lookback) \
881
+ Cls_##func::Cls_##func() : IndicatorImp(#func, 1) {} \
882
+ \
883
+ Cls_##func::Cls_##func(const KData &k) : IndicatorImp(#func, 1) { \
884
+ setParam<KData>("kdata", k); \
885
+ Cls_##func::_calculate(Indicator()); \
886
+ } \
887
+ \
888
+ void Cls_##func::_calculate(const Indicator &data) { \
889
+ HKU_WARN_IF(!isLeaf() && !data.empty(), \
890
+ "The input is ignored because {} depends on the context!", m_name); \
891
+ \
892
+ KData k = getContext(); \
893
+ size_t total = k.size(); \
894
+ HKU_IF_RETURN(total == 0, void()); \
895
+ \
896
+ _readyBuffer(total, 1); \
897
+ int lookback = func_lookback(); \
898
+ if (lookback < 0 || lookback >= total) { \
899
+ m_discard = 0; \
900
+ return; \
901
+ } \
902
+ \
903
+ const KRecord *kptr = k.data(); \
904
+ std::unique_ptr<double[]> buf = std::make_unique<double[]>(2 * total); \
905
+ double *close = buf.get(); \
906
+ double *vol = close + total; \
907
+ for (size_t i = 0; i < total; ++i) { \
908
+ close[i] = kptr[i].closePrice; \
909
+ vol[i] = kptr[i].transCount; \
910
+ } \
911
+ \
912
+ auto *dst = this->data(); \
913
+ int outBegIdx; \
914
+ int outNbElement; \
915
+ m_discard = lookback; \
916
+ func(m_discard, total - 1, close, vol, &outBegIdx, &outNbElement, dst + m_discard); \
917
+ HKU_ASSERT((outBegIdx == m_discard) && (outBegIdx + outNbElement) <= total); \
918
+ } \
919
+ \
920
+ Indicator HKU_API func() { \
921
+ return make_shared<Cls_##func>()->calculate(); \
922
+ } \
923
+ \
924
+ Indicator HKU_API func(const KData &k) { \
925
+ return Indicator(make_shared<Cls_##func>(k)); \
926
+ }
927
+
928
+ #define TA_HLC_OUT1_IMP(func, func_lookback) \
929
+ Cls_##func::Cls_##func() : IndicatorImp(#func, 1) {} \
930
+ \
931
+ Cls_##func::Cls_##func(const KData &k) : IndicatorImp(#func, 1) { \
932
+ setParam<KData>("kdata", k); \
933
+ Cls_##func::_calculate(Indicator()); \
934
+ } \
935
+ \
936
+ void Cls_##func::_calculate(const Indicator &data) { \
937
+ HKU_WARN_IF(!isLeaf() && !data.empty(), \
938
+ "The input is ignored because {} depends on the context!", m_name); \
939
+ \
940
+ KData k = getContext(); \
941
+ size_t total = k.size(); \
942
+ HKU_IF_RETURN(total == 0, void()); \
943
+ \
944
+ _readyBuffer(total, 1); \
945
+ int lookback = func_lookback(); \
946
+ if (lookback < 0 || lookback >= total) { \
947
+ m_discard = total; \
948
+ return; \
949
+ } \
950
+ \
951
+ const KRecord *kptr = k.data(); \
952
+ std::unique_ptr<double[]> buf = std::make_unique<double[]>(3 * total); \
953
+ double *high = buf.get(); \
954
+ double *low = high + total; \
955
+ double *close = low + total; \
956
+ for (size_t i = 0; i < total; ++i) { \
957
+ high[i] = kptr[i].highPrice; \
958
+ low[i] = kptr[i].lowPrice; \
959
+ close[i] = kptr[i].closePrice; \
960
+ } \
961
+ \
962
+ m_discard = lookback; \
963
+ auto *dst = this->data(); \
964
+ int outBegIdx; \
965
+ int outNbElement; \
966
+ func(m_discard, total - 1, high, low, close, &outBegIdx, &outNbElement, dst + m_discard); \
967
+ HKU_ASSERT((outBegIdx == m_discard) && (outBegIdx + outNbElement) <= total); \
968
+ } \
969
+ \
970
+ Indicator HKU_API func() { \
971
+ return make_shared<Cls_##func>()->calculate(); \
972
+ } \
973
+ \
974
+ Indicator HKU_API func(const KData &k) { \
975
+ return Indicator(make_shared<Cls_##func>(k)); \
976
+ }
977
+
978
+ #define TA_HLC_OUT1_N_IMP(func, func_lookback, period, period_min, period_max) \
979
+ Cls_##func::Cls_##func() : IndicatorImp(#func, 1) { \
980
+ setParam<int>("n", period); \
981
+ } \
982
+ \
983
+ Cls_##func::Cls_##func(const KData &k, int n) : IndicatorImp(#func, 1) { \
984
+ setParam<KData>("kdata", k); \
985
+ setParam<int>("n", n); \
986
+ Cls_##func::_calculate(Indicator()); \
987
+ } \
988
+ \
989
+ void Cls_##func::_checkParam(const string &name) const { \
990
+ if (name == "n") { \
991
+ int n = getParam<int>("n"); \
992
+ HKU_ASSERT(n >= period_min && n <= period_max); \
993
+ } \
994
+ } \
995
+ \
996
+ void Cls_##func::_calculate(const Indicator &data) { \
997
+ HKU_WARN_IF(!isLeaf() && !data.empty(), \
998
+ "The input is ignored because {} depends on the context!", m_name); \
999
+ \
1000
+ KData k = getContext(); \
1001
+ size_t total = k.size(); \
1002
+ HKU_IF_RETURN(total == 0, void()); \
1003
+ \
1004
+ _readyBuffer(total, 1); \
1005
+ int n = getParam<int>("n"); \
1006
+ int back = func_lookback(n); \
1007
+ if (back < 0 || back >= total) { \
1008
+ m_discard = total; \
1009
+ return; \
1010
+ } \
1011
+ \
1012
+ const KRecord *kptr = k.data(); \
1013
+ std::unique_ptr<double[]> buf = std::make_unique<double[]>(3 * total); \
1014
+ double *high = buf.get(); \
1015
+ double *low = high + total; \
1016
+ double *close = low + total; \
1017
+ for (size_t i = 0; i < total; ++i) { \
1018
+ high[i] = kptr[i].highPrice; \
1019
+ low[i] = kptr[i].lowPrice; \
1020
+ close[i] = kptr[i].closePrice; \
1021
+ } \
1022
+ \
1023
+ m_discard = back; \
1024
+ auto *dst = this->data(); \
1025
+ int outBegIdx; \
1026
+ int outNbElement; \
1027
+ func(m_discard, total - 1, high, low, close, n, &outBegIdx, &outNbElement, \
1028
+ dst + m_discard); \
1029
+ HKU_ASSERT((outBegIdx == m_discard) && (outBegIdx + outNbElement) <= total); \
1030
+ } \
1031
+ \
1032
+ Indicator HKU_API func(int n) { \
1033
+ auto p = make_shared<Cls_##func>(); \
1034
+ p->setParam<int>("n", n); \
1035
+ p->calculate(); \
1036
+ return Indicator(p); \
1037
+ } \
1038
+ \
1039
+ Indicator HKU_API func(const KData &k, int n) { \
1040
+ return Indicator(make_shared<Cls_##func>(k, n)); \
1041
+ }
1042
+
1043
+ #define TA_HLCV_OUT1_N_IMP(func, func_lookback, period, period_min, period_max) \
1044
+ Cls_##func::Cls_##func() : IndicatorImp(#func, 1) { \
1045
+ setParam<int>("n", period); \
1046
+ } \
1047
+ \
1048
+ Cls_##func::Cls_##func(const KData &k, int n) : IndicatorImp(#func, 1) { \
1049
+ setParam<KData>("kdata", k); \
1050
+ setParam<int>("n", n); \
1051
+ Cls_##func::_calculate(Indicator()); \
1052
+ } \
1053
+ \
1054
+ void Cls_##func::_checkParam(const string &name) const { \
1055
+ if (name == "n") { \
1056
+ int n = getParam<int>("n"); \
1057
+ HKU_ASSERT(n >= period_min && n <= period_max); \
1058
+ } \
1059
+ } \
1060
+ \
1061
+ void Cls_##func::_calculate(const Indicator &data) { \
1062
+ HKU_WARN_IF(!isLeaf() && !data.empty(), \
1063
+ "The input is ignored because {} depends on the context!", m_name); \
1064
+ \
1065
+ KData k = getContext(); \
1066
+ size_t total = k.size(); \
1067
+ HKU_IF_RETURN(total == 0, void()); \
1068
+ \
1069
+ _readyBuffer(total, 1); \
1070
+ \
1071
+ int n = getParam<int>("n"); \
1072
+ int back = func_lookback(n); \
1073
+ if (back < 0 || back >= total) { \
1074
+ m_discard = total; \
1075
+ return; \
1076
+ } \
1077
+ \
1078
+ const KRecord *kptr = k.data(); \
1079
+ std::unique_ptr<double[]> buf = std::make_unique<double[]>(4 * total); \
1080
+ double *high = buf.get(); \
1081
+ double *low = high + total; \
1082
+ double *close = low + total; \
1083
+ double *vol = close + total; \
1084
+ for (size_t i = 0; i < total; ++i) { \
1085
+ high[i] = kptr[i].highPrice; \
1086
+ low[i] = kptr[i].lowPrice; \
1087
+ close[i] = kptr[i].closePrice; \
1088
+ vol[i] = kptr[i].transCount; \
1089
+ } \
1090
+ \
1091
+ m_discard = back; \
1092
+ auto *dst = this->data(); \
1093
+ int outBegIdx; \
1094
+ int outNbElement; \
1095
+ func(m_discard, total - 1, high, low, close, vol, n, &outBegIdx, &outNbElement, \
1096
+ dst + m_discard); \
1097
+ HKU_ASSERT((outBegIdx == m_discard) && (outBegIdx + outNbElement) <= total); \
1098
+ } \
1099
+ \
1100
+ Indicator HKU_API func(int n) { \
1101
+ auto p = make_shared<Cls_##func>(); \
1102
+ p->setParam<int>("n", n); \
1103
+ p->calculate(); \
1104
+ return Indicator(p); \
1105
+ } \
1106
+ \
1107
+ Indicator HKU_API func(const KData &k, int n) { \
1108
+ return Indicator(make_shared<Cls_##func>(k, n)); \
1109
+ }
1110
+
1111
+ #define TA_HL_OUT1_N_IMP(func, func_lookback, period, period_min, period_max) \
1112
+ Cls_##func::Cls_##func() : IndicatorImp(#func, 1) { \
1113
+ setParam<int>("n", period); \
1114
+ } \
1115
+ \
1116
+ Cls_##func::Cls_##func(const KData &k, int n) : IndicatorImp(#func, 1) { \
1117
+ setParam<KData>("kdata", k); \
1118
+ setParam<int>("n", n); \
1119
+ Cls_##func::_calculate(Indicator()); \
1120
+ } \
1121
+ \
1122
+ void Cls_##func::_checkParam(const string &name) const { \
1123
+ if (name == "n") { \
1124
+ int n = getParam<int>("n"); \
1125
+ HKU_ASSERT(n >= period_min && n <= period_max); \
1126
+ } \
1127
+ } \
1128
+ \
1129
+ void Cls_##func::_calculate(const Indicator &data) { \
1130
+ HKU_WARN_IF(!isLeaf() && !data.empty(), \
1131
+ "The input is ignored because {} depends on the context!", m_name); \
1132
+ \
1133
+ KData k = getContext(); \
1134
+ size_t total = k.size(); \
1135
+ HKU_IF_RETURN(total == 0, void()); \
1136
+ \
1137
+ _readyBuffer(total, 1); \
1138
+ int n = getParam<int>("n"); \
1139
+ int back = func_lookback(n); \
1140
+ if (back < 0 || back >= total) { \
1141
+ m_discard = total; \
1142
+ return; \
1143
+ } \
1144
+ \
1145
+ const KRecord *kptr = k.data(); \
1146
+ std::unique_ptr<double[]> buf = std::make_unique<double[]>(2 * total); \
1147
+ double *high = buf.get(); \
1148
+ double *low = high + total; \
1149
+ for (size_t i = 0; i < total; ++i) { \
1150
+ high[i] = kptr[i].highPrice; \
1151
+ low[i] = kptr[i].lowPrice; \
1152
+ } \
1153
+ \
1154
+ m_discard = back; \
1155
+ auto *dst = this->data(); \
1156
+ int outBegIdx; \
1157
+ int outNbElement; \
1158
+ func(m_discard, total - 1, high, low, n, &outBegIdx, &outNbElement, dst + m_discard); \
1159
+ HKU_ASSERT((outBegIdx == m_discard) && (outBegIdx + outNbElement) <= total); \
1160
+ } \
1161
+ \
1162
+ Indicator HKU_API func(int n) { \
1163
+ auto p = make_shared<Cls_##func>(); \
1164
+ p->setParam<int>("n", n); \
1165
+ p->calculate(); \
1166
+ return Indicator(p); \
1167
+ } \
1168
+ \
1169
+ Indicator HKU_API func(const KData &k, int n) { \
1170
+ return Indicator(make_shared<Cls_##func>(k, n)); \
1171
+ }
1172
+
1173
+ #define TA_HL_OUT2_N_IMP(func, func_lookback, period, period_min, period_max) \
1174
+ Cls_##func::Cls_##func() : IndicatorImp(#func, 2) { \
1175
+ setParam<int>("n", period); \
1176
+ } \
1177
+ \
1178
+ Cls_##func::Cls_##func(const KData &k, int n) : IndicatorImp(#func, 2) { \
1179
+ setParam<KData>("kdata", k); \
1180
+ setParam<int>("n", n); \
1181
+ Cls_##func::_calculate(Indicator()); \
1182
+ } \
1183
+ \
1184
+ void Cls_##func::_checkParam(const string &name) const { \
1185
+ if (name == "n") { \
1186
+ int n = getParam<int>("n"); \
1187
+ HKU_ASSERT(n >= period_min && n <= period_max); \
1188
+ } \
1189
+ } \
1190
+ \
1191
+ void Cls_##func::_calculate(const Indicator &data) { \
1192
+ HKU_WARN_IF(!isLeaf() && !data.empty(), \
1193
+ "The input is ignored because {} depends on the context!", m_name); \
1194
+ \
1195
+ KData k = getContext(); \
1196
+ size_t total = k.size(); \
1197
+ HKU_IF_RETURN(total == 0, void()); \
1198
+ \
1199
+ _readyBuffer(total, 2); \
1200
+ int n = getParam<int>("n"); \
1201
+ int back = func_lookback(n); \
1202
+ if (back < 0 || back >= total) { \
1203
+ m_discard = total; \
1204
+ return; \
1205
+ } \
1206
+ \
1207
+ const KRecord *kptr = k.data(); \
1208
+ std::unique_ptr<double[]> buf = std::make_unique<double[]>(2 * total); \
1209
+ double *high = buf.get(); \
1210
+ double *low = high + total; \
1211
+ for (size_t i = 0; i < total; ++i) { \
1212
+ high[i] = kptr[i].highPrice; \
1213
+ low[i] = kptr[i].lowPrice; \
1214
+ } \
1215
+ \
1216
+ m_discard = back; \
1217
+ auto *dst0 = this->data(0); \
1218
+ auto *dst1 = this->data(1); \
1219
+ int outBegIdx; \
1220
+ int outNbElement; \
1221
+ func(m_discard, total - 1, high, low, n, &outBegIdx, &outNbElement, dst0 + m_discard, \
1222
+ dst1 + m_discard); \
1223
+ HKU_ASSERT((outBegIdx == m_discard) && (outBegIdx + outNbElement) <= total); \
1224
+ } \
1225
+ \
1226
+ Indicator HKU_API func(int n) { \
1227
+ auto p = make_shared<Cls_##func>(); \
1228
+ p->setParam<int>("n", n); \
1229
+ p->calculate(); \
1230
+ return Indicator(p); \
1231
+ } \
1232
+ \
1233
+ Indicator HKU_API func(const KData &k, int n) { \
1234
+ return Indicator(make_shared<Cls_##func>(k, n)); \
1235
+ }
1236
+
1237
+ #define TA_HLC_OUT3_N_IMP(func, func_lookback, period, period_min, period_max) \
1238
+ Cls_##func::Cls_##func() : IndicatorImp(#func, 3) { \
1239
+ setParam<int>("n", period); \
1240
+ } \
1241
+ \
1242
+ Cls_##func::Cls_##func(const KData &k, int n) : IndicatorImp(#func, 3) { \
1243
+ setParam<KData>("kdata", k); \
1244
+ setParam<int>("n", n); \
1245
+ Cls_##func::_calculate(Indicator()); \
1246
+ } \
1247
+ \
1248
+ void Cls_##func::_checkParam(const string &name) const { \
1249
+ if (name == "n") { \
1250
+ int n = getParam<int>("n"); \
1251
+ HKU_ASSERT(n >= period_min && n <= period_max); \
1252
+ } \
1253
+ } \
1254
+ \
1255
+ void Cls_##func::_calculate(const Indicator &data) { \
1256
+ HKU_WARN_IF(!isLeaf() && !data.empty(), \
1257
+ "The input is ignored because {} depends on the context!", m_name); \
1258
+ \
1259
+ KData k = getContext(); \
1260
+ size_t total = k.size(); \
1261
+ HKU_IF_RETURN(total == 0, void()); \
1262
+ \
1263
+ _readyBuffer(total, 3); \
1264
+ int n = getParam<int>("n"); \
1265
+ int back = func_lookback(n); \
1266
+ if (back < 0 || back >= total) { \
1267
+ m_discard = total; \
1268
+ return; \
1269
+ } \
1270
+ \
1271
+ const KRecord *kptr = k.data(); \
1272
+ std::unique_ptr<double[]> buf = std::make_unique<double[]>(3 * total); \
1273
+ double *high = buf.get(); \
1274
+ double *low = high + total; \
1275
+ double *close = low + total; \
1276
+ for (size_t i = 0; i < total; ++i) { \
1277
+ high[i] = kptr[i].highPrice; \
1278
+ low[i] = kptr[i].lowPrice; \
1279
+ close[i] = kptr[i].closePrice; \
1280
+ } \
1281
+ \
1282
+ auto *dst0 = this->data(0); \
1283
+ auto *dst1 = this->data(1); \
1284
+ auto *dst2 = this->data(2); \
1285
+ m_discard = back; \
1286
+ int outBegIdx; \
1287
+ int outNbElement; \
1288
+ func(m_discard, total - 1, high, low, close, n, &outBegIdx, &outNbElement, \
1289
+ dst0 + m_discard, dst1 + m_discard, dst2 + m_discard); \
1290
+ HKU_ASSERT((outBegIdx == m_discard) && (outBegIdx + outNbElement) <= total); \
1291
+ } \
1292
+ \
1293
+ Indicator HKU_API func(int n) { \
1294
+ auto p = make_shared<Cls_##func>(); \
1295
+ p->setParam<int>("n", n); \
1296
+ p->calculate(); \
1297
+ return Indicator(p); \
1298
+ } \
1299
+ \
1300
+ Indicator HKU_API func(const KData &k, int n) { \
1301
+ return Indicator(make_shared<Cls_##func>(k, n)); \
1302
+ }
1303
+
1304
+ #define TA_OC_OUT1_N_IMP(func, func_lookback, period, period_min, period_max) \
1305
+ Cls_##func::Cls_##func() : IndicatorImp(#func, 1) { \
1306
+ setParam<int>("n", period); \
1307
+ } \
1308
+ \
1309
+ Cls_##func::Cls_##func(const KData &k, int n) : IndicatorImp(#func, 1) { \
1310
+ setParam<KData>("kdata", k); \
1311
+ setParam<int>("n", n); \
1312
+ Cls_##func::_calculate(Indicator()); \
1313
+ } \
1314
+ \
1315
+ void Cls_##func::_checkParam(const string &name) const { \
1316
+ if (name == "n") { \
1317
+ int n = getParam<int>("n"); \
1318
+ HKU_ASSERT(n >= period_min && n <= period_max); \
1319
+ } \
1320
+ } \
1321
+ \
1322
+ void Cls_##func::_calculate(const Indicator &data) { \
1323
+ HKU_WARN_IF(!isLeaf() && !data.empty(), \
1324
+ "The input is ignored because {} depends on the context!", m_name); \
1325
+ \
1326
+ KData k = getContext(); \
1327
+ size_t total = k.size(); \
1328
+ HKU_IF_RETURN(total == 0, void()); \
1329
+ \
1330
+ _readyBuffer(total, 1); \
1331
+ int n = getParam<int>("n"); \
1332
+ int back = func_lookback(n); \
1333
+ if (back < 0 || back >= total) { \
1334
+ m_discard = total; \
1335
+ return; \
1336
+ } \
1337
+ \
1338
+ const KRecord *kptr = k.data(); \
1339
+ std::unique_ptr<double[]> buf = std::make_unique<double[]>(2 * total); \
1340
+ double *open = buf.get(); \
1341
+ double *close = open + total; \
1342
+ for (size_t i = 0; i < total; ++i) { \
1343
+ open[i] = kptr[i].openPrice; \
1344
+ close[i] = kptr[i].closePrice; \
1345
+ } \
1346
+ \
1347
+ auto *dst = this->data(); \
1348
+ m_discard = back; \
1349
+ int outBegIdx; \
1350
+ int outNbElement; \
1351
+ func(m_discard, total - 1, open, close, n, &outBegIdx, &outNbElement, dst + m_discard); \
1352
+ HKU_ASSERT((outBegIdx == m_discard) && (outBegIdx + outNbElement) <= total); \
1353
+ } \
1354
+ \
1355
+ Indicator HKU_API func(int n) { \
1356
+ auto p = make_shared<Cls_##func>(); \
1357
+ p->setParam<int>("n", n); \
1358
+ p->calculate(); \
1359
+ return Indicator(p); \
1360
+ } \
1361
+ \
1362
+ Indicator HKU_API func(const KData &k, int n) { \
1363
+ return Indicator(make_shared<Cls_##func>(k, n)); \
1364
+ }