Skip to content

Commit

Permalink
Legacy code for MT4. OnCalculate() automatic ticking, ArraySetAsSerie…
Browse files Browse the repository at this point in the history
…s() for buffers and support for calling MT5 code from MT4.
  • Loading branch information
nseam committed May 17, 2024
1 parent 8e90bfc commit 42ccf6a
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 6 deletions.
7 changes: 7 additions & 0 deletions Indicator/IndicatorData.h
Original file line number Diff line number Diff line change
Expand Up @@ -1438,6 +1438,13 @@ class IndicatorData : public IndicatorBase {
return false;
}

/**
* Fetches historic ticks for a given index (absolute shift) range.
*/
virtual bool FetchHistoryByIndexRange(int _index_from, int _index_to, ARRAY_REF(TickTAB<double>, _out_ticks)) {
return false;
}

/**
* Fetches historic ticks for a given start time and minimum number of tick to retrieve.
*/
Expand Down
5 changes: 5 additions & 0 deletions Indicator/IndicatorTf.provider.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,14 @@ class ItemsHistoryTfCandleProvider : public ItemsHistoryCandleProvider<TV> {
long _candle_length_ms = (long)spc * 1000;
long _ticks_to_ms = _ticks_from_ms + _candle_length_ms - 1;

// We will try to fetch history by two methods.
// 1. By time range if IndicatorTick supports that way.
if (!_indi_tick PTR_DEREF FetchHistoryByTimeRange(_ticks_from_ms, _ticks_to_ms, _ticks)) {
// 2. By number of bars if IndicatorTick supports that way.
// if (!_indi_tick PTR_DEREF FetchHistoryByIndexRange(_ticks_from_index, _ticks_to_ms, _ticks))) {
// There is no more ticks in the history, giving up.
break;
//}
}

if (ArraySize(_ticks) > 0) {
Expand Down
44 changes: 41 additions & 3 deletions IndicatorLegacy.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,28 +23,66 @@
#ifdef __MQL4__

#include <EA31337-classes/Indicator/IndicatorData.h>
#include <EA31337-classes/Platform.h>
#include <EA31337-classes/Std.h>
#include <EA31337-classes/Storage/ObjectsCache.h>
#include <EA31337-classes/Util.h>
#include <EA31337-classes/Platform.h>

#ifndef INDICATOR_LEGACY_VERSION_ACQUIRE_BUFFER
#define INDICATOR_LEGACY_VERSION_ACQUIRE_BUFFER
#endif

#ifndef INDICATOR_LEGACY_VERSION_RELEASE_BUFFER
#define INDICATOR_LEGACY_VERSION_RELEASE_BUFFER
#endif

#ifdef INDICATOR_LEGACY_VERSION_MT5

#ifndef INDICATOR_LEGACY_VERSION_SHORT

/**
* Replacement for future OnCalculate().
* Replacement for future OHLC-based OnCalculate().
*/
int OnCalculate(const int rates_total, const int prev_calculated, const datetime& time[], const double& open[],
const double& high[], const double& low[], const double& close[], const long& tick_volume[],
const long& volume[], const int& spread[]) {
// We need to call Platform::Tick() and maybe also IndicatorData::EmitHistory() before.
Platform::OnCalculate(rates_total, prev_calculated);


INDICATOR_LEGACY_VERSION_ACQUIRE_BUFFER;

int _num_calculated =
OnCalculateMT5(rates_total, prev_calculated, time, open, high, low, close, tick_volume, volume, spread);

INDICATOR_LEGACY_VERSION_RELEASE_BUFFER;

return _num_calculated;
}

#else

/**
* Replacement for future price-based OnCalculate().
*/
int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double& price[]) {
// We need to call Platform::Tick() and maybe also IndicatorData::EmitHistory() before.
Platform::OnCalculate(rates_total, prev_calculated);

INDICATOR_LEGACY_VERSION_ACQUIRE_BUFFER;

// NOTE: If compiler sees an error here about parameter conversion then you
// probably must do:
// #define INDICATOR_LEGACY_VERSION_SHORT
// before including IndicatorLegacy.h
int _num_calculated = OnCalculateMT5(rates_total, prev_calculated, begin, price);

INDICATOR_LEGACY_VERSION_RELEASE_BUFFER;

return _num_calculated;
}

#endif

#define OnCalculate OnCalculateMT5

/**
Expand Down
76 changes: 73 additions & 3 deletions Indicators/Tick/Indi_TickMt.mqh
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ struct Indi_TickMtParams : IndicatorParams {

// MT platform's tick-based indicator.
class Indi_TickMt : public IndicatorTick<Indi_TickMtParams, double, ItemsHistoryTickProvider<double>> {
// Caching _to_ms in FetchHistoryByTimeRange() in order to start from last
// shift and don't loop over the same bars again.
long _cache_fetch_history_shift_to_ms;
// Shift to start with if given _to_ms is less that cached _cache_fetch_history_shift_to_ms.
long _cache_fetch_history_shift_shift;

public:
Indi_TickMt(Indi_TickMtParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL,
int _indi_src_mode = 0)
Expand All @@ -61,7 +67,10 @@ class Indi_TickMt : public IndicatorTick<Indi_TickMtParams, double, ItemsHistory
/**
* Initializes the class.
*/
void Init() {}
void Init() {
_cache_fetch_history_shift_to_ms = 0;
_cache_fetch_history_shift_shift = 0;
}

string GetName() override { return "Indi_TickMt"; }

Expand Down Expand Up @@ -121,11 +130,60 @@ class Indi_TickMt : public IndicatorTick<Indi_TickMtParams, double, ItemsHistory
virtual bool FetchHistoryByTimeRange(long _from_ms, long _to_ms, ARRAY_REF(TickTAB<double>, _out_ticks)) {
ArrayResize(_out_ticks, 0);

#ifdef __MQL4__
// Searching from current bar to older ones.
int _shift;

if (_to_ms <= _cache_fetch_history_shift_to_ms) {
_shift = _cache_fetch_history_shift_shift;
} else {
_shift = 0;
}

string _symbol = GetSymbol();

while (true) {
double _time = (double)iTime(_symbol, PERIOD_M1, _shift);

if (_time == 0) {
// Invalid time.
break;
}

long _time_ms = (long)_time * 1000;

if (_time_ms > _to_ms) {
// No yet get into valid time range.
++_shift;
continue;
}

if (_time_ms < _from_ms) {
// No more ticks.
break;
}

TickTAB<double> _tick_o(_time_ms, iOpen(_Symbol, PERIOD_M1, _shift));
TickTAB<double> _tick_h(_time_ms, iHigh(_Symbol, PERIOD_M1, _shift));
TickTAB<double> _tick_l(_time_ms, iLow(_Symbol, PERIOD_M1, _shift));
TickTAB<double> _tick_c(_time_ms, iClose(_Symbol, PERIOD_M1, _shift));
ArrayPushObject(_out_ticks, _tick_o);
ArrayPushObject(_out_ticks, _tick_h);
ArrayPushObject(_out_ticks, _tick_l);
ArrayPushObject(_out_ticks, _tick_c);
++_shift;
}

if (_shift != -1) {
_cache_fetch_history_shift_to_ms = _to_ms;
_cache_fetch_history_shift_shift = _shift;
}

return ArraySize(_out_ticks) != 0;
#else
static MqlTick _tmp_ticks[];
ArrayResize(_tmp_ticks, 0);

// There's no history in MQL4.
#ifndef __MQL4__
int _tries = 10;

while (_tries > 0) {
Expand Down Expand Up @@ -154,6 +212,18 @@ class Indi_TickMt : public IndicatorTick<Indi_TickMtParams, double, ItemsHistory
return false;
}

/**
* Fetches historic ticks for a given index (absolute shift) range.
*/
virtual bool FetchHistoryByIndexRange(int _index_from, int _index_to, ARRAY_REF(TickTAB<double>, _out_ticks)) {
return false;
}

/**
* Sends historic entries to listening indicators. May be overriden.
*/
virtual void EmitHistory() {}

void OnTick(int _global_tick_index) override {
#ifdef __MQL4__
// Refreshes Ask/Bid constants.
Expand Down

0 comments on commit 42ccf6a

Please sign in to comment.