diff --git a/Account/AccountMt.h b/Account/AccountMt.h index 8579f73cd..a021569df 100644 --- a/Account/AccountMt.h +++ b/Account/AccountMt.h @@ -319,42 +319,46 @@ class AccountMt { /* Setters */ - double UpdateStats(ENUM_ACC_STAT_VALUE _type, double _value) { - static datetime _last_check = TimeCurrent(); - bool _stats_rotate = false; - for (unsigned int _pindex = 0; _pindex < FINAL_ENUM_ACC_STAT_PERIOD; _pindex++) { - acc_stats[_type][_pindex][ACC_VALUE_MIN][ACC_VALUE_CURR] = - fmin(acc_stats[_type][_pindex][ACC_VALUE_MIN][ACC_VALUE_CURR], _value); - acc_stats[_type][_pindex][ACC_VALUE_MAX][ACC_VALUE_CURR] = - fmin(acc_stats[_type][_pindex][ACC_VALUE_MAX][ACC_VALUE_CURR], _value); - acc_stats[_type][_pindex][ACC_VALUE_AVG][ACC_VALUE_CURR] = - (acc_stats[_type][_pindex][ACC_VALUE_AVG][ACC_VALUE_CURR] + _value) / 2; - switch (_pindex) { - case ACC_DAILY: - _stats_rotate = _last_check < ChartStatic::iTime(_Symbol, PERIOD_D1); - break; - case ACC_WEEKLY: - _stats_rotate = _last_check < ChartStatic::iTime(_Symbol, PERIOD_W1); - break; - case ACC_MONTHLY: - _stats_rotate = _last_check < ChartStatic::iTime(_Symbol, PERIOD_MN1); - break; - } - if (_stats_rotate) { - acc_stats[_type][_pindex][ACC_VALUE_MIN][ACC_VALUE_PREV] = - acc_stats[_type][_pindex][ACC_VALUE_MIN][ACC_VALUE_CURR]; - acc_stats[_type][_pindex][ACC_VALUE_MAX][ACC_VALUE_PREV] = - acc_stats[_type][_pindex][ACC_VALUE_MAX][ACC_VALUE_CURR]; - acc_stats[_type][_pindex][ACC_VALUE_AVG][ACC_VALUE_PREV] = - acc_stats[_type][_pindex][ACC_VALUE_AVG][ACC_VALUE_CURR]; - acc_stats[_type][_pindex][ACC_VALUE_MIN][ACC_VALUE_CURR] = _value; - acc_stats[_type][_pindex][ACC_VALUE_MAX][ACC_VALUE_CURR] = _value; - acc_stats[_type][_pindex][ACC_VALUE_AVG][ACC_VALUE_CURR] = _value; - _last_check = TimeCurrent(); + /* + @TODO Still used? + + double UpdateStats(ENUM_ACC_STAT_VALUE _type, double _value) { + static datetime _last_check = TimeCurrent(); + bool _stats_rotate = false; + for (unsigned int _pindex = 0; _pindex < FINAL_ENUM_ACC_STAT_PERIOD; _pindex++) { + acc_stats[_type][_pindex][ACC_VALUE_MIN][ACC_VALUE_CURR] = + fmin(acc_stats[_type][_pindex][ACC_VALUE_MIN][ACC_VALUE_CURR], _value); + acc_stats[_type][_pindex][ACC_VALUE_MAX][ACC_VALUE_CURR] = + fmin(acc_stats[_type][_pindex][ACC_VALUE_MAX][ACC_VALUE_CURR], _value); + acc_stats[_type][_pindex][ACC_VALUE_AVG][ACC_VALUE_CURR] = + (acc_stats[_type][_pindex][ACC_VALUE_AVG][ACC_VALUE_CURR] + _value) / 2; + switch (_pindex) { + case ACC_DAILY: + _stats_rotate = _last_check < ChartStatic::iTime(_Symbol, PERIOD_D1); + break; + case ACC_WEEKLY: + _stats_rotate = _last_check < ChartStatic::iTime(_Symbol, PERIOD_W1); + break; + case ACC_MONTHLY: + _stats_rotate = _last_check < ChartStatic::iTime(_Symbol, PERIOD_MN1); + break; + } + if (_stats_rotate) { + acc_stats[_type][_pindex][ACC_VALUE_MIN][ACC_VALUE_PREV] = + acc_stats[_type][_pindex][ACC_VALUE_MIN][ACC_VALUE_CURR]; + acc_stats[_type][_pindex][ACC_VALUE_MAX][ACC_VALUE_PREV] = + acc_stats[_type][_pindex][ACC_VALUE_MAX][ACC_VALUE_CURR]; + acc_stats[_type][_pindex][ACC_VALUE_AVG][ACC_VALUE_PREV] = + acc_stats[_type][_pindex][ACC_VALUE_AVG][ACC_VALUE_CURR]; + acc_stats[_type][_pindex][ACC_VALUE_MIN][ACC_VALUE_CURR] = _value; + acc_stats[_type][_pindex][ACC_VALUE_MAX][ACC_VALUE_CURR] = _value; + acc_stats[_type][_pindex][ACC_VALUE_AVG][ACC_VALUE_CURR] = _value; + _last_check = TimeCurrent(); + } } + return _value; } - return _value; - } + */ /* Class getters */ diff --git a/Chart.mqh b/Chart.mqh index 117680732..e8e67b193 100644 --- a/Chart.mqh +++ b/Chart.mqh @@ -110,24 +110,6 @@ class Chart : public Market { int bar_index; public: - /* Getters */ - - /** - * Gets a chart parameter value. - */ - template - T Get(ENUM_CHART_PARAM _param) { - return cparams.Get(_param); - } - - /** - * Gets copy of params. - * - * @return - * Returns structure for Trade's params. - */ - ChartParams GetParams() const { return cparams; } - /* State checking */ /** @@ -195,44 +177,6 @@ class Chart : public Market { /* Conditions */ /* Printer methods */ - - /* Static methods */ - - /** - * Returns the price value given applied price type. - */ - static float GetAppliedPrice(ENUM_APPLIED_PRICE _ap, float _o, float _h, float _c, float _l) { - BarOHLC _bar(_o, _h, _c, _l); - return _bar.GetAppliedPrice(_ap); - } - - /* Other methods */ - - /** - * Load stored BarOHLC values. - * - * @param - * _index unsigned int Index of the element in BarOHLC array. - * @return - * Returns BarOHLC struct element. - */ - ChartEntry LoadChartEntry(unsigned int _index = 0) { return chart_saves[_index]; } - - /** - * Return size of BarOHLC array. - */ - unsigned long SizeChartEntry() { return ArraySize(chart_saves); } - - /* Serializers */ - - /** - * Returns serialized representation of the object instance. - */ - SerializerNodeType Serialize(Serializer &_s) { - ChartEntry _centry = GetEntry(); - _s.PassStruct(THIS_REF, "chart-entry", _centry, SERIALIZER_FIELD_FLAG_DYNAMIC); - return SerializerNodeObject; - } }; #endif diff --git a/Chart.symboltf.h b/Chart.symboltf.h index e20e8df49..52411498d 100644 --- a/Chart.symboltf.h +++ b/Chart.symboltf.h @@ -30,6 +30,9 @@ #pragma once #endif +// Includes. +#include "Std.h" + /** * Represents symbol and timeframe. To be used by IndicatorBase and ChartBase classes. */ @@ -38,8 +41,8 @@ struct SymbolTf { const ENUM_TIMEFRAMES tf; const string symbol_tf_key; - const string Key() const { return symbol_tf_key; } - const string Symbol() const { return symbol; } + CONST_REF_TO(string) Key() const { return symbol_tf_key; } + CONST_REF_TO(string) Symbol() const { return symbol; } ENUM_TIMEFRAMES Tf() const { return tf; } SymbolTf(string _symbol, ENUM_TIMEFRAMES _tf) diff --git a/ChartBase.h b/ChartBase.h index 1eae59765..253998046 100644 --- a/ChartBase.h +++ b/ChartBase.h @@ -30,7 +30,7 @@ #pragma once #endif -// Includes. +// Includes.` #include "Bar.struct.h" #include "Chart.enum.h" #include "Chart.struct.h" @@ -46,16 +46,14 @@ class ChartBase : public Dynamic { // Generic chart params. ChartParams cparams; - ENUM_TIMEFRAMES tf; + // Time of the last bar. + datetime last_bar_time; - // Time of the last bar per symbol and timeframe. - Dict last_bar_time; + // Index of the current bar. + int bar_index; - // Index of the current bar per symbol and timeframe. - Dict bar_index; - - // Index of the current tick per symbol and timeframe. - Dict tick_index; + // Index of the current tick. + int tick_index; // Logger. Ref logger; @@ -67,17 +65,12 @@ class ChartBase : public Dynamic { /** * Constructor. */ - ChartBase(ENUM_TIMEFRAMES _tf) : tf(_tf), logger(new Log()) {} + ChartBase(string _symbol, ENUM_TIMEFRAMES _tf) : logger(new Log()) { + Set(CHART_PARAM_SYMBOL, _symbol); + Set(CHART_PARAM_TF, _tf); + } - /** - * Returns pointer to logger. - */ - Log* GetLogger() { return logger.Ptr(); } - - /** - * Return time-frame bound to chart. - */ - ENUM_TIMEFRAMES GetTf() { return tf; } + /* Getters */ /** * Gets a chart parameter value. @@ -87,266 +80,280 @@ class ChartBase : public Dynamic { return cparams.Get(_param); } - /** - * Check if there is a new bar to parse. - */ - bool IsNewBar(CONST_REF_TO(string) _symbol) { - bool _result = false; - datetime _bar_time = GetBarTime(_symbol); - if (GetLastBarTime(_symbol) != _bar_time) { - SetLastBarTime(_symbol, _bar_time); - _result = true; - } - return _result; - } - - datetime GetLastBarTime(CONST_REF_TO(string) _symbol) { - if (last_bar_time.KeyExists(_symbol)) { - return last_bar_time.GetByKey(_symbol); - } - return GetBarTime(_symbol); - } - - void SetLastBarTime(CONST_REF_TO(string) _symbol, datetime _dt) { last_bar_time.Set(_symbol, _dt); } - /** * Returns current bar index (incremented every OnTick() if IsNewBar() is true). */ - int GetBarIndex(CONST_REF_TO(string) _symbol) { - if (bar_index.KeyExists(_symbol)) { - return bar_index.GetByKey(_symbol); - } - return 0; - } + int GetBarIndex() { return bar_index; } /** - * Sets current bar index. - */ - void SetBarIndex(CONST_REF_TO(string) _symbol, int _bar_index) { bar_index.Set(_symbol, _bar_index); } - - /** - * Increases current bar index (used in OnTick()). If there was no bar, the current bar will become 0. + * Returns time of the bar with a given shift. */ - void IncreaseBarIndex(CONST_REF_TO(string) _symbol) { - if (bar_index.KeyExists(_symbol)) { - SetBarIndex(_symbol, GetBarIndex(_symbol) + 1); - } else { - SetBarIndex(_symbol, 0); - } - } + virtual datetime GetBarTime(int _shift = 0) = 0; - /** - * Returns current tick index (incremented every OnTick()). - */ - int GetTickIndex(CONST_REF_TO(string) _symbol) { - if (tick_index.KeyExists(_symbol)) { - return tick_index.GetByKey(_symbol); - } - return 0; - } + datetime GetLastBarTime() { return last_bar_time; } /** - * Sets current tick index. + * Returns the number of bars on the chart. */ - void SetTickIndex(CONST_REF_TO(string) _symbol, int _tick_index) { tick_index.Set(_symbol, _tick_index); } + virtual int GetBars() = 0; /** - * Increases current tick index (used in OnTick()). If there was no tick, the current tick will become 0. + * Search for a bar by its time. + * + * Returns the index of the bar which covers the specified time. */ - void IncreaseTickIndex(CONST_REF_TO(string) _symbol) { - if (tick_index.KeyExists(_symbol)) { - SetTickIndex(_symbol, GetTickIndex(_symbol) + 1); - } else { - SetTickIndex(_symbol, 0); - } - } + virtual int GetBarShift(datetime _time, bool _exact = false) = 0; /** - * Acknowledges chart that new tick happened. + * Returns pointer to logger. */ - void OnTick(CONST_REF_TO(string) _symbol) { - IncreaseTickIndex(_symbol); - if (IsNewBar(_symbol)) { - IncreaseBarIndex(_symbol); - } - } + Log* GetLogger() { return logger.Ptr(); } /** - * Returns ask price value for the bar of indicated symbol. + * Gets copy of params. * - * If local history is empty (not loaded), function returns 0. + * @return + * Returns structure for Trade's params. */ - double GetAsk(CONST_REF_TO(string) _symbol, int _shift = 0) { return GetPrice(PRICE_ASK, _symbol, _shift); } + ChartParams GetParams() const { return cparams; } /** - * Returns bid price value for the bar of indicated symbol. - * - * If local history is empty (not loaded), function returns 0. + * Return symbol bound to chart. */ - double GetBid(CONST_REF_TO(string) _symbol, int _shift = 0) { return GetPrice(PRICE_BID, _symbol, _shift); } + CONST_REF_TO(string) GetSymbol() { return cparams.Get(CHART_PARAM_SYMBOL); } /** - * Returns open price value for the bar of indicated symbol. - * - * If local history is empty (not loaded), function returns 0. + * Return time-frame bound to chart. */ - double GetOpen(CONST_REF_TO(string) _symbol, int _shift = 0) { return GetPrice(PRICE_OPEN, _symbol, _shift); } + ENUM_TIMEFRAMES GetTf() { return cparams.Get(CHART_PARAM_TF); } /** - * Returns high price value for the bar of indicated symbol. - * - * If local history is empty (not loaded), function returns 0. + * Returns current tick index (incremented every OnTick()). */ - double GetHigh(CONST_REF_TO(string) _symbol, int _shift = 0) { return GetPrice(PRICE_HIGH, _symbol, _shift); } + int GetTickIndex() { return tick_index; } /** - * Returns low price value for the bar of indicated symbol. + * Returns open time price value for the bar of indicated symbol. * * If local history is empty (not loaded), function returns 0. */ - double GetLow(CONST_REF_TO(string) _symbol, int _shift = 0) { return GetPrice(PRICE_LOW, _symbol, _shift); } + virtual datetime GetTime(unsigned int _shift = 0) = 0; /** - * Returns close price value for the bar of indicated symbol. - * - * If local history is empty (not loaded), function returns 0. + * Return symbol pair for a given symbol index. */ - double GetClose(CONST_REF_TO(string) _symbol, int _shift = 0) { return GetPrice(PRICE_CLOSE, _symbol, _shift); } + virtual const string GetSymbolName(int _index) { return ::SymbolName(_index, true); } /** * Return number of symbols available for the chart. */ virtual int GetSymbolsTotal() { return ::SymbolsTotal(true); } + /* Price getters */ + /** - * Return symbol pair for a given symbol index. + * Returns the price value given applied price type. */ - virtual const string GetSymbolName(int _index) { return ::SymbolName(_index, true); } + static float GetAppliedPrice(ENUM_APPLIED_PRICE _ap, float _o, float _h, float _c, float _l) { + BarOHLC _bar(_o, _h, _c, _l); + return _bar.GetAppliedPrice(_ap); + } /** * Gets OHLC price values. */ - virtual BarOHLC GetOHLC(CONST_REF_TO(string) _symbol, int _shift = 0) { - datetime _time = GetBarTime(_symbol, _shift); + virtual BarOHLC GetOHLC(int _shift = 0) { + datetime _time = GetBarTime(_shift); float _open = 0, _high = 0, _low = 0, _close = 0; if (_time > 0) { - _open = (float)GetOpen(_symbol, _shift); - _high = (float)GetHigh(_symbol, _shift); - _low = (float)GetLow(_symbol, _shift); - _close = (float)GetClose(_symbol, _shift); + _open = (float)GetOpen(_shift); + _high = (float)GetHigh(_shift); + _low = (float)GetLow(_shift); + _close = (float)GetClose(_shift); } BarOHLC _ohlc(_open, _high, _low, _close, _time); return _ohlc; } - virtual datetime GetBarTime(CONST_REF_TO(string) _symbol, int _shift = 0) = 0; - /** * Returns the current price value given applied price type, symbol and timeframe. */ - virtual double GetPrice(ENUM_APPLIED_PRICE _ap, CONST_REF_TO(string) _symbol, int _shift = 0) = 0; + virtual double GetPrice(ENUM_APPLIED_PRICE _ap, int _shift = 0) = 0; /** * Returns tick volume value for the bar. * * If local history is empty (not loaded), function returns 0. */ - virtual long GetVolume(CONST_REF_TO(string) _symbol, int _shift = 0) = 0; + virtual long GetVolume(int _shift = 0) = 0; /** * Returns the shift of the maximum value over a specific number of periods depending on type. */ - virtual int GetHighest(CONST_REF_TO(string) _symbol, int type, int _count = WHOLE_ARRAY, int _start = 0) = 0; + virtual int GetHighest(int type, int _count = WHOLE_ARRAY, int _start = 0) = 0; /** * Returns the shift of the minimum value over a specific number of periods depending on type. */ - virtual int GetLowest(CONST_REF_TO(string) _symbol, int type, int _count = WHOLE_ARRAY, int _start = 0) = 0; + virtual int GetLowest(int type, int _count = WHOLE_ARRAY, int _start = 0) = 0; /** - * Returns the number of bars on the chart. + * Gets chart entry. + * + * @param + * _tf ENUM_TIMEFRAMES Timeframe to use. + * _shift unsigned int _shift Shift to use. + * _symbol string Symbol to use. + * + * @return + * Returns ChartEntry struct. */ - virtual int GetBars(CONST_REF_TO(string) _symbol) = 0; + ChartEntry GetEntry(unsigned int _shift = 0) { + ChartEntry _chart_entry; + BarOHLC _ohlc = GetOHLC(_shift); + if (_ohlc.open > 0) { + BarEntry _bar_entry(_ohlc); + _chart_entry.SetBar(_bar_entry); + } + return _chart_entry; + } /** - * Returns open time price value for the bar of indicated symbol. + * Returns ask price value for the bar of indicated symbol. * * If local history is empty (not loaded), function returns 0. */ - virtual datetime GetTime(CONST_REF_TO(string) _symbol, unsigned int _shift = 0) = 0; + double GetAsk(int _shift = 0) { return GetPrice(PRICE_ASK, _shift); } /** - * Search for a bar by its time. + * Returns bid price value for the bar of indicated symbol. * - * Returns the index of the bar which covers the specified time. + * If local history is empty (not loaded), function returns 0. */ - virtual int GetBarShift(CONST_REF_TO(string) _symbol, datetime _time, bool _exact = false) = 0; + double GetBid(int _shift = 0) { return GetPrice(PRICE_BID, _shift); } + + /** + * Returns close price value for the bar of indicated symbol. + * + * If local history is empty (not loaded), function returns 0. + */ + double GetClose(int _shift = 0) { return GetPrice(PRICE_CLOSE, _shift); } + + /** + * Returns high price value for the bar of indicated symbol. + * + * If local history is empty (not loaded), function returns 0. + */ + double GetHigh(int _shift = 0) { return GetPrice(PRICE_HIGH, _shift); } + + /** + * Returns open price value for the bar of indicated symbol. + * + * If local history is empty (not loaded), function returns 0. + */ + double GetOpen(int _shift = 0) { return GetPrice(PRICE_OPEN, _shift); } + + /** + * Returns low price value for the bar of indicated symbol. + * + * If local history is empty (not loaded), function returns 0. + */ + double GetLow(int _shift = 0) { return GetPrice(PRICE_LOW, _shift); } /** * Get peak price at given number of bars. * * In case of error, check it via GetLastError(). */ - virtual double GetPeakPrice(CONST_REF_TO(string) _symbol, int _bars, int _mode, int _index) { + virtual double GetPeakPrice(int _bars, int _mode, int _index) { int _ibar = -1; - double peak_price = GetOpen(_symbol, 0); + double peak_price = GetOpen(0); switch (_mode) { case MODE_HIGH: - _ibar = GetHighest(_symbol, MODE_HIGH, _bars, _index); - return _ibar >= 0 ? GetHigh(_symbol, _ibar) : false; + _ibar = GetHighest(MODE_HIGH, _bars, _index); + return _ibar >= 0 ? GetHigh(_ibar) : false; case MODE_LOW: - _ibar = GetLowest(_symbol, MODE_LOW, _bars, _index); - return _ibar >= 0 ? GetLow(_symbol, _ibar) : false; + _ibar = GetLowest(MODE_LOW, _bars, _index); + return _ibar >= 0 ? GetLow(_ibar) : false; default: return false; } } + /* Setters */ + /** - * Gets chart entry. - * - * @param - * _tf ENUM_TIMEFRAMES Timeframe to use. - * _shift unsigned int _shift Shift to use. - * _symbol string Symbol to use. - * - * @return - * Returns ChartEntry struct. + * Sets chart parameter value. */ - ChartEntry GetEntry(CONST_REF_TO(string) _symbol, unsigned int _shift = 0) { - ChartEntry _chart_entry; - BarOHLC _ohlc = GetOHLC(_symbol, _shift); - if (_ohlc.open > 0) { - BarEntry _bar_entry(_ohlc); - _chart_entry.SetBar(_bar_entry); - } - return _chart_entry; + template + void Set(ENUM_CHART_PARAM _param, T _value) { + return cparams.Get(_param, _value); } + /** + * Sets current bar index. + */ + void SetBarIndex(int _bar_index) { _bar_index = _bar_index; } + + /** + * Sets last bar time. + */ + void SetLastBarTime(datetime _dt) { last_bar_time = _dt; } + + /** + * Sets current tick index. + */ + void SetTickIndex(int _tick_index) { tick_index = _tick_index; } + + /* Chart state */ + + /** + * Increases current bar index (used in OnTick()). If there was no bar, the current bar will become 0. + */ + void IncreaseBarIndex() { SetBarIndex(bar_index == -1 ? 0 : bar_index + 1); } + + /** + * Increases current tick index (used in OnTick()). If there was no tick, the current tick will become 0. + */ + void IncreaseTickIndex() { SetTickIndex(tick_index == -1 ? 0 : tick_index + 1); } + /* State checking */ /** * Validate whether given timeframe index is valid. */ - bool IsValidTfIndex(ENUM_TIMEFRAMES_INDEX _tfi, string _symbol = NULL) { + bool IsValidTfIndex(ENUM_TIMEFRAMES_INDEX _tfi) { for (int i = 0; i < GetTfIndicesTotal(); ++i) { if (GetTfIndicesItem(i) == _tfi) { - return IsValidSymbol(_symbol); + return IsValidSymbol(); } } return false; } + /** + * Check if there is a new bar to parse. + */ + bool IsNewBar() { + bool _result = false; + datetime _bar_time = GetBarTime(); + if (GetLastBarTime() != _bar_time) { + SetLastBarTime(_bar_time); + _result = true; + } + return _result; + } + /** * Validates whether given timeframe is valid. */ - bool IsValidShift(CONST_REF_TO(string) _symbol, int _shift) { return GetTime(_symbol, _shift) > 0; } + bool IsValidShift(int _shift) { return GetTime(_shift) > 0; } /** * Validates whether given timeframe is valid. */ - bool IsValidSymbol(CONST_REF_TO(string) _symbol) { return GetOpen(_symbol) > 0; } + bool IsValidSymbol() { return GetOpen() > 0; } /** * Returns total number of timeframe indices the chart supports. Supports all TFs by default. @@ -473,6 +480,7 @@ class ChartBase : public Dynamic { 100; } + */ return (ModellingQuality); @@ -488,123 +496,123 @@ class ChartBase : public Dynamic { * @return * Returns true when the condition is met. */ - bool CheckCondition(CONST_REF_TO(string) _symbol, ENUM_CHART_CONDITION _cond, ARRAY_REF(DataParamEntry, _args)) { + bool CheckCondition(ENUM_CHART_CONDITION _cond, ARRAY_REF(DataParamEntry, _args)) { float _pp, _r1, _r2, _r3, _r4, _s1, _s2, _s3, _s4; switch (_cond) { case CHART_COND_ASK_BAR_PEAK: - return IsPeak(_symbol); + return IsPeak(); case CHART_COND_ASK_GT_BAR_HIGH: - return GetAsk(_symbol) > GetHigh(_symbol); + return GetAsk() > GetHigh(); case CHART_COND_ASK_GT_BAR_LOW: - return GetAsk(_symbol) > GetLow(_symbol); + return GetAsk() > GetLow(); case CHART_COND_ASK_LT_BAR_HIGH: - return GetAsk(_symbol) < GetHigh(_symbol); + return GetAsk() < GetHigh(); case CHART_COND_ASK_LT_BAR_LOW: - return GetAsk(_symbol) < GetLow(_symbol); + return GetAsk() < GetLow(); case CHART_COND_BAR_CLOSE_GT_PP_PP: { - ChartEntry _centry = GetEntry(_symbol, 1); - return GetClose(_symbol) > _centry.bar.ohlc.GetPivot(); + ChartEntry _centry = GetEntry(1); + return GetClose() > _centry.bar.ohlc.GetPivot(); } case CHART_COND_BAR_CLOSE_GT_PP_R1: { - ChartEntry _centry = GetEntry(_symbol, 1); + ChartEntry _centry = GetEntry(1); _centry.bar.ohlc.GetPivots(PP_CLASSIC, _pp, _r1, _r2, _r3, _r4, _s1, _s2, _s3, _s4); - return GetClose(_symbol) > _r1; + return GetClose() > _r1; } case CHART_COND_BAR_CLOSE_GT_PP_R2: { - ChartEntry _centry = GetEntry(_symbol, 1); + ChartEntry _centry = GetEntry(1); _centry.bar.ohlc.GetPivots(PP_CLASSIC, _pp, _r1, _r2, _r3, _r4, _s1, _s2, _s3, _s4); - return GetClose(_symbol) > _r2; + return GetClose() > _r2; } case CHART_COND_BAR_CLOSE_GT_PP_R3: { - ChartEntry _centry = GetEntry(_symbol, 1); + ChartEntry _centry = GetEntry(1); _centry.bar.ohlc.GetPivots(PP_CLASSIC, _pp, _r1, _r2, _r3, _r4, _s1, _s2, _s3, _s4); - return GetClose(_symbol) > _r3; + return GetClose() > _r3; } case CHART_COND_BAR_CLOSE_GT_PP_R4: { - ChartEntry _centry = GetEntry(_symbol, 1); + ChartEntry _centry = GetEntry(1); _centry.bar.ohlc.GetPivots(PP_CLASSIC, _pp, _r1, _r2, _r3, _r4, _s1, _s2, _s3, _s4); - return GetClose(_symbol) > _r4; + return GetClose() > _r4; } case CHART_COND_BAR_CLOSE_GT_PP_S1: { - ChartEntry _centry = GetEntry(_symbol, 1); + ChartEntry _centry = GetEntry(1); _centry.bar.ohlc.GetPivots(PP_CLASSIC, _pp, _r1, _r2, _r3, _r4, _s1, _s2, _s3, _s4); - return GetClose(_symbol) > _s1; + return GetClose() > _s1; } case CHART_COND_BAR_CLOSE_GT_PP_S2: { - ChartEntry _centry = GetEntry(_symbol, 1); + ChartEntry _centry = GetEntry(1); _centry.bar.ohlc.GetPivots(PP_CLASSIC, _pp, _r1, _r2, _r3, _r4, _s1, _s2, _s3, _s4); - return GetClose(_symbol) > _s2; + return GetClose() > _s2; } case CHART_COND_BAR_CLOSE_GT_PP_S3: { - ChartEntry _centry = GetEntry(_symbol, 1); + ChartEntry _centry = GetEntry(1); _centry.bar.ohlc.GetPivots(PP_CLASSIC, _pp, _r1, _r2, _r3, _r4, _s1, _s2, _s3, _s4); - return GetClose(_symbol) > _s3; + return GetClose() > _s3; } case CHART_COND_BAR_CLOSE_GT_PP_S4: { - ChartEntry _centry = GetEntry(_symbol, 1); + ChartEntry _centry = GetEntry(1); _centry.bar.ohlc.GetPivots(PP_CLASSIC, _pp, _r1, _r2, _r3, _r4, _s1, _s2, _s3, _s4); - return GetClose(_symbol) > _s4; + return GetClose() > _s4; } case CHART_COND_BAR_CLOSE_LT_PP_PP: { - ChartEntry _centry = GetEntry(_symbol, 1); - return GetClose(_symbol) < _centry.bar.ohlc.GetPivot(); + ChartEntry _centry = GetEntry(1); + return GetClose() < _centry.bar.ohlc.GetPivot(); } case CHART_COND_BAR_CLOSE_LT_PP_R1: { - ChartEntry _centry = GetEntry(_symbol, 1); + ChartEntry _centry = GetEntry(1); _centry.bar.ohlc.GetPivots(PP_CLASSIC, _pp, _r1, _r2, _r3, _r4, _s1, _s2, _s3, _s4); - return GetClose(_symbol) < _r1; + return GetClose() < _r1; } case CHART_COND_BAR_CLOSE_LT_PP_R2: { - ChartEntry _centry = GetEntry(_symbol, 1); + ChartEntry _centry = GetEntry(1); _centry.bar.ohlc.GetPivots(PP_CLASSIC, _pp, _r1, _r2, _r3, _r4, _s1, _s2, _s3, _s4); - return GetClose(_symbol) < _r2; + return GetClose() < _r2; } case CHART_COND_BAR_CLOSE_LT_PP_R3: { - ChartEntry _centry = GetEntry(_symbol, 1); + ChartEntry _centry = GetEntry(1); _centry.bar.ohlc.GetPivots(PP_CLASSIC, _pp, _r1, _r2, _r3, _r4, _s1, _s2, _s3, _s4); - return GetClose(_symbol) < _r3; + return GetClose() < _r3; } case CHART_COND_BAR_CLOSE_LT_PP_R4: { - ChartEntry _centry = GetEntry(_symbol, 1); + ChartEntry _centry = GetEntry(1); _centry.bar.ohlc.GetPivots(PP_CLASSIC, _pp, _r1, _r2, _r3, _r4, _s1, _s2, _s3, _s4); - return GetClose(_symbol) < _r4; + return GetClose() < _r4; } case CHART_COND_BAR_CLOSE_LT_PP_S1: { - ChartEntry _centry = GetEntry(_symbol, 1); + ChartEntry _centry = GetEntry(1); _centry.bar.ohlc.GetPivots(PP_CLASSIC, _pp, _r1, _r2, _r3, _r4, _s1, _s2, _s3, _s4); - return GetClose(_symbol) < _s1; + return GetClose() < _s1; } case CHART_COND_BAR_CLOSE_LT_PP_S2: { - ChartEntry _centry = GetEntry(_symbol, 1); + ChartEntry _centry = GetEntry(1); _centry.bar.ohlc.GetPivots(PP_CLASSIC, _pp, _r1, _r2, _r3, _r4, _s1, _s2, _s3, _s4); - return GetClose(_symbol) < _s2; + return GetClose() < _s2; } case CHART_COND_BAR_CLOSE_LT_PP_S3: { - ChartEntry _centry = GetEntry(_symbol, 1); + ChartEntry _centry = GetEntry(1); _centry.bar.ohlc.GetPivots(PP_CLASSIC, _pp, _r1, _r2, _r3, _r4, _s1, _s2, _s3, _s4); - return GetClose(_symbol) < _s3; + return GetClose() < _s3; } case CHART_COND_BAR_CLOSE_LT_PP_S4: { - ChartEntry _centry = GetEntry(_symbol, 1); + ChartEntry _centry = GetEntry(1); _centry.bar.ohlc.GetPivots(PP_CLASSIC, _pp, _r1, _r2, _r3, _r4, _s1, _s2, _s3, _s4); - return GetClose(_symbol) < _s4; + return GetClose() < _s4; } case CHART_COND_BAR_HIGHEST_CURR_20: - return GetHighest(_symbol, MODE_CLOSE, 20) == 0; + return GetHighest(MODE_CLOSE, 20) == 0; case CHART_COND_BAR_HIGHEST_CURR_50: - return GetHighest(_symbol, MODE_CLOSE, 50) == 0; + return GetHighest(MODE_CLOSE, 50) == 0; case CHART_COND_BAR_HIGHEST_PREV_20: - return GetHighest(_symbol, MODE_CLOSE, 20) == 1; + return GetHighest(MODE_CLOSE, 20) == 1; case CHART_COND_BAR_HIGHEST_PREV_50: - return GetHighest(_symbol, MODE_CLOSE, 50) == 1; + return GetHighest(MODE_CLOSE, 50) == 1; case CHART_COND_BAR_HIGH_GT_OPEN: - return GetHigh(_symbol) > GetOpen(_symbol); + return GetHigh() > GetOpen(); case CHART_COND_BAR_HIGH_LT_OPEN: - return GetHigh(_symbol) < GetOpen(_symbol); + return GetHigh() < GetOpen(); case CHART_COND_BAR_INDEX_EQ_ARG: // Current bar's index equals argument value. if (ArraySize(_args) > 0) { - return GetBarIndex(_symbol) == DataParamEntry::ToInteger(_args[0]); + return GetBarIndex() == DataParamEntry::ToInteger(_args[0]); } else { SetUserError(ERR_INVALID_PARAMETER); return false; @@ -612,7 +620,7 @@ class ChartBase : public Dynamic { case CHART_COND_BAR_INDEX_GT_ARG: // Current bar's index greater than argument value. if (ArraySize(_args) > 0) { - return GetBarIndex(_symbol) > DataParamEntry::ToInteger(_args[0]); + return GetBarIndex() > DataParamEntry::ToInteger(_args[0]); } else { SetUserError(ERR_INVALID_PARAMETER); return false; @@ -620,25 +628,25 @@ class ChartBase : public Dynamic { case CHART_COND_BAR_INDEX_LT_ARG: // Current bar's index lower than argument value. if (ArraySize(_args) > 0) { - return GetBarIndex(_symbol) < DataParamEntry::ToInteger(_args[0]); + return GetBarIndex() < DataParamEntry::ToInteger(_args[0]); } else { SetUserError(ERR_INVALID_PARAMETER); return false; } case CHART_COND_BAR_LOWEST_CURR_20: - return GetLowest(_symbol, MODE_CLOSE, 20) == 0; + return GetLowest(MODE_CLOSE, 20) == 0; case CHART_COND_BAR_LOWEST_CURR_50: - return GetLowest(_symbol, MODE_CLOSE, 50) == 0; + return GetLowest(MODE_CLOSE, 50) == 0; case CHART_COND_BAR_LOWEST_PREV_20: - return GetLowest(_symbol, MODE_CLOSE, 20) == 1; + return GetLowest(MODE_CLOSE, 20) == 1; case CHART_COND_BAR_LOWEST_PREV_50: - return GetLowest(_symbol, MODE_CLOSE, 50) == 1; + return GetLowest(MODE_CLOSE, 50) == 1; case CHART_COND_BAR_LOW_GT_OPEN: - return GetLow(_symbol) > GetOpen(_symbol); + return GetLow() > GetOpen(); case CHART_COND_BAR_LOW_LT_OPEN: - return GetLow(_symbol) < GetOpen(_symbol); + return GetLow() < GetOpen(); case CHART_COND_BAR_NEW: - return IsNewBar(_symbol); + return IsNewBar(); /* case CHART_COND_BAR_NEW_DAY: // @todo; @@ -661,9 +669,9 @@ class ChartBase : public Dynamic { return false; } } - bool CheckCondition(CONST_REF_TO(string) _symbol, ENUM_CHART_CONDITION _cond) { + bool CheckCondition(ENUM_CHART_CONDITION _cond) { ARRAY(DataParamEntry, _args); - return CheckCondition(_symbol, _cond, _args); + return CheckCondition(_cond, _args); } /* Printer methods */ @@ -671,9 +679,8 @@ class ChartBase : public Dynamic { /** * Returns textual representation of the Chart class. */ - string ToString(CONST_REF_TO(string) _symbol, unsigned int _shift = 0) { - return StringFormat("%s: %s", ChartTf::TfToString(Get(CHART_PARAM_TF)), - GetEntry(_symbol, _shift).ToCSV()); + string ToString(unsigned int _shift = 0) { + return StringFormat("%s: %s", ChartTf::TfToString(Get(CHART_PARAM_TF)), GetEntry(_shift).ToCSV()); } /* Snapshots */ @@ -684,15 +691,15 @@ class ChartBase : public Dynamic { * @return * Returns true if BarOHLC values has been saved, otherwise false. */ - bool SaveChartEntry(CONST_REF_TO(string) _symbol) { + bool SaveChartEntry() { // @todo: Use MqlRates. unsigned int _last = ArraySize(chart_saves); if (ArrayResize(chart_saves, _last + 1, 100)) { - chart_saves[_last].bar.ohlc.time = GetTime(_symbol); - chart_saves[_last].bar.ohlc.open = (float)GetOpen(_symbol); - chart_saves[_last].bar.ohlc.high = (float)GetHigh(_symbol); - chart_saves[_last].bar.ohlc.low = (float)GetLow(_symbol); - chart_saves[_last].bar.ohlc.close = (float)GetClose(_symbol); + chart_saves[_last].bar.ohlc.time = GetTime(); + chart_saves[_last].bar.ohlc.open = (float)GetOpen(); + chart_saves[_last].bar.ohlc.high = (float)GetHigh(); + chart_saves[_last].bar.ohlc.low = (float)GetLow(); + chart_saves[_last].bar.ohlc.close = (float)GetClose(); return true; } else { return false; @@ -704,7 +711,47 @@ class ChartBase : public Dynamic { /** * Check whether the price is in its peak for the current period. */ - bool IsPeak(CONST_REF_TO(string) _symbol) { - return GetAsk(_symbol) >= GetHigh(_symbol) || GetAsk(_symbol) <= GetLow(_symbol); + bool IsPeak() { return GetAsk() >= GetHigh() || GetAsk() <= GetLow(); } + + /* Other methods */ + + /** + * Load stored BarOHLC values. + * + * @param + * _index unsigned int Index of the element in BarOHLC array. + * @return + * Returns BarOHLC struct element. + */ + ChartEntry LoadChartEntry(unsigned int _index = 0) { return chart_saves[_index]; } + + /** + * Acknowledges chart that new tick happened. + */ + void OnTick() { + IncreaseTickIndex(); + if (IsNewBar()) { + IncreaseBarIndex(); + } + } + + /** + * Return size of BarOHLC array. + */ + unsigned long SizeChartEntry() { return ArraySize(chart_saves); } + + /* Serializers */ + + /** + * Returns serialized representation of the object instance. + */ + SerializerNodeType Serialize(Serializer& _s) { + /** + TODO + + ChartEntry _centry = GetEntry(); + _s.PassStruct(THIS_REF, "chart-entry", _centry, SERIALIZER_FIELD_FLAG_DYNAMIC); + */ + return SerializerNodeObject; } }; diff --git a/ChartMt.h b/ChartMt.h index 37d26915e..9f4710f03 100644 --- a/ChartMt.h +++ b/ChartMt.h @@ -42,93 +42,35 @@ class ChartMt : public ChartBase { /** * Constructor. */ - ChartMt(ENUM_TIMEFRAMES _tf) : ChartBase(_tf) {} + ChartMt(string _symbol, ENUM_TIMEFRAMES _tf) : ChartBase(_symbol, _tf) {} /** * Returns new or existing instance of Chart for a given timeframe. */ - static ChartMt* GetInstance(ENUM_TIMEFRAMES _tf) { + static ChartMt* GetInstance(const SymbolTf& _symbol_tf) { ChartMt* _ptr; - string _key = Util::MakeKey((int)_tf); - if (!Objects::TryGet(_key, _ptr)) { - _ptr = Objects::Set(_key, new ChartMt(_tf)); + if (!Objects::TryGet(_symbol_tf.Key(), _ptr)) { + _ptr = Objects::Set(_symbol_tf.Key(), new ChartMt(_symbol_tf.Symbol(), _symbol_tf.Tf())); } return _ptr; } // Virtual methods. - virtual datetime GetBarTime(CONST_REF_TO(string) _symbol, int _shift = 0) override { - return ::iTime(_symbol, GetTf(), _shift); - } - - /** - * Returns the current price value given applied price type, symbol and timeframe. - */ - virtual double GetPrice(ENUM_APPLIED_PRICE _ap, CONST_REF_TO(string) _symbol, int _shift = 0) override { - switch (_ap) { - case PRICE_OPEN: - return ::iOpen(_symbol, GetTf(), _shift); - case PRICE_HIGH: - return ::iHigh(_symbol, GetTf(), _shift); - case PRICE_LOW: - return ::iLow(_symbol, GetTf(), _shift); - case PRICE_CLOSE: - return ::iClose(_symbol, GetTf(), _shift); - } - Print("Invalid applied price!"); - DebugBreak(); - return 0; - } - - /** - * Returns tick volume value for the bar. - * - * If local history is empty (not loaded), function returns 0. - */ - virtual long GetVolume(CONST_REF_TO(string) _symbol, int _shift = 0) override { - return ::iVolume(_symbol, GetTf(), _shift); - } - /** - * Returns the shift of the maximum value over a specific number of periods depending on type. + * Returns time of the bar with a given shift. */ - virtual int GetHighest(CONST_REF_TO(string) _symbol, int type, int _count = WHOLE_ARRAY, int _start = 0) override { - return ::iHighest(_symbol, GetTf(), (ENUM_SERIESMODE)type, _count, _start); - } - - /** - * Returns the shift of the minimum value over a specific number of periods depending on type. - */ - virtual int GetLowest(CONST_REF_TO(string) _symbol, int type, int _count = WHOLE_ARRAY, int _start = 0) override { - return ::iLowest(_symbol, GetTf(), (ENUM_SERIESMODE)type, _count, _start); - } + virtual datetime GetBarTime(int _shift = 0) override { return ::iTime(GetSymbol(), GetTf(), _shift); } /** * Returns the number of bars on the chart. */ - virtual int GetBars(CONST_REF_TO(string) _symbol) override { + virtual int GetBars() override { #ifdef __MQL4__ // In MQL4, for the current chart, the information about the amount of bars is in the Bars predefined variable. - return ::iBars(_symbol, GetTf()); + return ::iBars(GetSymbol(), GetTf()); #else // _MQL5__ - return ::Bars(_symbol, GetTf()); -#endif - } - - /** - * Returns open time price value for the bar of indicated symbol. - * - * If local history is empty (not loaded), function returns 0. - */ - virtual datetime GetTime(CONST_REF_TO(string) _symbol, unsigned int _shift = 0) override { -#ifdef __MQL4__ - return ::iTime(_symbol, GetTf(), _shift); // Same as: Time[_shift] -#else // __MQL5__ - ARRAY(datetime, _arr); - // ENUM_TIMEFRAMES _tf = MQL4::TFMigrate(_tf); - // @todo: Improves performance by caching values. - return (_shift >= 0 && ::CopyTime(_symbol, GetTf(), _shift, 1, _arr) > 0) ? _arr[0] : 0; + return ::Bars(GetSymbol(), GetTf()); #endif } @@ -137,17 +79,17 @@ class ChartMt : public ChartBase { * * Returns the index of the bar which covers the specified time. */ - virtual int GetBarShift(CONST_REF_TO(string) _symbol, datetime _time, bool _exact = false) override { + virtual int GetBarShift(datetime _time, bool _exact = false) override { #ifdef __MQL4__ - return ::iBarShift(_symbol, GetTf(), _time, _exact); + return ::iBarShift(GetTf(), _time, _exact); #else // __MQL5__ if (_time < 0) return (-1); ARRAY(datetime, arr); datetime _time0; // ENUM_TIMEFRAMES _tf = MQL4::TFMigrate(_tf); - CopyTime(_symbol, GetTf(), 0, 1, arr); + CopyTime(GetSymbol(), GetTf(), 0, 1, arr); _time0 = arr[0]; - if (CopyTime(_symbol, GetTf(), _time, _time0, arr) > 0) { + if (CopyTime(GetSymbol(), GetTf(), _time, _time0, arr) > 0) { if (ArraySize(arr) > 2) { return ArraySize(arr) - 1; } else { @@ -159,26 +101,82 @@ class ChartMt : public ChartBase { #endif } + /** + * Returns the shift of the maximum value over a specific number of periods depending on type. + */ + virtual int GetHighest(int type, int _count = WHOLE_ARRAY, int _start = 0) override { + return ::iHighest(GetSymbol(), GetTf(), (ENUM_SERIESMODE)type, _count, _start); + } + + /** + * Returns the shift of the minimum value over a specific number of periods depending on type. + */ + virtual int GetLowest(int type, int _count = WHOLE_ARRAY, int _start = 0) override { + return ::iLowest(GetSymbol(), GetTf(), (ENUM_SERIESMODE)type, _count, _start); + } + /** * Get peak price at given number of bars. * * In case of error, check it via GetLastError(). */ - virtual double GetPeakPrice(CONST_REF_TO(string) _symbol, int _bars, int _mode, int _index) override { + virtual double GetPeakPrice(int _bars, int _mode, int _index) override { int _ibar = -1; // @todo: Add symbol parameter. - double _peak_price = GetOpen(_symbol, 0); + double _peak_price = GetOpen(0); switch (_mode) { case MODE_HIGH: - _ibar = GetHighest(_symbol, MODE_HIGH, _bars, _index); - return _ibar >= 0 ? GetHigh(_symbol, _ibar) : false; + _ibar = GetHighest(MODE_HIGH, _bars, _index); + return _ibar >= 0 ? GetHigh(_ibar) : false; case MODE_LOW: - _ibar = GetLowest(_symbol, MODE_LOW, _bars, _index); - return _ibar >= 0 ? GetLow(_symbol, _ibar) : false; + _ibar = GetLowest(MODE_LOW, _bars, _index); + return _ibar >= 0 ? GetLow(_ibar) : false; default: return false; } } + + /** + * Returns the current price value given applied price type, symbol and timeframe. + */ + virtual double GetPrice(ENUM_APPLIED_PRICE _ap, int _shift = 0) override { + switch (_ap) { + case PRICE_OPEN: + return ::iOpen(GetSymbol(), GetTf(), _shift); + case PRICE_HIGH: + return ::iHigh(GetSymbol(), GetTf(), _shift); + case PRICE_LOW: + return ::iLow(GetSymbol(), GetTf(), _shift); + case PRICE_CLOSE: + return ::iClose(GetSymbol(), GetTf(), _shift); + } + Print("Invalid applied price!"); + DebugBreak(); + return 0; + } + + /** + * Returns open time price value for the bar of indicated symbol. + * + * If local history is empty (not loaded), function returns 0. + */ + virtual datetime GetTime(unsigned int _shift = 0) override { +#ifdef __MQL4__ + return ::iTime(GetTf(), _shift); // Same as: Time[_shift] +#else // __MQL5__ + ARRAY(datetime, _arr); + // ENUM_TIMEFRAMES _tf = MQL4::TFMigrate(_tf); + // @todo: Improves performance by caching values. + return (_shift >= 0 && ::CopyTime(GetSymbol(), GetTf(), _shift, 1, _arr) > 0) ? _arr[0] : 0; +#endif + } + + /** + * Returns tick volume value for the bar. + * + * If local history is empty (not loaded), function returns 0. + */ + virtual long GetVolume(int _shift = 0) override { return ::iVolume(GetSymbol(), GetTf(), _shift); } }; /** @@ -191,10 +189,10 @@ struct ChartPriceClose { const SymbolTf symbol_tf; public: - ChartPriceClose() : symbol_tf(_Symbol, PERIOD_CURRENT) {} + ChartPriceClose() : symbol_tf(Symbol(), PERIOD_CURRENT) {} double operator[](const int _shift) const { return Get(symbol_tf, _shift); } static double Get(const SymbolTf& _symbol_tf, const int _shift) { - return ChartMt::GetInstance(_symbol_tf.Tf()) PTR_DEREF GetClose(_symbol_tf.Symbol(), _shift); + return ChartMt::GetInstance(_symbol_tf) PTR_DEREF GetClose(_shift); } }; @@ -208,10 +206,10 @@ struct ChartPriceHigh { const SymbolTf symbol_tf; public: - ChartPriceHigh() : symbol_tf(_Symbol, PERIOD_CURRENT) {} + ChartPriceHigh() : symbol_tf(Symbol(), PERIOD_CURRENT) {} double operator[](const int _shift) const { return Get(symbol_tf, _shift); } static double Get(const SymbolTf& _symbol_tf, const int _shift) { - return ChartMt::GetInstance(_symbol_tf.Tf()) PTR_DEREF GetHigh(_symbol_tf.Symbol(), _shift); + return ChartMt::GetInstance(_symbol_tf) PTR_DEREF GetHigh(_shift); } }; @@ -225,10 +223,10 @@ struct ChartPriceLow { const SymbolTf symbol_tf; public: - ChartPriceLow() : symbol_tf(_Symbol, PERIOD_CURRENT) {} + ChartPriceLow() : symbol_tf(Symbol(), PERIOD_CURRENT) {} double operator[](const int _shift) const { return Get(symbol_tf, _shift); } static double Get(const SymbolTf& _symbol_tf, const int _shift) { - return ChartMt::GetInstance(_symbol_tf.Tf()) PTR_DEREF GetLow(_symbol_tf.Symbol(), _shift); + return ChartMt::GetInstance(_symbol_tf) PTR_DEREF GetLow(_shift); } }; @@ -242,10 +240,10 @@ struct ChartPriceOpen { const SymbolTf symbol_tf; public: - ChartPriceOpen() : symbol_tf(_Symbol, PERIOD_CURRENT) {} + ChartPriceOpen() : symbol_tf(Symbol(), PERIOD_CURRENT) {} double operator[](const int _shift) const { return Get(symbol_tf, _shift); } static double Get(const SymbolTf& _symbol_tf, const int _shift) { - return ChartMt::GetInstance(_symbol_tf.Tf()) PTR_DEREF GetOpen(_symbol_tf.Symbol(), _shift); + return ChartMt::GetInstance(_symbol_tf) PTR_DEREF GetOpen(_shift); } }; @@ -259,9 +257,9 @@ struct ChartBarTime { const SymbolTf symbol_tf; public: - ChartBarTime() : symbol_tf(_Symbol, PERIOD_CURRENT) {} + ChartBarTime() : symbol_tf(Symbol(), PERIOD_CURRENT) {} datetime operator[](const int _shift) const { return Get(symbol_tf, _shift); } static datetime Get(const SymbolTf& _symbol_tf, const int _shift) { - return ChartMt::GetInstance(_symbol_tf.Tf()) PTR_DEREF GetTime(_symbol_tf.Symbol(), _shift); + return ChartMt::GetInstance(_symbol_tf) PTR_DEREF GetTime(_shift); } }; diff --git a/Indicator.mqh b/Indicator.mqh index 6b22655e8..5262dd4ef 100644 --- a/Indicator.mqh +++ b/Indicator.mqh @@ -936,7 +936,7 @@ class Indicator : public IndicatorBase { bool AddEntry(IndicatorDataEntry& entry, int _shift = 0) { if (!entry.IsValid()) return false; - datetime timestamp = GetTime(_shift); + datetime timestamp = GetBarTime(_shift); entry.timestamp = timestamp; idata.Add(entry, timestamp); @@ -948,7 +948,7 @@ class Indicator : public IndicatorBase { // Print("Drawing ", GetName(), iparams.indi_data != NULL ? (" (over " + iparams.indi_data.GetName() + ")") : ""); for (int i = 0; i < (int)iparams.GetMaxModes(); ++i) draw.DrawLineTo(GetName() + "_" + IntegerToString(i) + "_" + IntegerToString(iparams.GetDataSourceMode()), - ChartStatic::iTime(GetSymbol(), GetTf(), 0), GetEntry(0)[i], iparams.draw_window); + GetBarTime(0), GetEntry(0)[i], iparams.draw_window); } } @@ -1070,11 +1070,11 @@ class Indicator : public IndicatorBase { IndicatorDataEntry GetEntry(int _index = -1) override { ResetLastError(); int _ishift = _index >= 0 ? _index : iparams.GetShift(); - long _bar_time = ChartStatic::iTime(GetSymbol(), GetTf(), _ishift); + long _bar_time = GetBarTime(_ishift); IndicatorDataEntry _entry = idata.GetByKey(_bar_time); if (_bar_time > 0 && !_entry.IsValid() && !_entry.CheckFlag(INDI_ENTRY_FLAG_INSUFFICIENT_DATA)) { _entry.Resize(iparams.GetMaxModes()); - _entry.timestamp = ChartStatic::iTime(GetSymbol(), GetTf(), _ishift); + _entry.timestamp = GetBarTime(_ishift); for (int _mode = 0; _mode < (int)iparams.GetMaxModes(); _mode++) { switch (iparams.GetDataValueType()) { case TYPE_BOOL: diff --git a/Indicator/IndicatorCandle.h b/Indicator/IndicatorCandle.h index 491c7882a..63c021768 100644 --- a/Indicator/IndicatorCandle.h +++ b/Indicator/IndicatorCandle.h @@ -99,7 +99,7 @@ class IndicatorCandle : public Indicator { IndicatorDataEntry GetEntry(int _index = -1) override { ResetLastError(); unsigned int _ishift = _index >= 0 ? _index : iparams.GetShift(); - long _candle_time = CalcCandleTimestamp(ChartStatic::iTime(GetSymbol(), GetTf(), _ishift)); + long _candle_time = CalcCandleTimestamp(GetBarTime(_ishift)); long _curr_candle_time; CandleOCTOHLC _candle; @@ -107,7 +107,7 @@ class IndicatorCandle : public Indicator { if (icdata.Size() > 0) { int i = 0; while (true) { - _curr_candle_time = CalcCandleTimestamp(ChartStatic::iTime(GetSymbol(), GetTf(), i++)); + _curr_candle_time = CalcCandleTimestamp(GetBarTime(i++)); if (_curr_candle_time < icdata.GetMin()) { // There is no older entries. diff --git a/IndicatorBase.h b/IndicatorBase.h index 84bf198b2..d69318888 100644 --- a/IndicatorBase.h +++ b/IndicatorBase.h @@ -355,11 +355,17 @@ class IndicatorBase : public Object { /* Getters */ /** - * Returns pointer to chart the indicator is bound to. + * Returns pointer to chart the indicator is bound to. By default it tries to instantiate MT-based chart for current + * symbol and timeframe. */ ChartBase* GetChart() { if (!chart.IsSet()) { - chart = new ChartMt(PERIOD_CURRENT); + chart = new ChartMt(_Symbol, PERIOD_CURRENT); + } + + if (!chart.IsSet()) { + Print("Error: Indicator has no chart specified!"); + DebugBreak(); } return chart.Ptr(); @@ -368,68 +374,62 @@ class IndicatorBase : public Object { /** * Gets OHLC price values. */ - BarOHLC GetOHLC(int _shift = 0) { return chart.Ptr() PTR_DEREF GetOHLC(GetSymbol(), _shift); } + BarOHLC GetOHLC(int _shift = 0) { return chart REF_DEREF GetOHLC(_shift); } /** * Returns time of the bar for a given shift. */ - datetime GetBarTime(int _shift = 0) { return chart.Ptr() PTR_DEREF GetBarTime(GetSymbol(), _shift); } + datetime GetBarTime(int _shift = 0) { return chart REF_DEREF GetBarTime(_shift); } /** * Returns time of the last bar. */ - datetime GetLastBarTime() { return chart.Ptr() PTR_DEREF GetLastBarTime(GetSymbol()); } + datetime GetLastBarTime() { return chart REF_DEREF GetLastBarTime(); } /** * Returns the current price value given applied price type, symbol and timeframe. */ - double GetPrice(ENUM_APPLIED_PRICE _ap, int _shift = 0) { - return chart.Ptr() PTR_DEREF GetPrice(_ap, GetSymbol(), _shift); - } + double GetPrice(ENUM_APPLIED_PRICE _ap, int _shift = 0) { return chart REF_DEREF GetPrice(_ap, _shift); } /** * Returns tick volume value for the bar. * * If local history is empty (not loaded), function returns 0. */ - long GetVolume(int _shift = 0) { return chart.Ptr() PTR_DEREF GetVolume(GetSymbol(), _shift); } + long GetVolume(int _shift = 0) { return chart REF_DEREF GetVolume(_shift); } /** * Returns the shift of the maximum value over a specific number of periods depending on type. */ int GetHighest(int type, int _count = WHOLE_ARRAY, int _start = 0) { - return chart.Ptr() PTR_DEREF GetHighest(GetSymbol(), type, _count, _start); + return chart REF_DEREF GetHighest(type, _count, _start); } /** * Returns the shift of the minimum value over a specific number of periods depending on type. */ int GetLowest(string _symbol, ENUM_TIMEFRAMES _tf, int type, int _count = WHOLE_ARRAY, int _start = 0) { - return chart.Ptr() PTR_DEREF GetLowest(GetSymbol(), type, _count, _start); + return chart REF_DEREF GetLowest(type, _count, _start); } /** * Returns the number of bars on the chart. */ - int GetBars() { return chart.Ptr() PTR_DEREF GetBars(GetSymbol()); } + int GetBars() { return chart REF_DEREF GetBars(); } /** * Search for a bar by its time. * * Returns the index of the bar which covers the specified time. */ - int GetBarShift(datetime _time, bool _exact = false) { - return chart.Ptr() PTR_DEREF GetBarShift(GetSymbol(), _time, _exact); - } + int GetBarShift(datetime _time, bool _exact = false) { return chart REF_DEREF GetBarShift(_time, _exact); } /** * Get peak price at given number of bars. * * In case of error, check it via GetLastError(). */ - double GetPeakPrice(int _bars, int _mode, int _index) { - return chart.Ptr() PTR_DEREF GetPeakPrice(GetSymbol(), _bars, _mode, _index); - } + double GetPeakPrice(int _bars, int _mode, int _index) { return chart REF_DEREF GetPeakPrice(_bars, _mode, _index); } /** * Returns indicator's flags. diff --git a/Indicators/Indi_Momentum.mqh b/Indicators/Indi_Momentum.mqh index ca69aa649..327588ed2 100644 --- a/Indicators/Indi_Momentum.mqh +++ b/Indicators/Indi_Momentum.mqh @@ -162,8 +162,7 @@ class Indi_Momentum : public IndicatorTickOrCandleSource { _value = Indi_Momentum::iMomentumOnIndicator(GetDataSource(), GetSymbol(), GetTf(), GetPeriod(), GetDataSourceMode(), iparams.shift + _shift); if (iparams.is_draw) { - draw.DrawLineTo(StringFormat("%s", GetName()), - GetChart() PTR_DEREF GetBarTime(GetSymbol(), GetTf(), iparams.shift + _shift), _value, 1); + draw.DrawLineTo(StringFormat("%s", GetName()), GetBarTime(iparams.shift + _shift), _value, 1); } break; } diff --git a/Indicators/Indi_PriceFeeder.mqh b/Indicators/Indi_PriceFeeder.mqh index 0f6225ec9..9dfc075ea 100644 --- a/Indicators/Indi_PriceFeeder.mqh +++ b/Indicators/Indi_PriceFeeder.mqh @@ -92,8 +92,7 @@ class Indi_PriceFeeder : public IndicatorTickOrCandleSource { static double iRSIOnIndicator(IndicatorBase *_indi, Indi_RSI *_obj, string _symbol = NULL, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, unsigned int _period = 14, ENUM_APPLIED_PRICE _applied_price = PRICE_CLOSE, int _shift = 0) { - long _bar_time_curr = - _obj PTR_DEREF GetChart() PTR_DEREF GetBarTime(_obj PTR_DEREF GetSymbol(), _obj PTR_DEREF GetTf(), _shift); - long _bar_time_prev = - _obj PTR_DEREF GetChart() PTR_DEREF GetBarTime(_obj PTR_DEREF GetSymbol(), _obj PTR_DEREF GetTf(), _shift + 1); + long _bar_time_curr = _obj PTR_DEREF GetBarTime(_shift); + long _bar_time_prev = _obj PTR_DEREF GetBarTime(_shift + 1); if (fmin(_bar_time_curr, _bar_time_prev) < 0) { // Return empty value on invalid bar time. return EMPTY_VALUE; diff --git a/Indicators/Price/Indi_Price.mqh b/Indicators/Price/Indi_Price.mqh index d5ff8341a..e1c651cbe 100644 --- a/Indicators/Price/Indi_Price.mqh +++ b/Indicators/Price/Indi_Price.mqh @@ -58,9 +58,7 @@ class Indi_Price : public IndicatorTickOrCandleSource { /** * Checks whether indicator has a valid value for a given shift. */ - virtual bool HasValidEntry(int _shift = 0) { - return GetChart() PTR_DEREF GetBarTime(GetSymbol(), GetTf(), _shift) != 0; - } + virtual bool HasValidEntry(int _shift = 0) { return GetBarTime(_shift) != 0; } /** * Returns the indicator's value. diff --git a/Std.h b/Std.h index 6ac8bf397..a680db7d2 100644 --- a/Std.h +++ b/Std.h @@ -51,6 +51,7 @@ #define PTR_TO_REF(PTR) PTR #define MAKE_REF_FROM_PTR(TYPE, NAME, PTR) TYPE* NAME = PTR #define nullptr NULL +#define REF_DEREF .Ptr(). #else #define THIS_ATTR this-> #define THIS_PTR (this) @@ -60,6 +61,7 @@ #define PTR_ATTRIB2(O, A, B) O->A->B #define PTR_TO_REF(PTR) (*PTR) #define MAKE_REF_FROM_PTR(TYPE, NAME, PTR) TYPE& NAME = PTR +#define REF_DEREF .Ptr()-> #endif // References. diff --git a/Storage/Objects.h b/Storage/Objects.h index 9a312608e..3be674f54 100644 --- a/Storage/Objects.h +++ b/Storage/Objects.h @@ -48,7 +48,7 @@ class Objects { /** * Tries to retrieve pointer to object for a given key. Returns true if object did exist. */ - static bool TryGet(string& key, C*& out_ptr) { + static bool TryGet(CONST_REF_TO(string) key, C*& out_ptr) { int position; if (!GetObjects().KeyExists(key, position)) { out_ptr = NULL; @@ -62,7 +62,7 @@ class Objects { /** * Stores object pointer with a given key. */ - static C* Set(string& key, C* ptr) { + static C* Set(CONST_REF_TO(string) key, C* ptr) { Ref _ref(ptr); GetObjects().Set(key, _ref); return ptr; diff --git a/Strategy.mqh b/Strategy.mqh index 1f13a0167..b8f6d3286 100644 --- a/Strategy.mqh +++ b/Strategy.mqh @@ -1003,7 +1003,7 @@ class Strategy : public Taskable { Chart *_chart = trade.GetChart(); IndicatorBase *_indi = GetIndicators().Begin().Value().Ptr(); StrategyPriceStop _psm(_method); - _psm.SetChartParams(_chart.GetParams()); + _psm.SetChart(_chart); if (Object::IsValid(_indi)) { int _ishift = 12; // @todo: Make it dynamic or as variable. float _value = 0.0f; // @todo diff --git a/Strategy.struct.pricestop.h b/Strategy.struct.pricestop.h index f018bfce9..6004ba79e 100644 --- a/Strategy.struct.pricestop.h +++ b/Strategy.struct.pricestop.h @@ -56,7 +56,7 @@ struct StrategyPriceStop { float ivalue; // Indicator price value. unsigned int method; // Store price stop methods (@see: ENUM_STRATEGY_PRICE_STOP). // unsigned int mode[2]; // Indicator modes to use. - ChartParams cparams; + Ref chart; // IndicatorDataEntry idata[]; // IndicatorParams iparams; @@ -66,8 +66,8 @@ struct StrategyPriceStop { // Calculate price stop value. float GetValue(int _shift = 0, int _direction = -1, float _min_trade_dist = 0.0f) { float _result = ivalue, _trail = _min_trade_dist; - BarOHLC _ohlc0 = Chart::GetOHLC(cparams.tf.GetTf(), 0, cparams.symbol); - BarOHLC _ohlc1 = Chart::GetOHLC(cparams.tf.GetTf(), _shift, cparams.symbol); + BarOHLC _ohlc0 = chart REF_DEREF GetOHLC(0); + BarOHLC _ohlc1 = chart REF_DEREF GetOHLC(_shift); if (CheckMethod(STRATEGY_PRICE_STOP_INDI_PRICE)) { _result = ivalue; } @@ -79,7 +79,7 @@ struct StrategyPriceStop { // On peak, use low or high prices instead. _ap = _direction > 0 ? PRICE_HIGH : PRICE_LOW; } - _price = (float)ChartStatic::iPrice(_ap, cparams.symbol, cparams.tf.GetTf(), _shift); + _price = (float)chart REF_DEREF GetPrice(_ap, _shift); _result = _direction > 0 ? fmax(_price, _result) : fmin(_price, _result); } if (CheckMethod(STRATEGY_PRICE_STOP_PRICE_PP)) { @@ -103,7 +103,7 @@ struct StrategyPriceStop { return _result; } /* Setters */ - void SetChartParams(ChartParams &_cparams) { cparams = _cparams; } + void SetChart(ChartBase* _chart) { chart = _chart; } void SetIndicatorPriceValue(float _ivalue) { ivalue = _ivalue; } /* void SetIndicatorDataEntry(IndicatorDataEntry &_data[]) { @@ -136,7 +136,7 @@ struct StrategyPriceStop { } void SetMethod(unsigned int _flags) { method = _flags; } /* Serializers */ - SerializerNodeType Serialize(Serializer &_s) { + SerializerNodeType Serialize(Serializer& _s) { int _size = sizeof(int) * 8; for (int i = 0; i < _size; i++) { int _value = CheckMethod(1 << i) ? 1 : 0;