Skip to content

Commit

Permalink
Refs EA31337-classes/EA31337-indicators-other#13, EA31337-classes/EA3…
Browse files Browse the repository at this point in the history
…1337-indicators-other#15. WIP. TDI-RT-Clone and Heiken_Ashi_Smoothed indicators made to work in MT5.
  • Loading branch information
nseam committed Dec 1, 2023
1 parent 0ddfa58 commit 9fb1008
Show file tree
Hide file tree
Showing 4 changed files with 222 additions and 11 deletions.
3 changes: 2 additions & 1 deletion Indicator.define.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ class DrawIndicator;
_obj.SetHandle(_handle); \
} \
} \
if (Terminal::IsVisualMode()) { \
if (false && Terminal::IsVisualMode()) { \
/* To avoid error 4806 (ERR_INDICATOR_DATA_NOT_FOUND), */ \
/* we check the number of calculated data only in visual mode. */ \
int _bars_calc = BarsCalculated(_handle); \
Expand All @@ -128,6 +128,7 @@ class DrawIndicator;
} \
} \
if (CopyBuffer(_handle, MODE, SHIFT, 1, _res) < 0) { \
Print(#NATIVE_METHOD_CALL, " = ", _res[0], ", LE = ", _LastError); \
return ArraySize(_res) > 0 ? _res[0] : EMPTY_VALUE; \
} \
return _res[0];
119 changes: 117 additions & 2 deletions IndicatorLegacy.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,28 @@
#pragma once
#endif

#ifdef INDICATOR_LEGACY_VERSION_MT4
#define INDICATOR_LEGACY_VERSION_DEFINED
#endif

#ifdef INDICATOR_LEGACY_VERSION_MT5
#define INDICATOR_LEGACY_VERSION_DEFINED
#endif

#ifndef INDICATOR_LEGACY_VERSION_DEFINED
#define INDICATOR_LEGACY_VERSION_MT5
#define INDICATOR_LEGACY_VERSION_DEFINED
#endif

#ifdef __MQL4__

#include <EA31337-classes/IndicatorBase.h>
#include <EA31337-classes/Std.h>
#include <EA31337-classes/Storage/ObjectsCache.h>
#include <EA31337-classes/Util.h>

#ifdef INDICATOR_LEGACY_VERSION_MT5

/**
* Replacement for future OnCalculate(). Currently not used, but could be handy in the future.
*/
Expand Down Expand Up @@ -338,8 +353,30 @@ DEFINE_LEGACY_INDICATOR_2(iAD, iAD, string, symbol, int, period);
// int iATR(string symbol, ENUM_TIMEFRAMES period, int ma_period);
DEFINE_LEGACY_INDICATOR_3(iATR, iATR, string, symbol, int, period, int, ma_period);

// int iRSI(string symbol, ENUM_TIMEFRAMES period, int ma_period, int applied_price);
#define T1 string
#define N1 symbol
#define T2 int
#define N2 period
#define T3 int
#define N3 ma_period
#define T4 int
#define N4 applied_price
DEFINE_LEGACY_INDICATOR_4(iRSI, iRSI)
#undef T1
#undef N1
#undef T2
#undef N2
#undef T3
#undef N3
#undef T4
#undef N4
#undef T5
#undef N5
#undef T6
#undef N6

// int iMA(string symbol, ENUM_TIMEFRAMES period, int ma_period, int ma_shift, ENUM_MA_METHOD ma_method,
// ENUM_APPLIED_PRICE applied_price);
#define T1 string
#define N1 symbol
#define T2 int
Expand All @@ -366,4 +403,82 @@ DEFINE_LEGACY_INDICATOR_6(iMA, iMA)
#undef T6
#undef N6

#endif
#endif // INDICATOR_LEGACY_VERSION_MT5
#endif // __MQL4__

#ifdef __MQL5__
#ifdef INDICATOR_LEGACY_VERSION_MT4

/**
* Replacement for future StringConcatenate().
*/
#define StringConcatenate StringConcatenateMT4

/**
* MQL5 wrapper of MQL4's StringConcatenate().
*/
template <typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I,
typename J, typename K, typename L, typename M>
string StringConcatenateMT4(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,
M _m) {
return (string)_a + (string)_b + (string)_c + (string)_d + (string)_e + (string)_f + (string)_g + (string)_h +
(string)_i + (string)_j + (string)_k + (string)_l + (string)_m;
}
template <typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I,
typename J, typename K, typename L>
string StringConcatenateMT4(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) {
return (string)_a + (string)_b + (string)_c + (string)_d + (string)_e + (string)_f + (string)_g + (string)_h +
(string)_i + (string)_j + (string)_k + (string)_l;
}
template <typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I,
typename J, typename K>
string StringConcatenateMT4(string& _result, A _a, B _b, C _c, D _d, E _e, F _f, G _g, H _h, I _i, J _j, K _k) {
return (string)_a + (string)_b + (string)_c + (string)_d + (string)_e + (string)_f + (string)_g + (string)_h +
(string)_i + (string)_j + (string)_k;
}
template <typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I,
typename J>
string StringConcatenateMT4(string& _result, A _a, B _b, C _c, D _d, E _e, F _f, G _g, H _h, I _i, J _j) {
return (string)_a + (string)_b + (string)_c + (string)_d + (string)_e + (string)_f + (string)_g + (string)_h +
(string)_i + (string)_j;
}
template <typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I>
string StringConcatenateMT4(string& _result, A _a, B _b, C _c, D _d, E _e, F _f, G _g, H _h, I _i) {
return (string)_a + (string)_b + (string)_c + (string)_d + (string)_e + (string)_f + (string)_g + (string)_h +
(string)_i;
}
template <typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H>
string StringConcatenateMT4(string& _result, A _a, B _b, C _c, D _d, E _e, F _f, G _g, H _h) {
return (string)_a + (string)_b + (string)_c + (string)_d + (string)_e + (string)_f + (string)_g + (string)_h;
}
template <typename A, typename B, typename C, typename D, typename E, typename F, typename G>
string StringConcatenateMT4(string& _result, A _a, B _b, C _c, D _d, E _e, F _f, G _g) {
return (string)_a + (string)_b + (string)_c + (string)_d + (string)_e + (string)_f + (string)_g;
}
template <typename A, typename B, typename C, typename D, typename E, typename F>
string StringConcatenateMT4(string& _result, A _a, B _b, C _c, D _d, E _e, F _f) {
return (string)_a + (string)_b + (string)_c + (string)_d + (string)_e + (string)_f;
}
template <typename A, typename B, typename C, typename D, typename E>
string StringConcatenateMT4(string& _result, A _a, B _b, C _c, D _d, E _e) {
return (string)_a + (string)_b + (string)_c + (string)_d + (string)_e;
}
template <typename A, typename B, typename C, typename D>
string StringConcatenateMT4(string& _result, A _a, B _b, C _c, D _d) {
return (string)_a + (string)_b + (string)_c + (string)_d;
}
template <typename A, typename B, typename C>
string StringConcatenateMT4(string& _result, A _a, B _b, C _c) {
return (string)_a + (string)_b + (string)_c;
}
template <typename A, typename B>
string StringConcatenateMT4(string& _result, A _a, B _b) {
return (string)_a + (string)_b;
}
template <typename A>
string StringConcatenateMT4(string& _result, A _a) {
return (string)_a;
}

#endif // INDICATOR_LEGACY_VERSION_MT4
#endif // __MQL5__
95 changes: 90 additions & 5 deletions Indicators/Indi_MA.mqh
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,96 @@ class Indi_MA : public Indicator<IndiMAParams> {
#ifdef __MQL4__
return ::iMAOnArray(price, total, ma_period, ma_shift, ma_method, shift);
#else
// We're reusing the same native array for each consecutive calculation.
NativeValueStorage<double> *_array_storage = Singleton<NativeValueStorage<double>>::Get();
_array_storage.SetData(price);

return iMAOnArray((ValueStorage<double> *)_array_storage, total, ma_period, ma_shift, ma_method, shift, cache);
if (cache != NULL) {
// We're reusing the same native array for each consecutive calculation.
NativeValueStorage<double> *_array_storage = Singleton<NativeValueStorage<double>>::Get();
_array_storage.SetData(price);

return iMAOnArray((ValueStorage<double> *)_array_storage, total, ma_period, ma_shift, ma_method, shift, cache);
} else {
double buf[], arr[], _result, pr, _array;
int pos, i, k, weight;
double sum, lsum;
if (total == 0) total = ArraySize(price);
if (total > 0 && total < ma_period) return (0);
if (shift > total - ma_period - ma_shift) return (0);
bool _was_series = ArrayGetAsSeries(price);
ArraySetAsSeries(price, true);
switch (ma_method) {
case MODE_SMA:
total = ArrayCopy(arr, price, 0, shift + ma_shift, ma_period);
if (ArrayResize(buf, total) < 0) return (0);
sum = 0;
pos = total - 1;
for (i = 1; i < ma_period; i++, pos--) sum += arr[pos];
while (pos >= 0) {
sum += arr[pos];
buf[pos] = sum / ma_period;
sum -= arr[pos + ma_period - 1];
pos--;
}
_result = buf[0];
break;
case MODE_EMA:
if (ArrayResize(buf, total) < 0) return (0);
pr = 2.0 / (ma_period + 1);
pos = total - 2;
while (pos >= 0) {
if (pos == total - 2) buf[pos + 1] = price[pos + 1];
buf[pos] = price[pos] * pr + buf[pos + 1] * (1 - pr);
pos--;
}
_result = buf[0];
break;
case MODE_SMMA:
if (ArrayResize(buf, total) < 0) return (0);
sum = 0;
pos = total - ma_period;
while (pos >= 0) {
if (pos == total - ma_period) {
for (i = 0, k = pos; i < ma_period; i++, k++) {
sum += price[k];
buf[k] = 0;
}
} else
sum = buf[pos + 1] * (ma_period - 1) + price[pos];
buf[pos] = sum / ma_period;
pos--;
}
_result = buf[0];
break;
case MODE_LWMA:
if (ArrayResize(buf, total) < 0) return (0);
sum = 0.0;
lsum = 0.0;
weight = 0;
pos = total - 1;
for (i = 1; i <= ma_period; i++, pos--) {
_array = price[pos];
sum += _array * i;
lsum += _array;
weight += i;
}
pos++;
i = pos + ma_period;
while (pos >= 0) {
buf[pos] = sum / weight;
if (pos == 0) break;
pos--;
i--;
_array = price[pos];
sum = sum - lsum + _array * ma_period;
lsum -= price[i];
lsum += _array;
}
_result = buf[0];
break;
default:
_result = 0;
}
ArraySetAsSeries(price, _was_series);
return _result;
}
#endif
}

Expand Down
16 changes: 13 additions & 3 deletions Storage/ValueStorage.native.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ template <typename C>
class NativeValueStorage : public ValueStorage<C> {
// Dynamic native array.
C _values[];
int _values_size;

public:
/**
Expand All @@ -49,7 +50,16 @@ class NativeValueStorage : public ValueStorage<C> {
/**
* Initializes array with given one.
*/
void SetData(ARRAY_REF(C, _arr)) { ArrayCopy(_values, _arr); }
void SetData(ARRAY_REF(C, _arr)) {
bool _was_series = ArrayGetAsSeries(_arr);
ArraySetAsSeries(_arr, false);
ArraySetAsSeries(_values, false);
ArrayResize(_values, 0);
ArrayCopy(_values, _arr);
_values_size = ArraySize(_arr);
ArraySetAsSeries(_arr, _was_series);
ArraySetAsSeries(_values, _was_series);
}

/**
* Initializes storage with given value.
Expand All @@ -60,7 +70,7 @@ class NativeValueStorage : public ValueStorage<C> {
* Fetches value from a given shift. Takes into consideration as-series flag.
*/
virtual C Fetch(int _shift) {
if (_shift < 0 || _shift >= ArraySize(_values)) {
if (_shift < 0 || _shift >= _values_size) {
return (C)EMPTY_VALUE;
// Print("Invalid buffer data index: ", _shift, ". Buffer size: ", ArraySize(_values));
// DebugBreak();
Expand All @@ -77,7 +87,7 @@ class NativeValueStorage : public ValueStorage<C> {
/**
* Returns number of values available to fetch (size of the values buffer).
*/
virtual int Size() const { return ArraySize(_values); }
virtual int Size() const { return _values_size; }

/**
* Resizes storage to given size.
Expand Down

0 comments on commit 9fb1008

Please sign in to comment.