Skip to content

Commit 0ddfa58

Browse files
committed
Refs EA31337/EA31337-indicators-other#8. Added IndicatorLegacy.h file to allow using MQL5 versions of iNAME() indicators like iMA(), iRSI() in MQL4. Used to run MQL5 indicators in MQL4.
1 parent 30ed4a8 commit 0ddfa58

File tree

1 file changed

+369
-0
lines changed

1 file changed

+369
-0
lines changed

IndicatorLegacy.h

Lines changed: 369 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,369 @@
1+
/**
2+
* @file
3+
* Wrappers to be used by MQL4 code to allow calling MQL5's indicator functions like iMA() in MQL4.
4+
*/
5+
6+
#ifndef __MQL__
7+
#pragma once
8+
#endif
9+
10+
#ifdef __MQL4__
11+
12+
#include <EA31337-classes/IndicatorBase.h>
13+
#include <EA31337-classes/Std.h>
14+
#include <EA31337-classes/Storage/ObjectsCache.h>
15+
#include <EA31337-classes/Util.h>
16+
17+
/**
18+
* Replacement for future OnCalculate(). Currently not used, but could be handy in the future.
19+
*/
20+
int OnCalculate(const int rates_total, const int prev_calculated, const datetime& time[], const double& open[],
21+
const double& high[], const double& low[], const double& close[], const long& tick_volume[],
22+
const long& volume[], const int& spread[]) {
23+
int _num_calculated =
24+
OnCalculateMT5(rates_total, prev_calculated, time, open, high, low, close, tick_volume, volume, spread);
25+
26+
return _num_calculated;
27+
}
28+
29+
#define OnCalculate OnCalculateMT5
30+
31+
/**
32+
* Wrapper class to be used by MQL4 code to allow calling MQL5's indicator functions like iMA() in MQL4.
33+
*/
34+
class IndicatorLegacy : public Dynamic {
35+
// Handle to be used by BarsCalculated(), CopyBuffer() and so on.
36+
int handle;
37+
38+
// Name of the indicator.
39+
string name;
40+
41+
public:
42+
/**
43+
* Constructor.
44+
*/
45+
IndicatorLegacy(string _name) : name(_name) { handle = indis.Size(); }
46+
47+
/**
48+
* Returns indicator's handle.
49+
*/
50+
int GetHandle() { return handle; }
51+
52+
/**
53+
* Returns name of the indicator.
54+
*/
55+
string GetName() { return name; }
56+
57+
/**
58+
* Returns value for a given shift.
59+
*/
60+
virtual double GetValue(int _shift) = 0;
61+
62+
/**
63+
* Returns number of bars calculated for this indicator.
64+
*/
65+
int GetBarsCalculated() {
66+
// @todo We probably need to replace it with some more specific check per indicator.
67+
return Bars;
68+
}
69+
70+
// Dictionary of registered indicators (key -> indicator).
71+
static DictStruct<string, Ref<IndicatorLegacy>> indis;
72+
73+
// Dictionary of registered indicators (handle -> indicator).
74+
static DictStruct<int, Ref<IndicatorLegacy>> indis_handles;
75+
76+
/**
77+
* Returns number of bars calculated for a given indicator's handle.
78+
*/
79+
static int GetBarsCalculated(int _handle) {
80+
if (_handle < 0 || _handle >= (int)indis.Size()) {
81+
Print("Error: Given handle index is out of bounds! Given handle index ", _handle, " and there is ", indis.Size(),
82+
" handles available.");
83+
DebugBreak();
84+
return 0;
85+
}
86+
87+
IndicatorLegacy* _indi = indis_handles[_handle].Ptr();
88+
return PTR_ATTRIB(_indi, GetBarsCalculated());
89+
}
90+
};
91+
92+
DictStruct<string, Ref<IndicatorLegacy>> IndicatorLegacy::indis;
93+
DictStruct<int, Ref<IndicatorLegacy>> IndicatorLegacy::indis_handles;
94+
95+
/**
96+
* MQL4 wrapper of MQL5's BarsCalculated().
97+
*/
98+
int BarsCalculated(int _handle) { return IndicatorLegacy::GetBarsCalculated(_handle); }
99+
100+
/**
101+
* MQL4 wrapper of MQL5's CopyBuffer().
102+
*/
103+
int CopyBuffer(int _handle, int _mode, int _start, int _count, double& _buffer[]) {
104+
IndicatorLegacy* _indi = IndicatorLegacy::indis_handles[_handle].Ptr();
105+
106+
if (_mode != 0) {
107+
Print("Only mode 0 is supported for ", PTR_ATTRIB(_indi, GetName()),
108+
" legacy indicator as MQL4 supports only a single mode.");
109+
DebugBreak();
110+
return 0;
111+
}
112+
113+
int _num_copied = 0;
114+
int _buffer_size = ArraySize(_buffer);
115+
116+
if (_buffer_size < _count) {
117+
_buffer_size = ArrayResize(_buffer, _count);
118+
}
119+
120+
for (int i = 0; i < _count; ++i) {
121+
double _value = PTR_ATTRIB(_indi, GetValue(_start + i));
122+
123+
if (_value == WRONG_VALUE) {
124+
break;
125+
}
126+
127+
_buffer[_buffer_size - i - 1] = _value;
128+
++_num_copied;
129+
}
130+
131+
return _num_copied;
132+
}
133+
134+
/**
135+
* Defines wrapper class and global iNAME() indicator function (e.g., iMA(), iATR()).
136+
*/
137+
// Print(#FN_NAME " key = ", _key); \
138+
#define DEFINE_LEGACY_INDICATOR(FN_NAME, BUILTIN_NAME, TYPED_PARAMS_COMMA, TYPED_PARAMS_NO_UDL_SEMICOLON, UNTYPED_PARAMS_COMMA_KEY, UNTYPED_PARAMS_COMMA_VALUES, ASSIGNMENTS_COMMA, UNTYPED_PARAMS_NO_UDL_COMMA_VALUES) \
139+
class BUILTIN_NAME##Legacy : public IndicatorLegacy { \
140+
TYPED_PARAMS_NO_UDL_SEMICOLON; \
141+
public: \
142+
BUILTIN_NAME##Legacy(string _name, TYPED_PARAMS_COMMA) : IndicatorLegacy(_name), ASSIGNMENTS_COMMA {} \
143+
virtual double GetValue(int _shift) { \
144+
double _value = ::BUILTIN_NAME(UNTYPED_PARAMS_NO_UDL_COMMA_VALUES, _shift); \
145+
if (false) Print(GetName(), "[-", _shift, "]: ", _value); \
146+
return _value; \
147+
} \
148+
}; \
149+
int FN_NAME(TYPED_PARAMS_COMMA) { \
150+
Ref<IndicatorLegacy> _indi; \
151+
int _handle = INVALID_HANDLE; \
152+
string _key = Util::MakeKey(#FN_NAME, UNTYPED_PARAMS_COMMA_KEY); \
153+
if (IndicatorLegacy::indis.KeyExists(_key)) { \
154+
_indi = IndicatorLegacy::indis[_key]; \
155+
} \
156+
else { \
157+
_indi = new BUILTIN_NAME##Legacy(#BUILTIN_NAME, UNTYPED_PARAMS_COMMA_VALUES); \
158+
IndicatorLegacy::indis.Set(_key, _indi); \
159+
IndicatorLegacy::indis_handles.Set(PTR_ATTRIB(_indi.Ptr(), GetHandle()), _indi); \
160+
} \
161+
return PTR_ATTRIB(_indi.Ptr(), GetHandle()); \
162+
}
163+
164+
/**
165+
* 1-parameter helper for DEFINE_LEGACY_INDICATOR.
166+
*/
167+
#define DEFINE_LEGACY_INDICATOR_1(FN_NAME, INDI_NAME, T1, N1) \
168+
DEFINE_LEGACY_INDICATOR(INDI_NAME, T1 _##N1, T1 N1, _##N1, _##N1, N1(_##N1), N1);
169+
170+
/**
171+
* 2-parameter helper for DEFINE_LEGACY_INDICATOR.
172+
*/
173+
#define DEFINE_LEGACY_INDICATOR_2(FN_NAME, INDI_NAME, T1, N1, T2, N2) \
174+
DEFINE_LEGACY_INDICATOR(FN_NAME, INDI_NAME, T1 _##N1 COMMA T2 _##N2, T1 N1 SEMICOLON T2 N2, _##N1 COMMA _##N2, \
175+
_##N1 COMMA _##N2, N1(_##N1) COMMA N2(_##N2), N1 COMMA N2);
176+
177+
/**
178+
* 3-parameter helper for DEFINE_LEGACY_INDICATOR.
179+
*/
180+
#define DEFINE_LEGACY_INDICATOR_3(FN_NAME, INDI_NAME, T1, N1, T2, N2, T3, N3) \
181+
DEFINE_LEGACY_INDICATOR(FN_NAME, INDI_NAME, T1 _##N1 COMMA T2 _##N2 COMMA T3 _##N3, \
182+
T1 N1 SEMICOLON T2 N2 SEMICOLON T3 N3, _##N1 COMMA _##N2 COMMA _##N3, \
183+
_##N1 COMMA _##N2 COMMA _##N3, N1(_##N1) COMMA N2(_##N2) COMMA N3(_##N3), \
184+
N1 COMMA N2 COMMA N3);
185+
186+
/**
187+
* 4-parameter helper for DEFINE_LEGACY_INDICATOR.
188+
*/
189+
#define DEFINE_LEGACY_INDICATOR_4(FN_NAME, INDI_NAME) \
190+
DEFINE_LEGACY_INDICATOR(FN_NAME, INDI_NAME, T1 _##N1 COMMA T2 _##N2 COMMA T3 _##N3 COMMA T4 _##N4, \
191+
T1 N1 SEMICOLON T2 N2 SEMICOLON T3 N3 SEMICOLON T4 N4, \
192+
_##N1 COMMA _##N2 COMMA _##N3 COMMA _##N4, _##N1 COMMA _##N2 COMMA _##N3 COMMA _##N4, \
193+
N1(_##N1) COMMA N2(_##N2) COMMA N3(_##N3) COMMA N4(_##N4), N1 COMMA N2 COMMA N3 COMMA N4);
194+
195+
/**
196+
* 5-parameter helper for DEFINE_LEGACY_INDICATOR.
197+
*/
198+
#define DEFINE_LEGACY_INDICATOR_5(FN_NAME, INDI_NAME) \
199+
DEFINE_LEGACY_INDICATOR(FN_NAME, INDI_NAME, T1 _##N1 COMMA T2 _##N2 COMMA T3 _##N3 COMMA T4 _##N4 COMMA T5 _##N5, \
200+
T1 N1 SEMICOLON T2 N2 SEMICOLON T3 N3 SEMICOLON T4 N4 SEMICOLON T5 N5, \
201+
_##N1 COMMA _##N2 COMMA _##N3 COMMA _##N4 COMMA _##N5, \
202+
_##N1 COMMA _##N2 COMMA _##N3 COMMA _##N4 COMMA _##N5, \
203+
N1(_##N1) COMMA N2(_##N2) COMMA N3(_##N3) COMMA N4(_##N4) COMMA N5(_##N5), \
204+
N1 COMMA N2 COMMA N3 COMMA N4 COMMA N5);
205+
206+
/**
207+
* 6-parameter helper for DEFINE_LEGACY_INDICATOR.
208+
*/
209+
#define DEFINE_LEGACY_INDICATOR_6(FN_NAME, INDI_NAME) \
210+
DEFINE_LEGACY_INDICATOR(FN_NAME, INDI_NAME, \
211+
T1 _##N1 COMMA T2 _##N2 COMMA T3 _##N3 COMMA T4 _##N4 COMMA T5 _##N5 COMMA T6 _##N6, \
212+
T1 N1 SEMICOLON T2 N2 SEMICOLON T3 N3 SEMICOLON T4 N4 SEMICOLON T5 N5 SEMICOLON T6 N6, \
213+
_##N1 COMMA _##N2 COMMA _##N3 COMMA _##N4 COMMA _##N5 COMMA _##N6, \
214+
_##N1 COMMA _##N2 COMMA _##N3 COMMA _##N4 COMMA _##N5 COMMA _##N6, \
215+
N1(_##N1) COMMA N2(_##N2) COMMA N3(_##N3) COMMA N4(_##N4) COMMA N5(_##N5) COMMA N6(_##N6), \
216+
N1 COMMA N2 COMMA N3 COMMA N4 COMMA N5 COMMA N6);
217+
218+
/**
219+
* 7-parameter helper for DEFINE_LEGACY_INDICATOR.
220+
*/
221+
#define DEFINE_LEGACY_INDICATOR_7(FN_NAME, INDI_NAME) \
222+
DEFINE_LEGACY_INDICATOR( \
223+
FN_NAME, INDI_NAME, \
224+
T1 _##N1 COMMA T2 _##N2 COMMA T3 _##N3 COMMA T4 _##N4 COMMA T5 _##N5 COMMA T6 _##N6 COMMA T7 _##N7, \
225+
T1 N1 SEMICOLON T2 N2 SEMICOLON T3 N3 SEMICOLON T4 N4 SEMICOLON T5 N5 SEMICOLON T6 N6 SEMICOLON T7 N7, \
226+
_##N1 COMMA _##N2 COMMA _##N3 COMMA _##N4 COMMA _##N5 COMMA _##N6 COMMA _##N7, \
227+
_##N1 COMMA _##N2 COMMA _##N3 COMMA _##N4 COMMA _##N5 COMMA _##N6 COMMA _##N7, \
228+
N1(_##N1) COMMA N2(_##N2) COMMA N3(_##N3) COMMA N4(_##N4) COMMA N5(_##N5) COMMA N6(_##N6) COMMA N7(_##N7), \
229+
N1 COMMA N2 COMMA N3 COMMA N4 COMMA N5 COMMA N6 COMMA N7);
230+
231+
/**
232+
* 8-parameter helper for DEFINE_LEGACY_INDICATOR.
233+
*/
234+
#define DEFINE_LEGACY_INDICATOR_8(FN_NAME, INDI_NAME) \
235+
DEFINE_LEGACY_INDICATOR(FN_NAME, INDI_NAME, \
236+
T1 _##N1 COMMA T2 _##N2 COMMA T3 _##N3 COMMA T4 _##N4 COMMA T5 _##N5 COMMA T6 _##N6 COMMA T7 \
237+
_##N7 COMMA T8 _##N8, \
238+
T1 N1 SEMICOLON T2 N2 SEMICOLON T3 N3 SEMICOLON T4 N4 SEMICOLON T5 N5 SEMICOLON T6 N6 \
239+
SEMICOLON T7 N7 SEMICOLON T8 N8, \
240+
_##N1 COMMA _##N2 COMMA _##N3 COMMA _##N4 COMMA _##N5 COMMA _##N6 COMMA _##N7 COMMA _##N8, \
241+
_##N1 COMMA _##N2 COMMA _##N3 COMMA _##N4 COMMA _##N5 COMMA _##N6 COMMA _##N7 COMMA _##N8, \
242+
N1(_##N1) COMMA N2(_##N2) COMMA N3(_##N3) COMMA N4(_##N4) COMMA N5(_##N5) COMMA N6(_##N6) \
243+
COMMA N7(_##N7) COMMA N8(_##N8), \
244+
N1 COMMA N2 COMMA N3 COMMA N4 COMMA N5 COMMA N6 COMMA N7 COMMA N8);
245+
246+
/**
247+
* Replacement for future StringConcatenate().
248+
*/
249+
#define StringConcatenate StringConcatenateMT5
250+
251+
/**
252+
* MQL4 wrapper of MQL5's StringConcatenate().
253+
*/
254+
template <typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I,
255+
typename J, typename K, typename L, typename M>
256+
int StringConcatenateMT5(string& _result, A _a, B _b, C _c, D _d, E _e, F _f, G _g, H _h, I _i, J _j, K _k, L _l,
257+
M _m) {
258+
_result = (string)_a + (string)_b + (string)_c + (string)_d + (string)_e + (string)_f + (string)_g + (string)_h +
259+
(string)_i + (string)_j + (string)_k + (string)_l + (string)_m;
260+
return StringLen(_result);
261+
}
262+
template <typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I,
263+
typename J, typename K, typename L>
264+
int StringConcatenateMT5(string& _result, A _a, B _b, C _c, D _d, E _e, F _f, G _g, H _h, I _i, J _j, K _k, L _l) {
265+
_result = (string)_a + (string)_b + (string)_c + (string)_d + (string)_e + (string)_f + (string)_g + (string)_h +
266+
(string)_i + (string)_j + (string)_k + (string)_l;
267+
return StringLen(_result);
268+
}
269+
template <typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I,
270+
typename J, typename K>
271+
int StringConcatenateMT5(string& _result, A _a, B _b, C _c, D _d, E _e, F _f, G _g, H _h, I _i, J _j, K _k) {
272+
_result = (string)_a + (string)_b + (string)_c + (string)_d + (string)_e + (string)_f + (string)_g + (string)_h +
273+
(string)_i + (string)_j + (string)_k;
274+
return StringLen(_result);
275+
}
276+
template <typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I,
277+
typename J>
278+
int StringConcatenateMT5(string& _result, A _a, B _b, C _c, D _d, E _e, F _f, G _g, H _h, I _i, J _j) {
279+
_result = (string)_a + (string)_b + (string)_c + (string)_d + (string)_e + (string)_f + (string)_g + (string)_h +
280+
(string)_i + (string)_j;
281+
return StringLen(_result);
282+
}
283+
template <typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I>
284+
int StringConcatenateMT5(string& _result, A _a, B _b, C _c, D _d, E _e, F _f, G _g, H _h, I _i) {
285+
_result = (string)_a + (string)_b + (string)_c + (string)_d + (string)_e + (string)_f + (string)_g + (string)_h +
286+
(string)_i;
287+
return StringLen(_result);
288+
}
289+
template <typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H>
290+
int StringConcatenateMT5(string& _result, A _a, B _b, C _c, D _d, E _e, F _f, G _g, H _h) {
291+
_result = (string)_a + (string)_b + (string)_c + (string)_d + (string)_e + (string)_f + (string)_g + (string)_h;
292+
return StringLen(_result);
293+
}
294+
template <typename A, typename B, typename C, typename D, typename E, typename F, typename G>
295+
int StringConcatenateMT5(string& _result, A _a, B _b, C _c, D _d, E _e, F _f, G _g) {
296+
_result = (string)_a + (string)_b + (string)_c + (string)_d + (string)_e + (string)_f + (string)_g;
297+
return StringLen(_result);
298+
}
299+
template <typename A, typename B, typename C, typename D, typename E, typename F>
300+
int StringConcatenateMT5(string& _result, A _a, B _b, C _c, D _d, E _e, F _f) {
301+
_result = (string)_a + (string)_b + (string)_c + (string)_d + (string)_e + (string)_f;
302+
return StringLen(_result);
303+
}
304+
template <typename A, typename B, typename C, typename D, typename E>
305+
int StringConcatenateMT5(string& _result, A _a, B _b, C _c, D _d, E _e) {
306+
_result = (string)_a + (string)_b + (string)_c + (string)_d + (string)_e;
307+
return StringLen(_result);
308+
}
309+
template <typename A, typename B, typename C, typename D>
310+
int StringConcatenateMT5(string& _result, A _a, B _b, C _c, D _d) {
311+
_result = (string)_a + (string)_b + (string)_c + (string)_d;
312+
return StringLen(_result);
313+
}
314+
template <typename A, typename B, typename C>
315+
int StringConcatenateMT5(string& _result, A _a, B _b, C _c) {
316+
_result = (string)_a + (string)_b + (string)_c;
317+
return StringLen(_result);
318+
}
319+
template <typename A, typename B>
320+
int StringConcatenateMT5(string& _result, A _a, B _b) {
321+
_result = (string)_a + (string)_b;
322+
return StringLen(_result);
323+
}
324+
template <typename A>
325+
int StringConcatenateMT5(string& _result, A _a) {
326+
_result = (string)_a;
327+
return StringLen(_result);
328+
}
329+
330+
// ----- LEGACY INDICATOR DEFINITIONS
331+
332+
// int iAC(string symbol, ENUM_TIMEFRAMES period);
333+
DEFINE_LEGACY_INDICATOR_2(iAC, iAC, string, symbol, int, period);
334+
335+
// int iAD(string symbol, ENUM_TIMEFRAMES period, ENUM_APPLIED_VOLUME applied_volume);
336+
DEFINE_LEGACY_INDICATOR_2(iAD, iAD, string, symbol, int, period);
337+
338+
// int iATR(string symbol, ENUM_TIMEFRAMES period, int ma_period);
339+
DEFINE_LEGACY_INDICATOR_3(iATR, iATR, string, symbol, int, period, int, ma_period);
340+
341+
// int iMA(string symbol, ENUM_TIMEFRAMES period, int ma_period, int ma_shift, ENUM_MA_METHOD ma_method,
342+
// ENUM_APPLIED_PRICE applied_price);
343+
#define T1 string
344+
#define N1 symbol
345+
#define T2 int
346+
#define N2 period
347+
#define T3 int
348+
#define N3 ma_period
349+
#define T4 int
350+
#define N4 ma_shift
351+
#define T5 int
352+
#define N5 ma_method
353+
#define T6 int
354+
#define N6 applied_price
355+
DEFINE_LEGACY_INDICATOR_6(iMA, iMA)
356+
#undef T1
357+
#undef N1
358+
#undef T2
359+
#undef N2
360+
#undef T3
361+
#undef N3
362+
#undef T4
363+
#undef N4
364+
#undef T5
365+
#undef N5
366+
#undef T6
367+
#undef N6
368+
369+
#endif

0 commit comments

Comments
 (0)