From 4e763ae798519f18c02e1983dbdcd2647e05c49e Mon Sep 17 00:00:00 2001 From: Adrian Kierzkowski Date: Wed, 27 Mar 2024 15:13:43 +0100 Subject: [PATCH] WIP. Refs EA31337/EA31337-indicators-stats#2. Indi_AccountStats closer to be finished. Awaiting to fix MT5 compiler bug. --- IndicatorData.mqh | 48 ++++++++++--------- Indicators/Account/Indi_AccountStats.mqh | 26 ++++++++-- .../Account/tests/Indi_AccountStats.test.mq5 | 2 +- Storage/ValueStorage.native.h | 9 ++++ 4 files changed, 58 insertions(+), 27 deletions(-) diff --git a/IndicatorData.mqh b/IndicatorData.mqh index bc0c498b1..990c2e1f3 100644 --- a/IndicatorData.mqh +++ b/IndicatorData.mqh @@ -68,7 +68,7 @@ class IndicatorData : public IndicatorBase { case IDATA_ICUSTOM: break; case IDATA_INDICATOR: - if (indi_src.IsSet() == NULL) { + if (indi_src.IsSet()) { // Indi_Price* _indi_price = Indi_Price::GetCached(GetSymbol(), GetTf(), iparams.GetShift()); // SetDataSource(_indi_price, true, PRICE_OPEN); } @@ -109,7 +109,7 @@ class IndicatorData : public IndicatorBase { /** * Class constructor. */ - IndicatorData(const IndicatorDataParams& _idparams, IndicatorBase* _indi_src = NULL, int _indi_mode = 0) + IndicatorData(const IndicatorDataParams& _idparams, IndicatorBase* _indi_src = nullptr, int _indi_mode = 0) : do_draw(false), idparams(_idparams), indi_src(_indi_src) { Init(); } @@ -572,9 +572,9 @@ class IndicatorData : public IndicatorBase { * Returns currently selected data source doing validation. */ IndicatorData* GetDataSource(bool _validate = true) { - IndicatorData* _result = NULL; + IndicatorData* _result = nullptr; - if (GetDataSourceRaw() != NULL) { + if (GetDataSourceRaw() != nullptr) { _result = GetDataSourceRaw(); } else if (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_SRC_ID)) != -1) { int _source_id = Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_SRC_ID)); @@ -603,7 +603,7 @@ class IndicatorData : public IndicatorBase { // Requesting potential data source. _result = OnDataSourceRequest(); - if (_result != NULL) { + if (_result != nullptr) { // Initializing with new data source. SetDataSource(_result); Set(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE), IDATA_INDICATOR); @@ -621,7 +621,7 @@ class IndicatorData : public IndicatorBase { * Returns given data source type. Used by i*OnIndicator methods if indicator's Calculate() uses other indicators. */ IndicatorData* GetDataSource(ENUM_INDICATOR_TYPE _type) { - IndicatorData* _result = NULL; + IndicatorData* _result = nullptr; if (indicators.KeyExists((int)_type)) { _result = indicators[(int)_type].Ptr(); } else { @@ -697,11 +697,15 @@ class IndicatorData : public IndicatorBase { } if (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE)) == IDATA_INDICATOR && - GetDataSourceRaw() == NULL && _try_initialize) { + GetDataSourceRaw() == nullptr && _try_initialize) { SetDataSource(OnDataSourceRequest()); } - return GetDataSourceRaw() != NULL; + IndicatorData* _ptr = GetDataSourceRaw(); + + bool _result = _ptr != nullptr; + + return _result; } /** @@ -802,7 +806,7 @@ class IndicatorData : public IndicatorBase { indi_src.Ptr().RemoveListener(THIS_PTR); } indi_src = _indi; - if (_indi != NULL) { + if (_indi != nullptr) { indi_src.Ptr().AddListener(THIS_PTR); Set(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_SRC_ID), -1); Set(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_SRC_MODE), _input_mode); @@ -862,7 +866,7 @@ class IndicatorData : public IndicatorBase { last_tick_time = _current_time; // Checking and potentially initializing new data source. - if (HasDataSource(true) != NULL) { + if (HasDataSource(true)) { // Ticking data source if not yet ticked. GetDataSource().Tick(); } @@ -905,13 +909,13 @@ class IndicatorData : public IndicatorBase { * Loads and validates built-in indicators whose can be used as data source. */ void ValidateDataSource(IndicatorData* _target, IndicatorData* _source) { - if (_target == NULL) { + if (_target == nullptr) { Alert("Internal Error! _target is NULL in ", __FUNCTION_LINE__, "."); DebugBreak(); return; } - if (_source == NULL) { + if (_source == nullptr) { Alert("Error! You have to select source indicator's via SetDataSource()."); DebugBreak(); return; @@ -1129,7 +1133,7 @@ class IndicatorData : public IndicatorBase { _originator PTR_DEREF GetFullName(), "!"); DebugBreak(); } - return NULL; + return nullptr; } } @@ -1146,7 +1150,7 @@ class IndicatorData : public IndicatorBase { /** * Returns the indicator's struct value via index. */ - virtual IndicatorDataEntry GetEntry(long _index = 0) = NULL; + virtual IndicatorDataEntry GetEntry(long _index = 0) = 0; /** * Returns the indicator's struct value via timestamp. @@ -1171,7 +1175,7 @@ class IndicatorData : public IndicatorBase { /** * Returns the indicator's entry value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) = NULL; + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) = 0; /** * Returns the shift of the maximum value over a specific number of periods depending on type. @@ -1238,7 +1242,7 @@ class IndicatorData : public IndicatorBase { * * When indicator values are not valid, returns empty signals. */ - virtual IndicatorSignal GetSignals(int _count = 3, int _shift = 0, int _mode1 = 0, int _mode2 = 0) = NULL; + virtual IndicatorSignal GetSignals(int _count = 3, int _shift = 0, int _mode1 = 0, int _mode2 = 0) = 0; /** * Returns spread for the bar. @@ -1331,7 +1335,7 @@ class IndicatorData : public IndicatorBase { ", only PRICE_(OPEN|HIGH|LOW|CLOSE|MEDIAN|TYPICAL|WEIGHTED) are currently supported by " "IndicatorBase::GetSpecificAppliedPriceValueStorage()!"); DebugBreak(); - return NULL; + return nullptr; } } @@ -1374,7 +1378,7 @@ class IndicatorData : public IndicatorBase { "Volume) in the hierarchy!"); DebugBreak(); } - return NULL; + return nullptr; } /** @@ -1390,7 +1394,7 @@ class IndicatorData : public IndicatorBase { virtual IValueStorage* GetSpecificValueStorage(ENUM_INDI_VS_TYPE _type) { Print("Error: ", GetFullName(), " indicator has no storage type ", EnumToString(_type), "!"); DebugBreak(); - return NULL; + return nullptr; } /** @@ -1632,7 +1636,7 @@ class IndicatorData : public IndicatorBase { /** * Provides built-in indicators whose can be used as data source. */ - virtual IndicatorData* FetchDataSource(ENUM_INDICATOR_TYPE _id) { return NULL; } + virtual IndicatorData* FetchDataSource(ENUM_INDICATOR_TYPE _id) { return nullptr; } /** * Checks whether indicator support given value storage type. @@ -1700,7 +1704,7 @@ class IndicatorData : public IndicatorBase { " without explicitly selecting an indicator, ", GetFullName(), " must override OnDataSourceRequest() method and return new instance of data source to be used by default."); DebugBreak(); - return NULL; + return nullptr; } /** @@ -1708,7 +1712,7 @@ class IndicatorData : public IndicatorBase { */ virtual IndicatorData* DataSourceRequestReturnDefault(int _applied_price) { DebugBreak(); - return NULL; + return nullptr; } /** diff --git a/Indicators/Account/Indi_AccountStats.mqh b/Indicators/Account/Indi_AccountStats.mqh index da45fef7d..975064d96 100644 --- a/Indicators/Account/Indi_AccountStats.mqh +++ b/Indicators/Account/Indi_AccountStats.mqh @@ -145,7 +145,6 @@ class Indi_AccountStats : public Indicator { * Returns value storage of given kind. */ IValueStorage *GetSpecificValueStorage(ENUM_INDI_VS_TYPE _type) override { - // Returning Price indicator which provides applied price in the only buffer #0. switch (_type) { case INDI_VS_TYPE_ACCOUNT_STATS_DATE_TIME: return buffer_date_time.Ptr(); @@ -200,8 +199,27 @@ class Indi_AccountStats : public Indicator { return; } - // Adding new account stats entry. - - Print("New candle: ", entry.ToString()); + // New candle means that account stats for current index 0 will be that we + // will now extract and store in the buffers. + + // Extracting current account stats. + datetime stats_date_time = iparams.GetAccount() PTR_DEREF GetDateTime(); + float stats_balance = iparams.GetAccount() PTR_DEREF GetBalance(); + float stats_credit = iparams.GetAccount() PTR_DEREF GetCredit(); + float stats_profit = iparams.GetAccount() PTR_DEREF GetProfit(); + float stats_equity = iparams.GetAccount() PTR_DEREF GetEquity(); + float stats_margin_used = iparams.GetAccount() PTR_DEREF GetMarginUsed(); + float stats_margin_free = iparams.GetAccount() PTR_DEREF GetMarginFree(); + float stats_margin_avail = iparams.GetAccount() PTR_DEREF GetMarginAvail(); + + // Appending account stats into buffers. + buffer_date_time REF_DEREF Append(stats_date_time); + buffer_balance REF_DEREF Append(stats_balance); + buffer_credit REF_DEREF Append(stats_credit); + buffer_profit REF_DEREF Append(stats_profit); + buffer_equity REF_DEREF Append(stats_equity); + buffer_margin_used REF_DEREF Append(stats_margin_used); + buffer_margin_free REF_DEREF Append(stats_margin_free); + buffer_margin_avail REF_DEREF Append(stats_margin_avail); } }; diff --git a/Indicators/Account/tests/Indi_AccountStats.test.mq5 b/Indicators/Account/tests/Indi_AccountStats.test.mq5 index c81e0da79..9f72f4356 100644 --- a/Indicators/Account/tests/Indi_AccountStats.test.mq5 +++ b/Indicators/Account/tests/Indi_AccountStats.test.mq5 @@ -48,7 +48,7 @@ int OnInit() { void OnTick() { Platform::Tick(); - if (Platform::IsNewHour()) { + if (Platform::IsNewMinute()) { IndicatorDataEntry _entry = indi_account_mt REF_DEREF GetEntry(); bool _is_ready = indi_account_mt REF_DEREF Get(STRUCT_ENUM(IndicatorState, INDICATOR_STATE_PROP_IS_READY)); bool _is_valid = _entry.IsValid(); diff --git a/Storage/ValueStorage.native.h b/Storage/ValueStorage.native.h index 0c6180881..7fb8219fc 100644 --- a/Storage/ValueStorage.native.h +++ b/Storage/ValueStorage.native.h @@ -83,6 +83,15 @@ class NativeValueStorage : public ValueStorage { Array::ArrayStore(_values, _index, _value, 4096); } + /** + * Inserts new value at the end of the buffer. If buffer works as As-Series, + * then new value will act as the one at index 0. + */ + void Append(C _value) override { + Resize(Size() + 1, 4096); + Store(Size() - 1, _value); + } + /** * Returns number of values available to fetch (size of the values buffer). */