Skip to content

Commit

Permalink
WIP. Fixing remaining tests. Some are still to be fixed.
Browse files Browse the repository at this point in the history
  • Loading branch information
nseam committed Jun 30, 2022
1 parent aba07ba commit 5dc3ec3
Show file tree
Hide file tree
Showing 12 changed files with 154 additions and 36 deletions.
21 changes: 15 additions & 6 deletions EA.mqh
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "EA.enum.h"
#include "EA.struct.h"
#include "Market.mqh"
#include "Platform.h"
#include "Refs.struct.h"
#include "SerializerConverter.mqh"
#include "SerializerCsv.mqh"
Expand Down Expand Up @@ -79,7 +80,12 @@ class EA : public Taskable<DataParamEntry> {
/**
* Init code (called on constructor).
*/
void Init() { InitTask(); }
void Init() {
// Ensuring Platform singleton is already initialized.
Platform::Init();

InitTask();
}

/**
* Process initial task (called on constructor).
Expand All @@ -103,9 +109,9 @@ class EA : public Taskable<DataParamEntry> {
// Add and process tasks.
Init();
// Initialize a trade instance for the current chart and symbol.
ChartParams _cparams((ENUM_TIMEFRAMES)_Period, _Symbol);
Ref<IndicatorBase> _source = Platform::FetchDefaultCandleIndicator(_Symbol, PERIOD_CURRENT);
TradeParams _tparams;
Trade _trade(_tparams, _cparams);
Trade _trade(_tparams, _source.Ptr());
trade.Set(_Symbol, _trade);
logger.Link(_trade.GetLogger());
}
Expand Down Expand Up @@ -196,7 +202,7 @@ class EA : public Taskable<DataParamEntry> {
_signals |= _strat.SignalClose(ORDER_TYPE_SELL, _scm, _scl, _ss) ? SIGNAL_CLOSE_SELL_MAIN : 0;
_signals |= !_strat.SignalCloseFilter(ORDER_TYPE_SELL, _scfm) ? SIGNAL_CLOSE_SELL_FILTER : 0;
_signals |= !_strat.SignalCloseFilterTime(_scft) ? SIGNAL_CLOSE_TIME_FILTER : 0;
TradeSignalEntry _sentry(_signals, _strat.Get<ENUM_TIMEFRAMES>(STRAT_PARAM_TF), _strat.Get<long>(STRAT_PARAM_ID));
TradeSignalEntry _sentry(_signals, _strat.GetSource() PTR_DEREF GetTf(), _strat.Get<long>(STRAT_PARAM_ID));
_sentry.Set(STRUCT_ENUM(TradeSignalEntry, TRADE_SIGNAL_PROP_STRENGTH), _strat.SignalOpen(_sofm, _sol, _ss));
_sentry.Set(STRUCT_ENUM(TradeSignalEntry, TRADE_SIGNAL_PROP_TIME), ::TimeGMT());
return _sentry;
Expand Down Expand Up @@ -353,7 +359,10 @@ class EA : public Taskable<DataParamEntry> {
_request.magic = _strat.Get<long>(STRAT_PARAM_ID);
_request.price = SymbolInfoStatic::GetOpenOffer(_symbol, _cmd);
_request.volume = fmax(_strat.Get<float>(STRAT_PARAM_LS), SymbolInfoStatic::GetVolumeMin(_symbol));
_request.volume = _trade.NormalizeLots(_request.volume);

// @fixit Uncomment
// _request.volume = _trade.NormalizeLots(_request.volume);

// Prepare an order parameters.
OrderParams _oparams;
_strat.OnOrderOpen(_oparams);
Expand Down Expand Up @@ -442,7 +451,7 @@ class EA : public Taskable<DataParamEntry> {
Strategy *_strati = iter.Value().Ptr();
IndicatorBase *_indi = _strati.GetIndicator();
if (_indi != NULL) {
ENUM_TIMEFRAMES _itf = _indi.GetParams().tf.GetTf();
ENUM_TIMEFRAMES _itf = _indi PTR_DEREF GetTf();
IndicatorDataEntry _ientry = _indi.GetEntry();
if (!data_indi.KeyExists(_itf)) {
// Create new timeframe buffer if does not exist.
Expand Down
18 changes: 17 additions & 1 deletion Indicator/IndicatorTick.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,23 @@ class IndicatorTick : public Indicator<TS> {
/**
* Gets symbol info for active symbol.
*/
virtual SymbolInfoProp GetSymbolProps() { return symbol_props; }
SymbolInfoProp GetSymbolProps() override {
if (!symbol_props.initialized) {
Print(
"Error: Tried to fetch symbol properties, but they're not yet initialized! Please call "
"SetSymbolProps(SymbolInfoProp) before trying to use symbol-related information.");
DebugBreak();
}
return symbol_props;
}

/**
* Sets symbol info for symbol attached to the indicator.
*/
void SetSymbolProps(const SymbolInfoProp& _props) override {
symbol_props = _props;
symbol_props.initialized = true;
}

/**
* Traverses source indicators' hierarchy and tries to find IndicatorTick object at the end.
Expand Down
5 changes: 5 additions & 0 deletions IndicatorBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -1453,6 +1453,11 @@ class IndicatorBase : public Object {
*/
virtual SymbolInfoProp GetSymbolProps() { return GetTick() PTR_DEREF GetSymbolProps(); }

/**
* Sets symbol info for symbol attached to the indicator.
*/
virtual void SetSymbolProps(const SymbolInfoProp& _props) {}

/**
* Gets indicator's time-frame.
*/
Expand Down
1 change: 1 addition & 0 deletions Order.mqh
Original file line number Diff line number Diff line change
Expand Up @@ -1395,6 +1395,7 @@ class Order : public SymbolInfo {
} else {
odata.Set<unsigned int>(ORDER_PROP_LAST_ERROR,
fmax(odata.Get<unsigned int>(ORDER_PROP_LAST_ERROR), GetLastError()));
oresult.retcode = odata.Get<unsigned int>(ORDER_PROP_LAST_ERROR);
}
return _result;
}
Expand Down
56 changes: 55 additions & 1 deletion Platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,12 @@
#else
#error "Platform not supported!
#endif
#include "SymbolInfo.struct.static.h"

class Platform {
// Whether Init() was already called.
static bool initialized;

// Date and time used to determine periods that passed.
static DateTime time;

Expand All @@ -51,11 +55,21 @@ class Platform {
// List of added indicators.
static DictStruct<long, Ref<IndicatorBase>> indis;

// List of default Candle/Tick indicators.
static DictStruct<long, Ref<IndicatorBase>> indis_dflt;

public:
/**
* Initializes platform. Sets event timer and so on.
*/
static void Init() {
if (initialized) {
// Already initialized.
return;
}

initialized = true;

// OnTimer() every second.
EventSetTimer(1);
}
Expand Down Expand Up @@ -85,9 +99,16 @@ class Platform {
* Performs tick on every added indicator.
*/
static void Tick() {
for (DictStructIterator<long, Ref<IndicatorBase>> _iter = indis.Begin(); _iter.IsValid(); ++_iter) {
DictStructIterator<long, Ref<IndicatorBase>> _iter;

for (_iter = indis.Begin(); _iter.IsValid(); ++_iter) {
_iter.Value() REF_DEREF Tick();
}

for (_iter = indis_dflt.Begin(); _iter.IsValid(); ++_iter) {
_iter.Value() REF_DEREF Tick();
}

// Will check for new time periods in consecutive Platform::UpdateTime().
time_clear_flags = true;
}
Expand All @@ -97,6 +118,11 @@ class Platform {
*/
static DateTime Time() { return time; }

/**
* Returns number of seconds passed from the Unix epoch.
*/
static datetime Timestamp() { return TimeCurrent(); }

/**
* Checks whether it's a new second.
*/
Expand Down Expand Up @@ -205,6 +231,10 @@ class Platform {
IndicatorBase *_indi_candle;
if (!Objects<IndicatorBase>::TryGet(_key, _indi_candle)) {
_indi_candle = Objects<IndicatorBase>::Set(_key, new IndicatorTfDummy(_tf));

// Adding indicator to list of default indicators in order to tick it on every Tick() call.
Ref<IndicatorBase> _ref = _indi_candle;
indis_dflt.Set(_indi_candle PTR_DEREF GetId(), _ref);
}

if (!_indi_candle PTR_DEREF HasDataSource()) {
Expand All @@ -223,10 +253,32 @@ class Platform {
IndicatorBase *_indi_tick;
if (!Objects<IndicatorBase>::TryGet(_key, _indi_tick)) {
_indi_tick = Objects<IndicatorBase>::Set(_key, new PLATFORM_DEFAULT_INDICATOR_TICK(_symbol));
_indi_tick PTR_DEREF SetSymbolProps(Platform::FetchDefaultSymbolProps(_symbol));

// Adding indicator to list of default indicators in order to tick it on every Tick() call.
Ref<IndicatorBase> _ref = _indi_tick;
indis_dflt.Set(_indi_tick PTR_DEREF GetId(), _ref);
}
return _indi_tick;
}

/**
* Returns default properties for given symbol for current platform.
*/
static SymbolInfoProp FetchDefaultSymbolProps(CONST_REF_TO(string) _symbol) {
SymbolInfoProp props;
#ifdef __MQLBUILD__
props.pip_value = SymbolInfoStatic::GetPipValue(_symbol);
props.digits = SymbolInfoStatic::GetDigits(_symbol);
props.pip_digits = SymbolInfoStatic::GetPipDigits(_symbol);
props.pts_per_pip = SymbolInfoStatic::GetPointsPerPip(_symbol);
props.vol_digits = SymbolInfoStatic::GetVolumeDigits(_symbol);
props.vol_min = SymbolInfoStatic::GetVolumeMin(_symbol);
props.vol_max = SymbolInfoStatic::GetVolumeMax(_symbol);
#endif
return props;
}

/**
* Prints indicators' values at the given shift.
*/
Expand All @@ -240,10 +292,12 @@ class Platform {
}
};

bool Platform::initialized = false;
DateTime Platform::time;
unsigned int Platform::time_flags = 0;
bool Platform::time_clear_flags = true;
DictStruct<long, Ref<IndicatorBase>> Platform::indis;
DictStruct<long, Ref<IndicatorBase>> Platform::indis_dflt;

void OnTimer() { Platform::OnTimer(); }

Expand Down
5 changes: 3 additions & 2 deletions Stats.mqh
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

// Includes.
#include "Chart.mqh"
#include "Platform.h"

/**
* Class to collect ticks, bars and other data for statistical purposes.
Expand Down Expand Up @@ -56,8 +57,8 @@ class Stats {
void OnTick() {
static long _last_bar_time = 0;
total_ticks++;
if (_last_bar_time != ChartStatic::iTime(_Symbol, 0, 0)) {
_last_bar_time = ChartStatic::iTime(_Symbol, 0, 0);
if (_last_bar_time != Platform::Timestamp()) {
_last_bar_time = Platform::Timestamp();
total_bars++;
}
}
Expand Down
20 changes: 18 additions & 2 deletions SymbolInfo.struct.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,20 +71,34 @@ struct SymbolInfoEntry

// Defines structure for SymbolInfo properties.
struct SymbolInfoProp {
bool initialized;
double pip_value; // Pip value.
unsigned int digits; // Currency digits? @fixit
unsigned int pip_digits; // Pip digits (precision).
unsigned int pts_per_pip; // Points per pip.
unsigned int vol_digits; // Volume digits.
double vol_min; // Minimum volume for a deal.
double vol_max; // Maximum volume for a deal.
// Constructors.
SymbolInfoProp() {}
SymbolInfoProp(const SymbolInfoProp& _sip) {}
SymbolInfoProp() : initialized(false) {}
SymbolInfoProp(const SymbolInfoProp& _sip) {
initialized = _sip.initialized;
pip_value = _sip.pip_value;
digits = _sip.digits;
pip_digits = _sip.pip_digits;
pts_per_pip = _sip.pts_per_pip;
vol_digits = _sip.vol_digits;
vol_min = _sip.vol_min;
vol_max = _sip.vol_max;
}
// Getters.
double GetPipValue() { return pip_value; }
unsigned int GetDigits() { return digits; }
unsigned int GetPipDigits() { return pip_digits; }
unsigned int GetPointsPerPip() { return pts_per_pip; }
unsigned int GetVolumeDigits() { return vol_digits; }
double GetVolumeMin() { return vol_min; }
double GetVolumeMax() { return vol_max; }

// Serializers.
void SerializeStub(int _n1 = 1, int _n2 = 1, int _n3 = 1, int _n4 = 1, int _n5 = 1) {}
Expand All @@ -107,5 +121,7 @@ SerializerNodeType SymbolInfoProp::Serialize(Serializer& _s) {
_s.Pass(THIS_REF, "pip_digits", pip_digits);
_s.Pass(THIS_REF, "pts_per_pip", pts_per_pip);
_s.Pass(THIS_REF, "vol_digits", vol_digits);
_s.Pass(THIS_REF, "vol_min", vol_min);
_s.Pass(THIS_REF, "vol_max", vol_max);
return SerializerNodeObject;
}
7 changes: 7 additions & 0 deletions Test.mqh
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@
return (INIT_FAILED); \
}

#define assertEqualOrReturn(current, expected, msg, ret) \
if ((current) != (expected)) { \
Alert(msg + " - Assert fail. Expected ", expected, ", but got ", current, \
" in " + __FILE__ + ":" + (string)__LINE__); \
return (ret); \
}

#define assertFalseOrFail(cond, msg) \
if ((cond)) { \
Alert(msg + " - Assert fail on " + #cond + " in " + __FILE__ + ":" + (string)__LINE__); \
Expand Down
7 changes: 6 additions & 1 deletion Trade.mqh
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,12 @@ class Trade : public Taskable<DataParamEntry> {
};

/**
* Class copy constructor.
* Default constructor.
*/
Trade() {}

/**
* Copy constructor.
*/
Trade(const Trade &_trade) {
tparams = _trade.tparams;
Expand Down
12 changes: 5 additions & 7 deletions tests/DrawIndicatorTest.mq5
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,17 @@
#include "../Test.mqh"

// Global variables.
Chart *chart;
Ref<IndicatorBase> candles;
Dict<long, IndicatorBase *> indis;
int bar_processed;

/**
* Implements Init event handler.
*/
int OnInit() {
Platform::Init();
candles = Platform::FetchDefaultCandleIndicator(_Symbol, PERIOD_CURRENT);
bool _result = true;
// Initialize chart.
chart = new Chart();
// Initialize indicators.
_result &= InitIndicators();
Print("Indicators to test: ", indis.Size());
Expand All @@ -59,9 +59,9 @@ int OnInit() {
* Implements Tick event handler.
*/
void OnTick() {
chart.OnTick();
Platform::Tick();

if (chart.IsNewBar()) {
if (candles REF_DEREF IsNewBar()) {
bar_processed++;

for (DictIterator<long, IndicatorBase *> iter = indis.Begin(); iter.IsValid(); ++iter) {
Expand All @@ -79,8 +79,6 @@ void OnTick() {
* Implements Deinit event handler.
*/
void OnDeinit(const int reason) {
delete chart;

for (DictIterator<long, IndicatorBase *> iter = indis.Begin(); iter.IsValid(); ++iter) {
delete iter.Value();
}
Expand Down
Loading

0 comments on commit 5dc3ec3

Please sign in to comment.