From dbf7af068357b1deb837b468684c890f717ef3c0 Mon Sep 17 00:00:00 2001 From: kenorb Date: Thu, 28 Oct 2021 20:17:45 +0100 Subject: [PATCH 01/77] Indicator: Adds IndicatorTick --- Action.mqh | 18 +-- Condition.mqh | 20 +-- Indicator.mqh | 98 ++++++------- Indicator/IndicatorTick.h | 96 +++++++++++++ Indicator/tests/IndicatorTick.test.mq4 | 28 ++++ Indicator/tests/IndicatorTick.test.mq5 | 64 +++++++++ IndicatorBase.h | 189 ++----------------------- 7 files changed, 263 insertions(+), 250 deletions(-) create mode 100644 Indicator/IndicatorTick.h create mode 100644 Indicator/tests/IndicatorTick.test.mq4 create mode 100644 Indicator/tests/IndicatorTick.test.mq5 diff --git a/Action.mqh b/Action.mqh index 5ed379560..1e01b324d 100644 --- a/Action.mqh +++ b/Action.mqh @@ -139,14 +139,16 @@ class Action { break; #endif #ifdef INDICATOR_MQH - case ACTION_TYPE_INDICATOR: - if (Object::IsValid(_entry.obj)) { - _result = ((IndicatorBase *)_entry.obj).ExecuteAction((ENUM_INDICATOR_ACTION)_entry.action_id); - } else { - _result = false; - _entry.AddFlags(ACTION_ENTRY_FLAG_IS_INVALID); - } - break; + /* + case ACTION_TYPE_INDICATOR: + if (Object::IsValid(_entry.obj)) { + _result = ((IndicatorBase *)_entry.obj).ExecuteAction((ENUM_INDICATOR_ACTION)_entry.action_id); + } else { + _result = false; + _entry.AddFlags(ACTION_ENTRY_FLAG_IS_INVALID); + } + break; + */ #endif #ifdef STRATEGY_MQH case ACTION_TYPE_STRATEGY: diff --git a/Condition.mqh b/Condition.mqh index 915cbcd4e..862d20264 100644 --- a/Condition.mqh +++ b/Condition.mqh @@ -165,15 +165,17 @@ class Condition { } break; #ifdef INDICATOR_MQH - case COND_TYPE_INDICATOR: - if (Object::IsValid(_entry.obj)) { - _result = ((IndicatorBase *)_entry.obj).CheckCondition((ENUM_INDICATOR_CONDITION)_entry.cond_id, _entry.args); - } else { - // Static method not supported. - _result = false; - _entry.AddFlags(COND_ENTRY_FLAG_IS_INVALID); - } - break; + /* + case COND_TYPE_INDICATOR: + if (Object::IsValid(_entry.obj)) { + _result = ((IndicatorBase *)_entry.obj).CheckCondition((ENUM_INDICATOR_CONDITION)_entry.cond_id, + _entry.args); } else { + // Static method not supported. + _result = false; + _entry.AddFlags(COND_ENTRY_FLAG_IS_INVALID); + } + break; + */ #endif case COND_TYPE_MARKET: if (Object::IsValid(_entry.obj)) { diff --git a/Indicator.mqh b/Indicator.mqh index 3717c10aa..069497a53 100644 --- a/Indicator.mqh +++ b/Indicator.mqh @@ -56,9 +56,49 @@ class Chart; template class Indicator : public IndicatorBase { protected: - // Structs. + BufferStruct idata; TS iparams; + protected: + /* Protected methods */ + + bool Init() { + ArrayResize(value_storages, iparams.GetMaxModes()); + switch (iparams.GetDataSourceType()) { + case IDATA_BUILTIN: + break; + case IDATA_ICUSTOM: + break; + case IDATA_INDICATOR: + if (indi_src == NULL) { + // Indi_Price* _indi_price = Indi_Price::GetCached(GetSymbol(), GetTf(), iparams.GetShift()); + // SetDataSource(_indi_price, true, PRICE_OPEN); + } + break; + } + return InitDraw(); + } + + /** + * Initialize indicator data drawing on custom data. + */ + bool InitDraw() { + if (iparams.is_draw && !Object::IsValid(draw)) { + draw = new DrawIndicator(THIS_PTR); + draw.SetColorLine(iparams.indi_color); + } + return iparams.is_draw; + } + + /** + * Deinitialize drawing. + */ + void DeinitDraw() { + if (draw) { + delete draw; + } + } + public: /* Indicator enumerations */ @@ -115,47 +155,6 @@ class Indicator : public IndicatorBase { } } - /* Init methods */ - - bool Init() { - ArrayResize(value_storages, iparams.GetMaxModes()); - switch (iparams.GetDataSourceType()) { - case IDATA_BUILTIN: - break; - case IDATA_ICUSTOM: - break; - case IDATA_INDICATOR: - if (indi_src == NULL) { - // Indi_Price* _indi_price = Indi_Price::GetCached(GetSymbol(), GetTf(), iparams.GetShift()); - // SetDataSource(_indi_price, true, PRICE_OPEN); - } - break; - } - return InitDraw(); - } - - /** - * Initialize indicator data drawing on custom data. - */ - bool InitDraw() { - if (iparams.is_draw && !Object::IsValid(draw)) { - draw = new DrawIndicator(THIS_PTR); - draw.SetColorLine(iparams.indi_color); - } - return iparams.is_draw; - } - - /* Deinit methods */ - - /** - * Deinitialize drawing. - */ - void DeinitDraw() { - if (draw) { - delete draw; - } - } - /* Getters */ /** @@ -402,16 +401,12 @@ class Indicator : public IndicatorBase { */ virtual IndicatorBase* FetchDataSource(ENUM_INDICATOR_TYPE _id) { return NULL; } - /* Operator overloading methods */ + /* Getters */ /** - * Access indicator entry data using [] operator. + * Get pointer to data of indicator. */ - IndicatorDataEntry operator[](int _shift) { return GetEntry(_shift); } - IndicatorDataEntry operator[](ENUM_INDICATOR_INDEX _shift) { return GetEntry(_shift); } - IndicatorDataEntry operator[](datetime _dt) { return idata[_dt]; } - - /* Getters */ + BufferStruct* GetData() { return GetPointer(idata); } /** * Returns the highest bar's index (shift). @@ -613,11 +608,6 @@ class Indicator : public IndicatorBase { return _signals; } - /** - * Get pointer to data of indicator. - */ - BufferStruct* GetData() { return GetPointer(idata); } - /** * Get name of the indicator. */ diff --git a/Indicator/IndicatorTick.h b/Indicator/IndicatorTick.h new file mode 100644 index 000000000..3fe26bdf9 --- /dev/null +++ b/Indicator/IndicatorTick.h @@ -0,0 +1,96 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2021, EA31337 Ltd | +//| https://github.com/EA31337 | +//+------------------------------------------------------------------+ + +/* + * This file is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +// Ignore processing of this file if already included. +#ifndef INDICATOR_TICK_MQH +#define INDICATOR_TICK_MQH + +// Includes. +#include "../IndicatorBase.h" +//#include "Array.mqh" +//#include "BufferStruct.mqh" +//#include "Chart.mqh" +//#include "DateTime.mqh" +//#include "DrawIndicator.mqh" +//#include "Indicator.define.h" +//#include "Indicator.enum.h" +//#include "Indicator.struct.cache.h" +//#include "Indicator.struct.h" +//#include "Indicator.struct.serialize.h" +//#include "Indicator.struct.signal.h" +//#include "IndicatorBase.h" +//#include "Math.h" +//#include "Object.mqh" +//#include "Refs.mqh" +//#include "Serializer.mqh" +//#include "SerializerCsv.mqh" +//#include "SerializerJson.mqh" +//#include "Storage/ValueStorage.h" +//#include "Storage/ValueStorage.indicator.h" +//#include "Storage/ValueStorage.native.h" + +/** + * Class to deal with tick indicators. + */ +// template +class IndicatorTick : public IndicatorBase { + protected: + BufferStruct tickdata; + + public: + /* Special methods */ + + /** + * Class constructor. + */ + IndicatorTick() {} + + /* Virtual method implementations */ + + /** + * Returns the indicator's data entry. + * + * @see: IndicatorDataEntry. + * + * @return + * Returns IndicatorDataEntry struct filled with indicator values. + */ + IndicatorDataEntry GetEntry(int _timestamp = 0) { + IndicatorDataEntry _entry = tickdata.GetByKey(_timestamp); + if (!_entry.IsValid() && !_entry.CheckFlag(INDI_ENTRY_FLAG_INSUFFICIENT_DATA)) { + _entry.timestamp = _timestamp; + _entry.Resize(4); + _entry.SetFlag(INDI_ENTRY_FLAG_IS_VALID, IsValidEntry(_entry)); + for (int _mode = 0; _mode < (int)iparams.GetMaxModes(); _mode++) { + //_entry.values[_mode] = GetValue(_mode, _shift); / @todo + } + if (_entry.IsValid()) { + idata.Add(_entry, _bar_time); + } else { + _entry.AddFlags(INDI_ENTRY_FLAG_INSUFFICIENT_DATA); + } + } + return _entry; + } +}; + +#endif diff --git a/Indicator/tests/IndicatorTick.test.mq4 b/Indicator/tests/IndicatorTick.test.mq4 new file mode 100644 index 000000000..430e9d0e3 --- /dev/null +++ b/Indicator/tests/IndicatorTick.test.mq4 @@ -0,0 +1,28 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2021, EA31337 Ltd | +//| https://github.com/EA31337 | +//+------------------------------------------------------------------+ + +/* + * This file is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * @file + * Test functionality of IndicatorTick class. + */ + +// Includes. +#include "IndicatorTick.test.mq5" diff --git a/Indicator/tests/IndicatorTick.test.mq5 b/Indicator/tests/IndicatorTick.test.mq5 new file mode 100644 index 000000000..495154af3 --- /dev/null +++ b/Indicator/tests/IndicatorTick.test.mq5 @@ -0,0 +1,64 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2021, EA31337 Ltd | +//| https://github.com/EA31337 | +//+------------------------------------------------------------------+ + +/* + * This file is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * @file + * Test functionality of IndicatorTick class. + */ + +// Includes. +#include "../../Test.mqh" +#include "../IndicatorTick.h" + +/** + * Implements OnInit(). + */ +int OnInit() { + /* @fixme + // Initialize. + IndicatorParams iparams(INDI_NONE, TYPE_INT, 10); + Indicator *in = new Indicator(iparams, NULL); + // Check empty values. + assertTrueOrFail(in.GetBufferSize() == 10, "Wrong buffer size!"); + assertTrueOrFail(in.GetEmpty().double_value == 0.0, "Wrong empty double value!"); + assertTrueOrFail(in.GetEmpty().integer_value == 0, "Wrong empty integer value!"); + // Check dynamic allocation. + MqlParam entry; + entry.integer_value = 1; + for (uint i = 0; i < in.GetBufferSize() * 2; i++) { + in.AddValue(entry); + Print("Index ", i, ": Curr: ", in.GetValue(0).integer_value, "; Prev: ", in.GetValue(1).integer_value); + assertTrueOrFail(in.GetValue(0).integer_value == entry.integer_value, + StringFormat("Wrong latest value (%d <> %d)!", + in.GetValue(0).integer_value, + entry.integer_value)); + assertTrueOrFail(in.GetValue(1).integer_value == entry.integer_value - 1, + StringFormat("Wrong previous value (%d <> %d)!", + in.GetValue(1).integer_value, + entry.integer_value - 1)); + entry.integer_value++; + } + Print(in.ToString()); + // Clean up. + delete in; + */ + return (INIT_SUCCEEDED); +} diff --git a/IndicatorBase.h b/IndicatorBase.h index eed35dcdb..406bf8761 100644 --- a/IndicatorBase.h +++ b/IndicatorBase.h @@ -71,7 +71,6 @@ int IndicatorCounted(int _value = 0) { */ class IndicatorBase : public Chart { protected: - BufferStruct idata; DrawIndicator* draw; IndicatorState istate; void* mydata; @@ -99,11 +98,6 @@ class IndicatorBase : public Chart { /* Special methods */ - /** - * Class constructor. - */ - IndicatorBase() : indi_src(NULL) { is_fed = false; } - /** * Class constructor. */ @@ -112,7 +106,7 @@ class IndicatorBase : public Chart { /** * Class constructor. */ - IndicatorBase(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, string _symbol = NULL) : Chart(_tf, _symbol) { + IndicatorBase(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, string _symbol = NULL) : indi_src(NULL), Chart(_tf, _symbol) { is_fed = false; indi_src = NULL; } @@ -138,6 +132,15 @@ class IndicatorBase : public Chart { } } + /* Operator overloading methods */ + + /** + * Access indicator entry data using [] operator. + */ + // IndicatorDataEntry operator[](datetime _dt) { return GetEntry(_dt); } + IndicatorDataEntry operator[](int _index) { return GetEntry(_index); } + IndicatorDataEntry operator[](ENUM_INDICATOR_INDEX _index) { return GetEntry(_index); } + /* Defines MQL backward compatible methods */ double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, int _mode, int _shift) { @@ -406,15 +409,6 @@ class IndicatorBase : public Chart { */ IndicatorBase* GetDataSourceRaw() { return indi_src; } - /* Operator overloading methods */ - - /** - * Access indicator entry data using [] operator. - */ - IndicatorDataEntry operator[](int _shift) { return GetEntry(_shift); } - IndicatorDataEntry operator[](ENUM_INDICATOR_INDEX _shift) { return GetEntry(_shift); } - IndicatorDataEntry operator[](datetime _dt) { return idata[_dt]; } - /* Getters */ /** @@ -603,11 +597,6 @@ class IndicatorBase : public Chart { */ virtual ENUM_INDICATOR_TYPE GetType() { return INDI_NONE; } - /** - * Get pointer to data of indicator. - */ - BufferStruct* GetData() { return GetPointer(idata); } - /** * Get data type of indicator. */ @@ -665,88 +654,6 @@ class IndicatorBase : public Chart { */ void SetSymbol(string _symbol) { Set(CHART_PARAM_SYMBOL, _symbol); } - /* Conditions */ - - /** - * Checks for indicator condition. - * - * @param ENUM_INDICATOR_CONDITION _cond - * Indicator condition. - * @param MqlParam[] _args - * Condition arguments. - * @return - * Returns true when the condition is met. - */ - bool CheckCondition(ENUM_INDICATOR_CONDITION _cond, DataParamEntry& _args[]) { - switch (_cond) { - case INDI_COND_ENTRY_IS_MAX: - // @todo: Add arguments, check if the entry value is max. - return false; - case INDI_COND_ENTRY_IS_MIN: - // @todo: Add arguments, check if the entry value is min. - return false; - case INDI_COND_ENTRY_GT_AVG: - // @todo: Add arguments, check if... - // Indicator entry value is greater than average. - return false; - case INDI_COND_ENTRY_GT_MED: - // @todo: Add arguments, check if... - // Indicator entry value is greater than median. - return false; - case INDI_COND_ENTRY_LT_AVG: - // @todo: Add arguments, check if... - // Indicator entry value is lesser than average. - return false; - case INDI_COND_ENTRY_LT_MED: - // @todo: Add arguments, check if... - // Indicator entry value is lesser than median. - return false; - default: - GetLogger().Error(StringFormat("Invalid indicator condition: %s!", EnumToString(_cond), __FUNCTION_LINE__)); - return false; - } - } - bool CheckCondition(ENUM_INDICATOR_CONDITION _cond) { - ARRAY(DataParamEntry, _args); - return IndicatorBase::CheckCondition(_cond, _args); - } - - /** - * Execute Indicator action. - * - * @param ENUM_INDICATOR_ACTION _action - * Indicator action to execute. - * @param MqlParam _args - * Indicator action arguments. - * @return - * Returns true when the action has been executed successfully. - */ - virtual bool ExecuteAction(ENUM_INDICATOR_ACTION _action, DataParamEntry& _args[]) { - bool _result = true; - long _arg1 = ArraySize(_args) > 0 ? DataParamEntry::ToInteger(_args[0]) : WRONG_VALUE; - switch (_action) { - case INDI_ACTION_CLEAR_CACHE: - _arg1 = _arg1 > 0 ? _arg1 : TimeCurrent(); - idata.Clear(_arg1); - return true; - default: - GetLogger().Error(StringFormat("Invalid Indicator action: %s!", EnumToString(_action), __FUNCTION_LINE__)); - return false; - } - return _result; - } - bool ExecuteAction(ENUM_INDICATOR_ACTION _action) { - ARRAY(DataParamEntry, _args); - return ExecuteAction(_action, _args); - } - bool ExecuteAction(ENUM_INDICATOR_ACTION _action, long _arg1) { - ARRAY(DataParamEntry, _args); - DataParamEntry _param1 = _arg1; - ArrayPushObject(_args, _param1); - _args[0].integer_value = _arg1; - return ExecuteAction(_action, _args); - } - /* Other methods */ /** @@ -764,82 +671,6 @@ class IndicatorBase : public Chart { istate.is_changed = true; } - /** - * Checks whether indicator has a valid value for a given shift. - */ - virtual bool HasValidEntry(int _shift = 0) { - unsigned int position; - long bar_time = GetBarTime(_shift); - - if (idata.KeyExists(bar_time, position)) { - return idata.GetByPos(position).IsValid(); - } - - return false; - } - - /** - * Adds entry to the indicator's buffer. Invalid entry won't be added. - */ - bool AddEntry(IndicatorDataEntry& entry, int _shift = 0) { - if (!entry.IsValid()) return false; - - datetime timestamp = GetBarTime(_shift); - entry.timestamp = timestamp; - idata.Add(entry, timestamp); - - return true; - } - - /** - * Returns shift at which the last known valid entry exists for a given - * period (or from the start, when period is not specified). - */ - bool GetLastValidEntryShift(int& out_shift, int period = 0) { - out_shift = 0; - - while (true) { - if ((period != 0 && out_shift >= period) || !HasValidEntry(out_shift + 1)) - return out_shift > 0; // Current shift is always invalid. - - ++out_shift; - } - - return out_shift > 0; - } - - /** - * Returns shift at which the oldest known valid entry exists for a given - * period (or from the start, when period is not specified). - */ - bool GetOldestValidEntryShift(int& out_shift, int& out_num_valid, int shift = 0, int period = 0) { - bool found = false; - // Counting from previous up to previous - period. - for (out_shift = shift + 1; out_shift < shift + period + 1; ++out_shift) { - if (!HasValidEntry(out_shift)) { - --out_shift; - out_num_valid = out_shift - shift; - return found; - } else - found = true; - } - - --out_shift; - out_num_valid = out_shift - shift; - return found; - } - - /** - * Checks whether indicator has valid at least given number of last entries - * (counting from given shift or 0). - */ - bool HasAtLeastValidLastEntries(int period, int shift = 0) { - for (int i = 0; i < period; ++i) - if (!HasValidEntry(shift + i)) return false; - - return true; - } - virtual ENUM_IDATA_VALUE_RANGE GetIDataValueRange() = 0; ValueStorage* GetValueStorage(int _mode = 0) { From d829961595f7bf21604c67c30a514ba5dc189d36 Mon Sep 17 00:00:00 2001 From: kenorb Date: Tue, 9 Nov 2021 13:22:57 +0000 Subject: [PATCH 02/77] Indicator: Fixes compilation errors --- Indicator.mqh | 9 +++++++-- IndicatorBase.h | 2 ++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Indicator.mqh b/Indicator.mqh index bbdf08ef6..a995ae56d 100644 --- a/Indicator.mqh +++ b/Indicator.mqh @@ -70,7 +70,7 @@ class Indicator : public IndicatorBase { case IDATA_ICUSTOM: break; case IDATA_INDICATOR: - if (indi_src == NULL) { + if (indi_src.IsSet() == NULL) { // Indi_Price* _indi_price = Indi_Price::GetCached(GetSymbol(), GetTf(), iparams.GetShift()); // SetDataSource(_indi_price, true, PRICE_OPEN); } @@ -789,6 +789,7 @@ class Indicator : public IndicatorBase { * Returns shift at which the last known valid entry exists for a given * period (or from the start, when period is not specified). */ + /* bool GetLastValidEntryShift(int& out_shift, int period = 0) { out_shift = 0; @@ -800,12 +801,13 @@ class Indicator : public IndicatorBase { } return out_shift > 0; - } + }*/ /** * Returns shift at which the oldest known valid entry exists for a given * period (or from the start, when period is not specified). */ + /* bool GetOldestValidEntryShift(int& out_shift, int& out_num_valid, int shift = 0, int period = 0) { bool found = false; // Counting from previous up to previous - period. @@ -822,17 +824,20 @@ class Indicator : public IndicatorBase { out_num_valid = out_shift - shift; return found; } + */ /** * Checks whether indicator has valid at least given number of last entries * (counting from given shift or 0). */ + /* bool HasAtLeastValidLastEntries(int period, int shift = 0) { for (int i = 0; i < period; ++i) if (!HasValidEntry(shift + i)) return false; return true; } + */ ENUM_IDATA_VALUE_RANGE GetIDataValueRange() { return iparams.idvrange; } diff --git a/IndicatorBase.h b/IndicatorBase.h index 7e1753779..c7749d4a6 100644 --- a/IndicatorBase.h +++ b/IndicatorBase.h @@ -818,11 +818,13 @@ class IndicatorBase : public Chart { /** * Checks whether indicator has a valid value for a given shift. */ + /* virtual bool HasValidEntry(int _shift = 0) { unsigned int position; long bar_time = GetBarTime(_shift); return bar_time > 0 && idata.KeyExists(bar_time, position) ? idata.GetByPos(position).IsValid() : false; } + */ /** * Returns stored data in human-readable format. From e8554a1f27d5fcf001c33cfbf1f8d6cfbfcb566d Mon Sep 17 00:00:00 2001 From: kenorb Date: Tue, 9 Nov 2021 14:05:45 +0000 Subject: [PATCH 03/77] IndicatorTick: Fixes compilation errors --- Indicator/IndicatorTick.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Indicator/IndicatorTick.h b/Indicator/IndicatorTick.h index 3fe26bdf9..21352c584 100644 --- a/Indicator/IndicatorTick.h +++ b/Indicator/IndicatorTick.h @@ -79,12 +79,12 @@ class IndicatorTick : public IndicatorBase { if (!_entry.IsValid() && !_entry.CheckFlag(INDI_ENTRY_FLAG_INSUFFICIENT_DATA)) { _entry.timestamp = _timestamp; _entry.Resize(4); - _entry.SetFlag(INDI_ENTRY_FLAG_IS_VALID, IsValidEntry(_entry)); - for (int _mode = 0; _mode < (int)iparams.GetMaxModes(); _mode++) { - //_entry.values[_mode] = GetValue(_mode, _shift); / @todo - } + //_entry.SetFlag(INDI_ENTRY_FLAG_IS_VALID, IsValidEntry(_entry)); + // for (int _mode = 0; _mode < (int)iparams.GetMaxModes(); _mode++) { + //_entry.values[_mode] = GetValue(_mode, _shift); / @todo + //} if (_entry.IsValid()) { - idata.Add(_entry, _bar_time); + // idata.Add(_entry, _bar_time); } else { _entry.AddFlags(INDI_ENTRY_FLAG_INSUFFICIENT_DATA); } From 53310b4889f9fe2f19aa1ee1b5e7c637e9a28a80 Mon Sep 17 00:00:00 2001 From: kenorb Date: Sun, 31 Oct 2021 18:34:18 +0000 Subject: [PATCH 04/77] Indicators: Adds Indi_TickMt --- .github/workflows/test-indicators-tick.yml | 65 ++++++++++++++++++ Indicator.enum.h | 5 +- Indicators/Tick/Indi_TickMt.mqh | 76 ++++++++++++++++++++++ Indicators/Tick/tests/Indi_TickMt.test.mq4 | 27 ++++++++ Indicators/Tick/tests/Indi_TickMt.test.mq5 | 60 +++++++++++++++++ 5 files changed, 231 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/test-indicators-tick.yml create mode 100644 Indicators/Tick/Indi_TickMt.mqh create mode 100644 Indicators/Tick/tests/Indi_TickMt.test.mq4 create mode 100644 Indicators/Tick/tests/Indi_TickMt.test.mq5 diff --git a/.github/workflows/test-indicators-tick.yml b/.github/workflows/test-indicators-tick.yml new file mode 100644 index 000000000..25eabe43c --- /dev/null +++ b/.github/workflows/test-indicators-tick.yml @@ -0,0 +1,65 @@ +--- +name: Test Indicators (Tick) + +# yamllint disable-line rule:truthy +on: + pull_request: + paths: + - 'Indicator**' + - 'Indicators/Tick/**' + - '.github/workflows/test-indicators-tick.yml' + push: + paths: + - 'Indicator**' + - 'Indicators/Tick/**' + - '.github/workflows/test-indicators-tick.yml' + +jobs: + + Compile: + runs-on: windows-latest + steps: + - uses: actions/checkout@v2 + - name: Compile + uses: fx31337/mql-compile-action@master + with: + init-platform: true + path: 'Indicators/Tick/tests' + verbose: true + - name: Print compiled files + run: '(Get-ChildItem -Recurse -Path . -Include *.ex[45]).fullname' + shell: powershell + - name: Upload artifacts (MQL4) + uses: actions/upload-artifact@v2 + with: + name: files-ex4 + path: '**/*.ex4' + - name: Upload artifacts (MQL5) + uses: actions/upload-artifact@v2 + with: + name: files-ex5 + path: '**/*.ex5' + + Indicators-Tests-MQL4: + defaults: + run: + shell: bash + working-directory: Indicators/tests + needs: Compile + runs-on: ubuntu-latest + strategy: + matrix: + test: + - Indi_Tick.test + steps: + - uses: actions/download-artifact@v2 + with: + name: files-ex4 + - name: Run ${{ matrix.test }} + uses: fx31337/mql-tester-action@master + with: + BtDays: 4-8 + BtMonths: 1 + BtYears: 2020 + TestExpert: ${{ matrix.test }} + timeout-minutes: 10 diff --git a/Indicator.enum.h b/Indicator.enum.h index 884f705a4..375064b34 100644 --- a/Indicator.enum.h +++ b/Indicator.enum.h @@ -96,7 +96,7 @@ enum ENUM_INDICATOR_TYPE { INDI_OSMA, // OsMA INDI_PATTERN, // Pattern Detector INDI_PIVOT, // Pivot Detector - INDI_PRICE, // Price Indicator + INDI_PRICE, // Price INDI_PRICE_CHANNEL, // Price Channel INDI_PRICE_FEEDER, // Indicator which returns prices from custom array INDI_PRICE_VOLUME_TREND, // Price and Volume Trend @@ -114,7 +114,8 @@ enum ENUM_INDICATOR_TYPE { INDI_STOCHASTIC, // Stochastic Oscillator INDI_SVE_BB, // SVE Bollinger Bands INDI_TEMA, // Triple Exponential Moving Average - INDI_TMA_TRUE, /// Triangular Moving Average True + INDI_TICK, // Tick + INDI_TMA_TRUE, // Triangular Moving Average True INDI_TRIX, // Triple Exponential Moving Averages Oscillator INDI_ULTIMATE_OSCILLATOR, // Ultimate Oscillator INDI_VIDYA, // Variable Index Dynamic Average diff --git a/Indicators/Tick/Indi_TickMt.mqh b/Indicators/Tick/Indi_TickMt.mqh new file mode 100644 index 000000000..3bb9ee092 --- /dev/null +++ b/Indicators/Tick/Indi_TickMt.mqh @@ -0,0 +1,76 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2021, EA31337 Ltd | +//| https://github.com/EA31337 | +//+------------------------------------------------------------------+ + +/* + * This file is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +// Includes. +#include "../../BufferStruct.mqh" +#include "../../Indicator.mqh" +#include "../../Storage/Objects.h" + +// Structs. +struct IndiTickMtParams : IndicatorParams { + string symbol; + // Struct constructor. + IndiTickMtParams(string _symbol = NULL, int _shift = 0) : IndicatorParams(INDI_TICK, 3, TYPE_DOUBLE) { + SetShift(_shift); + }; + IndiTickMtParams(IndiTickMtParams &_params, ENUM_TIMEFRAMES _tf) { + THIS_REF = _params; + tf = _tf; + }; + // Getters. + string GetSymbol() { return symbol; } + // Setters. + void SetSymbol(string _symbol) { symbol = _symbol; } +}; + +/** + * Price Indicator. + */ +class Indi_TickMt : public Indicator { + public: + /** + * Class constructor. + */ + Indi_TickMt(IndiTickMtParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; + Indi_TickMt(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_TICK, _tf, _shift){}; + + /** + * Returns the indicator's value. + */ + virtual double GetValue(int _mode = 0, int _shift = 0) { + MqlTick _tick = SymbolInfoStatic::GetTick(_Symbol); + switch (_mode) { + case 0: + return _tick.ask; + case 1: + return _tick.bid; + case 2: +#ifdef __MQL4__ + return _tick.volume; +#else + return _tick.volume_real; +#endif + } + SetUserError(ERR_INVALID_PARAMETER); + return DBL_MAX; + } +}; diff --git a/Indicators/Tick/tests/Indi_TickMt.test.mq4 b/Indicators/Tick/tests/Indi_TickMt.test.mq4 new file mode 100644 index 000000000..091a1ba01 --- /dev/null +++ b/Indicators/Tick/tests/Indi_TickMt.test.mq4 @@ -0,0 +1,27 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2021, EA31337 Ltd | +//| https://github.com/EA31337 | +//+------------------------------------------------------------------+ + +/* + * This file is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * @file + * Test functionality of Indi_Tick indicator class. + */ + +#include "Indi_TickMt.test.mq5" diff --git a/Indicators/Tick/tests/Indi_TickMt.test.mq5 b/Indicators/Tick/tests/Indi_TickMt.test.mq5 new file mode 100644 index 000000000..4c9572767 --- /dev/null +++ b/Indicators/Tick/tests/Indi_TickMt.test.mq5 @@ -0,0 +1,60 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2021, EA31337 Ltd | +//| https://github.com/EA31337 | +//+------------------------------------------------------------------+ + +/* + * This file is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +// Includes. +#include "../../../Test.mqh" +#include "../Indi_TickMt.mqh" + +/** + * @file + * Test functionality of Indi_TickMt indicator class. + */ + +Indi_TickMt indi(PERIOD_CURRENT); + +/** + * Implements Init event handler. + */ +int OnInit() { + bool _result = true; + assertTrueOrFail(indi.IsValid(), "Error on IsValid!"); + // assertTrueOrFail(indi.IsValidEntry(), "Error on IsValidEntry!"); + return (_result && _LastError == ERR_NO_ERROR ? INIT_SUCCEEDED : INIT_FAILED); +} + +/** + * Implements Tick event handler. + */ +void OnTick() { + static MqlTick _tick_last; + MqlTick _tick_new = SymbolInfoStatic::GetTick(_Symbol); + if (_tick_new.time % 60 < _tick_last.time % 60) { + // Process ticks each minute. + if (_tick_new.time % 3600 < _tick_last.time % 3600) { + // Print indicator values every hour. + Print(indi.ToString()); + if (indi.Get(STRUCT_ENUM(IndicatorState, INDICATOR_STATE_PROP_IS_READY))) { + assertTrueOrExit(indi.GetEntry().IsValid(), "Invalid entry!"); + } + } + } + _tick_last = _tick_new; +} From ad83367eb465821b3bdc8f033d3993611f8e023d Mon Sep 17 00:00:00 2001 From: kenorb Date: Tue, 9 Nov 2021 15:32:38 +0000 Subject: [PATCH 05/77] Tick/Indi_TickMt: Renames GetValue() to GetMixedValue() --- Indicators/Tick/Indi_TickMt.mqh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Indicators/Tick/Indi_TickMt.mqh b/Indicators/Tick/Indi_TickMt.mqh index 3bb9ee092..46e5a44c6 100644 --- a/Indicators/Tick/Indi_TickMt.mqh +++ b/Indicators/Tick/Indi_TickMt.mqh @@ -56,7 +56,7 @@ class Indi_TickMt : public Indicator { /** * Returns the indicator's value. */ - virtual double GetValue(int _mode = 0, int _shift = 0) { + IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { MqlTick _tick = SymbolInfoStatic::GetTick(_Symbol); switch (_mode) { case 0: From 28ff4d40f41123cf20f905b3a977bba20358d68c Mon Sep 17 00:00:00 2001 From: kenorb Date: Tue, 9 Nov 2021 19:42:46 +0000 Subject: [PATCH 06/77] IndicatorTick: Implements tick fetching logic --- Indicator.mqh | 30 ++- Indicator/IndicatorTick.h | 207 ++++++++++++++++++--- IndicatorBase.h | 32 +--- Indicators/Tick/Indi_TickMt.mqh | 47 +++-- Indicators/Tick/tests/Indi_TickMt.test.mq5 | 5 +- Strategy.mqh | 3 +- 6 files changed, 242 insertions(+), 82 deletions(-) diff --git a/Indicator.mqh b/Indicator.mqh index 94df3212e..c7def0976 100644 --- a/Indicator.mqh +++ b/Indicator.mqh @@ -519,6 +519,34 @@ class Indicator : public IndicatorBase { return median; } + /** + * Returns price corresponding to indicator value for a given shift and mode. + * + * Can be useful for calculating trailing stops based on the indicator. + * + * @return + * Returns price value of the corresponding indicator values. + */ + template + float GetValuePrice(int _shift = 0, int _mode = 0, ENUM_APPLIED_PRICE _ap = PRICE_TYPICAL) { + float _price = 0; + if (GetIDataValueRange() != IDATA_RANGE_PRICE) { + _price = (float)GetPrice(_ap, _shift); + } else if (GetIDataValueRange() == IDATA_RANGE_PRICE) { + // When indicator values are the actual prices. + T _values[4]; + if (!CopyValues(_values, 4, _shift, _mode)) { + // When values aren't valid, return 0. + return _price; + } + datetime _bar_time = GetBarTime(_shift); + float _value = 0; + BarOHLC _ohlc(_values, _bar_time); + _price = _ohlc.GetAppliedPrice(_ap); + } + return _price; + } + /** * Returns currently selected data source doing validation. */ @@ -839,7 +867,7 @@ class Indicator : public IndicatorBase { } */ - ENUM_IDATA_VALUE_RANGE GetIDataValueRange() { return iparams.idvrange; } + // ENUM_IDATA_VALUE_RANGE GetIDataValueRange() { return iparams.idvrange; } virtual void OnTick() { Chart::OnTick(); diff --git a/Indicator/IndicatorTick.h b/Indicator/IndicatorTick.h index 21352c584..8f54219a9 100644 --- a/Indicator/IndicatorTick.h +++ b/Indicator/IndicatorTick.h @@ -26,35 +26,28 @@ // Includes. #include "../IndicatorBase.h" -//#include "Array.mqh" -//#include "BufferStruct.mqh" -//#include "Chart.mqh" -//#include "DateTime.mqh" -//#include "DrawIndicator.mqh" -//#include "Indicator.define.h" -//#include "Indicator.enum.h" -//#include "Indicator.struct.cache.h" -//#include "Indicator.struct.h" -//#include "Indicator.struct.serialize.h" -//#include "Indicator.struct.signal.h" -//#include "IndicatorBase.h" -//#include "Math.h" -//#include "Object.mqh" -//#include "Refs.mqh" -//#include "Serializer.mqh" -//#include "SerializerCsv.mqh" -//#include "SerializerJson.mqh" -//#include "Storage/ValueStorage.h" -//#include "Storage/ValueStorage.indicator.h" -//#include "Storage/ValueStorage.native.h" /** * Class to deal with tick indicators. */ -// template +template class IndicatorTick : public IndicatorBase { protected: - BufferStruct tickdata; + BufferStruct itdata; + TS itparams; + + protected: + /* Protected methods */ + + /** + * Initialize class. + * + * Called on constructor. + */ + void Init() { + itdata.AddFlags(DICT_FLAG_FILL_HOLES_UNSORTED); + itdata.SetOverflowListener(IndicatorTickOverflowListener, 10); + } public: /* Special methods */ @@ -62,7 +55,18 @@ class IndicatorTick : public IndicatorBase { /** * Class constructor. */ - IndicatorTick() {} + IndicatorTick(const TS& _itparams, IndicatorBase* _indi_src = NULL, int _indi_mode = 0) { + itparams = _itparams; + if (_indi_src != NULL) { + SetDataSource(_indi_src, _indi_mode); + } + Init(); + } + IndicatorTick(ENUM_INDICATOR_TYPE _itype, string _symbol, int _shift = 0, string _name = "") { + itparams.SetIndicatorType(_itype); + itparams.SetShift(_shift); + Init(); + } /* Virtual method implementations */ @@ -75,22 +79,163 @@ class IndicatorTick : public IndicatorBase { * Returns IndicatorDataEntry struct filled with indicator values. */ IndicatorDataEntry GetEntry(int _timestamp = 0) { - IndicatorDataEntry _entry = tickdata.GetByKey(_timestamp); + ResetLastError(); + IndicatorDataEntry _entry = itdata.GetByKey(_timestamp); if (!_entry.IsValid() && !_entry.CheckFlag(INDI_ENTRY_FLAG_INSUFFICIENT_DATA)) { + _entry.Resize(itparams.GetMaxModes()); _entry.timestamp = _timestamp; - _entry.Resize(4); - //_entry.SetFlag(INDI_ENTRY_FLAG_IS_VALID, IsValidEntry(_entry)); - // for (int _mode = 0; _mode < (int)iparams.GetMaxModes(); _mode++) { - //_entry.values[_mode] = GetValue(_mode, _shift); / @todo - //} + for (int _mode = 0; _mode < (int)itparams.GetMaxModes(); _mode++) { + switch (itparams.GetDataValueType()) { + case TYPE_BOOL: + case TYPE_CHAR: + case TYPE_INT: + _entry.values[_mode] = GetValue(_mode, _timestamp); + break; + case TYPE_LONG: + _entry.values[_mode] = GetValue(_mode, _timestamp); + break; + case TYPE_UINT: + _entry.values[_mode] = GetValue(_mode, _timestamp); + break; + case TYPE_ULONG: + _entry.values[_mode] = GetValue(_mode, _timestamp); + break; + case TYPE_DOUBLE: + _entry.values[_mode] = GetValue(_mode, _timestamp); + break; + case TYPE_FLOAT: + _entry.values[_mode] = GetValue(_mode, _timestamp); + break; + case TYPE_STRING: + case TYPE_UCHAR: + default: + SetUserError(ERR_INVALID_PARAMETER); + break; + } + } + GetEntryAlter(_entry, _timestamp); + _entry.SetFlag(INDI_ENTRY_FLAG_IS_VALID, IsValidEntry(_entry)); if (_entry.IsValid()) { - // idata.Add(_entry, _bar_time); + itdata.Add(_entry, _timestamp); + istate.is_changed = false; + istate.is_ready = true; } else { _entry.AddFlags(INDI_ENTRY_FLAG_INSUFFICIENT_DATA); } } + if (_LastError != ERR_NO_ERROR) { + istate.is_ready = false; + ResetLastError(); + } return _entry; } + + /** + * Alters indicator's struct value. + * + * This method allows user to modify the struct entry before it's added to cache. + * This method is called on GetEntry() right after values are set. + */ + virtual void GetEntryAlter(IndicatorDataEntry& _entry, int _shift = -1) { + _entry.AddFlags(_entry.GetDataTypeFlags(itparams.GetDataValueType())); + }; + + /** + * Returns the indicator's entry value for the given shift and mode. + * + * @see: DataParamEntry. + * + * @return + * Returns DataParamEntry struct filled with a single value. + */ + virtual DataParamEntry GetEntryValue(int _shift = -1, int _mode = 0) { + IndicatorDataEntry _entry = GetEntry(_shift >= 0 ? _shift : itparams.GetShift()); + DataParamEntry _value_entry; + return _value_entry; + } + + /** + * Function should return true if resize can be made, or false to overwrite current slot. + */ + static bool IndicatorTickOverflowListener(ENUM_DICT_OVERFLOW_REASON _reason, int _size, int _num_conflicts) { + switch (_reason) { + case DICT_OVERFLOW_REASON_FULL: + // We allow resize if dictionary size is less than 86400 slots. + return _size < 86400; + case DICT_OVERFLOW_REASON_TOO_MANY_CONFLICTS: + default: + // When there is too many conflicts, we just reject doing resize, so first conflicting slot will be reused. + break; + } + return false; + } + + /** + * Sets indicator data source. + */ + void SetDataSource(IndicatorBase* _indi, int _input_mode = 0) { + indi_src = _indi; + itparams.SetDataSource(-1, _input_mode); + } + + /* Virtual methods */ + + /** + * Returns a tick struct with price values. + * + * @see: MqlTick. + * + * @return + * Returns MqlTick struct with prices of the symbol. + */ + virtual MqlTick GetTick(int _timestamp = 0) { + IndicatorDataEntry _entry = GetEntry(_timestamp); + MqlTick _tick; + _tick.time = (datetime)_entry.GetTime(); + _tick.bid = _entry[0]; + _tick.ask = _entry[1]; + return _tick; + } + + /** + * Checks if indicator entry is valid. + * + * @return + * Returns true if entry is valid (has valid values), otherwise false. + */ + virtual bool IsValidEntry(IndicatorDataEntry& _entry) { + bool _result = true; + _result &= _entry.timestamp > 0; + _result &= _entry.GetSize() > 0; + if (_entry.CheckFlags(INDI_ENTRY_FLAG_IS_REAL)) { + if (_entry.CheckFlags(INDI_ENTRY_FLAG_IS_DOUBLED)) { + _result &= !_entry.HasValue(DBL_MAX); + _result &= !_entry.HasValue(NULL); + } else { + _result &= !_entry.HasValue(FLT_MAX); + _result &= !_entry.HasValue(NULL); + } + } else { + if (_entry.CheckFlags(INDI_ENTRY_FLAG_IS_UNSIGNED)) { + if (_entry.CheckFlags(INDI_ENTRY_FLAG_IS_DOUBLED)) { + _result &= !_entry.HasValue(ULONG_MAX); + _result &= !_entry.HasValue(NULL); + } else { + _result &= !_entry.HasValue(UINT_MAX); + _result &= !_entry.HasValue(NULL); + } + } else { + if (_entry.CheckFlags(INDI_ENTRY_FLAG_IS_DOUBLED)) { + _result &= !_entry.HasValue(LONG_MAX); + _result &= !_entry.HasValue(NULL); + } else { + _result &= !_entry.HasValue(INT_MAX); + _result &= !_entry.HasValue(NULL); + } + } + } + return _result; + } }; #endif diff --git a/IndicatorBase.h b/IndicatorBase.h index ae3059e16..61f26a2a8 100644 --- a/IndicatorBase.h +++ b/IndicatorBase.h @@ -695,8 +695,6 @@ class IndicatorBase : public Chart { istate.is_changed = true; } - virtual ENUM_IDATA_VALUE_RANGE GetIDataValueRange() = 0; - ValueStorage* GetValueStorage(int _mode = 0) { if (value_storages[_mode] == NULL) { value_storages[_mode] = new IndicatorBufferValueStorage(THIS_PTR, _mode); @@ -713,34 +711,6 @@ class IndicatorBase : public Chart { virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) = NULL; - /** - * Returns price corresponding to indicator value for a given shift and mode. - * - * Can be useful for calculating trailing stops based on the indicator. - * - * @return - * Returns price value of the corresponding indicator values. - */ - template - float GetValuePrice(int _shift = 0, int _mode = 0, ENUM_APPLIED_PRICE _ap = PRICE_TYPICAL) { - float _price = 0; - if (GetIDataValueRange() != IDATA_RANGE_PRICE) { - _price = (float)GetPrice(_ap, _shift); - } else if (GetIDataValueRange() == IDATA_RANGE_PRICE) { - // When indicator values are the actual prices. - T _values[4]; - if (!CopyValues(_values, 4, _shift, _mode)) { - // When values aren't valid, return 0. - return _price; - } - datetime _bar_time = GetBarTime(_shift); - float _value = 0; - BarOHLC _ohlc(_values, _bar_time); - _price = _ohlc.GetAppliedPrice(_ap); - } - return _price; - } - /** * Returns values for a given shift. * @@ -798,6 +768,8 @@ class IndicatorBase : public Chart { */ virtual void GetEntryAlter(IndicatorDataEntry& _entry, int _shift = -1) = NULL; + // virtual ENUM_IDATA_VALUE_RANGE GetIDataValueRange() = NULL; + /** * Returns the indicator's entry value. */ diff --git a/Indicators/Tick/Indi_TickMt.mqh b/Indicators/Tick/Indi_TickMt.mqh index 46e5a44c6..ced489df0 100644 --- a/Indicators/Tick/Indi_TickMt.mqh +++ b/Indicators/Tick/Indi_TickMt.mqh @@ -21,9 +21,7 @@ */ // Includes. -#include "../../BufferStruct.mqh" -#include "../../Indicator.mqh" -#include "../../Storage/Objects.h" +#include "../../Indicator/IndicatorTick.h" // Structs. struct IndiTickMtParams : IndicatorParams { @@ -45,32 +43,49 @@ struct IndiTickMtParams : IndicatorParams { /** * Price Indicator. */ -class Indi_TickMt : public Indicator { +class Indi_TickMt : public IndicatorTick { + protected: + MqlTick tick; + public: /** * Class constructor. */ - Indi_TickMt(IndiTickMtParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_TickMt(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_TICK, _tf, _shift){}; + Indi_TickMt(IndiTickMtParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTick(_p, _indi_src){}; + Indi_TickMt(string _symbol, int _shift = 0) : IndicatorTick(INDI_TICK, _symbol, _shift){}; /** * Returns the indicator's value. */ IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { - MqlTick _tick = SymbolInfoStatic::GetTick(_Symbol); - switch (_mode) { - case 0: - return _tick.ask; - case 1: - return _tick.bid; - case 2: + if (_shift == 0) { + // Fetch a current prices of a specified symbol. + tick = SymbolInfoStatic::GetTick(itparams.GetSymbol()); + switch (_mode) { + case 0: + return tick.ask; + case 1: + return tick.bid; + case 2: #ifdef __MQL4__ - return _tick.volume; + return tick.volume; #else - return _tick.volume_real; + return tick.volume_real; #endif + } + SetUserError(ERR_INVALID_PARAMETER); } - SetUserError(ERR_INVALID_PARAMETER); return DBL_MAX; } + + /** + * Alters indicator's struct value. + * + * This method allows user to modify the struct entry before it's added to cache. + * This method is called on GetEntry() right after values are set. + */ + virtual void GetEntryAlter(IndicatorDataEntry &_entry, int _shift = -1) { + IndicatorTick::GetEntryAlter(_entry, _shift); + _entry.timestamp = _entry.timestamp > 0 ? _entry.timestamp : tick.time; + }; }; diff --git a/Indicators/Tick/tests/Indi_TickMt.test.mq5 b/Indicators/Tick/tests/Indi_TickMt.test.mq5 index 4c9572767..428552d78 100644 --- a/Indicators/Tick/tests/Indi_TickMt.test.mq5 +++ b/Indicators/Tick/tests/Indi_TickMt.test.mq5 @@ -28,7 +28,7 @@ * Test functionality of Indi_TickMt indicator class. */ -Indi_TickMt indi(PERIOD_CURRENT); +Indi_TickMt indi(_Symbol); /** * Implements Init event handler. @@ -36,7 +36,6 @@ Indi_TickMt indi(PERIOD_CURRENT); int OnInit() { bool _result = true; assertTrueOrFail(indi.IsValid(), "Error on IsValid!"); - // assertTrueOrFail(indi.IsValidEntry(), "Error on IsValidEntry!"); return (_result && _LastError == ERR_NO_ERROR ? INIT_SUCCEEDED : INIT_FAILED); } @@ -45,7 +44,7 @@ int OnInit() { */ void OnTick() { static MqlTick _tick_last; - MqlTick _tick_new = SymbolInfoStatic::GetTick(_Symbol); + MqlTick _tick_new = indi.GetTick(); if (_tick_new.time % 60 < _tick_last.time % 60) { // Process ticks each minute. if (_tick_new.time % 3600 < _tick_last.time % 3600) { diff --git a/Strategy.mqh b/Strategy.mqh index 50fe5c66c..a062b368d 100644 --- a/Strategy.mqh +++ b/Strategy.mqh @@ -1207,7 +1207,8 @@ class Strategy : public Object { _psm.SetChartParams(_chart.GetParams()); if (Object::IsValid(_indi)) { int _ishift = 12; // @todo: Make it dynamic or as variable. - float _value = _indi.GetValuePrice(_ishift, 0, _direction > 0 ? PRICE_HIGH : PRICE_LOW); + float _value = 0.0f; // @todo + //float _value = _indi.GetValuePrice(_ishift, 0, _direction > 0 ? PRICE_HIGH : PRICE_LOW); _value = _value + (float)Math::ChangeByPct(fabs(_value - _chart.GetCloseOffer(0)), _level) * _direction; _psm.SetIndicatorPriceValue(_value); /* From 565e493fb9b3c5e8a8cee42f30d9a6882d883504 Mon Sep 17 00:00:00 2001 From: kenorb Date: Mon, 8 Nov 2021 14:11:23 +0000 Subject: [PATCH 07/77] Indicator: Renames GetMixedValue to GetEntryValue --- Indicator.mqh | 6 ++++-- IndicatorBase.h | 6 ++---- Indicators/Bitwise/Indi_Candle.mqh | 13 +++++++------ Indicators/Bitwise/Indi_Pattern.mqh | 13 +++++++------ Indicators/Indi_AC.mqh | 7 ++++--- Indicators/Indi_AD.mqh | 7 ++++--- Indicators/Indi_ADX.mqh | 8 +++++--- Indicators/Indi_ADXW.mqh | 7 ++++--- Indicators/Indi_AMA.mqh | 7 ++++--- Indicators/Indi_AO.mqh | 7 ++++--- Indicators/Indi_ASI.mqh | 7 ++++--- Indicators/Indi_ATR.mqh | 7 ++++--- Indicators/Indi_Alligator.mqh | 11 ++++++----- Indicators/Indi_AppliedPrice.mqh | 5 +++-- Indicators/Indi_BWMFI.mqh | 7 ++++--- Indicators/Indi_BWZT.mqh | 7 ++++--- Indicators/Indi_Bands.mqh | 9 +++++---- Indicators/Indi_BearsPower.mqh | 7 ++++--- Indicators/Indi_BullsPower.mqh | 7 ++++--- Indicators/Indi_CCI.mqh | 11 ++++++----- Indicators/Indi_CHO.mqh | 7 ++++--- Indicators/Indi_CHV.mqh | 7 ++++--- Indicators/Indi_ColorBars.mqh | 7 ++++--- Indicators/Indi_ColorCandlesDaily.mqh | 7 ++++--- Indicators/Indi_ColorLine.mqh | 7 ++++--- Indicators/Indi_CustomMovingAverage.mqh | 5 +++-- Indicators/Indi_DEMA.mqh | 9 +++++---- Indicators/Indi_DeMarker.mqh | 7 ++++--- Indicators/Indi_Demo.mqh | 7 ++++--- Indicators/Indi_DetrendedPrice.mqh | 7 ++++--- Indicators/Indi_Drawer.mqh | 7 ++++--- Indicators/Indi_Envelopes.mqh | 10 ++++++---- Indicators/Indi_Force.mqh | 7 ++++--- Indicators/Indi_FractalAdaptiveMA.mqh | 7 ++++--- Indicators/Indi_Fractals.mqh | 7 ++++--- Indicators/Indi_Gator.mqh | 7 ++++--- Indicators/Indi_HeikenAshi.mqh | 9 +++++---- Indicators/Indi_Ichimoku.mqh | 11 ++++++----- Indicators/Indi_Killzones.mqh | 5 +++-- Indicators/Indi_MA.mqh | 11 ++++++----- Indicators/Indi_MACD.mqh | 7 ++++--- Indicators/Indi_MFI.mqh | 9 +++++---- Indicators/Indi_MassIndex.mqh | 8 +++++--- Indicators/Indi_Momentum.mqh | 7 ++++--- Indicators/Indi_OBV.mqh | 9 +++++---- Indicators/Indi_OsMA.mqh | 7 ++++--- Indicators/Indi_Pivot.mqh | 5 ++++- Indicators/Indi_PriceChannel.mqh | 10 ++++------ Indicators/Indi_PriceFeeder.mqh | 7 ++++--- Indicators/Indi_PriceVolumeTrend.mqh | 7 ++++--- Indicators/Indi_RS.mqh | 5 +++-- Indicators/Indi_RSI.mqh | 10 ++++++---- Indicators/Indi_RVI.mqh | 7 ++++--- Indicators/Indi_RateOfChange.mqh | 7 ++++--- Indicators/Indi_SAR.mqh | 7 ++++--- Indicators/Indi_StdDev.mqh | 9 +++++---- Indicators/Indi_Stochastic.mqh | 7 ++++--- Indicators/Indi_TEMA.mqh | 7 ++++--- Indicators/Indi_TRIX.mqh | 9 +++++---- Indicators/Indi_UltimateOscillator.mqh | 7 ++++--- Indicators/Indi_VIDYA.mqh | 7 ++++--- Indicators/Indi_VROC.mqh | 7 ++++--- Indicators/Indi_Volumes.mqh | 7 ++++--- Indicators/Indi_WPR.mqh | 7 ++++--- Indicators/Indi_WilliamsAD.mqh | 7 ++++--- Indicators/Indi_ZigZag.mqh | 7 ++++--- Indicators/Indi_ZigZagColor.mqh | 11 +++++------ Indicators/OHLC/Indi_OHLC.mqh | 5 +++-- Indicators/Price/Indi_Price.mqh | 5 +++-- Indicators/Special/Indi_Math.mqh | 7 ++++--- Indicators/Tick/Indi_TickMt.mqh | 2 +- tests/DrawIndicatorTest.mq5 | 7 +------ tests/IndicatorsTest.mq5 | 2 +- 73 files changed, 303 insertions(+), 239 deletions(-) diff --git a/Indicator.mqh b/Indicator.mqh index c7def0976..42955d2a9 100644 --- a/Indicator.mqh +++ b/Indicator.mqh @@ -1022,8 +1022,9 @@ class Indicator : public IndicatorBase { * @return * Returns DataParamEntry struct filled with a single value. */ - virtual DataParamEntry GetEntryValue(int _shift = -1, int _mode = 0) { - IndicatorDataEntry _entry = GetEntry(_shift >= 0 ? _shift : iparams.GetShift()); + /* + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + IndicatorDataEntry _entry = GetEntry(fmax(_shift, _shift >= 0 ? _shift : iparams.GetShift())); DataParamEntry _value_entry; switch (iparams.GetDataValueType()) { case TYPE_BOOL: @@ -1054,6 +1055,7 @@ class Indicator : public IndicatorBase { } return _value_entry; } + */ /** * Returns the indicator's value. diff --git a/IndicatorBase.h b/IndicatorBase.h index 61f26a2a8..d581a28b4 100644 --- a/IndicatorBase.h +++ b/IndicatorBase.h @@ -705,12 +705,10 @@ class IndicatorBase : public Chart { template T GetValue(int _shift = 0, int _mode = 0) { T _out; - GetMixedValue(_shift, _mode).Get(_out); + GetEntryValue(_shift, _mode).Get(_out); return _out; } - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) = NULL; - /** * Returns values for a given shift. * @@ -773,7 +771,7 @@ class IndicatorBase : public Chart { /** * Returns the indicator's entry value. */ - virtual DataParamEntry GetEntryValue(int _shift = -1, int _mode = 0) = NULL; + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) = NULL; /** * Returns indicator value for a given shift and mode. diff --git a/Indicators/Bitwise/Indi_Candle.mqh b/Indicators/Bitwise/Indi_Candle.mqh index 0ff594c0d..a9b94aea1 100644 --- a/Indicators/Bitwise/Indi_Candle.mqh +++ b/Indicators/Bitwise/Indi_Candle.mqh @@ -66,14 +66,15 @@ class Indi_Candle : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); BarOHLC _ohlcs[1]; switch (iparams.idstype) { case IDATA_BUILTIN: // In this mode, price is fetched from chart. - _ohlcs[0] = Chart::GetOHLC(_shift); + _ohlcs[0] = Chart::GetOHLC(_ishift); break; case IDATA_INDICATOR: // In this mode, price is fetched from given indicator. Such indicator @@ -92,10 +93,10 @@ class Indi_Candle : public Indicator { break; } - _ohlcs[0].open = GetDataSource().GetValue(_shift, PRICE_OPEN); - _ohlcs[0].high = GetDataSource().GetValue(_shift, PRICE_HIGH); - _ohlcs[0].low = GetDataSource().GetValue(_shift, PRICE_LOW); - _ohlcs[0].close = GetDataSource().GetValue(_shift, PRICE_CLOSE); + _ohlcs[0].open = GetDataSource().GetValue(_ishift, PRICE_OPEN); + _ohlcs[0].high = GetDataSource().GetValue(_ishift, PRICE_HIGH); + _ohlcs[0].low = GetDataSource().GetValue(_ishift, PRICE_LOW); + _ohlcs[0].close = GetDataSource().GetValue(_ishift, PRICE_CLOSE); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Bitwise/Indi_Pattern.mqh b/Indicators/Bitwise/Indi_Pattern.mqh index ed0d71f6d..f9e014ec0 100644 --- a/Indicators/Bitwise/Indi_Pattern.mqh +++ b/Indicators/Bitwise/Indi_Pattern.mqh @@ -57,15 +57,16 @@ class Indi_Pattern : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { int i; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); BarOHLC _ohlcs[8]; switch (iparams.idstype) { case IDATA_BUILTIN: // In this mode, price is fetched from chart. for (i = 0; i < iparams.GetMaxModes(); ++i) { - _ohlcs[i] = Chart::GetOHLC(_shift + i); + _ohlcs[i] = Chart::GetOHLC(_ishift + i); if (!_ohlcs[i].IsValid()) { // Return empty entry on invalid candles. return WRONG_VALUE; @@ -90,10 +91,10 @@ class Indi_Pattern : public Indicator { } for (i = 0; i < iparams.GetMaxModes(); ++i) { - _ohlcs[i].open = GetDataSource().GetValue(_shift + i, PRICE_OPEN); - _ohlcs[i].high = GetDataSource().GetValue(_shift + i, PRICE_HIGH); - _ohlcs[i].low = GetDataSource().GetValue(_shift + i, PRICE_LOW); - _ohlcs[i].close = GetDataSource().GetValue(_shift + i, PRICE_CLOSE); + _ohlcs[i].open = GetDataSource().GetValue(_ishift + i, PRICE_OPEN); + _ohlcs[i].high = GetDataSource().GetValue(_ishift + i, PRICE_HIGH); + _ohlcs[i].low = GetDataSource().GetValue(_ishift + i, PRICE_LOW); + _ohlcs[i].close = GetDataSource().GetValue(_ishift + i, PRICE_CLOSE); if (!_ohlcs[i].IsValid()) { // Return empty entry on invalid candles. return WRONG_VALUE; diff --git a/Indicators/Indi_AC.mqh b/Indicators/Indi_AC.mqh index 5e9fb260e..be9fe709b 100644 --- a/Indicators/Indi_AC.mqh +++ b/Indicators/Indi_AC.mqh @@ -100,15 +100,16 @@ class Indi_AC : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { IndicatorDataEntryValue _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; - _value = Indi_AC::iAC(GetSymbol(), GetTf(), _shift, THIS_PTR); + _value = Indi_AC::iAC(GetSymbol(), GetTf(), _ishift, THIS_PTR); break; case IDATA_ICUSTOM: - _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), _mode, _shift); + _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), _mode, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_AD.mqh b/Indicators/Indi_AD.mqh index e2fcf2d5e..51ea677cf 100644 --- a/Indicators/Indi_AD.mqh +++ b/Indicators/Indi_AD.mqh @@ -101,15 +101,16 @@ class Indi_AD : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; - _value = Indi_AD::iAD(GetSymbol(), GetTf(), _shift, THIS_PTR); + _value = Indi_AD::iAD(GetSymbol(), GetTf(), _ishift, THIS_PTR); break; case IDATA_ICUSTOM: - _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), _mode, _shift); + _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), _mode, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_ADX.mqh b/Indicators/Indi_ADX.mqh index a403d961d..752805800 100644 --- a/Indicators/Indi_ADX.mqh +++ b/Indicators/Indi_ADX.mqh @@ -115,19 +115,21 @@ class Indi_ADX : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = LINE_MAIN_ADX, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = LINE_MAIN_ADX, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; - _value = Indi_ADX::iADX(GetSymbol(), GetTf(), GetPeriod(), GetAppliedPrice(), _mode, _shift, THIS_PTR); + _value = Indi_ADX::iADX(GetSymbol(), GetTf(), GetPeriod(), GetAppliedPrice(), _mode, _ishift, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod() /*]*/, - _mode, _shift); + _mode, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); + break; } return _value; } diff --git a/Indicators/Indi_ADXW.mqh b/Indicators/Indi_ADXW.mqh index 6ac3565d7..efd22ce2e 100644 --- a/Indicators/Indi_ADXW.mqh +++ b/Indicators/Indi_ADXW.mqh @@ -215,16 +215,17 @@ class Indi_ADXW : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = LINE_MAIN_ADX, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = LINE_MAIN_ADX, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; - _value = Indi_ADXW::iADXWilder(GetSymbol(), GetTf(), GetPeriod(), _mode, _shift, THIS_PTR); + _value = Indi_ADXW::iADXWilder(GetSymbol(), GetTf(), GetPeriod(), _mode, _ishift, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod() /*]*/, - _mode, _shift); + _mode, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_AMA.mqh b/Indicators/Indi_AMA.mqh index ceb65c602..58a8bee10 100644 --- a/Indicators/Indi_AMA.mqh +++ b/Indicators/Indi_AMA.mqh @@ -199,16 +199,17 @@ class Indi_AMA : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: _value = Indi_AMA::iAMA(GetSymbol(), GetTf(), /*[*/ GetPeriod(), GetFastPeriod(), GetSlowPeriod(), - GetAMAShift(), GetAppliedPrice() /*]*/, _mode, _shift, THIS_PTR); + GetAMAShift(), GetAppliedPrice() /*]*/, _mode, _ishift, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod(), - GetFastPeriod(), GetSlowPeriod(), GetAMAShift() /*]*/, _mode, _shift); + GetFastPeriod(), GetSlowPeriod(), GetAMAShift() /*]*/, _mode, _ishift); break; case IDATA_INDICATOR: diff --git a/Indicators/Indi_AO.mqh b/Indicators/Indi_AO.mqh index 6b494132e..a88552202 100644 --- a/Indicators/Indi_AO.mqh +++ b/Indicators/Indi_AO.mqh @@ -103,15 +103,16 @@ class Indi_AO : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; - _value = Indi_AO::iAO(GetSymbol(), GetTf(), _shift, _mode, THIS_PTR); + _value = Indi_AO::iAO(GetSymbol(), GetTf(), _ishift, _mode, THIS_PTR); break; case IDATA_ICUSTOM: - _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), _mode, _shift); + _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), _mode, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_ASI.mqh b/Indicators/Indi_ASI.mqh index 953691830..2e0cf341b 100644 --- a/Indicators/Indi_ASI.mqh +++ b/Indicators/Indi_ASI.mqh @@ -155,18 +155,19 @@ class Indi_ASI : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), - /*[*/ GetMaximumPriceChanging() /*]*/, 0, _shift); + /*[*/ GetMaximumPriceChanging() /*]*/, 0, _ishift); break; case IDATA_ONCALCULATE: { INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG(GetSymbol(), GetTf(), Util::MakeKey("Indi_ASI", GetMaximumPriceChanging())); _value = - iASIOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, GetMaximumPriceChanging(), _mode, _shift, _cache); + iASIOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, GetMaximumPriceChanging(), _mode, _ishift, _cache); break; } default: diff --git a/Indicators/Indi_ATR.mqh b/Indicators/Indi_ATR.mqh index e792d52a0..c74f1edd6 100644 --- a/Indicators/Indi_ATR.mqh +++ b/Indicators/Indi_ATR.mqh @@ -103,15 +103,16 @@ class Indi_ATR : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; - _value = Indi_ATR::iATR(GetSymbol(), GetTf(), GetPeriod(), _shift, THIS_PTR); + _value = Indi_ATR::iATR(GetSymbol(), GetTf(), GetPeriod(), _ishift, THIS_PTR); break; case IDATA_ICUSTOM: - _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), _mode, _shift); + _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), _mode, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_Alligator.mqh b/Indicators/Indi_Alligator.mqh index afccb5ff6..62b552df7 100644 --- a/Indicators/Indi_Alligator.mqh +++ b/Indicators/Indi_Alligator.mqh @@ -162,20 +162,21 @@ class Indi_Alligator : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode, int _shift = -1) { + double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); #ifdef __MQL4__ if (_mode == 0) { // In MQL4 mode 0 should be treated as mode 1 as Alligator buffers starts from index 1. - return GetMixedValue((ENUM_ALLIGATOR_LINE)1, _shift); + return GetEntryValue((ENUM_ALLIGATOR_LINE)1, _ishift); } #endif - double _value = EMPTY_VALUE; switch (iparams.idstype) { case IDATA_BUILTIN: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; _value = Indi_Alligator::iAlligator(GetSymbol(), GetTf(), GetJawPeriod(), GetJawShift(), GetTeethPeriod(), GetTeethShift(), GetLipsPeriod(), GetLipsShift(), GetMAMethod(), - GetAppliedPrice(), (ENUM_ALLIGATOR_LINE)_mode, _shift, THIS_PTR); + GetAppliedPrice(), (ENUM_ALLIGATOR_LINE)_mode, _ishift, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ @@ -183,7 +184,7 @@ class Indi_Alligator : public Indicator { GetLipsShift(), GetMAMethod(), GetAppliedPrice() /*]*/, - _mode, _shift); + _mode, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_AppliedPrice.mqh b/Indicators/Indi_AppliedPrice.mqh index f4d875ddb..379596331 100644 --- a/Indicators/Indi_AppliedPrice.mqh +++ b/Indicators/Indi_AppliedPrice.mqh @@ -74,15 +74,16 @@ class Indi_AppliedPrice : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_INDICATOR: if (HasDataSource()) { // Future validation of indi_src will check if we set mode for source indicator // (e.g. for applied price of Indi_Price). iparams.SetDataSourceMode(GetAppliedPrice()); - _value = Indi_AppliedPrice::iAppliedPriceOnIndicator(GetDataSource(), GetAppliedPrice(), _shift); + _value = Indi_AppliedPrice::iAppliedPriceOnIndicator(GetDataSource(), GetAppliedPrice(), _ishift); } break; default: diff --git a/Indicators/Indi_BWMFI.mqh b/Indicators/Indi_BWMFI.mqh index a0216a332..cc8b55e08 100644 --- a/Indicators/Indi_BWMFI.mqh +++ b/Indicators/Indi_BWMFI.mqh @@ -114,16 +114,17 @@ class Indi_BWMFI : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = BWMFI_BUFFER, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = BWMFI_BUFFER, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; - _value = Indi_BWMFI::iBWMFI(GetSymbol(), GetTf(), _shift, (ENUM_BWMFI_BUFFER)_mode, THIS_PTR); + _value = Indi_BWMFI::iBWMFI(GetSymbol(), GetTf(), _ishift, (ENUM_BWMFI_BUFFER)_mode, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ VOLUME_TICK /*]*/, - _mode, _shift); + _mode, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_BWZT.mqh b/Indicators/Indi_BWZT.mqh index e03857648..65d7cb881 100644 --- a/Indicators/Indi_BWZT.mqh +++ b/Indicators/Indi_BWZT.mqh @@ -172,14 +172,15 @@ class Indi_BWZT : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: - _value = Indi_BWZT::iBWZT(GetSymbol(), GetTf(), _mode, _shift, THIS_PTR); + _value = Indi_BWZT::iBWZT(GetSymbol(), GetTf(), _mode, _ishift, THIS_PTR); break; case IDATA_ICUSTOM: - _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), _mode, _shift); + _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), _mode, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_Bands.mqh b/Indicators/Indi_Bands.mqh index ee085c44b..0ff6a92e1 100644 --- a/Indicators/Indi_Bands.mqh +++ b/Indicators/Indi_Bands.mqh @@ -239,22 +239,23 @@ class Indi_Bands : public Indicator { * Note that in MQL5 Applied Price must be passed as the last parameter * (before mode and shift). */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = BAND_BASE, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = BAND_BASE, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; _value = Indi_Bands::iBands(GetSymbol(), GetTf(), GetPeriod(), GetDeviation(), GetBandsShift(), - GetAppliedPrice(), (ENUM_BANDS_LINE)_mode, _shift, THIS_PTR); + GetAppliedPrice(), (ENUM_BANDS_LINE)_mode, _ishift, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.custom_indi_name, /* [ */ GetPeriod(), - GetBandsShift(), GetDeviation(), GetAppliedPrice() /* ] */, _mode, _shift); + GetBandsShift(), GetDeviation(), GetAppliedPrice() /* ] */, _mode, _ishift); break; case IDATA_INDICATOR: // Calculating bands value from specified indicator. _value = Indi_Bands::iBandsOnIndicator(GetDataSource(), GetSymbol(), GetTf(), GetPeriod(), GetDeviation(), - GetBandsShift(), (ENUM_BANDS_LINE)_mode, _shift, THIS_PTR); + GetBandsShift(), (ENUM_BANDS_LINE)_mode, _ishift, THIS_PTR); break; } return _value; diff --git a/Indicators/Indi_BearsPower.mqh b/Indicators/Indi_BearsPower.mqh index d27567064..1b9721606 100644 --- a/Indicators/Indi_BearsPower.mqh +++ b/Indicators/Indi_BearsPower.mqh @@ -104,16 +104,17 @@ class Indi_BearsPower : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; - _value = _value = iBearsPower(GetSymbol(), GetTf(), GetPeriod(), GetAppliedPrice(), _shift, THIS_PTR); + _value = _value = iBearsPower(GetSymbol(), GetTf(), GetPeriod(), GetAppliedPrice(), _ishift, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod() /*]*/, - _mode, _shift); + _mode, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_BullsPower.mqh b/Indicators/Indi_BullsPower.mqh index 9d0bbabe7..1741f8da7 100644 --- a/Indicators/Indi_BullsPower.mqh +++ b/Indicators/Indi_BullsPower.mqh @@ -104,16 +104,17 @@ class Indi_BullsPower : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; - _value = iBullsPower(GetSymbol(), GetTf(), GetPeriod(), GetAppliedPrice(), _shift, THIS_PTR); + _value = iBullsPower(GetSymbol(), GetTf(), GetPeriod(), GetAppliedPrice(), _ishift, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /**/ GetPeriod() /**/, - _mode, _shift); + _mode, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_CCI.mqh b/Indicators/Indi_CCI.mqh index a0362f867..c32d4c191 100644 --- a/Indicators/Indi_CCI.mqh +++ b/Indicators/Indi_CCI.mqh @@ -145,25 +145,26 @@ class Indi_CCI : public Indicator { * Note that in MQL5 Applied Price must be passed as the last parameter * (before mode and shift). */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); double _value = EMPTY_VALUE; switch (iparams.idstype) { case IDATA_BUILTIN: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; // @fixit Somehow shift isn't used neither in MT4 nor MT5. - _value = - Indi_CCI::iCCI(GetSymbol(), GetTf(), GetPeriod(), GetAppliedPrice(), _shift /* + iparams.shift*/, THIS_PTR); + _value = Indi_CCI::iCCI(GetSymbol(), GetTf(), GetPeriod(), GetAppliedPrice(), _ishift /* + iparams.shift*/, + THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.custom_indi_name, /* [ */ GetPeriod(), - GetAppliedPrice() /* ] */, 0, _shift); + GetAppliedPrice() /* ] */, 0, _ishift); break; case IDATA_INDICATOR: ValidateSelectedDataSource(); // @fixit Somehow shift isn't used neither in MT4 nor MT5. _value = Indi_CCI::iCCIOnIndicator(GetDataSource(), GetSymbol(), GetTf(), GetPeriod(), GetDataSourceMode(), - _shift /* + iparams.shift*/); + _ishift /* + iparams.shift*/); break; } return _value; diff --git a/Indicators/Indi_CHO.mqh b/Indicators/Indi_CHO.mqh index 16fe50ea1..1cf24699e 100644 --- a/Indicators/Indi_CHO.mqh +++ b/Indicators/Indi_CHO.mqh @@ -166,16 +166,17 @@ class Indi_CHO : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: _value = Indi_CHO::iChaikin(GetSymbol(), GetTf(), /*[*/ GetSlowMA(), GetFastMA(), GetSmoothMethod(), - GetInputVolume() /*]*/, _mode, _shift, THIS_PTR); + GetInputVolume() /*]*/, _mode, _ishift, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetFastMA(), - GetSlowMA(), GetSmoothMethod(), GetInputVolume() /*]*/, 0, _shift); + GetSlowMA(), GetSmoothMethod(), GetInputVolume() /*]*/, 0, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_CHV.mqh b/Indicators/Indi_CHV.mqh index ea7b34bc5..d3f97fd42 100644 --- a/Indicators/Indi_CHV.mqh +++ b/Indicators/Indi_CHV.mqh @@ -162,16 +162,17 @@ class Indi_CHV : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: _value = Indi_CHV::iCHV(GetSymbol(), GetTf(), /*[*/ GetSmoothPeriod(), GetCHVPeriod(), GetSmoothMethod() /*]*/, - _mode, _shift, THIS_PTR); + _mode, _ishift, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetSmoothPeriod(), - GetCHVPeriod(), GetSmoothMethod() /*]*/, _mode, _shift); + GetCHVPeriod(), GetSmoothMethod() /*]*/, _mode, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_ColorBars.mqh b/Indicators/Indi_ColorBars.mqh index 056dcf04f..f89773c19 100644 --- a/Indicators/Indi_ColorBars.mqh +++ b/Indicators/Indi_ColorBars.mqh @@ -113,14 +113,15 @@ class Indi_ColorBars : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: - _value = Indi_ColorBars::iColorBars(GetSymbol(), GetTf(), _mode, _shift, THIS_PTR); + _value = Indi_ColorBars::iColorBars(GetSymbol(), GetTf(), _mode, _ishift, THIS_PTR); break; case IDATA_ICUSTOM: - _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), _mode, _shift); + _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), _mode, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_ColorCandlesDaily.mqh b/Indicators/Indi_ColorCandlesDaily.mqh index 31fc381c8..b8c4b851c 100644 --- a/Indicators/Indi_ColorCandlesDaily.mqh +++ b/Indicators/Indi_ColorCandlesDaily.mqh @@ -110,14 +110,15 @@ class Indi_ColorCandlesDaily : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: - _value = Indi_ColorCandlesDaily::iCCD(GetSymbol(), GetTf(), _mode, _shift, THIS_PTR); + _value = Indi_ColorCandlesDaily::iCCD(GetSymbol(), GetTf(), _mode, _ishift, THIS_PTR); break; case IDATA_ICUSTOM: - _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), _mode, _shift); + _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), _mode, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_ColorLine.mqh b/Indicators/Indi_ColorLine.mqh index 51ed0d7e9..d3dd60ed7 100644 --- a/Indicators/Indi_ColorLine.mqh +++ b/Indicators/Indi_ColorLine.mqh @@ -172,14 +172,15 @@ class Indi_ColorLine : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: - _value = Indi_ColorLine::iColorLine(GetSymbol(), GetTf(), _mode, _shift, THIS_PTR); + _value = Indi_ColorLine::iColorLine(GetSymbol(), GetTf(), _mode, _ishift, THIS_PTR); break; case IDATA_ICUSTOM: - _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), _mode, _shift); + _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), _mode, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_CustomMovingAverage.mqh b/Indicators/Indi_CustomMovingAverage.mqh index 2c801b9bb..7d83ee7dc 100644 --- a/Indicators/Indi_CustomMovingAverage.mqh +++ b/Indicators/Indi_CustomMovingAverage.mqh @@ -67,12 +67,13 @@ class Indi_CustomMovingAverage : public Indicator /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetSmoothPeriod(), - GetSmoothShift(), GetSmoothMethod() /*]*/, 0, _shift); + GetSmoothShift(), GetSmoothMethod() /*]*/, 0, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_DEMA.mqh b/Indicators/Indi_DEMA.mqh index 2d91c0934..420034607 100644 --- a/Indicators/Indi_DEMA.mqh +++ b/Indicators/Indi_DEMA.mqh @@ -166,26 +166,27 @@ class Indi_DEMA : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: // We're getting DEMA from Price indicator. istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; - _value = Indi_DEMA::iDEMA(GetSymbol(), GetTf(), GetPeriod(), GetMAShift(), GetAppliedPrice(), _shift, _mode, + _value = Indi_DEMA::iDEMA(GetSymbol(), GetTf(), GetPeriod(), GetMAShift(), GetAppliedPrice(), _ishift, _mode, GetPointer(this)); break; case IDATA_ICUSTOM: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.custom_indi_name, /*[*/ GetPeriod(), GetMAShift(), - GetAppliedPrice() /*]*/, _mode, _shift); + GetAppliedPrice() /*]*/, _mode, _ishift); break; case IDATA_INDICATOR: // Calculating DEMA value from specified indicator. _value = Indi_DEMA::iDEMAOnIndicator(GetCache(), GetDataSource(), GetDataSourceMode(), GetPeriod(), - GetMAShift(), _shift); + GetMAShift(), _ishift); break; } return _value; diff --git a/Indicators/Indi_DeMarker.mqh b/Indicators/Indi_DeMarker.mqh index 81a1e657e..98524dcdb 100644 --- a/Indicators/Indi_DeMarker.mqh +++ b/Indicators/Indi_DeMarker.mqh @@ -102,16 +102,17 @@ class Indi_DeMarker : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; - _value = _value = Indi_DeMarker::iDeMarker(GetSymbol(), GetTf(), GetPeriod(), _shift, THIS_PTR); + _value = _value = Indi_DeMarker::iDeMarker(GetSymbol(), GetTf(), GetPeriod(), _ishift, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod() /*]*/, - 0, _shift); + 0, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_Demo.mqh b/Indicators/Indi_Demo.mqh index 4f482b3b5..a5bf323d5 100644 --- a/Indicators/Indi_Demo.mqh +++ b/Indicators/Indi_Demo.mqh @@ -72,10 +72,11 @@ class Indi_Demo : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { - double _value = Indi_Demo::iDemo(GetSymbol(), GetTf(), _shift, THIS_PTR); + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); + double _value = Indi_Demo::iDemo(GetSymbol(), GetTf(), _ishift, THIS_PTR); if (iparams.is_draw) { - draw.DrawLineTo(GetName(), GetBarTime(_shift), _value); + draw.DrawLineTo(GetName(), GetBarTime(_ishift), _value); } return _value; } diff --git a/Indicators/Indi_DetrendedPrice.mqh b/Indicators/Indi_DetrendedPrice.mqh index b2836d80c..b8c4fe1cd 100644 --- a/Indicators/Indi_DetrendedPrice.mqh +++ b/Indicators/Indi_DetrendedPrice.mqh @@ -116,16 +116,17 @@ class Indi_DetrendedPrice : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: _value = Indi_DetrendedPrice::iDPO(GetSymbol(), GetTf(), /*[*/ GetPeriod(), GetAppliedPrice() /*]*/, _mode, - _shift, THIS_PTR); + _ishift, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod() /*]*/, - 0, _shift); + 0, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_Drawer.mqh b/Indicators/Indi_Drawer.mqh index 85d74f98b..2fc3c2593 100644 --- a/Indicators/Indi_Drawer.mqh +++ b/Indicators/Indi_Drawer.mqh @@ -172,15 +172,16 @@ class Indi_Drawer : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; - _value = Indi_Drawer::iDrawer(GetSymbol(), GetTf(), _shift, THIS_PTR); + _value = Indi_Drawer::iDrawer(GetSymbol(), GetTf(), _ishift, THIS_PTR); break; case IDATA_INDICATOR: - _value = Indi_Drawer::iDrawerOnIndicator(GetDataSource(), THIS_PTR, GetSymbol(), GetTf(), _shift); + _value = Indi_Drawer::iDrawerOnIndicator(GetDataSource(), THIS_PTR, GetSymbol(), GetTf(), _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_Envelopes.mqh b/Indicators/Indi_Envelopes.mqh index a3173c8a7..4761ab8ce 100644 --- a/Indicators/Indi_Envelopes.mqh +++ b/Indicators/Indi_Envelopes.mqh @@ -197,25 +197,27 @@ class Indi_Envelopes : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; _value = Indi_Envelopes::iEnvelopes(GetSymbol(), GetTf(), GetMAPeriod(), GetMAMethod(), GetMAShift(), - GetAppliedPrice(), GetDeviation(), _mode, _shift, THIS_PTR); + GetAppliedPrice(), GetDeviation(), _mode, _ishift, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /**/ GetMAPeriod(), - GetMAMethod(), GetMAShift(), GetAppliedPrice(), GetDeviation() /**/, _mode, _shift); + GetMAMethod(), GetMAShift(), GetAppliedPrice(), GetDeviation() /**/, _mode, _ishift); break; case IDATA_INDICATOR: _value = Indi_Envelopes::iEnvelopesOnIndicator(GetCache(), GetDataSource(), GetSymbol(), GetTf(), GetMAPeriod(), GetMAMethod(), GetDataSourceMode(), GetMAShift(), GetDeviation(), - _mode, _shift); + _mode, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); + break; } return _value; } diff --git a/Indicators/Indi_Force.mqh b/Indicators/Indi_Force.mqh index a592684f0..9e047338b 100644 --- a/Indicators/Indi_Force.mqh +++ b/Indicators/Indi_Force.mqh @@ -117,17 +117,18 @@ class Indi_Force : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; _value = - Indi_Force::iForce(GetSymbol(), GetTf(), GetPeriod(), GetMAMethod(), GetAppliedPrice(), _shift, THIS_PTR); + Indi_Force::iForce(GetSymbol(), GetTf(), GetPeriod(), GetMAMethod(), GetAppliedPrice(), _ishift, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod(), - GetMAMethod(), GetAppliedPrice(), VOLUME_TICK /*]*/, 0, _shift); + GetMAMethod(), GetAppliedPrice(), VOLUME_TICK /*]*/, 0, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_FractalAdaptiveMA.mqh b/Indicators/Indi_FractalAdaptiveMA.mqh index 6f2d90889..7640170c0 100644 --- a/Indicators/Indi_FractalAdaptiveMA.mqh +++ b/Indicators/Indi_FractalAdaptiveMA.mqh @@ -134,16 +134,17 @@ class Indi_FrAMA : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: _value = Indi_FrAMA::iFrAMA(GetSymbol(), GetTf(), /*[*/ GetPeriod(), GetFRAMAShift(), GetAppliedPrice() /*]*/, - _mode, _shift, THIS_PTR); + _mode, _ishift, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod(), - GetFRAMAShift() /*]*/, 0, _shift); + GetFRAMAShift() /*]*/, 0, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_Fractals.mqh b/Indicators/Indi_Fractals.mqh index c7c47158c..49d395311 100644 --- a/Indicators/Indi_Fractals.mqh +++ b/Indicators/Indi_Fractals.mqh @@ -102,15 +102,16 @@ class Indi_Fractals : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; - _value = _value = Indi_Fractals::iFractals(GetSymbol(), GetTf(), (ENUM_LO_UP_LINE)_mode, _shift, THIS_PTR); + _value = _value = Indi_Fractals::iFractals(GetSymbol(), GetTf(), (ENUM_LO_UP_LINE)_mode, _ishift, THIS_PTR); break; case IDATA_ICUSTOM: - _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), _mode, _shift); + _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), _mode, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_Gator.mqh b/Indicators/Indi_Gator.mqh index 561b712f5..9dca4b882 100644 --- a/Indicators/Indi_Gator.mqh +++ b/Indicators/Indi_Gator.mqh @@ -169,14 +169,15 @@ class Indi_Gator : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; _value = Indi_Gator::iGator(GetSymbol(), GetTf(), GetJawPeriod(), GetJawShift(), GetTeethPeriod(), GetTeethShift(), GetLipsPeriod(), GetLipsShift(), GetMAMethod(), GetAppliedPrice(), - (ENUM_GATOR_HISTOGRAM)_mode, _shift, THIS_PTR); + (ENUM_GATOR_HISTOGRAM)_mode, _ishift, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /**/ @@ -184,7 +185,7 @@ class Indi_Gator : public Indicator { GetLipsShift(), GetMAMethod(), GetAppliedPrice() /**/, - _mode, _shift); + _mode, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_HeikenAshi.mqh b/Indicators/Indi_HeikenAshi.mqh index 30bbd751a..789478852 100644 --- a/Indicators/Indi_HeikenAshi.mqh +++ b/Indicators/Indi_HeikenAshi.mqh @@ -195,8 +195,9 @@ class Indi_HeikenAshi : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = HA_OPEN, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = HA_OPEN, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: #ifdef __MQL4__ @@ -216,15 +217,15 @@ class Indi_HeikenAshi : public Indicator { break; } #endif - _value = Indi_HeikenAshi::iHeikenAshi(GetSymbol(), GetTf(), _mode, _shift, THIS_PTR); + _value = Indi_HeikenAshi::iHeikenAshi(GetSymbol(), GetTf(), _mode, _ishift, THIS_PTR); break; case IDATA_ICUSTOM: - _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), _mode, _shift); + _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), _mode, _ishift); break; case IDATA_ICUSTOM_LEGACY: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; _value = Indi_HeikenAshi::iCustomLegacyHeikenAshi(GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), _mode, - _shift, THIS_PTR); + _ishift, THIS_PTR); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_Ichimoku.mqh b/Indicators/Indi_Ichimoku.mqh index 504a7adc2..0f381d8d5 100644 --- a/Indicators/Indi_Ichimoku.mqh +++ b/Indicators/Indi_Ichimoku.mqh @@ -142,17 +142,18 @@ class Indi_Ichimoku : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; _value = Indi_Ichimoku::iIchimoku(GetSymbol(), GetTf(), GetTenkanSen(), GetKijunSen(), GetSenkouSpanB(), _mode, - _shift, THIS_PTR); + _ishift, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetTenkanSen(), - GetKijunSen(), GetSenkouSpanB() /*]*/, _mode, _shift); + GetKijunSen(), GetSenkouSpanB() /*]*/, _mode, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); @@ -168,9 +169,9 @@ class Indi_Ichimoku : public Indicator { #ifdef __MQL4__ // In MQL4 value of LINE_TENKANSEN is 1 (not 0 as in MQL5), // so we are duplicating it. - _entry.values[0] = GetMixedValue(LINE_TENKANSEN, _shift); + _entry.values[0] = GetEntryValue(LINE_TENKANSEN, _shift); #endif - _entry.values[LINE_CHIKOUSPAN] = GetMixedValue(LINE_CHIKOUSPAN, _shift + 26); + _entry.values[LINE_CHIKOUSPAN] = GetEntryValue(LINE_CHIKOUSPAN, _shift + 26); } /** diff --git a/Indicators/Indi_Killzones.mqh b/Indicators/Indi_Killzones.mqh index c930ea5ab..70016b6db 100644 --- a/Indicators/Indi_Killzones.mqh +++ b/Indicators/Indi_Killzones.mqh @@ -106,9 +106,10 @@ class Indi_Killzones : public Indicator { /** * Returns the indicator's value. */ - IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { float _value = FLT_MAX; int _index = (int)_mode / 2; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: // Builtin mode not supported. @@ -118,7 +119,7 @@ class Indi_Killzones : public Indicator { ikt.Set(::TimeGMT()); if (ikt.CheckHours(_index)) { // Pass values to check for new highs or lows. - ikt.Update(_mode % 2 == 0 ? (float)GetHigh(_shift) : (float)GetLow(_shift), _index); + ikt.Update(_mode % 2 == 0 ? (float)GetHigh(_ishift) : (float)GetLow(_ishift), _index); } // Set a final value. _value = _mode % 2 == 0 ? ikt.GetHigh(_index) : ikt.GetLow(_index); diff --git a/Indicators/Indi_MA.mqh b/Indicators/Indi_MA.mqh index 5dfbba5eb..d8ec96e68 100644 --- a/Indicators/Indi_MA.mqh +++ b/Indicators/Indi_MA.mqh @@ -627,23 +627,24 @@ class Indi_MA : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; - _value = Indi_MA::iMA(GetSymbol(), GetTf(), GetPeriod(), GetMAShift(), GetMAMethod(), GetAppliedPrice(), _shift, - THIS_PTR); + _value = Indi_MA::iMA(GetSymbol(), GetTf(), GetPeriod(), GetMAShift(), GetMAMethod(), GetAppliedPrice(), + _ishift, THIS_PTR); break; case IDATA_ICUSTOM: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.custom_indi_name, /* [ */ GetPeriod(), - GetMAShift(), GetMAMethod(), GetAppliedPrice() /* ] */, 0, _shift); + GetMAShift(), GetMAMethod(), GetAppliedPrice() /* ] */, 0, _ishift); break; case IDATA_INDICATOR: // Calculating MA value from specified indicator. _value = Indi_MA::iMAOnIndicator(GetCache(), GetDataSource(), GetDataSourceMode(), GetSymbol(), GetTf(), - GetPeriod(), GetMAShift(), GetMAMethod(), _shift); + GetPeriod(), GetMAShift(), GetMAMethod(), _ishift); break; } return _value; diff --git a/Indicators/Indi_MACD.mqh b/Indicators/Indi_MACD.mqh index a440c8ad4..64570f79b 100644 --- a/Indicators/Indi_MACD.mqh +++ b/Indicators/Indi_MACD.mqh @@ -114,18 +114,19 @@ class Indi_MACD : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = LINE_MAIN, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = LINE_MAIN, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; _value = Indi_MACD::iMACD(GetSymbol(), GetTf(), GetEmaFastPeriod(), GetEmaSlowPeriod(), GetSignalPeriod(), - GetAppliedPrice(), (ENUM_SIGNAL_LINE)_mode, _shift, THIS_PTR); + GetAppliedPrice(), (ENUM_SIGNAL_LINE)_mode, _ishift, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetEmaFastPeriod(), - GetEmaSlowPeriod(), GetSignalPeriod(), GetAppliedPrice() /*]*/, _mode, _shift); + GetEmaSlowPeriod(), GetSignalPeriod(), GetAppliedPrice() /*]*/, _mode, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_MFI.mqh b/Indicators/Indi_MFI.mqh index 0c27f09f6..902d6d08b 100644 --- a/Indicators/Indi_MFI.mqh +++ b/Indicators/Indi_MFI.mqh @@ -111,20 +111,21 @@ class Indi_MFI : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; #ifdef __MQL4__ - _value = Indi_MFI::iMFI(GetSymbol(), GetTf(), GetPeriod(), _shift); + _value = Indi_MFI::iMFI(GetSymbol(), GetTf(), GetPeriod(), _ishift); #else // __MQL5__ - _value = Indi_MFI::iMFI(GetSymbol(), GetTf(), GetPeriod(), GetAppliedVolume(), _shift, THIS_PTR); + _value = Indi_MFI::iMFI(GetSymbol(), GetTf(), GetPeriod(), GetAppliedVolume(), _ishift, THIS_PTR); #endif break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod(), - VOLUME_TICK /*]*/, 0, _shift); + VOLUME_TICK /*]*/, 0, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_MassIndex.mqh b/Indicators/Indi_MassIndex.mqh index 8df1fb995..817b81cd8 100644 --- a/Indicators/Indi_MassIndex.mqh +++ b/Indicators/Indi_MassIndex.mqh @@ -153,19 +153,21 @@ class Indi_MassIndex : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: _value = Indi_MassIndex::iMI(GetSymbol(), GetTf(), /*[*/ GetPeriod(), GetSecondPeriod(), GetSumPeriod() /*]*/, - _mode, _shift, THIS_PTR); + _mode, _ishift, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod(), - GetSecondPeriod(), GetSumPeriod() /*]*/, _mode, _shift); + GetSecondPeriod(), GetSumPeriod() /*]*/, _mode, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); + break; } return _value; } diff --git a/Indicators/Indi_Momentum.mqh b/Indicators/Indi_Momentum.mqh index 3a2c2cc32..5f4266dd0 100644 --- a/Indicators/Indi_Momentum.mqh +++ b/Indicators/Indi_Momentum.mqh @@ -141,18 +141,19 @@ class Indi_Momentum : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; // @fixit Somehow shift isn't used neither in MT4 nor MT5. - _value = Indi_Momentum::iMomentum(GetSymbol(), GetTf(), GetPeriod(), GetAppliedPrice(), iparams.shift + _shift, + _value = Indi_Momentum::iMomentum(GetSymbol(), GetTf(), GetPeriod(), GetAppliedPrice(), iparams.shift + _ishift, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod() /*]*/, - 0, _shift); + 0, _ishift); break; case IDATA_INDICATOR: ValidateSelectedDataSource(); diff --git a/Indicators/Indi_OBV.mqh b/Indicators/Indi_OBV.mqh index 96ef284df..cefa485e9 100644 --- a/Indicators/Indi_OBV.mqh +++ b/Indicators/Indi_OBV.mqh @@ -118,20 +118,21 @@ class Indi_OBV : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; #ifdef __MQL4__ - _value = Indi_OBV::iOBV(GetSymbol(), GetTf(), GetAppliedPrice(), _shift); + _value = Indi_OBV::iOBV(GetSymbol(), GetTf(), GetAppliedPrice(), _ishift); #else // __MQL5__ - _value = Indi_OBV::iOBV(GetSymbol(), GetTf(), GetAppliedVolume(), _shift, THIS_PTR); + _value = Indi_OBV::iOBV(GetSymbol(), GetTf(), GetAppliedVolume(), _ishift, THIS_PTR); #endif break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ VOLUME_TICK /*]*/, - 0, _shift); + 0, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_OsMA.mqh b/Indicators/Indi_OsMA.mqh index cd6c7a8e4..ac0a608a7 100644 --- a/Indicators/Indi_OsMA.mqh +++ b/Indicators/Indi_OsMA.mqh @@ -111,18 +111,19 @@ class Indi_OsMA : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); double _value = EMPTY_VALUE; switch (iparams.idstype) { case IDATA_BUILTIN: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; _value = Indi_OsMA::iOsMA(GetSymbol(), GetTf(), GetEmaFastPeriod(), GetEmaSlowPeriod(), GetSignalPeriod(), - GetAppliedPrice(), _shift, THIS_PTR); + GetAppliedPrice(), _ishift, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetEmaFastPeriod(), - GetEmaSlowPeriod(), GetSignalPeriod(), GetAppliedPrice() /*]*/, 0, _shift); + GetEmaSlowPeriod(), GetSignalPeriod(), GetAppliedPrice() /*]*/, 0, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_Pivot.mqh b/Indicators/Indi_Pivot.mqh index 586e15f9c..fd4c7cf4d 100644 --- a/Indicators/Indi_Pivot.mqh +++ b/Indicators/Indi_Pivot.mqh @@ -100,7 +100,10 @@ class Indi_Pivot : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { return GetEntry(_shift)[_mode]; } + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); + return GetEntry(_ishift)[_mode]; + } /** * Checks if indicator entry values are valid. diff --git a/Indicators/Indi_PriceChannel.mqh b/Indicators/Indi_PriceChannel.mqh index c5513fa72..0afc2392e 100644 --- a/Indicators/Indi_PriceChannel.mqh +++ b/Indicators/Indi_PriceChannel.mqh @@ -106,22 +106,20 @@ class Indi_PriceChannel : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { - ResetLastError(); + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: - _value = Indi_PriceChannel::iPriceChannel(GetSymbol(), GetTf(), GetPeriod(), _mode, _shift, THIS_PTR); + _value = Indi_PriceChannel::iPriceChannel(GetSymbol(), GetTf(), GetPeriod(), _mode, _ishift, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod() /*]*/, - 0, _shift); + 0, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); } - istate.is_ready = _LastError == ERR_NO_ERROR; - istate.is_changed = false; return _value; } diff --git a/Indicators/Indi_PriceFeeder.mqh b/Indicators/Indi_PriceFeeder.mqh index e88ed67fc..c1d286d88 100644 --- a/Indicators/Indi_PriceFeeder.mqh +++ b/Indicators/Indi_PriceFeeder.mqh @@ -75,12 +75,13 @@ class Indi_PriceFeeder : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { int data_size = ArraySize(iparams.price_data); + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - if (_shift >= data_size || _shift < 0) return DBL_MIN; + if (_ishift >= data_size || _ishift < 0) return DBL_MIN; - double _value = iparams.price_data[data_size - _shift - 1]; + double _value = iparams.price_data[data_size - _ishift - 1]; return _value; } diff --git a/Indicators/Indi_PriceVolumeTrend.mqh b/Indicators/Indi_PriceVolumeTrend.mqh index f96c37dc5..17505eff1 100644 --- a/Indicators/Indi_PriceVolumeTrend.mqh +++ b/Indicators/Indi_PriceVolumeTrend.mqh @@ -121,16 +121,17 @@ class Indi_PriceVolumeTrend : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: _value = - Indi_PriceVolumeTrend::iPVT(GetSymbol(), GetTf(), /*[*/ GetAppliedVolume() /*]*/, _mode, _shift, THIS_PTR); + Indi_PriceVolumeTrend::iPVT(GetSymbol(), GetTf(), /*[*/ GetAppliedVolume() /*]*/, _mode, _ishift, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), - /*[*/ GetAppliedVolume() /*]*/, 0, _shift); + /*[*/ GetAppliedVolume() /*]*/, 0, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_RS.mqh b/Indicators/Indi_RS.mqh index 4e71dd17c..51c03ed8d 100644 --- a/Indicators/Indi_RS.mqh +++ b/Indicators/Indi_RS.mqh @@ -78,10 +78,11 @@ class Indi_RS : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_MATH: - return imath[_mode].Ptr().GetMixedValue(); + return imath[_mode].Ptr().GetEntryValue(); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_RSI.mqh b/Indicators/Indi_RSI.mqh index 895c13e54..41b7339a9 100644 --- a/Indicators/Indi_RSI.mqh +++ b/Indicators/Indi_RSI.mqh @@ -289,23 +289,25 @@ class Indi_RSI : public Indicator { * Note that in MQL5 Applied Price must be passed as the last parameter * (before mode and shift). */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; double _res[]; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; - _value = Indi_RSI::iRSI(GetSymbol(), GetTf(), iparams.GetPeriod(), iparams.GetAppliedPrice(), _shift, THIS_PTR); + _value = + Indi_RSI::iRSI(GetSymbol(), GetTf(), iparams.GetPeriod(), iparams.GetAppliedPrice(), _ishift, THIS_PTR); break; case IDATA_ICUSTOM: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.custom_indi_name, /* [ */ iparams.GetPeriod(), - iparams.GetAppliedPrice() /* ] */, 0, _shift); + iparams.GetAppliedPrice() /* ] */, 0, _ishift); Print(_value); break; case IDATA_INDICATOR: _value = Indi_RSI::iRSIOnIndicator(GetDataSource(), THIS_PTR, GetSymbol(), GetTf(), iparams.GetPeriod(), - iparams.GetAppliedPrice(), _shift); + iparams.GetAppliedPrice(), _ishift); break; } return _value; diff --git a/Indicators/Indi_RVI.mqh b/Indicators/Indi_RVI.mqh index 93967b54a..18402acad 100644 --- a/Indicators/Indi_RVI.mqh +++ b/Indicators/Indi_RVI.mqh @@ -103,16 +103,17 @@ class Indi_RVI : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = LINE_MAIN, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = LINE_MAIN, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; - _value = Indi_RVI::iRVI(GetSymbol(), GetTf(), GetPeriod(), (ENUM_SIGNAL_LINE)_mode, _shift, THIS_PTR); + _value = Indi_RVI::iRVI(GetSymbol(), GetTf(), GetPeriod(), (ENUM_SIGNAL_LINE)_mode, _ishift, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod() /*]*/, - _mode, _shift); + _mode, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_RateOfChange.mqh b/Indicators/Indi_RateOfChange.mqh index 438d4d6b3..076f4798a 100644 --- a/Indicators/Indi_RateOfChange.mqh +++ b/Indicators/Indi_RateOfChange.mqh @@ -110,16 +110,17 @@ class Indi_RateOfChange : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: _value = Indi_RateOfChange::iROC(GetSymbol(), GetTf(), /*[*/ GetPeriod(), GetAppliedPrice() /*]*/, _mode, - _shift, THIS_PTR); + _ishift, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod() /*]*/, - 0, _shift); + 0, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_SAR.mqh b/Indicators/Indi_SAR.mqh index 570232fa0..2381c9cf3 100644 --- a/Indicators/Indi_SAR.mqh +++ b/Indicators/Indi_SAR.mqh @@ -102,16 +102,17 @@ class Indi_SAR : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; - _value = Indi_SAR::iSAR(GetSymbol(), GetTf(), GetStep(), GetMax(), _shift, THIS_PTR); + _value = Indi_SAR::iSAR(GetSymbol(), GetTf(), GetStep(), GetMax(), _ishift, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetStep(), - GetMax() /*]*/, _mode, _shift); + GetMax() /*]*/, _mode, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_StdDev.mqh b/Indicators/Indi_StdDev.mqh index 097771e74..4ef932b03 100644 --- a/Indicators/Indi_StdDev.mqh +++ b/Indicators/Indi_StdDev.mqh @@ -226,22 +226,23 @@ class Indi_StdDev : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; _value = Indi_StdDev::iStdDev(GetSymbol(), GetTf(), GetMAPeriod(), GetMAShift(), GetMAMethod(), - GetAppliedPrice(), _shift, THIS_PTR); + GetAppliedPrice(), _ishift, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, Get(CHART_PARAM_SYMBOL), Get(CHART_PARAM_TF), iparams.GetCustomIndicatorName(), /*[*/ GetMAPeriod(), GetMAShift(), GetMAMethod() /*]*/, 0, - _shift); + _ishift); break; case IDATA_INDICATOR: _value = Indi_StdDev::iStdDevOnIndicator(GetDataSource(), GetSymbol(), GetTf(), GetMAPeriod(), GetMAShift(), - GetAppliedPrice(), _shift, THIS_PTR); + GetAppliedPrice(), _ishift, THIS_PTR); break; } return _value; diff --git a/Indicators/Indi_Stochastic.mqh b/Indicators/Indi_Stochastic.mqh index 60628f69f..d60246205 100644 --- a/Indicators/Indi_Stochastic.mqh +++ b/Indicators/Indi_Stochastic.mqh @@ -119,17 +119,18 @@ class Indi_Stochastic : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = LINE_MAIN, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = LINE_MAIN, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; _value = Indi_Stochastic::iStochastic(GetSymbol(), GetTf(), GetKPeriod(), GetDPeriod(), GetSlowing(), - GetMAMethod(), GetPriceField(), _mode, _shift, THIS_PTR); + GetMAMethod(), GetPriceField(), _mode, _ishift, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetKPeriod(), - GetDPeriod(), GetSlowing() /*]*/, _mode, _shift); + GetDPeriod(), GetSlowing() /*]*/, _mode, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_TEMA.mqh b/Indicators/Indi_TEMA.mqh index 9b1d201d4..3cc9e949b 100644 --- a/Indicators/Indi_TEMA.mqh +++ b/Indicators/Indi_TEMA.mqh @@ -126,16 +126,17 @@ class Indi_TEMA : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: _value = Indi_TEMA::iTEMA(GetSymbol(), GetTf(), /*[*/ GetPeriod(), GetTEMAShift(), GetAppliedPrice() /*]*/, 0, - _shift, THIS_PTR); + _ishift, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod(), - GetTEMAShift() /*]*/, 0, _shift); + GetTEMAShift() /*]*/, 0, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_TRIX.mqh b/Indicators/Indi_TRIX.mqh index b30899b8b..a8086bd27 100644 --- a/Indicators/Indi_TRIX.mqh +++ b/Indicators/Indi_TRIX.mqh @@ -127,16 +127,17 @@ class Indi_TRIX : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: - _value = - Indi_TRIX::iTriX(GetSymbol(), GetTf(), /*[*/ GetPeriod(), GetAppliedPrice() /*]*/, _mode, _shift, THIS_PTR); + _value = Indi_TRIX::iTriX(GetSymbol(), GetTf(), /*[*/ GetPeriod(), GetAppliedPrice() /*]*/, _mode, _ishift, + THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod() /*]*/, - 0, _shift); + 0, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_UltimateOscillator.mqh b/Indicators/Indi_UltimateOscillator.mqh index 6a528dffa..7788bd77b 100644 --- a/Indicators/Indi_UltimateOscillator.mqh +++ b/Indicators/Indi_UltimateOscillator.mqh @@ -209,20 +209,21 @@ class Indi_UltimateOscillator : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: _value = Indi_UltimateOscillator::iUO(GetSymbol(), GetTf(), /*[*/ GetFastPeriod(), GetMiddlePeriod(), GetSlowPeriod(), GetFastK(), GetMiddleK(), GetSlowK() /*]*/, _mode, - _shift, THIS_PTR); + _ishift, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetFastPeriod(), GetMiddlePeriod(), GetSlowPeriod(), GetFastK(), GetMiddleK(), GetSlowK() /*]*/, - 0, _shift); + 0, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_VIDYA.mqh b/Indicators/Indi_VIDYA.mqh index 9e1d39bf0..a5647974c 100644 --- a/Indicators/Indi_VIDYA.mqh +++ b/Indicators/Indi_VIDYA.mqh @@ -147,19 +147,20 @@ class Indi_VIDYA : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: _value = Indi_VIDYA::iVIDyA(GetSymbol(), GetTf(), /*[*/ GetCMOPeriod(), GetMAPeriod(), GetVIDYAShift(), - GetAppliedPrice() /*]*/, 0, _shift, THIS_PTR); + GetAppliedPrice() /*]*/, 0, _ishift, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetCMOPeriod(), GetMAPeriod(), GetVIDYAShift() /*]*/, - 0, _shift); + 0, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_VROC.mqh b/Indicators/Indi_VROC.mqh index 5ed32df45..2170fa831 100644 --- a/Indicators/Indi_VROC.mqh +++ b/Indicators/Indi_VROC.mqh @@ -130,16 +130,17 @@ class Indi_VROC : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: - _value = Indi_VROC::iVROC(GetSymbol(), GetTf(), /*[*/ GetPeriod(), GetAppliedVolume() /*]*/, _mode, _shift, + _value = Indi_VROC::iVROC(GetSymbol(), GetTf(), /*[*/ GetPeriod(), GetAppliedVolume() /*]*/, _mode, _ishift, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), - /*[*/ GetPeriod(), GetAppliedVolume() /*]*/, _mode, _shift); + /*[*/ GetPeriod(), GetAppliedVolume() /*]*/, _mode, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_Volumes.mqh b/Indicators/Indi_Volumes.mqh index 29fea52dd..786f9fbbe 100644 --- a/Indicators/Indi_Volumes.mqh +++ b/Indicators/Indi_Volumes.mqh @@ -124,15 +124,16 @@ class Indi_Volumes : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: - _value = Indi_Volumes::iVolumes(GetSymbol(), GetTf(), /*[*/ GetAppliedVolume() /*]*/, _mode, _shift, THIS_PTR); + _value = Indi_Volumes::iVolumes(GetSymbol(), GetTf(), /*[*/ GetAppliedVolume() /*]*/, _mode, _ishift, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), - /*[*/ GetAppliedVolume() /*]*/, _mode, _shift); + /*[*/ GetAppliedVolume() /*]*/, _mode, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_WPR.mqh b/Indicators/Indi_WPR.mqh index 1aad02998..8dcc258aa 100644 --- a/Indicators/Indi_WPR.mqh +++ b/Indicators/Indi_WPR.mqh @@ -101,16 +101,17 @@ class Indi_WPR : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; - _value = Indi_WPR::iWPR(GetSymbol(), GetTf(), GetPeriod(), _shift, THIS_PTR); + _value = Indi_WPR::iWPR(GetSymbol(), GetTf(), GetPeriod(), _ishift, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod() /*]*/, - 0, _shift); + 0, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_WilliamsAD.mqh b/Indicators/Indi_WilliamsAD.mqh index 03987b796..754cff808 100644 --- a/Indicators/Indi_WilliamsAD.mqh +++ b/Indicators/Indi_WilliamsAD.mqh @@ -124,14 +124,15 @@ class Indi_WilliamsAD : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: - _value = Indi_WilliamsAD::iWAD(GetSymbol(), GetTf(), _mode, _shift, THIS_PTR); + _value = Indi_WilliamsAD::iWAD(GetSymbol(), GetTf(), _mode, _ishift, THIS_PTR); break; case IDATA_ICUSTOM: - _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), 0, _shift); + _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), 0, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_ZigZag.mqh b/Indicators/Indi_ZigZag.mqh index 9c207f57e..94fa26e33 100644 --- a/Indicators/Indi_ZigZag.mqh +++ b/Indicators/Indi_ZigZag.mqh @@ -334,17 +334,18 @@ class Indi_ZigZag : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: _value = Indi_ZigZag::iZigZag(GetSymbol(), GetTf(), GetDepth(), GetDeviation(), GetBackstep(), - (ENUM_ZIGZAG_LINE)_mode, _shift, THIS_PTR); + (ENUM_ZIGZAG_LINE)_mode, _ishift, THIS_PTR); break; case IDATA_ICUSTOM: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; _value = Indi_ZigZag::iCustomZigZag(GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), GetDepth(), - GetDeviation(), GetBackstep(), (ENUM_ZIGZAG_LINE)_mode, _shift, THIS_PTR); + GetDeviation(), GetBackstep(), (ENUM_ZIGZAG_LINE)_mode, _ishift, THIS_PTR); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_ZigZagColor.mqh b/Indicators/Indi_ZigZagColor.mqh index 90c5ed66e..26489fd8f 100644 --- a/Indicators/Indi_ZigZagColor.mqh +++ b/Indicators/Indi_ZigZagColor.mqh @@ -268,23 +268,22 @@ class Indi_ZigZagColor : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { - ResetLastError(); + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: _value = Indi_ZigZagColor::iZigZagColor(GetSymbol(), GetTf(), GetDepth(), GetDeviation(), GetBackstep(), - (ENUM_ZIGZAG_LINE)_mode, _shift, THIS_PTR); + (ENUM_ZIGZAG_LINE)_mode, _ishift, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), - /*[*/ GetDepth(), GetDeviation(), GetBackstep() /*]*/, _mode, _shift); + /*[*/ GetDepth(), GetDeviation(), GetBackstep() /*]*/, _mode, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); + break; } - istate.is_ready = _LastError == ERR_NO_ERROR; - istate.is_changed = false; return _value; } diff --git a/Indicators/OHLC/Indi_OHLC.mqh b/Indicators/OHLC/Indi_OHLC.mqh index cc1b5f926..7d7d26d93 100644 --- a/Indicators/OHLC/Indi_OHLC.mqh +++ b/Indicators/OHLC/Indi_OHLC.mqh @@ -60,7 +60,8 @@ class Indi_OHLC : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); ENUM_APPLIED_PRICE _ap = PRICE_OPEN; switch (_mode) { case INDI_OHLC_CLOSE: @@ -76,7 +77,7 @@ class Indi_OHLC : public Indicator { _ap = PRICE_LOW; break; } - return ChartStatic::iPrice(_ap, GetSymbol(), GetTf(), _shift); + return ChartStatic::iPrice(_ap, GetSymbol(), GetTf(), _ishift); } /** diff --git a/Indicators/Price/Indi_Price.mqh b/Indicators/Price/Indi_Price.mqh index 4f155f775..74cd43db8 100644 --- a/Indicators/Price/Indi_Price.mqh +++ b/Indicators/Price/Indi_Price.mqh @@ -62,8 +62,9 @@ class Indi_Price : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { - return ChartStatic::iPrice(iparams.GetAppliedPrice(), GetSymbol(), GetTf(), _shift); + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); + return ChartStatic::iPrice(iparams.GetAppliedPrice(), GetSymbol(), GetTf(), _ishift); } /** diff --git a/Indicators/Special/Indi_Math.mqh b/Indicators/Special/Indi_Math.mqh index dd11760b7..033377c04 100644 --- a/Indicators/Special/Indi_Math.mqh +++ b/Indicators/Special/Indi_Math.mqh @@ -93,8 +93,9 @@ class Indi_Math : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_INDICATOR: if (!indi_src.IsSet()) { @@ -112,12 +113,12 @@ class Indi_Math : public Indicator { case MATH_OP_MODE_BUILTIN: _value = Indi_Math::iMathOnIndicator(GetDataSource(), GetSymbol(), GetTf(), /*[*/ GetOpBuiltIn(), GetMode1(), GetMode2(), GetShift1(), - GetShift2() /*]*/, 0, _shift, &this); + GetShift2() /*]*/, 0, _ishift, &this); break; case MATH_OP_MODE_CUSTOM_FUNCTION: _value = Indi_Math::iMathOnIndicator(GetDataSource(), GetSymbol(), GetTf(), /*[*/ GetOpFunction(), GetMode1(), GetMode2(), GetShift1(), - GetShift2() /*]*/, 0, _shift, &this); + GetShift2() /*]*/, 0, _ishift, &this); break; } break; diff --git a/Indicators/Tick/Indi_TickMt.mqh b/Indicators/Tick/Indi_TickMt.mqh index ced489df0..a5d1b0e8e 100644 --- a/Indicators/Tick/Indi_TickMt.mqh +++ b/Indicators/Tick/Indi_TickMt.mqh @@ -57,7 +57,7 @@ class Indi_TickMt : public IndicatorTick { /** * Returns the indicator's value. */ - IndicatorDataEntryValue GetMixedValue(int _mode = 0, int _shift = 0) { + IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { if (_shift == 0) { // Fetch a current prices of a specified symbol. tick = SymbolInfoStatic::GetTick(itparams.GetSymbol()); diff --git a/tests/DrawIndicatorTest.mq5 b/tests/DrawIndicatorTest.mq5 index 19786332b..0ec2fc83b 100644 --- a/tests/DrawIndicatorTest.mq5 +++ b/tests/DrawIndicatorTest.mq5 @@ -151,14 +151,9 @@ bool InitIndicators() { * Print indicators. */ bool PrintIndicators(string _prefix = "") { + ResetLastError(); for (DictIterator iter = indis.Begin(); iter.IsValid(); ++iter) { IndicatorBase *_indi = iter.Value(); - MqlParam _value = _indi.GetEntryValue(); - if (GetLastError() == ERR_INDICATOR_DATA_NOT_FOUND || - GetLastError() == ERR_USER_ERROR_FIRST + ERR_USER_INVALID_BUFF_NUM) { - ResetLastError(); - continue; - } if (_indi.Get(STRUCT_ENUM(IndicatorState, INDICATOR_STATE_PROP_IS_READY))) { PrintFormat("%s: %s: %s", _prefix, _indi.GetName(), _indi.ToString()); } diff --git a/tests/IndicatorsTest.mq5 b/tests/IndicatorsTest.mq5 index 5c6ff58bf..3863538ae 100644 --- a/tests/IndicatorsTest.mq5 +++ b/tests/IndicatorsTest.mq5 @@ -557,7 +557,7 @@ bool PrintIndicators(string _prefix = "") { } string _indi_name = _indi.GetFullName(); - MqlParam _value = _indi.GetEntryValue(); + IndicatorDataEntryValue _value = _indi.GetEntryValue(); if (GetLastError() == ERR_INDICATOR_DATA_NOT_FOUND || GetLastError() == ERR_USER_ERROR_FIRST + ERR_USER_INVALID_BUFF_NUM) { ResetLastError(); From 42a6879cc6ed55683001ee14b46aa8ababb8e669 Mon Sep 17 00:00:00 2001 From: kenorb Date: Mon, 8 Nov 2021 14:11:23 +0000 Subject: [PATCH 08/77] Indicator/IndicatorTick: Fixes return type --- Indicator/IndicatorTick.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Indicator/IndicatorTick.h b/Indicator/IndicatorTick.h index 8f54219a9..602a27a6e 100644 --- a/Indicator/IndicatorTick.h +++ b/Indicator/IndicatorTick.h @@ -148,10 +148,9 @@ class IndicatorTick : public IndicatorBase { * @return * Returns DataParamEntry struct filled with a single value. */ - virtual DataParamEntry GetEntryValue(int _shift = -1, int _mode = 0) { - IndicatorDataEntry _entry = GetEntry(_shift >= 0 ? _shift : itparams.GetShift()); - DataParamEntry _value_entry; - return _value_entry; + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + int _ishift = _shift >= 0 ? _shift : itparams.GetShift(); + return GetEntry(_ishift)[_mode]; } /** From 16385fd779c4ecfed44db6be450b88c970abcce3 Mon Sep 17 00:00:00 2001 From: kenorb Date: Tue, 9 Nov 2021 21:31:38 +0000 Subject: [PATCH 09/77] Indicator: Moving some methods from base class to main Indicator: Renames _shift to _index --- Indicator.mqh | 286 ++++++++++++++++++++++++++++++- Indicator/IndicatorTick.h | 2 +- IndicatorBase.h | 342 +++----------------------------------- 3 files changed, 311 insertions(+), 319 deletions(-) diff --git a/Indicator.mqh b/Indicator.mqh index 42955d2a9..ae7c48e07 100644 --- a/Indicator.mqh +++ b/Indicator.mqh @@ -50,12 +50,39 @@ class Chart; #include "Storage/ValueStorage.indicator.h" #include "Storage/ValueStorage.native.h" +#ifndef __MQL4__ +// Defines global functions (for MQL4 backward compatibility). +bool IndicatorBuffers(int _count) { return Indicator::SetIndicatorBuffers(_count); } +int IndicatorCounted(int _value = 0) { + static int prev_calculated = 0; + // https://docs.mql4.com/customind/indicatorcounted + prev_calculated = _value > 0 ? _value : prev_calculated; + return prev_calculated; +} +#endif + +#ifdef __MQL5__ +// Defines global functions (for MQL5 forward compatibility). +template +double iCustom5(string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, G _g, H _h, I _i, + J _j, int _mode, int _shift) { + ResetLastError(); + static Dict _handlers; + string _key = Util::MakeKey(_symbol, (string)_tf, _name, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j); + int _handle = _handlers.GetByKey(_key); + ICUSTOM_DEF(_handlers.Set(_key, _handle), + COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g COMMA _h COMMA _i COMMA _j); +} +#endif + /** * Class to deal with indicators. */ template class Indicator : public IndicatorBase { protected: + DrawIndicator* draw; BufferStruct idata; TS iparams; @@ -387,6 +414,127 @@ class Indicator : public IndicatorBase { */ virtual IndicatorBase* FetchDataSource(ENUM_INDICATOR_TYPE _id) { return NULL; } + /* State methods */ + + /** + * Checks for crossover. + * + * @return + * Returns true when values are crossing over, otherwise false. + */ + bool IsCrossover(int _shift1 = 0, int _shift2 = 1, int _mode1 = 0, int _mode2 = 0) { + double _curr_value1 = GetEntry(_shift1)[_mode1]; + double _prev_value1 = GetEntry(_shift2)[_mode1]; + double _curr_value2 = GetEntry(_shift1)[_mode2]; + double _prev_value2 = GetEntry(_shift2)[_mode2]; + return ((_curr_value1 > _prev_value1 && _curr_value2 < _prev_value2) || + (_prev_value1 > _curr_value1 && _prev_value2 < _curr_value2)); + } + + /** + * Checks if values are decreasing. + * + * @param int _rows + * Numbers of rows to check. + * @param int _mode + * Indicator index mode to check. + * @param int _shift + * Shift which is the final value to take into the account. + * + * @return + * Returns true when values are increasing. + */ + bool IsDecreasing(int _rows = 1, int _mode = 0, int _shift = 0) { + bool _result = true; + for (int i = _shift + _rows - 1; i >= _shift && _result; i--) { + IndicatorDataEntry _entry_curr = GetEntry(i); + IndicatorDataEntry _entry_prev = GetEntry(i + 1); + _result &= _entry_curr.IsValid() && _entry_prev.IsValid() && _entry_curr[_mode] < _entry_prev[_mode]; + if (!_result) { + break; + } + } + return _result; + } + + /** + * Checks if value decreased by the given percentage value. + * + * @param int _pct + * Percentage value to use for comparison. + * @param int _mode + * Indicator index mode to use. + * @param int _shift + * Indicator value shift to use. + * @param int _count + * Count of bars to compare change backward. + * @param int _hundreds + * When true, use percentage in hundreds, otherwise 1 is 100%. + * + * @return + * Returns true when value increased. + */ + bool IsDecByPct(float _pct, int _mode = 0, int _shift = 0, int _count = 1, bool _hundreds = true) { + bool _result = true; + IndicatorDataEntry _v0 = GetEntry(_shift); + IndicatorDataEntry _v1 = GetEntry(_shift + _count); + _result &= _v0.IsValid() && _v1.IsValid(); + _result &= _result && Math::ChangeInPct(_v1[_mode], _v0[_mode], _hundreds) < _pct; + return _result; + } + + /** + * Checks if values are increasing. + * + * @param int _rows + * Numbers of rows to check. + * @param int _mode + * Indicator index mode to check. + * @param int _shift + * Shift which is the final value to take into the account. + * + * @return + * Returns true when values are increasing. + */ + bool IsIncreasing(int _rows = 1, int _mode = 0, int _shift = 0) { + bool _result = true; + for (int i = _shift + _rows - 1; i >= _shift && _result; i--) { + IndicatorDataEntry _entry_curr = GetEntry(i); + IndicatorDataEntry _entry_prev = GetEntry(i + 1); + _result &= _entry_curr.IsValid() && _entry_prev.IsValid() && _entry_curr[_mode] > _entry_prev[_mode]; + if (!_result) { + break; + } + } + return _result; + } + + /** + * Checks if value increased by the given percentage value. + * + * @param int _pct + * Percentage value to use for comparison. + * @param int _mode + * Indicator index mode to use. + * @param int _shift + * Indicator value shift to use. + * @param int _count + * Count of bars to compare change backward. + * @param int _hundreds + * When true, use percentage in hundreds, otherwise 1 is 100%. + * + * @return + * Returns true when value increased. + */ + bool IsIncByPct(float _pct, int _mode = 0, int _shift = 0, int _count = 1, bool _hundreds = true) { + bool _result = true; + IndicatorDataEntry _v0 = GetEntry(_shift); + IndicatorDataEntry _v1 = GetEntry(_shift + _count); + _result &= _v0.IsValid() && _v1.IsValid(); + _result &= _result && Math::ChangeInPct(_v1[_mode], _v0[_mode], _hundreds) > _pct; + return _result; + } + /* Getters */ /** @@ -950,9 +1098,9 @@ class Indicator : public IndicatorBase { * @return * Returns IndicatorDataEntry struct filled with indicator values. */ - virtual IndicatorDataEntry GetEntry(int _shift = -1) { + virtual IndicatorDataEntry GetEntry(int _index = -1) { ResetLastError(); - int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); + int _ishift = _index >= 0 ? _index : iparams.GetShift(); long _bar_time = GetBarTime(_ishift); IndicatorDataEntry _entry = idata.GetByKey(_bar_time); if (_bar_time > 0 && !_entry.IsValid() && !_entry.CheckFlag(INDI_ENTRY_FLAG_INSUFFICIENT_DATA)) { @@ -1023,7 +1171,7 @@ class Indicator : public IndicatorBase { * Returns DataParamEntry struct filled with a single value. */ /* - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, long _shift = -1) { IndicatorDataEntry _entry = GetEntry(fmax(_shift, _shift >= 0 ? _shift : iparams.GetShift())); DataParamEntry _value_entry; switch (iparams.GetDataValueType()) { @@ -1068,6 +1216,138 @@ class Indicator : public IndicatorBase { return EMPTY_VALUE; } */ + + /* Defines MQL backward compatible methods */ + + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, int _mode, int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, DUMMY); +#endif + } + + template + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, int _mode, int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _a, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, COMMA _a); +#endif + } + + template + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, int _mode, int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _a, _b, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, COMMA _a COMMA _b); +#endif + } + + template + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, int _mode, + int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c); +#endif + } + + template + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, int _mode, + int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d); +#endif + } + + template + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, + int _mode, int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e); +#endif + } + + template + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, + int _mode, int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f); +#endif + } + + template + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, + G _g, int _mode, int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _g, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g); +#endif + } + + template + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, + G _g, H _h, int _mode, int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _g, _h, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g COMMA _h); +#endif + } + + template + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, + G _g, H _h, I _i, int _mode, int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _g, _h, _i, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g COMMA _h COMMA _i); +#endif + } + + template + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, + G _g, H _h, I _i, J _j, int _mode, int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g COMMA _h COMMA _i COMMA _j); +#endif + } + + template + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, + G _g, H _h, I _i, J _j, K _k, int _mode, int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g COMMA _h COMMA _i COMMA _j COMMA _k); +#endif + } + + template + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, 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, int _mode, int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g COMMA _h COMMA _i COMMA _j COMMA _k + COMMA _l COMMA _m); +#endif + } }; #endif diff --git a/Indicator/IndicatorTick.h b/Indicator/IndicatorTick.h index 602a27a6e..04c0fb3f7 100644 --- a/Indicator/IndicatorTick.h +++ b/Indicator/IndicatorTick.h @@ -136,7 +136,7 @@ class IndicatorTick : public IndicatorBase { * This method allows user to modify the struct entry before it's added to cache. * This method is called on GetEntry() right after values are set. */ - virtual void GetEntryAlter(IndicatorDataEntry& _entry, int _shift = -1) { + virtual void GetEntryAlter(IndicatorDataEntry& _entry, int _timestamp = -1) { _entry.AddFlags(_entry.GetDataTypeFlags(itparams.GetDataValueType())); }; diff --git a/IndicatorBase.h b/IndicatorBase.h index d581a28b4..e13b9ed17 100644 --- a/IndicatorBase.h +++ b/IndicatorBase.h @@ -55,38 +55,11 @@ class Chart; #include "Storage/ValueStorage.native.h" #include "Util.h" -#ifndef __MQL4__ -// Defines global functions (for MQL4 backward compatibility). -bool IndicatorBuffers(int _count) { return Indicator::SetIndicatorBuffers(_count); } -int IndicatorCounted(int _value = 0) { - static int prev_calculated = 0; - // https://docs.mql4.com/customind/indicatorcounted - prev_calculated = _value > 0 ? _value : prev_calculated; - return prev_calculated; -} -#endif - -#ifdef __MQL5__ -// Defines global functions (for MQL5 forward compatibility). -template -double iCustom5(string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, G _g, H _h, I _i, - J _j, int _mode, int _shift) { - ResetLastError(); - static Dict _handlers; - string _key = Util::MakeKey(_symbol, (string)_tf, _name, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j); - int _handle = _handlers.GetByKey(_key); - ICUSTOM_DEF(_handlers.Set(_key, _handle), - COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g COMMA _h COMMA _i COMMA _j); -} -#endif - /** * Class to deal with indicators. */ class IndicatorBase : public Chart { protected: - DrawIndicator* draw; IndicatorState istate; void* mydata; bool is_fed; // Whether calc_start_bar is already calculated. @@ -153,138 +126,6 @@ class IndicatorBase : public Chart { IndicatorDataEntry operator[](int _index) { return GetEntry(_index); } IndicatorDataEntry operator[](ENUM_INDICATOR_INDEX _index) { return GetEntry(_index); } - /* Defines MQL backward compatible methods */ - - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, int _mode, int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, DUMMY); -#endif - } - - template - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, int _mode, int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _a, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, COMMA _a); -#endif - } - - template - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, int _mode, int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _a, _b, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, COMMA _a COMMA _b); -#endif - } - - template - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, int _mode, - int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c); -#endif - } - - template - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, int _mode, - int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d); -#endif - } - - template - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, - int _mode, int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e); -#endif - } - - template - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, - int _mode, int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f); -#endif - } - - template - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, - G _g, int _mode, int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _g, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g); -#endif - } - - template - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, - G _g, H _h, int _mode, int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _g, _h, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g COMMA _h); -#endif - } - - template - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, - G _g, H _h, I _i, int _mode, int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _g, _h, _i, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g COMMA _h COMMA _i); -#endif - } - - template - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, - G _g, H _h, I _i, J _j, int _mode, int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g COMMA _h COMMA _i COMMA _j); -#endif - } - - template - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, - G _g, H _h, I _i, J _j, K _k, int _mode, int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g COMMA _h COMMA _i COMMA _j COMMA _k); -#endif - } - - template - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, 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, int _mode, int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g COMMA _h COMMA _i COMMA _j COMMA _k - COMMA _l COMMA _m); -#endif - } - /* Buffer methods */ virtual string CacheKey() { return GetName(); } @@ -461,127 +302,6 @@ class IndicatorBase : public Chart { */ virtual int GetModeCount() { return 0; } - /* State methods */ - - /** - * Checks for crossover. - * - * @return - * Returns true when values are crossing over, otherwise false. - */ - bool IsCrossover(int _shift1 = 0, int _shift2 = 1, int _mode1 = 0, int _mode2 = 0) { - double _curr_value1 = GetEntry(_shift1)[_mode1]; - double _prev_value1 = GetEntry(_shift2)[_mode1]; - double _curr_value2 = GetEntry(_shift1)[_mode2]; - double _prev_value2 = GetEntry(_shift2)[_mode2]; - return ((_curr_value1 > _prev_value1 && _curr_value2 < _prev_value2) || - (_prev_value1 > _curr_value1 && _prev_value2 < _curr_value2)); - } - - /** - * Checks if values are decreasing. - * - * @param int _rows - * Numbers of rows to check. - * @param int _mode - * Indicator index mode to check. - * @param int _shift - * Shift which is the final value to take into the account. - * - * @return - * Returns true when values are increasing. - */ - bool IsDecreasing(int _rows = 1, int _mode = 0, int _shift = 0) { - bool _result = true; - for (int i = _shift + _rows - 1; i >= _shift && _result; i--) { - IndicatorDataEntry _entry_curr = GetEntry(i); - IndicatorDataEntry _entry_prev = GetEntry(i + 1); - _result &= _entry_curr.IsValid() && _entry_prev.IsValid() && _entry_curr[_mode] < _entry_prev[_mode]; - if (!_result) { - break; - } - } - return _result; - } - - /** - * Checks if value decreased by the given percentage value. - * - * @param int _pct - * Percentage value to use for comparison. - * @param int _mode - * Indicator index mode to use. - * @param int _shift - * Indicator value shift to use. - * @param int _count - * Count of bars to compare change backward. - * @param int _hundreds - * When true, use percentage in hundreds, otherwise 1 is 100%. - * - * @return - * Returns true when value increased. - */ - bool IsDecByPct(float _pct, int _mode = 0, int _shift = 0, int _count = 1, bool _hundreds = true) { - bool _result = true; - IndicatorDataEntry _v0 = GetEntry(_shift); - IndicatorDataEntry _v1 = GetEntry(_shift + _count); - _result &= _v0.IsValid() && _v1.IsValid(); - _result &= _result && Math::ChangeInPct(_v1[_mode], _v0[_mode], _hundreds) < _pct; - return _result; - } - - /** - * Checks if values are increasing. - * - * @param int _rows - * Numbers of rows to check. - * @param int _mode - * Indicator index mode to check. - * @param int _shift - * Shift which is the final value to take into the account. - * - * @return - * Returns true when values are increasing. - */ - bool IsIncreasing(int _rows = 1, int _mode = 0, int _shift = 0) { - bool _result = true; - for (int i = _shift + _rows - 1; i >= _shift && _result; i--) { - IndicatorDataEntry _entry_curr = GetEntry(i); - IndicatorDataEntry _entry_prev = GetEntry(i + 1); - _result &= _entry_curr.IsValid() && _entry_prev.IsValid() && _entry_curr[_mode] > _entry_prev[_mode]; - if (!_result) { - break; - } - } - return _result; - } - - /** - * Checks if value increased by the given percentage value. - * - * @param int _pct - * Percentage value to use for comparison. - * @param int _mode - * Indicator index mode to use. - * @param int _shift - * Indicator value shift to use. - * @param int _count - * Count of bars to compare change backward. - * @param int _hundreds - * When true, use percentage in hundreds, otherwise 1 is 100%. - * - * @return - * Returns true when value increased. - */ - bool IsIncByPct(float _pct, int _mode = 0, int _shift = 0, int _count = 1, bool _hundreds = true) { - bool _result = true; - IndicatorDataEntry _v0 = GetEntry(_shift); - IndicatorDataEntry _v1 = GetEntry(_shift + _count); - _result &= _v0.IsValid() && _v1.IsValid(); - _result &= _result && Math::ChangeInPct(_v1[_mode], _v0[_mode], _hundreds) > _pct; - return _result; - } - /* Getters */ /** @@ -596,26 +316,6 @@ class IndicatorBase : public Chart { int GetDataSourceMode() { return indi_src_mode; } - /** - * Gets indicator's symbol. - */ - string GetSymbol() { return Get(CHART_PARAM_SYMBOL); } - - /** - * Gets indicator's time-frame. - */ - ENUM_TIMEFRAMES GetTf() { return Get(CHART_PARAM_TF); } - - /** - * Gets indicator's signals. - * - * When indicator values are not valid, returns empty signals. - */ - virtual IndicatorSignal GetSignals(int _count = 3, int _shift = 0, int _mode1 = 0, int _mode2 = 0) { - IndicatorSignal _signal; - return _signal; - } - /** * Get indicator type. */ @@ -703,9 +403,9 @@ class IndicatorBase : public Chart { } template - T GetValue(int _shift = 0, int _mode = 0) { + T GetValue(int _index = 0, int _mode = 0) { T _out; - GetEntryValue(_shift, _mode).Get(_out); + GetEntryValue(_index, _mode).Get(_out); return _out; } @@ -715,8 +415,8 @@ class IndicatorBase : public Chart { * Note: Remember to check if shift exists by HasValidEntry(shift). */ template - bool GetValues(int _shift, T& _out1, T& _out2) { - IndicatorDataEntry _entry = GetEntry(_shift); + bool GetValues(int _index, T& _out1, T& _out2) { + IndicatorDataEntry _entry = GetEntry(_index); _out1 = _entry.values[0]; _out2 = _entry.values[1]; bool _result = GetLastError() != 4401; @@ -725,8 +425,8 @@ class IndicatorBase : public Chart { } template - bool GetValues(int _shift, T& _out1, T& _out2, T& _out3) { - IndicatorDataEntry _entry = GetEntry(_shift); + bool GetValues(int _index, T& _out1, T& _out2, T& _out3) { + IndicatorDataEntry _entry = GetEntry(_index); _out1 = _entry.values[0]; _out2 = _entry.values[1]; _out3 = _entry.values[2]; @@ -736,8 +436,8 @@ class IndicatorBase : public Chart { } template - bool GetValues(int _shift, T& _out1, T& _out2, T& _out3, T& _out4) { - IndicatorDataEntry _entry = GetEntry(_shift); + bool GetValues(int _index, T& _out1, T& _out2, T& _out3, T& _out4) { + IndicatorDataEntry _entry = GetEntry(_index); _out1 = _entry.values[0]; _out2 = _entry.values[1]; _out3 = _entry.values[2]; @@ -756,7 +456,7 @@ class IndicatorBase : public Chart { /** * Returns the indicator's struct value. */ - virtual IndicatorDataEntry GetEntry(int _shift = -1) = NULL; + virtual IndicatorDataEntry GetEntry(int _index = -1) = NULL; /** * Alters indicator's struct value. @@ -764,14 +464,14 @@ class IndicatorBase : public Chart { * This method allows user to modify the struct entry before it's added to cache. * This method is called on GetEntry() right after values are set. */ - virtual void GetEntryAlter(IndicatorDataEntry& _entry, int _shift = -1) = NULL; + virtual void GetEntryAlter(IndicatorDataEntry& _entry, int _index = -1) = NULL; // virtual ENUM_IDATA_VALUE_RANGE GetIDataValueRange() = NULL; /** * Returns the indicator's entry value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) = NULL; + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _index = -1) = NULL; /** * Returns indicator value for a given shift and mode. @@ -782,9 +482,9 @@ class IndicatorBase : public Chart { * Checks whether indicator has a valid value for a given shift. */ /* - virtual bool HasValidEntry(int _shift = 0) { + virtual bool HasValidEntry(int _index = 0) { unsigned int position; - long bar_time = GetBarTime(_shift); + long bar_time = GetBarTime(_index); return bar_time > 0 && idata.KeyExists(bar_time, position) ? idata.GetByPos(position).IsValid() : false; } */ @@ -810,8 +510,8 @@ class IndicatorBase : public Chart { /** * Returns the indicator's value in plain format. */ - virtual string ToString(int _shift = 0) { - IndicatorDataEntry _entry = GetEntry(_shift); + virtual string ToString(int _index = 0) { + IndicatorDataEntry _entry = GetEntry(_index); int _serializer_flags = SERIALIZER_FLAG_SKIP_HIDDEN | SERIALIZER_FLAG_INCLUDE_DEFAULT | SERIALIZER_FLAG_INCLUDE_DYNAMIC | SERIALIZER_FLAG_INCLUDE_FEATURE; @@ -846,6 +546,18 @@ class IndicatorBase : public Chart { // Assuming all entries are calculated (even if have invalid values). return _bars; } + + /* Methods to get rid of */ + + /** + * Gets indicator's symbol. + */ + string GetSymbol() { return Get(CHART_PARAM_SYMBOL); } + + /** + * Gets indicator's time-frame. + */ + ENUM_TIMEFRAMES GetTf() { return Get(CHART_PARAM_TF); } }; /** From 9f9c620ff57509bd159cbc07a0f5708ea7987246 Mon Sep 17 00:00:00 2001 From: kenorb Date: Tue, 9 Nov 2021 23:05:56 +0000 Subject: [PATCH 10/77] IndicatorTick: Adds SetTick() --- Indicator/IndicatorTick.h | 46 +++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/Indicator/IndicatorTick.h b/Indicator/IndicatorTick.h index 04c0fb3f7..f97b2c43a 100644 --- a/Indicator/IndicatorTick.h +++ b/Indicator/IndicatorTick.h @@ -153,20 +153,24 @@ class IndicatorTick : public IndicatorBase { return GetEntry(_ishift)[_mode]; } + /* Setters */ + /** - * Function should return true if resize can be made, or false to overwrite current slot. + * Sets a tick struct with price values. + * + * @see: MqlTick. */ - static bool IndicatorTickOverflowListener(ENUM_DICT_OVERFLOW_REASON _reason, int _size, int _num_conflicts) { - switch (_reason) { - case DICT_OVERFLOW_REASON_FULL: - // We allow resize if dictionary size is less than 86400 slots. - return _size < 86400; - case DICT_OVERFLOW_REASON_TOO_MANY_CONFLICTS: - default: - // When there is too many conflicts, we just reject doing resize, so first conflicting slot will be reused. - break; - } - return false; + void SetTick(MqlTick& _tick, int _timestamp = 0) { + IndicatorDataEntry _entry(itparams.GetMaxModes()); + _entry.timestamp = _timestamp; + _entry.values[0] = _tick.bid; + _entry.values[1] = _tick.ask; +#ifdef __MQL4__ + _entry.values[2] = _tick.volume; +#else + _entry.values[2] = _tick.volume_real; +#endif + itdata.Add(_entry, _timestamp); } /** @@ -235,6 +239,24 @@ class IndicatorTick : public IndicatorBase { } return _result; } + + /* Callback methods */ + + /** + * Function should return true if resize can be made, or false to overwrite current slot. + */ + static bool IndicatorTickOverflowListener(ENUM_DICT_OVERFLOW_REASON _reason, int _size, int _num_conflicts) { + switch (_reason) { + case DICT_OVERFLOW_REASON_FULL: + // We allow resize if dictionary size is less than 86400 slots. + return _size < 86400; + case DICT_OVERFLOW_REASON_TOO_MANY_CONFLICTS: + default: + // When there is too many conflicts, we just reject doing resize, so first conflicting slot will be reused. + break; + } + return false; + } }; #endif From 4115a08b1265d303a922cd22457dbec4873d8ea1 Mon Sep 17 00:00:00 2001 From: kenorb Date: Tue, 9 Nov 2021 23:28:13 +0000 Subject: [PATCH 11/77] IndicatorTick: Implements test --- .github/workflows/test-indicator.yml | 65 ++++++++++++++++++++++++++ Indicator/IndicatorTick.h | 2 +- Indicator/tests/IndicatorTick.test.mq5 | 52 ++++++++++----------- Indicators/Tick/Indi_TickMt.mqh | 1 + 4 files changed, 92 insertions(+), 28 deletions(-) create mode 100644 .github/workflows/test-indicator.yml diff --git a/.github/workflows/test-indicator.yml b/.github/workflows/test-indicator.yml new file mode 100644 index 000000000..0e0069949 --- /dev/null +++ b/.github/workflows/test-indicator.yml @@ -0,0 +1,65 @@ +--- +name: Test Indicator + +# yamllint disable-line rule:truthy +on: + pull_request: + paths: + - 'Indicator**' + - 'Indicator/**' + - '.github/workflows/test-indicator.yml' + push: + paths: + - 'Indicator**' + - 'Indicator/**' + - '.github/workflows/test-indicator.yml' + +jobs: + + Compile: + runs-on: windows-latest + steps: + - uses: actions/checkout@v2 + - name: Compile + uses: fx31337/mql-compile-action@master + with: + init-platform: true + path: 'Indicator/tests' + verbose: true + - name: Print compiled files + run: '(Get-ChildItem -Recurse -Path . -Include *.ex[45]).fullname' + shell: powershell + - name: Upload artifacts (MQL4) + uses: actions/upload-artifact@v2 + with: + name: files-ex4 + path: '**/*.ex4' + - name: Upload artifacts (MQL5) + uses: actions/upload-artifact@v2 + with: + name: files-ex5 + path: '**/*.ex5' + + Indicator-Tests-MQL4: + defaults: + run: + shell: bash + working-directory: Indicator/tests + needs: Compile + runs-on: ubuntu-latest + strategy: + matrix: + test: + - IndicatorTick.test + steps: + - uses: actions/download-artifact@v2 + with: + name: files-ex4 + - name: Run ${{ matrix.test }} + uses: fx31337/mql-tester-action@master + with: + BtDays: 4-8 + BtMonths: 1 + BtYears: 2020 + TestExpert: ${{ matrix.test }} + timeout-minutes: 10 diff --git a/Indicator/IndicatorTick.h b/Indicator/IndicatorTick.h index f97b2c43a..f64418f5c 100644 --- a/Indicator/IndicatorTick.h +++ b/Indicator/IndicatorTick.h @@ -160,7 +160,7 @@ class IndicatorTick : public IndicatorBase { * * @see: MqlTick. */ - void SetTick(MqlTick& _tick, int _timestamp = 0) { + void SetTick(MqlTick& _tick, long _timestamp = 0) { IndicatorDataEntry _entry(itparams.GetMaxModes()); _entry.timestamp = _timestamp; _entry.values[0] = _tick.bid; diff --git a/Indicator/tests/IndicatorTick.test.mq5 b/Indicator/tests/IndicatorTick.test.mq5 index 495154af3..07bab9c74 100644 --- a/Indicator/tests/IndicatorTick.test.mq5 +++ b/Indicator/tests/IndicatorTick.test.mq5 @@ -28,37 +28,35 @@ #include "../../Test.mqh" #include "../IndicatorTick.h" +// Structs. +struct IndicatorTickDummyParams : IndicatorParams { + IndicatorTickDummyParams() : IndicatorParams(INDI_TICK, 3, TYPE_DOUBLE) {} +}; + +/** + * Price Indicator. + */ +class IndicatorTickDummy : public IndicatorTick { + public: + IndicatorTickDummy(string _symbol, int _shift = 0, string _name = "") + : IndicatorTick(INDI_TICK, _symbol, _shift, _name) { + SetSymbol(_symbol); + } +}; + /** * Implements OnInit(). */ int OnInit() { - /* @fixme - // Initialize. - IndicatorParams iparams(INDI_NONE, TYPE_INT, 10); - Indicator *in = new Indicator(iparams, NULL); - // Check empty values. - assertTrueOrFail(in.GetBufferSize() == 10, "Wrong buffer size!"); - assertTrueOrFail(in.GetEmpty().double_value == 0.0, "Wrong empty double value!"); - assertTrueOrFail(in.GetEmpty().integer_value == 0, "Wrong empty integer value!"); - // Check dynamic allocation. - MqlParam entry; - entry.integer_value = 1; - for (uint i = 0; i < in.GetBufferSize() * 2; i++) { - in.AddValue(entry); - Print("Index ", i, ": Curr: ", in.GetValue(0).integer_value, "; Prev: ", in.GetValue(1).integer_value); - assertTrueOrFail(in.GetValue(0).integer_value == entry.integer_value, - StringFormat("Wrong latest value (%d <> %d)!", - in.GetValue(0).integer_value, - entry.integer_value)); - assertTrueOrFail(in.GetValue(1).integer_value == entry.integer_value - 1, - StringFormat("Wrong previous value (%d <> %d)!", - in.GetValue(1).integer_value, - entry.integer_value - 1)); - entry.integer_value++; + IndicatorTickDummy _indi_tick(_Symbol); + long _time = 1; + for (double _price = 0.1; _price <= 2.0; _price += 0.1) { + MqlTick _tick; + _tick.time = (datetime)_time++; + _tick.ask = _price; + _tick.bid = _price; + _indi_tick.SetTick(_tick, _tick.time); } - Print(in.ToString()); - // Clean up. - delete in; - */ + // Print(_indi_tick.ToString()); return (INIT_SUCCEEDED); } diff --git a/Indicators/Tick/Indi_TickMt.mqh b/Indicators/Tick/Indi_TickMt.mqh index a5d1b0e8e..01d7dd2f7 100644 --- a/Indicators/Tick/Indi_TickMt.mqh +++ b/Indicators/Tick/Indi_TickMt.mqh @@ -29,6 +29,7 @@ struct IndiTickMtParams : IndicatorParams { // Struct constructor. IndiTickMtParams(string _symbol = NULL, int _shift = 0) : IndicatorParams(INDI_TICK, 3, TYPE_DOUBLE) { SetShift(_shift); + SetSymbol(_symbol); }; IndiTickMtParams(IndiTickMtParams &_params, ENUM_TIMEFRAMES _tf) { THIS_REF = _params; From ef95f6f12734dde0c5e525fa496f285b981ec8c0 Mon Sep 17 00:00:00 2001 From: kenorb Date: Tue, 9 Nov 2021 23:40:25 +0000 Subject: [PATCH 12/77] Indicator: Adds IndicatorCandle class --- .github/workflows/test-indicator.yml | 1 + Indicator/IndicatorCandle.h | 223 +++++++++++++++++++++++ Indicator/tests/IndicatorCandle.test.mq4 | 28 +++ Indicator/tests/IndicatorCandle.test.mq5 | 37 ++++ 4 files changed, 289 insertions(+) create mode 100644 Indicator/IndicatorCandle.h create mode 100644 Indicator/tests/IndicatorCandle.test.mq4 create mode 100644 Indicator/tests/IndicatorCandle.test.mq5 diff --git a/.github/workflows/test-indicator.yml b/.github/workflows/test-indicator.yml index 0e0069949..66f4b9673 100644 --- a/.github/workflows/test-indicator.yml +++ b/.github/workflows/test-indicator.yml @@ -50,6 +50,7 @@ jobs: strategy: matrix: test: + - IndicatorCandle.test - IndicatorTick.test steps: - uses: actions/download-artifact@v2 diff --git a/Indicator/IndicatorCandle.h b/Indicator/IndicatorCandle.h new file mode 100644 index 000000000..b2ff1abca --- /dev/null +++ b/Indicator/IndicatorCandle.h @@ -0,0 +1,223 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2021, EA31337 Ltd | +//| https://github.com/EA31337 | +//+------------------------------------------------------------------+ + +/* + * This file is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +// Ignore processing of this file if already included. +#ifndef INDICATOR_CANDLE_MQH +#define INDICATOR_CANDLE_MQH + +// Includes. +#include "../IndicatorBase.h" + +/** + * Class to deal with candle indicators. + */ +template +class IndicatorCandle : public IndicatorBase { + protected: + BufferStruct icdata; + TS icparams; + + protected: + /* Protected methods */ + + /** + * Initialize class. + * + * Called on constructor. + */ + void Init() { + itdata.AddFlags(DICT_FLAG_FILL_HOLES_UNSORTED); + itdata.SetOverflowListener(IndicatorCandleOverflowListener, 10); + } + + public: + /* Special methods */ + + /** + * Class constructor. + */ + IndicatorCandle(const TS& _icdata, IndicatorBase* _indi_src = NULL, int _indi_mode = 0) { + icdata = _icdata; + if (_indi_src != NULL) { + SetDataSource(_indi_src, _indi_mode); + } + Init(); + } + IndicatorCandle(ENUM_INDICATOR_TYPE _itype, string _symbol, int _shift = 0, string _name = "") { + itparams.SetIndicatorType(_itype); + itparams.SetShift(_shift); + Init(); + } + + /* Virtual method implementations */ + + /** + * Returns the indicator's data entry. + * + * @see: IndicatorDataEntry. + * + * @return + * Returns IndicatorDataEntry struct filled with indicator values. + */ + IndicatorDataEntry GetEntry(int _timestamp = 0) { + ResetLastError(); + IndicatorDataEntry _entry = itdata.GetByKey(_timestamp); + if (!_entry.IsValid() && !_entry.CheckFlag(INDI_ENTRY_FLAG_INSUFFICIENT_DATA)) { + _entry.Resize(itparams.GetMaxModes()); + _entry.timestamp = _timestamp; + for (int _mode = 0; _mode < (int)itparams.GetMaxModes(); _mode++) { + switch (itparams.GetDataValueType()) { + case TYPE_BOOL: + case TYPE_CHAR: + case TYPE_INT: + _entry.values[_mode] = GetValue(_mode, _timestamp); + break; + case TYPE_LONG: + _entry.values[_mode] = GetValue(_mode, _timestamp); + break; + case TYPE_UINT: + _entry.values[_mode] = GetValue(_mode, _timestamp); + break; + case TYPE_ULONG: + _entry.values[_mode] = GetValue(_mode, _timestamp); + break; + case TYPE_DOUBLE: + _entry.values[_mode] = GetValue(_mode, _timestamp); + break; + case TYPE_FLOAT: + _entry.values[_mode] = GetValue(_mode, _timestamp); + break; + case TYPE_STRING: + case TYPE_UCHAR: + default: + SetUserError(ERR_INVALID_PARAMETER); + break; + } + } + GetEntryAlter(_entry, _timestamp); + _entry.SetFlag(INDI_ENTRY_FLAG_IS_VALID, IsValidEntry(_entry)); + if (_entry.IsValid()) { + itdata.Add(_entry, _timestamp); + istate.is_changed = false; + istate.is_ready = true; + } else { + _entry.AddFlags(INDI_ENTRY_FLAG_INSUFFICIENT_DATA); + } + } + if (_LastError != ERR_NO_ERROR) { + istate.is_ready = false; + ResetLastError(); + } + return _entry; + } + + /** + * Alters indicator's struct value. + * + * This method allows user to modify the struct entry before it's added to cache. + * This method is called on GetEntry() right after values are set. + */ + virtual void GetEntryAlter(IndicatorDataEntry& _entry, int _timestamp = -1) { + _entry.AddFlags(_entry.GetDataTypeFlags(itparams.GetDataValueType())); + }; + + /** + * Returns the indicator's entry value for the given shift and mode. + * + * @see: DataParamEntry. + * + * @return + * Returns DataParamEntry struct filled with a single value. + */ + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + int _ishift = _shift >= 0 ? _shift : icparams.GetShift(); + return GetEntry(_ishift)[_mode]; + } + + /** + * Function should return true if resize can be made, or false to overwrite current slot. + */ + static bool IndicatorCandleOverflowListener(ENUM_DICT_OVERFLOW_REASON _reason, int _size, int _num_conflicts) const { + switch (_reason) { + case DICT_OVERFLOW_REASON_FULL: + // We allow resize if dictionary size is less than 86400 slots. + return _size < 86400; + case DICT_OVERFLOW_REASON_TOO_MANY_CONFLICTS: + default: + // When there is too many conflicts, we just reject doing resize, so first conflicting slot will be reused. + break; + } + return false; + } + + /** + * Sets indicator data source. + */ + void SetDataSource(IndicatorBase* _indi, int _input_mode = 0) { + indi_src = _indi; + itparams.SetDataSource(-1, _input_mode); + } + + /* Virtual methods */ + + /** + * Checks if indicator entry is valid. + * + * @return + * Returns true if entry is valid (has valid values), otherwise false. + */ + virtual bool IsValidEntry(IndicatorDataEntry& _entry) { + bool _result = true; + _result &= _entry.timestamp > 0; + _result &= _entry.GetSize() > 0; + if (_entry.CheckFlags(INDI_ENTRY_FLAG_IS_REAL)) { + if (_entry.CheckFlags(INDI_ENTRY_FLAG_IS_DOUBLED)) { + _result &= !_entry.HasValue(DBL_MAX); + _result &= !_entry.HasValue(NULL); + } else { + _result &= !_entry.HasValue(FLT_MAX); + _result &= !_entry.HasValue(NULL); + } + } else { + if (_entry.CheckFlags(INDI_ENTRY_FLAG_IS_UNSIGNED)) { + if (_entry.CheckFlags(INDI_ENTRY_FLAG_IS_DOUBLED)) { + _result &= !_entry.HasValue(ULONG_MAX); + _result &= !_entry.HasValue(NULL); + } else { + _result &= !_entry.HasValue(UINT_MAX); + _result &= !_entry.HasValue(NULL); + } + } else { + if (_entry.CheckFlags(INDI_ENTRY_FLAG_IS_DOUBLED)) { + _result &= !_entry.HasValue(LONG_MAX); + _result &= !_entry.HasValue(NULL); + } else { + _result &= !_entry.HasValue(INT_MAX); + _result &= !_entry.HasValue(NULL); + } + } + } + return _result; + } +}; + +#endif diff --git a/Indicator/tests/IndicatorCandle.test.mq4 b/Indicator/tests/IndicatorCandle.test.mq4 new file mode 100644 index 000000000..93a0098bb --- /dev/null +++ b/Indicator/tests/IndicatorCandle.test.mq4 @@ -0,0 +1,28 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2021, EA31337 Ltd | +//| https://github.com/EA31337 | +//+------------------------------------------------------------------+ + +/* + * This file is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * @file + * Test functionality of IndicatorCandle class. + */ + +// Includes. +#include "IndicatorCandle.test.mq5" diff --git a/Indicator/tests/IndicatorCandle.test.mq5 b/Indicator/tests/IndicatorCandle.test.mq5 new file mode 100644 index 000000000..1d3f5c0d5 --- /dev/null +++ b/Indicator/tests/IndicatorCandle.test.mq5 @@ -0,0 +1,37 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2021, EA31337 Ltd | +//| https://github.com/EA31337 | +//+------------------------------------------------------------------+ + +/* + * This file is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * @file + * Test functionality of IndicatorCandle class. + */ + +// Includes. +#include "../../Test.mqh" +#include "../IndicatorCandle.h" + +/** + * Implements OnInit(). + */ +int OnInit() { + // @todo + return (INIT_SUCCEEDED); +} From cc388699f2df303e70393e333e53e691fc5b28b0 Mon Sep 17 00:00:00 2001 From: kenorb Date: Wed, 10 Nov 2021 00:20:24 +0000 Subject: [PATCH 13/77] Indicator: Adds IndicatorTf class --- .github/workflows/test-indicator.yml | 1 + Indicator/IndicatorCandle.h | 38 ++++++++------- Indicator/IndicatorTf.h | 69 ++++++++++++++++++++++++++++ Indicator/IndicatorTf.struct.h | 44 ++++++++++++++++++ Indicator/IndicatorTick.h | 9 +++- Indicator/tests/IndicatorTf.test.mq4 | 28 +++++++++++ Indicator/tests/IndicatorTf.test.mq5 | 37 +++++++++++++++ 7 files changed, 207 insertions(+), 19 deletions(-) create mode 100644 Indicator/IndicatorTf.h create mode 100644 Indicator/IndicatorTf.struct.h create mode 100644 Indicator/tests/IndicatorTf.test.mq4 create mode 100644 Indicator/tests/IndicatorTf.test.mq5 diff --git a/.github/workflows/test-indicator.yml b/.github/workflows/test-indicator.yml index 66f4b9673..87b68aa41 100644 --- a/.github/workflows/test-indicator.yml +++ b/.github/workflows/test-indicator.yml @@ -51,6 +51,7 @@ jobs: matrix: test: - IndicatorCandle.test + - IndicatorTf.test - IndicatorTick.test steps: - uses: actions/download-artifact@v2 diff --git a/Indicator/IndicatorCandle.h b/Indicator/IndicatorCandle.h index b2ff1abca..4b00672ac 100644 --- a/Indicator/IndicatorCandle.h +++ b/Indicator/IndicatorCandle.h @@ -21,8 +21,13 @@ */ // Ignore processing of this file if already included. -#ifndef INDICATOR_CANDLE_MQH -#define INDICATOR_CANDLE_MQH +#ifndef INDICATOR_CANDLE_H +#define INDICATOR_CANDLE_H + +#ifndef __MQL__ +// Allows the preprocessor to include a header file when it is needed. +#pragma once +#endif // Includes. #include "../IndicatorBase.h" @@ -45,8 +50,8 @@ class IndicatorCandle : public IndicatorBase { * Called on constructor. */ void Init() { - itdata.AddFlags(DICT_FLAG_FILL_HOLES_UNSORTED); - itdata.SetOverflowListener(IndicatorCandleOverflowListener, 10); + icdata.AddFlags(DICT_FLAG_FILL_HOLES_UNSORTED); + icdata.SetOverflowListener(IndicatorCandleOverflowListener, 10); } public: @@ -55,16 +60,15 @@ class IndicatorCandle : public IndicatorBase { /** * Class constructor. */ - IndicatorCandle(const TS& _icdata, IndicatorBase* _indi_src = NULL, int _indi_mode = 0) { - icdata = _icdata; + IndicatorCandle(const TS& _icparams, IndicatorBase* _indi_src = NULL, int _indi_mode = 0) : icparams(_icparams) { if (_indi_src != NULL) { SetDataSource(_indi_src, _indi_mode); } Init(); } - IndicatorCandle(ENUM_INDICATOR_TYPE _itype, string _symbol, int _shift = 0, string _name = "") { - itparams.SetIndicatorType(_itype); - itparams.SetShift(_shift); + IndicatorCandle(ENUM_INDICATOR_TYPE _itype = INDI_CANDLE, int _shift = 0, string _name = "") { + icparams.SetIndicatorType(_itype); + icparams.SetShift(_shift); Init(); } @@ -80,12 +84,12 @@ class IndicatorCandle : public IndicatorBase { */ IndicatorDataEntry GetEntry(int _timestamp = 0) { ResetLastError(); - IndicatorDataEntry _entry = itdata.GetByKey(_timestamp); + IndicatorDataEntry _entry = icdata.GetByKey(_timestamp); if (!_entry.IsValid() && !_entry.CheckFlag(INDI_ENTRY_FLAG_INSUFFICIENT_DATA)) { - _entry.Resize(itparams.GetMaxModes()); + _entry.Resize(icparams.GetMaxModes()); _entry.timestamp = _timestamp; - for (int _mode = 0; _mode < (int)itparams.GetMaxModes(); _mode++) { - switch (itparams.GetDataValueType()) { + for (int _mode = 0; _mode < (int)icparams.GetMaxModes(); _mode++) { + switch (icparams.GetDataValueType()) { case TYPE_BOOL: case TYPE_CHAR: case TYPE_INT: @@ -116,7 +120,7 @@ class IndicatorCandle : public IndicatorBase { GetEntryAlter(_entry, _timestamp); _entry.SetFlag(INDI_ENTRY_FLAG_IS_VALID, IsValidEntry(_entry)); if (_entry.IsValid()) { - itdata.Add(_entry, _timestamp); + icdata.Add(_entry, _timestamp); istate.is_changed = false; istate.is_ready = true; } else { @@ -137,7 +141,7 @@ class IndicatorCandle : public IndicatorBase { * This method is called on GetEntry() right after values are set. */ virtual void GetEntryAlter(IndicatorDataEntry& _entry, int _timestamp = -1) { - _entry.AddFlags(_entry.GetDataTypeFlags(itparams.GetDataValueType())); + _entry.AddFlags(_entry.GetDataTypeFlags(icparams.GetDataValueType())); }; /** @@ -156,7 +160,7 @@ class IndicatorCandle : public IndicatorBase { /** * Function should return true if resize can be made, or false to overwrite current slot. */ - static bool IndicatorCandleOverflowListener(ENUM_DICT_OVERFLOW_REASON _reason, int _size, int _num_conflicts) const { + static bool IndicatorCandleOverflowListener(ENUM_DICT_OVERFLOW_REASON _reason, int _size, int _num_conflicts) { switch (_reason) { case DICT_OVERFLOW_REASON_FULL: // We allow resize if dictionary size is less than 86400 slots. @@ -174,7 +178,7 @@ class IndicatorCandle : public IndicatorBase { */ void SetDataSource(IndicatorBase* _indi, int _input_mode = 0) { indi_src = _indi; - itparams.SetDataSource(-1, _input_mode); + icparams.SetDataSource(-1, _input_mode); } /* Virtual methods */ diff --git a/Indicator/IndicatorTf.h b/Indicator/IndicatorTf.h new file mode 100644 index 000000000..b51828ce5 --- /dev/null +++ b/Indicator/IndicatorTf.h @@ -0,0 +1,69 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2021, EA31337 Ltd | +//| https://github.com/EA31337 | +//+------------------------------------------------------------------+ + +/* + * This file is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +// Ignore processing of this file if already included. +#ifndef INDICATOR_TF_H +#define INDICATOR_TF_H + +#ifndef __MQL__ +// Allows the preprocessor to include a header file when it is needed. +#pragma once +#endif + +// Includes. +#include "IndicatorCandle.h" +#include "IndicatorTf.struct.h" + +/** + * Class to deal with candle indicators. + */ +class IndicatorTf : public IndicatorCandle { + protected: + /* Protected methods */ + + /** + * Initialize class. + * + * Called on constructor. + */ + void Init() {} + + public: + /* Special methods */ + + /** + * Class constructor. + */ + IndicatorTf(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) { Init(); } + + /** + * Class constructor. + */ + IndicatorTf(ENUM_TIMEFRAMES_INDEX _tfi = 0) { Init(); } + + /** + * Class constructor with parameters. + */ + IndicatorTf(IndicatorTfParams &_params) : IndicatorCandle(_params) { Init(); } +}; + +#endif diff --git a/Indicator/IndicatorTf.struct.h b/Indicator/IndicatorTf.struct.h new file mode 100644 index 000000000..8e82a67bd --- /dev/null +++ b/Indicator/IndicatorTf.struct.h @@ -0,0 +1,44 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2021, EA31337 Ltd | +//| https://github.com/EA31337 | +//+------------------------------------------------------------------+ + +/* + * This file is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +/** + * @file + * Includes IndicatorTf's structs. + */ + +#ifndef __MQL__ +// Allows the preprocessor to include a header file when it is needed. +#pragma once +#endif + +/* Structure for IndicatorTf class parameters. */ +struct IndicatorTfParams : IndicatorParams { + // Struct constructor. + IndicatorTfParams() {} + // Copy constructor. + IndicatorTfParams(const IndicatorTfParams &_params, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) { + THIS_REF = _params; + if (_tf != PERIOD_CURRENT) { + tf.SetTf(_tf); + } + } +}; diff --git a/Indicator/IndicatorTick.h b/Indicator/IndicatorTick.h index f64418f5c..bf1487a03 100644 --- a/Indicator/IndicatorTick.h +++ b/Indicator/IndicatorTick.h @@ -21,8 +21,13 @@ */ // Ignore processing of this file if already included. -#ifndef INDICATOR_TICK_MQH -#define INDICATOR_TICK_MQH +#ifndef INDICATOR_TICK_H +#define INDICATOR_TICK_H + +#ifndef __MQL__ +// Allows the preprocessor to include a header file when it is needed. +#pragma once +#endif // Includes. #include "../IndicatorBase.h" diff --git a/Indicator/tests/IndicatorTf.test.mq4 b/Indicator/tests/IndicatorTf.test.mq4 new file mode 100644 index 000000000..360408073 --- /dev/null +++ b/Indicator/tests/IndicatorTf.test.mq4 @@ -0,0 +1,28 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2021, EA31337 Ltd | +//| https://github.com/EA31337 | +//+------------------------------------------------------------------+ + +/* + * This file is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * @file + * Test functionality of IndicatorTf class. + */ + +// Includes. +#include "IndicatorTf.test.mq5" diff --git a/Indicator/tests/IndicatorTf.test.mq5 b/Indicator/tests/IndicatorTf.test.mq5 new file mode 100644 index 000000000..5c68d79a2 --- /dev/null +++ b/Indicator/tests/IndicatorTf.test.mq5 @@ -0,0 +1,37 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2021, EA31337 Ltd | +//| https://github.com/EA31337 | +//+------------------------------------------------------------------+ + +/* + * This file is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * @file + * Test functionality of IndicatorTf class. + */ + +// Includes. +#include "../../Test.mqh" +#include "../IndicatorTf.h" + +/** + * Implements OnInit(). + */ +int OnInit() { + // @todo + return (INIT_SUCCEEDED); +} From 4fbbc910c8aeabc05dbae335e5afa5abb39d5963 Mon Sep 17 00:00:00 2001 From: kenorb Date: Thu, 11 Nov 2021 00:21:36 +0000 Subject: [PATCH 14/77] Indicator: Adds README.md with info about indicators --- Indicator/README.md | 54 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 Indicator/README.md diff --git a/Indicator/README.md b/Indicator/README.md new file mode 100644 index 000000000..add1d2685 --- /dev/null +++ b/Indicator/README.md @@ -0,0 +1,54 @@ +# Indicator + +Indicator classes are intended for implementation of technical indicators. + +They can help with storing and accessing values and indicator parameters. + +## `IndicatorBase` + +An abstract class for all type of indicators (a base class). + +## `Indicator` + +An abstract class (subclass of `IndicatorBase`) to implement all type of indicators. + +It implements structure for storing input parameters +and buffer for accessing cached values by a given timestamp. + +## `IndicatorCandle` + +An abstract class (subclass of `IndicatorBase`) to implement candle indicators. + +It aims at managing prices by grouping them into OHLC chart candles. + +## `IndicatorRenko` + +(to be added) + +An abstract class (subclass of `IndicatorCandle`) to implement Renko indicators. + +It aims at managing prices by splitting them based solely on price movements. + +It can accept `IndicatorTick` as a data source. + +## `IndicatorTf` + +An abstract class (subclass of `IndicatorCandle`) +to implement timeframe indicators. + +It aims at storing prices by grouping them based on standardized time intervals +(e.g. M1, M2, M5). + +An instance has information about timeframe. + +Information about symbol can be accessed through the tick indicator. + +It can accept `IndicatorTick` as a data source. + +## `IndicatorTick` + +An abstract class (subclass of `IndicatorBase`) to implement tick indicators. + +It aims at managing bid and ask prices and can be used as data source. + +An instance has information about symbol, but it doesn't have timeframe. From 1c9a5eb05269e6077893f33058e6549078284605 Mon Sep 17 00:00:00 2001 From: kenorb Date: Thu, 11 Nov 2021 13:08:54 +0000 Subject: [PATCH 15/77] Adds CandleOHLC and CandleTOHLC structs --- Candle.struct.h | 260 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 260 insertions(+) create mode 100644 Candle.struct.h diff --git a/Candle.struct.h b/Candle.struct.h new file mode 100644 index 000000000..2fea358e6 --- /dev/null +++ b/Candle.struct.h @@ -0,0 +1,260 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2021, EA31337 Ltd | +//| https://github.com/EA31337 | +//+------------------------------------------------------------------+ + +/* + * This file is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +/** + * @file + * Includes Bar's structs. + */ + +#ifndef __MQL__ +// Allows the preprocessor to include a header file when it is needed. +#pragma once +#endif + +// Forward class declaration. +class Serializer; + +// Includes. +#include "Bar.enum.h" +#include "Chart.enum.h" +#include "ISerializable.h" +#include "Serializer.enum.h" +#include "SerializerNode.enum.h" +#include "Std.h" + +/* Structore for storing OHLC values. */ +template +struct CandleOHLC +#ifndef __MQL__ + : public ISerializable +#endif +{ + T open, high, low, close; + CandleOHLC(T _open = 0, T _high = 0, T _low = 0, T _close = 0) : open(_open), high(_high), low(_low), close(_close) {} + CandleOHLC(ARRAY_REF(T, _prices)) { + int _size = ArraySize(_prices); + close = _prices[0]; + open = _prices[_size - 1]; + high = fmax(close, open); + low = fmin(close, open); + for (int i = 0; i < _size; i++) { + high = fmax(high, _prices[i]); + low = fmin(low, _prices[i]); + } + } + // Struct methods. + // Getters + bool GetPivots(ENUM_PP_TYPE _type, float &_pp, float &_r1, float &_r2, float &_r3, float &_r4, float &_s1, float &_s2, + float &_s3, float &_s4) { + float _range = GetRange(); + switch (_type) { + case PP_CAMARILLA: + // A set of eight very probable levels which resemble support and resistance values for a current trend. + _pp = GetPivot(); + _r1 = (float)(close + _range * 1.1 / 12); + _r2 = (float)(close + _range * 1.1 / 6); + _r3 = (float)(close + _range * 1.1 / 4); + _r4 = (float)(close + _range * 1.1 / 2); + _s1 = (float)(close - _range * 1.1 / 12); + _s2 = (float)(close - _range * 1.1 / 6); + _s3 = (float)(close - _range * 1.1 / 4); + _s4 = (float)(close - _range * 1.1 / 2); + break; + case PP_CLASSIC: + _pp = GetPivot(); + _r1 = (2 * _pp) - low; // R1 = (H - L) * 1.1 / 12 + C (1.0833) + _r2 = _pp + _range; // R2 = (H - L) * 1.1 / 6 + C (1.1666) + _r3 = _pp + _range * 2; // R3 = (H - L) * 1.1 / 4 + C (1.25) + _r4 = _pp + _range * 3; // R4 = (H - L) * 1.1 / 2 + C (1.5) + _s1 = (2 * _pp) - high; // S1 = C - (H - L) * 1.1 / 12 (1.0833) + _s2 = _pp - _range; // S2 = C - (H - L) * 1.1 / 6 (1.1666) + _s3 = _pp - _range * 2; // S3 = C - (H - L) * 1.1 / 4 (1.25) + _s4 = _pp - _range * 3; // S4 = C - (H - L) * 1.1 / 2 (1.5) + break; + case PP_FIBONACCI: + _pp = GetPivot(); + _r1 = (float)(_pp + 0.382 * _range); + _r2 = (float)(_pp + 0.618 * _range); + _r3 = _pp + _range; + _r4 = _r1 + _range; // ? + _s1 = (float)(_pp - 0.382 * _range); + _s2 = (float)(_pp - 0.618 * _range); + _s3 = _pp - _range; + _s4 = _s1 - _range; // ? + break; + case PP_FLOOR: + // Most basic and popular type of pivots used in Forex trading technical analysis. + _pp = GetPivot(); // Pivot (P) = (H + L + C) / 3 + _r1 = (2 * _pp) - low; // Resistance (R1) = (2 * P) - L + _r2 = _pp + _range; // R2 = P + H - L + _r3 = high + 2 * (_pp - low); // R3 = H + 2 * (P - L) + _r4 = _r3; + _s1 = (2 * _pp) - high; // Support (S1) = (2 * P) - H + _s2 = _pp - _range; // S2 = P - H + L + _s3 = low - 2 * (high - _pp); // S3 = L - 2 * (H - P) + _s4 = _s3; // ? + break; + case PP_TOM_DEMARK: + // Tom DeMark's pivot point (predicted lows and highs of the period). + _pp = GetPivotDeMark(); + _r1 = (2 * _pp) - low; // New High = X / 2 - L. + _r2 = _pp + _range; + _r3 = _r1 + _range; + _r4 = _r2 + _range; // ? + _s1 = (2 * _pp) - high; // New Low = X / 2 - H. + _s2 = _pp - _range; + _s3 = _s1 - _range; + _s4 = _s2 - _range; // ? + break; + case PP_WOODIE: + // Woodie's pivot point are giving more weight to the Close price of the previous period. + // They are similar to floor pivot points, but are calculated in a somewhat different way. + _pp = GetWeighted(); // Pivot (P) = (H + L + 2 * C) / 4 + _r1 = (2 * _pp) - low; // Resistance (R1) = (2 * P) - L + _r2 = _pp + _range; // R2 = P + H - L + _r3 = _r1 + _range; + _r4 = _r2 + _range; // ? + _s1 = (2 * _pp) - high; // Support (S1) = (2 * P) - H + _s2 = _pp - _range; // S2 = P - H + L + _s3 = _s1 - _range; + _s4 = _s2 - _range; // ? + break; + default: + break; + } + return _r4 > _r3 && _r3 > _r2 && _r2 > _r1 && _r1 > _pp && _pp > _s1 && _s1 > _s2 && _s2 > _s3 && _s3 > _s4; + } + float GetAppliedPrice(ENUM_APPLIED_PRICE _ap) const { + return CandleOHLC::GetAppliedPrice(_ap, open, high, low, close); + } + float GetBody() const { return close - open; } + float GetBodyAbs() const { return fabs(close - open); } + float GetBodyInPct(int _hundreds = 100) const { return GetRange() > 0 ? _hundreds / GetRange() * GetBodyAbs() : 0; } + float GetChangeInPct(int _hundreds = 100) const { return (close - open) / open * _hundreds; } + float GetClose() const { return close; } + float GetHigh() const { return high; } + float GetLow() const { return low; } + float GetMaxOC() const { return fmax(open, close); } + float GetMedian() const { return (high + low) / 2; } + float GetMinOC() const { return fmin(open, close); } + float GetOpen() const { return open; } + float GetPivot() const { return GetTypical(); } + float GetPivotDeMark() const { + // If Close < Open Then X = H + 2 * L + C + // If Close > Open Then X = 2 * H + L + C + // If Close = Open Then X = H + L + 2 * C + float _pp = open > close ? (high + (2 * low) + close) / 4 : ((2 * high) + low + close) / 4; + return open == close ? (high + low + (2 * close)) / 4 : _pp; + } + float GetPivotWithOpen() const { return (open + high + low + close) / 4; } + float GetPivotWithOpen(float _open) const { return (_open + high + low + close) / 4; } + float GetRange() const { return high - low; } + float GetRangeChangeInPct(int _hundreds = 100) const { + return _hundreds - (_hundreds / open * fabs(open - GetRange())); + } + float GetRangeInPips(float _ppp) const { return GetRange() / _ppp; } + float GetTypical() const { return (high + low + close) / 3; } + float GetWeighted() const { return (high + low + close + close) / 4; } + float GetWickMin() const { return fmin(GetWickLower(), GetWickUpper()); } + float GetWickLower() const { return GetMinOC() - low; } + float GetWickLowerInPct() const { return GetRange() > 0 ? 100 / GetRange() * GetWickLower() : 0; } + float GetWickMax() const { return fmax(GetWickLower(), GetWickUpper()); } + float GetWickSum() const { return GetWickLower() + GetWickUpper(); } + float GetWickUpper() const { return high - GetMaxOC(); } + float GetWickUpperInPct() const { return GetRange() > 0 ? 100 / GetRange() * GetWickUpper() : 0; } + short GetType() const { return IsBull() ? 1 : (IsBear() ? -1 : 0); } + void GetValues(ARRAY_REF(float, _out)) { + ArrayResize(_out, 4); + int _index = ArraySize(_out) - 4; + _out[_index++] = open; + _out[_index++] = high; + _out[_index++] = low; + _out[_index++] = close; + } + static T GetAppliedPrice(ENUM_APPLIED_PRICE _ap, T _o, T _h, T _l, T _c) { + switch (_ap) { + case PRICE_CLOSE: + return _c; + case PRICE_OPEN: + return _o; + case PRICE_HIGH: + return _h; + case PRICE_LOW: + return _l; + case PRICE_MEDIAN: + return (_h + _l) / 2; + case PRICE_TYPICAL: + return (_h + _l + _c) / 3; + case PRICE_WEIGHTED: + return (_h + _l + _c + _c) / 4; + default: + return _o; + } + } + // State checkers. + bool IsBear() const { return open > close; } + bool IsBull() const { return open < close; } + bool IsValid() const { return high >= low && fmin(open, close) > 0; } + // Serializers. + SerializerNodeType Serialize(Serializer &s); + // Converters. + string ToCSV() { return StringFormat("%g,%g,%g,%g", open, high, low, close); } +}; + +/* Structore for storing OHLC values with timestamp. */ +template +struct CandleTOHLC : CandleOHLC { + datetime time; + // Struct constructors. + CandleTOHLC(datetime _time = 0, T _open = 0, T _high = 0, T _low = 0, T _close = 0) + : time(_time), CandleOHLC(_open, _high, _low, _close) {} + // Getters. + datetime GetTime() { return time; } + // Serializers. + SerializerNodeType Serialize(Serializer &s); + // Converters. + string ToCSV() { return StringFormat("%d,%g,%g,%g,%g", time, open, high, low, close); } +}; + +#include "Serializer.mqh" + +/* Method to serialize CandleEntry structure. */ +template +SerializerNodeType CandleOHLC::Serialize(Serializer &s) { + // s.Pass(THIS_REF, "time", TimeToString(time)); + s.Pass(THIS_REF, "open", open, SERIALIZER_FIELD_FLAG_DYNAMIC); + s.Pass(THIS_REF, "high", high, SERIALIZER_FIELD_FLAG_DYNAMIC); + s.Pass(THIS_REF, "low", low, SERIALIZER_FIELD_FLAG_DYNAMIC); + s.Pass(THIS_REF, "close", close, SERIALIZER_FIELD_FLAG_DYNAMIC); + return SerializerNodeObject; +} + +/* Method to serialize CandleEntry structure. */ +template +SerializerNodeType CandleTOHLC::Serialize(Serializer &s) { + s.Pass(THIS_REF, "time", time); + s.Pass(THIS_REF, "open", open, SERIALIZER_FIELD_FLAG_DYNAMIC); + s.Pass(THIS_REF, "high", high, SERIALIZER_FIELD_FLAG_DYNAMIC); + s.Pass(THIS_REF, "low", low, SERIALIZER_FIELD_FLAG_DYNAMIC); + s.Pass(THIS_REF, "close", close, SERIALIZER_FIELD_FLAG_DYNAMIC); + return SerializerNodeObject; +} From b7b85d629b3f99c0f828fc9335bfd6b49ac35a44 Mon Sep 17 00:00:00 2001 From: kenorb Date: Thu, 11 Nov 2021 13:10:59 +0000 Subject: [PATCH 16/77] Buffer: Adds BufferCandle --- .github/workflows/test-buffer.yml | 60 +++++++++++++++++++++ Buffer/BufferCandle.h | 80 ++++++++++++++++++++++++++++ Buffer/tests/BufferCandle.test.mq4 | 28 ++++++++++ Buffer/tests/BufferCandle.test.mq5 | 59 +++++++++++++++++++++ Candle.struct.h | 85 ++++++++++++++---------------- 5 files changed, 267 insertions(+), 45 deletions(-) create mode 100644 .github/workflows/test-buffer.yml create mode 100644 Buffer/BufferCandle.h create mode 100644 Buffer/tests/BufferCandle.test.mq4 create mode 100644 Buffer/tests/BufferCandle.test.mq5 diff --git a/.github/workflows/test-buffer.yml b/.github/workflows/test-buffer.yml new file mode 100644 index 000000000..7dc097568 --- /dev/null +++ b/.github/workflows/test-buffer.yml @@ -0,0 +1,60 @@ +--- +name: Test Buffer + +# yamllint disable-line rule:truthy +on: + pull_request: + paths: + - 'Buffer/**' + - '.github/workflows/test-buffer.yml' + push: + paths: + - 'Buffer/**' + - '.github/workflows/test-buffer.yml' + +jobs: + + Compile: + runs-on: windows-latest + steps: + - uses: actions/checkout@v2 + - name: Compile + uses: fx31337/mql-compile-action@master + with: + init-platform: true + path: 'Buffer/tests' + verbose: true + - name: Print compiled files + run: '(Get-ChildItem -Recurse -Path . -Include *.ex[45]).fullname' + shell: powershell + - name: Upload artifacts (MQL4) + uses: actions/upload-artifact@v2 + with: + name: files-ex4 + path: '**/*.ex4' + - name: Upload artifacts (MQL5) + uses: actions/upload-artifact@v2 + with: + name: files-ex5 + path: '**/*.ex5' + + Buffer-Tests-MQL4: + defaults: + run: + shell: bash + working-directory: Buffer/tests + needs: Compile + runs-on: ubuntu-latest + strategy: + matrix: + test: + - BufferCandle.test + steps: + - uses: actions/download-artifact@v2 + with: + name: files-ex4 + - name: Run ${{ matrix.test }} + uses: fx31337/mql-tester-action@master + with: + Script: ${{ matrix.test }} + timeout-minutes: 10 diff --git a/Buffer/BufferCandle.h b/Buffer/BufferCandle.h new file mode 100644 index 000000000..91586eb45 --- /dev/null +++ b/Buffer/BufferCandle.h @@ -0,0 +1,80 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2021, EA31337 Ltd | +//| https://github.com/EA31337 | +//+------------------------------------------------------------------+ + +/* + * This file is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +// Prevents processing this includes file for the second time. +#ifndef BUFFER_CANDLE_H +#define BUFFER_CANDLE_H + +// Includes. +#include "../BufferStruct.mqh" +#include "../Candle.struct.h" + +/** + * Class to store struct data. + */ +class BufferCandle : public BufferStruct> { + protected: + uint cache_limit; + + protected: + /* Protected methods */ + + /** + * Initialize class. + * + * Called on constructor. + */ + void Init() { SetOverflowListener(BufferCandleOverflowListener, 10); } + + public: + /* Constructors */ + + /** + * Constructor. + */ + BufferCandle() { Init(); } + BufferCandle(BufferCandle& _right) { + THIS_REF = _right; + Init(); + } + + /* Callback methods */ + + /** + * Function should return true if resize can be made, or false to overwrite current slot. + */ + static bool BufferCandleOverflowListener(ENUM_DICT_OVERFLOW_REASON _reason, int _size, int _num_conflicts) { + static int cache_limit = 86400; + switch (_reason) { + case DICT_OVERFLOW_REASON_FULL: + // We allow resize if dictionary size is less than 86400 slots. + return _size < cache_limit; + case DICT_OVERFLOW_REASON_TOO_MANY_CONFLICTS: + default: + // When there is too many conflicts, we just reject doing resize, so first conflicting slot will be reused. + break; + } + return false; + } +}; + +#endif // BUFFER_CANDLE_H diff --git a/Buffer/tests/BufferCandle.test.mq4 b/Buffer/tests/BufferCandle.test.mq4 new file mode 100644 index 000000000..fe6c0a00d --- /dev/null +++ b/Buffer/tests/BufferCandle.test.mq4 @@ -0,0 +1,28 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2021, EA31337 Ltd | +//| https://github.com/EA31337 | +//+------------------------------------------------------------------+ + +/* + * This file is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * @file + * Test functionality of BufferCandle class. + */ + +// Includes. +#include "BufferCandle.test.mq5" diff --git a/Buffer/tests/BufferCandle.test.mq5 b/Buffer/tests/BufferCandle.test.mq5 new file mode 100644 index 000000000..61e66e616 --- /dev/null +++ b/Buffer/tests/BufferCandle.test.mq5 @@ -0,0 +1,59 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2021, EA31337 Ltd | +//| https://github.com/EA31337 | +//+------------------------------------------------------------------+ + +/* + * This file is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * @file + * Test functionality of BufferCandle class. + */ + +// Includes +#include "../../Test.mqh" +#include "../BufferCandle.h" + +/** + * Implements OnInit(). + */ +int OnInit() { + BufferCandle buffer1; // 128 + CandleOHLC _ohlc_d; // 32 + CandleOHLC _ohlc_f; // 16 + CandleTOHLC _tohlc_d; // 32 + CandleTOHLC _tohlc_f; // 16 + // CandleEntry _centry_d; // 40 + // CandleEntry _centry_f; // 24 + Print("buffer1: ", sizeof(buffer1)); + Print("_ohlc_d: ", sizeof(_ohlc_d)); + Print("_ohlc_f: ", sizeof(_ohlc_f)); + Print("_tohlc_d: ", sizeof(_tohlc_d)); + Print("_tohlc_f: ", sizeof(_tohlc_f)); + // @todo + return (GetLastError() > 0 ? INIT_FAILED : INIT_SUCCEEDED); +} + +/** + * Implements OnTick(). + */ +void OnTick() {} + +/** + * Implements OnDeinit(). + */ +void OnDeinit(const int reason) {} diff --git a/Candle.struct.h b/Candle.struct.h index 2fea358e6..e713ceb22 100644 --- a/Candle.struct.h +++ b/Candle.struct.h @@ -63,21 +63,20 @@ struct CandleOHLC } // Struct methods. // Getters - bool GetPivots(ENUM_PP_TYPE _type, float &_pp, float &_r1, float &_r2, float &_r3, float &_r4, float &_s1, float &_s2, - float &_s3, float &_s4) { - float _range = GetRange(); + bool GetPivots(ENUM_PP_TYPE _type, T &_pp, T &_r1, T &_r2, T &_r3, T &_r4, T &_s1, T &_s2, T &_s3, T &_s4) { + T _range = GetRange(); switch (_type) { case PP_CAMARILLA: // A set of eight very probable levels which resemble support and resistance values for a current trend. _pp = GetPivot(); - _r1 = (float)(close + _range * 1.1 / 12); - _r2 = (float)(close + _range * 1.1 / 6); - _r3 = (float)(close + _range * 1.1 / 4); - _r4 = (float)(close + _range * 1.1 / 2); - _s1 = (float)(close - _range * 1.1 / 12); - _s2 = (float)(close - _range * 1.1 / 6); - _s3 = (float)(close - _range * 1.1 / 4); - _s4 = (float)(close - _range * 1.1 / 2); + _r1 = (T)(close + _range * 1.1 / 12); + _r2 = (T)(close + _range * 1.1 / 6); + _r3 = (T)(close + _range * 1.1 / 4); + _r4 = (T)(close + _range * 1.1 / 2); + _s1 = (T)(close - _range * 1.1 / 12); + _s2 = (T)(close - _range * 1.1 / 6); + _s3 = (T)(close - _range * 1.1 / 4); + _s4 = (T)(close - _range * 1.1 / 2); break; case PP_CLASSIC: _pp = GetPivot(); @@ -143,46 +142,42 @@ struct CandleOHLC } return _r4 > _r3 && _r3 > _r2 && _r2 > _r1 && _r1 > _pp && _pp > _s1 && _s1 > _s2 && _s2 > _s3 && _s3 > _s4; } - float GetAppliedPrice(ENUM_APPLIED_PRICE _ap) const { - return CandleOHLC::GetAppliedPrice(_ap, open, high, low, close); - } - float GetBody() const { return close - open; } - float GetBodyAbs() const { return fabs(close - open); } - float GetBodyInPct(int _hundreds = 100) const { return GetRange() > 0 ? _hundreds / GetRange() * GetBodyAbs() : 0; } - float GetChangeInPct(int _hundreds = 100) const { return (close - open) / open * _hundreds; } - float GetClose() const { return close; } - float GetHigh() const { return high; } - float GetLow() const { return low; } - float GetMaxOC() const { return fmax(open, close); } - float GetMedian() const { return (high + low) / 2; } - float GetMinOC() const { return fmin(open, close); } - float GetOpen() const { return open; } - float GetPivot() const { return GetTypical(); } - float GetPivotDeMark() const { + T GetAppliedPrice(ENUM_APPLIED_PRICE _ap) const { return CandleOHLC::GetAppliedPrice(_ap, open, high, low, close); } + T GetBody() const { return close - open; } + T GetBodyAbs() const { return fabs(close - open); } + T GetBodyInPct(int _hundreds = 100) const { return GetRange() > 0 ? _hundreds / GetRange() * GetBodyAbs() : 0; } + T GetChangeInPct(int _hundreds = 100) const { return (close - open) / open * _hundreds; } + T GetClose() const { return close; } + T GetHigh() const { return high; } + T GetLow() const { return low; } + T GetMaxOC() const { return fmax(open, close); } + T GetMedian() const { return (high + low) / 2; } + T GetMinOC() const { return fmin(open, close); } + T GetOpen() const { return open; } + T GetPivot() const { return GetTypical(); } + T GetPivotDeMark() const { // If Close < Open Then X = H + 2 * L + C // If Close > Open Then X = 2 * H + L + C // If Close = Open Then X = H + L + 2 * C - float _pp = open > close ? (high + (2 * low) + close) / 4 : ((2 * high) + low + close) / 4; + T _pp = open > close ? (high + (2 * low) + close) / 4 : ((2 * high) + low + close) / 4; return open == close ? (high + low + (2 * close)) / 4 : _pp; } - float GetPivotWithOpen() const { return (open + high + low + close) / 4; } - float GetPivotWithOpen(float _open) const { return (_open + high + low + close) / 4; } - float GetRange() const { return high - low; } - float GetRangeChangeInPct(int _hundreds = 100) const { - return _hundreds - (_hundreds / open * fabs(open - GetRange())); - } - float GetRangeInPips(float _ppp) const { return GetRange() / _ppp; } - float GetTypical() const { return (high + low + close) / 3; } - float GetWeighted() const { return (high + low + close + close) / 4; } - float GetWickMin() const { return fmin(GetWickLower(), GetWickUpper()); } - float GetWickLower() const { return GetMinOC() - low; } - float GetWickLowerInPct() const { return GetRange() > 0 ? 100 / GetRange() * GetWickLower() : 0; } - float GetWickMax() const { return fmax(GetWickLower(), GetWickUpper()); } - float GetWickSum() const { return GetWickLower() + GetWickUpper(); } - float GetWickUpper() const { return high - GetMaxOC(); } - float GetWickUpperInPct() const { return GetRange() > 0 ? 100 / GetRange() * GetWickUpper() : 0; } + T GetPivotWithOpen() const { return (open + high + low + close) / 4; } + T GetPivotWithOpen(float _open) const { return (_open + high + low + close) / 4; } + T GetRange() const { return high - low; } + T GetRangeChangeInPct(int _hundreds = 100) const { return _hundreds - (_hundreds / open * fabs(open - GetRange())); } + T GetRangeInPips(float _ppp) const { return GetRange() / _ppp; } + T GetTypical() const { return (high + low + close) / 3; } + T GetWeighted() const { return (high + low + close + close) / 4; } + T GetWickMin() const { return fmin(GetWickLower(), GetWickUpper()); } + T GetWickLower() const { return GetMinOC() - low; } + T GetWickLowerInPct() const { return GetRange() > 0 ? 100 / GetRange() * GetWickLower() : 0; } + T GetWickMax() const { return fmax(GetWickLower(), GetWickUpper()); } + T GetWickSum() const { return GetWickLower() + GetWickUpper(); } + T GetWickUpper() const { return high - GetMaxOC(); } + T GetWickUpperInPct() const { return GetRange() > 0 ? 100 / GetRange() * GetWickUpper() : 0; } short GetType() const { return IsBull() ? 1 : (IsBear() ? -1 : 0); } - void GetValues(ARRAY_REF(float, _out)) { + void GetValues(ARRAY_REF(T, _out)) { ArrayResize(_out, 4); int _index = ArraySize(_out) - 4; _out[_index++] = open; From e80fd947af90c03c79303ea4efeea724948a8edb Mon Sep 17 00:00:00 2001 From: kenorb Date: Thu, 11 Nov 2021 18:03:36 +0000 Subject: [PATCH 17/77] Indicator/IndicatorCandle: Adds BufferCandle --- Buffer/BufferCandle.h | 3 ++- Buffer/tests/BufferCandle.test.mq5 | 2 +- Indicator/IndicatorCandle.h | 10 ++++++++-- Indicator/IndicatorTf.h | 4 ++-- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/Buffer/BufferCandle.h b/Buffer/BufferCandle.h index 91586eb45..ff77d7a08 100644 --- a/Buffer/BufferCandle.h +++ b/Buffer/BufferCandle.h @@ -31,7 +31,8 @@ /** * Class to store struct data. */ -class BufferCandle : public BufferStruct> { +template +class BufferCandle : public BufferStruct> { protected: uint cache_limit; diff --git a/Buffer/tests/BufferCandle.test.mq5 b/Buffer/tests/BufferCandle.test.mq5 index 61e66e616..ab76d8da8 100644 --- a/Buffer/tests/BufferCandle.test.mq5 +++ b/Buffer/tests/BufferCandle.test.mq5 @@ -32,7 +32,7 @@ * Implements OnInit(). */ int OnInit() { - BufferCandle buffer1; // 128 + BufferCandle buffer1; // 128 CandleOHLC _ohlc_d; // 32 CandleOHLC _ohlc_f; // 16 CandleTOHLC _tohlc_d; // 32 diff --git a/Indicator/IndicatorCandle.h b/Indicator/IndicatorCandle.h index 4b00672ac..ff2e0fdc2 100644 --- a/Indicator/IndicatorCandle.h +++ b/Indicator/IndicatorCandle.h @@ -30,15 +30,16 @@ #endif // Includes. +#include "../Buffer/BufferCandle.h" #include "../IndicatorBase.h" /** * Class to deal with candle indicators. */ -template +template class IndicatorCandle : public IndicatorBase { protected: - BufferStruct icdata; + BufferCandle icdata; TS icparams; protected: @@ -84,6 +85,8 @@ class IndicatorCandle : public IndicatorBase { */ IndicatorDataEntry GetEntry(int _timestamp = 0) { ResetLastError(); + CandleOHLC _entry = icdata.GetByKey(_timestamp); + /* IndicatorDataEntry _entry = icdata.GetByKey(_timestamp); if (!_entry.IsValid() && !_entry.CheckFlag(INDI_ENTRY_FLAG_INSUFFICIENT_DATA)) { _entry.Resize(icparams.GetMaxModes()); @@ -132,6 +135,9 @@ class IndicatorCandle : public IndicatorBase { ResetLastError(); } return _entry; + */ + IndicatorDataEntry _foo; + return _foo; } /** diff --git a/Indicator/IndicatorTf.h b/Indicator/IndicatorTf.h index b51828ce5..a64d22338 100644 --- a/Indicator/IndicatorTf.h +++ b/Indicator/IndicatorTf.h @@ -36,7 +36,7 @@ /** * Class to deal with candle indicators. */ -class IndicatorTf : public IndicatorCandle { +class IndicatorTf : public IndicatorCandle { protected: /* Protected methods */ @@ -63,7 +63,7 @@ class IndicatorTf : public IndicatorCandle { /** * Class constructor with parameters. */ - IndicatorTf(IndicatorTfParams &_params) : IndicatorCandle(_params) { Init(); } + IndicatorTf(IndicatorTfParams &_params) : IndicatorCandle(_params) { Init(); } }; #endif From 88e4c7191bacb1f25a524fdef57ec84ffb461a38 Mon Sep 17 00:00:00 2001 From: kenorb Date: Thu, 11 Nov 2021 18:23:02 +0000 Subject: [PATCH 18/77] Renames MqlTick.h to MqlTick.struct.h --- MqlTick.h => MqlTick.struct.h | 0 SymbolInfo.struct.h | 2 +- SymbolInfo.struct.static.h | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename MqlTick.h => MqlTick.struct.h (100%) diff --git a/MqlTick.h b/MqlTick.struct.h similarity index 100% rename from MqlTick.h rename to MqlTick.struct.h diff --git a/SymbolInfo.struct.h b/SymbolInfo.struct.h index ba2dc565d..60f5b7b1a 100644 --- a/SymbolInfo.struct.h +++ b/SymbolInfo.struct.h @@ -32,7 +32,7 @@ // Includes. #include "ISerializable.h" -#include "MqlTick.h" +#include "MqlTick.struct.h" #include "SymbolInfo.struct.static.h" // Defines struct to store symbol data. diff --git a/SymbolInfo.struct.static.h b/SymbolInfo.struct.static.h index 7133cc0a3..a214f1ef5 100644 --- a/SymbolInfo.struct.static.h +++ b/SymbolInfo.struct.static.h @@ -26,7 +26,7 @@ #endif #include "MQL5.mqh" -#include "MqlTick.h" +#include "MqlTick.struct.h" #include "Std.h" /** From e0632a6262a4bac16ef8349495add24dbb9bdc4c Mon Sep 17 00:00:00 2001 From: kenorb Date: Thu, 11 Nov 2021 18:28:04 +0000 Subject: [PATCH 19/77] Renames MqlTick.struct.h to Tick.struct.h --- SymbolInfo.struct.h | 2 +- SymbolInfo.struct.static.h | 2 +- MqlTick.struct.h => Tick.struct.h | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename MqlTick.struct.h => Tick.struct.h (100%) diff --git a/SymbolInfo.struct.h b/SymbolInfo.struct.h index 60f5b7b1a..3e7b94bc8 100644 --- a/SymbolInfo.struct.h +++ b/SymbolInfo.struct.h @@ -32,7 +32,7 @@ // Includes. #include "ISerializable.h" -#include "MqlTick.struct.h" +#include "Tick.struct.h" #include "SymbolInfo.struct.static.h" // Defines struct to store symbol data. diff --git a/SymbolInfo.struct.static.h b/SymbolInfo.struct.static.h index a214f1ef5..f99368708 100644 --- a/SymbolInfo.struct.static.h +++ b/SymbolInfo.struct.static.h @@ -26,7 +26,7 @@ #endif #include "MQL5.mqh" -#include "MqlTick.struct.h" +#include "Tick.struct.h" #include "Std.h" /** diff --git a/MqlTick.struct.h b/Tick.struct.h similarity index 100% rename from MqlTick.struct.h rename to Tick.struct.h From f47bd0921993818ae33a946d4fcee2943623a871 Mon Sep 17 00:00:00 2001 From: kenorb Date: Thu, 11 Nov 2021 18:48:50 +0000 Subject: [PATCH 20/77] Adds TickAB and TickTAB structs --- Tick.struct.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/Tick.struct.h b/Tick.struct.h index 241e807b5..46d4efee4 100644 --- a/Tick.struct.h +++ b/Tick.struct.h @@ -29,6 +29,29 @@ #pragma once #endif +/** + * Structure for storing ask and bid prices of the symbol. + */ +template +struct TickAB { + T ask; // Current Ask price. + T bid; // Current Bid price. + // Struct constructors. + TickAB(T _ask = 0, T _bid = 0) : ask(_ask), bid(_bid) {} + TickAB(MqlTick &_tick) : ask(_tick.ask), bid(_tick.bid) {} +}; + +/** + * Structure for storing ask and bid prices of the symbol. + */ +template +struct TickTAB : TickAB { + datetime time; // Time of the last prices update. + // Struct constructors. + TickTAB(datetime _time = 0, T _ask = 0, T _bid = 0) : time(_time), TickAB(_ask, _bid) {} + TickAB(MqlTick &_tick) : time(_tick.time), TickAB(_tick.ask, _tick.bid) {} +}; + #ifndef __MQL__ /** * Structure for storing the latest prices of the symbol. From cb7ba0d4ea7f88e8d622255e9cb2112c9381059c Mon Sep 17 00:00:00 2001 From: kenorb Date: Thu, 11 Nov 2021 18:49:05 +0000 Subject: [PATCH 21/77] Buffer: Adds BufferTick --- .github/workflows/test-buffer.yml | 1 + Buffer/BufferCandle.h | 2 - Buffer/BufferTick.h | 79 ++++++++++++++++++++++++++ Buffer/tests/BufferTick.test.mq4 | 28 +++++++++ Buffer/tests/BufferTick.test.mq5 | 57 +++++++++++++++++++ Candle.struct.h | 1 + Indicator/IndicatorTick.h | 24 ++++---- Indicator/tests/IndicatorTick.test.mq5 | 2 +- Indicators/Tick/Indi_TickMt.mqh | 7 ++- Tick.struct.h | 4 +- 10 files changed, 184 insertions(+), 21 deletions(-) create mode 100644 Buffer/BufferTick.h create mode 100644 Buffer/tests/BufferTick.test.mq4 create mode 100644 Buffer/tests/BufferTick.test.mq5 diff --git a/.github/workflows/test-buffer.yml b/.github/workflows/test-buffer.yml index 7dc097568..bf23d92e7 100644 --- a/.github/workflows/test-buffer.yml +++ b/.github/workflows/test-buffer.yml @@ -49,6 +49,7 @@ jobs: matrix: test: - BufferCandle.test + - BufferTick.test steps: - uses: actions/download-artifact@v2 with: diff --git a/Buffer/BufferCandle.h b/Buffer/BufferCandle.h index ff77d7a08..b0230c58a 100644 --- a/Buffer/BufferCandle.h +++ b/Buffer/BufferCandle.h @@ -34,8 +34,6 @@ template class BufferCandle : public BufferStruct> { protected: - uint cache_limit; - protected: /* Protected methods */ diff --git a/Buffer/BufferTick.h b/Buffer/BufferTick.h new file mode 100644 index 000000000..8e6ac9093 --- /dev/null +++ b/Buffer/BufferTick.h @@ -0,0 +1,79 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2021, EA31337 Ltd | +//| https://github.com/EA31337 | +//+------------------------------------------------------------------+ + +/* + * This file is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +// Prevents processing this includes file for the second time. +#ifndef BUFFER_TICK_H +#define BUFFER_TICK_H + +// Includes. +#include "../BufferStruct.mqh" +#include "../Tick.struct.h" + +/** + * Class to store struct data. + */ +template +class BufferTick : public BufferStruct> { + protected: + protected: + /* Protected methods */ + + /** + * Initialize class. + * + * Called on constructor. + */ + void Init() { SetOverflowListener(BufferTickOverflowListener, 10); } + + public: + /* Constructors */ + + /** + * Constructor. + */ + BufferTick() { Init(); } + BufferTick(BufferTick& _right) { + THIS_REF = _right; + Init(); + } + + /* Callback methods */ + + /** + * Function should return true if resize can be made, or false to overwrite current slot. + */ + static bool BufferTickOverflowListener(ENUM_DICT_OVERFLOW_REASON _reason, int _size, int _num_conflicts) { + static int cache_limit = 86400; + switch (_reason) { + case DICT_OVERFLOW_REASON_FULL: + // We allow resize if dictionary size is less than 86400 slots. + return _size < cache_limit; + case DICT_OVERFLOW_REASON_TOO_MANY_CONFLICTS: + default: + // When there is too many conflicts, we just reject doing resize, so first conflicting slot will be reused. + break; + } + return false; + } +}; + +#endif // BUFFER_TICK_H diff --git a/Buffer/tests/BufferTick.test.mq4 b/Buffer/tests/BufferTick.test.mq4 new file mode 100644 index 000000000..5a45ef4fa --- /dev/null +++ b/Buffer/tests/BufferTick.test.mq4 @@ -0,0 +1,28 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2021, EA31337 Ltd | +//| https://github.com/EA31337 | +//+------------------------------------------------------------------+ + +/* + * This file is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * @file + * Test functionality of BufferTick class. + */ + +// Includes. +#include "BufferTick.test.mq5" diff --git a/Buffer/tests/BufferTick.test.mq5 b/Buffer/tests/BufferTick.test.mq5 new file mode 100644 index 000000000..1daf2ea7b --- /dev/null +++ b/Buffer/tests/BufferTick.test.mq5 @@ -0,0 +1,57 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2021, EA31337 Ltd | +//| https://github.com/EA31337 | +//+------------------------------------------------------------------+ + +/* + * This file is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * @file + * Test functionality of BufferTick class. + */ + +// Includes +#include "../../Test.mqh" +#include "../BufferTick.h" + +/** + * Implements OnInit(). + */ +int OnInit() { + MqlTick mql_tick; // 60 + TickAB _tick_ab_d; // 16 + TickAB _tick_ab_f; // 8 + TickTAB _tick_tab_d; // 24 + TickTAB _tick_tab_f; // 16 + Print("mql_tick: ", sizeof(mql_tick)); + Print("_tick_ab_d: ", sizeof(_tick_ab_d)); + Print("_tick_ab_f: ", sizeof(_tick_ab_f)); + Print("_tick_tab_d: ", sizeof(_tick_tab_d)); + Print("_tick_tab_f: ", sizeof(_tick_tab_f)); + // @todo + return (GetLastError() > 0 ? INIT_FAILED : INIT_SUCCEEDED); +} + +/** + * Implements OnTick(). + */ +void OnTick() {} + +/** + * Implements OnDeinit(). + */ +void OnDeinit(const int reason) {} diff --git a/Candle.struct.h b/Candle.struct.h index e713ceb22..2adbe4900 100644 --- a/Candle.struct.h +++ b/Candle.struct.h @@ -49,6 +49,7 @@ struct CandleOHLC #endif { T open, high, low, close; + // Struct constructors. CandleOHLC(T _open = 0, T _high = 0, T _low = 0, T _close = 0) : open(_open), high(_high), low(_low), close(_close) {} CandleOHLC(ARRAY_REF(T, _prices)) { int _size = ArraySize(_prices); diff --git a/Indicator/IndicatorTick.h b/Indicator/IndicatorTick.h index bf1487a03..9b1c3d6cf 100644 --- a/Indicator/IndicatorTick.h +++ b/Indicator/IndicatorTick.h @@ -30,15 +30,16 @@ #endif // Includes. +#include "../Buffer/BufferTick.h" #include "../IndicatorBase.h" /** * Class to deal with tick indicators. */ -template +template class IndicatorTick : public IndicatorBase { protected: - BufferStruct itdata; + BufferTick itdata; TS itparams; protected: @@ -85,6 +86,8 @@ class IndicatorTick : public IndicatorBase { */ IndicatorDataEntry GetEntry(int _timestamp = 0) { ResetLastError(); + TickAB _entry = itdata.GetByKey(_timestamp); + /* IndicatorDataEntry _entry = itdata.GetByKey(_timestamp); if (!_entry.IsValid() && !_entry.CheckFlag(INDI_ENTRY_FLAG_INSUFFICIENT_DATA)) { _entry.Resize(itparams.GetMaxModes()); @@ -133,6 +136,9 @@ class IndicatorTick : public IndicatorBase { ResetLastError(); } return _entry; + */ + IndicatorDataEntry _foo; + return _foo; } /** @@ -165,17 +171,9 @@ class IndicatorTick : public IndicatorBase { * * @see: MqlTick. */ - void SetTick(MqlTick& _tick, long _timestamp = 0) { - IndicatorDataEntry _entry(itparams.GetMaxModes()); - _entry.timestamp = _timestamp; - _entry.values[0] = _tick.bid; - _entry.values[1] = _tick.ask; -#ifdef __MQL4__ - _entry.values[2] = _tick.volume; -#else - _entry.values[2] = _tick.volume_real; -#endif - itdata.Add(_entry, _timestamp); + void SetTick(MqlTick& _mql_tick, long _timestamp = 0) { + TickAB _tick(_mql_tick); + itdata.Add(_tick, _timestamp); } /** diff --git a/Indicator/tests/IndicatorTick.test.mq5 b/Indicator/tests/IndicatorTick.test.mq5 index 07bab9c74..0fc115be5 100644 --- a/Indicator/tests/IndicatorTick.test.mq5 +++ b/Indicator/tests/IndicatorTick.test.mq5 @@ -36,7 +36,7 @@ struct IndicatorTickDummyParams : IndicatorParams { /** * Price Indicator. */ -class IndicatorTickDummy : public IndicatorTick { +class IndicatorTickDummy : public IndicatorTick { public: IndicatorTickDummy(string _symbol, int _shift = 0, string _name = "") : IndicatorTick(INDI_TICK, _symbol, _shift, _name) { diff --git a/Indicators/Tick/Indi_TickMt.mqh b/Indicators/Tick/Indi_TickMt.mqh index 01d7dd2f7..db392ce69 100644 --- a/Indicators/Tick/Indi_TickMt.mqh +++ b/Indicators/Tick/Indi_TickMt.mqh @@ -44,7 +44,7 @@ struct IndiTickMtParams : IndicatorParams { /** * Price Indicator. */ -class Indi_TickMt : public IndicatorTick { +class Indi_TickMt : public IndicatorTick { protected: MqlTick tick; @@ -52,7 +52,8 @@ class Indi_TickMt : public IndicatorTick { /** * Class constructor. */ - Indi_TickMt(IndiTickMtParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTick(_p, _indi_src){}; + Indi_TickMt(IndiTickMtParams &_p, IndicatorBase *_indi_src = NULL) + : IndicatorTick(_p, _indi_src){}; Indi_TickMt(string _symbol, int _shift = 0) : IndicatorTick(INDI_TICK, _symbol, _shift){}; /** @@ -86,7 +87,7 @@ class Indi_TickMt : public IndicatorTick { * This method is called on GetEntry() right after values are set. */ virtual void GetEntryAlter(IndicatorDataEntry &_entry, int _shift = -1) { - IndicatorTick::GetEntryAlter(_entry, _shift); + IndicatorTick::GetEntryAlter(_entry, _shift); _entry.timestamp = _entry.timestamp > 0 ? _entry.timestamp : tick.time; }; }; diff --git a/Tick.struct.h b/Tick.struct.h index 46d4efee4..0d36f8095 100644 --- a/Tick.struct.h +++ b/Tick.struct.h @@ -38,7 +38,7 @@ struct TickAB { T bid; // Current Bid price. // Struct constructors. TickAB(T _ask = 0, T _bid = 0) : ask(_ask), bid(_bid) {} - TickAB(MqlTick &_tick) : ask(_tick.ask), bid(_tick.bid) {} + TickAB(MqlTick &_tick) : ask((T)_tick.ask), bid((T)_tick.bid) {} }; /** @@ -49,7 +49,7 @@ struct TickTAB : TickAB { datetime time; // Time of the last prices update. // Struct constructors. TickTAB(datetime _time = 0, T _ask = 0, T _bid = 0) : time(_time), TickAB(_ask, _bid) {} - TickAB(MqlTick &_tick) : time(_tick.time), TickAB(_tick.ask, _tick.bid) {} + TickTAB(MqlTick &_tick) : time(_tick.time), TickAB(_tick) {} }; #ifndef __MQL__ From 11dd81219e7a3aee39ccea03e5c8fd2f756c3f4e Mon Sep 17 00:00:00 2001 From: kenorb Date: Thu, 28 Oct 2021 21:58:12 +0100 Subject: [PATCH 22/77] Chart: ChartTf: Adds SecsToTf() --- Chart.struct.tf.h | 63 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/Chart.struct.tf.h b/Chart.struct.tf.h index 6c91b1c16..49c7c88f3 100644 --- a/Chart.struct.tf.h +++ b/Chart.struct.tf.h @@ -116,6 +116,69 @@ struct ChartTf { /* Static methods */ + /** + * Converts number of seconds per bar to chart's timeframe. + * + * @param _secs + * Number of seconds per one bar chart (OHLC). + * + * @return ENUM_TIMEFRAMES + * Returns enum representing chart's timeframe value. + */ + static ENUM_TIMEFRAMES SecsToTf(uint _secs = 0) { + switch (_secs) { + case 0: + return PERIOD_CURRENT; + case 60: + return PERIOD_M1; // 1 minute. + case 60 * 2: + return PERIOD_M2; // 2 minutes (non-standard). + case 60 * 3: + return PERIOD_M3; // 3 minutes (non-standard). + case 60 * 4: + return PERIOD_M4; // 4 minutes (non-standard). + case 60 * 5: + return PERIOD_M5; // 5 minutes. + case 60 * 6: + return PERIOD_M6; // 6 minutes (non-standard). + case 60 * 10: + return PERIOD_M10; // 10 minutes (non-standard). + case 60 * 12: + return PERIOD_M12; // 12 minutes (non-standard). + case 60 * 15: + return PERIOD_M15; // 15 minutes. + case 60 * 20: + return PERIOD_M20; // 20 minutes (non-standard). + case 60 * 30: + return PERIOD_M30; // 30 minutes. + case 60 * 60: + return PERIOD_H1; // 1 hour. + case 60 * 60 * 2: + return PERIOD_H2; // 2 hours (non-standard). + case 60 * 60 * 3: + return PERIOD_H3; // 3 hours (non-standard). + case 60 * 60 * 4: + return PERIOD_H4; // 4 hours. + case 60 * 60 * 6: + return PERIOD_H6; // 6 hours (non-standard). + case 60 * 60 * 8: + return PERIOD_H8; // 8 hours (non-standard). + case 60 * 60 * 12: + return PERIOD_H12; // 12 hours (non-standard). + case 60 * 60 * 24: + return PERIOD_D1; // Daily. + case 60 * 60 * 24 * 7: + return PERIOD_W1; // Weekly. + default: + break; + } + if (_secs >= 60 * 60 * 24 * 28 && _secs <= 60 * 60 * 24 * 31) { + return PERIOD_MN1; // Monthly range. + } + SetUserError(ERR_INVALID_PARAMETER); + return PERIOD_CURRENT; + } + /** * Convert period to proper chart timeframe value. * From 0b2e66f6522f5b07fc631996371616c367cb484b Mon Sep 17 00:00:00 2001 From: kenorb Date: Thu, 11 Nov 2021 20:12:19 +0000 Subject: [PATCH 23/77] Indicator/IndicatorTf: Improves constructors --- Buffer/BufferTick.h | 16 ++++++++++++++++ Chart.struct.tf.h | 3 +-- Indicator/IndicatorTf.h | 23 +++++++++++++++++++---- Indicator/IndicatorTf.struct.h | 10 +++++++++- 4 files changed, 45 insertions(+), 7 deletions(-) diff --git a/Buffer/BufferTick.h b/Buffer/BufferTick.h index 8e6ac9093..70965dcfe 100644 --- a/Buffer/BufferTick.h +++ b/Buffer/BufferTick.h @@ -56,6 +56,22 @@ class BufferTick : public BufferStruct> { Init(); } + /* Grouping methods */ + + /** + * Group ticks by seconds. + */ + DictStruct>> GroupBySecs(uint _spc) { + // DictStruct>> _result; + // @todo: for each iter + // for (DictStructIterator>> iter(Begin()); iter.IsValid(); ++iter) { + // Load timestamp from key, TickAB from value + // foreach some timestamp mod % _spc - calculate shift + // _result.Push(_shift, TickAB) + // Convert to OHLC in upper method + return NULL; + } + /* Callback methods */ /** diff --git a/Chart.struct.tf.h b/Chart.struct.tf.h index 49c7c88f3..7074f67e8 100644 --- a/Chart.struct.tf.h +++ b/Chart.struct.tf.h @@ -32,6 +32,7 @@ // Includes. #include "Chart.enum.h" +#include "Serializer.mqh" /* Defines struct for chart timeframe. */ struct ChartTf { @@ -346,8 +347,6 @@ struct ChartTf { SerializerNodeType Serialize(Serializer& s); }; -#include "Serializer.mqh" - /* Method to serialize ChartTf structure. */ SerializerNodeType ChartTf::Serialize(Serializer& s) { s.PassEnum(THIS_REF, "tf", tf); diff --git a/Indicator/IndicatorTf.h b/Indicator/IndicatorTf.h index a64d22338..956fb2b45 100644 --- a/Indicator/IndicatorTf.h +++ b/Indicator/IndicatorTf.h @@ -30,6 +30,7 @@ #endif // Includes. +#include "../Chart.struct.tf.h" #include "IndicatorCandle.h" #include "IndicatorTf.struct.h" @@ -51,14 +52,28 @@ class IndicatorTf : public IndicatorCandle { /* Special methods */ /** - * Class constructor. + * Class constructor with timeframe enum. */ - IndicatorTf(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) { Init(); } + IndicatorTf(uint _spc) { + icparams.SetSecsPerCandle(_spc); + Init(); + } /** - * Class constructor. + * Class constructor with timeframe enum. */ - IndicatorTf(ENUM_TIMEFRAMES_INDEX _tfi = 0) { Init(); } + IndicatorTf(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) { + icparams.SetSecsPerCandle(ChartTf::TfToSeconds(_tf)); + Init(); + } + + /** + * Class constructor with timeframe index. + */ + IndicatorTf(ENUM_TIMEFRAMES_INDEX _tfi = 0) { + icparams.SetSecsPerCandle(ChartTf::TfToSeconds(ChartTf::IndexToTf(_tfi))); + Init(); + } /** * Class constructor with parameters. diff --git a/Indicator/IndicatorTf.struct.h b/Indicator/IndicatorTf.struct.h index 8e82a67bd..5feae87e4 100644 --- a/Indicator/IndicatorTf.struct.h +++ b/Indicator/IndicatorTf.struct.h @@ -30,10 +30,18 @@ #pragma once #endif +// Includes. +#include "../Indicator.struct.h" + /* Structure for IndicatorTf class parameters. */ struct IndicatorTfParams : IndicatorParams { + uint spc; // Seconds per candle. // Struct constructor. - IndicatorTfParams() {} + IndicatorTfParams(uint _spc = 60) : spc(_spc) {} + // Getters. + uint GetSecsPerCandle() { return spc; } + // Setters. + void SetSecsPerCandle(uint _spc) { spc = _spc; } // Copy constructor. IndicatorTfParams(const IndicatorTfParams &_params, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) { THIS_REF = _params; From 112a998ab3b8fc4baa7fb1e0988c894118c05933 Mon Sep 17 00:00:00 2001 From: Adrian Kierzkowski Date: Fri, 19 Nov 2021 22:02:24 +0100 Subject: [PATCH 24/77] Just some WIP. --- Candle.struct.h | 2 +- Indicator.enum.h | 1 + Indicator.mqh | 3 +-- Indicator/IndicatorCandle.h | 22 ++++++++++++++++++++-- Indicator/IndicatorTf.h | 5 +++-- Indicator/tests/IndicatorTf.test.mq5 | 21 +++++++++++++++++++++ 6 files changed, 47 insertions(+), 7 deletions(-) diff --git a/Candle.struct.h b/Candle.struct.h index 2adbe4900..6a7338c27 100644 --- a/Candle.struct.h +++ b/Candle.struct.h @@ -41,7 +41,7 @@ class Serializer; #include "SerializerNode.enum.h" #include "Std.h" -/* Structore for storing OHLC values. */ +/* Structure for storing OHLC values. */ template struct CandleOHLC #ifndef __MQL__ diff --git a/Indicator.enum.h b/Indicator.enum.h index 375064b34..63baad455 100644 --- a/Indicator.enum.h +++ b/Indicator.enum.h @@ -114,6 +114,7 @@ enum ENUM_INDICATOR_TYPE { INDI_STOCHASTIC, // Stochastic Oscillator INDI_SVE_BB, // SVE Bollinger Bands INDI_TEMA, // Triple Exponential Moving Average + INDI_TF, // Timeframe INDI_TICK, // Tick INDI_TMA_TRUE, // Triangular Moving Average True INDI_TRIX, // Triple Exponential Moving Averages Oscillator diff --git a/Indicator.mqh b/Indicator.mqh index da1721aa2..ccfe59441 100644 --- a/Indicator.mqh +++ b/Indicator.mqh @@ -1098,7 +1098,7 @@ class Indicator : public IndicatorBase { * @return * Returns IndicatorDataEntry struct filled with indicator values. */ - virtual IndicatorDataEntry GetEntry(int _index = -1) { + IndicatorDataEntry GetEntry(int _index = -1) override { ResetLastError(); int _ishift = _index >= 0 ? _index : iparams.GetShift(); long _bar_time = GetBarTime(_ishift); @@ -1293,7 +1293,6 @@ class Indicator : public IndicatorBase { COMMA _l COMMA _m); #endif } - }; #endif diff --git a/Indicator/IndicatorCandle.h b/Indicator/IndicatorCandle.h index ff2e0fdc2..7886ec953 100644 --- a/Indicator/IndicatorCandle.h +++ b/Indicator/IndicatorCandle.h @@ -61,7 +61,8 @@ class IndicatorCandle : public IndicatorBase { /** * Class constructor. */ - IndicatorCandle(const TS& _icparams, IndicatorBase* _indi_src = NULL, int _indi_mode = 0) : icparams(_icparams) { + IndicatorCandle(const TS& _icparams, IndicatorBase* _indi_src = NULL, int _indi_mode = 0) { + icparams = _icparams; if (_indi_src != NULL) { SetDataSource(_indi_src, _indi_mode); } @@ -83,9 +84,26 @@ class IndicatorCandle : public IndicatorBase { * @return * Returns IndicatorDataEntry struct filled with indicator values. */ - IndicatorDataEntry GetEntry(int _timestamp = 0) { + IndicatorDataEntry GetEntry(int _index = -1) override { ResetLastError(); + int _ishift = _index >= 0 ? _index : icparams.GetShift(); + long _bar_time = GetBarTime(_ishift); + + // Trying to fetch entry from cache. + IndicatorDataEntry _entry = icdata.GetByKey(_bar_time); + + if (_bar_time > 0 && !_entry.IsValid() && !_entry.CheckFlag(INDI_ENTRY_FLAG_INSUFFICIENT_DATA)) { + // There is no valid entry in the cache. + _entry.Resize(iparams.GetMaxModes()); + _entry.timestamp = _bar_time; + } + CandleOHLC _entry = icdata.GetByKey(_timestamp); + + if (!_entry.IsValid() && !_entry.CheckFlag(INDI_ENTRY_FLAG_INSUFFICIENT_DATA)) { + // There is no candle for given timestamp. + } + /* IndicatorDataEntry _entry = icdata.GetByKey(_timestamp); if (!_entry.IsValid() && !_entry.CheckFlag(INDI_ENTRY_FLAG_INSUFFICIENT_DATA)) { diff --git a/Indicator/IndicatorTf.h b/Indicator/IndicatorTf.h index 956fb2b45..21350c445 100644 --- a/Indicator/IndicatorTf.h +++ b/Indicator/IndicatorTf.h @@ -37,7 +37,8 @@ /** * Class to deal with candle indicators. */ -class IndicatorTf : public IndicatorCandle { +template +class IndicatorTf : public IndicatorCandle { protected: /* Protected methods */ @@ -78,7 +79,7 @@ class IndicatorTf : public IndicatorCandle { /** * Class constructor with parameters. */ - IndicatorTf(IndicatorTfParams &_params) : IndicatorCandle(_params) { Init(); } + IndicatorTf(TFP &_params) : IndicatorCandle(_params) { Init(); } }; #endif diff --git a/Indicator/tests/IndicatorTf.test.mq5 b/Indicator/tests/IndicatorTf.test.mq5 index 5c68d79a2..ab020542a 100644 --- a/Indicator/tests/IndicatorTf.test.mq5 +++ b/Indicator/tests/IndicatorTf.test.mq5 @@ -22,16 +22,37 @@ /** * @file * Test functionality of IndicatorTf class. + * + * Idea is to check if ticks from IndicatorTick will be properly grouped by given timespan/timeframe. */ // Includes. #include "../../Test.mqh" #include "../IndicatorTf.h" +// Structs. +struct IndicatorTfDummyParams : IndicatorTfParams { + IndicatorTfDummyParams(uint _spc = 60) : IndicatorTfParams(_spc) {} +}; + +/** + * Price Indicator. + */ +class IndicatorTfDummy : public IndicatorTf { + public: + IndicatorTfDummy(uint _spc) : IndicatorTf(_spc) {} + IndicatorTfDummy(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) : IndicatorTf(_tf) {} + IndicatorTfDummy(ENUM_TIMEFRAMES_INDEX _tfi = 0) : IndicatorTf(_tfi) {} +}; + /** * Implements OnInit(). */ int OnInit() { // @todo + + // 1-second candles. + Ref indi_tf = new IndicatorTfDummy(1); + return (INIT_SUCCEEDED); } From 769631969ee8af9bdfbd915a68b45aa44b6bc3c9 Mon Sep 17 00:00:00 2001 From: Adrian Kierzkowski Date: Mon, 22 Nov 2021 19:50:10 +0100 Subject: [PATCH 25/77] WIP. Added idea of event listeners for indicators and emitting a historic and new entries. --- Indicator.mqh | 5 ++ Indicator/IndicatorCandle.h | 104 ++++++++++--------------- Indicator/IndicatorTick.h | 18 +++++ Indicator/tests/IndicatorTf.test.mq5 | 33 ++++++++ Indicator/tests/IndicatorTick.test.mq5 | 23 +++++- IndicatorBase.h | 43 ++++++++++ Util.h | 14 ++++ 7 files changed, 175 insertions(+), 65 deletions(-) diff --git a/Indicator.mqh b/Indicator.mqh index ccfe59441..389d9fc54 100644 --- a/Indicator.mqh +++ b/Indicator.mqh @@ -820,8 +820,13 @@ class Indicator : public IndicatorBase { * Sets indicator data source. */ void SetDataSource(IndicatorBase* _indi, int _input_mode = 0) { + if (indi_src.IsSet() && indi_src.Ptr() != _indi) { + indi_src.Ptr().RemoveListener(THIS_PTR); + } indi_src = _indi; + indi_src.Ptr().AddListener(THIS_PTR); iparams.SetDataSource(-1, _input_mode); + indi_src.Ptr().OnBecomeDataSourceFor(THIS_PTR); } /** diff --git a/Indicator/IndicatorCandle.h b/Indicator/IndicatorCandle.h index 7886ec953..f2321ff25 100644 --- a/Indicator/IndicatorCandle.h +++ b/Indicator/IndicatorCandle.h @@ -79,6 +79,17 @@ class IndicatorCandle : public IndicatorBase { /** * Returns the indicator's data entry. * + * We will fetch consecutive entries from the source indicator and check its + * timestamps. We need to gather entries matching calculated timespan. + * + * For example: We want 5s candle at shift=1. That mean we have to ask source + * indicator for entries between + * candle.timestamp + (1 * 5s) and candle.timestamp + (2 * 5s). + * + * The question is: How to calculate shift for source indicator's GetEntry()? + * + * + * * @see: IndicatorDataEntry. * * @return @@ -86,76 +97,18 @@ class IndicatorCandle : public IndicatorBase { */ IndicatorDataEntry GetEntry(int _index = -1) override { ResetLastError(); - int _ishift = _index >= 0 ? _index : icparams.GetShift(); + unsigned int _ishift = _index >= 0 ? _index : icparams.GetShift(); long _bar_time = GetBarTime(_ishift); - // Trying to fetch entry from cache. - IndicatorDataEntry _entry = icdata.GetByKey(_bar_time); + CandleOHLC _entry = icdata.GetByKey(_bar_time); - if (_bar_time > 0 && !_entry.IsValid() && !_entry.CheckFlag(INDI_ENTRY_FLAG_INSUFFICIENT_DATA)) { - // There is no valid entry in the cache. - _entry.Resize(iparams.GetMaxModes()); - _entry.timestamp = _bar_time; + if (!_entry.IsValid()) { + // There is no candle and won't ever be for given timestamp. } - CandleOHLC _entry = icdata.GetByKey(_timestamp); - - if (!_entry.IsValid() && !_entry.CheckFlag(INDI_ENTRY_FLAG_INSUFFICIENT_DATA)) { - // There is no candle for given timestamp. - } + IndicatorDataEntry _data_entry; - /* - IndicatorDataEntry _entry = icdata.GetByKey(_timestamp); - if (!_entry.IsValid() && !_entry.CheckFlag(INDI_ENTRY_FLAG_INSUFFICIENT_DATA)) { - _entry.Resize(icparams.GetMaxModes()); - _entry.timestamp = _timestamp; - for (int _mode = 0; _mode < (int)icparams.GetMaxModes(); _mode++) { - switch (icparams.GetDataValueType()) { - case TYPE_BOOL: - case TYPE_CHAR: - case TYPE_INT: - _entry.values[_mode] = GetValue(_mode, _timestamp); - break; - case TYPE_LONG: - _entry.values[_mode] = GetValue(_mode, _timestamp); - break; - case TYPE_UINT: - _entry.values[_mode] = GetValue(_mode, _timestamp); - break; - case TYPE_ULONG: - _entry.values[_mode] = GetValue(_mode, _timestamp); - break; - case TYPE_DOUBLE: - _entry.values[_mode] = GetValue(_mode, _timestamp); - break; - case TYPE_FLOAT: - _entry.values[_mode] = GetValue(_mode, _timestamp); - break; - case TYPE_STRING: - case TYPE_UCHAR: - default: - SetUserError(ERR_INVALID_PARAMETER); - break; - } - } - GetEntryAlter(_entry, _timestamp); - _entry.SetFlag(INDI_ENTRY_FLAG_IS_VALID, IsValidEntry(_entry)); - if (_entry.IsValid()) { - icdata.Add(_entry, _timestamp); - istate.is_changed = false; - istate.is_ready = true; - } else { - _entry.AddFlags(INDI_ENTRY_FLAG_INSUFFICIENT_DATA); - } - } - if (_LastError != ERR_NO_ERROR) { - istate.is_ready = false; - ResetLastError(); - } - return _entry; - */ - IndicatorDataEntry _foo; - return _foo; + return _data_entry; } /** @@ -197,12 +150,35 @@ class IndicatorCandle : public IndicatorBase { return false; } + /** + * Sends historic entries to listening indicators. May be overriden. + */ + void EmitHistory() override { + for (DictStructIterator> iter(icdata.Begin()); iter.IsValid(); ++iter) { + IndicatorDataEntry _entry = CandleToEntry(iter.Value()); + EmitEntry(_entry); + } + } + + /** + * @todo + */ + IndicatorDataEntry CandleToEntry(CandleOHLC& _candle) { + IndicatorDataEntry _entry; + return _entry; + } + /** * Sets indicator data source. */ void SetDataSource(IndicatorBase* _indi, int _input_mode = 0) { + if (indi_src.IsSet() && indi_src.Ptr() != _indi) { + indi_src.Ptr().RemoveListener(THIS_PTR); + } indi_src = _indi; + indi_src.Ptr().AddListener(THIS_PTR); icparams.SetDataSource(-1, _input_mode); + indi_src.Ptr().OnBecomeDataSourceFor(THIS_PTR); } /* Virtual methods */ diff --git a/Indicator/IndicatorTick.h b/Indicator/IndicatorTick.h index 9b1c3d6cf..e1213cc87 100644 --- a/Indicator/IndicatorTick.h +++ b/Indicator/IndicatorTick.h @@ -76,6 +76,24 @@ class IndicatorTick : public IndicatorBase { /* Virtual method implementations */ + /** + * Sends historic entries to listening indicators. May be overriden. + */ + void EmitHistory() override { + for (DictStructIterator> iter(itdata.Begin()); iter.IsValid(); ++iter) { + IndicatorDataEntry _entry = TickToEntry(iter.Value()); + EmitEntry(_entry); + } + } + + /** + * @todo + */ + IndicatorDataEntry TickToEntry(TickAB& _tick) { + IndicatorDataEntry _entry; + return _entry; + } + /** * Returns the indicator's data entry. * diff --git a/Indicator/tests/IndicatorTf.test.mq5 b/Indicator/tests/IndicatorTf.test.mq5 index ab020542a..75e5e19d9 100644 --- a/Indicator/tests/IndicatorTf.test.mq5 +++ b/Indicator/tests/IndicatorTf.test.mq5 @@ -29,6 +29,32 @@ // Includes. #include "../../Test.mqh" #include "../IndicatorTf.h" +#include "../IndicatorTick.h" + +// Structs. +struct IndicatorTickDummyParams : IndicatorParams { + IndicatorTickDummyParams() : IndicatorParams(INDI_TICK, 3, TYPE_DOUBLE) {} +}; + +class IndicatorTickDummy : public IndicatorTick { + public: + IndicatorTickDummy(string _symbol, int _shift = 0, string _name = "") + : IndicatorTick(INDI_TICK, _symbol, _shift, _name) { + SetSymbol(_symbol); + } + + string GetName() override { return "IndicatorTickDummy"; } + + void OnBecomeDataSourceFor(IndicatorBase* _base_indi) override { + // Feeding base indicator with historic entries of this indicator. + Print(GetName(), " became a data source for ", _base_indi.GetName()); + + IndicatorDataEntry _entry; + EmitEntry(_entry); + EmitEntry(_entry); + EmitEntry(_entry); + }; +}; // Structs. struct IndicatorTfDummyParams : IndicatorTfParams { @@ -43,6 +69,10 @@ class IndicatorTfDummy : public IndicatorTf { IndicatorTfDummy(uint _spc) : IndicatorTf(_spc) {} IndicatorTfDummy(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) : IndicatorTf(_tf) {} IndicatorTfDummy(ENUM_TIMEFRAMES_INDEX _tfi = 0) : IndicatorTf(_tfi) {} + + string GetName() override { return "IndicatorTfDummy(" + IntegerToString(icparams.spc) + ")"; } + + void OnDataSourceEntry(IndicatorDataEntry& entry) override { Print(GetName(), " got new entry!"); }; }; /** @@ -51,8 +81,11 @@ class IndicatorTfDummy : public IndicatorTf { int OnInit() { // @todo + Ref indi_tick = new IndicatorTickDummy(_Symbol); + // 1-second candles. Ref indi_tf = new IndicatorTfDummy(1); + indi_tf.Ptr().SetDataSource(indi_tick.Ptr()); return (INIT_SUCCEEDED); } diff --git a/Indicator/tests/IndicatorTick.test.mq5 b/Indicator/tests/IndicatorTick.test.mq5 index 0fc115be5..9b9a082e3 100644 --- a/Indicator/tests/IndicatorTick.test.mq5 +++ b/Indicator/tests/IndicatorTick.test.mq5 @@ -34,7 +34,28 @@ struct IndicatorTickDummyParams : IndicatorParams { }; /** - * Price Indicator. + * Tick indicator is an indicator that provides per-tick information. + * When asked to return data via GetEntry() it could fetch data from pre-made + * tick history or generate tick on-the-fly from remote source and save it in + * the history. + * + * Note that indicators could provide data also for future shifts, so shift=-10 + * is perfectly valid for them when doing GetEntry()/GetValue(). + * + * Tick indicator may become a data source for Candle indicator. In this + * scenario, when trying to fetch candle for a given shift, tick indicator is + * asked for ticks in a given timespan. E.g., Candle indicator may work in a 5s + * timespans, so when fetching candle with shift now+1, Tick indicator will be + * asked for ticks between now+5s and now+10s. + *rmf + * In order to fetch consecutive candles, you have to call + * IndicatorCandle::NextMaybe() to check whether new candle is ready to be + * processed. If yes, then new candle will be at index 0. + * + * if (indi_candle.NextMaybe()) { + * double _open = indi_candle.Open(0); // Shift 0 = current candle. + * double _close = indi_candle.Close(0); // Shift 0 = current candle. + * } */ class IndicatorTickDummy : public IndicatorTick { public: diff --git a/IndicatorBase.h b/IndicatorBase.h index e13b9ed17..d54f50417 100644 --- a/IndicatorBase.h +++ b/IndicatorBase.h @@ -70,6 +70,7 @@ class IndicatorBase : public Chart { Ref indi_src; // // Indicator used as data source. int indi_src_mode; // Mode of source indicator IndicatorCalculateCache cache; + ARRAY(WeakRef, listeners); // List of indicators that listens for events from this one. public: /* Indicator enumerations */ @@ -351,6 +352,22 @@ class IndicatorBase : public Chart { Chart::Set(_param, _value); } + /** + * Adds event listener. + */ + void AddListener(IndicatorBase* _indi) { + WeakRef _ref = _indi; + ArrayPushObject(listeners, _ref); + } + + /** + * Removes event listener. + */ + void RemoveListener(IndicatorBase* _indi) { + WeakRef _ref = _indi; + Util::ArrayRemoveFirst(listeners, _ref); + } + /** * Sets indicator data source. */ @@ -473,6 +490,32 @@ class IndicatorBase : public Chart { */ virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _index = -1) = NULL; + /** + * Sends entry to listening indicators. + */ + void EmitEntry(IndicatorDataEntry& entry) { + for (int i = 0; i < ArraySize(listeners); ++i) { + if (listeners[i].ObjectExists()) { + listeners[i].Ptr().OnDataSourceEntry(entry); + } + } + } + + /** + * Sends historic entries to listening indicators. May be overriden. + */ + virtual void EmitHistory() {} + + /** + * Called when data source emits new entry (historic or future one). + */ + virtual void OnDataSourceEntry(IndicatorDataEntry& entry){}; + + /** + * Called when indicator became a data source for other indicator. + */ + virtual void OnBecomeDataSourceFor(IndicatorBase* _base_indi){}; + /** * Returns indicator value for a given shift and mode. */ diff --git a/Util.h b/Util.h index 12ccb0c28..42a8a3009 100644 --- a/Util.h +++ b/Util.h @@ -65,6 +65,20 @@ class Util { return _result; } + /** + * Removes value from the array. + */ + template + static bool ArrayRemoveFirst(T& _array[], T& value) { + for (int i = 0; i < ArraySize(_array); ++i) { + if (_array[i] == value) { + ArrayRemove(_array, i); + return true; + } + } + return false; + } + template static T Print(T& _array[]) { string _result; From 1d2427aecd38ef111b0565c9144fcdff85e1a92c Mon Sep 17 00:00:00 2001 From: Adrian Kierzkowski Date: Tue, 23 Nov 2021 18:40:18 +0100 Subject: [PATCH 26/77] WIP. Added candle grouping when receiving ticks via OnDataSourceEntry(). --- Buffer/BufferCandle.h | 2 +- Candle.struct.h | 32 +++++++++++++++++ Indicator/IndicatorCandle.h | 52 +++++++++++++++++++++++++--- Indicator/IndicatorTick.h | 10 ++++-- Indicator/tests/IndicatorTf.test.mq5 | 36 +++++++++++++------ 5 files changed, 114 insertions(+), 18 deletions(-) diff --git a/Buffer/BufferCandle.h b/Buffer/BufferCandle.h index b0230c58a..8401ee3f8 100644 --- a/Buffer/BufferCandle.h +++ b/Buffer/BufferCandle.h @@ -32,7 +32,7 @@ * Class to store struct data. */ template -class BufferCandle : public BufferStruct> { +class BufferCandle : public BufferStruct> { protected: protected: /* Protected methods */ diff --git a/Candle.struct.h b/Candle.struct.h index 6a7338c27..4d4e03dfb 100644 --- a/Candle.struct.h +++ b/Candle.struct.h @@ -49,6 +49,7 @@ struct CandleOHLC #endif { T open, high, low, close; + // Struct constructors. CandleOHLC(T _open = 0, T _high = 0, T _low = 0, T _close = 0) : open(_open), high(_high), low(_low), close(_close) {} CandleOHLC(ARRAY_REF(T, _prices)) { @@ -216,6 +217,37 @@ struct CandleOHLC string ToCSV() { return StringFormat("%g,%g,%g,%g", open, high, low, close); } }; +/* Structure for storing OHLC values with open and close timestamp. */ +template +struct CandleOCTOHLC : CandleOHLC { + long open_timestamp, close_timestamp; + + // Struct constructors. + CandleOCTOHLC(T _open = 0, T _high = 0, T _low = 0, T _close = 0, long _open_timestamp = -1, + long _close_timestamp = -1) + : CandleOHLC(_open, _high, _low, _close), open_timestamp(_open_timestamp), close_timestamp(_close_timestamp) {} + + // Updates OHLC values taking into consideration tick's timestamp. + void Update(long _timestamp, T _price) { + if (_timestamp < open_timestamp) { + open_timestamp = _timestamp; + open = _price; + } + if (_timestamp > close_timestamp) { + close_timestamp = _timestamp; + close = _price; + } + high = MathMax(high, _price); + low = MathMin(low, _price); + } + + // Returns timestamp of open price. + long GetOpenTimestamp() { return open_timestamp; } + + // Returns timestamp of close price. + long GetCloseTimestamp() { return close_timestamp; } +}; + /* Structore for storing OHLC values with timestamp. */ template struct CandleTOHLC : CandleOHLC { diff --git a/Indicator/IndicatorCandle.h b/Indicator/IndicatorCandle.h index f2321ff25..603a20117 100644 --- a/Indicator/IndicatorCandle.h +++ b/Indicator/IndicatorCandle.h @@ -154,8 +154,8 @@ class IndicatorCandle : public IndicatorBase { * Sends historic entries to listening indicators. May be overriden. */ void EmitHistory() override { - for (DictStructIterator> iter(icdata.Begin()); iter.IsValid(); ++iter) { - IndicatorDataEntry _entry = CandleToEntry(iter.Value()); + for (DictStructIterator> iter(icdata.Begin()); iter.IsValid(); ++iter) { + IndicatorDataEntry _entry = CandleToEntry(iter.Key(), iter.Value()); EmitEntry(_entry); } } @@ -163,11 +163,46 @@ class IndicatorCandle : public IndicatorBase { /** * @todo */ - IndicatorDataEntry CandleToEntry(CandleOHLC& _candle) { - IndicatorDataEntry _entry; + IndicatorDataEntry CandleToEntry(long _timestamp, CandleOCTOHLC& _candle) { + IndicatorDataEntry _entry(4); + _entry.timestamp = _timestamp; + _entry.values[0] = _candle.open; + _entry.values[1] = _candle.high; + _entry.values[2] = _candle.low; + _entry.values[3] = _candle.close; + _entry.SetFlags(INDI_ENTRY_FLAG_IS_VALID); return _entry; } + /** + * Adds tick's price to the matching candle and updates its OHLC values. + */ + void UpdateCandle(long _tick_timestamp, double _price) { + long _candle_timestamp = CalcCandleTimestamp(_tick_timestamp); + + CandleOCTOHLC _candle; + if (icdata.KeyExists(_candle_timestamp)) { + _candle = icdata.GetByKey(_candle_timestamp); + _candle.Update(_tick_timestamp, _price); + } else { + _candle = CandleOCTOHLC(_price, _price, _price, _price, _tick_timestamp, _tick_timestamp); + } + + icdata.Set(_candle_timestamp, _candle); + } + + /** + * Calculates candle's timestamp from tick's timestamp. + */ + long CalcCandleTimestamp(long _tick_timestamp) { + return _tick_timestamp - _tick_timestamp % (icparams.GetSecsPerCandle() * 1000); + } + + /** + * Called when data source emits new entry (historic or future one). + */ + virtual void OnDataSourceEntry(IndicatorDataEntry& entry) { UpdateCandle(entry.timestamp, entry[0]); }; + /** * Sets indicator data source. */ @@ -181,6 +216,15 @@ class IndicatorCandle : public IndicatorBase { indi_src.Ptr().OnBecomeDataSourceFor(THIS_PTR); } + string CandlesToString() { + string _result; + for (DictStructIterator> iter(icdata.Begin()); iter.IsValid(); ++iter) { + IndicatorDataEntry _entry = CandleToEntry(iter.Key(), iter.Value()); + _result += IntegerToString(iter.Key()) + ": " + _entry.ToString() + "\n"; + } + return _result; + } + /* Virtual methods */ /** diff --git a/Indicator/IndicatorTick.h b/Indicator/IndicatorTick.h index e1213cc87..5d7dd0925 100644 --- a/Indicator/IndicatorTick.h +++ b/Indicator/IndicatorTick.h @@ -81,7 +81,7 @@ class IndicatorTick : public IndicatorBase { */ void EmitHistory() override { for (DictStructIterator> iter(itdata.Begin()); iter.IsValid(); ++iter) { - IndicatorDataEntry _entry = TickToEntry(iter.Value()); + IndicatorDataEntry _entry = TickToEntry(iter.Key(), iter.Value()); EmitEntry(_entry); } } @@ -89,8 +89,12 @@ class IndicatorTick : public IndicatorBase { /** * @todo */ - IndicatorDataEntry TickToEntry(TickAB& _tick) { - IndicatorDataEntry _entry; + IndicatorDataEntry TickToEntry(long _timestamp, TickAB& _tick) { + IndicatorDataEntry _entry(2); + _entry.timestamp = _timestamp; + _entry.values[0] = _tick.ask; + _entry.values[1] = _tick.bid; + _entry.SetFlags(INDI_ENTRY_FLAG_IS_VALID); return _entry; } diff --git a/Indicator/tests/IndicatorTf.test.mq5 b/Indicator/tests/IndicatorTf.test.mq5 index 75e5e19d9..a16b19aec 100644 --- a/Indicator/tests/IndicatorTf.test.mq5 +++ b/Indicator/tests/IndicatorTf.test.mq5 @@ -31,11 +31,12 @@ #include "../IndicatorTf.h" #include "../IndicatorTick.h" -// Structs. +// Parasms for dummy tick-based indicator. struct IndicatorTickDummyParams : IndicatorParams { IndicatorTickDummyParams() : IndicatorParams(INDI_TICK, 3, TYPE_DOUBLE) {} }; +// Dummy tick-based indicator. class IndicatorTickDummy : public IndicatorTick { public: IndicatorTickDummy(string _symbol, int _shift = 0, string _name = "") @@ -49,20 +50,24 @@ class IndicatorTickDummy : public IndicatorTick(1.0f, 1.01f))); + EmitEntry(TickToEntry(1500, TickAB(1.5f, 1.51f))); + EmitEntry(TickToEntry(2000, TickAB(2.0f, 2.01f))); + EmitEntry(TickToEntry(3000, TickAB(3.0f, 3.01f))); + EmitEntry(TickToEntry(4000, TickAB(4.0f, 4.01f))); + EmitEntry(TickToEntry(4100, TickAB(4.1f, 4.11f))); + EmitEntry(TickToEntry(4200, TickAB(4.2f, 4.21f))); + EmitEntry(TickToEntry(4800, TickAB(4.8f, 4.81f))); }; }; -// Structs. +// Params for dummy candle-based indicator. struct IndicatorTfDummyParams : IndicatorTfParams { IndicatorTfDummyParams(uint _spc = 60) : IndicatorTfParams(_spc) {} }; /** - * Price Indicator. + * Dummy candle-based indicator. */ class IndicatorTfDummy : public IndicatorTf { public: @@ -72,20 +77,31 @@ class IndicatorTfDummy : public IndicatorTf { string GetName() override { return "IndicatorTfDummy(" + IntegerToString(icparams.spc) + ")"; } - void OnDataSourceEntry(IndicatorDataEntry& entry) override { Print(GetName(), " got new entry!"); }; + void OnDataSourceEntry(IndicatorDataEntry& entry) override { + // When overriding OnDataSourceEntry() we have to remember to call parent + // method, because IndicatorCandle also need to invoke it in order to + // create/update matching candle. + IndicatorTf::OnDataSourceEntry(entry); + + Print(GetName(), " got new tick at ", entry.timestamp, ": ", entry.ToString()); + } }; /** * Implements OnInit(). */ int OnInit() { - // @todo - Ref indi_tick = new IndicatorTickDummy(_Symbol); // 1-second candles. Ref indi_tf = new IndicatorTfDummy(1); + + // Candles will take data from tick indicator. indi_tf.Ptr().SetDataSource(indi_tick.Ptr()); + // Printing all grouped candles. + Print(indi_tf.Ptr().GetName(), "'s candles:"); + Print(indi_tf.Ptr().CandlesToString()); + return (INIT_SUCCEEDED); } From e625d6ffc3fc522c84551294d744dab9f09293b8 Mon Sep 17 00:00:00 2001 From: Adrian Kierzkowski Date: Thu, 25 Nov 2021 18:57:22 +0100 Subject: [PATCH 27/77] Working simulation of real ticking indicator. --- Indicator/IndicatorCandle.h | 5 +- Indicator/tests/IndicatorTf.test.mq5 | 95 +++++++++++++++++++++++++--- 2 files changed, 91 insertions(+), 9 deletions(-) diff --git a/Indicator/IndicatorCandle.h b/Indicator/IndicatorCandle.h index 603a20117..fa740f392 100644 --- a/Indicator/IndicatorCandle.h +++ b/Indicator/IndicatorCandle.h @@ -201,7 +201,10 @@ class IndicatorCandle : public IndicatorBase { /** * Called when data source emits new entry (historic or future one). */ - virtual void OnDataSourceEntry(IndicatorDataEntry& entry) { UpdateCandle(entry.timestamp, entry[0]); }; + virtual void OnDataSourceEntry(IndicatorDataEntry& entry) { + // Updating candle from bid price. + UpdateCandle(entry.timestamp, entry[1]); + }; /** * Sets indicator data source. diff --git a/Indicator/tests/IndicatorTf.test.mq5 b/Indicator/tests/IndicatorTf.test.mq5 index a16b19aec..3593d6194 100644 --- a/Indicator/tests/IndicatorTf.test.mq5 +++ b/Indicator/tests/IndicatorTf.test.mq5 @@ -28,12 +28,50 @@ // Includes. #include "../../Test.mqh" +#include "../../Util.h" #include "../IndicatorTf.h" #include "../IndicatorTick.h" -// Parasms for dummy tick-based indicator. +// Params for real tick-based indicator. +struct IndicatorTickRealParams : IndicatorParams { + IndicatorTickRealParams() : IndicatorParams(INDI_TICK, 3, TYPE_DOUBLE) {} +}; + +// Real tick-based indicator. +class IndicatorTickReal : public IndicatorTick { + public: + IndicatorTickReal(string _symbol, int _shift = 0, string _name = "") + : IndicatorTick(INDI_TICK, _symbol, _shift, _name) { + SetSymbol(_symbol); + } + + string GetName() override { return "IndicatorTickDummy"; } + + void OnBecomeDataSourceFor(IndicatorBase* _base_indi) override { + // Feeding base indicator with historic entries of this indicator. + Print(GetName(), " became a data source for ", _base_indi.GetName()); + + int _ticks_to_emit = 100; + + // For testing purposes we are emitting 100 last ticks. + for (int i = 0; i < MathMin(Bars(GetSymbol(), GetTf()), _ticks_to_emit); ++i) { + long _timestamp = ChartStatic::iTime(GetSymbol(), GetTf(), _ticks_to_emit - i - 1); + double _bid = ChartStatic::iClose(GetSymbol(), GetTf(), _ticks_to_emit - i - 1); + EmitEntry(TickToEntry(_timestamp, TickAB(0.0f, _bid))); + } + }; + + void OnTick() override { + long _timestamp = ChartStatic::iTime(GetSymbol(), GetTf()); + double _bid = ChartStatic::iClose(GetSymbol(), GetTf()); + // MT doesn't provide historical ask prices, so we're filling tick with bid price only. + EmitEntry(TickToEntry(_timestamp, TickAB(_bid, _bid))); + } +}; + +// Params for dummy tick-based indicator. struct IndicatorTickDummyParams : IndicatorParams { - IndicatorTickDummyParams() : IndicatorParams(INDI_TICK, 3, TYPE_DOUBLE) {} + IndicatorTickDummyParams() : IndicatorParams(INDI_TICK, 2, TYPE_DOUBLE) {} }; // Dummy tick-based indicator. @@ -87,21 +125,62 @@ class IndicatorTfDummy : public IndicatorTf { } }; +/** + * Helper class to store all indicators and call OnTick() on them. + */ +class _Indicators { + Ref _indis[]; + + public: + void Add(IndicatorBase* _indi) { + Ref _ref = _indi; + ArrayPushObject(_indis, _ref); + } + + void Remove(IndicatorBase* _indi) { + Ref _ref = _indi; + Util::ArrayRemoveFirst(_indis, _ref); + } + + void Tick() { + for (int i = 0; i < ArraySize(_indis); ++i) { + _indis[i].Ptr().OnTick(); + } + } + +} indicators; + +Ref indi_tick; +Ref indi_tf; + /** * Implements OnInit(). */ int OnInit() { - Ref indi_tick = new IndicatorTickDummy(_Symbol); + indicators.Add(indi_tick = new IndicatorTickReal(_Symbol)); // 1-second candles. - Ref indi_tf = new IndicatorTfDummy(1); + indicators.Add(indi_tf = new IndicatorTfDummy(1)); - // Candles will take data from tick indicator. + // Candles will be initialized from tick's history. indi_tf.Ptr().SetDataSource(indi_tick.Ptr()); - // Printing all grouped candles. - Print(indi_tf.Ptr().GetName(), "'s candles:"); + // Checking if there are candles for last 100 ticks. + Print(indi_tf.Ptr().GetName(), "'s historic candles (from 100 ticks):"); Print(indi_tf.Ptr().CandlesToString()); - return (INIT_SUCCEEDED); } + +/** + * Implements OnTick(). + */ +void OnTick() { indicators.Tick(); } + +/** + * Implements OnDeinit(). + */ +void OnDeinit(const int reason) { + // Printing all grouped candles. + Print(indi_tf.Ptr().GetName(), "'s all candles:"); + Print(indi_tf.Ptr().CandlesToString()); +} From 04378bd12ecbc66eed7325aee36a6fccafda850e Mon Sep 17 00:00:00 2001 From: Adrian Kierzkowski Date: Fri, 26 Nov 2021 20:00:02 +0100 Subject: [PATCH 28/77] Moved example indicator classes into separate files. Added OnIndicator support for AMA indicator. --- Indicator/IndicatorCandle.h | 28 +--- Indicator/tests/IndicatorTf.test.mq5 | 135 +++---------------- Indicator/tests/classes/IndicatorTfDummy.h | 56 ++++++++ Indicator/tests/classes/IndicatorTickDummy.h | 29 ++++ Indicator/tests/classes/IndicatorTickReal.h | 67 +++++++++ Indicator/tests/classes/Indicators.h | 73 ++++++++++ IndicatorBase.h | 4 + Indicators/Indi_AMA.mqh | 18 ++- Storage/ValueStorage.h | 4 + 9 files changed, 272 insertions(+), 142 deletions(-) create mode 100644 Indicator/tests/classes/IndicatorTfDummy.h create mode 100644 Indicator/tests/classes/IndicatorTickDummy.h create mode 100644 Indicator/tests/classes/IndicatorTickReal.h create mode 100644 Indicator/tests/classes/Indicators.h diff --git a/Indicator/IndicatorCandle.h b/Indicator/IndicatorCandle.h index fa740f392..31fa5bee4 100644 --- a/Indicator/IndicatorCandle.h +++ b/Indicator/IndicatorCandle.h @@ -79,17 +79,6 @@ class IndicatorCandle : public IndicatorBase { /** * Returns the indicator's data entry. * - * We will fetch consecutive entries from the source indicator and check its - * timestamps. We need to gather entries matching calculated timespan. - * - * For example: We want 5s candle at shift=1. That mean we have to ask source - * indicator for entries between - * candle.timestamp + (1 * 5s) and candle.timestamp + (2 * 5s). - * - * The question is: How to calculate shift for source indicator's GetEntry()? - * - * - * * @see: IndicatorDataEntry. * * @return @@ -98,17 +87,14 @@ class IndicatorCandle : public IndicatorBase { IndicatorDataEntry GetEntry(int _index = -1) override { ResetLastError(); unsigned int _ishift = _index >= 0 ? _index : icparams.GetShift(); - long _bar_time = GetBarTime(_ishift); - - CandleOHLC _entry = icdata.GetByKey(_bar_time); + long _candle_time = CalcCandleTimestamp(GetBarTime(_ishift)); + CandleOCTOHLC _candle = icdata.GetByKey(_candle_time); - if (!_entry.IsValid()) { - // There is no candle and won't ever be for given timestamp. + if (!_candle.IsValid()) { + Print(GetName(), ": Missing candle at shift ", _index, " (", _candle_time, ")"); } - IndicatorDataEntry _data_entry; - - return _data_entry; + return CandleToEntry(_candle_time, _candle); } /** @@ -161,7 +147,7 @@ class IndicatorCandle : public IndicatorBase { } /** - * @todo + * Converts candle into indicator's data entry. */ IndicatorDataEntry CandleToEntry(long _timestamp, CandleOCTOHLC& _candle) { IndicatorDataEntry _entry(4); @@ -170,7 +156,7 @@ class IndicatorCandle : public IndicatorBase { _entry.values[1] = _candle.high; _entry.values[2] = _candle.low; _entry.values[3] = _candle.close; - _entry.SetFlags(INDI_ENTRY_FLAG_IS_VALID); + _entry.SetFlag(INDI_ENTRY_FLAG_IS_VALID, _candle.IsValid()); return _entry; } diff --git a/Indicator/tests/IndicatorTf.test.mq5 b/Indicator/tests/IndicatorTf.test.mq5 index 3593d6194..0096c7310 100644 --- a/Indicator/tests/IndicatorTf.test.mq5 +++ b/Indicator/tests/IndicatorTf.test.mq5 @@ -27,131 +27,19 @@ */ // Includes. +#include "../../Indicators/Indi_AMA.mqh" #include "../../Test.mqh" #include "../../Util.h" #include "../IndicatorTf.h" #include "../IndicatorTick.h" +#include "classes/IndicatorTfDummy.h" +#include "classes/IndicatorTickReal.h" +#include "classes/Indicators.h" -// Params for real tick-based indicator. -struct IndicatorTickRealParams : IndicatorParams { - IndicatorTickRealParams() : IndicatorParams(INDI_TICK, 3, TYPE_DOUBLE) {} -}; - -// Real tick-based indicator. -class IndicatorTickReal : public IndicatorTick { - public: - IndicatorTickReal(string _symbol, int _shift = 0, string _name = "") - : IndicatorTick(INDI_TICK, _symbol, _shift, _name) { - SetSymbol(_symbol); - } - - string GetName() override { return "IndicatorTickDummy"; } - - void OnBecomeDataSourceFor(IndicatorBase* _base_indi) override { - // Feeding base indicator with historic entries of this indicator. - Print(GetName(), " became a data source for ", _base_indi.GetName()); - - int _ticks_to_emit = 100; - - // For testing purposes we are emitting 100 last ticks. - for (int i = 0; i < MathMin(Bars(GetSymbol(), GetTf()), _ticks_to_emit); ++i) { - long _timestamp = ChartStatic::iTime(GetSymbol(), GetTf(), _ticks_to_emit - i - 1); - double _bid = ChartStatic::iClose(GetSymbol(), GetTf(), _ticks_to_emit - i - 1); - EmitEntry(TickToEntry(_timestamp, TickAB(0.0f, _bid))); - } - }; - - void OnTick() override { - long _timestamp = ChartStatic::iTime(GetSymbol(), GetTf()); - double _bid = ChartStatic::iClose(GetSymbol(), GetTf()); - // MT doesn't provide historical ask prices, so we're filling tick with bid price only. - EmitEntry(TickToEntry(_timestamp, TickAB(_bid, _bid))); - } -}; - -// Params for dummy tick-based indicator. -struct IndicatorTickDummyParams : IndicatorParams { - IndicatorTickDummyParams() : IndicatorParams(INDI_TICK, 2, TYPE_DOUBLE) {} -}; - -// Dummy tick-based indicator. -class IndicatorTickDummy : public IndicatorTick { - public: - IndicatorTickDummy(string _symbol, int _shift = 0, string _name = "") - : IndicatorTick(INDI_TICK, _symbol, _shift, _name) { - SetSymbol(_symbol); - } - - string GetName() override { return "IndicatorTickDummy"; } - - void OnBecomeDataSourceFor(IndicatorBase* _base_indi) override { - // Feeding base indicator with historic entries of this indicator. - Print(GetName(), " became a data source for ", _base_indi.GetName()); - - EmitEntry(TickToEntry(1000, TickAB(1.0f, 1.01f))); - EmitEntry(TickToEntry(1500, TickAB(1.5f, 1.51f))); - EmitEntry(TickToEntry(2000, TickAB(2.0f, 2.01f))); - EmitEntry(TickToEntry(3000, TickAB(3.0f, 3.01f))); - EmitEntry(TickToEntry(4000, TickAB(4.0f, 4.01f))); - EmitEntry(TickToEntry(4100, TickAB(4.1f, 4.11f))); - EmitEntry(TickToEntry(4200, TickAB(4.2f, 4.21f))); - EmitEntry(TickToEntry(4800, TickAB(4.8f, 4.81f))); - }; -}; - -// Params for dummy candle-based indicator. -struct IndicatorTfDummyParams : IndicatorTfParams { - IndicatorTfDummyParams(uint _spc = 60) : IndicatorTfParams(_spc) {} -}; - -/** - * Dummy candle-based indicator. - */ -class IndicatorTfDummy : public IndicatorTf { - public: - IndicatorTfDummy(uint _spc) : IndicatorTf(_spc) {} - IndicatorTfDummy(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) : IndicatorTf(_tf) {} - IndicatorTfDummy(ENUM_TIMEFRAMES_INDEX _tfi = 0) : IndicatorTf(_tfi) {} - - string GetName() override { return "IndicatorTfDummy(" + IntegerToString(icparams.spc) + ")"; } - - void OnDataSourceEntry(IndicatorDataEntry& entry) override { - // When overriding OnDataSourceEntry() we have to remember to call parent - // method, because IndicatorCandle also need to invoke it in order to - // create/update matching candle. - IndicatorTf::OnDataSourceEntry(entry); - - Print(GetName(), " got new tick at ", entry.timestamp, ": ", entry.ToString()); - } -}; - -/** - * Helper class to store all indicators and call OnTick() on them. - */ -class _Indicators { - Ref _indis[]; - - public: - void Add(IndicatorBase* _indi) { - Ref _ref = _indi; - ArrayPushObject(_indis, _ref); - } - - void Remove(IndicatorBase* _indi) { - Ref _ref = _indi; - Util::ArrayRemoveFirst(_indis, _ref); - } - - void Tick() { - for (int i = 0; i < ArraySize(_indis); ++i) { - _indis[i].Ptr().OnTick(); - } - } - -} indicators; - +Indicators indicators; Ref indi_tick; Ref indi_tf; +Ref indi_ama; /** * Implements OnInit(). @@ -162,9 +50,15 @@ int OnInit() { // 1-second candles. indicators.Add(indi_tf = new IndicatorTfDummy(1)); + // 1-second candles. + indicators.Add(indi_ama = new Indi_AMA()); + // Candles will be initialized from tick's history. indi_tf.Ptr().SetDataSource(indi_tick.Ptr()); + // AMA will work on the candle indicator. + indi_ama.Ptr().SetDataSource(indi_tf.Ptr()); + // Checking if there are candles for last 100 ticks. Print(indi_tf.Ptr().GetName(), "'s historic candles (from 100 ticks):"); Print(indi_tf.Ptr().CandlesToString()); @@ -174,7 +68,10 @@ int OnInit() { /** * Implements OnTick(). */ -void OnTick() { indicators.Tick(); } +void OnTick() { + indicators.Tick(); + Print("Tick: \n" + indicators.ToString(0)); +} /** * Implements OnDeinit(). diff --git a/Indicator/tests/classes/IndicatorTfDummy.h b/Indicator/tests/classes/IndicatorTfDummy.h new file mode 100644 index 000000000..fc79a3634 --- /dev/null +++ b/Indicator/tests/classes/IndicatorTfDummy.h @@ -0,0 +1,56 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2021, EA31337 Ltd | +//| https://github.com/EA31337 | +//+------------------------------------------------------------------+ + +/* + * This file is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * @file + * Dummy candle-based indicator. + */ + +#ifndef __MQL__ +// Allows the preprocessor to include a header file when it is needed. +#pragma once +#endif + +// Params for dummy candle-based indicator. +struct IndicatorTfDummyParams : IndicatorTfParams { + IndicatorTfDummyParams(uint _spc = 60) : IndicatorTfParams(_spc) {} +}; + +/** + * Dummy candle-based indicator. + */ +class IndicatorTfDummy : public IndicatorTf { + public: + IndicatorTfDummy(uint _spc) : IndicatorTf(_spc) {} + IndicatorTfDummy(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) : IndicatorTf(_tf) {} + IndicatorTfDummy(ENUM_TIMEFRAMES_INDEX _tfi = 0) : IndicatorTf(_tfi) {} + + string GetName() override { return "IndicatorTfDummy(" + IntegerToString(icparams.spc) + ")"; } + + void OnDataSourceEntry(IndicatorDataEntry& entry) override { + // When overriding OnDataSourceEntry() we have to remember to call parent + // method, because IndicatorCandle also need to invoke it in order to + // create/update matching candle. + IndicatorTf::OnDataSourceEntry(entry); + + Print(GetName(), " got new tick at ", entry.timestamp, ": ", entry.ToString()); + } +}; diff --git a/Indicator/tests/classes/IndicatorTickDummy.h b/Indicator/tests/classes/IndicatorTickDummy.h new file mode 100644 index 000000000..355659ff9 --- /dev/null +++ b/Indicator/tests/classes/IndicatorTickDummy.h @@ -0,0 +1,29 @@ +// Params for dummy tick-based indicator. +struct IndicatorTickDummyParams : IndicatorParams { + IndicatorTickDummyParams() : IndicatorParams(INDI_TICK, 2, TYPE_DOUBLE) {} +}; + +// Dummy tick-based indicator. +class IndicatorTickDummy : public IndicatorTick { + public: + IndicatorTickDummy(string _symbol, int _shift = 0, string _name = "") + : IndicatorTick(INDI_TICK, _symbol, _shift, _name) { + SetSymbol(_symbol); + } + + string GetName() override { return "IndicatorTickDummy"; } + + void OnBecomeDataSourceFor(IndicatorBase* _base_indi) override { + // Feeding base indicator with historic entries of this indicator. + Print(GetName(), " became a data source for ", _base_indi.GetName()); + + EmitEntry(TickToEntry(1000, TickAB(1.0f, 1.01f))); + EmitEntry(TickToEntry(1500, TickAB(1.5f, 1.51f))); + EmitEntry(TickToEntry(2000, TickAB(2.0f, 2.01f))); + EmitEntry(TickToEntry(3000, TickAB(3.0f, 3.01f))); + EmitEntry(TickToEntry(4000, TickAB(4.0f, 4.01f))); + EmitEntry(TickToEntry(4100, TickAB(4.1f, 4.11f))); + EmitEntry(TickToEntry(4200, TickAB(4.2f, 4.21f))); + EmitEntry(TickToEntry(4800, TickAB(4.8f, 4.81f))); + }; +}; diff --git a/Indicator/tests/classes/IndicatorTickReal.h b/Indicator/tests/classes/IndicatorTickReal.h new file mode 100644 index 000000000..00a2aafb3 --- /dev/null +++ b/Indicator/tests/classes/IndicatorTickReal.h @@ -0,0 +1,67 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2021, EA31337 Ltd | +//| https://github.com/EA31337 | +//+------------------------------------------------------------------+ + +/* + * This file is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * @file + * Real tick-based indicator. + */ + +#ifndef __MQL__ +// Allows the preprocessor to include a header file when it is needed. +#pragma once +#endif + +// Params for real tick-based indicator. +struct IndicatorTickRealParams : IndicatorParams { + IndicatorTickRealParams() : IndicatorParams(INDI_TICK, 3, TYPE_DOUBLE) {} +}; + +// Real tick-based indicator. +class IndicatorTickReal : public IndicatorTick { + public: + IndicatorTickReal(string _symbol, int _shift = 0, string _name = "") + : IndicatorTick(INDI_TICK, _symbol, _shift, _name) { + SetSymbol(_symbol); + } + + string GetName() override { return "IndicatorTickDummy"; } + + void OnBecomeDataSourceFor(IndicatorBase* _base_indi) override { + // Feeding base indicator with historic entries of this indicator. + Print(GetName(), " became a data source for ", _base_indi.GetName()); + + int _ticks_to_emit = 100; + + // For testing purposes we are emitting 100 last ticks. + for (int i = 0; i < MathMin(Bars(GetSymbol(), GetTf()), _ticks_to_emit); ++i) { + long _timestamp = ChartStatic::iTime(GetSymbol(), GetTf(), _ticks_to_emit - i - 1); + double _bid = ChartStatic::iClose(GetSymbol(), GetTf(), _ticks_to_emit - i - 1); + EmitEntry(TickToEntry(_timestamp, TickAB(0.0f, _bid))); + } + }; + + void OnTick() override { + long _timestamp = ChartStatic::iTime(GetSymbol(), GetTf()); + double _bid = ChartStatic::iClose(GetSymbol(), GetTf()); + // MT doesn't provide historical ask prices, so we're filling tick with bid price only. + EmitEntry(TickToEntry(_timestamp, TickAB(_bid, _bid))); + } +}; diff --git a/Indicator/tests/classes/Indicators.h b/Indicator/tests/classes/Indicators.h new file mode 100644 index 000000000..2022df473 --- /dev/null +++ b/Indicator/tests/classes/Indicators.h @@ -0,0 +1,73 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2021, EA31337 Ltd | +//| https://github.com/EA31337 | +//+------------------------------------------------------------------+ + +/* + * This file is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * @file + * Helper class to store all indicators and call OnTick() on them. + */ + +#ifndef __MQL__ +// Allows the preprocessor to include a header file when it is needed. +#pragma once +#endif + +// Includes. +#include "../../../IndicatorBase.h" +#include "../../../Refs.mqh" + +/** + * Helper class to store all indicators and call OnTick() on them. + */ +class Indicators { + Ref _indis[]; + + public: + void Add(IndicatorBase* _indi) { + Ref _ref = _indi; + ArrayPushObject(_indis, _ref); + } + + void Remove(IndicatorBase* _indi) { + Ref _ref = _indi; + Util::ArrayRemoveFirst(_indis, _ref); + } + + /** + * Executes OnTick() on every added indicator. + */ + void Tick() { + for (int i = 0; i < ArraySize(_indis); ++i) { + _indis[i].Ptr().OnTick(); + } + } + + /** + * Prints indicators' values at the given shift. + */ + string ToString(int _shift = 0) { + string _result; + for (int i = 0; i < ArraySize(_indis); ++i) { + IndicatorDataEntry _entry = _indis[i].Ptr().GetEntry(_shift); + _result += _indis[i].Ptr().GetName() + " = " + _entry.ToString() + "\n"; + } + return _result; + } +}; diff --git a/IndicatorBase.h b/IndicatorBase.h index d54f50417..d1f61d607 100644 --- a/IndicatorBase.h +++ b/IndicatorBase.h @@ -413,6 +413,10 @@ class IndicatorBase : public Chart { } ValueStorage* GetValueStorage(int _mode = 0) { + if (_mode >= ArraySize(value_storages)) { + ArrayResize(value_storages, _mode + 1); + } + if (value_storages[_mode] == NULL) { value_storages[_mode] = new IndicatorBufferValueStorage(THIS_PTR, _mode); } diff --git a/Indicators/Indi_AMA.mqh b/Indicators/Indi_AMA.mqh index 58a8bee10..25028689a 100644 --- a/Indicators/Indi_AMA.mqh +++ b/Indicators/Indi_AMA.mqh @@ -88,6 +88,19 @@ class Indi_AMA : public Indicator { #endif } + /** + * On-indicator version of AMA. + */ + static double iAMAOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _ama_period, + int _fast_ema_period, int _slow_ema_period, int _ama_shift, ENUM_APPLIED_PRICE _ap, + int _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_SHORT_DS( + _indi, _symbol, _tf, _ap, + Util::MakeKey("INDI_AMA", _ama_period, _fast_ema_period, _slow_ema_period, _ama_shift, (int)_ap)); + return iAMAOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_SHORT, _ama_period, _fast_ema_period, _slow_ema_period, + _ama_shift, _mode, _shift, _cache); + } + /** * Calculates AMA on the array of values. */ @@ -213,8 +226,9 @@ class Indi_AMA : public Indicator { break; case IDATA_INDICATOR: - // @todo - SetUserError(ERR_INVALID_PARAMETER); + _value = Indi_AMA::iAMAOnIndicator(GetDataSource(), GetSymbol(), GetTf(), /*[*/ GetPeriod(), GetFastPeriod(), + GetSlowPeriod(), GetAMAShift(), GetAppliedPrice() /*]*/, _mode, _ishift, + THIS_PTR); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Storage/ValueStorage.h b/Storage/ValueStorage.h index cf9105c30..6fa64909a 100644 --- a/Storage/ValueStorage.h +++ b/Storage/ValueStorage.h @@ -87,6 +87,10 @@ enum ENUM_IPEAK { IPEAK_LOWEST, IPEAK_HIGHEST }; ValueStorage *_price = PriceValueStorage::GetInstance(SYMBOL, TF, APPLIED_PRICE); \ INDICATOR_CALCULATE_POPULATE_CACHE(SYMBOL, TF, KEY) +#define INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_SHORT_DS(INDI, SYMBOL, TF, APPLIED_PRICE, KEY) \ + ValueStorage *_price = INDI.GetValueStorage(APPLIED_PRICE); \ + INDICATOR_CALCULATE_POPULATE_CACHE(SYMBOL, TF, KEY) + #define INDICATOR_CALCULATE_POPULATED_PARAMS_LONG \ _time, _price_open, _price_high, _price_low, _price_close, _tick_volume, _volume, _spread From f7b99ec15b59ee1903b25753e7d9006e8f017817 Mon Sep 17 00:00:00 2001 From: Adrian Kierzkowski Date: Fri, 26 Nov 2021 22:04:51 +0100 Subject: [PATCH 29/77] Added support for MT4. --- Indicator/IndicatorCandle.h | 5 ++--- Indicator/tests/classes/IndicatorTickReal.h | 6 ++++-- Util.h | 18 +++++++++++++++++- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/Indicator/IndicatorCandle.h b/Indicator/IndicatorCandle.h index 31fa5bee4..2bf8a760c 100644 --- a/Indicator/IndicatorCandle.h +++ b/Indicator/IndicatorCandle.h @@ -166,12 +166,11 @@ class IndicatorCandle : public IndicatorBase { void UpdateCandle(long _tick_timestamp, double _price) { long _candle_timestamp = CalcCandleTimestamp(_tick_timestamp); - CandleOCTOHLC _candle; + CandleOCTOHLC _candle(_price, _price, _price, _price, _tick_timestamp, _tick_timestamp); if (icdata.KeyExists(_candle_timestamp)) { + // Candle already exists. _candle = icdata.GetByKey(_candle_timestamp); _candle.Update(_tick_timestamp, _price); - } else { - _candle = CandleOCTOHLC(_price, _price, _price, _price, _tick_timestamp, _tick_timestamp); } icdata.Set(_candle_timestamp, _candle); diff --git a/Indicator/tests/classes/IndicatorTickReal.h b/Indicator/tests/classes/IndicatorTickReal.h index 00a2aafb3..c3c36269d 100644 --- a/Indicator/tests/classes/IndicatorTickReal.h +++ b/Indicator/tests/classes/IndicatorTickReal.h @@ -54,7 +54,8 @@ class IndicatorTickReal : public IndicatorTick for (int i = 0; i < MathMin(Bars(GetSymbol(), GetTf()), _ticks_to_emit); ++i) { long _timestamp = ChartStatic::iTime(GetSymbol(), GetTf(), _ticks_to_emit - i - 1); double _bid = ChartStatic::iClose(GetSymbol(), GetTf(), _ticks_to_emit - i - 1); - EmitEntry(TickToEntry(_timestamp, TickAB(0.0f, _bid))); + TickAB _tick(0.0f, _bid); + EmitEntry(TickToEntry(_timestamp, _tick)); } }; @@ -62,6 +63,7 @@ class IndicatorTickReal : public IndicatorTick long _timestamp = ChartStatic::iTime(GetSymbol(), GetTf()); double _bid = ChartStatic::iClose(GetSymbol(), GetTf()); // MT doesn't provide historical ask prices, so we're filling tick with bid price only. - EmitEntry(TickToEntry(_timestamp, TickAB(_bid, _bid))); + TickAB _tick(_bid, _bid); + EmitEntry(TickToEntry(_timestamp, _tick)); } }; diff --git a/Util.h b/Util.h index 42a8a3009..739fb9f85 100644 --- a/Util.h +++ b/Util.h @@ -65,6 +65,22 @@ class Util { return _result; } + /** + * Removes value from the array. + */ + template + static bool ArrayRemove(T& _array[], int index) { + if (index < 0 || index >= ArraySize(_array)) { + // Index out of array bounds. + return false; + } + for (int i = index; i < ArraySize(_array); ++i) { + _array[i] = _array[i + 1]; + } + Util::ArrayResize(_array, ArraySize(_array) - 1); + return true; + } + /** * Removes value from the array. */ @@ -72,7 +88,7 @@ class Util { static bool ArrayRemoveFirst(T& _array[], T& value) { for (int i = 0; i < ArraySize(_array); ++i) { if (_array[i] == value) { - ArrayRemove(_array, i); + Util::ArrayRemove(_array, i); return true; } } From 3537a04ae292a953036f5df1d2c5f52ce7ebfe38 Mon Sep 17 00:00:00 2001 From: Adrian Kierzkowski Date: Tue, 30 Nov 2021 18:12:37 +0100 Subject: [PATCH 30/77] WIP. Trying to make "AMA on Candle indicator on Tick indicator" to print the same results as original AMA based on real platform ticks. Currently without a success. --- Indicator/IndicatorCandle.h | 45 +++++++++++++++++++++ Indicator/tests/IndicatorTf.test.mq5 | 23 ++++++++++- Indicator/tests/classes/IndicatorTfDummy.h | 3 +- Indicator/tests/classes/IndicatorTickReal.h | 9 +++-- Indicator/tests/classes/Indicators.h | 2 +- Util.h | 15 +++++++ 6 files changed, 91 insertions(+), 6 deletions(-) diff --git a/Indicator/IndicatorCandle.h b/Indicator/IndicatorCandle.h index 2bf8a760c..e229d0539 100644 --- a/Indicator/IndicatorCandle.h +++ b/Indicator/IndicatorCandle.h @@ -254,6 +254,51 @@ class IndicatorCandle : public IndicatorBase { } return _result; } + + /** + * Get full name of the indicator (with "over ..." part). + */ + string GetFullName() override { + return GetName() + "[" + IntegerToString(icparams.GetMaxModes()) + "]" + + (HasDataSource() ? (" (over " + GetDataSource().GetFullName() + ")") : ""); + } + + /** + * Whether data source is selected. + */ + bool HasDataSource() override { return GetDataSourceRaw() != NULL || icparams.GetDataSourceId() != -1; } + + /** + * Returns currently selected data source doing validation. + */ + IndicatorBase* GetDataSource() override { + IndicatorBase* _result = NULL; + + if (GetDataSourceRaw() != NULL) { + _result = GetDataSourceRaw(); + } else if (icparams.GetDataSourceId() != -1) { + int _source_id = icparams.GetDataSourceId(); + + if (indicators.KeyExists(_source_id)) { + _result = indicators[_source_id].Ptr(); + } else { + Ref _source = FetchDataSource((ENUM_INDICATOR_TYPE)_source_id); + + if (!_source.IsSet()) { + Alert(GetName(), " has no built-in source indicator ", _source_id); + DebugBreak(); + } else { + indicators.Set(_source_id, _source); + + _result = _source.Ptr(); + } + } + } + + ValidateDataSource(&this, _result); + + return _result; + } }; #endif diff --git a/Indicator/tests/IndicatorTf.test.mq5 b/Indicator/tests/IndicatorTf.test.mq5 index 0096c7310..7f9aa4d4d 100644 --- a/Indicator/tests/IndicatorTf.test.mq5 +++ b/Indicator/tests/IndicatorTf.test.mq5 @@ -39,7 +39,10 @@ Indicators indicators; Ref indi_tick; Ref indi_tf; +Ref indi_tf_orig_sim; Ref indi_ama; +Ref indi_ama_orig; +Ref indi_ama_orig_sim; /** * Implements OnInit(). @@ -50,15 +53,28 @@ int OnInit() { // 1-second candles. indicators.Add(indi_tf = new IndicatorTfDummy(1)); + // 1:1 candles from platform using current timeframe. + indicators.Add(indi_tf_orig_sim = new IndicatorTfDummy(ChartTf::TfToSeconds(PERIOD_CURRENT))); + // 1-second candles. indicators.Add(indi_ama = new Indi_AMA()); + // AMA on platform candles. + indicators.Add(indi_ama_orig_sim = new Indi_AMA()); + + // Original built-in or OnCalculate()-based AMA indicator on platform OHLCs. + indicators.Add(indi_ama_orig = new Indi_AMA()); + // Candles will be initialized from tick's history. indi_tf.Ptr().SetDataSource(indi_tick.Ptr()); + indi_tf_orig_sim.Ptr().SetDataSource(indi_tick.Ptr()); // AMA will work on the candle indicator. indi_ama.Ptr().SetDataSource(indi_tf.Ptr()); + // AMA will work on the simulation of real candles. + indi_ama_orig_sim.Ptr().SetDataSource(indi_tf_orig_sim.Ptr()); + // Checking if there are candles for last 100 ticks. Print(indi_tf.Ptr().GetName(), "'s historic candles (from 100 ticks):"); Print(indi_tf.Ptr().CandlesToString()); @@ -70,7 +86,12 @@ int OnInit() { */ void OnTick() { indicators.Tick(); - Print("Tick: \n" + indicators.ToString(0)); + string o = DoubleToStr(iOpen(_Symbol, PERIOD_CURRENT, 0), 5); + string h = DoubleToStr(iHigh(_Symbol, PERIOD_CURRENT, 0), 5); + string l = DoubleToStr(iLow(_Symbol, PERIOD_CURRENT, 0), 5); + string c = DoubleToStr(iClose(_Symbol, PERIOD_CURRENT, 0), 5); + + Util::Print("Tick: real = " + o + ", " + h + ", " + l + ", " + c + "\n" + indicators.ToString(0)); } /** diff --git a/Indicator/tests/classes/IndicatorTfDummy.h b/Indicator/tests/classes/IndicatorTfDummy.h index fc79a3634..7bd57829e 100644 --- a/Indicator/tests/classes/IndicatorTfDummy.h +++ b/Indicator/tests/classes/IndicatorTfDummy.h @@ -51,6 +51,7 @@ class IndicatorTfDummy : public IndicatorTf { // create/update matching candle. IndicatorTf::OnDataSourceEntry(entry); - Print(GetName(), " got new tick at ", entry.timestamp, ": ", entry.ToString()); + Print(GetFullName(), " got new tick at ", entry.timestamp, + " (" + TimeToString(entry.timestamp) + "): ", entry.ToString()); } }; diff --git a/Indicator/tests/classes/IndicatorTickReal.h b/Indicator/tests/classes/IndicatorTickReal.h index c3c36269d..f0719417c 100644 --- a/Indicator/tests/classes/IndicatorTickReal.h +++ b/Indicator/tests/classes/IndicatorTickReal.h @@ -42,20 +42,23 @@ class IndicatorTickReal : public IndicatorTick SetSymbol(_symbol); } - string GetName() override { return "IndicatorTickDummy"; } + string GetName() override { return "IndicatorTickReal"; } void OnBecomeDataSourceFor(IndicatorBase* _base_indi) override { // Feeding base indicator with historic entries of this indicator. - Print(GetName(), " became a data source for ", _base_indi.GetName()); + Print(GetFullName(), " became a data source for ", _base_indi.GetFullName()); int _ticks_to_emit = 100; + Print(_base_indi.GetFullName(), " will be now filled with 100 historical entries generated by " + GetFullName()); + // For testing purposes we are emitting 100 last ticks. for (int i = 0; i < MathMin(Bars(GetSymbol(), GetTf()), _ticks_to_emit); ++i) { long _timestamp = ChartStatic::iTime(GetSymbol(), GetTf(), _ticks_to_emit - i - 1); double _bid = ChartStatic::iClose(GetSymbol(), GetTf(), _ticks_to_emit - i - 1); TickAB _tick(0.0f, _bid); - EmitEntry(TickToEntry(_timestamp, _tick)); + // We can't call EmitTick() here, as tick would go to multiple sources at the same time! + _base_indi.OnDataSourceEntry(TickToEntry(_timestamp, _tick)); } }; diff --git a/Indicator/tests/classes/Indicators.h b/Indicator/tests/classes/Indicators.h index 2022df473..f8258b555 100644 --- a/Indicator/tests/classes/Indicators.h +++ b/Indicator/tests/classes/Indicators.h @@ -66,7 +66,7 @@ class Indicators { string _result; for (int i = 0; i < ArraySize(_indis); ++i) { IndicatorDataEntry _entry = _indis[i].Ptr().GetEntry(_shift); - _result += _indis[i].Ptr().GetName() + " = " + _entry.ToString() + "\n"; + _result += _indis[i].Ptr().GetFullName() + " = " + _entry.ToString() + "\n"; } return _result; } diff --git a/Util.h b/Util.h index 739fb9f85..e1782d19d 100644 --- a/Util.h +++ b/Util.h @@ -104,6 +104,21 @@ class Util { return _result; } + /** + * Splits prints by newlines on MT4. + */ + static void Print(string _value) { +#ifdef __MQL4__ + string _segments[]; + StringSplit(_value, '\n', _segments); + for (int i = 0; i < ArraySize(_segments); ++i) { + ::Print(_segments[i]); + } +#else + ::Print(_value); +#endif + } + /** * Checks whether array has given value. */ From f92dda0e485020e9db3b074c74f879f5d5a7fb46 Mon Sep 17 00:00:00 2001 From: Adrian Kierzkowski Date: Fri, 3 Dec 2021 17:31:06 +0100 Subject: [PATCH 31/77] Probably working scenario of AMA <- IndicatorTfDummy(IndicatorCandle) <- IndicatorTickReal(IndicatorTick) <- platform ticks' ask/bid prices. --- Indicator/IndicatorCandle.h | 10 +++- Indicator/IndicatorTick.h | 66 +++++---------------- Indicator/tests/IndicatorTf.test.mq5 | 32 ++++++---- Indicator/tests/classes/IndicatorTickReal.h | 63 +++++++++++++++----- Indicators/Indi_AMA.mqh | 3 +- 5 files changed, 93 insertions(+), 81 deletions(-) diff --git a/Indicator/IndicatorCandle.h b/Indicator/IndicatorCandle.h index e229d0539..34dbc37c6 100644 --- a/Indicator/IndicatorCandle.h +++ b/Indicator/IndicatorCandle.h @@ -53,6 +53,7 @@ class IndicatorCandle : public IndicatorBase { void Init() { icdata.AddFlags(DICT_FLAG_FILL_HOLES_UNSORTED); icdata.SetOverflowListener(IndicatorCandleOverflowListener, 10); + icparams.SetMaxModes(4); } public: @@ -91,7 +92,9 @@ class IndicatorCandle : public IndicatorBase { CandleOCTOHLC _candle = icdata.GetByKey(_candle_time); if (!_candle.IsValid()) { - Print(GetName(), ": Missing candle at shift ", _index, " (", _candle_time, ")"); + Print(GetFullName(), ": Missing candle at shift ", _index, " (", TimeToString(_candle_time), ")"); + } else { + Print(GetFullName(), ": Retrieving candle at shift ", _index, " (", TimeToString(_candle_time), ")"); } return CandleToEntry(_candle_time, _candle); @@ -166,6 +169,9 @@ class IndicatorCandle : public IndicatorBase { void UpdateCandle(long _tick_timestamp, double _price) { long _candle_timestamp = CalcCandleTimestamp(_tick_timestamp); + Print("Updating candle for ", GetFullName(), " at candle ", TimeToString(_candle_timestamp), " from tick at ", + TimeToString(_tick_timestamp)); + CandleOCTOHLC _candle(_price, _price, _price, _price, _tick_timestamp, _tick_timestamp); if (icdata.KeyExists(_candle_timestamp)) { // Candle already exists. @@ -180,7 +186,7 @@ class IndicatorCandle : public IndicatorBase { * Calculates candle's timestamp from tick's timestamp. */ long CalcCandleTimestamp(long _tick_timestamp) { - return _tick_timestamp - _tick_timestamp % (icparams.GetSecsPerCandle() * 1000); + return _tick_timestamp - _tick_timestamp % (icparams.GetSecsPerCandle()); } /** diff --git a/Indicator/IndicatorTick.h b/Indicator/IndicatorTick.h index 5d7dd0925..4cf53be6b 100644 --- a/Indicator/IndicatorTick.h +++ b/Indicator/IndicatorTick.h @@ -53,6 +53,8 @@ class IndicatorTick : public IndicatorBase { void Init() { itdata.AddFlags(DICT_FLAG_FILL_HOLES_UNSORTED); itdata.SetOverflowListener(IndicatorTickOverflowListener, 10); + // Ask and Bid price. + itparams.SetMaxModes(2); } public: @@ -106,61 +108,23 @@ class IndicatorTick : public IndicatorBase { * @return * Returns IndicatorDataEntry struct filled with indicator values. */ - IndicatorDataEntry GetEntry(int _timestamp = 0) { + IndicatorDataEntry GetEntry(int _timestamp = 0) override { ResetLastError(); - TickAB _entry = itdata.GetByKey(_timestamp); - /* - IndicatorDataEntry _entry = itdata.GetByKey(_timestamp); - if (!_entry.IsValid() && !_entry.CheckFlag(INDI_ENTRY_FLAG_INSUFFICIENT_DATA)) { - _entry.Resize(itparams.GetMaxModes()); - _entry.timestamp = _timestamp; - for (int _mode = 0; _mode < (int)itparams.GetMaxModes(); _mode++) { - switch (itparams.GetDataValueType()) { - case TYPE_BOOL: - case TYPE_CHAR: - case TYPE_INT: - _entry.values[_mode] = GetValue(_mode, _timestamp); - break; - case TYPE_LONG: - _entry.values[_mode] = GetValue(_mode, _timestamp); - break; - case TYPE_UINT: - _entry.values[_mode] = GetValue(_mode, _timestamp); - break; - case TYPE_ULONG: - _entry.values[_mode] = GetValue(_mode, _timestamp); - break; - case TYPE_DOUBLE: - _entry.values[_mode] = GetValue(_mode, _timestamp); - break; - case TYPE_FLOAT: - _entry.values[_mode] = GetValue(_mode, _timestamp); - break; - case TYPE_STRING: - case TYPE_UCHAR: - default: - SetUserError(ERR_INVALID_PARAMETER); - break; - } - } - GetEntryAlter(_entry, _timestamp); - _entry.SetFlag(INDI_ENTRY_FLAG_IS_VALID, IsValidEntry(_entry)); - if (_entry.IsValid()) { - itdata.Add(_entry, _timestamp); - istate.is_changed = false; - istate.is_ready = true; - } else { - _entry.AddFlags(INDI_ENTRY_FLAG_INSUFFICIENT_DATA); - } + if (itdata.KeyExists(_timestamp)) { + TickAB _tick = itdata.GetByKey(_timestamp); + return TickToEntry(_timestamp, _tick); } - if (_LastError != ERR_NO_ERROR) { - istate.is_ready = false; - ResetLastError(); + + // No tick at given timestamp. Returning invalid entry. + IndicatorDataEntry _entry(itparams.GetMaxModes()); + GetEntryAlter(_entry, _timestamp); + + for (int i = 0; i < itparams.GetMaxModes(); ++i) { + _entry.values[i] = (double)0; } + + _entry.SetFlag(INDI_ENTRY_FLAG_IS_VALID, false); return _entry; - */ - IndicatorDataEntry _foo; - return _foo; } /** diff --git a/Indicator/tests/IndicatorTf.test.mq5 b/Indicator/tests/IndicatorTf.test.mq5 index 7f9aa4d4d..739855fae 100644 --- a/Indicator/tests/IndicatorTf.test.mq5 +++ b/Indicator/tests/IndicatorTf.test.mq5 @@ -51,33 +51,36 @@ int OnInit() { indicators.Add(indi_tick = new IndicatorTickReal(_Symbol)); // 1-second candles. - indicators.Add(indi_tf = new IndicatorTfDummy(1)); + // indicators.Add(indi_tf = new IndicatorTfDummy(1)); // 1:1 candles from platform using current timeframe. indicators.Add(indi_tf_orig_sim = new IndicatorTfDummy(ChartTf::TfToSeconds(PERIOD_CURRENT))); // 1-second candles. - indicators.Add(indi_ama = new Indi_AMA()); + // indicators.Add(indi_ama = new Indi_AMA()); + + IndiAMAParams _ama_params; + _ama_params.applied_price = PRICE_OPEN; // AMA on platform candles. - indicators.Add(indi_ama_orig_sim = new Indi_AMA()); + indicators.Add(indi_ama_orig_sim = new Indi_AMA(_ama_params)); // Original built-in or OnCalculate()-based AMA indicator on platform OHLCs. - indicators.Add(indi_ama_orig = new Indi_AMA()); + indicators.Add(indi_ama_orig = new Indi_AMA(_ama_params)); // Candles will be initialized from tick's history. - indi_tf.Ptr().SetDataSource(indi_tick.Ptr()); + // indi_tf.Ptr().SetDataSource(indi_tick.Ptr()); indi_tf_orig_sim.Ptr().SetDataSource(indi_tick.Ptr()); // AMA will work on the candle indicator. - indi_ama.Ptr().SetDataSource(indi_tf.Ptr()); + // indi_ama.Ptr().SetDataSource(indi_tf.Ptr()); // AMA will work on the simulation of real candles. indi_ama_orig_sim.Ptr().SetDataSource(indi_tf_orig_sim.Ptr()); // Checking if there are candles for last 100 ticks. - Print(indi_tf.Ptr().GetName(), "'s historic candles (from 100 ticks):"); - Print(indi_tf.Ptr().CandlesToString()); + // Print(indi_tf.Ptr().GetName(), "'s historic candles (from 100 ticks):"); + // Print(indi_tf.Ptr().CandlesToString()); return (INIT_SUCCEEDED); } @@ -85,13 +88,18 @@ int OnInit() { * Implements OnTick(). */ void OnTick() { - indicators.Tick(); string o = DoubleToStr(iOpen(_Symbol, PERIOD_CURRENT, 0), 5); string h = DoubleToStr(iHigh(_Symbol, PERIOD_CURRENT, 0), 5); string l = DoubleToStr(iLow(_Symbol, PERIOD_CURRENT, 0), 5); string c = DoubleToStr(iClose(_Symbol, PERIOD_CURRENT, 0), 5); + string time = TimeToString(iTime(_Symbol, PERIOD_CURRENT, 0)); + + Util::Print("Tick: " + IntegerToString((long)iTime(_Symbol, PERIOD_CURRENT, 0)) + " (" + time + "), real = " + o + + ", " + h + ", " + l + ", " + c); + + indicators.Tick(); - Util::Print("Tick: real = " + o + ", " + h + ", " + l + ", " + c + "\n" + indicators.ToString(0)); + Util::Print(indicators.ToString(0)); } /** @@ -99,6 +107,6 @@ void OnTick() { */ void OnDeinit(const int reason) { // Printing all grouped candles. - Print(indi_tf.Ptr().GetName(), "'s all candles:"); - Print(indi_tf.Ptr().CandlesToString()); + // Print(indi_tf.Ptr().GetName(), "'s all candles:"); + // Print(indi_tf.Ptr().CandlesToString()); } diff --git a/Indicator/tests/classes/IndicatorTickReal.h b/Indicator/tests/classes/IndicatorTickReal.h index f0719417c..668ddc1bf 100644 --- a/Indicator/tests/classes/IndicatorTickReal.h +++ b/Indicator/tests/classes/IndicatorTickReal.h @@ -29,6 +29,10 @@ #pragma once #endif +// Includes. +#include "../../../Chart.struct.static.h" +#include "../../IndicatorTick.h" + // Params for real tick-based indicator. struct IndicatorTickRealParams : IndicatorParams { IndicatorTickRealParams() : IndicatorParams(INDI_TICK, 3, TYPE_DOUBLE) {} @@ -48,25 +52,54 @@ class IndicatorTickReal : public IndicatorTick // Feeding base indicator with historic entries of this indicator. Print(GetFullName(), " became a data source for ", _base_indi.GetFullName()); - int _ticks_to_emit = 100; +#ifndef __MQL4__ + int _ticks_to_emit = 1000; + + Print(_base_indi.GetFullName(), " will be now filled with ", _ticks_to_emit, + " historical entries generated by " + GetFullName()); + + static MqlTick _ticks[]; + ArrayResize(_ticks, 0); + + int _tries = 10; + int _num_copied = -1; + + while (_tries-- > 0) { + _num_copied = CopyTicks(GetSymbol(), _ticks, COPY_TICKS_ALL); - Print(_base_indi.GetFullName(), " will be now filled with 100 historical entries generated by " + GetFullName()); + if (_num_copied == -1) { + Sleep(1000); + } else { + break; + } + } - // For testing purposes we are emitting 100 last ticks. - for (int i = 0; i < MathMin(Bars(GetSymbol(), GetTf()), _ticks_to_emit); ++i) { - long _timestamp = ChartStatic::iTime(GetSymbol(), GetTf(), _ticks_to_emit - i - 1); - double _bid = ChartStatic::iClose(GetSymbol(), GetTf(), _ticks_to_emit - i - 1); - TickAB _tick(0.0f, _bid); - // We can't call EmitTick() here, as tick would go to multiple sources at the same time! - _base_indi.OnDataSourceEntry(TickToEntry(_timestamp, _tick)); + for (int i = 0; i < _num_copied; ++i) { + TickAB _tick(_ticks[i].ask, _ticks[i].bid); + // We can't call EmitEntry() here, as tick would go to multiple sources at the same time! + _base_indi.OnDataSourceEntry(TickToEntry(_ticks[i].time, _tick)); } - }; +#endif + } void OnTick() override { - long _timestamp = ChartStatic::iTime(GetSymbol(), GetTf()); - double _bid = ChartStatic::iClose(GetSymbol(), GetTf()); - // MT doesn't provide historical ask prices, so we're filling tick with bid price only. - TickAB _tick(_bid, _bid); - EmitEntry(TickToEntry(_timestamp, _tick)); +#ifdef __MQL4__ + // Refreshes Ask/Bid constants. + RefreshRates(); + double _ask = Ask; + double _bid = Bid; + long _time = TimeCurrent(); +#else + static MqlTick _ticks[]; + // Copying only the last tick. + int _num_copied = CopyTicks(GetSymbol(), _ticks, COPY_TICKS_INFO, 0, 1); + + Print("TickReal: ", TimeToString(_ticks[0].time), " = ", _ticks[0].bid); + double _ask = _ticks[0].ask; + double _bid = _ticks[0].bid; + long _time = _ticks[0].time; +#endif + TickAB _tick(_ask, _bid); + EmitEntry(TickToEntry(_time, _tick)); } }; diff --git a/Indicators/Indi_AMA.mqh b/Indicators/Indi_AMA.mqh index 25028689a..861d08cda 100644 --- a/Indicators/Indi_AMA.mqh +++ b/Indicators/Indi_AMA.mqh @@ -96,7 +96,8 @@ class Indi_AMA : public Indicator { int _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) { INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_SHORT_DS( _indi, _symbol, _tf, _ap, - Util::MakeKey("INDI_AMA", _ama_period, _fast_ema_period, _slow_ema_period, _ama_shift, (int)_ap)); + Util::MakeKey("INDI_AMA_ON_" + _indi.GetFullName(), _ama_period, _fast_ema_period, _slow_ema_period, _ama_shift, + (int)_ap)); return iAMAOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_SHORT, _ama_period, _fast_ema_period, _slow_ema_period, _ama_shift, _mode, _shift, _cache); } From 6f3b99adf73f78fa33de91f440b1827c59af5c88 Mon Sep 17 00:00:00 2001 From: Adrian Kierzkowski Date: Fri, 3 Dec 2021 18:35:00 +0100 Subject: [PATCH 32/77] Fixed Util::ArrayRemove() method. --- Util.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Util.h b/Util.h index e1782d19d..904fde211 100644 --- a/Util.h +++ b/Util.h @@ -74,7 +74,7 @@ class Util { // Index out of array bounds. return false; } - for (int i = index; i < ArraySize(_array); ++i) { + for (int i = index; i < ArraySize(_array) - 1; ++i) { _array[i] = _array[i + 1]; } Util::ArrayResize(_array, ArraySize(_array) - 1); From 9603dc3b15bc7c85848c374322fd0b2671d2d26b Mon Sep 17 00:00:00 2001 From: Adrian Kierzkowski Date: Tue, 7 Dec 2021 19:19:37 +0100 Subject: [PATCH 33/77] WIP. i*OnIndicator versions of all indicators (except MA). --- Indicator.enum.h | 12 ++++++ IndicatorBase.h | 30 +++++++++++++++ Indicators/Indi_ADXW.mqh | 10 +++++ Indicators/Indi_AMA.mqh | 30 +++++++-------- Indicators/Indi_ASI.mqh | 10 +++++ Indicators/Indi_BWZT.mqh | 34 ++++++++++++++++- Indicators/Indi_CHO.mqh | 16 +++++++- Indicators/Indi_CHV.mqh | 13 +++++++ Indicators/Indi_ColorBars.mqh | 12 +++++- Indicators/Indi_ColorCandlesDaily.mqh | 10 +++++ Indicators/Indi_ColorLine.mqh | 26 +++++++++++++ Indicators/Indi_DEMA.mqh | 52 +++++++++++++++----------- Indicators/Indi_DetrendedPrice.mqh | 16 ++++++-- Indicators/Indi_FractalAdaptiveMA.mqh | 15 +++++++- Indicators/Indi_HeikenAshi.mqh | 10 +++++ Indicators/Indi_MassIndex.mqh | 13 +++++++ Indicators/Indi_PriceChannel.mqh | 12 +++++- Indicators/Indi_PriceVolumeTrend.mqh | 10 +++++ Indicators/Indi_RateOfChange.mqh | 10 +++++ Indicators/Indi_TEMA.mqh | 12 ++++++ Indicators/Indi_TRIX.mqh | 10 +++++ Indicators/Indi_UltimateOscillator.mqh | 20 ++++++++++ Indicators/Indi_VIDYA.mqh | 13 +++++++ Indicators/Indi_VROC.mqh | 12 +++++- Indicators/Indi_Volumes.mqh | 12 +++++- Indicators/Indi_WilliamsAD.mqh | 10 +++++ Indicators/Indi_ZigZag.mqh | 12 ++++++ Indicators/Indi_ZigZagColor.mqh | 13 +++++++ Storage/ValueStorage.h | 11 ++++++ 29 files changed, 419 insertions(+), 47 deletions(-) diff --git a/Indicator.enum.h b/Indicator.enum.h index 63baad455..e67e3ff88 100644 --- a/Indicator.enum.h +++ b/Indicator.enum.h @@ -228,3 +228,15 @@ enum INDICATOR_ENTRY_FLAGS { INDI_ENTRY_FLAG_IS_VALID = 1 << 6, INDI_ENTRY_FLAG_INSUFFICIENT_DATA = 1 << 7, // Entry has missing value for that shift and probably won't ever have. }; + +// Storage type for IndicatorBase::GetSpecificValueStorage(). +enum ENUM_INDI_VS_TYPE { + INDI_VS_TYPE_TIME, + INDI_VS_TYPE_TICK_VOLUME, + INDI_VS_TYPE_VOLUME, + INDI_VS_TYPE_SPREAD, + INDI_VS_TYPE_PRICE_OPEN, + INDI_VS_TYPE_PRICE_HIGH, + INDI_VS_TYPE_PRICE_LOW, + INDI_VS_TYPE_PRICE_CLOSE +}; \ No newline at end of file diff --git a/IndicatorBase.h b/IndicatorBase.h index d1f61d607..a0bed2b73 100644 --- a/IndicatorBase.h +++ b/IndicatorBase.h @@ -275,6 +275,27 @@ class IndicatorBase : public Chart { */ IndicatorBase* GetDataSourceRaw() { return indi_src.Ptr(); } + /** + * Returns given data source type. Used by i*OnIndicator methods if indicator's Calculate() uses other indicators. + */ + IndicatorBase* GetDataSource(ENUM_INDICATOR_TYPE _type) { + IndicatorBase* _result = NULL; + if (indicators.KeyExists((int)_type)) { + _result = indicators[(int)_type].Ptr(); + } else { + Ref _indi = FetchDataSource(_type); + if (!_indi.IsSet()) { + Alert(GetFullName(), " does not define required indicator type ", EnumToString(_type), " for symbol ", + GetSymbol(), ", and timeframe ", GetTf(), "!"); + DebugBreak(); + } else { + indicators.Set((int)_type, _indi); + _result = _indi.Ptr(); + } + } + return _result; + } + /* Getters */ /** @@ -423,6 +444,15 @@ class IndicatorBase : public Chart { return value_storages[_mode]; } + /** + * Returns value storage of given kind. + */ + virtual IValueStorage* GetSpecificValueStorage(ENUM_INDI_VS_TYPE _type) { + Print("Error: ", GetFullName(), " indicator has no storage type ", EnumToString(_type), "!"); + DebugBreak(); + return NULL; + } + template T GetValue(int _index = 0, int _mode = 0) { T _out; diff --git a/Indicators/Indi_ADXW.mqh b/Indicators/Indi_ADXW.mqh index efd22ce2e..b8142fd78 100644 --- a/Indicators/Indi_ADXW.mqh +++ b/Indicators/Indi_ADXW.mqh @@ -102,6 +102,16 @@ class Indi_ADXW : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of ADX Wilder. + */ + static double iADXWilderOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _period, + int _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS( + _indi, _symbol, _tf, Util::MakeKey("Indi_ADXW_ON_" + _indi.GetFullName(), _period)); + return iADXWilderOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _period, _mode, _shift, _cache); + } + /** * OnCalculate() method for ADXW indicator. */ diff --git a/Indicators/Indi_AMA.mqh b/Indicators/Indi_AMA.mqh index 861d08cda..d71d33756 100644 --- a/Indicators/Indi_AMA.mqh +++ b/Indicators/Indi_AMA.mqh @@ -82,26 +82,12 @@ class Indi_AMA : public Indicator { #else INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_SHORT( _symbol, _tf, _ap, - Util::MakeKey("INDI_AMA", _ama_period, _fast_ema_period, _slow_ema_period, _ama_shift, (int)_ap)); + Util::MakeKey("Indi_AMA", _ama_period, _fast_ema_period, _slow_ema_period, _ama_shift, (int)_ap)); return iAMAOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_SHORT, _ama_period, _fast_ema_period, _slow_ema_period, _ama_shift, _mode, _shift, _cache); #endif } - /** - * On-indicator version of AMA. - */ - static double iAMAOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _ama_period, - int _fast_ema_period, int _slow_ema_period, int _ama_shift, ENUM_APPLIED_PRICE _ap, - int _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) { - INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_SHORT_DS( - _indi, _symbol, _tf, _ap, - Util::MakeKey("INDI_AMA_ON_" + _indi.GetFullName(), _ama_period, _fast_ema_period, _slow_ema_period, _ama_shift, - (int)_ap)); - return iAMAOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_SHORT, _ama_period, _fast_ema_period, _slow_ema_period, - _ama_shift, _mode, _shift, _cache); - } - /** * Calculates AMA on the array of values. */ @@ -124,6 +110,20 @@ class Indi_AMA : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of AMA. + */ + static double iAMAOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _ama_period, + int _fast_ema_period, int _slow_ema_period, int _ama_shift, ENUM_APPLIED_PRICE _ap, + int _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_SHORT_DS( + _indi, _symbol, _tf, _ap, + Util::MakeKey("Indi_AMA_ON_" + _indi.GetFullName(), _ama_period, _fast_ema_period, _slow_ema_period, _ama_shift, + (int)_ap)); + return iAMAOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_SHORT, _ama_period, _fast_ema_period, _slow_ema_period, + _ama_shift, _mode, _shift, _cache); + } + /** * OnInit() method for AMA indicator. */ diff --git a/Indicators/Indi_ASI.mqh b/Indicators/Indi_ASI.mqh index 2e0cf341b..1e9f54281 100644 --- a/Indicators/Indi_ASI.mqh +++ b/Indicators/Indi_ASI.mqh @@ -84,6 +84,16 @@ class Indi_ASI : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of ASI. + */ + static double iASIOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, double _mpc, int _mode = 0, + int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS(_indi, _symbol, _tf, + Util::MakeKey("Indi_ASI_ON_" + _indi.GetFullName(), _mpc)); + return iASIOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _mpc, _mode, _shift, _cache); + } + /** * OnInit() method for ASI indicator. */ diff --git a/Indicators/Indi_BWZT.mqh b/Indicators/Indi_BWZT.mqh index 65d7cb881..08405e14f 100644 --- a/Indicators/Indi_BWZT.mqh +++ b/Indicators/Indi_BWZT.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTf.h" #include "../Storage/ValueStorage.all.h" #include "Indi_AC.mqh" #include "Indi_AO.mqh" @@ -40,11 +40,15 @@ enum ENUM_INDI_BWZT_MODE { // Structs. struct IndiBWZTParams : IndicatorParams { + Indi_AC *indi_ac; + Indi_AC *indi_ao; unsigned int period; unsigned int second_period; unsigned int sum_period; // Struct constructor. IndiBWZTParams(int _shift = 0) : IndicatorParams(INDI_BWZT, FINAL_INDI_BWZT_MODE_ENTRY, TYPE_DOUBLE) { + indi_ac = NULL; + indi_ao = NULL; SetDataValueRange(IDATA_RANGE_MIXED); SetCustomIndicatorName("Examples\\BW-ZoneTrade"); shift = _shift; @@ -102,6 +106,34 @@ class Indi_BWZT : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of BWZT. + */ + static double iBWZTOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, double _mpc, int _mode, + int _shift, IndicatorBase *_obj) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS(_indi, _symbol, _tf, + Util::MakeKey("Indi_BWZT_ON_" + _indi.GetFullName())); + + Indi_AC *_indi_ac = _obj.GetDataSource(INDI_AC); + Indi_AO *_indi_ao = _obj.GetDataSource(INDI_AO); + + return iBWZTOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _mode, _shift, _cache, _indi_ac, _indi_ao); + } + + /** + * Provides built-in indicators whose can be used as data source. + */ + virtual IndicatorBase *FetchDataSource(ENUM_INDICATOR_TYPE _id) override { + switch (_id) { + case INDI_AC: + return iparams.indi_ac; + case INDI_AO: + return iparams.indi_ac; + } + + return NULL; + } + /** * OnCalculate() method for BWZT indicator. */ diff --git a/Indicators/Indi_CHO.mqh b/Indicators/Indi_CHO.mqh index 1cf24699e..6106dbefe 100644 --- a/Indicators/Indi_CHO.mqh +++ b/Indicators/Indi_CHO.mqh @@ -73,7 +73,7 @@ class Indi_CHO : public Indicator { _mode, _shift); #else INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG( - _symbol, _tf, Util::MakeKey("INDI_CHO", _fast_ma_period, _slow_ma_period, (int)_ma_method, (int)_av)); + _symbol, _tf, Util::MakeKey("Indi_CHO", _fast_ma_period, _slow_ma_period, (int)_ma_method, (int)_av)); return iChaikinOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _fast_ma_period, _slow_ma_period, _ma_method, _av, _mode, _shift, _cache); #endif @@ -102,6 +102,20 @@ class Indi_CHO : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of Chaikin Oscillator. + */ + static double iChaikinOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _fast_ma_period, + int _slow_ma_period, ENUM_MA_METHOD _ma_method, ENUM_APPLIED_VOLUME _av, + int _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS( + _indi, _symbol, _tf, + Util::MakeKey("Indi_CHO_ON_" + _indi.GetFullName(), _fast_ma_period, _slow_ma_period, (int)_ma_method, + (int)_av)); + return iChaikinOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _fast_ma_period, _slow_ma_period, _ma_method, _av, + _mode, _shift, _cache); + } + /** * OnCalculate() method for Chaikin Oscillator indicator. */ diff --git a/Indicators/Indi_CHV.mqh b/Indicators/Indi_CHV.mqh index d3f97fd42..8b8f9490e 100644 --- a/Indicators/Indi_CHV.mqh +++ b/Indicators/Indi_CHV.mqh @@ -99,6 +99,19 @@ class Indi_CHV : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of Chaikin Volatility. + */ + static double iCHVOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _smooth_period, + int _chv_period, ENUM_CHV_SMOOTH_METHOD _smooth_method, int _mode = 0, int _shift = 0, + IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS( + _indi, _symbol, _tf, + Util::MakeKey("Indi_CHV_ON_" + _indi.GetFullName(), _smooth_period, _chv_period, _smooth_method)); + return iCHVOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _smooth_period, _chv_period, _smooth_method, _mode, + _shift, _cache); + } + /** * OnInit() method for Chaikin Volatility indicator. */ diff --git a/Indicators/Indi_ColorBars.mqh b/Indicators/Indi_ColorBars.mqh index f89773c19..676a91767 100644 --- a/Indicators/Indi_ColorBars.mqh +++ b/Indicators/Indi_ColorBars.mqh @@ -56,7 +56,7 @@ class Indi_ColorBars : public Indicator { */ static double iColorBars(string _symbol, ENUM_TIMEFRAMES _tf, int _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) { - INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG(_symbol, _tf, "Indi_ColorCandlesDaily"); + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG(_symbol, _tf, "Indi_ColorBars"); return iColorBarsOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _mode, _shift, _cache); } @@ -82,6 +82,16 @@ class Indi_ColorBars : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of Color Bars. + */ + static double iColorBarsOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _mode = 0, + int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS(_indi, _symbol, _tf, + Util::MakeKey("Indi_ColorBars_ON_" + _indi.GetFullName())); + return iColorBarsOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _mode, _shift, _cache); + } + /** * OnCalculate() method for Color Bars indicator. */ diff --git a/Indicators/Indi_ColorCandlesDaily.mqh b/Indicators/Indi_ColorCandlesDaily.mqh index b8c4b851c..1515cdc45 100644 --- a/Indicators/Indi_ColorCandlesDaily.mqh +++ b/Indicators/Indi_ColorCandlesDaily.mqh @@ -82,6 +82,16 @@ class Indi_ColorCandlesDaily : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of Color Candles Daily. + */ + static double iCCDOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _mode = 0, + int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS( + _indi, _symbol, _tf, Util::MakeKey("Indi_ColorCandlesDaily_ON_" + _indi.GetFullName())); + return iCCDOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _mode, _shift, _cache); + } + /** * OnCalculate() method for Color Candles Daily indicator. */ diff --git a/Indicators/Indi_ColorLine.mqh b/Indicators/Indi_ColorLine.mqh index d3dd60ed7..886c70737 100644 --- a/Indicators/Indi_ColorLine.mqh +++ b/Indicators/Indi_ColorLine.mqh @@ -28,8 +28,10 @@ // Structs. struct IndiColorLineParams : IndicatorParams { + IndicatorBase *indi_ma; // Struct constructor. IndiColorLineParams(int _shift = 0) : IndicatorParams(INDI_COLOR_LINE, 2, TYPE_DOUBLE) { + indi_ma = NULL; SetDataValueRange(IDATA_RANGE_MIXED); SetCustomIndicatorName("Examples\\ColorLine"); shift = _shift; @@ -86,6 +88,30 @@ class Indi_ColorLine : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of Color Line. + */ + static double iColorLineOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _mode = 0, + int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS(_indi, _symbol, _tf, + Util::MakeKey("Indi_ColorLine_ON_" + _indi.GetFullName())); + + Indi_MA *_indi_ma = _obj.GetDataSource(INDI_MA); + + return iColorLineOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _mode, _shift, _cache, _indi_ma); + } + + /** + * Provides built-in indicators whose can be used as data source. + */ + virtual IndicatorBase *FetchDataSource(ENUM_INDICATOR_TYPE _id) override { + switch (_id) { + case INDI_MA: + return iparams.indi_ma; + } + return NULL; + } + /** * OnCalculate() method for Color Line indicator. */ diff --git a/Indicators/Indi_DEMA.mqh b/Indicators/Indi_DEMA.mqh index 420034607..e89f07723 100644 --- a/Indicators/Indi_DEMA.mqh +++ b/Indicators/Indi_DEMA.mqh @@ -108,44 +108,54 @@ class Indi_DEMA : public Indicator { #else Indi_Price *_indi_price = Indi_Price::GetCached(_symbol, _applied_price, _tf, _shift); // Note that _applied_price and Indi_Price mode indices are compatible. - return Indi_DEMA::iDEMAOnIndicator(_indi_price.GetCache(), _indi_price, 0, _period, _ma_shift, _shift); + return Indi_DEMA::iDEMAOnIndicatorSlow(_indi_price.GetCache(), _indi_price, 0, _period, _ma_shift, _shift); #endif } - static double iDEMAOnIndicator(IndicatorCalculateCache *cache, IndicatorBase *_indi, int indi_mode, - unsigned int ma_period, unsigned int ma_shift, int shift) { + static double iDEMAOnIndicatorSlow(IndicatorCalculateCache *cache, IndicatorBase *_indi, int indi_mode, + unsigned int ma_period, unsigned int ma_shift, int shift) { return iDEMAOnArray(_indi.GetValueStorage(indi_mode), 0, ma_period, ma_shift, shift, cache); } - static double iDEMAOnArray(ValueStorage &price, int total, unsigned int ma_period, unsigned int ma_shift, - int shift, IndicatorCalculateCache *cache = NULL, bool recalculate = false) { - if (cache == NULL) { + static double iDEMAOnArray(INDICATOR_CALCULATE_PARAMS_SHORT, unsigned int _ma_period, unsigned int _ma_shift, + int _mode, int _shift, IndicatorCalculateCache *_cache = NULL, + bool _recalculate = false) { + if (_cache == NULL) { Print("iDEMAOnArray() cannot yet work without cache object!"); DebugBreak(); return 0.0f; } - cache.SetPriceBuffer(price); + _cache.SetPriceBuffer(_price); - if (!cache.HasBuffers()) { - cache.AddBuffer>(3); // 3 buffers. + if (!_cache.HasBuffers()) { + _cache.AddBuffer>(3); // 3 buffers. } - if (recalculate) { + if (_recalculate) { // We don't want to continue calculations, but to recalculate previous one. - cache.ResetPrevCalculated(); + _cache.ResetPrevCalculated(); } - cache.SetPrevCalculated(Indi_DEMA::Calculate(cache.GetTotal(), cache.GetPrevCalculated(), 0, cache.GetPriceBuffer(), - ma_period, cache.GetBuffer(0), cache.GetBuffer(1), - cache.GetBuffer(2))); + _cache.SetPrevCalculated(Indi_DEMA::Calculate(INDICATOR_CALCULATE_GET_PARAMS_SHORT, _cache.GetBuffer(0), + _cache.GetBuffer(1), _cache.GetBuffer(2), + _ma_period)); - return cache.GetTailValue(0, ma_shift + shift); + return _cache.GetTailValue(0, _ma_shift + _shift); } - static int Calculate(const int rates_total, const int prev_calculated, const int begin, ValueStorage &price, - int InpPeriodEMA, ValueStorage &DemaBuffer, ValueStorage &Ema, - ValueStorage &EmaOfEma) { + /** + * On-indicator version of DEMA. + */ + static double iDEMAOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _period, int _ma_shift, + ENUM_APPLIED_PRICE _ap, int _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_SHORT_DS( + _indi, _symbol, _tf, (int)_ap, Util::MakeKey("Indi_CHV_ON_" + _indi.GetFullName(), _period, _ma_shift)); + return iDEMAOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_SHORT, _period, _ma_shift, _mode, _shift, _cache); + } + + static int Calculate(INDICATOR_CALCULATE_METHOD_PARAMS_SHORT, ValueStorage &DemaBuffer, + ValueStorage &Ema, ValueStorage &EmaOfEma, int InpPeriodEMA) { if (rates_total < 2 * InpPeriodEMA - 2) return (0); int start; @@ -176,7 +186,7 @@ class Indi_DEMA : public Indicator { istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; _value = Indi_DEMA::iDEMA(GetSymbol(), GetTf(), GetPeriod(), GetMAShift(), GetAppliedPrice(), _ishift, _mode, - GetPointer(this)); + THIS_PTR); break; case IDATA_ICUSTOM: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; @@ -185,8 +195,8 @@ class Indi_DEMA : public Indicator { break; case IDATA_INDICATOR: // Calculating DEMA value from specified indicator. - _value = Indi_DEMA::iDEMAOnIndicator(GetCache(), GetDataSource(), GetDataSourceMode(), GetPeriod(), - GetMAShift(), _ishift); + _value = Indi_DEMA::iDEMAOnIndicator(GetDataSource(), GetSymbol(), GetTf(), GetPeriod(), GetMAShift(), + GetAppliedPrice(), _mode, _ishift, THIS_PTR); break; } return _value; diff --git a/Indicators/Indi_DetrendedPrice.mqh b/Indicators/Indi_DetrendedPrice.mqh index b8c4fe1cd..ef34a7391 100644 --- a/Indicators/Indi_DetrendedPrice.mqh +++ b/Indicators/Indi_DetrendedPrice.mqh @@ -65,14 +65,14 @@ class Indi_DetrendedPrice : public Indicator { int _shift = 0, IndicatorBase *_obj = NULL) { INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_SHORT(_symbol, _tf, _ap, Util::MakeKey("Indi_DPO", _period, (int)_ap)); - return iDPOOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_SHORT, _period, _mode, _shift, _cache); + return iDPOOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_SHORT, _period, _ap, _mode, _shift, _cache); } /** * Calculates DPO on the array of values. */ - static double iDPOOnArray(INDICATOR_CALCULATE_PARAMS_SHORT, int _period, int _mode, int _shift, - IndicatorCalculateCache *_cache, bool _recalculate = false) { + static double iDPOOnArray(INDICATOR_CALCULATE_PARAMS_SHORT, int _period, ENUM_APPLIED_PRICE _ap, int _mode, + int _shift, IndicatorCalculateCache *_cache, bool _recalculate = false) { _cache.SetPriceBuffer(_price); if (!_cache.HasBuffers()) { @@ -89,6 +89,16 @@ class Indi_DetrendedPrice : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of DPO. + */ + static double iDPOOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _period, + ENUM_APPLIED_PRICE _ap, int _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_SHORT_DS( + _indi, _symbol, _tf, _ap, Util::MakeKey("Indi_DPO_ON_" + _indi.GetFullName(), _period, (int)_ap)); + return iDPOOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_SHORT, _period, _ap, _mode, _shift, _cache); + } + /** * OnCalculate() method for DPO indicator. */ diff --git a/Indicators/Indi_FractalAdaptiveMA.mqh b/Indicators/Indi_FractalAdaptiveMA.mqh index 7640170c0..67dc21173 100644 --- a/Indicators/Indi_FractalAdaptiveMA.mqh +++ b/Indicators/Indi_FractalAdaptiveMA.mqh @@ -76,8 +76,8 @@ class Indi_FrAMA : public Indicator { /** * Calculates FrAMA on the array of values. */ - static double iFrAMAOnArray(INDICATOR_CALCULATE_PARAMS_LONG, int _ma_period, int _ma_shift, int _mode, int _shift, - ENUM_APPLIED_PRICE _ap, IndicatorCalculateCache *_cache, + static double iFrAMAOnArray(INDICATOR_CALCULATE_PARAMS_LONG, int _ma_period, int _ma_shift, ENUM_APPLIED_PRICE _ap, + int _mode, int _shift, IndicatorCalculateCache *_cache, bool _recalculate = false) { _cache.SetPriceBuffer(_open, _high, _low, _close); @@ -95,6 +95,17 @@ class Indi_FrAMA : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of FrAMA. + */ + static double iFrAMAOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _ma_period, + int _ma_shift, ENUM_APPLIED_PRICE _ap, int _mode = 0, int _shift = 0, + IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS( + _indi, _symbol, _tf, Util::MakeKey("Indi_AMA_ON_" + _indi.GetFullName(), _ma_period, _ma_shift, (int)_ap)); + return iFrAMAOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _ma_period, _ma_shift, _ap, _mode, _shift, _cache); + } + static int Calculate(INDICATOR_CALCULATE_METHOD_PARAMS_LONG, ValueStorage &FrAmaBuffer, int InpPeriodFrAMA, int InpShift, ENUM_APPLIED_PRICE InpAppliedPrice) { if (rates_total < 2 * InpPeriodFrAMA) return (0); diff --git a/Indicators/Indi_HeikenAshi.mqh b/Indicators/Indi_HeikenAshi.mqh index 789478852..5239c1790 100644 --- a/Indicators/Indi_HeikenAshi.mqh +++ b/Indicators/Indi_HeikenAshi.mqh @@ -157,6 +157,16 @@ class Indi_HeikenAshi : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of Heiken Ashi. + */ + static double iHeikenAshiOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _mode = 0, + int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS(_indi, _symbol, _tf, + Util::MakeKey("Indi_HeikenAshi_ON_" + _indi.GetFullName())); + return iHeikenAshiOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _mode, _shift, _cache); + } + /** * OnCalculate() method for Mass Index indicator. */ diff --git a/Indicators/Indi_MassIndex.mqh b/Indicators/Indi_MassIndex.mqh index 817b81cd8..1e0076f55 100644 --- a/Indicators/Indi_MassIndex.mqh +++ b/Indicators/Indi_MassIndex.mqh @@ -92,6 +92,19 @@ class Indi_MassIndex : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of Mass Index. + */ + static double iMIOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _period, + int _second_period, int _sum_period, int _mode = 0, int _shift = 0, + IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS( + _indi, _symbol, _tf, + Util::MakeKey("Indi_MassIndex_ON_" + _indi.GetFullName(), _period, _second_period, _sum_period)); + return iMIOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _period, _second_period, _sum_period, _mode, _shift, + _cache); + } + /** * OnCalculate() method for Mass Index indicator. */ diff --git a/Indicators/Indi_PriceChannel.mqh b/Indicators/Indi_PriceChannel.mqh index 0afc2392e..415082498 100644 --- a/Indicators/Indi_PriceChannel.mqh +++ b/Indicators/Indi_PriceChannel.mqh @@ -43,7 +43,7 @@ struct IndiPriceChannelParams : IndicatorParams { }; /** - * Implements the Bill Williams' Accelerator/Decelerator oscillator. + * Implements Price Channel indicator. */ class Indi_PriceChannel : public Indicator { public: @@ -86,6 +86,16 @@ class Indi_PriceChannel : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of Price Channel. + */ + static double iPriceChannelOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _period, + int _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS( + _indi, _symbol, _tf, Util::MakeKey("Indi_PriceChannel_ON_" + _indi.GetFullName(), _period)); + return iPriceChannelOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _period, _mode, _shift, _cache); + } + /** * OnCalculate() method for Price Channel indicator. */ diff --git a/Indicators/Indi_PriceVolumeTrend.mqh b/Indicators/Indi_PriceVolumeTrend.mqh index 17505eff1..ecf0ae493 100644 --- a/Indicators/Indi_PriceVolumeTrend.mqh +++ b/Indicators/Indi_PriceVolumeTrend.mqh @@ -85,6 +85,16 @@ class Indi_PriceVolumeTrend : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of Price Volume Trend. + */ + static double iPVTOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, ENUM_APPLIED_VOLUME _av, + int _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS( + _indi, _symbol, _tf, Util::MakeKey("Indi_PVT_ON_" + _indi.GetFullName(), (int)_av)); + return iPVTOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _av, _mode, _shift, _cache); + } + /** * OnCalculate() method for Price Volume Trend indicator. */ diff --git a/Indicators/Indi_RateOfChange.mqh b/Indicators/Indi_RateOfChange.mqh index 076f4798a..fd597bbe0 100644 --- a/Indicators/Indi_RateOfChange.mqh +++ b/Indicators/Indi_RateOfChange.mqh @@ -88,6 +88,16 @@ class Indi_RateOfChange : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of Rate of Change. + */ + static double iROCOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _period, + ENUM_APPLIED_PRICE _ap, int _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_SHORT_DS( + _indi, _symbol, _tf, _ap, Util::MakeKey("Indi_RateOfChange_ON_" + _indi.GetFullName(), _period, (int)_ap)); + return iROCOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_SHORT, _period, _mode, _shift, _cache); + } + /** * OnCalculate() method for Rate of Change indicator. */ diff --git a/Indicators/Indi_TEMA.mqh b/Indicators/Indi_TEMA.mqh index 3cc9e949b..626ad9186 100644 --- a/Indicators/Indi_TEMA.mqh +++ b/Indicators/Indi_TEMA.mqh @@ -94,6 +94,18 @@ class Indi_TEMA : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of TEMA. + */ + static double iAMAOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _ma_period, + int _ma_shift, ENUM_APPLIED_PRICE _ap, int _mode = 0, int _shift = 0, + IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_SHORT_DS( + _indi, _symbol, _tf, _ap, + Util::MakeKey("Indi_TEMA_ON_" + _indi.GetFullName(), _ma_period, _ma_shift, (int)_ap)); + return iTEMAOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_SHORT, _ma_period, _ma_shift, _mode, _shift, _cache); + } + /** * OnCalculate() method for TEMA indicator. * diff --git a/Indicators/Indi_TRIX.mqh b/Indicators/Indi_TRIX.mqh index a8086bd27..da77f4e33 100644 --- a/Indicators/Indi_TRIX.mqh +++ b/Indicators/Indi_TRIX.mqh @@ -93,6 +93,16 @@ class Indi_TRIX : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of TriX. + */ + static double iTriXOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _ma_period, + ENUM_APPLIED_PRICE _ap, int _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_SHORT_DS( + _indi, _symbol, _tf, _ap, Util::MakeKey("Indi_TriX_ON_" + _indi.GetFullName(), _ma_period, (int)_ap)); + return iTriXOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_SHORT, _ma_period, _mode, _shift, _cache); + } + /** * OnCalculate() method for TriX indicator. */ diff --git a/Indicators/Indi_UltimateOscillator.mqh b/Indicators/Indi_UltimateOscillator.mqh index 7788bd77b..ee6782641 100644 --- a/Indicators/Indi_UltimateOscillator.mqh +++ b/Indicators/Indi_UltimateOscillator.mqh @@ -113,6 +113,26 @@ class Indi_UltimateOscillator : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of Ultimate Oscillator. + */ + static double iUOOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _fast_period, + int _middle_period, int _slow_period, int _fast_k, int _middle_k, int _slow_k, + int _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS( + _indi, _symbol, _tf, + Util::MakeKey("Indi_UltimateOscillator_ON_" + _indi.GetFullName(), _fast_period, _middle_period, _slow_period, + _fast_k, _middle_k, _slow_k)); + + // @fixit This won't work! Find a way to differentiate ATRs. + Indi_ATR *_indi_atr_fast = (Indi_ATR *)_indi.GetDataSource(INDI_ATR); + Indi_ATR *_indi_atr_middle = (Indi_ATR *)_indi.GetDataSource(INDI_ATR); + Indi_ATR *_indi_atr_slow = (Indi_ATR *)_indi.GetDataSource(INDI_ATR); + + return iUOOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _fast_period, _middle_period, _slow_period, _fast_k, + _middle_k, _slow_k, _mode, _shift, _cache, _indi_atr_fast, _indi_atr_middle, _indi_atr_slow); + } + /** * OnCalculate() method for Ultimate Oscillator. */ diff --git a/Indicators/Indi_VIDYA.mqh b/Indicators/Indi_VIDYA.mqh index a5647974c..15f959e15 100644 --- a/Indicators/Indi_VIDYA.mqh +++ b/Indicators/Indi_VIDYA.mqh @@ -98,6 +98,19 @@ class Indi_VIDYA : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of VIDya indicator. + */ + static double iVIDyAOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _cmo_period, + int _ema_period, int _ma_shift, ENUM_APPLIED_PRICE _ap, int _mode = 0, int _shift = 0, + IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_SHORT_DS( + _indi, _symbol, _tf, _ap, + Util::MakeKey("Indi_VIDYA_ON_" + _indi.GetFullName(), _cmo_period, _ema_period, _ma_shift, (int)_ap)); + return iVIDyAOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_SHORT, _cmo_period, _ema_period, _ma_shift, _mode, _shift, + _cache); + } + /** * OnCalculate() method for VIDyA indicator. * diff --git a/Indicators/Indi_VROC.mqh b/Indicators/Indi_VROC.mqh index 2170fa831..dfad54d06 100644 --- a/Indicators/Indi_VROC.mqh +++ b/Indicators/Indi_VROC.mqh @@ -65,7 +65,7 @@ class Indi_VROC : public Indicator { } /** - * Calculates AMVROC on the array of values. + * Calculates VROC on the array of values. */ static double iVROCOnArray(INDICATOR_CALCULATE_PARAMS_LONG, int _period, ENUM_APPLIED_VOLUME _av, int _mode, int _shift, IndicatorCalculateCache *_cache, bool _recalculate = false) { @@ -85,6 +85,16 @@ class Indi_VROC : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of VROC indicator. + */ + static double iVROCOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _period, + ENUM_APPLIED_VOLUME _av, int _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS( + _indi, _symbol, _tf, Util::MakeKey("Indi_VROC_ON_" + _indi.GetFullName(), _period, (int)_av)); + return iVROCOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _period, _av, _mode, _shift, _cache); + } + /** * OnCalculate() method for VROC indicator. */ diff --git a/Indicators/Indi_Volumes.mqh b/Indicators/Indi_Volumes.mqh index 786f9fbbe..4fb2a2888 100644 --- a/Indicators/Indi_Volumes.mqh +++ b/Indicators/Indi_Volumes.mqh @@ -44,7 +44,7 @@ struct IndiVolumesParams : IndicatorParams { }; /** - * Implements the Bill Williams' Accelerator/Decelerator oscillator. + * Implements the Volumes indicator. */ class Indi_Volumes : public Indicator { public: @@ -84,6 +84,16 @@ class Indi_Volumes : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of Volumes indicator. + */ + static double iVolumesOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, ENUM_APPLIED_VOLUME _av, + int _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS( + _indi, _symbol, _tf, Util::MakeKey("Indi_Volumes_ON_" + _indi.GetFullName(), (int)_av)); + return iVolumesOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _av, _mode, _shift, _cache); + } + /** * OnCalculate() method for Volumes indicator. */ diff --git a/Indicators/Indi_WilliamsAD.mqh b/Indicators/Indi_WilliamsAD.mqh index 754cff808..36b56685b 100644 --- a/Indicators/Indi_WilliamsAD.mqh +++ b/Indicators/Indi_WilliamsAD.mqh @@ -80,6 +80,16 @@ class Indi_WilliamsAD : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of Williams' AD. + */ + static double iWADOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _mode = 0, + int _shift = 0, IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS(_indi, _symbol, _tf, + Util::MakeKey("Indi_WilliamsAD_ON_" + _indi.GetFullName())); + return iWADOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _mode, _shift, _cache); + } + /** * OnCalculate() method for Williams' AD indicator. */ diff --git a/Indicators/Indi_ZigZag.mqh b/Indicators/Indi_ZigZag.mqh index 94fa26e33..e79ca128c 100644 --- a/Indicators/Indi_ZigZag.mqh +++ b/Indicators/Indi_ZigZag.mqh @@ -135,6 +135,18 @@ class Indi_ZigZag : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of ZigZag indicator. + */ + static double iZigZagOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _depth, + int _deviation, int _backstep, int _mode = 0, int _shift = 0, + IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS( + _indi, _symbol, _tf, Util::MakeKey("Indi_ZigZag_ON_" + _indi.GetFullName(), _depth, _deviation, _backstep)); + return iZigZagOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _depth, _deviation, _backstep, _mode, _shift, + _cache); + } + /** * OnCalculate() method for ZigZag indicator. */ diff --git a/Indicators/Indi_ZigZagColor.mqh b/Indicators/Indi_ZigZagColor.mqh index 26489fd8f..f30004ebb 100644 --- a/Indicators/Indi_ZigZagColor.mqh +++ b/Indicators/Indi_ZigZagColor.mqh @@ -96,6 +96,19 @@ class Indi_ZigZagColor : public Indicator { return _cache.GetTailValue(_mode, _shift); } + /** + * On-indicator version of ZigZag indicator. + */ + static double iZigZagColorOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _depth, + int _deviation, int _backstep, int _mode = 0, int _shift = 0, + IndicatorBase *_obj = NULL) { + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS( + _indi, _symbol, _tf, + Util::MakeKey("Indi_ZigZagColor_ON_" + _indi.GetFullName(), _depth, _deviation, _backstep)); + return iZigZagColorOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _depth, _deviation, _backstep, _mode, _shift, + _cache); + } + /** * OnCalculate() method for ZigZag Color indicator. */ diff --git a/Storage/ValueStorage.h b/Storage/ValueStorage.h index 6fa64909a..0348eb0c5 100644 --- a/Storage/ValueStorage.h +++ b/Storage/ValueStorage.h @@ -91,6 +91,17 @@ enum ENUM_IPEAK { IPEAK_LOWEST, IPEAK_HIGHEST }; ValueStorage *_price = INDI.GetValueStorage(APPLIED_PRICE); \ INDICATOR_CALCULATE_POPULATE_CACHE(SYMBOL, TF, KEY) +#define INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS(INDI, SYMBOL, TF, KEY) \ + ValueStorage *_time = (ValueStorage *)INDI.GetSpecificValueStorage(INDI_VS_TYPE_TIME); \ + ValueStorage *_tick_volume = (ValueStorage *)INDI.GetSpecificValueStorage(INDI_VS_TYPE_TICK_VOLUME); \ + ValueStorage *_volume = (ValueStorage *)INDI.GetSpecificValueStorage(INDI_VS_TYPE_VOLUME); \ + ValueStorage *_spread = (ValueStorage *)INDI.GetSpecificValueStorage(INDI_VS_TYPE_SPREAD); \ + ValueStorage *_price_open = (ValueStorage *)INDI.GetSpecificValueStorage(INDI_VS_TYPE_PRICE_OPEN); \ + ValueStorage *_price_high = (ValueStorage *)INDI.GetSpecificValueStorage(INDI_VS_TYPE_PRICE_HIGH); \ + ValueStorage *_price_low = (ValueStorage *)INDI.GetSpecificValueStorage(INDI_VS_TYPE_PRICE_LOW); \ + ValueStorage *_price_close = (ValueStorage *)INDI.GetSpecificValueStorage(INDI_VS_TYPE_PRICE_CLOSE); \ + INDICATOR_CALCULATE_POPULATE_CACHE(SYMBOL, TF, KEY) + #define INDICATOR_CALCULATE_POPULATED_PARAMS_LONG \ _time, _price_open, _price_high, _price_low, _price_close, _tick_volume, _volume, _spread From a493f36b41fde813afa3ca534fc4f98908ff746a Mon Sep 17 00:00:00 2001 From: Adrian Kierzkowski Date: Thu, 9 Dec 2021 19:43:19 +0100 Subject: [PATCH 34/77] WIP. Finished i*OnIndicator mode for all indicators except MA. Changed default shift for IndicatorBase::GetEntry() from -1 to 0. AMA and BWMFI don't work yet. --- Chart.mqh | 2 +- EA.mqh | 2 +- Indicator.define.h | 14 +- Indicator.enum.h | 171 ++++++++++---------- Indicator.mqh | 134 +-------------- Indicator/IndicatorCandle.h | 12 +- Indicator/IndicatorTick.h | 2 +- Indicator/tests/classes/IndicatorTickReal.h | 3 + IndicatorBase.h | 136 +++++++++++++++- Indicators/Bitwise/Indi_Candle.mqh | 2 +- Indicators/Bitwise/Indi_Pattern.mqh | 4 +- Indicators/Indi_AC.mqh | 2 +- Indicators/Indi_AD.mqh | 2 +- Indicators/Indi_ADX.mqh | 2 +- Indicators/Indi_ADXW.mqh | 6 +- Indicators/Indi_AMA.mqh | 55 ++++--- Indicators/Indi_AO.mqh | 2 +- Indicators/Indi_ASI.mqh | 7 +- Indicators/Indi_ATR.mqh | 2 +- Indicators/Indi_Alligator.mqh | 2 +- Indicators/Indi_AppliedPrice.mqh | 2 +- Indicators/Indi_BWMFI.mqh | 4 +- Indicators/Indi_BWZT.mqh | 17 +- Indicators/Indi_Bands.mqh | 2 +- Indicators/Indi_BearsPower.mqh | 2 +- Indicators/Indi_BullsPower.mqh | 2 +- Indicators/Indi_CCI.mqh | 2 +- Indicators/Indi_CHO.mqh | 6 +- Indicators/Indi_CHV.mqh | 6 +- Indicators/Indi_ColorBars.mqh | 5 +- Indicators/Indi_ColorCandlesDaily.mqh | 6 +- Indicators/Indi_ColorLine.mqh | 5 +- Indicators/Indi_CustomMovingAverage.mqh | 4 +- Indicators/Indi_DEMA.mqh | 10 +- Indicators/Indi_DeMarker.mqh | 2 +- Indicators/Indi_Demo.mqh | 2 +- Indicators/Indi_DetrendedPrice.mqh | 6 +- Indicators/Indi_Drawer.mqh | 2 +- Indicators/Indi_Envelopes.mqh | 4 +- Indicators/Indi_Force.mqh | 2 +- Indicators/Indi_FractalAdaptiveMA.mqh | 6 +- Indicators/Indi_Fractals.mqh | 4 +- Indicators/Indi_Gator.mqh | 4 +- Indicators/Indi_HeikenAshi.mqh | 6 +- Indicators/Indi_Ichimoku.mqh | 4 +- Indicators/Indi_Killzones.mqh | 2 +- Indicators/Indi_MA.mqh | 2 +- Indicators/Indi_MACD.mqh | 2 +- Indicators/Indi_MFI.mqh | 2 +- Indicators/Indi_MassIndex.mqh | 6 +- Indicators/Indi_Momentum.mqh | 2 +- Indicators/Indi_OBV.mqh | 2 +- Indicators/Indi_OsMA.mqh | 2 +- Indicators/Indi_Pivot.mqh | 4 +- Indicators/Indi_PriceChannel.mqh | 6 +- Indicators/Indi_PriceFeeder.mqh | 2 +- Indicators/Indi_PriceVolumeTrend.mqh | 6 +- Indicators/Indi_RS.mqh | 2 +- Indicators/Indi_RSI.mqh | 2 +- Indicators/Indi_RVI.mqh | 2 +- Indicators/Indi_RateOfChange.mqh | 6 +- Indicators/Indi_SAR.mqh | 2 +- Indicators/Indi_StdDev.mqh | 2 +- Indicators/Indi_Stochastic.mqh | 2 +- Indicators/Indi_TEMA.mqh | 12 +- Indicators/Indi_TRIX.mqh | 6 +- Indicators/Indi_UltimateOscillator.mqh | 31 +++- Indicators/Indi_VIDYA.mqh | 7 +- Indicators/Indi_VROC.mqh | 6 +- Indicators/Indi_Volumes.mqh | 6 +- Indicators/Indi_WPR.mqh | 2 +- Indicators/Indi_WilliamsAD.mqh | 5 +- Indicators/Indi_ZigZag.mqh | 13 +- Indicators/Indi_ZigZagColor.mqh | 11 +- Indicators/OHLC/Indi_OHLC.mqh | 2 +- Indicators/Price/Indi_Price.mqh | 2 +- Indicators/Special/Indi_Math.mqh | 2 +- Indicators/Tick/Indi_TickMt.mqh | 2 +- tests/IndicatorsTest.mq5 | 5 + 79 files changed, 493 insertions(+), 352 deletions(-) diff --git a/Chart.mqh b/Chart.mqh index a568d8ae5..c73720415 100644 --- a/Chart.mqh +++ b/Chart.mqh @@ -224,7 +224,7 @@ class Chart : public Market { * @return * Returns ChartEntry struct. */ - ChartEntry GetEntry(unsigned int _shift = 0) { + ChartEntry GetEntry(int _shift = 0) { ChartEntry _chart_entry; BarOHLC _ohlc = GetOHLC(_shift); if (_ohlc.open > 0) { diff --git a/EA.mqh b/EA.mqh index 62cd02cb8..cf5ef44d2 100644 --- a/EA.mqh +++ b/EA.mqh @@ -149,7 +149,7 @@ class EA { * @return * Returns TradeSignalEntry struct. */ - TradeSignalEntry GetStrategySignalEntry(Strategy *_strat, bool _trade_allowed = true, int _shift = -1) { + TradeSignalEntry GetStrategySignalEntry(Strategy *_strat, bool _trade_allowed = true, int _shift = 0) { // float _bf = 1.0; float _scl = _strat.Get(STRAT_PARAM_SCL); float _sol = _strat.Get(STRAT_PARAM_SOL); diff --git a/Indicator.define.h b/Indicator.define.h index 6743cba67..ab51a433d 100644 --- a/Indicator.define.h +++ b/Indicator.define.h @@ -43,12 +43,14 @@ } \ SET_HANDLE; \ } \ - int _bars_calc = ::BarsCalculated(_handle); \ - if (GetLastError() > 0) { \ - return EMPTY_VALUE; \ - } else if (_bars_calc <= 2) { \ - SetUserError(ERR_USER_INVALID_BUFF_NUM); \ - return EMPTY_VALUE; \ + if (Terminal::IsVisualMode()) { \ + int _bars_calc = ::BarsCalculated(_handle); \ + if (GetLastError() > 0) { \ + return EMPTY_VALUE; \ + } else if (_bars_calc <= 2) { \ + SetUserError(ERR_USER_INVALID_BUFF_NUM); \ + return EMPTY_VALUE; \ + } \ } \ if (::CopyBuffer(_handle, _mode, _shift, 1, _res) < 0) { \ return ArraySize(_res) > 0 ? _res[0] : EMPTY_VALUE; \ diff --git a/Indicator.enum.h b/Indicator.enum.h index e67e3ff88..c98f42ce1 100644 --- a/Indicator.enum.h +++ b/Indicator.enum.h @@ -42,90 +42,93 @@ enum ENUM_INDICATOR_ACTION { /* Define type of indicators. */ enum ENUM_INDICATOR_TYPE { - INDI_NONE = 0, // (None) - INDI_AC, // Accelerator Oscillator - INDI_AD, // Accumulation/Distribution - INDI_ADX, // Average Directional Index - INDI_ADXW, // ADX by Welles Wilder - INDI_ALLIGATOR, // Alligator - INDI_AMA, // Adaptive Moving Average - INDI_APPLIED_PRICE, // Applied Price over OHLC Indicator - INDI_AO, // Awesome Oscillator - INDI_ASI, // Accumulation Swing Index - INDI_ATR, // Average True Range - INDI_BANDS, // Bollinger Bands - INDI_BANDS_ON_PRICE, // Bollinger Bands (on Price) - INDI_BEARS, // Bears Power - INDI_BULLS, // Bulls Power - INDI_BWMFI, // Market Facilitation Index - INDI_BWZT, // Bill Williams' Zone Trade - INDI_CANDLE, // Candle Pattern Detector - INDI_CCI, // Commodity Channel Index - INDI_CCI_ON_PRICE, // Commodity Channel Index (CCI) (on Price) - INDI_CHAIKIN, // Chaikin Oscillator - INDI_CHAIKIN_V, // Chaikin Volatility - INDI_COLOR_BARS, // Color Bars - INDI_COLOR_CANDLES_DAILY, // Color Candles Daily - INDI_COLOR_LINE, // Color Line - INDI_CUSTOM, // Custom indicator - INDI_CUSTOM_MOVING_AVG, // Custom Moving Average - INDI_DEMA, // Double Exponential Moving Average - INDI_DEMARKER, // DeMarker - INDI_DEMO, // Demo/Dummy Indicator - INDI_DETRENDED_PRICE, // Detrended Price Oscillator - INDI_DRAWER, // Drawer (Socket-based) Indicator - INDI_ENVELOPES, // Envelopes - INDI_ENVELOPES_ON_PRICE, // Evelopes (on Price) - INDI_FORCE, // Force Index - INDI_FRACTALS, // Fractals - INDI_FRAMA, // Fractal Adaptive Moving Average - INDI_GATOR, // Gator Oscillator - INDI_HEIKENASHI, // Heiken Ashi - INDI_ICHIMOKU, // Ichimoku Kinko Hyo - INDI_KILLZONES, // Killzones - INDI_MA, // Moving Average - INDI_MACD, // MACD - INDI_MA_ON_PRICE, // Moving Average (on Price). - INDI_MARKET_FI, // Market Facilitation Index - INDI_MASS_INDEX, // Mass Index - INDI_MFI, // Money Flow Index - INDI_MOMENTUM, // Momentum - INDI_MOMENTUM_ON_PRICE, // Momentum (on Price) - INDI_OBV, // On Balance Volume - INDI_OHLC, // OHLC (Open-High-Low-Close) - INDI_OSMA, // OsMA - INDI_PATTERN, // Pattern Detector - INDI_PIVOT, // Pivot Detector - INDI_PRICE, // Price - INDI_PRICE_CHANNEL, // Price Channel - INDI_PRICE_FEEDER, // Indicator which returns prices from custom array - INDI_PRICE_VOLUME_TREND, // Price and Volume Trend - INDI_RATE_OF_CHANGE, // Rate of Change - INDI_RS, // Indi_Math-based RSI indicator. - INDI_RSI, // Relative Strength Index - INDI_RSI_ON_PRICE, // Relative Strength Index (RSI) (on Price) - INDI_RVI, // Relative Vigor Index - INDI_SAR, // Parabolic SAR - INDI_SPECIAL_MATH, // Math operations over given indicator. - INDI_STDDEV, // Standard Deviation - INDI_STDDEV_ON_MA_SMA, // Standard Deviation on Moving Average in SMA mode - INDI_STDDEV_ON_PRICE, // Standard Deviation (on Price) - INDI_STDDEV_SMA_ON_PRICE, // Standard Deviation in SMA mode (on Price) - INDI_STOCHASTIC, // Stochastic Oscillator - INDI_SVE_BB, // SVE Bollinger Bands - INDI_TEMA, // Triple Exponential Moving Average - INDI_TF, // Timeframe - INDI_TICK, // Tick - INDI_TMA_TRUE, // Triangular Moving Average True - INDI_TRIX, // Triple Exponential Moving Averages Oscillator - INDI_ULTIMATE_OSCILLATOR, // Ultimate Oscillator - INDI_VIDYA, // Variable Index Dynamic Average - INDI_VOLUMES, // Volumes - INDI_VROC, // Volume Rate of Change - INDI_WILLIAMS_AD, // Larry Williams' Accumulation/Distribution - INDI_WPR, // Williams' Percent Range - INDI_ZIGZAG, // ZigZag - INDI_ZIGZAG_COLOR, // ZigZag Color + INDI_NONE = 0, // (None) + INDI_AC, // Accelerator Oscillator + INDI_AD, // Accumulation/Distribution + INDI_ADX, // Average Directional Index + INDI_ADXW, // ADX by Welles Wilder + INDI_ALLIGATOR, // Alligator + INDI_AMA, // Adaptive Moving Average + INDI_APPLIED_PRICE, // Applied Price over OHLC Indicator + INDI_AO, // Awesome Oscillator + INDI_ASI, // Accumulation Swing Index + INDI_ATR, // Average True Range + INDI_BANDS, // Bollinger Bands + INDI_BANDS_ON_PRICE, // Bollinger Bands (on Price) + INDI_BEARS, // Bears Power + INDI_BULLS, // Bulls Power + INDI_BWMFI, // Market Facilitation Index + INDI_BWZT, // Bill Williams' Zone Trade + INDI_CANDLE, // Candle Pattern Detector + INDI_CCI, // Commodity Channel Index + INDI_CCI_ON_PRICE, // Commodity Channel Index (CCI) (on Price) + INDI_CHAIKIN, // Chaikin Oscillator + INDI_CHAIKIN_V, // Chaikin Volatility + INDI_COLOR_BARS, // Color Bars + INDI_COLOR_CANDLES_DAILY, // Color Candles Daily + INDI_COLOR_LINE, // Color Line + INDI_CUSTOM, // Custom indicator + INDI_CUSTOM_MOVING_AVG, // Custom Moving Average + INDI_DEMA, // Double Exponential Moving Average + INDI_DEMARKER, // DeMarker + INDI_DEMO, // Demo/Dummy Indicator + INDI_DETRENDED_PRICE, // Detrended Price Oscillator + INDI_DRAWER, // Drawer (Socket-based) Indicator + INDI_ENVELOPES, // Envelopes + INDI_ENVELOPES_ON_PRICE, // Evelopes (on Price) + INDI_FORCE, // Force Index + INDI_FRACTALS, // Fractals + INDI_FRAMA, // Fractal Adaptive Moving Average + INDI_GATOR, // Gator Oscillator + INDI_HEIKENASHI, // Heiken Ashi + INDI_ICHIMOKU, // Ichimoku Kinko Hyo + INDI_KILLZONES, // Killzones + INDI_MA, // Moving Average + INDI_MACD, // MACD + INDI_MA_ON_PRICE, // Moving Average (on Price). + INDI_MARKET_FI, // Market Facilitation Index + INDI_MASS_INDEX, // Mass Index + INDI_MFI, // Money Flow Index + INDI_MOMENTUM, // Momentum + INDI_MOMENTUM_ON_PRICE, // Momentum (on Price) + INDI_OBV, // On Balance Volume + INDI_OHLC, // OHLC (Open-High-Low-Close) + INDI_OSMA, // OsMA + INDI_PATTERN, // Pattern Detector + INDI_PIVOT, // Pivot Detector + INDI_PRICE, // Price + INDI_PRICE_CHANNEL, // Price Channel + INDI_PRICE_FEEDER, // Indicator which returns prices from custom array + INDI_PRICE_VOLUME_TREND, // Price and Volume Trend + INDI_RATE_OF_CHANGE, // Rate of Change + INDI_RS, // Indi_Math-based RSI indicator. + INDI_RSI, // Relative Strength Index + INDI_RSI_ON_PRICE, // Relative Strength Index (RSI) (on Price) + INDI_RVI, // Relative Vigor Index + INDI_SAR, // Parabolic SAR + INDI_SPECIAL_MATH, // Math operations over given indicator. + INDI_STDDEV, // Standard Deviation + INDI_STDDEV_ON_MA_SMA, // Standard Deviation on Moving Average in SMA mode + INDI_STDDEV_ON_PRICE, // Standard Deviation (on Price) + INDI_STDDEV_SMA_ON_PRICE, // Standard Deviation in SMA mode (on Price) + INDI_STOCHASTIC, // Stochastic Oscillator + INDI_SVE_BB, // SVE Bollinger Bands + INDI_TEMA, // Triple Exponential Moving Average + INDI_TF, // Timeframe + INDI_TICK, // Tick + INDI_TMA_TRUE, // Triangular Moving Average True + INDI_TRIX, // Triple Exponential Moving Averages Oscillator + INDI_ULTIMATE_OSCILLATOR, // Ultimate Oscillator + INDI_ULTIMATE_OSCILLATOR_ATR_FAST, // Ultimate Oscillator's ATR, Fast + INDI_ULTIMATE_OSCILLATOR_ATR_MIDDLE, // Ultimate Oscillator's ATR, Middle + INDI_ULTIMATE_OSCILLATOR_ATR_SLOW, // Ultimate Oscillator's ATR, Slow + INDI_VIDYA, // Variable Index Dynamic Average + INDI_VOLUMES, // Volumes + INDI_VROC, // Volume Rate of Change + INDI_WILLIAMS_AD, // Larry Williams' Accumulation/Distribution + INDI_WPR, // Williams' Percent Range + INDI_ZIGZAG, // ZigZag + INDI_ZIGZAG_COLOR, // ZigZag Color FINAL_INDICATOR_TYPE_ENTRY }; diff --git a/Indicator.mqh b/Indicator.mqh index 389d9fc54..665ca3060 100644 --- a/Indicator.mqh +++ b/Indicator.mqh @@ -176,7 +176,7 @@ class Indicator : public IndicatorBase { /** * Gets an indicator property flag. */ - bool GetFlag(INDICATOR_ENTRY_FLAGS _prop, int _shift = -1) { + bool GetFlag(INDICATOR_ENTRY_FLAGS _prop, int _shift = 0) { IndicatorDataEntry _entry = GetEntry(_shift >= 0 ? _shift : iparams.GetShift()); return _entry.CheckFlag(_prop); } @@ -1166,138 +1166,6 @@ class Indicator : public IndicatorBase { virtual void GetEntryAlter(IndicatorDataEntry& _entry, int _index = -1) { _entry.AddFlags(_entry.GetDataTypeFlags(iparams.GetDataValueType())); }; - - /* Defines MQL backward compatible methods */ - - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, int _mode, int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, DUMMY); -#endif - } - - template - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, int _mode, int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _a, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, COMMA _a); -#endif - } - - template - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, int _mode, int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _a, _b, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, COMMA _a COMMA _b); -#endif - } - - template - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, int _mode, - int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c); -#endif - } - - template - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, int _mode, - int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d); -#endif - } - - template - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, - int _mode, int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e); -#endif - } - - template - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, - int _mode, int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f); -#endif - } - - template - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, - G _g, int _mode, int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _g, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g); -#endif - } - - template - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, - G _g, H _h, int _mode, int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _g, _h, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g COMMA _h); -#endif - } - - template - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, - G _g, H _h, I _i, int _mode, int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _g, _h, _i, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g COMMA _h COMMA _i); -#endif - } - - template - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, - G _g, H _h, I _i, J _j, int _mode, int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g COMMA _h COMMA _i COMMA _j); -#endif - } - - template - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, - G _g, H _h, I _i, J _j, K _k, int _mode, int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g COMMA _h COMMA _i COMMA _j COMMA _k); -#endif - } - - template - double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, 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, int _mode, int _shift) { -#ifdef __MQL4__ - return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _mode, _shift); -#else // __MQL5__ - ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g COMMA _h COMMA _i COMMA _j COMMA _k - COMMA _l COMMA _m); -#endif - } }; #endif diff --git a/Indicator/IndicatorCandle.h b/Indicator/IndicatorCandle.h index 34dbc37c6..6a36c4312 100644 --- a/Indicator/IndicatorCandle.h +++ b/Indicator/IndicatorCandle.h @@ -85,7 +85,7 @@ class IndicatorCandle : public IndicatorBase { * @return * Returns IndicatorDataEntry struct filled with indicator values. */ - IndicatorDataEntry GetEntry(int _index = -1) override { + IndicatorDataEntry GetEntry(int _index) override { ResetLastError(); unsigned int _ishift = _index >= 0 ? _index : icparams.GetShift(); long _candle_time = CalcCandleTimestamp(GetBarTime(_ishift)); @@ -118,7 +118,7 @@ class IndicatorCandle : public IndicatorBase { * @return * Returns DataParamEntry struct filled with a single value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { int _ishift = _shift >= 0 ? _shift : icparams.GetShift(); return GetEntry(_ishift)[_mode]; } @@ -205,9 +205,11 @@ class IndicatorCandle : public IndicatorBase { indi_src.Ptr().RemoveListener(THIS_PTR); } indi_src = _indi; - indi_src.Ptr().AddListener(THIS_PTR); - icparams.SetDataSource(-1, _input_mode); - indi_src.Ptr().OnBecomeDataSourceFor(THIS_PTR); + if (_indi != NULL) { + indi_src.Ptr().AddListener(THIS_PTR); + icparams.SetDataSource(-1, _input_mode); + indi_src.Ptr().OnBecomeDataSourceFor(THIS_PTR); + } } string CandlesToString() { diff --git a/Indicator/IndicatorTick.h b/Indicator/IndicatorTick.h index 4cf53be6b..79784d472 100644 --- a/Indicator/IndicatorTick.h +++ b/Indicator/IndicatorTick.h @@ -145,7 +145,7 @@ class IndicatorTick : public IndicatorBase { * @return * Returns DataParamEntry struct filled with a single value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { int _ishift = _shift >= 0 ? _shift : itparams.GetShift(); return GetEntry(_ishift)[_mode]; } diff --git a/Indicator/tests/classes/IndicatorTickReal.h b/Indicator/tests/classes/IndicatorTickReal.h index 668ddc1bf..a8884c3a6 100644 --- a/Indicator/tests/classes/IndicatorTickReal.h +++ b/Indicator/tests/classes/IndicatorTickReal.h @@ -74,6 +74,9 @@ class IndicatorTickReal : public IndicatorTick } } + // Clearing possible error 4004. + ResetLastError(); + for (int i = 0; i < _num_copied; ++i) { TickAB _tick(_ticks[i].ask, _ticks[i].bid); // We can't call EmitEntry() here, as tick would go to multiple sources at the same time! diff --git a/IndicatorBase.h b/IndicatorBase.h index a0bed2b73..5d74af976 100644 --- a/IndicatorBase.h +++ b/IndicatorBase.h @@ -507,7 +507,7 @@ class IndicatorBase : public Chart { /** * Returns the indicator's struct value. */ - virtual IndicatorDataEntry GetEntry(int _index = -1) = NULL; + virtual IndicatorDataEntry GetEntry(int _index = 0) = NULL; /** * Alters indicator's struct value. @@ -553,7 +553,7 @@ class IndicatorBase : public Chart { /** * Returns indicator value for a given shift and mode. */ - // virtual double GetValue(int _shift = -1, int _mode = 0) = NULL; + // virtual double GetValue(int _shift = 0, int _mode = 0) = NULL; /** * Checks whether indicator has a valid value for a given shift. @@ -635,6 +635,138 @@ class IndicatorBase : public Chart { * Gets indicator's time-frame. */ ENUM_TIMEFRAMES GetTf() { return Get(CHART_PARAM_TF); } + + /* Defines MQL backward compatible methods */ + + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, int _mode, int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, DUMMY); +#endif + } + + template + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, int _mode, int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _a, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, COMMA _a); +#endif + } + + template + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, int _mode, int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _a, _b, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, COMMA _a COMMA _b); +#endif + } + + template + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, int _mode, + int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c); +#endif + } + + template + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, int _mode, + int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d); +#endif + } + + template + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, + int _mode, int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e); +#endif + } + + template + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, + int _mode, int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f); +#endif + } + + template + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, + G _g, int _mode, int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _g, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g); +#endif + } + + template + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, + G _g, H _h, int _mode, int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _g, _h, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g COMMA _h); +#endif + } + + template + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, + G _g, H _h, I _i, int _mode, int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _g, _h, _i, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g COMMA _h COMMA _i); +#endif + } + + template + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, + G _g, H _h, I _i, J _j, int _mode, int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g COMMA _h COMMA _i COMMA _j); +#endif + } + + template + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, + G _g, H _h, I _i, J _j, K _k, int _mode, int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g COMMA _h COMMA _i COMMA _j COMMA _k); +#endif + } + + template + double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, 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, int _mode, int _shift) { +#ifdef __MQL4__ + return ::iCustom(_symbol, _tf, _name, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _mode, _shift); +#else // __MQL5__ + ICUSTOM_DEF(;, COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g COMMA _h COMMA _i COMMA _j COMMA _k + COMMA _l COMMA _m); +#endif + } }; /** diff --git a/Indicators/Bitwise/Indi_Candle.mqh b/Indicators/Bitwise/Indi_Candle.mqh index a9b94aea1..40575e792 100644 --- a/Indicators/Bitwise/Indi_Candle.mqh +++ b/Indicators/Bitwise/Indi_Candle.mqh @@ -66,7 +66,7 @@ class Indi_Candle : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); BarOHLC _ohlcs[1]; diff --git a/Indicators/Bitwise/Indi_Pattern.mqh b/Indicators/Bitwise/Indi_Pattern.mqh index f9e014ec0..fec403314 100644 --- a/Indicators/Bitwise/Indi_Pattern.mqh +++ b/Indicators/Bitwise/Indi_Pattern.mqh @@ -57,7 +57,7 @@ class Indi_Pattern : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { int i; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); BarOHLC _ohlcs[8]; @@ -112,7 +112,7 @@ class Indi_Pattern : public Indicator { /** * Alters indicator's struct value. */ - virtual void GetEntryAlter(IndicatorDataEntry& _entry, int _shift = -1) { + virtual void GetEntryAlter(IndicatorDataEntry& _entry, int _shift = 0) { _entry.SetFlag(INDI_ENTRY_FLAG_IS_BITWISE, true); Indicator::GetEntryAlter(_entry); } diff --git a/Indicators/Indi_AC.mqh b/Indicators/Indi_AC.mqh index be9fe709b..8c222b537 100644 --- a/Indicators/Indi_AC.mqh +++ b/Indicators/Indi_AC.mqh @@ -100,7 +100,7 @@ class Indi_AC : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { IndicatorDataEntryValue _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_AD.mqh b/Indicators/Indi_AD.mqh index 51ea677cf..8473fe8de 100644 --- a/Indicators/Indi_AD.mqh +++ b/Indicators/Indi_AD.mqh @@ -101,7 +101,7 @@ class Indi_AD : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_ADX.mqh b/Indicators/Indi_ADX.mqh index 752805800..041d8b975 100644 --- a/Indicators/Indi_ADX.mqh +++ b/Indicators/Indi_ADX.mqh @@ -115,7 +115,7 @@ class Indi_ADX : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = LINE_MAIN_ADX, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = LINE_MAIN_ADX, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_ADXW.mqh b/Indicators/Indi_ADXW.mqh index b8142fd78..bac89a6c8 100644 --- a/Indicators/Indi_ADXW.mqh +++ b/Indicators/Indi_ADXW.mqh @@ -225,7 +225,7 @@ class Indi_ADXW : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = LINE_MAIN_ADX, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = LINE_MAIN_ADX, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -237,6 +237,10 @@ class Indi_ADXW : public Indicator { _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod() /*]*/, _mode, _ishift); break; + case IDATA_INDICATOR: + _value = Indi_ADXW::iADXWilderOnIndicator(GetDataSource(), GetSymbol(), GetTf(), /*[*/ GetPeriod() /*]*/, _mode, + _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); } diff --git a/Indicators/Indi_AMA.mqh b/Indicators/Indi_AMA.mqh index d71d33756..4342dad6c 100644 --- a/Indicators/Indi_AMA.mqh +++ b/Indicators/Indi_AMA.mqh @@ -22,13 +22,14 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTf.h" +#include "../Indicator/tests/classes/IndicatorTickReal.h" #include "../Storage/ValueStorage.h" #include "../Storage/ValueStorage.price.h" #include "Price/Indi_Price.mqh" // Structs. -struct IndiAMAParams : IndicatorParams { +struct IndiAMAParams : IndicatorTfParams { unsigned int period; unsigned int fast_period; unsigned int slow_period; @@ -41,8 +42,7 @@ struct IndiAMAParams : IndicatorParams { fast_period(_fast_period), slow_period(_slow_period), ama_shift(_ama_shift), - applied_price(_ap), - IndicatorParams(INDI_AMA, 1, TYPE_DOUBLE) { + applied_price(_ap) { SetDataValueRange(IDATA_RANGE_PRICE); SetShift(_shift); switch (idstype) { @@ -62,13 +62,26 @@ struct IndiAMAParams : IndicatorParams { /** * Implements the AMA indicator. */ -class Indi_AMA : public Indicator { +class Indi_AMA : public IndicatorTf { public: /** * Class constructor. */ - Indi_AMA(IndiAMAParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_AMA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_AMA, _tf, _shift){}; + Indi_AMA(IndiAMAParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTf(_p) { + icparams.SetIndicatorType(INDI_AMA); + if (_indi_src != NULL) { + SetDataSource(_indi_src); + icparams.SetDataSourceType(IDATA_INDICATOR); + } else { + // Defaulting to platform ticks. + SetDataSource(new IndicatorTickReal(GetSymbol(), GetTf(), "AMA on IndicatorTickReal")); + icparams.SetDataSourceType(IDATA_INDICATOR); + } + }; + Indi_AMA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTf(_tf) { + icparams.SetIndicatorType(INDI_AMA); + icparams.SetShift(_shift); + }; /** * Built-in version of AMA. @@ -213,16 +226,16 @@ class Indi_AMA : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; - int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + int _ishift = _shift >= 0 ? _shift : icparams.GetShift(); + switch (icparams.idstype) { case IDATA_BUILTIN: _value = Indi_AMA::iAMA(GetSymbol(), GetTf(), /*[*/ GetPeriod(), GetFastPeriod(), GetSlowPeriod(), GetAMAShift(), GetAppliedPrice() /*]*/, _mode, _ishift, THIS_PTR); break; case IDATA_ICUSTOM: - _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod(), + _value = iCustom(istate.handle, GetSymbol(), GetTf(), icparams.GetCustomIndicatorName(), /*[*/ GetPeriod(), GetFastPeriod(), GetSlowPeriod(), GetAMAShift() /*]*/, _mode, _ishift); break; @@ -242,27 +255,27 @@ class Indi_AMA : public Indicator { /** * Get AMA shift. */ - unsigned int GetAMAShift() { return iparams.ama_shift; } + unsigned int GetAMAShift() { return icparams.ama_shift; } /** * Get period. */ - unsigned int GetPeriod() { return iparams.period; } + unsigned int GetPeriod() { return icparams.period; } /** * Get fast period. */ - unsigned int GetFastPeriod() { return iparams.fast_period; } + unsigned int GetFastPeriod() { return icparams.fast_period; } /** * Get slow period. */ - unsigned int GetSlowPeriod() { return iparams.slow_period; } + unsigned int GetSlowPeriod() { return icparams.slow_period; } /** * Get applied price. */ - ENUM_APPLIED_PRICE GetAppliedPrice() { return iparams.applied_price; } + ENUM_APPLIED_PRICE GetAppliedPrice() { return icparams.applied_price; } /* Setters */ @@ -271,7 +284,7 @@ class Indi_AMA : public Indicator { */ void SetAMAShift(unsigned int _ama_shift) { istate.is_changed = true; - iparams.ama_shift = _ama_shift; + icparams.ama_shift = _ama_shift; } /** @@ -279,7 +292,7 @@ class Indi_AMA : public Indicator { */ void SetPeriod(unsigned int _period) { istate.is_changed = true; - iparams.period = _period; + icparams.period = _period; } /** @@ -287,7 +300,7 @@ class Indi_AMA : public Indicator { */ void SetFastPeriod(unsigned int _fast_period) { istate.is_changed = true; - iparams.fast_period = _fast_period; + icparams.fast_period = _fast_period; } /** @@ -295,7 +308,7 @@ class Indi_AMA : public Indicator { */ void SetSlowPeriod(unsigned int _slow_period) { istate.is_changed = true; - iparams.slow_period = _slow_period; + icparams.slow_period = _slow_period; } /** @@ -303,6 +316,6 @@ class Indi_AMA : public Indicator { */ void SetAppliedPrice(ENUM_APPLIED_PRICE _applied_price) { istate.is_changed = true; - iparams.applied_price = _applied_price; + icparams.applied_price = _applied_price; } }; diff --git a/Indicators/Indi_AO.mqh b/Indicators/Indi_AO.mqh index a88552202..e65e367aa 100644 --- a/Indicators/Indi_AO.mqh +++ b/Indicators/Indi_AO.mqh @@ -103,7 +103,7 @@ class Indi_AO : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_ASI.mqh b/Indicators/Indi_ASI.mqh index 1e9f54281..1f18b15a5 100644 --- a/Indicators/Indi_ASI.mqh +++ b/Indicators/Indi_ASI.mqh @@ -165,7 +165,7 @@ class Indi_ASI : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -178,8 +178,11 @@ class Indi_ASI : public Indicator { Util::MakeKey("Indi_ASI", GetMaximumPriceChanging())); _value = iASIOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, GetMaximumPriceChanging(), _mode, _ishift, _cache); + } break; + case IDATA_INDICATOR: + _value = Indi_ASI::iASIOnIndicator(GetDataSource(), GetSymbol(), GetTf(), /*[*/ GetMaximumPriceChanging() /*]*/, + _mode, _ishift, THIS_PTR); break; - } default: SetUserError(ERR_INVALID_PARAMETER); } diff --git a/Indicators/Indi_ATR.mqh b/Indicators/Indi_ATR.mqh index c74f1edd6..f0d65d2f1 100644 --- a/Indicators/Indi_ATR.mqh +++ b/Indicators/Indi_ATR.mqh @@ -103,7 +103,7 @@ class Indi_ATR : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_Alligator.mqh b/Indicators/Indi_Alligator.mqh index 62b552df7..52acbfd76 100644 --- a/Indicators/Indi_Alligator.mqh +++ b/Indicators/Indi_Alligator.mqh @@ -162,7 +162,7 @@ class Indi_Alligator : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); #ifdef __MQL4__ diff --git a/Indicators/Indi_AppliedPrice.mqh b/Indicators/Indi_AppliedPrice.mqh index 379596331..90e78ed63 100644 --- a/Indicators/Indi_AppliedPrice.mqh +++ b/Indicators/Indi_AppliedPrice.mqh @@ -74,7 +74,7 @@ class Indi_AppliedPrice : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_BWMFI.mqh b/Indicators/Indi_BWMFI.mqh index cc8b55e08..b0e3e1853 100644 --- a/Indicators/Indi_BWMFI.mqh +++ b/Indicators/Indi_BWMFI.mqh @@ -114,7 +114,7 @@ class Indi_BWMFI : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = BWMFI_BUFFER, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = BWMFI_BUFFER, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -136,7 +136,7 @@ class Indi_BWMFI : public Indicator { /** * Alters indicator's struct value. */ - virtual void GetEntryAlter(IndicatorDataEntry &_entry, int _shift = -1) { + virtual void GetEntryAlter(IndicatorDataEntry &_entry, int _shift = 0) { Indicator::GetEntryAlter(_entry); #ifdef __MQL4__ // @see: https://en.wikipedia.org/wiki/Market_facilitation_index diff --git a/Indicators/Indi_BWZT.mqh b/Indicators/Indi_BWZT.mqh index 08405e14f..73d027824 100644 --- a/Indicators/Indi_BWZT.mqh +++ b/Indicators/Indi_BWZT.mqh @@ -40,8 +40,8 @@ enum ENUM_INDI_BWZT_MODE { // Structs. struct IndiBWZTParams : IndicatorParams { - Indi_AC *indi_ac; - Indi_AC *indi_ao; + Ref indi_ac; + Ref indi_ao; unsigned int period; unsigned int second_period; unsigned int sum_period; @@ -109,8 +109,8 @@ class Indi_BWZT : public Indicator { /** * On-indicator version of BWZT. */ - static double iBWZTOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, double _mpc, int _mode, - int _shift, IndicatorBase *_obj) { + static double iBWZTOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _mode, int _shift, + IndicatorBase *_obj) { INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS(_indi, _symbol, _tf, Util::MakeKey("Indi_BWZT_ON_" + _indi.GetFullName())); @@ -126,9 +126,9 @@ class Indi_BWZT : public Indicator { virtual IndicatorBase *FetchDataSource(ENUM_INDICATOR_TYPE _id) override { switch (_id) { case INDI_AC: - return iparams.indi_ac; + return iparams.indi_ac.Ptr(); case INDI_AO: - return iparams.indi_ac; + return iparams.indi_ac.Ptr(); } return NULL; @@ -204,7 +204,7 @@ class Indi_BWZT : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -214,6 +214,9 @@ class Indi_BWZT : public Indicator { case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), _mode, _ishift); break; + case IDATA_INDICATOR: + _value = Indi_BWZT::iBWZTOnIndicator(GetDataSource(), GetSymbol(), GetTf(), _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); break; diff --git a/Indicators/Indi_Bands.mqh b/Indicators/Indi_Bands.mqh index 0ff6a92e1..a368d6b85 100644 --- a/Indicators/Indi_Bands.mqh +++ b/Indicators/Indi_Bands.mqh @@ -239,7 +239,7 @@ class Indi_Bands : public Indicator { * Note that in MQL5 Applied Price must be passed as the last parameter * (before mode and shift). */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = BAND_BASE, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = BAND_BASE, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_BearsPower.mqh b/Indicators/Indi_BearsPower.mqh index 1b9721606..b2bb83164 100644 --- a/Indicators/Indi_BearsPower.mqh +++ b/Indicators/Indi_BearsPower.mqh @@ -104,7 +104,7 @@ class Indi_BearsPower : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_BullsPower.mqh b/Indicators/Indi_BullsPower.mqh index 1741f8da7..1e55f0010 100644 --- a/Indicators/Indi_BullsPower.mqh +++ b/Indicators/Indi_BullsPower.mqh @@ -104,7 +104,7 @@ class Indi_BullsPower : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_CCI.mqh b/Indicators/Indi_CCI.mqh index c32d4c191..ed4f71c4a 100644 --- a/Indicators/Indi_CCI.mqh +++ b/Indicators/Indi_CCI.mqh @@ -145,7 +145,7 @@ class Indi_CCI : public Indicator { * Note that in MQL5 Applied Price must be passed as the last parameter * (before mode and shift). */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); double _value = EMPTY_VALUE; switch (iparams.idstype) { diff --git a/Indicators/Indi_CHO.mqh b/Indicators/Indi_CHO.mqh index 6106dbefe..a42f126a7 100644 --- a/Indicators/Indi_CHO.mqh +++ b/Indicators/Indi_CHO.mqh @@ -180,7 +180,7 @@ class Indi_CHO : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -192,6 +192,10 @@ class Indi_CHO : public Indicator { _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetFastMA(), GetSlowMA(), GetSmoothMethod(), GetInputVolume() /*]*/, 0, _ishift); break; + case IDATA_INDICATOR: + _value = Indi_CHO::iChaikinOnIndicator(GetDataSource(), GetSymbol(), GetTf(), /*[*/ GetFastMA(), GetSlowMA(), + GetSmoothMethod(), GetInputVolume() /*]*/, _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); } diff --git a/Indicators/Indi_CHV.mqh b/Indicators/Indi_CHV.mqh index 8b8f9490e..1c0c15119 100644 --- a/Indicators/Indi_CHV.mqh +++ b/Indicators/Indi_CHV.mqh @@ -175,7 +175,7 @@ class Indi_CHV : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -187,6 +187,10 @@ class Indi_CHV : public Indicator { _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetSmoothPeriod(), GetCHVPeriod(), GetSmoothMethod() /*]*/, _mode, _ishift); break; + case IDATA_INDICATOR: + _value = Indi_CHV::iCHVOnIndicator(GetDataSource(), GetSymbol(), GetTf(), /*[*/ GetSmoothPeriod(), + GetCHVPeriod(), GetSmoothMethod() /*]*/, _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); } diff --git a/Indicators/Indi_ColorBars.mqh b/Indicators/Indi_ColorBars.mqh index 676a91767..ae5dfcd9e 100644 --- a/Indicators/Indi_ColorBars.mqh +++ b/Indicators/Indi_ColorBars.mqh @@ -123,7 +123,7 @@ class Indi_ColorBars : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -133,6 +133,9 @@ class Indi_ColorBars : public Indicator { case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), _mode, _ishift); break; + case IDATA_INDICATOR: + _value = Indi_ColorBars::iColorBarsOnIndicator(GetDataSource(), GetSymbol(), GetTf(), _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); break; diff --git a/Indicators/Indi_ColorCandlesDaily.mqh b/Indicators/Indi_ColorCandlesDaily.mqh index 1515cdc45..140320f7b 100644 --- a/Indicators/Indi_ColorCandlesDaily.mqh +++ b/Indicators/Indi_ColorCandlesDaily.mqh @@ -120,7 +120,7 @@ class Indi_ColorCandlesDaily : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -130,6 +130,10 @@ class Indi_ColorCandlesDaily : public Indicator { case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), _mode, _ishift); break; + case IDATA_INDICATOR: + _value = + Indi_ColorCandlesDaily::iCCDOnIndicator(GetDataSource(), GetSymbol(), GetTf(), _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); } diff --git a/Indicators/Indi_ColorLine.mqh b/Indicators/Indi_ColorLine.mqh index 886c70737..fcf734106 100644 --- a/Indicators/Indi_ColorLine.mqh +++ b/Indicators/Indi_ColorLine.mqh @@ -198,7 +198,7 @@ class Indi_ColorLine : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -208,6 +208,9 @@ class Indi_ColorLine : public Indicator { case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), _mode, _ishift); break; + case IDATA_INDICATOR: + _value = Indi_ColorLine::iColorLineOnIndicator(GetDataSource(), GetSymbol(), GetTf(), _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); } diff --git a/Indicators/Indi_CustomMovingAverage.mqh b/Indicators/Indi_CustomMovingAverage.mqh index 7d83ee7dc..664251971 100644 --- a/Indicators/Indi_CustomMovingAverage.mqh +++ b/Indicators/Indi_CustomMovingAverage.mqh @@ -32,7 +32,7 @@ struct IndiCustomMovingAverageParams : IndicatorParams { // Struct constructor. IndiCustomMovingAverageParams(int _smooth_period = 13, int _smooth_shift = 0, ENUM_MA_METHOD _smooth_method = MODE_SMMA, int _shift = 0) - : IndicatorParams(INDI_CUSTOM_MOVING_AVG, 3, TYPE_DOUBLE) { + : IndicatorParams(INDI_CUSTOM_MOVING_AVG, 1, TYPE_DOUBLE) { SetDataValueRange(IDATA_RANGE_MIXED); SetDataSourceType(IDATA_ICUSTOM); #ifdef __MQL5__ @@ -67,7 +67,7 @@ class Indi_CustomMovingAverage : public Indicator /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_DEMA.mqh b/Indicators/Indi_DEMA.mqh index e89f07723..4621be7c2 100644 --- a/Indicators/Indi_DEMA.mqh +++ b/Indicators/Indi_DEMA.mqh @@ -176,7 +176,7 @@ class Indi_DEMA : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); @@ -185,8 +185,8 @@ class Indi_DEMA : public Indicator { // We're getting DEMA from Price indicator. istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; - _value = Indi_DEMA::iDEMA(GetSymbol(), GetTf(), GetPeriod(), GetMAShift(), GetAppliedPrice(), _ishift, _mode, - THIS_PTR); + _value = Indi_DEMA::iDEMA(GetSymbol(), GetTf(), /*[*/ GetPeriod(), GetMAShift(), GetAppliedPrice() /*]*/, + _ishift, _mode, THIS_PTR); break; case IDATA_ICUSTOM: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; @@ -195,8 +195,8 @@ class Indi_DEMA : public Indicator { break; case IDATA_INDICATOR: // Calculating DEMA value from specified indicator. - _value = Indi_DEMA::iDEMAOnIndicator(GetDataSource(), GetSymbol(), GetTf(), GetPeriod(), GetMAShift(), - GetAppliedPrice(), _mode, _ishift, THIS_PTR); + _value = Indi_DEMA::iDEMAOnIndicator(GetDataSource(), GetSymbol(), GetTf(), /*[*/ GetPeriod(), GetMAShift(), + GetAppliedPrice() /*]*/, _mode, _ishift, THIS_PTR); break; } return _value; diff --git a/Indicators/Indi_DeMarker.mqh b/Indicators/Indi_DeMarker.mqh index 98524dcdb..cea440264 100644 --- a/Indicators/Indi_DeMarker.mqh +++ b/Indicators/Indi_DeMarker.mqh @@ -102,7 +102,7 @@ class Indi_DeMarker : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_Demo.mqh b/Indicators/Indi_Demo.mqh index a5bf323d5..cdf8fbb2e 100644 --- a/Indicators/Indi_Demo.mqh +++ b/Indicators/Indi_Demo.mqh @@ -72,7 +72,7 @@ class Indi_Demo : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); double _value = Indi_Demo::iDemo(GetSymbol(), GetTf(), _ishift, THIS_PTR); if (iparams.is_draw) { diff --git a/Indicators/Indi_DetrendedPrice.mqh b/Indicators/Indi_DetrendedPrice.mqh index ef34a7391..9c60f2207 100644 --- a/Indicators/Indi_DetrendedPrice.mqh +++ b/Indicators/Indi_DetrendedPrice.mqh @@ -126,7 +126,7 @@ class Indi_DetrendedPrice : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -138,6 +138,10 @@ class Indi_DetrendedPrice : public Indicator { _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod() /*]*/, 0, _ishift); break; + case IDATA_INDICATOR: + _value = Indi_DetrendedPrice::iDPOOnIndicator(GetDataSource(), GetSymbol(), GetTf(), /*[*/ GetPeriod(), + GetAppliedPrice() /*]*/, _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); } diff --git a/Indicators/Indi_Drawer.mqh b/Indicators/Indi_Drawer.mqh index 2fc3c2593..3130ea7c6 100644 --- a/Indicators/Indi_Drawer.mqh +++ b/Indicators/Indi_Drawer.mqh @@ -172,7 +172,7 @@ class Indi_Drawer : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_Envelopes.mqh b/Indicators/Indi_Envelopes.mqh index 4761ab8ce..bc4e5c41a 100644 --- a/Indicators/Indi_Envelopes.mqh +++ b/Indicators/Indi_Envelopes.mqh @@ -197,7 +197,7 @@ class Indi_Envelopes : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -225,7 +225,7 @@ class Indi_Envelopes : public Indicator { /** * Alters indicator's struct value. */ - virtual void GetEntryAlter(IndicatorDataEntry &_entry, int _shift = -1) { + virtual void GetEntryAlter(IndicatorDataEntry &_entry, int _shift = 0) { Indicator::GetEntryAlter(_entry); #ifdef __MQL4__ // The LINE_MAIN only exists in MQL4 for Envelopes. diff --git a/Indicators/Indi_Force.mqh b/Indicators/Indi_Force.mqh index 9e047338b..a752c8938 100644 --- a/Indicators/Indi_Force.mqh +++ b/Indicators/Indi_Force.mqh @@ -117,7 +117,7 @@ class Indi_Force : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_FractalAdaptiveMA.mqh b/Indicators/Indi_FractalAdaptiveMA.mqh index 67dc21173..63b2b1246 100644 --- a/Indicators/Indi_FractalAdaptiveMA.mqh +++ b/Indicators/Indi_FractalAdaptiveMA.mqh @@ -145,7 +145,7 @@ class Indi_FrAMA : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -157,6 +157,10 @@ class Indi_FrAMA : public Indicator { _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod(), GetFRAMAShift() /*]*/, 0, _ishift); break; + case IDATA_INDICATOR: + _value = Indi_FrAMA::iFrAMAOnIndicator(GetDataSource(), GetSymbol(), GetTf(), /*[*/ GetPeriod(), + GetFRAMAShift(), GetAppliedPrice() /*]*/, _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); } diff --git a/Indicators/Indi_Fractals.mqh b/Indicators/Indi_Fractals.mqh index 49d395311..832f5d9aa 100644 --- a/Indicators/Indi_Fractals.mqh +++ b/Indicators/Indi_Fractals.mqh @@ -102,7 +102,7 @@ class Indi_Fractals : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -122,7 +122,7 @@ class Indi_Fractals : public Indicator { /** * Alters indicator's struct value. */ - virtual void GetEntryAlter(IndicatorDataEntry &_entry, int _shift = -1) { + virtual void GetEntryAlter(IndicatorDataEntry &_entry, int _shift = 0) { Indicator::GetEntryAlter(_entry); #ifdef __MQL4__ // In MT4 line identifiers starts from 1, so populating also at 0. diff --git a/Indicators/Indi_Gator.mqh b/Indicators/Indi_Gator.mqh index 9dca4b882..e256b21b7 100644 --- a/Indicators/Indi_Gator.mqh +++ b/Indicators/Indi_Gator.mqh @@ -169,7 +169,7 @@ class Indi_Gator : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -196,7 +196,7 @@ class Indi_Gator : public Indicator { /** * Alters indicator's struct value. */ - virtual void GetEntryAlter(IndicatorDataEntry &_entry, int _shift = -1) { + virtual void GetEntryAlter(IndicatorDataEntry &_entry, int _shift = 0) { Indicator::GetEntryAlter(_entry); #ifdef __MQL4__ // @todo: Can we calculate upper and lower histogram color in MT4? diff --git a/Indicators/Indi_HeikenAshi.mqh b/Indicators/Indi_HeikenAshi.mqh index 5239c1790..52c15667e 100644 --- a/Indicators/Indi_HeikenAshi.mqh +++ b/Indicators/Indi_HeikenAshi.mqh @@ -205,7 +205,7 @@ class Indi_HeikenAshi : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = HA_OPEN, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = HA_OPEN, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -237,6 +237,10 @@ class Indi_HeikenAshi : public Indicator { _value = Indi_HeikenAshi::iCustomLegacyHeikenAshi(GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), _mode, _ishift, THIS_PTR); break; + case IDATA_INDICATOR: + _value = + Indi_HeikenAshi::iHeikenAshiOnIndicator(GetDataSource(), GetSymbol(), GetTf(), _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); } diff --git a/Indicators/Indi_Ichimoku.mqh b/Indicators/Indi_Ichimoku.mqh index 0f381d8d5..2b3378c79 100644 --- a/Indicators/Indi_Ichimoku.mqh +++ b/Indicators/Indi_Ichimoku.mqh @@ -142,7 +142,7 @@ class Indi_Ichimoku : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -164,7 +164,7 @@ class Indi_Ichimoku : public Indicator { /** * Alters indicator's struct value. */ - virtual void GetEntryAlter(IndicatorDataEntry &_entry, int _shift = -1) { + virtual void GetEntryAlter(IndicatorDataEntry &_entry, int _shift = 0) { Indicator::GetEntryAlter(_entry); #ifdef __MQL4__ // In MQL4 value of LINE_TENKANSEN is 1 (not 0 as in MQL5), diff --git a/Indicators/Indi_Killzones.mqh b/Indicators/Indi_Killzones.mqh index 70016b6db..89913eeb5 100644 --- a/Indicators/Indi_Killzones.mqh +++ b/Indicators/Indi_Killzones.mqh @@ -106,7 +106,7 @@ class Indi_Killzones : public Indicator { /** * Returns the indicator's value. */ - IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { float _value = FLT_MAX; int _index = (int)_mode / 2; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); diff --git a/Indicators/Indi_MA.mqh b/Indicators/Indi_MA.mqh index d8ec96e68..3cdd2083d 100644 --- a/Indicators/Indi_MA.mqh +++ b/Indicators/Indi_MA.mqh @@ -627,7 +627,7 @@ class Indi_MA : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_MACD.mqh b/Indicators/Indi_MACD.mqh index 64570f79b..6724dfc2a 100644 --- a/Indicators/Indi_MACD.mqh +++ b/Indicators/Indi_MACD.mqh @@ -114,7 +114,7 @@ class Indi_MACD : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = LINE_MAIN, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = LINE_MAIN, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_MFI.mqh b/Indicators/Indi_MFI.mqh index 902d6d08b..4a9327585 100644 --- a/Indicators/Indi_MFI.mqh +++ b/Indicators/Indi_MFI.mqh @@ -111,7 +111,7 @@ class Indi_MFI : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_MassIndex.mqh b/Indicators/Indi_MassIndex.mqh index 1e0076f55..3b4821127 100644 --- a/Indicators/Indi_MassIndex.mqh +++ b/Indicators/Indi_MassIndex.mqh @@ -166,7 +166,7 @@ class Indi_MassIndex : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -178,6 +178,10 @@ class Indi_MassIndex : public Indicator { _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod(), GetSecondPeriod(), GetSumPeriod() /*]*/, _mode, _ishift); break; + case IDATA_INDICATOR: + _value = Indi_MassIndex::iMIOnIndicator(GetDataSource(), GetSymbol(), GetTf(), /*[*/ GetPeriod(), + GetSecondPeriod(), GetSumPeriod() /*]*/, _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); break; diff --git a/Indicators/Indi_Momentum.mqh b/Indicators/Indi_Momentum.mqh index 5f4266dd0..0d461e47c 100644 --- a/Indicators/Indi_Momentum.mqh +++ b/Indicators/Indi_Momentum.mqh @@ -141,7 +141,7 @@ class Indi_Momentum : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_OBV.mqh b/Indicators/Indi_OBV.mqh index cefa485e9..b904b3e52 100644 --- a/Indicators/Indi_OBV.mqh +++ b/Indicators/Indi_OBV.mqh @@ -118,7 +118,7 @@ class Indi_OBV : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_OsMA.mqh b/Indicators/Indi_OsMA.mqh index ac0a608a7..a6930aab8 100644 --- a/Indicators/Indi_OsMA.mqh +++ b/Indicators/Indi_OsMA.mqh @@ -111,7 +111,7 @@ class Indi_OsMA : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); double _value = EMPTY_VALUE; switch (iparams.idstype) { diff --git a/Indicators/Indi_Pivot.mqh b/Indicators/Indi_Pivot.mqh index fd4c7cf4d..6ef493d08 100644 --- a/Indicators/Indi_Pivot.mqh +++ b/Indicators/Indi_Pivot.mqh @@ -62,7 +62,7 @@ class Indi_Pivot : public Indicator { * @return * Returns IndicatorDataEntry struct filled with indicator values. */ - virtual IndicatorDataEntry GetEntry(int _shift = -1) { + virtual IndicatorDataEntry GetEntry(int _shift = 0) { int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); long _bar_time = GetBarTime(_ishift); IndicatorDataEntry _entry = idata.GetByKey(_bar_time); @@ -100,7 +100,7 @@ class Indi_Pivot : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); return GetEntry(_ishift)[_mode]; } diff --git a/Indicators/Indi_PriceChannel.mqh b/Indicators/Indi_PriceChannel.mqh index 415082498..afcc17ed5 100644 --- a/Indicators/Indi_PriceChannel.mqh +++ b/Indicators/Indi_PriceChannel.mqh @@ -116,7 +116,7 @@ class Indi_PriceChannel : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -127,6 +127,10 @@ class Indi_PriceChannel : public Indicator { _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod() /*]*/, 0, _ishift); break; + case IDATA_INDICATOR: + _value = Indi_PriceChannel::iPriceChannelOnIndicator(GetDataSource(), GetSymbol(), GetTf(), + /*[*/ GetPeriod() /*]*/, _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); } diff --git a/Indicators/Indi_PriceFeeder.mqh b/Indicators/Indi_PriceFeeder.mqh index c1d286d88..459c8e8df 100644 --- a/Indicators/Indi_PriceFeeder.mqh +++ b/Indicators/Indi_PriceFeeder.mqh @@ -75,7 +75,7 @@ class Indi_PriceFeeder : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { int data_size = ArraySize(iparams.price_data); int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); diff --git a/Indicators/Indi_PriceVolumeTrend.mqh b/Indicators/Indi_PriceVolumeTrend.mqh index ecf0ae493..35b40cdc9 100644 --- a/Indicators/Indi_PriceVolumeTrend.mqh +++ b/Indicators/Indi_PriceVolumeTrend.mqh @@ -131,7 +131,7 @@ class Indi_PriceVolumeTrend : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -143,6 +143,10 @@ class Indi_PriceVolumeTrend : public Indicator { _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetAppliedVolume() /*]*/, 0, _ishift); break; + case IDATA_INDICATOR: + _value = Indi_PriceVolumeTrend::iPVTOnIndicator(GetDataSource(), GetSymbol(), GetTf(), + /*[*/ GetAppliedVolume() /*]*/, _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); } diff --git a/Indicators/Indi_RS.mqh b/Indicators/Indi_RS.mqh index 51c03ed8d..29df1fecb 100644 --- a/Indicators/Indi_RS.mqh +++ b/Indicators/Indi_RS.mqh @@ -78,7 +78,7 @@ class Indi_RS : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_MATH: diff --git a/Indicators/Indi_RSI.mqh b/Indicators/Indi_RSI.mqh index 41b7339a9..41af38bbe 100644 --- a/Indicators/Indi_RSI.mqh +++ b/Indicators/Indi_RSI.mqh @@ -289,7 +289,7 @@ class Indi_RSI : public Indicator { * Note that in MQL5 Applied Price must be passed as the last parameter * (before mode and shift). */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; double _res[]; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); diff --git a/Indicators/Indi_RVI.mqh b/Indicators/Indi_RVI.mqh index 18402acad..e7c7d8b39 100644 --- a/Indicators/Indi_RVI.mqh +++ b/Indicators/Indi_RVI.mqh @@ -103,7 +103,7 @@ class Indi_RVI : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = LINE_MAIN, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = LINE_MAIN, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_RateOfChange.mqh b/Indicators/Indi_RateOfChange.mqh index fd597bbe0..e6508ddab 100644 --- a/Indicators/Indi_RateOfChange.mqh +++ b/Indicators/Indi_RateOfChange.mqh @@ -120,7 +120,7 @@ class Indi_RateOfChange : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -132,6 +132,10 @@ class Indi_RateOfChange : public Indicator { _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod() /*]*/, 0, _ishift); break; + case IDATA_INDICATOR: + _value = Indi_RateOfChange::iROCOnIndicator(GetDataSource(), GetSymbol(), GetTf(), /*[*/ GetPeriod(), + GetAppliedPrice() /*]*/, _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); } diff --git a/Indicators/Indi_SAR.mqh b/Indicators/Indi_SAR.mqh index 2381c9cf3..bb7acb110 100644 --- a/Indicators/Indi_SAR.mqh +++ b/Indicators/Indi_SAR.mqh @@ -102,7 +102,7 @@ class Indi_SAR : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_StdDev.mqh b/Indicators/Indi_StdDev.mqh index 4ef932b03..4dc2327eb 100644 --- a/Indicators/Indi_StdDev.mqh +++ b/Indicators/Indi_StdDev.mqh @@ -226,7 +226,7 @@ class Indi_StdDev : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_Stochastic.mqh b/Indicators/Indi_Stochastic.mqh index d60246205..95384d8ae 100644 --- a/Indicators/Indi_Stochastic.mqh +++ b/Indicators/Indi_Stochastic.mqh @@ -119,7 +119,7 @@ class Indi_Stochastic : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = LINE_MAIN, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = LINE_MAIN, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_TEMA.mqh b/Indicators/Indi_TEMA.mqh index 626ad9186..5ac6bbb6c 100644 --- a/Indicators/Indi_TEMA.mqh +++ b/Indicators/Indi_TEMA.mqh @@ -97,9 +97,9 @@ class Indi_TEMA : public Indicator { /** * On-indicator version of TEMA. */ - static double iAMAOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _ma_period, - int _ma_shift, ENUM_APPLIED_PRICE _ap, int _mode = 0, int _shift = 0, - IndicatorBase *_obj = NULL) { + static double iTEMAOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _ma_period, + int _ma_shift, ENUM_APPLIED_PRICE _ap, int _mode = 0, int _shift = 0, + IndicatorBase *_obj = NULL) { INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_SHORT_DS( _indi, _symbol, _tf, _ap, Util::MakeKey("Indi_TEMA_ON_" + _indi.GetFullName(), _ma_period, _ma_shift, (int)_ap)); @@ -138,7 +138,7 @@ class Indi_TEMA : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -150,6 +150,10 @@ class Indi_TEMA : public Indicator { _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod(), GetTEMAShift() /*]*/, 0, _ishift); break; + case IDATA_INDICATOR: + _value = Indi_TEMA::iTEMAOnIndicator(GetDataSource(), GetSymbol(), GetTf(), /*[*/ GetPeriod(), GetTEMAShift(), + GetAppliedPrice() /*]*/, _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); break; diff --git a/Indicators/Indi_TRIX.mqh b/Indicators/Indi_TRIX.mqh index da77f4e33..e480701b7 100644 --- a/Indicators/Indi_TRIX.mqh +++ b/Indicators/Indi_TRIX.mqh @@ -137,7 +137,7 @@ class Indi_TRIX : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -149,6 +149,10 @@ class Indi_TRIX : public Indicator { _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod() /*]*/, 0, _ishift); break; + case IDATA_INDICATOR: + _value = Indi_TRIX::iTriXOnIndicator(GetDataSource(), GetSymbol(), GetTf(), /*[*/ GetPeriod(), + GetAppliedPrice() /*]*/, _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); } diff --git a/Indicators/Indi_UltimateOscillator.mqh b/Indicators/Indi_UltimateOscillator.mqh index ee6782641..ff63857d4 100644 --- a/Indicators/Indi_UltimateOscillator.mqh +++ b/Indicators/Indi_UltimateOscillator.mqh @@ -29,6 +29,9 @@ // Structs. struct IndiUltimateOscillatorParams : IndicatorParams { + Ref indi_atr_fast; + Ref indi_atr_middle; + Ref indi_atr_slow; int fast_period; int middle_period; int slow_period; @@ -125,14 +128,29 @@ class Indi_UltimateOscillator : public Indicator { _fast_k, _middle_k, _slow_k)); // @fixit This won't work! Find a way to differentiate ATRs. - Indi_ATR *_indi_atr_fast = (Indi_ATR *)_indi.GetDataSource(INDI_ATR); - Indi_ATR *_indi_atr_middle = (Indi_ATR *)_indi.GetDataSource(INDI_ATR); - Indi_ATR *_indi_atr_slow = (Indi_ATR *)_indi.GetDataSource(INDI_ATR); + Indi_ATR *_indi_atr_fast = (Indi_ATR *)_indi.GetDataSource(INDI_ULTIMATE_OSCILLATOR_ATR_FAST); + Indi_ATR *_indi_atr_middle = (Indi_ATR *)_indi.GetDataSource(INDI_ULTIMATE_OSCILLATOR_ATR_MIDDLE); + Indi_ATR *_indi_atr_slow = (Indi_ATR *)_indi.GetDataSource(INDI_ULTIMATE_OSCILLATOR_ATR_SLOW); return iUOOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _fast_period, _middle_period, _slow_period, _fast_k, _middle_k, _slow_k, _mode, _shift, _cache, _indi_atr_fast, _indi_atr_middle, _indi_atr_slow); } + /** + * Provides built-in indicators whose can be used as data source. + */ + IndicatorBase *FetchDataSource(ENUM_INDICATOR_TYPE _id) override { + switch (_id) { + case INDI_ULTIMATE_OSCILLATOR_ATR_FAST: + return iparams.indi_atr_fast.Ptr(); + case INDI_ULTIMATE_OSCILLATOR_ATR_MIDDLE: + return iparams.indi_atr_middle.Ptr(); + case INDI_ULTIMATE_OSCILLATOR_ATR_SLOW: + return iparams.indi_atr_slow.Ptr(); + } + return NULL; + } + /** * OnCalculate() method for Ultimate Oscillator. */ @@ -229,7 +247,7 @@ class Indi_UltimateOscillator : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -245,6 +263,11 @@ class Indi_UltimateOscillator : public Indicator { /*]*/, 0, _ishift); break; + case IDATA_INDICATOR: + _value = Indi_UltimateOscillator::iUOOnIndicator(GetDataSource(), GetSymbol(), GetTf(), /*[*/ GetFastPeriod(), + GetMiddlePeriod(), GetSlowPeriod(), GetFastK(), GetMiddleK(), + GetSlowK() /*]*/, _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); } diff --git a/Indicators/Indi_VIDYA.mqh b/Indicators/Indi_VIDYA.mqh index 15f959e15..8499e9b32 100644 --- a/Indicators/Indi_VIDYA.mqh +++ b/Indicators/Indi_VIDYA.mqh @@ -160,7 +160,7 @@ class Indi_VIDYA : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -175,6 +175,11 @@ class Indi_VIDYA : public Indicator { /*]*/, 0, _ishift); break; + case IDATA_INDICATOR: + _value = + Indi_VIDYA::iVIDyAOnIndicator(GetDataSource(), GetSymbol(), GetTf(), /*[*/ GetCMOPeriod(), GetMAPeriod(), + GetVIDYAShift(), GetAppliedPrice() /*]*/, _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); } diff --git a/Indicators/Indi_VROC.mqh b/Indicators/Indi_VROC.mqh index dfad54d06..439e009fe 100644 --- a/Indicators/Indi_VROC.mqh +++ b/Indicators/Indi_VROC.mqh @@ -140,7 +140,7 @@ class Indi_VROC : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -152,6 +152,10 @@ class Indi_VROC : public Indicator { _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod(), GetAppliedVolume() /*]*/, _mode, _ishift); break; + case IDATA_INDICATOR: + _value = Indi_VROC::iVROCOnIndicator(GetDataSource(), GetSymbol(), GetTf(), /*[*/ GetPeriod(), + GetAppliedVolume() /*]*/, _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); } diff --git a/Indicators/Indi_Volumes.mqh b/Indicators/Indi_Volumes.mqh index 4fb2a2888..1f5333b93 100644 --- a/Indicators/Indi_Volumes.mqh +++ b/Indicators/Indi_Volumes.mqh @@ -134,7 +134,7 @@ class Indi_Volumes : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -145,6 +145,10 @@ class Indi_Volumes : public Indicator { _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetAppliedVolume() /*]*/, _mode, _ishift); break; + case IDATA_INDICATOR: + _value = Indi_Volumes::iVolumesOnIndicator(GetDataSource(), GetSymbol(), GetTf(), + /*[*/ GetAppliedVolume() /*]*/, _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); } diff --git a/Indicators/Indi_WPR.mqh b/Indicators/Indi_WPR.mqh index 8dcc258aa..1504f2ecf 100644 --- a/Indicators/Indi_WPR.mqh +++ b/Indicators/Indi_WPR.mqh @@ -101,7 +101,7 @@ class Indi_WPR : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Indi_WilliamsAD.mqh b/Indicators/Indi_WilliamsAD.mqh index 36b56685b..cf1a6513f 100644 --- a/Indicators/Indi_WilliamsAD.mqh +++ b/Indicators/Indi_WilliamsAD.mqh @@ -134,7 +134,7 @@ class Indi_WilliamsAD : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { @@ -144,6 +144,9 @@ class Indi_WilliamsAD : public Indicator { case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), 0, _ishift); break; + case IDATA_INDICATOR: + _value = Indi_WilliamsAD::iWADOnIndicator(GetDataSource(), GetSymbol(), GetTf(), _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); } diff --git a/Indicators/Indi_ZigZag.mqh b/Indicators/Indi_ZigZag.mqh index e79ca128c..912eb8eff 100644 --- a/Indicators/Indi_ZigZag.mqh +++ b/Indicators/Indi_ZigZag.mqh @@ -346,18 +346,23 @@ class Indi_ZigZag : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: - _value = Indi_ZigZag::iZigZag(GetSymbol(), GetTf(), GetDepth(), GetDeviation(), GetBackstep(), + _value = Indi_ZigZag::iZigZag(GetSymbol(), GetTf(), /*[*/ GetDepth(), GetDeviation(), GetBackstep() /*]*/, (ENUM_ZIGZAG_LINE)_mode, _ishift, THIS_PTR); break; case IDATA_ICUSTOM: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; - _value = Indi_ZigZag::iCustomZigZag(GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), GetDepth(), - GetDeviation(), GetBackstep(), (ENUM_ZIGZAG_LINE)_mode, _ishift, THIS_PTR); + _value = + Indi_ZigZag::iCustomZigZag(GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetDepth(), + GetDeviation(), GetBackstep() /*]*/, (ENUM_ZIGZAG_LINE)_mode, _ishift, THIS_PTR); + break; + case IDATA_INDICATOR: + _value = Indi_ZigZag::iZigZagOnIndicator(GetDataSource(), GetSymbol(), GetTf(), /*[*/ GetDepth(), + GetDeviation(), GetBackstep() /*]*/, _mode, _ishift, THIS_PTR); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_ZigZagColor.mqh b/Indicators/Indi_ZigZagColor.mqh index f30004ebb..af74e2f50 100644 --- a/Indicators/Indi_ZigZagColor.mqh +++ b/Indicators/Indi_ZigZagColor.mqh @@ -281,18 +281,23 @@ class Indi_ZigZagColor : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { case IDATA_BUILTIN: - _value = Indi_ZigZagColor::iZigZagColor(GetSymbol(), GetTf(), GetDepth(), GetDeviation(), GetBackstep(), - (ENUM_ZIGZAG_LINE)_mode, _ishift, THIS_PTR); + _value = Indi_ZigZagColor::iZigZagColor(GetSymbol(), GetTf(), /*[*/ GetDepth(), GetDeviation(), + GetBackstep() /*]*/, (ENUM_ZIGZAG_LINE)_mode, _ishift, THIS_PTR); break; case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetDepth(), GetDeviation(), GetBackstep() /*]*/, _mode, _ishift); break; + case IDATA_INDICATOR: + _value = + Indi_ZigZagColor::iZigZagColorOnIndicator(GetDataSource(), GetSymbol(), GetTf(), /*[*/ GetDepth(), + GetDeviation(), GetBackstep() /*]*/, _mode, _ishift, THIS_PTR); + break; default: SetUserError(ERR_INVALID_PARAMETER); break; diff --git a/Indicators/OHLC/Indi_OHLC.mqh b/Indicators/OHLC/Indi_OHLC.mqh index 7d7d26d93..c6c3d39ef 100644 --- a/Indicators/OHLC/Indi_OHLC.mqh +++ b/Indicators/OHLC/Indi_OHLC.mqh @@ -60,7 +60,7 @@ class Indi_OHLC : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); ENUM_APPLIED_PRICE _ap = PRICE_OPEN; switch (_mode) { diff --git a/Indicators/Price/Indi_Price.mqh b/Indicators/Price/Indi_Price.mqh index 74cd43db8..89b0f7279 100644 --- a/Indicators/Price/Indi_Price.mqh +++ b/Indicators/Price/Indi_Price.mqh @@ -62,7 +62,7 @@ class Indi_Price : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); return ChartStatic::iPrice(iparams.GetAppliedPrice(), GetSymbol(), GetTf(), _ishift); } diff --git a/Indicators/Special/Indi_Math.mqh b/Indicators/Special/Indi_Math.mqh index 033377c04..e1c991916 100644 --- a/Indicators/Special/Indi_Math.mqh +++ b/Indicators/Special/Indi_Math.mqh @@ -93,7 +93,7 @@ class Indi_Math : public Indicator { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); switch (iparams.idstype) { diff --git a/Indicators/Tick/Indi_TickMt.mqh b/Indicators/Tick/Indi_TickMt.mqh index db392ce69..c32f45482 100644 --- a/Indicators/Tick/Indi_TickMt.mqh +++ b/Indicators/Tick/Indi_TickMt.mqh @@ -86,7 +86,7 @@ class Indi_TickMt : public IndicatorTick { * This method allows user to modify the struct entry before it's added to cache. * This method is called on GetEntry() right after values are set. */ - virtual void GetEntryAlter(IndicatorDataEntry &_entry, int _shift = -1) { + virtual void GetEntryAlter(IndicatorDataEntry &_entry, int _shift = 0) { IndicatorTick::GetEntryAlter(_entry, _shift); _entry.timestamp = _entry.timestamp > 0 ? _entry.timestamp : tick.time; }; diff --git a/tests/IndicatorsTest.mq5 b/tests/IndicatorsTest.mq5 index 60a416e0c..87b63f56b 100644 --- a/tests/IndicatorsTest.mq5 +++ b/tests/IndicatorsTest.mq5 @@ -83,6 +83,11 @@ int OnInit() { void OnTick() { chart.OnTick(); + // All indicators should execute its OnTick() method for every platform tick. + for (DictStructIterator> iter = indis.Begin(); iter.IsValid(); ++iter) { + iter.Value().Ptr().OnTick(); + } + if (chart.IsNewBar()) { bar_processed++; if (indis.Size() == 0) { From f4c946d6c07bc7bf324a7a8690eac23019fa57e0 Mon Sep 17 00:00:00 2001 From: Adrian Kierzkowski Date: Sat, 11 Dec 2021 01:24:36 +0100 Subject: [PATCH 35/77] WIP. AMA now requires refactor back to be parent of Indicator or something similar. --- Indicator/IndicatorCandle.h | 11 ++++++++ Indicator/tests/classes/IndicatorTickReal.h | 7 +++++ IndicatorBase.h | 29 ++++++++++++++++++++- Indicators/Indi_AMA.mqh | 3 ++- tests/IndicatorsTest.mq5 | 11 ++++++-- 5 files changed, 57 insertions(+), 4 deletions(-) diff --git a/Indicator/IndicatorCandle.h b/Indicator/IndicatorCandle.h index 6a36c4312..19b2478a1 100644 --- a/Indicator/IndicatorCandle.h +++ b/Indicator/IndicatorCandle.h @@ -92,9 +92,13 @@ class IndicatorCandle : public IndicatorBase { CandleOCTOHLC _candle = icdata.GetByKey(_candle_time); if (!_candle.IsValid()) { +#ifdef __debug__ Print(GetFullName(), ": Missing candle at shift ", _index, " (", TimeToString(_candle_time), ")"); +#endif } else { +#ifdef __debug__verbose_ Print(GetFullName(), ": Retrieving candle at shift ", _index, " (", TimeToString(_candle_time), ")"); +#endif } return CandleToEntry(_candle_time, _candle); @@ -169,8 +173,10 @@ class IndicatorCandle : public IndicatorBase { void UpdateCandle(long _tick_timestamp, double _price) { long _candle_timestamp = CalcCandleTimestamp(_tick_timestamp); +#ifdef __debug_verbose__ Print("Updating candle for ", GetFullName(), " at candle ", TimeToString(_candle_timestamp), " from tick at ", TimeToString(_tick_timestamp)); +#endif CandleOCTOHLC _candle(_price, _price, _price, _price, _tick_timestamp, _tick_timestamp); if (icdata.KeyExists(_candle_timestamp)) { @@ -307,6 +313,11 @@ class IndicatorCandle : public IndicatorBase { return _result; } + + /** + * Get indicator type. + */ + ENUM_INDICATOR_TYPE GetType() override { return icparams.itype; } }; #endif diff --git a/Indicator/tests/classes/IndicatorTickReal.h b/Indicator/tests/classes/IndicatorTickReal.h index a8884c3a6..a654c4da8 100644 --- a/Indicator/tests/classes/IndicatorTickReal.h +++ b/Indicator/tests/classes/IndicatorTickReal.h @@ -50,13 +50,17 @@ class IndicatorTickReal : public IndicatorTick void OnBecomeDataSourceFor(IndicatorBase* _base_indi) override { // Feeding base indicator with historic entries of this indicator. +#ifdef __debug__ Print(GetFullName(), " became a data source for ", _base_indi.GetFullName()); +#endif #ifndef __MQL4__ int _ticks_to_emit = 1000; +#ifdef __debug_verbose__ Print(_base_indi.GetFullName(), " will be now filled with ", _ticks_to_emit, " historical entries generated by " + GetFullName()); +#endif static MqlTick _ticks[]; ArrayResize(_ticks, 0); @@ -97,7 +101,10 @@ class IndicatorTickReal : public IndicatorTick // Copying only the last tick. int _num_copied = CopyTicks(GetSymbol(), _ticks, COPY_TICKS_INFO, 0, 1); +#ifdef __debug_verbose__ Print("TickReal: ", TimeToString(_ticks[0].time), " = ", _ticks[0].bid); +#endif + double _ask = _ticks[0].ask; double _bid = _ticks[0].bid; long _time = _ticks[0].time; diff --git a/IndicatorBase.h b/IndicatorBase.h index 5d74af976..54b681fdf 100644 --- a/IndicatorBase.h +++ b/IndicatorBase.h @@ -71,6 +71,7 @@ class IndicatorBase : public Chart { int indi_src_mode; // Mode of source indicator IndicatorCalculateCache cache; ARRAY(WeakRef, listeners); // List of indicators that listens for events from this one. + long last_tick_time; // Time of the last Tick() call. public: /* Indicator enumerations */ @@ -94,6 +95,7 @@ class IndicatorBase : public Chart { calc_start_bar = 0; is_fed = false; indi_src = NULL; + last_tick_time = 0; } /** @@ -103,6 +105,7 @@ class IndicatorBase : public Chart { calc_start_bar = 0; is_fed = false; indi_src = NULL; + last_tick_time = 0; } /** @@ -351,7 +354,7 @@ class IndicatorBase : public Chart { /** * Get name of the indicator. */ - virtual string GetName() { return ""; } + virtual string GetName() { return EnumToString(GetType()); } /** * Get full name of the indicator (with "over ..." part). @@ -498,6 +501,30 @@ class IndicatorBase : public Chart { return _result; } + void Tick() { + long _current_time = TimeCurrent(); + + if (last_tick_time == _current_time) { + // We've already ticked. + return; + } + + last_tick_time = _current_time; + + // Overridable OnTick() method. + OnTick(); + + if (HasDataSource()) { + // Ticking data source if not yet ticked.s + GetDataSource().Tick(); + } + + // Also ticking all used indicators if they've not yet ticked. + for (DictStructIterator> iter = indicators.Begin(); iter.IsValid(); ++iter) { + iter.Value().Ptr().Tick(); + } + } + virtual void OnTick() {} /* Data representation methods */ diff --git a/Indicators/Indi_AMA.mqh b/Indicators/Indi_AMA.mqh index 4342dad6c..ea4481f09 100644 --- a/Indicators/Indi_AMA.mqh +++ b/Indicators/Indi_AMA.mqh @@ -56,7 +56,8 @@ struct IndiAMAParams : IndicatorTfParams { IndiAMAParams(IndiAMAParams &_params, ENUM_TIMEFRAMES _tf) { THIS_REF = _params; tf = _tf; - }; + } + 5; }; /** diff --git a/tests/IndicatorsTest.mq5 b/tests/IndicatorsTest.mq5 index 87b63f56b..cdb3b16cc 100644 --- a/tests/IndicatorsTest.mq5 +++ b/tests/IndicatorsTest.mq5 @@ -78,14 +78,14 @@ int OnInit() { } /** - * Implements Tick event handler. + * Implements Tick event handler . */ void OnTick() { chart.OnTick(); // All indicators should execute its OnTick() method for every platform tick. for (DictStructIterator> iter = indis.Begin(); iter.IsValid(); ++iter) { - iter.Value().Ptr().OnTick(); + iter.Value().Ptr().Tick(); } if (chart.IsNewBar()) { @@ -109,6 +109,13 @@ void OnTick() { IndicatorBase* _indi = iter.Value().Ptr(); _indi.OnTick(); IndicatorDataEntry _entry(_indi.GetEntry()); + + if (_indi.GetType() == INDI_AMA) { + PrintFormat("%s: bar %d: %s", _indi.GetFullName(), bar_processed, _indi.ToString()); + } else { + continue; + } + if (_indi.Get(STRUCT_ENUM(IndicatorState, INDICATOR_STATE_PROP_IS_READY))) { if (_entry.IsValid()) { PrintFormat("%s: bar %d: %s", _indi.GetFullName(), bar_processed, _indi.ToString()); From 761facece28196e4263db29e2c030312a25bd0a4 Mon Sep 17 00:00:00 2001 From: Adrian Kierzkowski Date: Wed, 15 Dec 2021 18:19:43 +0100 Subject: [PATCH 36/77] WIP. Introduces IndicatorCandleSource and IndicatorTickSource indicator class bases. Also reverted back to using Indicator as parent for IndicatorCandle (and later for IndicatorTick). --- Indicator.mqh | 143 +++++++-------- Indicator/IndicatorCandle.h | 199 +++++++-------------- Indicator/IndicatorCandleSource.h | 99 ++++++++++ Indicator/IndicatorTf.h | 6 +- Indicator/IndicatorTickSource.h | 83 +++++++++ Indicator/tests/classes/IndicatorTfDummy.h | 5 +- IndicatorBase.h | 18 +- Indicators/Indi_AMA.mqh | 58 +++--- tests/IndicatorsTest.mq5 | 5 +- 9 files changed, 360 insertions(+), 256 deletions(-) create mode 100644 Indicator/IndicatorCandleSource.h create mode 100644 Indicator/IndicatorTickSource.h diff --git a/Indicator.mqh b/Indicator.mqh index 665ca3060..cfcc683f6 100644 --- a/Indicator.mqh +++ b/Indicator.mqh @@ -720,6 +720,15 @@ class Indicator : public IndicatorBase { _result = _source.Ptr(); } } + } else { + // Requesting potential data source. + IndicatorBase* _ds = OnDataSourceRequest(); + + if (_ds != NULL) { + // Initializing with new data source. + SetDataSource(_ds); + iparams.SetDataSourceType(IDATA_INDICATOR); + } } ValidateDataSource(&this, _result); @@ -735,7 +744,17 @@ class Indicator : public IndicatorBase { /** * Whether data source is selected. */ - virtual bool HasDataSource() { return GetDataSourceRaw() != NULL || iparams.GetDataSourceId() != -1; } + virtual bool HasDataSource(bool _try_initialize = false) { + if (iparams.GetDataSourceId() != -1) { + return true; + } + + if (GetDataSourceRaw() == NULL && _try_initialize) { + SetDataSource(OnDataSourceRequest()); + } + + return GetDataSourceRaw() != NULL; + } /** * Gets indicator's params. @@ -775,14 +794,6 @@ class Indicator : public IndicatorBase { */ string GetName() { return iparams.name; } - /** - * Get full name of the indicator (with "over ..." part). - */ - string GetFullName() { - return iparams.name + "[" + IntegerToString(iparams.GetMaxModes()) + "]" + - (HasDataSource() ? (" (over " + GetDataSource().GetFullName() + ")") : ""); - } - /** * Get more descriptive name of the indicator. */ @@ -816,19 +827,6 @@ class Indicator : public IndicatorBase { Chart::Set(_param, _value); } - /** - * Sets indicator data source. - */ - void SetDataSource(IndicatorBase* _indi, int _input_mode = 0) { - if (indi_src.IsSet() && indi_src.Ptr() != _indi) { - indi_src.Ptr().RemoveListener(THIS_PTR); - } - indi_src = _indi; - indi_src.Ptr().AddListener(THIS_PTR); - iparams.SetDataSource(-1, _input_mode); - indi_src.Ptr().OnBecomeDataSourceFor(THIS_PTR); - } - /** * Sets name of the indicator. */ @@ -966,63 +964,7 @@ class Indicator : public IndicatorBase { return true; } - /** - * Returns shift at which the last known valid entry exists for a given - * period (or from the start, when period is not specified). - */ - /* - bool GetLastValidEntryShift(int& out_shift, int period = 0) { - out_shift = 0; - - while (true) { - if ((period != 0 && out_shift >= period) || !HasValidEntry(out_shift + 1)) - return out_shift > 0; // Current shift is always invalid. - - ++out_shift; - } - - return out_shift > 0; - }*/ - - /** - * Returns shift at which the oldest known valid entry exists for a given - * period (or from the start, when period is not specified). - */ - /* - bool GetOldestValidEntryShift(int& out_shift, int& out_num_valid, int shift = 0, int period = 0) { - bool found = false; - // Counting from previous up to previous - period. - for (out_shift = shift + 1; out_shift < shift + period + 1; ++out_shift) { - if (!HasValidEntry(out_shift)) { - --out_shift; - out_num_valid = out_shift - shift; - return found; - } else - found = true; - } - - --out_shift; - out_num_valid = out_shift - shift; - return found; - } - */ - - /** - * Checks whether indicator has valid at least given number of last entries - * (counting from given shift or 0). - */ - /* - bool HasAtLeastValidLastEntries(int period, int shift = 0) { - for (int i = 0; i < period; ++i) - if (!HasValidEntry(shift + i)) return false; - - return true; - } - */ - - // ENUM_IDATA_VALUE_RANGE GetIDataValueRange() { return iparams.idvrange; } - - virtual void OnTick() { + void OnTick() override { Chart::OnTick(); if (iparams.is_draw) { @@ -1033,6 +975,21 @@ class Indicator : public IndicatorBase { } } + /** + * Sets indicator data source. + */ + void SetDataSource(IndicatorBase* _indi, int _input_mode = 0) override { + if (indi_src.IsSet() && indi_src.Ptr() != _indi) { + indi_src.Ptr().RemoveListener(THIS_PTR); + } + indi_src = _indi; + if (_indi != NULL) { + indi_src.Ptr().AddListener(THIS_PTR); + iparams.SetDataSource(-1, _input_mode); + indi_src.Ptr().OnBecomeDataSourceFor(THIS_PTR); + } + } + /* Data representation methods */ /* Virtual methods */ @@ -1087,6 +1044,19 @@ class Indicator : public IndicatorBase { return _result; } + /** + * Get full name of the indicator (with "over ..." part). + */ + string GetFullName() override { + return GetName() + "[" + IntegerToString(iparams.GetMaxModes()) + "]" + + (HasDataSource() ? (" (over " + GetDataSource().GetFullName() + ")") : ""); + } + + /** + * Get indicator type. + */ + ENUM_INDICATOR_TYPE GetType() override { return iparams.itype; } + /** * Update indicator. */ @@ -1163,9 +1133,22 @@ class Indicator : public IndicatorBase { * This method allows user to modify the struct entry before it's added to cache. * This method is called on GetEntry() right after values are set. */ - virtual void GetEntryAlter(IndicatorDataEntry& _entry, int _index = -1) { + virtual void GetEntryAlter(IndicatorDataEntry& _entry, int _timestamp = -1) { _entry.AddFlags(_entry.GetDataTypeFlags(iparams.GetDataValueType())); }; + + /** + * Returns the indicator's entry value for the given shift and mode. + * + * @see: DataParamEntry. + * + * @return + * Returns DataParamEntry struct filled with a single value. + */ + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); + return GetEntry(_ishift)[_mode]; + } }; #endif diff --git a/Indicator/IndicatorCandle.h b/Indicator/IndicatorCandle.h index 19b2478a1..e1b0ecf52 100644 --- a/Indicator/IndicatorCandle.h +++ b/Indicator/IndicatorCandle.h @@ -31,16 +31,26 @@ // Includes. #include "../Buffer/BufferCandle.h" -#include "../IndicatorBase.h" +#include "../Indicator.mqh" + +enum ENUM_INDI_CANDLE_MODE { + INDI_CANDLE_MODE_PRICE_OPEN, + INDI_CANDLE_MODE_PRICE_HIGH, + INDI_CANDLE_MODE_PRICE_LOW, + INDI_CANDLE_MODE_PRICE_CLOSE, + INDI_CANDLE_MODE_SPREAD, + INDI_CANDLE_MODE_TICK_VOLUME, + INDI_CANDLE_MODE_VOLUME, + FINAL_INDI_CANDLE_MODE_ENTRY, +}; /** * Class to deal with candle indicators. */ template -class IndicatorCandle : public IndicatorBase { +class IndicatorCandle : public Indicator { protected: BufferCandle icdata; - TS icparams; protected: /* Protected methods */ @@ -53,7 +63,7 @@ class IndicatorCandle : public IndicatorBase { void Init() { icdata.AddFlags(DICT_FLAG_FILL_HOLES_UNSORTED); icdata.SetOverflowListener(IndicatorCandleOverflowListener, 10); - icparams.SetMaxModes(4); + iparams.SetMaxModes(4); } public: @@ -62,16 +72,13 @@ class IndicatorCandle : public IndicatorBase { /** * Class constructor. */ - IndicatorCandle(const TS& _icparams, IndicatorBase* _indi_src = NULL, int _indi_mode = 0) { - icparams = _icparams; - if (_indi_src != NULL) { - SetDataSource(_indi_src, _indi_mode); - } + IndicatorCandle(const TS& _icparams, IndicatorBase* _indi_src = NULL, int _indi_mode = 0) + : Indicator(_icparams, _indi_src, _indi_mode) { Init(); } - IndicatorCandle(ENUM_INDICATOR_TYPE _itype = INDI_CANDLE, int _shift = 0, string _name = "") { - icparams.SetIndicatorType(_itype); - icparams.SetShift(_shift); + IndicatorCandle(ENUM_INDICATOR_TYPE _itype = INDI_CANDLE, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0, + string _name = "") + : Indicator(_itype, _tf, _shift, _name) { Init(); } @@ -87,7 +94,7 @@ class IndicatorCandle : public IndicatorBase { */ IndicatorDataEntry GetEntry(int _index) override { ResetLastError(); - unsigned int _ishift = _index >= 0 ? _index : icparams.GetShift(); + unsigned int _ishift = _index >= 0 ? _index : iparams.GetShift(); long _candle_time = CalcCandleTimestamp(GetBarTime(_ishift)); CandleOCTOHLC _candle = icdata.GetByKey(_candle_time); @@ -104,29 +111,6 @@ class IndicatorCandle : public IndicatorBase { return CandleToEntry(_candle_time, _candle); } - /** - * Alters indicator's struct value. - * - * This method allows user to modify the struct entry before it's added to cache. - * This method is called on GetEntry() right after values are set. - */ - virtual void GetEntryAlter(IndicatorDataEntry& _entry, int _timestamp = -1) { - _entry.AddFlags(_entry.GetDataTypeFlags(icparams.GetDataValueType())); - }; - - /** - * Returns the indicator's entry value for the given shift and mode. - * - * @see: DataParamEntry. - * - * @return - * Returns DataParamEntry struct filled with a single value. - */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { - int _ishift = _shift >= 0 ? _shift : icparams.GetShift(); - return GetEntry(_ishift)[_mode]; - } - /** * Function should return true if resize can be made, or false to overwrite current slot. */ @@ -192,29 +176,58 @@ class IndicatorCandle : public IndicatorBase { * Calculates candle's timestamp from tick's timestamp. */ long CalcCandleTimestamp(long _tick_timestamp) { - return _tick_timestamp - _tick_timestamp % (icparams.GetSecsPerCandle()); + return _tick_timestamp - _tick_timestamp % (iparams.GetSecsPerCandle()); } /** * Called when data source emits new entry (historic or future one). */ - virtual void OnDataSourceEntry(IndicatorDataEntry& entry) { + void OnDataSourceEntry(IndicatorDataEntry& entry) override { // Updating candle from bid price. UpdateCandle(entry.timestamp, entry[1]); }; /** - * Sets indicator data source. - */ - void SetDataSource(IndicatorBase* _indi, int _input_mode = 0) { - if (indi_src.IsSet() && indi_src.Ptr() != _indi) { - indi_src.Ptr().RemoveListener(THIS_PTR); + * Returns value storage of given kind. + */ + IValueStorage* GetSpecificValueStorage(ENUM_INDI_VS_TYPE _type) override { + switch (_type) { + case INDI_VS_TYPE_PRICE_OPEN: + return GetValueStorage(INDI_CANDLE_MODE_PRICE_OPEN); + case INDI_VS_TYPE_PRICE_HIGH: + return GetValueStorage(INDI_CANDLE_MODE_PRICE_HIGH); + case INDI_VS_TYPE_PRICE_LOW: + return GetValueStorage(INDI_CANDLE_MODE_PRICE_LOW); + case INDI_VS_TYPE_PRICE_CLOSE: + return GetValueStorage(INDI_CANDLE_MODE_PRICE_CLOSE); + case INDI_VS_TYPE_SPREAD: + return GetValueStorage(INDI_CANDLE_MODE_SPREAD); + case INDI_VS_TYPE_TICK_VOLUME: + return GetValueStorage(INDI_CANDLE_MODE_TICK_VOLUME); + case INDI_VS_TYPE_VOLUME: + return GetValueStorage(INDI_CANDLE_MODE_VOLUME); + default: + // Trying in parent class. + return Indicator::GetSpecificValueStorage(_type); } - indi_src = _indi; - if (_indi != NULL) { - indi_src.Ptr().AddListener(THIS_PTR); - icparams.SetDataSource(-1, _input_mode); - indi_src.Ptr().OnBecomeDataSourceFor(THIS_PTR); + } + + /** + * Checks whether indicator support given value storage type. + */ + virtual bool HasSpecificValueStorage(ENUM_INDI_VS_TYPE _type) { + switch (_type) { + case INDI_VS_TYPE_PRICE_OPEN: + case INDI_VS_TYPE_PRICE_HIGH: + case INDI_VS_TYPE_PRICE_LOW: + case INDI_VS_TYPE_PRICE_CLOSE: + case INDI_VS_TYPE_SPREAD: + case INDI_VS_TYPE_TICK_VOLUME: + case INDI_VS_TYPE_VOLUME: + return true; + default: + // Trying in parent class. + return Indicator::HasSpecificValueStorage(_type); } } @@ -228,96 +241,6 @@ class IndicatorCandle : public IndicatorBase { } /* Virtual methods */ - - /** - * Checks if indicator entry is valid. - * - * @return - * Returns true if entry is valid (has valid values), otherwise false. - */ - virtual bool IsValidEntry(IndicatorDataEntry& _entry) { - bool _result = true; - _result &= _entry.timestamp > 0; - _result &= _entry.GetSize() > 0; - if (_entry.CheckFlags(INDI_ENTRY_FLAG_IS_REAL)) { - if (_entry.CheckFlags(INDI_ENTRY_FLAG_IS_DOUBLED)) { - _result &= !_entry.HasValue(DBL_MAX); - _result &= !_entry.HasValue(NULL); - } else { - _result &= !_entry.HasValue(FLT_MAX); - _result &= !_entry.HasValue(NULL); - } - } else { - if (_entry.CheckFlags(INDI_ENTRY_FLAG_IS_UNSIGNED)) { - if (_entry.CheckFlags(INDI_ENTRY_FLAG_IS_DOUBLED)) { - _result &= !_entry.HasValue(ULONG_MAX); - _result &= !_entry.HasValue(NULL); - } else { - _result &= !_entry.HasValue(UINT_MAX); - _result &= !_entry.HasValue(NULL); - } - } else { - if (_entry.CheckFlags(INDI_ENTRY_FLAG_IS_DOUBLED)) { - _result &= !_entry.HasValue(LONG_MAX); - _result &= !_entry.HasValue(NULL); - } else { - _result &= !_entry.HasValue(INT_MAX); - _result &= !_entry.HasValue(NULL); - } - } - } - return _result; - } - - /** - * Get full name of the indicator (with "over ..." part). - */ - string GetFullName() override { - return GetName() + "[" + IntegerToString(icparams.GetMaxModes()) + "]" + - (HasDataSource() ? (" (over " + GetDataSource().GetFullName() + ")") : ""); - } - - /** - * Whether data source is selected. - */ - bool HasDataSource() override { return GetDataSourceRaw() != NULL || icparams.GetDataSourceId() != -1; } - - /** - * Returns currently selected data source doing validation. - */ - IndicatorBase* GetDataSource() override { - IndicatorBase* _result = NULL; - - if (GetDataSourceRaw() != NULL) { - _result = GetDataSourceRaw(); - } else if (icparams.GetDataSourceId() != -1) { - int _source_id = icparams.GetDataSourceId(); - - if (indicators.KeyExists(_source_id)) { - _result = indicators[_source_id].Ptr(); - } else { - Ref _source = FetchDataSource((ENUM_INDICATOR_TYPE)_source_id); - - if (!_source.IsSet()) { - Alert(GetName(), " has no built-in source indicator ", _source_id); - DebugBreak(); - } else { - indicators.Set(_source_id, _source); - - _result = _source.Ptr(); - } - } - } - - ValidateDataSource(&this, _result); - - return _result; - } - - /** - * Get indicator type. - */ - ENUM_INDICATOR_TYPE GetType() override { return icparams.itype; } }; #endif diff --git a/Indicator/IndicatorCandleSource.h b/Indicator/IndicatorCandleSource.h new file mode 100644 index 000000000..47abebcd9 --- /dev/null +++ b/Indicator/IndicatorCandleSource.h @@ -0,0 +1,99 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2021, EA31337 Ltd | +//| https://github.com/EA31337 | +//+------------------------------------------------------------------+ + +/* + * This file is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#ifndef __MQL__ +// Allows the preprocessor to include a header file when it is needed. +#pragma once +#endif + +// Includes. +#include "../Indicator.mqh" +#include "tests/classes/IndicatorTfDummy.h" +#include "tests/classes/IndicatorTickReal.h" + +/** + * Indicator to be used with IndicatorCandle as a data source. + */ +template +class IndicatorCandleSource : public Indicator { + public: + /** + * Class constructor. + */ + IndicatorCandleSource(const TS& _iparams, IndicatorBase* _indi_src = NULL, int _indi_mode = 0) + : Indicator(_iparams, _indi_src, _indi_mode) {} + IndicatorCandleSource(const TS& _iparams, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) : Indicator(_iparams, _tf) {} + IndicatorCandleSource(ENUM_INDICATOR_TYPE _itype, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0, + string _name = "") + : Indicator(_itype, _tf, _shift, _name) {} + + /** + * Class deconstructor. + */ + ~IndicatorCandleSource() {} + + /** + * Sets indicator data source. + */ + void SetDataSource(IndicatorBase* _indi, int _input_mode = 0) override { + if (_indi == NULL) { + // Just deselecting data source. + Indicator::SetDataSource(_indi, _input_mode); + return; + } + + // We can only use data sources which supports all possible modes from IndicatorCandle. + bool _result = true; + + _result &= _indi.HasSpecificValueStorage(INDI_VS_TYPE_PRICE_OPEN); + _result &= _indi.HasSpecificValueStorage(INDI_VS_TYPE_PRICE_HIGH); + _result &= _indi.HasSpecificValueStorage(INDI_VS_TYPE_PRICE_LOW); + _result &= _indi.HasSpecificValueStorage(INDI_VS_TYPE_PRICE_CLOSE); + _result &= _indi.HasSpecificValueStorage(INDI_VS_TYPE_SPREAD); + _result &= _indi.HasSpecificValueStorage(INDI_VS_TYPE_TICK_VOLUME); + _result &= _indi.HasSpecificValueStorage(INDI_VS_TYPE_VOLUME); + + if (!_result) { + Alert("Passed indicator ", _indi.GetFullName(), " does not define all required specific data storages!"); + DebugBreak(); + } + + Indicator::SetDataSource(_indi, _input_mode); + } + + /** + * Called if data source is requested, but wasn't yet set. May be used to initialize indicators that must operate on + * some data source. + */ + IndicatorBase* OnDataSourceRequest() override { + // Defaulting to real platform ticks. + IndicatorBase* _indi_tick = + new IndicatorTickReal(GetSymbol(), GetTf(), "Ticker for Tf on IndicatorCandleSource-based indicator"); + + // Tf will work on real platform ticks. + IndicatorBase* _indi_tf = new IndicatorTfDummy(GetTf()); + _indi_tf.SetDataSource(_indi_tick); + + // Indicator will work on Tf, which will receive real platform ticks. + return _indi_tf; + } +}; diff --git a/Indicator/IndicatorTf.h b/Indicator/IndicatorTf.h index 21350c445..84fe4b7c0 100644 --- a/Indicator/IndicatorTf.h +++ b/Indicator/IndicatorTf.h @@ -56,7 +56,7 @@ class IndicatorTf : public IndicatorCandle { * Class constructor with timeframe enum. */ IndicatorTf(uint _spc) { - icparams.SetSecsPerCandle(_spc); + iparams.SetSecsPerCandle(_spc); Init(); } @@ -64,7 +64,7 @@ class IndicatorTf : public IndicatorCandle { * Class constructor with timeframe enum. */ IndicatorTf(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) { - icparams.SetSecsPerCandle(ChartTf::TfToSeconds(_tf)); + iparams.SetSecsPerCandle(ChartTf::TfToSeconds(_tf)); Init(); } @@ -72,7 +72,7 @@ class IndicatorTf : public IndicatorCandle { * Class constructor with timeframe index. */ IndicatorTf(ENUM_TIMEFRAMES_INDEX _tfi = 0) { - icparams.SetSecsPerCandle(ChartTf::TfToSeconds(ChartTf::IndexToTf(_tfi))); + iparams.SetSecsPerCandle(ChartTf::TfToSeconds(ChartTf::IndexToTf(_tfi))); Init(); } diff --git a/Indicator/IndicatorTickSource.h b/Indicator/IndicatorTickSource.h new file mode 100644 index 000000000..1b6273b8f --- /dev/null +++ b/Indicator/IndicatorTickSource.h @@ -0,0 +1,83 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2021, EA31337 Ltd | +//| https://github.com/EA31337 | +//+------------------------------------------------------------------+ + +/* + * This file is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#ifndef __MQL__ +// Allows the preprocessor to include a header file when it is needed. +#pragma once +#endif + +// Includes. +#include "../Indicator.mqh" + +/** + * Indicator to be used with IndicatorTick as a data source. + */ +template +class IndicatorTickSource : public Indicator { + public: + /** + * Class constructor. + */ + IndicatorTickSource(const TS& _iparams, IndicatorBase* _indi_src = NULL, int _indi_mode = 0) + : Indicator(_iparams, _indi_src, _indi_mode) {} + IndicatorTickSource(const TS& _iparams, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) : Indicator(_iparams, _tf) {} + IndicatorTickSource(ENUM_INDICATOR_TYPE _itype, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0, + string _name = "") + : Indicator(_itype, _tf, _shift, _name) {} + + /** + * Class deconstructor. + */ + ~IndicatorCandleSource() {} + + /** + * Sets indicator data source. + */ + void SetDataSource(IndicatorBase* _indi, int _input_mode = 0) override { + if (_indi == NULL) { + // Just deselecting data source. + Indicator::SetDataSource(_indi, _input_mode); + return; + } + + // We can only use data sources which supports all possible modes from IndicatorTick. + bool _result = true; + + _result &= _indi.HasSpecificValueStorage(INDI_VS_TYPE_PRICE_APPLIED); + + if (!_result) { + Alert("Passed indicator ", _indi.GetFullName(), " does not define all required specific data storages!"); + DebugBreak(); + } + + Indicator::SetDataSource(_indi, _input_mode); + } + + /** + * Called if data source is requested, but wasn't yet set. May be used to initialize indicators that must operate on + * some data source. + */ + IndicatorBase* OnDataSourceRequest() override { + // Defaulting to platform ticks. + return new IndicatorTickReal(GetSymbol(), GetTf(), "AMA on IndicatorTickReal"); + } +}; diff --git a/Indicator/tests/classes/IndicatorTfDummy.h b/Indicator/tests/classes/IndicatorTfDummy.h index 7bd57829e..8414f4786 100644 --- a/Indicator/tests/classes/IndicatorTfDummy.h +++ b/Indicator/tests/classes/IndicatorTfDummy.h @@ -29,6 +29,9 @@ #pragma once #endif +// Includes. +#include "../../IndicatorTf.h" + // Params for dummy candle-based indicator. struct IndicatorTfDummyParams : IndicatorTfParams { IndicatorTfDummyParams(uint _spc = 60) : IndicatorTfParams(_spc) {} @@ -43,7 +46,7 @@ class IndicatorTfDummy : public IndicatorTf { IndicatorTfDummy(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) : IndicatorTf(_tf) {} IndicatorTfDummy(ENUM_TIMEFRAMES_INDEX _tfi = 0) : IndicatorTf(_tfi) {} - string GetName() override { return "IndicatorTfDummy(" + IntegerToString(icparams.spc) + ")"; } + string GetName() override { return "IndicatorTfDummy(" + IntegerToString(iparams.spc) + ")"; } void OnDataSourceEntry(IndicatorDataEntry& entry) override { // When overriding OnDataSourceEntry() we have to remember to call parent diff --git a/IndicatorBase.h b/IndicatorBase.h index 54b681fdf..5a7d200b7 100644 --- a/IndicatorBase.h +++ b/IndicatorBase.h @@ -299,6 +299,12 @@ class IndicatorBase : public Chart { return _result; } + /** + * Called if data source is requested, but wasn't yet set. May be used to initialize indicators that must operate on + * some data source. + */ + virtual IndicatorBase* OnDataSourceRequest() { return NULL; } + /* Getters */ /** @@ -332,7 +338,7 @@ class IndicatorBase : public Chart { /** * Whether data source is selected. */ - virtual bool HasDataSource() { return false; } + virtual bool HasDataSource(bool _try_initialize = false) { return false; } /** * Returns currently selected data source doing validation. @@ -456,6 +462,11 @@ class IndicatorBase : public Chart { return NULL; } + /** + * Checks whether indicator support given value storage type. + */ + virtual bool HasSpecificValueStorage(ENUM_INDI_VS_TYPE _type) { return false; } + template T GetValue(int _index = 0, int _mode = 0) { T _out; @@ -514,8 +525,9 @@ class IndicatorBase : public Chart { // Overridable OnTick() method. OnTick(); - if (HasDataSource()) { - // Ticking data source if not yet ticked.s + // Checking and potentially initializing new data source. + if (HasDataSource(true) != NULL) { + // Ticking data source if not yet ticked. GetDataSource().Tick(); } diff --git a/Indicators/Indi_AMA.mqh b/Indicators/Indi_AMA.mqh index ea4481f09..abf35439b 100644 --- a/Indicators/Indi_AMA.mqh +++ b/Indicators/Indi_AMA.mqh @@ -22,14 +22,13 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator/IndicatorTf.h" -#include "../Indicator/tests/classes/IndicatorTickReal.h" +#include "../Indicator/IndicatorCandleSource.h" #include "../Storage/ValueStorage.h" #include "../Storage/ValueStorage.price.h" #include "Price/Indi_Price.mqh" // Structs. -struct IndiAMAParams : IndicatorTfParams { +struct IndiAMAParams : IndicatorParams { unsigned int period; unsigned int fast_period; unsigned int slow_period; @@ -44,6 +43,8 @@ struct IndiAMAParams : IndicatorTfParams { ama_shift(_ama_shift), applied_price(_ap) { SetDataValueRange(IDATA_RANGE_PRICE); + // Defaulting to on-indicator mode (will use real ticks from platform via IndicatorTickReal). + SetDataSourceMode(IDATA_INDICATOR); SetShift(_shift); switch (idstype) { case IDATA_ICUSTOM: @@ -57,32 +58,26 @@ struct IndiAMAParams : IndicatorTfParams { THIS_REF = _params; tf = _tf; } - 5; }; /** * Implements the AMA indicator. */ -class Indi_AMA : public IndicatorTf { +class Indi_AMA : public IndicatorCandleSource { public: /** * Class constructor. */ - Indi_AMA(IndiAMAParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTf(_p) { - icparams.SetIndicatorType(INDI_AMA); + Indi_AMA(IndiAMAParams &_p, IndicatorBase *_indi_src = NULL, int _indi_mode = 0) + : IndicatorCandleSource(_p, _indi_src, _indi_mode) { + iparams.SetIndicatorType(INDI_AMA); if (_indi_src != NULL) { - SetDataSource(_indi_src); - icparams.SetDataSourceType(IDATA_INDICATOR); + iparams.SetDataSourceType(IDATA_INDICATOR); } else { - // Defaulting to platform ticks. - SetDataSource(new IndicatorTickReal(GetSymbol(), GetTf(), "AMA on IndicatorTickReal")); - icparams.SetDataSourceType(IDATA_INDICATOR); } }; - Indi_AMA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTf(_tf) { - icparams.SetIndicatorType(INDI_AMA); - icparams.SetShift(_shift); - }; + Indi_AMA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorCandleSource(INDI_AMA, _tf, _shift){}; /** * Built-in version of AMA. @@ -229,14 +224,14 @@ class Indi_AMA : public IndicatorTf { */ virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; - int _ishift = _shift >= 0 ? _shift : icparams.GetShift(); - switch (icparams.idstype) { + int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); + switch (iparams.idstype) { case IDATA_BUILTIN: _value = Indi_AMA::iAMA(GetSymbol(), GetTf(), /*[*/ GetPeriod(), GetFastPeriod(), GetSlowPeriod(), GetAMAShift(), GetAppliedPrice() /*]*/, _mode, _ishift, THIS_PTR); break; case IDATA_ICUSTOM: - _value = iCustom(istate.handle, GetSymbol(), GetTf(), icparams.GetCustomIndicatorName(), /*[*/ GetPeriod(), + _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetPeriod(), GetFastPeriod(), GetSlowPeriod(), GetAMAShift() /*]*/, _mode, _ishift); break; @@ -251,32 +246,37 @@ class Indi_AMA : public IndicatorTf { return _value; } + /** + * Called when data source emits new entry (historic or future one). + */ + void OnDataSourceEntry(IndicatorDataEntry &entry) override { Print("New entry for AMA!"); }; + /* Getters */ /** * Get AMA shift. */ - unsigned int GetAMAShift() { return icparams.ama_shift; } + unsigned int GetAMAShift() { return iparams.ama_shift; } /** * Get period. */ - unsigned int GetPeriod() { return icparams.period; } + unsigned int GetPeriod() { return iparams.period; } /** * Get fast period. */ - unsigned int GetFastPeriod() { return icparams.fast_period; } + unsigned int GetFastPeriod() { return iparams.fast_period; } /** * Get slow period. */ - unsigned int GetSlowPeriod() { return icparams.slow_period; } + unsigned int GetSlowPeriod() { return iparams.slow_period; } /** * Get applied price. */ - ENUM_APPLIED_PRICE GetAppliedPrice() { return icparams.applied_price; } + ENUM_APPLIED_PRICE GetAppliedPrice() { return iparams.applied_price; } /* Setters */ @@ -285,7 +285,7 @@ class Indi_AMA : public IndicatorTf { */ void SetAMAShift(unsigned int _ama_shift) { istate.is_changed = true; - icparams.ama_shift = _ama_shift; + iparams.ama_shift = _ama_shift; } /** @@ -293,7 +293,7 @@ class Indi_AMA : public IndicatorTf { */ void SetPeriod(unsigned int _period) { istate.is_changed = true; - icparams.period = _period; + iparams.period = _period; } /** @@ -301,7 +301,7 @@ class Indi_AMA : public IndicatorTf { */ void SetFastPeriod(unsigned int _fast_period) { istate.is_changed = true; - icparams.fast_period = _fast_period; + iparams.fast_period = _fast_period; } /** @@ -309,7 +309,7 @@ class Indi_AMA : public IndicatorTf { */ void SetSlowPeriod(unsigned int _slow_period) { istate.is_changed = true; - icparams.slow_period = _slow_period; + iparams.slow_period = _slow_period; } /** @@ -317,6 +317,6 @@ class Indi_AMA : public IndicatorTf { */ void SetAppliedPrice(ENUM_APPLIED_PRICE _applied_price) { istate.is_changed = true; - icparams.applied_price = _applied_price; + iparams.applied_price = _applied_price; } }; diff --git a/tests/IndicatorsTest.mq5 b/tests/IndicatorsTest.mq5 index cdb3b16cc..3909a09d4 100644 --- a/tests/IndicatorsTest.mq5 +++ b/tests/IndicatorsTest.mq5 @@ -25,7 +25,8 @@ */ // Defines. -//#define __debug__ // Enables debug. +// #define __debug__ // Enables debug. +// #define __debug_verbose__ // Forward declaration. struct DataParamEntry; @@ -78,7 +79,7 @@ int OnInit() { } /** - * Implements Tick event handler . + * Implements Tick event handler. */ void OnTick() { chart.OnTick(); From fea144ae121d97480715f71bc8ee33a308d91642 Mon Sep 17 00:00:00 2001 From: Adrian Kierzkowski Date: Thu, 16 Dec 2021 18:22:18 +0100 Subject: [PATCH 37/77] WIP. Almost working AMA indicator (still varies to much with original one). BWMFI somehow return 0 in first calculation buffer. --- Indicator.enum.h | 2 +- Indicator.mqh | 16 +++++++++------- Indicator/tests/classes/IndicatorTfDummy.h | 2 ++ IndicatorBase.h | 22 ++++++++++++++++++++++ Indicators/Indi_AMA.mqh | 8 ++------ Indicators/Indi_FractalAdaptiveMA.mqh | 2 +- Storage/ValueStorage.h | 4 ++++ tests/IndicatorsTest.mq5 | 11 +++++++++-- 8 files changed, 50 insertions(+), 17 deletions(-) diff --git a/Indicator.enum.h b/Indicator.enum.h index c98f42ce1..658423502 100644 --- a/Indicator.enum.h +++ b/Indicator.enum.h @@ -242,4 +242,4 @@ enum ENUM_INDI_VS_TYPE { INDI_VS_TYPE_PRICE_HIGH, INDI_VS_TYPE_PRICE_LOW, INDI_VS_TYPE_PRICE_CLOSE -}; \ No newline at end of file +}; diff --git a/Indicator.mqh b/Indicator.mqh index cfcc683f6..24750d256 100644 --- a/Indicator.mqh +++ b/Indicator.mqh @@ -147,22 +147,20 @@ class Indicator : public IndicatorBase { Indicator(const TS& _iparams, IndicatorBase* _indi_src = NULL, int _indi_mode = 0) : IndicatorBase(_iparams.GetTf(), NULL) { iparams = _iparams; - SetName(_iparams.name != "" ? _iparams.name : EnumToString(iparams.itype)); if (_indi_src != NULL) { SetDataSource(_indi_src, _indi_mode); + iparams.SetDataSourceType(IDATA_INDICATOR); } Init(); } Indicator(const TS& _iparams, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) : IndicatorBase(_tf) { iparams = _iparams; - SetName(_iparams.name != "" ? _iparams.name : EnumToString(iparams.itype)); Init(); } Indicator(ENUM_INDICATOR_TYPE _itype, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0, string _name = "") : IndicatorBase(_tf) { iparams.SetIndicatorType(_itype); iparams.SetShift(_shift); - SetName(_name != "" ? _name : EnumToString(iparams.itype)); Init(); } @@ -183,7 +181,7 @@ class Indicator : public IndicatorBase { /* Buffer methods */ - virtual string CacheKey() { return GetName(); } + virtual string CacheKey() { return GetFullName(); } /** * Initializes a cached proxy between i*OnArray() methods and OnCalculate() @@ -720,7 +718,9 @@ class Indicator : public IndicatorBase { _result = _source.Ptr(); } } - } else { + } else if (iparams.GetDataSourceType() == IDATA_INDICATOR) { + // User sets data source's mode to On-Indicator, but not set data source via SetDataSource()! + // Requesting potential data source. IndicatorBase* _ds = OnDataSourceRequest(); @@ -749,7 +749,7 @@ class Indicator : public IndicatorBase { return true; } - if (GetDataSourceRaw() == NULL && _try_initialize) { + if (iparams.GetDataSourceType() == IDATA_INDICATOR && GetDataSourceRaw() == NULL && _try_initialize) { SetDataSource(OnDataSourceRequest()); } @@ -792,7 +792,9 @@ class Indicator : public IndicatorBase { /** * Get name of the indicator. */ - string GetName() { return iparams.name; } + string GetName() override { + return "(" + EnumToString(GetType()) + ")" + (iparams.name != "" ? (" " + iparams.name) : ""); + } /** * Get more descriptive name of the indicator. diff --git a/Indicator/tests/classes/IndicatorTfDummy.h b/Indicator/tests/classes/IndicatorTfDummy.h index 8414f4786..6680f07e0 100644 --- a/Indicator/tests/classes/IndicatorTfDummy.h +++ b/Indicator/tests/classes/IndicatorTfDummy.h @@ -54,7 +54,9 @@ class IndicatorTfDummy : public IndicatorTf { // create/update matching candle. IndicatorTf::OnDataSourceEntry(entry); +#ifdef __debug_indicator__ Print(GetFullName(), " got new tick at ", entry.timestamp, " (" + TimeToString(entry.timestamp) + "): ", entry.ToString()); +#endif } }; diff --git a/IndicatorBase.h b/IndicatorBase.h index 5a7d200b7..898d51f78 100644 --- a/IndicatorBase.h +++ b/IndicatorBase.h @@ -462,6 +462,28 @@ class IndicatorBase : public Chart { return NULL; } + virtual IValueStorage* GetSpecificAppliedPriceValueStorage(ENUM_APPLIED_PRICE _ap) { + switch (_ap) { + case PRICE_OPEN: + return GetSpecificValueStorage(INDI_VS_TYPE_PRICE_OPEN); + case PRICE_HIGH: + return GetSpecificValueStorage(INDI_VS_TYPE_PRICE_HIGH); + case PRICE_LOW: + return GetSpecificValueStorage(INDI_VS_TYPE_PRICE_LOW); + case PRICE_CLOSE: + return GetSpecificValueStorage(INDI_VS_TYPE_PRICE_CLOSE); + case PRICE_MEDIAN: + case PRICE_TYPICAL: + case PRICE_WEIGHTED: + default: + Print("Error: Invalid applied price " + EnumToString(_ap) + + ", only PRICE_(OPEN|HIGH|LOW|CLOSE) are currently supported by " + "IndicatorBase::GetSpecificAppliedPriceValueStorage()!"); + DebugBreak(); + return NULL; + } + } + /** * Checks whether indicator support given value storage type. */ diff --git a/Indicators/Indi_AMA.mqh b/Indicators/Indi_AMA.mqh index abf35439b..3238fcd07 100644 --- a/Indicators/Indi_AMA.mqh +++ b/Indicators/Indi_AMA.mqh @@ -36,7 +36,7 @@ struct IndiAMAParams : IndicatorParams { ENUM_APPLIED_PRICE applied_price; // Struct constructor. IndiAMAParams(int _period = 10, int _fast_period = 2, int _slow_period = 30, int _ama_shift = 0, - ENUM_APPLIED_PRICE _ap = PRICE_TYPICAL, int _shift = 0) + ENUM_APPLIED_PRICE _ap = PRICE_OPEN, int _shift = 0) : period(_period), fast_period(_fast_period), slow_period(_slow_period), @@ -71,10 +71,6 @@ class Indi_AMA : public IndicatorCandleSource { Indi_AMA(IndiAMAParams &_p, IndicatorBase *_indi_src = NULL, int _indi_mode = 0) : IndicatorCandleSource(_p, _indi_src, _indi_mode) { iparams.SetIndicatorType(INDI_AMA); - if (_indi_src != NULL) { - iparams.SetDataSourceType(IDATA_INDICATOR); - } else { - } }; Indi_AMA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorCandleSource(INDI_AMA, _tf, _shift){}; @@ -125,7 +121,7 @@ class Indi_AMA : public IndicatorCandleSource { static double iAMAOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _ama_period, int _fast_ema_period, int _slow_ema_period, int _ama_shift, ENUM_APPLIED_PRICE _ap, int _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) { - INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_SHORT_DS( + INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_SHORT_DS_SPECIFIC( _indi, _symbol, _tf, _ap, Util::MakeKey("Indi_AMA_ON_" + _indi.GetFullName(), _ama_period, _fast_ema_period, _slow_ema_period, _ama_shift, (int)_ap)); diff --git a/Indicators/Indi_FractalAdaptiveMA.mqh b/Indicators/Indi_FractalAdaptiveMA.mqh index 63b2b1246..a9d1810ac 100644 --- a/Indicators/Indi_FractalAdaptiveMA.mqh +++ b/Indicators/Indi_FractalAdaptiveMA.mqh @@ -69,7 +69,7 @@ class Indi_FrAMA : public Indicator { #else INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG(_symbol, _tf, Util::MakeKey("Indi_FrAMA", _ma_period, _ma_shift, (int)_ap)); - return iFrAMAOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _ma_period, _ma_shift, _mode, _shift, _ap, _cache); + return iFrAMAOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _ma_period, _ma_shift, _ap, _mode, _shift, _cache); #endif } diff --git a/Storage/ValueStorage.h b/Storage/ValueStorage.h index 0348eb0c5..ea2730712 100644 --- a/Storage/ValueStorage.h +++ b/Storage/ValueStorage.h @@ -91,6 +91,10 @@ enum ENUM_IPEAK { IPEAK_LOWEST, IPEAK_HIGHEST }; ValueStorage *_price = INDI.GetValueStorage(APPLIED_PRICE); \ INDICATOR_CALCULATE_POPULATE_CACHE(SYMBOL, TF, KEY) +#define INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_SHORT_DS_SPECIFIC(INDI, SYMBOL, TF, APPLIED_PRICE, KEY) \ + ValueStorage *_price = INDI.GetSpecificAppliedPriceValueStorage(APPLIED_PRICE); \ + INDICATOR_CALCULATE_POPULATE_CACHE(SYMBOL, TF, KEY) + #define INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS(INDI, SYMBOL, TF, KEY) \ ValueStorage *_time = (ValueStorage *)INDI.GetSpecificValueStorage(INDI_VS_TYPE_TIME); \ ValueStorage *_tick_volume = (ValueStorage *)INDI.GetSpecificValueStorage(INDI_VS_TYPE_TICK_VOLUME); \ diff --git a/tests/IndicatorsTest.mq5 b/tests/IndicatorsTest.mq5 index 3909a09d4..918c3e734 100644 --- a/tests/IndicatorsTest.mq5 +++ b/tests/IndicatorsTest.mq5 @@ -112,9 +112,9 @@ void OnTick() { IndicatorDataEntry _entry(_indi.GetEntry()); if (_indi.GetType() == INDI_AMA) { - PrintFormat("%s: bar %d: %s", _indi.GetFullName(), bar_processed, _indi.ToString()); + // PrintFormat("%s: bar %d: %s", _indi.GetFullName(), bar_processed, _indi.ToString()); } else { - continue; + // continue; } if (_indi.Get(STRUCT_ENUM(IndicatorState, INDICATOR_STATE_PROP_IS_READY))) { @@ -422,8 +422,15 @@ bool InitIndicators() { // AMA. IndiAMAParams ama_params(); + ama_params.SetDataSourceType(IDATA_INDICATOR); indis.Push(new Indi_AMA(ama_params)); + // Original AMA. + IndiAMAParams ama_params_orig(); + ama_params_orig.SetName("Original AMA to compare"); + ama_params_orig.SetDataSourceType(IDATA_BUILTIN); + indis.Push(new Indi_AMA(ama_params_orig)); + // Chaikin Oscillator. IndiCHOParams cho_params(); indis.Push(new Indi_CHO(cho_params)); From 0e1452722ec9da881f57f9b72ce19bd55c6b458e Mon Sep 17 00:00:00 2001 From: Adrian Kierzkowski Date: Wed, 22 Dec 2021 19:45:18 +0100 Subject: [PATCH 38/77] WIP. Partially working Tick/Candle/TickOrCandle indicators differentiation and automatic value (price) storage fetching after SetDataSource(). --- DrawIndicator.mqh | 1 - Indicator.enum.h | 35 ++++++------ Indicator.mqh | 2 +- Indicator.struct.h | 4 +- Indicator/IndicatorCandle.h | 2 +- Indicator/IndicatorCandleSource.h | 11 +++- Indicator/IndicatorTick.h | 2 +- Indicator/IndicatorTickOrCandleSource.h | 72 +++++++++++++++++++++++++ Indicator/IndicatorTickSource.h | 53 ++++++++++++++++-- IndicatorBase.h | 11 +++- Indicators/Bitwise/Indi_Candle.mqh | 9 ++-- Indicators/Bitwise/Indi_Pattern.mqh | 9 ++-- Indicators/Indi_AC.mqh | 8 +-- Indicators/Indi_AD.mqh | 8 +-- Indicators/Indi_ADX.mqh | 8 +-- Indicators/Indi_ADXW.mqh | 9 ++-- Indicators/Indi_AMA.mqh | 9 ++-- Indicators/Indi_AO.mqh | 8 +-- Indicators/Indi_ASI.mqh | 8 +-- Indicators/Indi_ATR.mqh | 8 +-- Indicators/Indi_Alligator.mqh | 9 ++-- Indicators/Indi_AppliedPrice.mqh | 9 ++-- Indicators/Indi_BWMFI.mqh | 16 +++--- Indicators/Indi_BWZT.mqh | 7 +-- Indicators/Indi_Bands.mqh | 8 +-- Indicators/Indi_BearsPower.mqh | 9 ++-- Indicators/Indi_BullsPower.mqh | 9 ++-- Indicators/Indi_CCI.mqh | 8 +-- Indicators/Indi_CHO.mqh | 9 ++-- Indicators/Indi_CHV.mqh | 9 ++-- Indicators/Indi_ColorBars.mqh | 9 ++-- Indicators/Indi_ColorCandlesDaily.mqh | 8 +-- Indicators/Indi_ColorLine.mqh | 9 ++-- Indicators/Indi_CustomMovingAverage.mqh | 8 +-- Indicators/Indi_DEMA.mqh | 9 ++-- Indicators/Indi_DeMarker.mqh | 10 ++-- Indicators/Indi_Demo.mqh | 9 ++-- Indicators/Indi_DetrendedPrice.mqh | 8 +-- Indicators/Indi_Drawer.mqh | 9 ++-- Indicators/Indi_Envelopes.mqh | 9 ++-- Indicators/Indi_Force.mqh | 9 ++-- Indicators/Indi_FractalAdaptiveMA.mqh | 10 ++-- Indicators/Indi_Fractals.mqh | 10 ++-- Indicators/Indi_Gator.mqh | 9 ++-- Indicators/Indi_HeikenAshi.mqh | 9 ++-- Indicators/Indi_Ichimoku.mqh | 10 ++-- Indicators/Indi_Killzones.mqh | 9 ++-- Indicators/Indi_MA.mqh | 37 +++++++++++-- Indicators/Indi_MACD.mqh | 9 ++-- Indicators/Indi_MFI.mqh | 8 +-- Indicators/Indi_MassIndex.mqh | 9 ++-- Indicators/Indi_Momentum.mqh | 10 ++-- Indicators/Indi_OBV.mqh | 8 +-- Indicators/Indi_OsMA.mqh | 9 ++-- Indicators/Indi_Pivot.mqh | 7 +-- Indicators/Indi_PriceChannel.mqh | 8 +-- Indicators/Indi_PriceFeeder.mqh | 11 ++-- Indicators/Indi_PriceVolumeTrend.mqh | 8 +-- Indicators/Indi_RS.mqh | 10 ++-- Indicators/Indi_RSI.mqh | 8 +-- Indicators/Indi_RVI.mqh | 8 +-- Indicators/Indi_RateOfChange.mqh | 8 +-- Indicators/Indi_SAR.mqh | 8 +-- Indicators/Indi_StdDev.mqh | 8 +-- Indicators/Indi_Stochastic.mqh | 9 ++-- Indicators/Indi_TEMA.mqh | 9 ++-- Indicators/Indi_TRIX.mqh | 9 ++-- Indicators/Indi_UltimateOscillator.mqh | 8 +-- Indicators/Indi_VIDYA.mqh | 9 ++-- Indicators/Indi_VROC.mqh | 9 ++-- Indicators/Indi_Volumes.mqh | 9 ++-- Indicators/Indi_WPR.mqh | 8 +-- Indicators/Indi_WilliamsAD.mqh | 9 ++-- Indicators/Indi_ZigZag.mqh | 9 ++-- Indicators/Indi_ZigZagColor.mqh | 9 ++-- Indicators/OHLC/Indi_OHLC.mqh | 9 ++-- Indicators/Price/Indi_Price.mqh | 59 ++++++++++++++++++-- Indicators/Special/Indi_Math.mqh | 9 ++-- tests/IndicatorsTest.mq5 | 2 +- 79 files changed, 566 insertions(+), 308 deletions(-) create mode 100644 Indicator/IndicatorTickOrCandleSource.h diff --git a/DrawIndicator.mqh b/DrawIndicator.mqh index 7017a81eb..2888b77cf 100644 --- a/DrawIndicator.mqh +++ b/DrawIndicator.mqh @@ -32,7 +32,6 @@ // Includes. #include "DictObject.mqh" #include "Draw.mqh" -#include "Indicator.mqh" #include "Object.mqh" // Forward declaration. diff --git a/Indicator.enum.h b/Indicator.enum.h index 658423502..563282745 100644 --- a/Indicator.enum.h +++ b/Indicator.enum.h @@ -40,7 +40,7 @@ enum ENUM_INDICATOR_ACTION { FINAL_INDICATOR_ACTION_ENTRY }; -/* Define type of indicators. */ +/* Define type of */ enum ENUM_INDICATOR_TYPE { INDI_NONE = 0, // (None) INDI_AC, // Accelerator Oscillator @@ -101,12 +101,12 @@ enum ENUM_INDICATOR_TYPE { INDI_PRICE_FEEDER, // Indicator which returns prices from custom array INDI_PRICE_VOLUME_TREND, // Price and Volume Trend INDI_RATE_OF_CHANGE, // Rate of Change - INDI_RS, // Indi_Math-based RSI indicator. + INDI_RS, // Indi_Math-based RSI INDI_RSI, // Relative Strength Index INDI_RSI_ON_PRICE, // Relative Strength Index (RSI) (on Price) INDI_RVI, // Relative Vigor Index INDI_SAR, // Parabolic SAR - INDI_SPECIAL_MATH, // Math operations over given indicator. + INDI_SPECIAL_MATH, // Math operations over given INDI_STDDEV, // Standard Deviation INDI_STDDEV_ON_MA_SMA, // Standard Deviation on Moving Average in SMA mode INDI_STDDEV_ON_PRICE, // Standard Deviation (on Price) @@ -132,7 +132,7 @@ enum ENUM_INDICATOR_TYPE { FINAL_INDICATOR_TYPE_ENTRY }; -/* Defines type of source data for indicator. */ +/* Defines type of source data for */ enum ENUM_IDATA_SOURCE_TYPE { IDATA_BUILTIN = 0, // Platform built-in IDATA_CHART, // Chart calculation @@ -154,7 +154,7 @@ enum ENUM_IDATA_VALUE_RANGE { IDATA_RANGE_UNKNOWN }; -// Indicator line identifiers used in ADX and ADXW indicators. +// Indicator line identifiers used in ADX and ADXW enum ENUM_INDI_ADX_LINE { #ifdef __MQL4__ LINE_MAIN_ADX = MODE_MAIN, // Base indicator line. @@ -176,7 +176,7 @@ enum ENUM_INDICATOR_INDEX { FINAL_ENUM_INDICATOR_INDEX = 3 // Should be the last one. Used to calculate the number of enum items. }; -/* Indicator line identifiers used in Envelopes and Fractals indicators. */ +/* Indicator line identifiers used in Envelopes and Fractals */ enum ENUM_LO_UP_LINE { #ifdef __MQL4__ LINE_UPPER = MODE_UPPER, // Upper line. @@ -189,7 +189,7 @@ enum ENUM_LO_UP_LINE { }; /** - * Indicator line identifiers used in MACD, RVI and Stochastic indicators. + * Indicator line identifiers used in MACD, RVI and Stochastic * * @see: * - https://docs.mql4.com/constants/indicatorconstants/lines @@ -234,12 +234,17 @@ enum INDICATOR_ENTRY_FLAGS { // Storage type for IndicatorBase::GetSpecificValueStorage(). enum ENUM_INDI_VS_TYPE { - INDI_VS_TYPE_TIME, - INDI_VS_TYPE_TICK_VOLUME, - INDI_VS_TYPE_VOLUME, - INDI_VS_TYPE_SPREAD, - INDI_VS_TYPE_PRICE_OPEN, - INDI_VS_TYPE_PRICE_HIGH, - INDI_VS_TYPE_PRICE_LOW, - INDI_VS_TYPE_PRICE_CLOSE + INDI_VS_TYPE_TIME, // Candle. + INDI_VS_TYPE_TICK_VOLUME, // Candle. + INDI_VS_TYPE_VOLUME, // Candle. + INDI_VS_TYPE_SPREAD, // Candle. + INDI_VS_TYPE_PRICE_OPEN, // Candle. + INDI_VS_TYPE_PRICE_HIGH, // Candle. + INDI_VS_TYPE_PRICE_LOW, // Candle. + INDI_VS_TYPE_PRICE_CLOSE, // Candle. + INDI_VS_TYPE_PRICE_MEDIAN, // Candle. + INDI_VS_TYPE_PRICE_TYPICAL, // Candle. + INDI_VS_TYPE_PRICE_WEIGHTED, // Candle. + INDI_VS_TYPE_PRICE_BID, // Tick. + INDI_VS_TYPE_PRICE_ASK, // Tick. }; diff --git a/Indicator.mqh b/Indicator.mqh index 24750d256..8687a702c 100644 --- a/Indicator.mqh +++ b/Indicator.mqh @@ -980,7 +980,7 @@ class Indicator : public IndicatorBase { /** * Sets indicator data source. */ - void SetDataSource(IndicatorBase* _indi, int _input_mode = 0) override { + void SetDataSource(IndicatorBase* _indi, int _input_mode = -1) override { if (indi_src.IsSet() && indi_src.Ptr() != _indi) { indi_src.Ptr().RemoveListener(THIS_PTR); } diff --git a/Indicator.struct.h b/Indicator.struct.h index 782ab22c9..4479aeea4 100644 --- a/Indicator.struct.h +++ b/Indicator.struct.h @@ -437,7 +437,7 @@ struct IndicatorParams { idstype(_idstype), idvrange(IDATA_RANGE_UNKNOWN), indi_data_source_id(-1), - indi_data_source_mode(0), + indi_data_source_mode(-1), itype(_itype), is_draw(false), indi_color(clrNONE), @@ -454,7 +454,7 @@ struct IndicatorParams { idstype(_idstype), idvrange(IDATA_RANGE_UNKNOWN), indi_data_source_id(-1), - indi_data_source_mode(0), + indi_data_source_mode(-1), is_draw(false), indi_color(clrNONE), draw_window(0) { diff --git a/Indicator/IndicatorCandle.h b/Indicator/IndicatorCandle.h index e1b0ecf52..29c4fbd2e 100644 --- a/Indicator/IndicatorCandle.h +++ b/Indicator/IndicatorCandle.h @@ -215,7 +215,7 @@ class IndicatorCandle : public Indicator { /** * Checks whether indicator support given value storage type. */ - virtual bool HasSpecificValueStorage(ENUM_INDI_VS_TYPE _type) { + bool HasSpecificValueStorage(ENUM_INDI_VS_TYPE _type) { switch (_type) { case INDI_VS_TYPE_PRICE_OPEN: case INDI_VS_TYPE_PRICE_HIGH: diff --git a/Indicator/IndicatorCandleSource.h b/Indicator/IndicatorCandleSource.h index 47abebcd9..2d721fb8a 100644 --- a/Indicator/IndicatorCandleSource.h +++ b/Indicator/IndicatorCandleSource.h @@ -54,7 +54,7 @@ class IndicatorCandleSource : public Indicator { /** * Sets indicator data source. */ - void SetDataSource(IndicatorBase* _indi, int _input_mode = 0) override { + void SetDataSource(IndicatorBase* _indi, int _input_mode = -1) override { if (_indi == NULL) { // Just deselecting data source. Indicator::SetDataSource(_indi, _input_mode); @@ -80,6 +80,15 @@ class IndicatorCandleSource : public Indicator { Indicator::SetDataSource(_indi, _input_mode); } + /** + * Called when user tries to set given data source. Could be used to check if indicator implements all required value + * storages. + */ + bool OnValidateDataSource(IndicatorBase* _ds, string& _reason) override { + // @todo Make use of this method. + return true; + } + /** * Called if data source is requested, but wasn't yet set. May be used to initialize indicators that must operate on * some data source. diff --git a/Indicator/IndicatorTick.h b/Indicator/IndicatorTick.h index 79784d472..c5ad92d86 100644 --- a/Indicator/IndicatorTick.h +++ b/Indicator/IndicatorTick.h @@ -165,7 +165,7 @@ class IndicatorTick : public IndicatorBase { /** * Sets indicator data source. */ - void SetDataSource(IndicatorBase* _indi, int _input_mode = 0) { + void SetDataSource(IndicatorBase* _indi, int _input_mode = -1) { indi_src = _indi; itparams.SetDataSource(-1, _input_mode); } diff --git a/Indicator/IndicatorTickOrCandleSource.h b/Indicator/IndicatorTickOrCandleSource.h new file mode 100644 index 000000000..b7bc25265 --- /dev/null +++ b/Indicator/IndicatorTickOrCandleSource.h @@ -0,0 +1,72 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2021, EA31337 Ltd | +//| https://github.com/EA31337 | +//+------------------------------------------------------------------+ + +/* + * This file is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#ifndef __MQL__ +// Allows the preprocessor to include a header file when it is needed. +#pragma once +#endif + +// Includes. +#include "../Indicator.mqh" +#include "tests/classes/IndicatorTickReal.h" + +/** + * Indicator to be used with IndicatorTick or IndicatorCandle as a data source. + * + * In order it to work with + */ +template +class IndicatorTickOrCandleSource : public Indicator { + public: + /** + * Class constructor. + */ + IndicatorTickOrCandleSource(const TS& _iparams, IndicatorBase* _indi_src = NULL, int _indi_mode = 0) + : Indicator(_iparams, _indi_src, _indi_mode) {} + IndicatorTickOrCandleSource(const TS& _iparams, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) : Indicator(_iparams, _tf) {} + IndicatorTickOrCandleSource(ENUM_INDICATOR_TYPE _itype, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0, + string _name = "") + : Indicator(_itype, _tf, _shift, _name) {} + + /** + * Class deconstructor. + */ + ~IndicatorTickOrCandleSource() {} + + /** + * Called when user tries to set given data source. Could be used to check if indicator implements all required value + * storages. + */ + bool OnValidateDataSource(IndicatorBase* _ds, string& _reason) override { + // @todo Make use of this method. + return true; + } + + /** + * Called if data source is requested, but wasn't yet set. May be used to initialize indicators that must operate on + * some data source. + */ + IndicatorBase* OnDataSourceRequest() override { + // Defaulting to platform ticks. + return new IndicatorTickReal(GetSymbol(), GetTf(), "AMA on IndicatorTickReal"); + } +}; diff --git a/Indicator/IndicatorTickSource.h b/Indicator/IndicatorTickSource.h index 1b6273b8f..58800c0b8 100644 --- a/Indicator/IndicatorTickSource.h +++ b/Indicator/IndicatorTickSource.h @@ -47,12 +47,12 @@ class IndicatorTickSource : public Indicator { /** * Class deconstructor. */ - ~IndicatorCandleSource() {} + ~IndicatorTickSource() {} /** * Sets indicator data source. */ - void SetDataSource(IndicatorBase* _indi, int _input_mode = 0) override { + void SetDataSource(IndicatorBase* _indi, int _input_mode = -1) override { if (_indi == NULL) { // Just deselecting data source. Indicator::SetDataSource(_indi, _input_mode); @@ -62,16 +62,61 @@ class IndicatorTickSource : public Indicator { // We can only use data sources which supports all possible modes from IndicatorTick. bool _result = true; - _result &= _indi.HasSpecificValueStorage(INDI_VS_TYPE_PRICE_APPLIED); + if (_input_mode == -1) { + // Source mode which acts as an applied price wasn't selected, so we have to ensure that source is a Tick + // indicator. Valid only if implements bid or ask price. + _result &= _indi.HasSpecificValueStorage(INDI_VS_TYPE_PRICE_BID) || + _indi.HasSpecificValueStorage(INDI_VS_TYPE_PRICE_ASK); + } else { + // Applied price selected. We will select source indicator only if it provides price buffer for given applied + // price. + switch (_input_mode) { + case PRICE_OPEN: + _result &= _indi.HasSpecificValueStorage(INDI_VS_TYPE_PRICE_OPEN); + break; + case PRICE_HIGH: + _result &= _indi.HasSpecificValueStorage(INDI_VS_TYPE_PRICE_HIGH); + break; + case PRICE_LOW: + _result &= _indi.HasSpecificValueStorage(INDI_VS_TYPE_PRICE_LOW); + break; + case PRICE_CLOSE: + _result &= _indi.HasSpecificValueStorage(INDI_VS_TYPE_PRICE_CLOSE); + break; + case PRICE_MEDIAN: + _result &= _indi.HasSpecificValueStorage(INDI_VS_TYPE_PRICE_MEDIAN); + break; + case PRICE_TYPICAL: + _result &= _indi.HasSpecificValueStorage(INDI_VS_TYPE_PRICE_TYPICAL); + break; + case PRICE_WEIGHTED: + _result &= _indi.HasSpecificValueStorage(INDI_VS_TYPE_PRICE_WEIGHTED); + break; + default: + Alert("Invalid input mode ", _input_mode, " for indicator ", _indi.GetFullName(), + ". Must be one one PRICE_(OPEN|HIGH|LOW|CLOSE|MEDIAN|TYPICAL|WEIGHTED)!"); + DebugBreak(); + } + } if (!_result) { - Alert("Passed indicator ", _indi.GetFullName(), " does not define all required specific data storages!"); + Alert("Passed indicator ", _indi.GetFullName(), + " does not provide required data storage(s)! Mode selected: ", _input_mode); DebugBreak(); } Indicator::SetDataSource(_indi, _input_mode); } + /** + * Called when user tries to set given data source. Could be used to check if indicator implements all required value + * storages. + */ + bool OnValidateDataSource(IndicatorBase* _ds, string& _reason) override { + // @todo Make use of this method. + return true; + } + /** * Called if data source is requested, but wasn't yet set. May be used to initialize indicators that must operate on * some data source. diff --git a/IndicatorBase.h b/IndicatorBase.h index 898d51f78..f0b0e4677 100644 --- a/IndicatorBase.h +++ b/IndicatorBase.h @@ -401,7 +401,7 @@ class IndicatorBase : public Chart { /** * Sets indicator data source. */ - virtual void SetDataSource(IndicatorBase* _indi, int _input_mode = 0) = NULL; + virtual void SetDataSource(IndicatorBase* _indi, int _input_mode = -1) = NULL; /** * Sets data source's input mode. @@ -611,6 +611,15 @@ class IndicatorBase : public Chart { */ virtual void OnBecomeDataSourceFor(IndicatorBase* _base_indi){}; + /** + * Called when user tries to set given data source. Could be used to check if indicator implements all required value + * storages. + */ + virtual bool OnValidateDataSource(IndicatorBase* _ds, string& _reason) { + _reason = "Indicator " + GetName() + " does not implement OnValidateDataSource()"; + return false; + } + /** * Returns indicator value for a given shift and mode. */ diff --git a/Indicators/Bitwise/Indi_Candle.mqh b/Indicators/Bitwise/Indi_Candle.mqh index 40575e792..13c98aeed 100644 --- a/Indicators/Bitwise/Indi_Candle.mqh +++ b/Indicators/Bitwise/Indi_Candle.mqh @@ -23,7 +23,7 @@ // Includes. #include "../../Bar.struct.h" #include "../../BufferStruct.mqh" -#include "../../Indicator.mqh" +#include "../../Indicator/IndicatorTickOrCandleSource.h" #include "../../Pattern.struct.h" #include "../../Serializer.mqh" #include "../Price/Indi_Price.mqh" @@ -47,13 +47,14 @@ struct CandleParams : IndicatorParams { /** * Implements Candle Pattern Detector. */ -class Indi_Candle : public Indicator { +class Indi_Candle : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_Candle(CandleParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_Candle(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_CANDLE, _tf, _shift){}; + Indi_Candle(CandleParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_Candle(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_CANDLE, _tf, _shift){}; /** * Alters indicator's struct value. diff --git a/Indicators/Bitwise/Indi_Pattern.mqh b/Indicators/Bitwise/Indi_Pattern.mqh index fec403314..1e13c4217 100644 --- a/Indicators/Bitwise/Indi_Pattern.mqh +++ b/Indicators/Bitwise/Indi_Pattern.mqh @@ -23,7 +23,7 @@ // Includes. #include "../../Bar.struct.h" #include "../../BufferStruct.mqh" -#include "../../Indicator.mqh" +#include "../../Indicator/IndicatorTickOrCandleSource.h" #include "../../Pattern.struct.h" #include "../../Serializer.mqh" #include "../Price/Indi_Price.mqh" @@ -46,13 +46,14 @@ struct IndiPatternParams : IndicatorParams { /** * Implements Pattern Detector. */ -class Indi_Pattern : public Indicator { +class Indi_Pattern : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_Pattern(IndiPatternParams& _p, IndicatorBase* _indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_Pattern(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_PATTERN, _tf, _shift){}; + Indi_Pattern(IndiPatternParams& _p, IndicatorBase* _indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_Pattern(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_PATTERN, _tf, _shift){}; /** * Returns the indicator's value. diff --git a/Indicators/Indi_AC.mqh b/Indicators/Indi_AC.mqh index 8c222b537..34f7863c8 100644 --- a/Indicators/Indi_AC.mqh +++ b/Indicators/Indi_AC.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -49,13 +49,13 @@ struct IndiACParams : IndicatorParams { /** * Implements the Bill Williams' Accelerator/Decelerator oscillator. */ -class Indi_AC : public Indicator { +class Indi_AC : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_AC(IndiACParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_AC(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_AC, _tf, _shift){}; + Indi_AC(IndiACParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_AC(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_AC, _tf, _shift){}; /** * Returns the indicator value. diff --git a/Indicators/Indi_AD.mqh b/Indicators/Indi_AD.mqh index 8473fe8de..c91a29f1f 100644 --- a/Indicators/Indi_AD.mqh +++ b/Indicators/Indi_AD.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -48,13 +48,13 @@ struct IndiADParams : IndicatorParams { /** * Implements the Accumulation/Distribution indicator. */ -class Indi_AD : public Indicator { +class Indi_AD : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_AD(IndiADParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_AD(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_AD, _tf, _shift) { + Indi_AD(IndiADParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_AD(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_AD, _tf, _shift) { iparams.SetTf(_tf); }; diff --git a/Indicators/Indi_ADX.mqh b/Indicators/Indi_ADX.mqh index 041d8b975..0301eec6e 100644 --- a/Indicators/Indi_ADX.mqh +++ b/Indicators/Indi_ADX.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "Price/Indi_Price.mqh" #ifndef __MQL4__ @@ -61,13 +61,13 @@ struct IndiADXParams : IndicatorParams { /** * Implements the Average Directional Movement Index indicator. */ -class Indi_ADX : public Indicator { +class Indi_ADX : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_ADX(IndiADXParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_ADX(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_ADX, _tf, _shift) {} + Indi_ADX(IndiADXParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_ADX(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_ADX, _tf, _shift) {} /** * Returns the indicator value. diff --git a/Indicators/Indi_ADXW.mqh b/Indicators/Indi_ADXW.mqh index bac89a6c8..dc199dae2 100644 --- a/Indicators/Indi_ADXW.mqh +++ b/Indicators/Indi_ADXW.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.h" #include "../Storage/ValueStorage.price.h" #include "../Storage/ValueStorage.spread.h" @@ -55,13 +55,14 @@ struct IndiADXWParams : IndiADXParams { /** * Implements the Average Directional Movement Index indicator by Welles Wilder. */ -class Indi_ADXW : public Indicator { +class Indi_ADXW : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_ADXW(IndiADXWParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_ADXW(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_ADXW, _tf, _shift){}; + Indi_ADXW(IndiADXWParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_ADXW(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_ADXW, _tf, _shift){}; /** * Built-in version of ADX Wilder. diff --git a/Indicators/Indi_AMA.mqh b/Indicators/Indi_AMA.mqh index 3238fcd07..206c2cb77 100644 --- a/Indicators/Indi_AMA.mqh +++ b/Indicators/Indi_AMA.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator/IndicatorCandleSource.h" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.h" #include "../Storage/ValueStorage.price.h" #include "Price/Indi_Price.mqh" @@ -63,17 +63,16 @@ struct IndiAMAParams : IndicatorParams { /** * Implements the AMA indicator. */ -class Indi_AMA : public IndicatorCandleSource { +class Indi_AMA : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_AMA(IndiAMAParams &_p, IndicatorBase *_indi_src = NULL, int _indi_mode = 0) - : IndicatorCandleSource(_p, _indi_src, _indi_mode) { + : IndicatorTickOrCandleSource(_p, _indi_src, _indi_mode) { iparams.SetIndicatorType(INDI_AMA); }; - Indi_AMA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) - : IndicatorCandleSource(INDI_AMA, _tf, _shift){}; + Indi_AMA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_AMA, _tf, _shift){}; /** * Built-in version of AMA. diff --git a/Indicators/Indi_AO.mqh b/Indicators/Indi_AO.mqh index e65e367aa..c2f9e6d35 100644 --- a/Indicators/Indi_AO.mqh +++ b/Indicators/Indi_AO.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -51,13 +51,13 @@ struct IndiAOParams : IndicatorParams { /** * Implements the Awesome oscillator. */ -class Indi_AO : public Indicator { +class Indi_AO : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_AO(IndiAOParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_AO(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_AO, _tf, _shift){}; + Indi_AO(IndiAOParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_AO(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_AO, _tf, _shift){}; /** * Returns the indicator value. diff --git a/Indicators/Indi_ASI.mqh b/Indicators/Indi_ASI.mqh index 1f18b15a5..cccfc3a2a 100644 --- a/Indicators/Indi_ASI.mqh +++ b/Indicators/Indi_ASI.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.all.h" // Structs. @@ -46,13 +46,13 @@ struct IndiASIParams : IndicatorParams { /** * Implements the Bill Williams' Accelerator/Decelerator oscillator. */ -class Indi_ASI : public Indicator { +class Indi_ASI : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_ASI(IndiASIParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_ASI(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_ASI, _tf, _shift){}; + Indi_ASI(IndiASIParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_ASI(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_ASI, _tf, _shift){}; /** * Built-in version of ASI. diff --git a/Indicators/Indi_ATR.mqh b/Indicators/Indi_ATR.mqh index f0d65d2f1..3a6328447 100644 --- a/Indicators/Indi_ATR.mqh +++ b/Indicators/Indi_ATR.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -52,13 +52,13 @@ struct IndiATRParams : IndicatorParams { * * Note: It doesn't give independent signals. It is used to define volatility (trend strength). */ -class Indi_ATR : public Indicator { +class Indi_ATR : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_ATR(IndiATRParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_ATR(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_ATR, _tf, _shift){}; + Indi_ATR(IndiATRParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_ATR(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_ATR, _tf, _shift){}; /** * Returns the indicator value. diff --git a/Indicators/Indi_Alligator.mqh b/Indicators/Indi_Alligator.mqh index 52acbfd76..ff8fe357d 100644 --- a/Indicators/Indi_Alligator.mqh +++ b/Indicators/Indi_Alligator.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -95,14 +95,15 @@ struct IndiAlligatorParams : IndicatorParams { /** * Implements the Alligator indicator. */ -class Indi_Alligator : public Indicator { +class Indi_Alligator : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_Alligator(IndiAlligatorParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src) {} - Indi_Alligator(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_ADX, _tf, _shift){}; + : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_Alligator(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_ADX, _tf, _shift){}; /** * Returns the indicator value. diff --git a/Indicators/Indi_AppliedPrice.mqh b/Indicators/Indi_AppliedPrice.mqh index 90e78ed63..28d43b785 100644 --- a/Indicators/Indi_AppliedPrice.mqh +++ b/Indicators/Indi_AppliedPrice.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "OHLC/Indi_OHLC.mqh" // Structs. @@ -44,7 +44,7 @@ struct IndiAppliedPriceParams : IndicatorParams { /** * Implements the "Applied Price over OHCL Indicator" indicator, e.g. over Indi_Price. */ -class Indi_AppliedPrice : public Indicator { +class Indi_AppliedPrice : public IndicatorTickOrCandleSource { protected: void OnInit() { if (!indi_src.IsSet()) { @@ -58,10 +58,11 @@ class Indi_AppliedPrice : public Indicator { * Class constructor. */ Indi_AppliedPrice(IndiAppliedPriceParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src) { + : IndicatorTickOrCandleSource(_p, _indi_src) { OnInit(); }; - Indi_AppliedPrice(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_PRICE, _tf, _shift) { + Indi_AppliedPrice(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_PRICE, _tf, _shift) { OnInit(); }; diff --git a/Indicators/Indi_BWMFI.mqh b/Indicators/Indi_BWMFI.mqh index b0e3e1853..cfb98b777 100644 --- a/Indicators/Indi_BWMFI.mqh +++ b/Indicators/Indi_BWMFI.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -62,14 +62,14 @@ struct IndiBWIndiMFIParams : IndicatorParams { /** * Implements the Market Facilitation Index by Bill Williams indicator. */ -class Indi_BWMFI : public Indicator { +class Indi_BWMFI : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_BWMFI(IndiBWIndiMFIParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src) {} - Indi_BWMFI(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_BWMFI, _tf, _shift) {} + Indi_BWMFI(IndiBWIndiMFIParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_BWMFI(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_BWMFI, _tf, _shift) {} /** * Returns the indicator value. @@ -81,7 +81,7 @@ class Indi_BWMFI : public Indicator { static double iBWMFI(string _symbol = NULL, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0, ENUM_BWMFI_BUFFER _mode = BWMFI_BUFFER, IndicatorBase *_obj = NULL) { #ifdef __MQL4__ - return ::iBWMFI(_symbol, _tf, _shift); + return ::iBWMFI(_symbol, _tf, _real_shift); #else // __MQL5__ int _handle = Object::IsValid(_obj) ? _obj.Get(IndicatorState::INDICATOR_STATE_PROP_HANDLE) : NULL; double _res[]; @@ -115,8 +115,10 @@ class Indi_BWMFI : public Indicator { * Returns the indicator's value. */ virtual IndicatorDataEntryValue GetEntryValue(int _mode = BWMFI_BUFFER, int _shift = 0) { + int _ishift = iparams.GetShift() + _shift; + double _value = EMPTY_VALUE; - int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); + switch (iparams.idstype) { case IDATA_BUILTIN: istate.handle = istate.is_changed ? INVALID_HANDLE : istate.handle; diff --git a/Indicators/Indi_BWZT.mqh b/Indicators/Indi_BWZT.mqh index 73d027824..70675404e 100644 --- a/Indicators/Indi_BWZT.mqh +++ b/Indicators/Indi_BWZT.mqh @@ -62,13 +62,14 @@ struct IndiBWZTParams : IndicatorParams { /** * Implements the Bill Williams' Zone Trade. */ -class Indi_BWZT : public Indicator { +class Indi_BWZT : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_BWZT(IndiBWZTParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_BWZT(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_BWZT, _tf, _shift){}; + Indi_BWZT(IndiBWZTParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_BWZT(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_BWZT, _tf, _shift){}; /** * Built-in version of BWZT. diff --git a/Indicators/Indi_Bands.mqh b/Indicators/Indi_Bands.mqh index a368d6b85..09e36401e 100644 --- a/Indicators/Indi_Bands.mqh +++ b/Indicators/Indi_Bands.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "Indi_CCI.mqh" #include "Indi_Envelopes.mqh" #include "Indi_MA.mqh" @@ -86,14 +86,14 @@ struct IndiBandsParams : IndicatorParams { /** * Implements the Bollinger Bands® indicator. */ -class Indi_Bands : public Indicator { +class Indi_Bands : public IndicatorTickSource { public: /** * Class constructor. */ Indi_Bands(IndiBandsParams &_p, IndicatorBase *_indi_src = NULL, int _mode = 0) - : Indicator(_p, _indi_src, _mode) {} - Indi_Bands(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_BANDS, _tf, _shift) {} + : IndicatorTickSource(_p, _indi_src, _mode) {} + Indi_Bands(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickSource(INDI_BANDS, _tf, _shift) {} /** * Returns the indicator value. diff --git a/Indicators/Indi_BearsPower.mqh b/Indicators/Indi_BearsPower.mqh index b2bb83164..dae950d35 100644 --- a/Indicators/Indi_BearsPower.mqh +++ b/Indicators/Indi_BearsPower.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -51,14 +51,15 @@ struct IndiBearsPowerParams : IndicatorParams { /** * Implements the Bears Power indicator. */ -class Indi_BearsPower : public Indicator { +class Indi_BearsPower : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_BearsPower(IndiBearsPowerParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src) {} - Indi_BearsPower(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_BEARS, _tf, _shift) {} + : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_BearsPower(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_BEARS, _tf, _shift) {} /** * Returns the indicator value. diff --git a/Indicators/Indi_BullsPower.mqh b/Indicators/Indi_BullsPower.mqh index 1e55f0010..520ef6ccb 100644 --- a/Indicators/Indi_BullsPower.mqh +++ b/Indicators/Indi_BullsPower.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -51,14 +51,15 @@ struct IndiBullsPowerParams : IndicatorParams { /** * Implements the Bulls Power indicator. */ -class Indi_BullsPower : public Indicator { +class Indi_BullsPower : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_BullsPower(IndiBullsPowerParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src) {} - Indi_BullsPower(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_BULLS, _tf, _shift) {} + : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_BullsPower(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_BULLS, _tf, _shift) {} /** * Returns the indicator value. diff --git a/Indicators/Indi_CCI.mqh b/Indicators/Indi_CCI.mqh index ed4f71c4a..4e34df025 100644 --- a/Indicators/Indi_CCI.mqh +++ b/Indicators/Indi_CCI.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickSource.h" #include "Indi_MA.mqh" #include "Indi_PriceFeeder.mqh" #include "Price/Indi_Price.mqh" @@ -58,13 +58,13 @@ struct IndiCCIParams : IndicatorParams { /** * Implements the Commodity Channel Index indicator. */ -class Indi_CCI : public Indicator { +class Indi_CCI : public IndicatorTickSource { public: /** * Class constructor. */ - Indi_CCI(IndiCCIParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_CCI(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_CCI, _tf, _shift) {} + Indi_CCI(IndiCCIParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickSource(_p, _indi_src) {} + Indi_CCI(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickSource(INDI_CCI, _tf, _shift) {} /** * Returns the indicator value. diff --git a/Indicators/Indi_CHO.mqh b/Indicators/Indi_CHO.mqh index a42f126a7..5366e2651 100644 --- a/Indicators/Indi_CHO.mqh +++ b/Indicators/Indi_CHO.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.all.h" #include "../Util.h" #include "Indi_MA.mqh" @@ -54,13 +54,14 @@ struct IndiCHOParams : IndicatorParams { /** * Implements the Bill Williams' Accelerator/Decelerator oscillator. */ -class Indi_CHO : public Indicator { +class Indi_CHO : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_CHO(IndiCHOParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_CHO(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_CHAIKIN, _tf, _shift){}; + Indi_CHO(IndiCHOParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_CHO(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_CHAIKIN, _tf, _shift){}; /** * Built-in version of Chaikin Oscillator. diff --git a/Indicators/Indi_CHV.mqh b/Indicators/Indi_CHV.mqh index 1c0c15119..145a03f59 100644 --- a/Indicators/Indi_CHV.mqh +++ b/Indicators/Indi_CHV.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.all.h" #include "../Util.h" #include "Indi_MA.mqh" @@ -55,13 +55,14 @@ struct IndiCHVParams : IndicatorParams { /** * Implements the Bill Williams' Accelerator/Decelerator oscillator. */ -class Indi_CHV : public Indicator { +class Indi_CHV : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_CHV(IndiCHVParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_CHV(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_CHAIKIN_V, _tf, _shift){}; + Indi_CHV(IndiCHVParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_CHV(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_CHAIKIN_V, _tf, _shift){}; /** * Built-in version of Chaikin Volatility. diff --git a/Indicators/Indi_ColorBars.mqh b/Indicators/Indi_ColorBars.mqh index ae5dfcd9e..7927d1fe2 100644 --- a/Indicators/Indi_ColorBars.mqh +++ b/Indicators/Indi_ColorBars.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.all.h" // Structs. @@ -42,14 +42,15 @@ struct IndiColorBarsParams : IndicatorParams { /** * Implements Color Bars */ -class Indi_ColorBars : public Indicator { +class Indi_ColorBars : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_ColorBars(IndiColorBarsParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src){}; - Indi_ColorBars(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_COLOR_BARS, _tf, _shift){}; + : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_ColorBars(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_COLOR_BARS, _tf, _shift){}; /** * "Built-in" version of Color Bars. diff --git a/Indicators/Indi_ColorCandlesDaily.mqh b/Indicators/Indi_ColorCandlesDaily.mqh index 140320f7b..9348b8095 100644 --- a/Indicators/Indi_ColorCandlesDaily.mqh +++ b/Indicators/Indi_ColorCandlesDaily.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.all.h" // Structs. @@ -42,15 +42,15 @@ struct IndiColorCandlesDailyParams : IndicatorParams { /** * Implements Color Bars */ -class Indi_ColorCandlesDaily : public Indicator { +class Indi_ColorCandlesDaily : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_ColorCandlesDaily(IndiColorCandlesDailyParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src){}; + : IndicatorTickOrCandleSource(_p, _indi_src){}; Indi_ColorCandlesDaily(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) - : Indicator(INDI_COLOR_CANDLES_DAILY, _tf, _shift){}; + : IndicatorTickOrCandleSource(INDI_COLOR_CANDLES_DAILY, _tf, _shift){}; /** * "Built-in" version of Color Candles Daily. diff --git a/Indicators/Indi_ColorLine.mqh b/Indicators/Indi_ColorLine.mqh index fcf734106..64adcf9dc 100644 --- a/Indicators/Indi_ColorLine.mqh +++ b/Indicators/Indi_ColorLine.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.all.h" #include "Indi_MA.mqh" @@ -45,14 +45,15 @@ struct IndiColorLineParams : IndicatorParams { /** * Implements Color Bars */ -class Indi_ColorLine : public Indicator { +class Indi_ColorLine : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_ColorLine(IndiColorLineParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src){}; - Indi_ColorLine(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_COLOR_LINE, _tf, _shift){}; + : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_ColorLine(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_COLOR_LINE, _tf, _shift){}; /** * "Built-in" version of Color Line. diff --git a/Indicators/Indi_CustomMovingAverage.mqh b/Indicators/Indi_CustomMovingAverage.mqh index 664251971..e172c2b69 100644 --- a/Indicators/Indi_CustomMovingAverage.mqh +++ b/Indicators/Indi_CustomMovingAverage.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" // Structs. struct IndiCustomMovingAverageParams : IndicatorParams { @@ -54,15 +54,15 @@ struct IndiCustomMovingAverageParams : IndicatorParams { /** * Implements the Custom Moving Average indicator. */ -class Indi_CustomMovingAverage : public Indicator { +class Indi_CustomMovingAverage : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_CustomMovingAverage(IndiCustomMovingAverageParams& _p, IndicatorBase* _indi_src = NULL) - : Indicator(_p, _indi_src){}; + : IndicatorTickOrCandleSource(_p, _indi_src){}; Indi_CustomMovingAverage(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) - : Indicator(INDI_CUSTOM_MOVING_AVG, _tf, _shift){}; + : IndicatorTickOrCandleSource(INDI_CUSTOM_MOVING_AVG, _tf, _shift){}; /** * Returns the indicator's value. diff --git a/Indicators/Indi_DEMA.mqh b/Indicators/Indi_DEMA.mqh index 4621be7c2..bf5a19ebd 100644 --- a/Indicators/Indi_DEMA.mqh +++ b/Indicators/Indi_DEMA.mqh @@ -27,7 +27,7 @@ // Includes. #include "../Dict.mqh" #include "../DictObject.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Refs.mqh" #include "../Storage/Objects.h" #include "../Storage/ValueStorage.h" @@ -63,13 +63,14 @@ struct IndiDEIndiMAParams : IndicatorParams { /** * Implements the Moving Average indicator. */ -class Indi_DEMA : public Indicator { +class Indi_DEMA : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_DEMA(IndiDEIndiMAParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_DEMA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_DEMA, _tf, _shift) {} + Indi_DEMA(IndiDEIndiMAParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_DEMA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_DEMA, _tf, _shift) {} /** * Updates the indicator value. diff --git a/Indicators/Indi_DeMarker.mqh b/Indicators/Indi_DeMarker.mqh index cea440264..dbff0f090 100644 --- a/Indicators/Indi_DeMarker.mqh +++ b/Indicators/Indi_DeMarker.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -50,14 +50,14 @@ struct IndiDeMarkerParams : IndicatorParams { /** * Implements the DeMarker indicator. */ -class Indi_DeMarker : public Indicator { +class Indi_DeMarker : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_DeMarker(IndiDeMarkerParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src) {} - Indi_DeMarker(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_DEMARKER, _tf, _shift) {} + Indi_DeMarker(IndiDeMarkerParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_DeMarker(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_DEMARKER, _tf, _shift) {} /** * Returns the indicator value. diff --git a/Indicators/Indi_Demo.mqh b/Indicators/Indi_Demo.mqh index cdf8fbb2e..9fd756862 100644 --- a/Indicators/Indi_Demo.mqh +++ b/Indicators/Indi_Demo.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "Price/Indi_Price.mqh" /** @@ -53,13 +53,14 @@ struct IndiDemoParams : IndicatorParams { /** * Demo/Dummy Indicator. */ -class Indi_Demo : public Indicator { +class Indi_Demo : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_Demo(IndiDemoParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_Demo(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_DEMO, _tf, _shift){}; + Indi_Demo(IndiDemoParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_Demo(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_DEMO, _tf, _shift){}; /** * Returns the indicator value. diff --git a/Indicators/Indi_DetrendedPrice.mqh b/Indicators/Indi_DetrendedPrice.mqh index 9c60f2207..3f78bdddd 100644 --- a/Indicators/Indi_DetrendedPrice.mqh +++ b/Indicators/Indi_DetrendedPrice.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.price.h" #include "Indi_MA.mqh" @@ -48,15 +48,15 @@ struct IndiDetrendedPriceParams : IndicatorParams { /** * Implements Detrended Price Oscillator. */ -class Indi_DetrendedPrice : public Indicator { +class Indi_DetrendedPrice : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_DetrendedPrice(IndiDetrendedPriceParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src){}; + : IndicatorTickOrCandleSource(_p, _indi_src){}; Indi_DetrendedPrice(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) - : Indicator(INDI_DETRENDED_PRICE, _tf, _shift){}; + : IndicatorTickOrCandleSource(INDI_DETRENDED_PRICE, _tf, _shift){}; /** * Built-in version of AMA. diff --git a/Indicators/Indi_Drawer.mqh b/Indicators/Indi_Drawer.mqh index 3130ea7c6..8825e447e 100644 --- a/Indicators/Indi_Drawer.mqh +++ b/Indicators/Indi_Drawer.mqh @@ -26,7 +26,7 @@ struct IndicatorParams; // Includes. #include "../Action.mqh" #include "../DictStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Redis.mqh" #include "Indi_Drawer.struct.h" #include "Price/Indi_Price.mqh" @@ -34,7 +34,7 @@ struct IndicatorParams; /** * Implements the Relative Strength Index indicator. */ -class Indi_Drawer : public Indicator { +class Indi_Drawer : public IndicatorTickOrCandleSource { Redis redis; public: @@ -42,10 +42,11 @@ class Indi_Drawer : public Indicator { * Class constructor. */ Indi_Drawer(const IndiDrawerParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src), redis(true) { + : IndicatorTickOrCandleSource(_p, _indi_src), redis(true) { Init(); } - Indi_Drawer(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_DRAWER, _tf, _shift), redis(true) { + Indi_Drawer(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_DRAWER, _tf, _shift), redis(true) { Init(); } diff --git a/Indicators/Indi_Envelopes.mqh b/Indicators/Indi_Envelopes.mqh index bc4e5c41a..c9ac3d055 100644 --- a/Indicators/Indi_Envelopes.mqh +++ b/Indicators/Indi_Envelopes.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/Singleton.h" #include "Indi_MA.mqh" #include "Indi_PriceFeeder.mqh" @@ -76,14 +76,15 @@ struct IndiEnvelopesParams : IndicatorParams { /** * Implements the Envelopes indicator. */ -class Indi_Envelopes : public Indicator { +class Indi_Envelopes : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_Envelopes(IndiEnvelopesParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src) {} - Indi_Envelopes(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_ENVELOPES, _tf, _shift) {} + : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_Envelopes(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_ENVELOPES, _tf, _shift) {} /** * Returns the indicator value. diff --git a/Indicators/Indi_Force.mqh b/Indicators/Indi_Force.mqh index a752c8938..3c6f6e408 100644 --- a/Indicators/Indi_Force.mqh +++ b/Indicators/Indi_Force.mqh @@ -32,7 +32,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -65,14 +65,15 @@ struct IndiForceParams : IndicatorParams { /** * Implements the Force Index indicator. */ -class Indi_Force : public Indicator { +class Indi_Force : public IndicatorTickOrCandleSource { protected: public: /** * Class constructor. */ - Indi_Force(IndiForceParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_Force(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_FORCE, _tf, _shift) {} + Indi_Force(IndiForceParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_Force(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_FORCE, _tf, _shift) {} /** * Returns the indicator value. diff --git a/Indicators/Indi_FractalAdaptiveMA.mqh b/Indicators/Indi_FractalAdaptiveMA.mqh index a9d1810ac..a0c69a60c 100644 --- a/Indicators/Indi_FractalAdaptiveMA.mqh +++ b/Indicators/Indi_FractalAdaptiveMA.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.all.h" // Structs. @@ -50,14 +50,14 @@ struct IndiFrAIndiMAParams : IndicatorParams { /** * Implements the Bill Williams' Accelerator/Decelerator oscillator. */ -class Indi_FrAMA : public Indicator { +class Indi_FrAMA : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_FrAMA(IndiFrAIndiMAParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src){}; - Indi_FrAMA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_FRAMA, _tf, _shift){}; + Indi_FrAMA(IndiFrAIndiMAParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_FrAMA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_FRAMA, _tf, _shift){}; /** * Built-in version of FrAMA. diff --git a/Indicators/Indi_Fractals.mqh b/Indicators/Indi_Fractals.mqh index 832f5d9aa..86d7a37fd 100644 --- a/Indicators/Indi_Fractals.mqh +++ b/Indicators/Indi_Fractals.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -48,14 +48,14 @@ struct IndiFractalsParams : IndicatorParams { /** * Implements the Fractals indicator. */ -class Indi_Fractals : public Indicator { +class Indi_Fractals : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_Fractals(IndiFractalsParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src) {} - Indi_Fractals(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_FRACTALS, _tf, _shift) {} + Indi_Fractals(IndiFractalsParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_Fractals(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_FRACTALS, _tf, _shift) {} /** * Returns the indicator value. diff --git a/Indicators/Indi_Gator.mqh b/Indicators/Indi_Gator.mqh index e256b21b7..ff8803c1b 100644 --- a/Indicators/Indi_Gator.mqh +++ b/Indicators/Indi_Gator.mqh @@ -28,7 +28,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -103,13 +103,14 @@ struct IndiGatorParams : IndicatorParams { /** * Implements the Gator oscillator. */ -class Indi_Gator : public Indicator { +class Indi_Gator : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_Gator(IndiGatorParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_Gator(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_GATOR, _tf, _shift) {} + Indi_Gator(IndiGatorParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_Gator(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_GATOR, _tf, _shift) {} /** * Returns the indicator value. diff --git a/Indicators/Indi_HeikenAshi.mqh b/Indicators/Indi_HeikenAshi.mqh index 52c15667e..5c2da1599 100644 --- a/Indicators/Indi_HeikenAshi.mqh +++ b/Indicators/Indi_HeikenAshi.mqh @@ -28,7 +28,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.all.h" // Enums. @@ -68,14 +68,15 @@ struct IndiHeikenAshiParams : IndicatorParams { /** * Implements the Heiken-Ashi indicator. */ -class Indi_HeikenAshi : public Indicator { +class Indi_HeikenAshi : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_HeikenAshi(IndiHeikenAshiParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src) {} - Indi_HeikenAshi(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_HEIKENASHI, _tf, _shift) {} + : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_HeikenAshi(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_HEIKENASHI, _tf, _shift) {} /** * Returns value for iHeikenAshi indicator. diff --git a/Indicators/Indi_Ichimoku.mqh b/Indicators/Indi_Ichimoku.mqh index 2b3378c79..a207e884d 100644 --- a/Indicators/Indi_Ichimoku.mqh +++ b/Indicators/Indi_Ichimoku.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -86,14 +86,14 @@ struct IndiIchimokuParams : IndicatorParams { /** * Implements the Ichimoku Kinko Hyo indicator. */ -class Indi_Ichimoku : public Indicator { +class Indi_Ichimoku : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_Ichimoku(IndiIchimokuParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src) {} - Indi_Ichimoku(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_ICHIMOKU, _tf, _shift) {} + Indi_Ichimoku(IndiIchimokuParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_Ichimoku(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_ICHIMOKU, _tf, _shift) {} /** * Returns the indicator value. diff --git a/Indicators/Indi_Killzones.mqh b/Indicators/Indi_Killzones.mqh index 89913eeb5..5fc584d03 100644 --- a/Indicators/Indi_Killzones.mqh +++ b/Indicators/Indi_Killzones.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Market.struct.h" // Defines enumerations. @@ -91,7 +91,7 @@ struct Indi_Killzones_Time : MarketTimeForex { /** * Implements Pivot Detector. */ -class Indi_Killzones : public Indicator { +class Indi_Killzones : public IndicatorTickOrCandleSource { protected: Indi_Killzones_Time ikt; @@ -100,8 +100,9 @@ class Indi_Killzones : public Indicator { * Class constructor. */ Indi_Killzones(IndiKillzonesParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src) {} - Indi_Killzones(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_KILLZONES, _tf, _shift) {} + : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_Killzones(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_KILLZONES, _tf, _shift) {} /** * Returns the indicator's value. diff --git a/Indicators/Indi_MA.mqh b/Indicators/Indi_MA.mqh index 3cdd2083d..d9a23f29c 100644 --- a/Indicators/Indi_MA.mqh +++ b/Indicators/Indi_MA.mqh @@ -27,7 +27,7 @@ // Includes. #include "../Dict.mqh" #include "../DictObject.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickSource.h" #include "../Refs.mqh" #include "../Storage/Singleton.h" #include "../Storage/ValueStorage.h" @@ -74,13 +74,13 @@ struct IndiMAParams : IndicatorParams { /** * Implements the Moving Average indicator. */ -class Indi_MA : public Indicator { +class Indi_MA : public IndicatorTickSource { public: /** * Class constructor. */ - Indi_MA(IndiMAParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_MA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_MA, _tf, _shift) {} + Indi_MA(IndiMAParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickSource(_p, _indi_src) {} + Indi_MA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickSource(INDI_MA, _tf, _shift) {} /** * Returns the indicator value. @@ -665,6 +665,35 @@ class Indi_MA : public Indicator { return _ptr; } + /** + * Returns value storage of given kind. + */ + IValueStorage *GetSpecificValueStorage(ENUM_INDI_VS_TYPE _type) override { + switch (_type) { + case INDI_VS_TYPE_PRICE_ASK: + case INDI_VS_TYPE_PRICE_BID: + // We're returning the same buffer for ask and bid price, as target indicator probably won't bother. + return GetValueStorage(0); + default: + // Trying in parent class. + return Indicator::GetSpecificValueStorage(_type); + } + } + + /** + * Checks whether indicator support given value storage type. + */ + bool HasSpecificValueStorage(ENUM_INDI_VS_TYPE _type) override { + switch (_type) { + case INDI_VS_TYPE_PRICE_ASK: + case INDI_VS_TYPE_PRICE_BID: + return true; + default: + // Trying in parent class. + return Indicator::HasSpecificValueStorage(_type); + } + } + /* Getters */ /** diff --git a/Indicators/Indi_MACD.mqh b/Indicators/Indi_MACD.mqh index 6724dfc2a..2470e2ead 100644 --- a/Indicators/Indi_MACD.mqh +++ b/Indicators/Indi_MACD.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -59,13 +59,14 @@ struct IndiMACDParams : IndicatorParams { /** * Implements the Moving Averages Convergence/Divergence indicator. */ -class Indi_MACD : public Indicator { +class Indi_MACD : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_MACD(IndiMACDParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_MACD(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_MACD, _tf, _shift) {} + Indi_MACD(IndiMACDParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_MACD(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_MACD, _tf, _shift) {} /** * Returns the indicator value. diff --git a/Indicators/Indi_MFI.mqh b/Indicators/Indi_MFI.mqh index 4a9327585..0427138c0 100644 --- a/Indicators/Indi_MFI.mqh +++ b/Indicators/Indi_MFI.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -51,13 +51,13 @@ struct IndiMFIParams : IndicatorParams { /** * Implements the Money Flow Index indicator. */ -class Indi_MFI : public Indicator { +class Indi_MFI : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_MFI(IndiMFIParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_MFI(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_MFI, _tf, _shift) {} + Indi_MFI(IndiMFIParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_MFI(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_MFI, _tf, _shift) {} /** * Calculates the Money Flow Index indicator and returns its value. diff --git a/Indicators/Indi_MassIndex.mqh b/Indicators/Indi_MassIndex.mqh index 3b4821127..b541f236e 100644 --- a/Indicators/Indi_MassIndex.mqh +++ b/Indicators/Indi_MassIndex.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.all.h" #include "Indi_MA.mqh" @@ -50,14 +50,15 @@ struct IndiMassIndexParams : IndicatorParams { /** * Implements the Bill Williams' Accelerator/Decelerator oscillator. */ -class Indi_MassIndex : public Indicator { +class Indi_MassIndex : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_MassIndex(IndiMassIndexParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src){}; - Indi_MassIndex(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_MASS_INDEX, _tf, _shift){}; + : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_MassIndex(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_MASS_INDEX, _tf, _shift){}; /** * Built-in version of Mass Index. diff --git a/Indicators/Indi_Momentum.mqh b/Indicators/Indi_Momentum.mqh index 0d461e47c..327588ed2 100644 --- a/Indicators/Indi_Momentum.mqh +++ b/Indicators/Indi_Momentum.mqh @@ -30,7 +30,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "Indi_PriceFeeder.mqh" #ifndef __MQL4__ @@ -61,14 +61,14 @@ struct IndiMomentumParams : IndicatorParams { /** * Implements the Momentum indicator. */ -class Indi_Momentum : public Indicator { +class Indi_Momentum : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_Momentum(IndiMomentumParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src) {} - Indi_Momentum(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_MOMENTUM, _tf, _shift) {} + Indi_Momentum(IndiMomentumParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_Momentum(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_MOMENTUM, _tf, _shift) {} /** * Returns the indicator value. diff --git a/Indicators/Indi_OBV.mqh b/Indicators/Indi_OBV.mqh index b904b3e52..86c6eb44a 100644 --- a/Indicators/Indi_OBV.mqh +++ b/Indicators/Indi_OBV.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -62,13 +62,13 @@ struct IndiOBVParams : IndicatorParams { /** * Implements the On Balance Volume indicator. */ -class Indi_OBV : public Indicator { +class Indi_OBV : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_OBV(IndiOBVParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_OBV(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_OBV, _tf, _shift) {} + Indi_OBV(IndiOBVParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_OBV(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_OBV, _tf, _shift) {} /** * Returns the indicator value. diff --git a/Indicators/Indi_OsMA.mqh b/Indicators/Indi_OsMA.mqh index a6930aab8..7a27cf939 100644 --- a/Indicators/Indi_OsMA.mqh +++ b/Indicators/Indi_OsMA.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -58,13 +58,14 @@ struct IndiOsMAParams : IndicatorParams { /** * Implements the Moving Average of Oscillator indicator. */ -class Indi_OsMA : public Indicator { +class Indi_OsMA : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_OsMA(IndiOsMAParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_OsMA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_OSMA, _tf, _shift) {} + Indi_OsMA(IndiOsMAParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_OsMA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_OSMA, _tf, _shift) {} /** * Returns the indicator value. diff --git a/Indicators/Indi_Pivot.mqh b/Indicators/Indi_Pivot.mqh index 6ef493d08..c4c785be6 100644 --- a/Indicators/Indi_Pivot.mqh +++ b/Indicators/Indi_Pivot.mqh @@ -44,13 +44,14 @@ struct IndiPivotParams : IndicatorParams { /** * Implements Pivot Detector. */ -class Indi_Pivot : public Indicator { +class Indi_Pivot : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_Pivot(IndiPivotParams& _p, IndicatorBase* _indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_Pivot(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_PIVOT, _tf, _shift) { + Indi_Pivot(IndiPivotParams& _p, IndicatorBase* _indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_Pivot(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_PIVOT, _tf, _shift) { iparams.tf = _tf; }; diff --git a/Indicators/Indi_PriceChannel.mqh b/Indicators/Indi_PriceChannel.mqh index afcc17ed5..97fbe41d2 100644 --- a/Indicators/Indi_PriceChannel.mqh +++ b/Indicators/Indi_PriceChannel.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "Indi_ZigZag.mqh" // Structs. @@ -45,15 +45,15 @@ struct IndiPriceChannelParams : IndicatorParams { /** * Implements Price Channel indicator. */ -class Indi_PriceChannel : public Indicator { +class Indi_PriceChannel : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_PriceChannel(IndiPriceChannelParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src){}; + : IndicatorTickOrCandleSource(_p, _indi_src){}; Indi_PriceChannel(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) - : Indicator(INDI_PRICE_CHANNEL, _tf, _shift){}; + : IndicatorTickOrCandleSource(INDI_PRICE_CHANNEL, _tf, _shift){}; /** * Returns value for Price Channel indicator. diff --git a/Indicators/Indi_PriceFeeder.mqh b/Indicators/Indi_PriceFeeder.mqh index 459c8e8df..9dfc075ea 100644 --- a/Indicators/Indi_PriceFeeder.mqh +++ b/Indicators/Indi_PriceFeeder.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" // Structs. struct IndiPriceFeederParams : IndicatorParams { @@ -53,17 +53,18 @@ struct IndiPriceFeederParams : IndicatorParams { /** * Price Indicator. */ -class Indi_PriceFeeder : public Indicator { +class Indi_PriceFeeder : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_PriceFeeder(IndiPriceFeederParams& _p, IndicatorBase* _indi_src = NULL) - : Indicator(_p, _indi_src){}; - Indi_PriceFeeder(const double& _price_data[], int _total = 0) : Indicator(INDI_PRICE_FEEDER) { + : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_PriceFeeder(const double& _price_data[], int _total = 0) : IndicatorTickOrCandleSource(INDI_PRICE_FEEDER) { ArrayCopy(iparams.price_data, _price_data); }; - Indi_PriceFeeder(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_PRICE_FEEDER, _tf, _shift) {} + Indi_PriceFeeder(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_PRICE_FEEDER, _tf, _shift) {} void SetPrices(const double& _price_data[], int _total = 0) { iparams = IndiPriceFeederParams(_price_data, _total); } diff --git a/Indicators/Indi_PriceVolumeTrend.mqh b/Indicators/Indi_PriceVolumeTrend.mqh index 35b40cdc9..9f4899142 100644 --- a/Indicators/Indi_PriceVolumeTrend.mqh +++ b/Indicators/Indi_PriceVolumeTrend.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.all.h" // Structs. @@ -45,15 +45,15 @@ struct IndiPriceVolumeTrendParams : IndicatorParams { /** * Implements the Price Volume Trend indicator. */ -class Indi_PriceVolumeTrend : public Indicator { +class Indi_PriceVolumeTrend : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_PriceVolumeTrend(IndiPriceVolumeTrendParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src){}; + : IndicatorTickOrCandleSource(_p, _indi_src){}; Indi_PriceVolumeTrend(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) - : Indicator(INDI_PRICE_VOLUME_TREND, _tf, _shift){}; + : IndicatorTickOrCandleSource(INDI_PRICE_VOLUME_TREND, _tf, _shift){}; /** * Built-in version of Price Volume Trend. diff --git a/Indicators/Indi_RS.mqh b/Indicators/Indi_RS.mqh index 29df1fecb..ef81af539 100644 --- a/Indicators/Indi_RS.mqh +++ b/Indicators/Indi_RS.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "OHLC/Indi_OHLC.mqh" #include "Special/Indi_Math.mqh" @@ -46,15 +46,17 @@ struct IndiRSParams : IndicatorParams { /** * Implements the Bill Williams' Accelerator/Decelerator oscillator. */ -class Indi_RS : public Indicator { +class Indi_RS : public IndicatorTickOrCandleSource { DictStruct> imath; public: /** * Class constructor. */ - Indi_RS(IndiRSParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) { Init(); }; - Indi_RS(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_RS, _tf, _shift) { Init(); }; + Indi_RS(IndiRSParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) { Init(); }; + Indi_RS(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_RS, _tf, _shift) { + Init(); + }; void Init() { if (iparams.GetDataSourceType() == IDATA_MATH) { diff --git a/Indicators/Indi_RSI.mqh b/Indicators/Indi_RSI.mqh index 41af38bbe..e8b725b7d 100644 --- a/Indicators/Indi_RSI.mqh +++ b/Indicators/Indi_RSI.mqh @@ -22,7 +22,7 @@ // Includes. #include "../DictStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "Indi_Bands.mqh" #include "Indi_CCI.mqh" #include "Indi_Envelopes.mqh" @@ -89,15 +89,15 @@ struct RSIGainLossData { /** * Implements the Relative Strength Index indicator. */ -class Indi_RSI : public Indicator { +class Indi_RSI : public IndicatorTickOrCandleSource { DictStruct aux_data; public: /** * Class constructor. */ - Indi_RSI(IndiRSIParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_RSI(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_RSI, _tf, _shift) {} + Indi_RSI(IndiRSIParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_RSI(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_RSI, _tf, _shift) {} /** * Returns the indicator value. diff --git a/Indicators/Indi_RVI.mqh b/Indicators/Indi_RVI.mqh index e7c7d8b39..24c2ac436 100644 --- a/Indicators/Indi_RVI.mqh +++ b/Indicators/Indi_RVI.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -50,13 +50,13 @@ struct IndiRVIParams : IndicatorParams { /** * Implements the Relative Vigor Index indicator. */ -class Indi_RVI : public Indicator { +class Indi_RVI : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_RVI(const IndiRVIParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_RVI(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_RVI, _tf, _shift) {} + Indi_RVI(const IndiRVIParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_RVI(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_RVI, _tf, _shift) {} /** * Returns the indicator value. diff --git a/Indicators/Indi_RateOfChange.mqh b/Indicators/Indi_RateOfChange.mqh index e6508ddab..2f0d5b061 100644 --- a/Indicators/Indi_RateOfChange.mqh +++ b/Indicators/Indi_RateOfChange.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.price.h" // Structs. @@ -47,15 +47,15 @@ struct IndiRateOfChangeParams : IndicatorParams { /** * Implements the Rate of Change indicator. */ -class Indi_RateOfChange : public Indicator { +class Indi_RateOfChange : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_RateOfChange(IndiRateOfChangeParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src){}; + : IndicatorTickOrCandleSource(_p, _indi_src){}; Indi_RateOfChange(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) - : Indicator(INDI_RATE_OF_CHANGE, _tf, _shift){}; + : IndicatorTickOrCandleSource(INDI_RATE_OF_CHANGE, _tf, _shift){}; /** * Built-in version of Rate of Change. diff --git a/Indicators/Indi_SAR.mqh b/Indicators/Indi_SAR.mqh index bb7acb110..6f17f2b73 100644 --- a/Indicators/Indi_SAR.mqh +++ b/Indicators/Indi_SAR.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -51,13 +51,13 @@ struct IndiSARParams : IndicatorParams { /** * Implements the Parabolic Stop and Reverse system indicator. */ -class Indi_SAR : public Indicator { +class Indi_SAR : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_SAR(IndiSARParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_SAR(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_SAR, _tf, _shift) {} + Indi_SAR(IndiSARParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_SAR(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_SAR, _tf, _shift) {} /** * Returns the indicator value. diff --git a/Indicators/Indi_StdDev.mqh b/Indicators/Indi_StdDev.mqh index 4dc2327eb..7a6305b77 100644 --- a/Indicators/Indi_StdDev.mqh +++ b/Indicators/Indi_StdDev.mqh @@ -28,7 +28,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickSource.h" #include "../Storage/ObjectsCache.h" #include "Indi_MA.mqh" #include "Indi_PriceFeeder.mqh" @@ -73,13 +73,13 @@ struct IndiStdDevParams : IndicatorParams { /** * Implements the Standard Deviation indicator. */ -class Indi_StdDev : public Indicator { +class Indi_StdDev : public IndicatorTickSource { public: /** * Class constructor. */ - Indi_StdDev(IndiStdDevParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_StdDev(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_STDDEV, _tf, _shift) {} + Indi_StdDev(IndiStdDevParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickSource(_p, _indi_src) {} + Indi_StdDev(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickSource(INDI_STDDEV, _tf, _shift) {} /** * Calculates the Standard Deviation indicator and returns its value. diff --git a/Indicators/Indi_Stochastic.mqh b/Indicators/Indi_Stochastic.mqh index 95384d8ae..453208b27 100644 --- a/Indicators/Indi_Stochastic.mqh +++ b/Indicators/Indi_Stochastic.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -62,13 +62,14 @@ struct IndiStochParams : IndicatorParams { /** * Implements the Stochastic Oscillator. */ -class Indi_Stochastic : public Indicator { +class Indi_Stochastic : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_Stochastic(IndiStochParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_Stochastic(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_STOCHASTIC, _tf, _shift) {} + Indi_Stochastic(IndiStochParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_Stochastic(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_STOCHASTIC, _tf, _shift) {} /** * Calculates the Stochastic Oscillator and returns its value. diff --git a/Indicators/Indi_TEMA.mqh b/Indicators/Indi_TEMA.mqh index 5ac6bbb6c..5954a9804 100644 --- a/Indicators/Indi_TEMA.mqh +++ b/Indicators/Indi_TEMA.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.price.h" #include "Indi_MA.mqh" @@ -50,13 +50,14 @@ struct IndiTEMAParams : IndicatorParams { /** * Implements the Triple Exponential Moving Average indicator. */ -class Indi_TEMA : public Indicator { +class Indi_TEMA : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_TEMA(IndiTEMAParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_TEMA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_TEMA, _tf, _shift){}; + Indi_TEMA(IndiTEMAParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_TEMA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_TEMA, _tf, _shift){}; /** * Built-in version of TEMA. diff --git a/Indicators/Indi_TRIX.mqh b/Indicators/Indi_TRIX.mqh index e480701b7..86caabb0d 100644 --- a/Indicators/Indi_TRIX.mqh +++ b/Indicators/Indi_TRIX.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.price.h" #include "Indi_MA.mqh" @@ -49,13 +49,14 @@ struct IndiTRIXParams : IndicatorParams { /** * Implements the Triple Exponential Average indicator. */ -class Indi_TRIX : public Indicator { +class Indi_TRIX : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_TRIX(IndiTRIXParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_TRIX(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_TRIX, _tf, _shift){}; + Indi_TRIX(IndiTRIXParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_TRIX(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_TRIX, _tf, _shift){}; /** * Built-in version of TriX. diff --git a/Indicators/Indi_UltimateOscillator.mqh b/Indicators/Indi_UltimateOscillator.mqh index ff63857d4..98a7f9e1f 100644 --- a/Indicators/Indi_UltimateOscillator.mqh +++ b/Indicators/Indi_UltimateOscillator.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.all.h" #include "Indi_ATR.mqh" #include "Indi_MA.mqh" @@ -62,15 +62,15 @@ struct IndiUltimateOscillatorParams : IndicatorParams { /** * Implements the Bill Williams' Accelerator/Decelerator oscillator. */ -class Indi_UltimateOscillator : public Indicator { +class Indi_UltimateOscillator : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_UltimateOscillator(IndiUltimateOscillatorParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src){}; + : IndicatorTickOrCandleSource(_p, _indi_src){}; Indi_UltimateOscillator(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) - : Indicator(INDI_ULTIMATE_OSCILLATOR, _tf, _shift){}; + : IndicatorTickOrCandleSource(INDI_ULTIMATE_OSCILLATOR, _tf, _shift){}; /** * Built-in version of Ultimate Oscillator. diff --git a/Indicators/Indi_VIDYA.mqh b/Indicators/Indi_VIDYA.mqh index 8499e9b32..4e98a6254 100644 --- a/Indicators/Indi_VIDYA.mqh +++ b/Indicators/Indi_VIDYA.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.price.h" // Structs. @@ -53,13 +53,14 @@ struct IndiVIDYAParams : IndicatorParams { /** * Implements the Variable Index Dynamic Average indicator. */ -class Indi_VIDYA : public Indicator { +class Indi_VIDYA : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_VIDYA(IndiVIDYAParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_VIDYA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_VIDYA, _tf, _shift){}; + Indi_VIDYA(IndiVIDYAParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_VIDYA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_VIDYA, _tf, _shift){}; /** * Built-in version of iVIDyA. diff --git a/Indicators/Indi_VROC.mqh b/Indicators/Indi_VROC.mqh index 439e009fe..cacf2861c 100644 --- a/Indicators/Indi_VROC.mqh +++ b/Indicators/Indi_VROC.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.all.h" // Structs. @@ -47,13 +47,14 @@ struct IndiVROCParams : IndicatorParams { /** * Implements the Volume Rate of Change indicator. */ -class Indi_VROC : public Indicator { +class Indi_VROC : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_VROC(IndiVROCParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_VROC(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_VROC, _tf, _shift){}; + Indi_VROC(IndiVROCParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_VROC(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_VROC, _tf, _shift){}; /** * Built-in version of VROC. diff --git a/Indicators/Indi_Volumes.mqh b/Indicators/Indi_Volumes.mqh index 1f5333b93..c46671424 100644 --- a/Indicators/Indi_Volumes.mqh +++ b/Indicators/Indi_Volumes.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.all.h" // Structs. @@ -46,13 +46,14 @@ struct IndiVolumesParams : IndicatorParams { /** * Implements the Volumes indicator. */ -class Indi_Volumes : public Indicator { +class Indi_Volumes : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_Volumes(IndiVolumesParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_Volumes(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_VOLUMES, _tf, _shift){}; + Indi_Volumes(IndiVolumesParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_Volumes(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_VOLUMES, _tf, _shift){}; /** * Built-in version of Volumes. diff --git a/Indicators/Indi_WPR.mqh b/Indicators/Indi_WPR.mqh index 1504f2ecf..98c59474c 100644 --- a/Indicators/Indi_WPR.mqh +++ b/Indicators/Indi_WPR.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). @@ -50,13 +50,13 @@ struct IndiWPRParams : IndicatorParams { /** * Implements the Larry Williams' Percent Range. */ -class Indi_WPR : public Indicator { +class Indi_WPR : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_WPR(IndiWPRParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_WPR(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_WPR, _tf, _shift) {} + Indi_WPR(IndiWPRParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_WPR(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_WPR, _tf, _shift) {} /** * Calculates the Larry Williams' Percent Range and returns its value. diff --git a/Indicators/Indi_WilliamsAD.mqh b/Indicators/Indi_WilliamsAD.mqh index cf1a6513f..7e2bf94e4 100644 --- a/Indicators/Indi_WilliamsAD.mqh +++ b/Indicators/Indi_WilliamsAD.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.all.h" // Structs. @@ -42,14 +42,15 @@ struct IndiWilliamsADParams : IndicatorParams { /** * Implements the Volume Rate of Change indicator. */ -class Indi_WilliamsAD : public Indicator { +class Indi_WilliamsAD : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_WilliamsAD(IndiWilliamsADParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src){}; - Indi_WilliamsAD(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_WILLIAMS_AD, _tf, _shift){}; + : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_WilliamsAD(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_WILLIAMS_AD, _tf, _shift){}; /** * Built-in version of Williams' AD. diff --git a/Indicators/Indi_ZigZag.mqh b/Indicators/Indi_ZigZag.mqh index 912eb8eff..4803a45e6 100644 --- a/Indicators/Indi_ZigZag.mqh +++ b/Indicators/Indi_ZigZag.mqh @@ -21,7 +21,7 @@ */ // Includes. -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.all.h" // Enums. @@ -58,13 +58,14 @@ enum EnSearchMode { /** * Implements ZigZag indicator. */ -class Indi_ZigZag : public Indicator { +class Indi_ZigZag : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_ZigZag(IndiZigZagParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_ZigZag(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_ZIGZAG, _tf, _shift) {} + Indi_ZigZag(IndiZigZagParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_ZigZag(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_ZIGZAG, _tf, _shift) {} /** * Returns value for ZigZag indicator. diff --git a/Indicators/Indi_ZigZagColor.mqh b/Indicators/Indi_ZigZagColor.mqh index af74e2f50..6e8cf6d9a 100644 --- a/Indicators/Indi_ZigZagColor.mqh +++ b/Indicators/Indi_ZigZagColor.mqh @@ -22,7 +22,7 @@ // Includes. #include "../BufferStruct.mqh" -#include "../Indicator.mqh" +#include "../Indicator/IndicatorTickOrCandleSource.h" #include "../Storage/ValueStorage.all.h" #include "Indi_ZigZag.mqh" @@ -52,14 +52,15 @@ struct IndiZigZagColorParams : IndicatorParams { /** * Implements the Volume Rate of Change indicator. */ -class Indi_ZigZagColor : public Indicator { +class Indi_ZigZagColor : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ Indi_ZigZagColor(IndiZigZagColorParams &_p, IndicatorBase *_indi_src = NULL) - : Indicator(_p, _indi_src){}; - Indi_ZigZagColor(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_VROC, _tf, _shift){}; + : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_ZigZagColor(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_VROC, _tf, _shift){}; /** * Returns value for ZigZag Color indicator. diff --git a/Indicators/OHLC/Indi_OHLC.mqh b/Indicators/OHLC/Indi_OHLC.mqh index c6c3d39ef..c7f9cc25c 100644 --- a/Indicators/OHLC/Indi_OHLC.mqh +++ b/Indicators/OHLC/Indi_OHLC.mqh @@ -22,7 +22,7 @@ // Includes. #include "../../BufferStruct.mqh" -#include "../../Indicator.mqh" +#include "../../Indicator/IndicatorTickOrCandleSource.h" #include "../../Storage/Objects.h" // Enums. @@ -49,13 +49,14 @@ struct IndiOHLCParams : IndicatorParams { /** * OHLC Indicator. */ -class Indi_OHLC : public Indicator { +class Indi_OHLC : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_OHLC(IndiOHLCParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_OHLC(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_PRICE, _tf, _shift){}; + Indi_OHLC(IndiOHLCParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_OHLC(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_PRICE, _tf, _shift){}; /** * Returns the indicator's value. diff --git a/Indicators/Price/Indi_Price.mqh b/Indicators/Price/Indi_Price.mqh index 89b0f7279..b0cbcc6d3 100644 --- a/Indicators/Price/Indi_Price.mqh +++ b/Indicators/Price/Indi_Price.mqh @@ -22,7 +22,7 @@ // Includes. #include "../../BufferStruct.mqh" -#include "../../Indicator.mqh" +#include "../../Indicator/IndicatorTickOrCandleSource.h" #include "../../Storage/Objects.h" // Structs. @@ -46,13 +46,14 @@ struct PriceIndiParams : IndicatorParams { /** * Price Indicator. */ -class Indi_Price : public Indicator { +class Indi_Price : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_Price(PriceIndiParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_Price(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_PRICE, _tf, _shift){}; + Indi_Price(PriceIndiParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_Price(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_PRICE, _tf, _shift){}; /** * Checks whether indicator has a valid value for a given shift. @@ -86,4 +87,54 @@ class Indi_Price : public Indicator { } return _indi_price; } + + /** + * 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_PRICE_ASK: // Tick. + case INDI_VS_TYPE_PRICE_BID: // Tick. + return GetCached(GetSymbol(), iparams.GetAppliedPrice(), GetTf(), iparams.GetShift()).GetValueStorage(0); + case INDI_VS_TYPE_PRICE_OPEN: // Candle. + return GetCached(GetSymbol(), PRICE_OPEN, GetTf(), iparams.GetShift()).GetValueStorage(0); + case INDI_VS_TYPE_PRICE_HIGH: // Candle. + return GetCached(GetSymbol(), PRICE_HIGH, GetTf(), iparams.GetShift()).GetValueStorage(0); + case INDI_VS_TYPE_PRICE_LOW: // Candle. + return GetCached(GetSymbol(), PRICE_LOW, GetTf(), iparams.GetShift()).GetValueStorage(0); + case INDI_VS_TYPE_PRICE_CLOSE: // Candle. + return GetCached(GetSymbol(), PRICE_CLOSE, GetTf(), iparams.GetShift()).GetValueStorage(0); + case INDI_VS_TYPE_PRICE_MEDIAN: // Candle. + return GetCached(GetSymbol(), PRICE_MEDIAN, GetTf(), iparams.GetShift()).GetValueStorage(0); + case INDI_VS_TYPE_PRICE_TYPICAL: // Candle. + return GetCached(GetSymbol(), PRICE_TYPICAL, GetTf(), iparams.GetShift()).GetValueStorage(0); + case INDI_VS_TYPE_PRICE_WEIGHTED: // Candle. + return GetCached(GetSymbol(), PRICE_WEIGHTED, GetTf(), iparams.GetShift()).GetValueStorage(0); + default: + // Trying in parent class. + return Indicator::GetSpecificValueStorage(_type); + } + } + + /** + * Checks whether indicator support given value storage type. + */ + bool HasSpecificValueStorage(ENUM_INDI_VS_TYPE _type) override { + switch (_type) { + case INDI_VS_TYPE_PRICE_ASK: // Tick. + case INDI_VS_TYPE_PRICE_BID: // Tick. + case INDI_VS_TYPE_PRICE_OPEN: // Candle. + case INDI_VS_TYPE_PRICE_HIGH: // Candle. + case INDI_VS_TYPE_PRICE_LOW: // Candle. + case INDI_VS_TYPE_PRICE_CLOSE: // Candle. + case INDI_VS_TYPE_PRICE_MEDIAN: // Candle. + case INDI_VS_TYPE_PRICE_TYPICAL: // Candle. + case INDI_VS_TYPE_PRICE_WEIGHTED: // Candle. + return true; + default: + // Trying in parent class. + return Indicator::HasSpecificValueStorage(_type); + } + } }; diff --git a/Indicators/Special/Indi_Math.mqh b/Indicators/Special/Indi_Math.mqh index e1c991916..eaacecca5 100644 --- a/Indicators/Special/Indi_Math.mqh +++ b/Indicators/Special/Indi_Math.mqh @@ -22,7 +22,7 @@ // Includes. #include "../../BufferStruct.mqh" -#include "../../Indicator.mqh" +#include "../../Indicator/IndicatorTickOrCandleSource.h" #include "../../Math.enum.h" enum ENUM_MATH_OP_MODE { MATH_OP_MODE_BUILTIN, MATH_OP_MODE_CUSTOM_FUNCTION }; @@ -82,13 +82,14 @@ struct IndiMathParams : IndicatorParams { /** * Implements the Volume Rate of Change indicator. */ -class Indi_Math : public Indicator { +class Indi_Math : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_Math(IndiMathParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src){}; - Indi_Math(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : Indicator(INDI_SPECIAL_MATH, _tf, _shift){}; + Indi_Math(IndiMathParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_Math(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_SPECIAL_MATH, _tf, _shift){}; /** * Returns the indicator's value. diff --git a/tests/IndicatorsTest.mq5 b/tests/IndicatorsTest.mq5 index 918c3e734..c23ca7cf5 100644 --- a/tests/IndicatorsTest.mq5 +++ b/tests/IndicatorsTest.mq5 @@ -334,7 +334,7 @@ bool InitIndicators() { stddev_params_on_ma_sma.SetDraw(true, 1); Ref indi_stddev_on_ma_sma = new Indi_StdDev(stddev_params_on_ma_sma); - indi_stddev_on_ma_sma.Ptr().SetDataSource(indi_ma_sma_for_stddev.Ptr(), 0); + indi_stddev_on_ma_sma.Ptr().SetDataSource(indi_ma_sma_for_stddev.Ptr()); indis.Push(indi_stddev_on_ma_sma.Ptr()); // Standard Deviation (StdDev) in SMA mode over Price. From c5be80f23f5fc475f2875ebb18b806bd5c232e6a Mon Sep 17 00:00:00 2001 From: Adrian Kierzkowski Date: Wed, 29 Dec 2021 19:03:22 +0100 Subject: [PATCH 39/77] WIP. Closer to the end. Now we need to find a way to feed indicator with ticks from data source, e.g., to feed AMA from Tick/Candle indicator when they ticks and provides new ask/bid prices. --- Chart.enum.h | 5 ++ Indicator/IndicatorCandle.h | 1 + Indicator/IndicatorTick.h | 46 +++++++++++++-- Indicator/IndicatorTickOrCandleSource.h | 9 --- Indicator/IndicatorTickSource.h | 2 +- Indicator/tests/classes/IndicatorTickReal.h | 6 +- IndicatorBase.h | 62 ++++++++++++++++++++- Indicators/Indi_AMA.mqh | 12 +++- Storage/ValueStorage.h | 10 +++- tests/IndicatorsTest.mq5 | 5 +- 10 files changed, 135 insertions(+), 23 deletions(-) diff --git a/Chart.enum.h b/Chart.enum.h index e7e68247c..5835ba3da 100644 --- a/Chart.enum.h +++ b/Chart.enum.h @@ -43,9 +43,14 @@ enum ENUM_APPLIED_PRICE { PRICE_MEDIAN, // Median price (H+L)/2 PRICE_TYPICAL, // Typical price, (H+L+C)/3 PRICE_WEIGHTED, // Weighted close price (H+L+C+C)/4 + FINAL_APPLIED_PRICE_ENTRY }; #endif +// Additional modes for applied price. +#define PRICE_ASK ((ENUM_APPLIED_PRICE)128) +#define PRICE_BID ((ENUM_APPLIED_PRICE)129) + // Defines enumeration for chart parameters. enum ENUM_CHART_PARAM { CHART_PARAM_NONE = 0, // None diff --git a/Indicator/IndicatorCandle.h b/Indicator/IndicatorCandle.h index 29c4fbd2e..6d5711a31 100644 --- a/Indicator/IndicatorCandle.h +++ b/Indicator/IndicatorCandle.h @@ -33,6 +33,7 @@ #include "../Buffer/BufferCandle.h" #include "../Indicator.mqh" +// Indicator modes. enum ENUM_INDI_CANDLE_MODE { INDI_CANDLE_MODE_PRICE_OPEN, INDI_CANDLE_MODE_PRICE_HIGH, diff --git a/Indicator/IndicatorTick.h b/Indicator/IndicatorTick.h index c5ad92d86..b29a8070b 100644 --- a/Indicator/IndicatorTick.h +++ b/Indicator/IndicatorTick.h @@ -33,11 +33,18 @@ #include "../Buffer/BufferTick.h" #include "../IndicatorBase.h" +// Indicator modes. +enum ENUM_INDI_TICK_MODE { + INDI_TICK_MODE_PRICE_ASK, + INDI_TICK_MODE_PRICE_BID, + FINAL_INDI_TICK_MODE_ENTRY, +}; + /** * Class to deal with tick indicators. */ template -class IndicatorTick : public IndicatorBase { +class IndicatorTick : public Indicator { protected: BufferTick itdata; TS itparams; @@ -63,21 +70,50 @@ class IndicatorTick : public IndicatorBase { /** * Class constructor. */ - IndicatorTick(const TS& _itparams, IndicatorBase* _indi_src = NULL, int _indi_mode = 0) { + IndicatorTick(const TS& _itparams, IndicatorBase* _indi_src = NULL, int _indi_mode = 0) + : Indicator(_itparams, _indi_src, _indi_mode) { itparams = _itparams; if (_indi_src != NULL) { SetDataSource(_indi_src, _indi_mode); } Init(); } - IndicatorTick(ENUM_INDICATOR_TYPE _itype, string _symbol, int _shift = 0, string _name = "") { - itparams.SetIndicatorType(_itype); - itparams.SetShift(_shift); + IndicatorTick(ENUM_INDICATOR_TYPE _itype = INDI_CANDLE, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0, + string _name = "") + : Indicator(_itype, _tf, _shift, _name) { Init(); } /* Virtual method implementations */ + /** + * Returns value storage of given kind. + */ + IValueStorage* GetSpecificValueStorage(ENUM_INDI_VS_TYPE _type) override { + switch (_type) { + case INDI_VS_TYPE_PRICE_ASK: + return GetValueStorage(INDI_TICK_MODE_PRICE_ASK); + case INDI_VS_TYPE_PRICE_BID: + return GetValueStorage(INDI_TICK_MODE_PRICE_BID); + default: + // Trying in parent class. + return Indicator::GetSpecificValueStorage(_type); + } + } + + /** + * Checks whether indicator support given value storage type. + */ + virtual bool HasSpecificValueStorage(ENUM_INDI_VS_TYPE _type) { + switch (_type) { + case INDI_VS_TYPE_PRICE_ASK: + case INDI_VS_TYPE_PRICE_BID: + return true; + } + + return Indicator::HasSpecificValueStorage(_type); + } + /** * Sends historic entries to listening indicators. May be overriden. */ diff --git a/Indicator/IndicatorTickOrCandleSource.h b/Indicator/IndicatorTickOrCandleSource.h index b7bc25265..a4e0f902f 100644 --- a/Indicator/IndicatorTickOrCandleSource.h +++ b/Indicator/IndicatorTickOrCandleSource.h @@ -60,13 +60,4 @@ class IndicatorTickOrCandleSource : public Indicator { // @todo Make use of this method. return true; } - - /** - * Called if data source is requested, but wasn't yet set. May be used to initialize indicators that must operate on - * some data source. - */ - IndicatorBase* OnDataSourceRequest() override { - // Defaulting to platform ticks. - return new IndicatorTickReal(GetSymbol(), GetTf(), "AMA on IndicatorTickReal"); - } }; diff --git a/Indicator/IndicatorTickSource.h b/Indicator/IndicatorTickSource.h index 58800c0b8..2780498f9 100644 --- a/Indicator/IndicatorTickSource.h +++ b/Indicator/IndicatorTickSource.h @@ -123,6 +123,6 @@ class IndicatorTickSource : public Indicator { */ IndicatorBase* OnDataSourceRequest() override { // Defaulting to platform ticks. - return new IndicatorTickReal(GetSymbol(), GetTf(), "AMA on IndicatorTickReal"); + return new IndicatorTickReal(GetTf(), 0, "AMA on IndicatorTickReal"); } }; diff --git a/Indicator/tests/classes/IndicatorTickReal.h b/Indicator/tests/classes/IndicatorTickReal.h index a654c4da8..977c5cc48 100644 --- a/Indicator/tests/classes/IndicatorTickReal.h +++ b/Indicator/tests/classes/IndicatorTickReal.h @@ -41,10 +41,8 @@ struct IndicatorTickRealParams : IndicatorParams { // Real tick-based indicator. class IndicatorTickReal : public IndicatorTick { public: - IndicatorTickReal(string _symbol, int _shift = 0, string _name = "") - : IndicatorTick(INDI_TICK, _symbol, _shift, _name) { - SetSymbol(_symbol); - } + IndicatorTickReal(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0, string _name = "") + : IndicatorTick(INDI_TICK, _tf, _shift, _name) {} string GetName() override { return "IndicatorTickReal"; } diff --git a/IndicatorBase.h b/IndicatorBase.h index f0b0e4677..2c734290d 100644 --- a/IndicatorBase.h +++ b/IndicatorBase.h @@ -303,7 +303,37 @@ class IndicatorBase : public Chart { * Called if data source is requested, but wasn't yet set. May be used to initialize indicators that must operate on * some data source. */ - virtual IndicatorBase* OnDataSourceRequest() { return NULL; } + virtual IndicatorBase* OnDataSourceRequest() { + Print("In order to use IDATA_INDICATOR mode for indicator ", GetFullName(), + " 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; + } + + /** + * Creates default, tick based indicator for given applied price. + */ + IndicatorBase* DataSourceRequestReturnDefault(int _applied_price) { + // Returning real candle indicator. Thus way we can use SetAppliedPrice() and select Ask or Bid price. + switch (_applied_price) { + case PRICE_ASK: + case PRICE_BID: + return new IndicatorTickReal(GetTf()); + case PRICE_OPEN: + case PRICE_HIGH: + case PRICE_LOW: + case PRICE_CLOSE: + case PRICE_MEDIAN: + case PRICE_TYPICAL: + case PRICE_WEIGHTED: + return new IndicatorTfDummy(GetTf()); + } + + Print("Passed wrong value for applied price for ", GetFullName(), " indicator!"); + DebugBreak(); + return NULL; + } /* Getters */ @@ -464,6 +494,10 @@ class IndicatorBase : public Chart { virtual IValueStorage* GetSpecificAppliedPriceValueStorage(ENUM_APPLIED_PRICE _ap) { switch (_ap) { + case PRICE_ASK: + return GetSpecificValueStorage(INDI_VS_TYPE_PRICE_ASK); + case PRICE_BID: + return GetSpecificValueStorage(INDI_VS_TYPE_PRICE_BID); case PRICE_OPEN: return GetSpecificValueStorage(INDI_VS_TYPE_PRICE_OPEN); case PRICE_HIGH: @@ -484,6 +518,32 @@ class IndicatorBase : public Chart { } } + virtual bool HasSpecificAppliedPriceValueStorage(ENUM_APPLIED_PRICE _ap) { + switch (_ap) { + case PRICE_ASK: + return HasSpecificValueStorage(INDI_VS_TYPE_PRICE_ASK); + case PRICE_BID: + return HasSpecificValueStorage(INDI_VS_TYPE_PRICE_BID); + case PRICE_OPEN: + return HasSpecificValueStorage(INDI_VS_TYPE_PRICE_OPEN); + case PRICE_HIGH: + return HasSpecificValueStorage(INDI_VS_TYPE_PRICE_HIGH); + case PRICE_LOW: + return HasSpecificValueStorage(INDI_VS_TYPE_PRICE_LOW); + case PRICE_CLOSE: + return HasSpecificValueStorage(INDI_VS_TYPE_PRICE_CLOSE); + case PRICE_MEDIAN: + case PRICE_TYPICAL: + case PRICE_WEIGHTED: + default: + Print("Error: Invalid applied price " + EnumToString(_ap) + + ", only PRICE_(OPEN|HIGH|LOW|CLOSE) are currently supported by " + "IndicatorBase::HasSpecificAppliedPriceValueStorage()!"); + DebugBreak(); + return false; + } + } + /** * Checks whether indicator support given value storage type. */ diff --git a/Indicators/Indi_AMA.mqh b/Indicators/Indi_AMA.mqh index 206c2cb77..819ee824f 100644 --- a/Indicators/Indi_AMA.mqh +++ b/Indicators/Indi_AMA.mqh @@ -23,6 +23,7 @@ // Includes. #include "../BufferStruct.mqh" #include "../Indicator/IndicatorTickOrCandleSource.h" +#include "../Indicator/tests/classes/IndicatorTfDummy.h" #include "../Storage/ValueStorage.h" #include "../Storage/ValueStorage.price.h" #include "Price/Indi_Price.mqh" @@ -244,7 +245,16 @@ class Indi_AMA : public IndicatorTickOrCandleSource { /** * Called when data source emits new entry (historic or future one). */ - void OnDataSourceEntry(IndicatorDataEntry &entry) override { Print("New entry for AMA!"); }; + void OnDataSourceEntry(IndicatorDataEntry &entry) override { + // Just to be able to make a breakpoint here. + int x = 4; + }; + + /** + * Called if data source is requested, but wasn't yet set. May be used to initialize indicators that must operate on + * some data source. + */ + virtual IndicatorBase *OnDataSourceRequest() { return DataSourceRequestReturnDefault(GetAppliedPrice()); } /* Getters */ diff --git a/Storage/ValueStorage.h b/Storage/ValueStorage.h index ea2730712..36efe0049 100644 --- a/Storage/ValueStorage.h +++ b/Storage/ValueStorage.h @@ -92,7 +92,15 @@ enum ENUM_IPEAK { IPEAK_LOWEST, IPEAK_HIGHEST }; INDICATOR_CALCULATE_POPULATE_CACHE(SYMBOL, TF, KEY) #define INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_SHORT_DS_SPECIFIC(INDI, SYMBOL, TF, APPLIED_PRICE, KEY) \ - ValueStorage *_price = INDI.GetSpecificAppliedPriceValueStorage(APPLIED_PRICE); \ + ValueStorage *_price; \ + if (_indi.HasSpecificAppliedPriceValueStorage(APPLIED_PRICE)) { \ + _price = INDI.GetSpecificAppliedPriceValueStorage(APPLIED_PRICE); \ + } else { \ + Print("Source indicator ", INDI.GetFullName(), \ + " cannot be used as it doesn't provide a single buffer to be used by target indicator!"); \ + DebugBreak(); \ + } \ + \ INDICATOR_CALCULATE_POPULATE_CACHE(SYMBOL, TF, KEY) #define INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS(INDI, SYMBOL, TF, KEY) \ diff --git a/tests/IndicatorsTest.mq5 b/tests/IndicatorsTest.mq5 index c23ca7cf5..0120c35ea 100644 --- a/tests/IndicatorsTest.mq5 +++ b/tests/IndicatorsTest.mq5 @@ -423,7 +423,10 @@ bool InitIndicators() { // AMA. IndiAMAParams ama_params(); ama_params.SetDataSourceType(IDATA_INDICATOR); - indis.Push(new Indi_AMA(ama_params)); + Indi_AMA* _indi_ama = new Indi_AMA(ama_params); + // AMA will automatically sets its data source to Tick or Candle indicator by value of APPLIED_PRICE. + _indi_ama.SetAppliedPrice(PRICE_ASK); + indis.Push(_indi_ama); // Original AMA. IndiAMAParams ama_params_orig(); From 88d0a7c3779b83c93590812998fe4dbb495c37b7 Mon Sep 17 00:00:00 2001 From: Adrian Kierzkowski Date: Thu, 30 Dec 2021 20:57:42 +0100 Subject: [PATCH 40/77] WIP. Now we need to find a way to make BufferTick to provide continuous ticks, instead of random ones collected in DictStruct. --- Buffer/BufferTick.h | 77 ++++++++++++++++++++++++- Indicator/IndicatorTick.h | 6 +- Indicator/IndicatorTickOrCandleSource.h | 7 +++ IndicatorBase.h | 6 +- 4 files changed, 87 insertions(+), 9 deletions(-) diff --git a/Buffer/BufferTick.h b/Buffer/BufferTick.h index 70965dcfe..bc8f2fa4e 100644 --- a/Buffer/BufferTick.h +++ b/Buffer/BufferTick.h @@ -26,14 +26,51 @@ // Includes. #include "../BufferStruct.mqh" +#include "../Storage/IValueStorage.h" #include "../Tick.struct.h" +template +class BufferTickValueStorage : ValueStorage { + // Poiner to buffer to take tick from. + BufferTick *buffer_tick; + + // PRICE_ASK or PRICE_BID. + int applied_price; + + public: + /** + * Constructor. + */ + BufferTickValueStorage(BufferTick *_buffer_tick, int _applied_price) + : buffer_tick(_buffer_tick), applied_price(_applied_price) {} + + /** + * Fetches value from a given shift. Takes into consideration as-series flag. + */ + TV Fetch(int _shift) override { + Print("BufferTickValueStorage: Fetching " + (applied_price == PRICE_ASK ? "Ask" : "Bid") + " price from shift ", + _shift); + return 0; + } + + /** + * Returns number of values available to fetch (size of the values buffer). + */ + int Size() const override { return (int)buffer_tick.Size(); } +}; + /** * Class to store struct data. */ template class BufferTick : public BufferStruct> { protected: + // Ask prices ValueStorage proxy. + BufferTickValueStorage *_vs_ask; + + // Bid prices ValueStorage proxy. + BufferTickValueStorage *_vs_bid; + protected: /* Protected methods */ @@ -42,7 +79,11 @@ class BufferTick : public BufferStruct> { * * Called on constructor. */ - void Init() { SetOverflowListener(BufferTickOverflowListener, 10); } + void Init() { + _vs_ask = NULL; + _vs_bid = NULL; + SetOverflowListener(BufferTickOverflowListener, 10); + } public: /* Constructors */ @@ -51,11 +92,43 @@ class BufferTick : public BufferStruct> { * Constructor. */ BufferTick() { Init(); } - BufferTick(BufferTick& _right) { + BufferTick(BufferTick &_right) { THIS_REF = _right; Init(); } + /** + * Destructor. + */ + ~BufferTick() { + if (_vs_ask != NULL) { + delete _vs_ask; + } + if (_vs_bid != NULL) { + delete _vs_bid; + } + } + + /** + * Returns Ask prices ValueStorage proxy. + */ + BufferTickValueStorage *GetAskValueStorage() { + if (_vs_ask == NULL) { + _vs_ask = new BufferTickValueStorage(THIS_PTR, PRICE_ASK); + } + return _vs_ask; + } + + /** + * Returns Bid prices ValueStorage proxy. + */ + BufferTickValueStorage *GetBidValueStorage() { + if (_vs_bid == NULL) { + _vs_bid = new BufferTickValueStorage(THIS_PTR, PRICE_BID); + } + return _vs_bid; + } + /* Grouping methods */ /** diff --git a/Indicator/IndicatorTick.h b/Indicator/IndicatorTick.h index b29a8070b..34c6564a9 100644 --- a/Indicator/IndicatorTick.h +++ b/Indicator/IndicatorTick.h @@ -84,17 +84,15 @@ class IndicatorTick : public Indicator { Init(); } - /* Virtual method implementations */ - /** * Returns value storage of given kind. */ IValueStorage* GetSpecificValueStorage(ENUM_INDI_VS_TYPE _type) override { switch (_type) { case INDI_VS_TYPE_PRICE_ASK: - return GetValueStorage(INDI_TICK_MODE_PRICE_ASK); + return (IValueStorage*)itdata.GetAskValueStorage(); case INDI_VS_TYPE_PRICE_BID: - return GetValueStorage(INDI_TICK_MODE_PRICE_BID); + return (IValueStorage*)itdata.GetBidValueStorage(); default: // Trying in parent class. return Indicator::GetSpecificValueStorage(_type); diff --git a/Indicator/IndicatorTickOrCandleSource.h b/Indicator/IndicatorTickOrCandleSource.h index a4e0f902f..89cebebe4 100644 --- a/Indicator/IndicatorTickOrCandleSource.h +++ b/Indicator/IndicatorTickOrCandleSource.h @@ -60,4 +60,11 @@ class IndicatorTickOrCandleSource : public Indicator { // @todo Make use of this method. return true; } + + /** + * Called when data source emits new entry (historic or future one). + */ + void OnDataSourceEntry(IndicatorDataEntry& entry) override{ + // We do nothing. + }; }; diff --git a/IndicatorBase.h b/IndicatorBase.h index 2c734290d..a57ff5bcd 100644 --- a/IndicatorBase.h +++ b/IndicatorBase.h @@ -604,9 +604,6 @@ class IndicatorBase : public Chart { last_tick_time = _current_time; - // Overridable OnTick() method. - OnTick(); - // Checking and potentially initializing new data source. if (HasDataSource(true) != NULL) { // Ticking data source if not yet ticked. @@ -617,6 +614,9 @@ class IndicatorBase : public Chart { for (DictStructIterator> iter = indicators.Begin(); iter.IsValid(); ++iter) { iter.Value().Ptr().Tick(); } + + // Overridable OnTick() method. + OnTick(); } virtual void OnTick() {} From c2a87cde54a57ccd48d181b7882403de3b491947 Mon Sep 17 00:00:00 2001 From: Adrian Kierzkowski Date: Tue, 4 Jan 2022 16:11:48 +0100 Subject: [PATCH 41/77] AS-IS. --- Indicator.enum.h | 8 +++++++ Indicator.mqh | 13 +++++++++++ Indicator/IndicatorCandle.h | 2 ++ Indicator/IndicatorTick.h | 5 ++++ IndicatorBase.h | 46 +++++++++++++++++++++++++++++++++---- 5 files changed, 70 insertions(+), 4 deletions(-) diff --git a/Indicator.enum.h b/Indicator.enum.h index 563282745..872c6ceb1 100644 --- a/Indicator.enum.h +++ b/Indicator.enum.h @@ -248,3 +248,11 @@ enum ENUM_INDI_VS_TYPE { INDI_VS_TYPE_PRICE_BID, // Tick. INDI_VS_TYPE_PRICE_ASK, // Tick. }; + +// Indicator flags. +enum ENUM_INDI_FLAGS { + INDI_FLAG_INDEXABLE_BY_SHIFT, // Indicator supports indexation by shift. + INDI_FLAG_INDEXABLE_BY_TIMESTAMP, // Indicator supports indexation by shift. + INDI_FLAG_SOURCE_REQ_INDEXABLE_BY_SHIFT, // Source indicator must be indexable by shift. + INDI_FLAG_SOURCE_REQ_INDEXABLE_BY_TIMESTAMP // Source indicator must be indexable by timestamp. +}; \ No newline at end of file diff --git a/Indicator.mqh b/Indicator.mqh index 8687a702c..47089083c 100644 --- a/Indicator.mqh +++ b/Indicator.mqh @@ -981,6 +981,19 @@ class Indicator : public IndicatorBase { * Sets indicator data source. */ void SetDataSource(IndicatorBase* _indi, int _input_mode = -1) override { + if (indi_src.IsSet()) { + if (bool(flags | INDI_FLAG_SOURCE_REQ_INDEXABLE_BY_SHIFT) && !bool(_indi.flags | INDI_FLAG_INDEXABLE_BY_SHIFT)) { + Print(GetFullName(), ": Cannot set data source to ", _indi.GetFullName(), ", because source indicator isn't indexable by shift!"); + DebugBreak(); + return; + } + if (bool(flags | INDI_FLAG_SOURCE_REQ_INDEXABLE_BY_TIMESTAMP) && !bool(_indi.flags | INDI_FLAG_INDEXABLE_BY_TIMESTAMP)) { + Print(GetFullName(), ": Cannot set data source to ", _indi.GetFullName(), ", because source indicator isn't indexable by timestamp!"); + DebugBreak(); + return; + } + } + if (indi_src.IsSet() && indi_src.Ptr() != _indi) { indi_src.Ptr().RemoveListener(THIS_PTR); } diff --git a/Indicator/IndicatorCandle.h b/Indicator/IndicatorCandle.h index 6d5711a31..0fffc48ae 100644 --- a/Indicator/IndicatorCandle.h +++ b/Indicator/IndicatorCandle.h @@ -62,6 +62,8 @@ class IndicatorCandle : public Indicator { * Called on constructor. */ void Init() { + // Along with indexing by shift, we can also index via timestamp! + flags |= INDI_FLAG_INDEXABLE_BY_TIMESTAMP; icdata.AddFlags(DICT_FLAG_FILL_HOLES_UNSORTED); icdata.SetOverflowListener(IndicatorCandleOverflowListener, 10); iparams.SetMaxModes(4); diff --git a/Indicator/IndicatorTick.h b/Indicator/IndicatorTick.h index 34c6564a9..0b7de9d52 100644 --- a/Indicator/IndicatorTick.h +++ b/Indicator/IndicatorTick.h @@ -58,6 +58,11 @@ class IndicatorTick : public Indicator { * Called on constructor. */ void Init() { + // We can't index by shift. + flags &= ~INDI_FLAG_INDEXABLE_BY_SHIFT; + // We can only index via timestamp. + flags |= INDI_FLAG_INDEXABLE_BY_TIMESTAMP; + itdata.AddFlags(DICT_FLAG_FILL_HOLES_UNSORTED); itdata.SetOverflowListener(IndicatorTickOverflowListener, 10); // Ask and Bid price. diff --git a/IndicatorBase.h b/IndicatorBase.h index a57ff5bcd..71d0e5950 100644 --- a/IndicatorBase.h +++ b/IndicatorBase.h @@ -72,6 +72,7 @@ class IndicatorBase : public Chart { IndicatorCalculateCache cache; ARRAY(WeakRef, listeners); // List of indicators that listens for events from this one. long last_tick_time; // Time of the last Tick() call. + int flags; // Flags such as INDI_FLAG_INDEXABLE_BY_SHIFT. public: /* Indicator enumerations */ @@ -92,6 +93,8 @@ class IndicatorBase : public Chart { * Class constructor. */ IndicatorBase(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, string _symbol = NULL) : indi_src(NULL), Chart(_tf, _symbol) { + // By default, indicator is indexable only by shift and data source must be also indexable by shift. + flags = INDI_FLAG_INDEXABLE_BY_SHIFT | INDI_FLAG_SOURCE_REQ_INDEXABLE_BY_SHIFT; calc_start_bar = 0; is_fed = false; indi_src = NULL; @@ -102,6 +105,8 @@ class IndicatorBase : public Chart { * Class constructor. */ IndicatorBase(ENUM_TIMEFRAMES_INDEX _tfi, string _symbol = NULL) : Chart(_tfi, _symbol) { + // By default, indicator is indexable only by shift and data source must be also indexable by shift. + flags = INDI_FLAG_INDEXABLE_BY_SHIFT | INDI_FLAG_SOURCE_REQ_INDEXABLE_BY_SHIFT; calc_start_bar = 0; is_fed = false; indi_src = NULL; @@ -124,11 +129,34 @@ class IndicatorBase : public Chart { /* Operator overloading methods */ /** - * Access indicator entry data using [] operator. + * Access indicator entry data using [] operator via shift. */ - // IndicatorDataEntry operator[](datetime _dt) { return GetEntry(_dt); } - IndicatorDataEntry operator[](int _index) { return GetEntry(_index); } - IndicatorDataEntry operator[](ENUM_INDICATOR_INDEX _index) { return GetEntry(_index); } + IndicatorDataEntry operator[](int _index) { + if (!bool(flags | INDI_FLAG_INDEXABLE_BY_SHIFT)) { + Print(GetFullName(), " is not indexable by shift!"); + DebugBreak(); + IndicatorDataEntry _default; + return _default; + } + return GetEntry(_index); + } + + /** + * Access indicator entry data using [] operator via datetime. + */ + IndicatorDataEntry operator[](datetime _dt) { + if (!bool(flags | INDI_FLAG_INDEXABLE_BY_TIMESTAMP)) { + Print(GetFullName(), " is not indexable by timestamp!"); + DebugBreak(); + IndicatorDataEntry _default; + return _default; + } + return GetEntry(_dt); + } + + IndicatorDataEntry operator[](ENUM_INDICATOR_INDEX _index) { + return GetEntry((int)_index); + } /* Buffer methods */ @@ -630,6 +658,16 @@ class IndicatorBase : public Chart { */ virtual IndicatorDataEntry GetEntry(int _index = 0) = NULL; + /** + * Returns the indicator's struct value. + */ + virtual IndicatorDataEntry GetEntry(datetime _dt) { + Print(GetFullName(), " must implement IndicatorDataEntry IndicatorBase::GetEntry(datetime _dt) in order to use GetEntry(datetime _dt) or _indi[datetime] subscript operator!"); + DebugBreak(); + IndicatorDataEntry _default; + return _default; + } + /** * Alters indicator's struct value. * From 435f1d1a0af2e26b368373d85cec6957650b5691 Mon Sep 17 00:00:00 2001 From: Adrian Kierzkowski Date: Wed, 5 Jan 2022 14:49:55 +0100 Subject: [PATCH 42/77] WIP. IndicatorsTest ready for testing! --- Buffer/BufferTick.h | 1 + Indicator.enum.h | 8 +-- Indicator.mqh | 14 +++-- Indicator/IndicatorTick.h | 4 +- Indicator/IndicatorTickOrCandleSource.h | 29 +++++++++ Indicator/IndicatorTickSource.h | 9 --- Indicator/tests/IndicatorTf.test.mq5 | 2 +- Indicator/tests/IndicatorTick.test.mq5 | 41 +----------- Indicator/tests/classes/IndicatorTickDummy.h | 66 ++++++++++++++++---- IndicatorBase.h | 35 ++++------- Indicators/Indi_BWMFI.mqh | 2 +- Indicators/Tick/Indi_TickMt.mqh | 3 +- Indicators/Tick/tests/Indi_TickMt.test.mq5 | 2 +- Storage/ValueStorage.h | 21 ++++--- tests/IndicatorsTest.mq5 | 5 +- 15 files changed, 132 insertions(+), 110 deletions(-) diff --git a/Buffer/BufferTick.h b/Buffer/BufferTick.h index bc8f2fa4e..d3eb35dab 100644 --- a/Buffer/BufferTick.h +++ b/Buffer/BufferTick.h @@ -26,6 +26,7 @@ // Includes. #include "../BufferStruct.mqh" +#include "../Chart.enum.h" #include "../Storage/IValueStorage.h" #include "../Tick.struct.h" diff --git a/Indicator.enum.h b/Indicator.enum.h index 872c6ceb1..8bf58e7b1 100644 --- a/Indicator.enum.h +++ b/Indicator.enum.h @@ -251,8 +251,8 @@ enum ENUM_INDI_VS_TYPE { // Indicator flags. enum ENUM_INDI_FLAGS { - INDI_FLAG_INDEXABLE_BY_SHIFT, // Indicator supports indexation by shift. - INDI_FLAG_INDEXABLE_BY_TIMESTAMP, // Indicator supports indexation by shift. - INDI_FLAG_SOURCE_REQ_INDEXABLE_BY_SHIFT, // Source indicator must be indexable by shift. + INDI_FLAG_INDEXABLE_BY_SHIFT, // Indicator supports indexation by shift. + INDI_FLAG_INDEXABLE_BY_TIMESTAMP, // Indicator supports indexation by shift. + INDI_FLAG_SOURCE_REQ_INDEXABLE_BY_SHIFT, // Source indicator must be indexable by shift. INDI_FLAG_SOURCE_REQ_INDEXABLE_BY_TIMESTAMP // Source indicator must be indexable by timestamp. -}; \ No newline at end of file +}; diff --git a/Indicator.mqh b/Indicator.mqh index 47089083c..dcba18a65 100644 --- a/Indicator.mqh +++ b/Indicator.mqh @@ -982,18 +982,22 @@ class Indicator : public IndicatorBase { */ void SetDataSource(IndicatorBase* _indi, int _input_mode = -1) override { if (indi_src.IsSet()) { - if (bool(flags | INDI_FLAG_SOURCE_REQ_INDEXABLE_BY_SHIFT) && !bool(_indi.flags | INDI_FLAG_INDEXABLE_BY_SHIFT)) { - Print(GetFullName(), ": Cannot set data source to ", _indi.GetFullName(), ", because source indicator isn't indexable by shift!"); + if (bool(flags | INDI_FLAG_SOURCE_REQ_INDEXABLE_BY_SHIFT) && + !bool(_indi.GetFlags() | INDI_FLAG_INDEXABLE_BY_SHIFT)) { + Print(GetFullName(), ": Cannot set data source to ", _indi.GetFullName(), + ", because source indicator isn't indexable by shift!"); DebugBreak(); return; } - if (bool(flags | INDI_FLAG_SOURCE_REQ_INDEXABLE_BY_TIMESTAMP) && !bool(_indi.flags | INDI_FLAG_INDEXABLE_BY_TIMESTAMP)) { - Print(GetFullName(), ": Cannot set data source to ", _indi.GetFullName(), ", because source indicator isn't indexable by timestamp!"); + if (bool(flags | INDI_FLAG_SOURCE_REQ_INDEXABLE_BY_TIMESTAMP) && + !bool(_indi.GetFlags() | INDI_FLAG_INDEXABLE_BY_TIMESTAMP)) { + Print(GetFullName(), ": Cannot set data source to ", _indi.GetFullName(), + ", because source indicator isn't indexable by timestamp!"); DebugBreak(); return; } } - + if (indi_src.IsSet() && indi_src.Ptr() != _indi) { indi_src.Ptr().RemoveListener(THIS_PTR); } diff --git a/Indicator/IndicatorTick.h b/Indicator/IndicatorTick.h index 0b7de9d52..e654dde70 100644 --- a/Indicator/IndicatorTick.h +++ b/Indicator/IndicatorTick.h @@ -31,7 +31,7 @@ // Includes. #include "../Buffer/BufferTick.h" -#include "../IndicatorBase.h" +#include "../Indicator.mqh" // Indicator modes. enum ENUM_INDI_TICK_MODE { @@ -62,7 +62,7 @@ class IndicatorTick : public Indicator { flags &= ~INDI_FLAG_INDEXABLE_BY_SHIFT; // We can only index via timestamp. flags |= INDI_FLAG_INDEXABLE_BY_TIMESTAMP; - + itdata.AddFlags(DICT_FLAG_FILL_HOLES_UNSORTED); itdata.SetOverflowListener(IndicatorTickOverflowListener, 10); // Ask and Bid price. diff --git a/Indicator/IndicatorTickOrCandleSource.h b/Indicator/IndicatorTickOrCandleSource.h index 89cebebe4..45fce1acd 100644 --- a/Indicator/IndicatorTickOrCandleSource.h +++ b/Indicator/IndicatorTickOrCandleSource.h @@ -27,6 +27,7 @@ // Includes. #include "../Indicator.mqh" +#include "tests/classes/IndicatorTfDummy.h" #include "tests/classes/IndicatorTickReal.h" /** @@ -67,4 +68,32 @@ class IndicatorTickOrCandleSource : public Indicator { void OnDataSourceEntry(IndicatorDataEntry& entry) override{ // We do nothing. }; + + /** + * Creates default, tick based indicator for given applied price. + */ + IndicatorBase* DataSourceRequestReturnDefault(int _applied_price) override { + // Returning real candle indicator. Thus way we can use SetAppliedPrice() and select Ask or Bid price. + IndicatorBase* _indi; + + switch (_applied_price) { + case PRICE_ASK: + case PRICE_BID: + case PRICE_OPEN: + case PRICE_HIGH: + case PRICE_LOW: + case PRICE_CLOSE: + case PRICE_MEDIAN: + case PRICE_TYPICAL: + case PRICE_WEIGHTED: + // @todo ASK/BID should return Tick indicator. Other APs should return Candle-over-Tick indicator. + _indi = new IndicatorTfDummy(GetTf()); + _indi.SetDataSource(new IndicatorTickReal(GetTf())); + return _indi; + } + + Print("Passed wrong value for applied price for ", GetFullName(), " indicator!"); + DebugBreak(); + return NULL; + } }; diff --git a/Indicator/IndicatorTickSource.h b/Indicator/IndicatorTickSource.h index 2780498f9..6e1734f4c 100644 --- a/Indicator/IndicatorTickSource.h +++ b/Indicator/IndicatorTickSource.h @@ -116,13 +116,4 @@ class IndicatorTickSource : public Indicator { // @todo Make use of this method. return true; } - - /** - * Called if data source is requested, but wasn't yet set. May be used to initialize indicators that must operate on - * some data source. - */ - IndicatorBase* OnDataSourceRequest() override { - // Defaulting to platform ticks. - return new IndicatorTickReal(GetTf(), 0, "AMA on IndicatorTickReal"); - } }; diff --git a/Indicator/tests/IndicatorTf.test.mq5 b/Indicator/tests/IndicatorTf.test.mq5 index 739855fae..71385aecd 100644 --- a/Indicator/tests/IndicatorTf.test.mq5 +++ b/Indicator/tests/IndicatorTf.test.mq5 @@ -48,7 +48,7 @@ Ref indi_ama_orig_sim; * Implements OnInit(). */ int OnInit() { - indicators.Add(indi_tick = new IndicatorTickReal(_Symbol)); + indicators.Add(indi_tick = new IndicatorTickReal(PERIOD_CURRENT)); // 1-second candles. // indicators.Add(indi_tf = new IndicatorTfDummy(1)); diff --git a/Indicator/tests/IndicatorTick.test.mq5 b/Indicator/tests/IndicatorTick.test.mq5 index 9b9a082e3..67400dc41 100644 --- a/Indicator/tests/IndicatorTick.test.mq5 +++ b/Indicator/tests/IndicatorTick.test.mq5 @@ -26,50 +26,13 @@ // Includes. #include "../../Test.mqh" -#include "../IndicatorTick.h" - -// Structs. -struct IndicatorTickDummyParams : IndicatorParams { - IndicatorTickDummyParams() : IndicatorParams(INDI_TICK, 3, TYPE_DOUBLE) {} -}; - -/** - * Tick indicator is an indicator that provides per-tick information. - * When asked to return data via GetEntry() it could fetch data from pre-made - * tick history or generate tick on-the-fly from remote source and save it in - * the history. - * - * Note that indicators could provide data also for future shifts, so shift=-10 - * is perfectly valid for them when doing GetEntry()/GetValue(). - * - * Tick indicator may become a data source for Candle indicator. In this - * scenario, when trying to fetch candle for a given shift, tick indicator is - * asked for ticks in a given timespan. E.g., Candle indicator may work in a 5s - * timespans, so when fetching candle with shift now+1, Tick indicator will be - * asked for ticks between now+5s and now+10s. - *rmf - * In order to fetch consecutive candles, you have to call - * IndicatorCandle::NextMaybe() to check whether new candle is ready to be - * processed. If yes, then new candle will be at index 0. - * - * if (indi_candle.NextMaybe()) { - * double _open = indi_candle.Open(0); // Shift 0 = current candle. - * double _close = indi_candle.Close(0); // Shift 0 = current candle. - * } - */ -class IndicatorTickDummy : public IndicatorTick { - public: - IndicatorTickDummy(string _symbol, int _shift = 0, string _name = "") - : IndicatorTick(INDI_TICK, _symbol, _shift, _name) { - SetSymbol(_symbol); - } -}; +#include "classes/IndicatorTickDummy.h" /** * Implements OnInit(). */ int OnInit() { - IndicatorTickDummy _indi_tick(_Symbol); + IndicatorTickDummy _indi_tick(PERIOD_CURRENT); long _time = 1; for (double _price = 0.1; _price <= 2.0; _price += 0.1) { MqlTick _tick; diff --git a/Indicator/tests/classes/IndicatorTickDummy.h b/Indicator/tests/classes/IndicatorTickDummy.h index 355659ff9..683025176 100644 --- a/Indicator/tests/classes/IndicatorTickDummy.h +++ b/Indicator/tests/classes/IndicatorTickDummy.h @@ -1,3 +1,38 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2021, EA31337 Ltd | +//| https://github.com/EA31337 | +//+------------------------------------------------------------------+ + +/* + * This file is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * @file + * Dummy candle-based indicator. + */ + +#ifndef __MQL__ +// Allows the preprocessor to include a header file when it is needed. +#pragma once +#endif + +// Includes. +#include "../../../Tick.struct.h" +#include "../../IndicatorTick.h" + // Params for dummy tick-based indicator. struct IndicatorTickDummyParams : IndicatorParams { IndicatorTickDummyParams() : IndicatorParams(INDI_TICK, 2, TYPE_DOUBLE) {} @@ -6,10 +41,8 @@ struct IndicatorTickDummyParams : IndicatorParams { // Dummy tick-based indicator. class IndicatorTickDummy : public IndicatorTick { public: - IndicatorTickDummy(string _symbol, int _shift = 0, string _name = "") - : IndicatorTick(INDI_TICK, _symbol, _shift, _name) { - SetSymbol(_symbol); - } + IndicatorTickDummy(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0, string _name = "") + : IndicatorTick(INDI_TICK, _tf, _shift, _name) {} string GetName() override { return "IndicatorTickDummy"; } @@ -17,13 +50,22 @@ class IndicatorTickDummy : public IndicatorTick(1.0f, 1.01f))); - EmitEntry(TickToEntry(1500, TickAB(1.5f, 1.51f))); - EmitEntry(TickToEntry(2000, TickAB(2.0f, 2.01f))); - EmitEntry(TickToEntry(3000, TickAB(3.0f, 3.01f))); - EmitEntry(TickToEntry(4000, TickAB(4.0f, 4.01f))); - EmitEntry(TickToEntry(4100, TickAB(4.1f, 4.11f))); - EmitEntry(TickToEntry(4200, TickAB(4.2f, 4.21f))); - EmitEntry(TickToEntry(4800, TickAB(4.8f, 4.81f))); + TickAB _t1(1.0f, 1.01f); + TickAB _t2(1.5f, 1.51f); + TickAB _t3(2.0f, 2.01f); + TickAB _t4(3.0f, 3.01f); + TickAB _t5(4.0f, 4.01f); + TickAB _t6(4.1f, 4.11f); + TickAB _t7(4.2f, 4.21f); + TickAB _t8(4.8f, 4.81f); + + EmitEntry(TickToEntry(1000, _t1)); + EmitEntry(TickToEntry(1500, _t2)); + EmitEntry(TickToEntry(2000, _t3)); + EmitEntry(TickToEntry(3000, _t4)); + EmitEntry(TickToEntry(4000, _t5)); + EmitEntry(TickToEntry(4100, _t6)); + EmitEntry(TickToEntry(4200, _t7)); + EmitEntry(TickToEntry(4800, _t8)); }; }; diff --git a/IndicatorBase.h b/IndicatorBase.h index 71d0e5950..09fcdcd98 100644 --- a/IndicatorBase.h +++ b/IndicatorBase.h @@ -72,7 +72,7 @@ class IndicatorBase : public Chart { IndicatorCalculateCache cache; ARRAY(WeakRef, listeners); // List of indicators that listens for events from this one. long last_tick_time; // Time of the last Tick() call. - int flags; // Flags such as INDI_FLAG_INDEXABLE_BY_SHIFT. + int flags; // Flags such as INDI_FLAG_INDEXABLE_BY_SHIFT. public: /* Indicator enumerations */ @@ -140,7 +140,7 @@ class IndicatorBase : public Chart { } return GetEntry(_index); } - + /** * Access indicator entry data using [] operator via datetime. */ @@ -154,9 +154,7 @@ class IndicatorBase : public Chart { return GetEntry(_dt); } - IndicatorDataEntry operator[](ENUM_INDICATOR_INDEX _index) { - return GetEntry((int)_index); - } + IndicatorDataEntry operator[](ENUM_INDICATOR_INDEX _index) { return GetEntry((int)_index); } /* Buffer methods */ @@ -342,29 +340,18 @@ class IndicatorBase : public Chart { /** * Creates default, tick based indicator for given applied price. */ - IndicatorBase* DataSourceRequestReturnDefault(int _applied_price) { - // Returning real candle indicator. Thus way we can use SetAppliedPrice() and select Ask or Bid price. - switch (_applied_price) { - case PRICE_ASK: - case PRICE_BID: - return new IndicatorTickReal(GetTf()); - case PRICE_OPEN: - case PRICE_HIGH: - case PRICE_LOW: - case PRICE_CLOSE: - case PRICE_MEDIAN: - case PRICE_TYPICAL: - case PRICE_WEIGHTED: - return new IndicatorTfDummy(GetTf()); - } - - Print("Passed wrong value for applied price for ", GetFullName(), " indicator!"); + virtual IndicatorBase* DataSourceRequestReturnDefault(int _applied_price) { DebugBreak(); return NULL; } /* Getters */ + /** + * Returns indicator's flags. + */ + int GetFlags() { return flags; } + /** * Returns buffers' cache. */ @@ -662,7 +649,9 @@ class IndicatorBase : public Chart { * Returns the indicator's struct value. */ virtual IndicatorDataEntry GetEntry(datetime _dt) { - Print(GetFullName(), " must implement IndicatorDataEntry IndicatorBase::GetEntry(datetime _dt) in order to use GetEntry(datetime _dt) or _indi[datetime] subscript operator!"); + Print(GetFullName(), + " must implement IndicatorDataEntry IndicatorBase::GetEntry(datetime _dt) in order to use GetEntry(datetime " + "_dt) or _indi[datetime] subscript operator!"); DebugBreak(); IndicatorDataEntry _default; return _default; diff --git a/Indicators/Indi_BWMFI.mqh b/Indicators/Indi_BWMFI.mqh index cfb98b777..50d44420d 100644 --- a/Indicators/Indi_BWMFI.mqh +++ b/Indicators/Indi_BWMFI.mqh @@ -81,7 +81,7 @@ class Indi_BWMFI : public IndicatorTickOrCandleSource { static double iBWMFI(string _symbol = NULL, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0, ENUM_BWMFI_BUFFER _mode = BWMFI_BUFFER, IndicatorBase *_obj = NULL) { #ifdef __MQL4__ - return ::iBWMFI(_symbol, _tf, _real_shift); + return ::iBWMFI(_symbol, _tf, _shift); #else // __MQL5__ int _handle = Object::IsValid(_obj) ? _obj.Get(IndicatorState::INDICATOR_STATE_PROP_HANDLE) : NULL; double _res[]; diff --git a/Indicators/Tick/Indi_TickMt.mqh b/Indicators/Tick/Indi_TickMt.mqh index c32f45482..9f03835b9 100644 --- a/Indicators/Tick/Indi_TickMt.mqh +++ b/Indicators/Tick/Indi_TickMt.mqh @@ -54,7 +54,8 @@ class Indi_TickMt : public IndicatorTick { */ Indi_TickMt(IndiTickMtParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTick(_p, _indi_src){}; - Indi_TickMt(string _symbol, int _shift = 0) : IndicatorTick(INDI_TICK, _symbol, _shift){}; + Indi_TickMt(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0, string _name = "") + : IndicatorTick(INDI_TICK, _tf, _shift, _name) {} /** * Returns the indicator's value. diff --git a/Indicators/Tick/tests/Indi_TickMt.test.mq5 b/Indicators/Tick/tests/Indi_TickMt.test.mq5 index 428552d78..e77d1ee23 100644 --- a/Indicators/Tick/tests/Indi_TickMt.test.mq5 +++ b/Indicators/Tick/tests/Indi_TickMt.test.mq5 @@ -28,7 +28,7 @@ * Test functionality of Indi_TickMt indicator class. */ -Indi_TickMt indi(_Symbol); +Indi_TickMt indi(PERIOD_CURRENT); /** * Implements Init event handler. diff --git a/Storage/ValueStorage.h b/Storage/ValueStorage.h index 36efe0049..3b019ba0e 100644 --- a/Storage/ValueStorage.h +++ b/Storage/ValueStorage.h @@ -91,16 +91,17 @@ enum ENUM_IPEAK { IPEAK_LOWEST, IPEAK_HIGHEST }; ValueStorage *_price = INDI.GetValueStorage(APPLIED_PRICE); \ INDICATOR_CALCULATE_POPULATE_CACHE(SYMBOL, TF, KEY) -#define INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_SHORT_DS_SPECIFIC(INDI, SYMBOL, TF, APPLIED_PRICE, KEY) \ - ValueStorage *_price; \ - if (_indi.HasSpecificAppliedPriceValueStorage(APPLIED_PRICE)) { \ - _price = INDI.GetSpecificAppliedPriceValueStorage(APPLIED_PRICE); \ - } else { \ - Print("Source indicator ", INDI.GetFullName(), \ - " cannot be used as it doesn't provide a single buffer to be used by target indicator!"); \ - DebugBreak(); \ - } \ - \ +#define INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_SHORT_DS_SPECIFIC(INDI, SYMBOL, TF, APPLIED_PRICE, KEY) \ + ValueStorage *_price; \ + if (_indi.HasSpecificAppliedPriceValueStorage(APPLIED_PRICE)) { \ + _price = INDI.GetSpecificAppliedPriceValueStorage(APPLIED_PRICE); \ + } else { \ + Print("Source indicator ", INDI.GetFullName(), \ + " cannot be used as it doesn't provide a single buffer to be used by target indicator! You may try to set " \ + "applied price/data source mode and try again."); \ + DebugBreak(); \ + } \ + \ INDICATOR_CALCULATE_POPULATE_CACHE(SYMBOL, TF, KEY) #define INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS(INDI, SYMBOL, TF, KEY) \ diff --git a/tests/IndicatorsTest.mq5 b/tests/IndicatorsTest.mq5 index 0120c35ea..e659d6c75 100644 --- a/tests/IndicatorsTest.mq5 +++ b/tests/IndicatorsTest.mq5 @@ -422,10 +422,11 @@ bool InitIndicators() { // AMA. IndiAMAParams ama_params(); + // Will use Candle indicator by default. However, in that case we need to specifiy applied price (excluding ASK and + // BID). ama_params.SetDataSourceType(IDATA_INDICATOR); Indi_AMA* _indi_ama = new Indi_AMA(ama_params); - // AMA will automatically sets its data source to Tick or Candle indicator by value of APPLIED_PRICE. - _indi_ama.SetAppliedPrice(PRICE_ASK); + _indi_ama.SetAppliedPrice(PRICE_OPEN); indis.Push(_indi_ama); // Original AMA. From 58f94f919b15c98af9995a8e82f098157bd9b84f Mon Sep 17 00:00:00 2001 From: Adrian Kierzkowski Date: Fri, 7 Jan 2022 18:49:46 +0100 Subject: [PATCH 43/77] Fixed bug with IndicatorBase::GetValue() which called GetEntryValue() with wrong order of mode and index parameters. --- Indicator.mqh | 2 +- IndicatorBase.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Indicator.mqh b/Indicator.mqh index 13dc6e974..66560fc15 100644 --- a/Indicator.mqh +++ b/Indicator.mqh @@ -1163,7 +1163,7 @@ class Indicator : public IndicatorBase { * @return * Returns DataParamEntry struct filled with a single value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { + IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) override { int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); return GetEntry(_ishift)[_mode]; } diff --git a/IndicatorBase.h b/IndicatorBase.h index 09fcdcd98..6e5ec56b4 100644 --- a/IndicatorBase.h +++ b/IndicatorBase.h @@ -567,7 +567,7 @@ class IndicatorBase : public Chart { template T GetValue(int _index = 0, int _mode = 0) { T _out; - GetEntryValue(_index, _mode).Get(_out); + GetEntryValue(_mode, _index).Get(_out); return _out; } @@ -670,7 +670,7 @@ class IndicatorBase : public Chart { /** * Returns the indicator's entry value. */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _index = -1) = NULL; + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) = NULL; /** * Sends entry to listening indicators. From e9504938c5892ebf451f51364a41e3f9446989ca Mon Sep 17 00:00:00 2001 From: Adrian Kierzkowski Date: Wed, 12 Jan 2022 16:20:06 +0100 Subject: [PATCH 44/77] State of the art --- Indicator/IndicatorCandle.h | 37 +++++++++++++++++++++++++++---------- Indicators/Indi_AMA.mqh | 4 ++++ tests/IndicatorsTest.mq5 | 5 +++-- 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/Indicator/IndicatorCandle.h b/Indicator/IndicatorCandle.h index 0fffc48ae..4293af43b 100644 --- a/Indicator/IndicatorCandle.h +++ b/Indicator/IndicatorCandle.h @@ -32,6 +32,7 @@ // Includes. #include "../Buffer/BufferCandle.h" #include "../Indicator.mqh" +#include "../Candle.struct.h" // Indicator modes. enum ENUM_INDI_CANDLE_MODE { @@ -95,20 +96,36 @@ class IndicatorCandle : public Indicator { * @return * Returns IndicatorDataEntry struct filled with indicator values. */ - IndicatorDataEntry GetEntry(int _index) override { + IndicatorDataEntry GetEntry(int _index = -1) override { ResetLastError(); unsigned int _ishift = _index >= 0 ? _index : iparams.GetShift(); long _candle_time = CalcCandleTimestamp(GetBarTime(_ishift)); - CandleOCTOHLC _candle = icdata.GetByKey(_candle_time); + long _curr_candle_time; + CandleOCTOHLC _candle; + // Trying current and older shifts. + if (icdata.Size() > 0) { + int i = 0; + while (true) { + _curr_candle_time = CalcCandleTimestamp(GetBarTime(i++)); + + if (_curr_candle_time < icdata.GetMin()) { + // There is no older entries. + break; + } + + _candle = icdata.GetByKey(_curr_candle_time); + + if (_candle.IsValid()) { + break; + } + } + } + if (!_candle.IsValid()) { -#ifdef __debug__ - Print(GetFullName(), ": Missing candle at shift ", _index, " (", TimeToString(_candle_time), ")"); -#endif - } else { -#ifdef __debug__verbose_ - Print(GetFullName(), ": Retrieving candle at shift ", _index, " (", TimeToString(_candle_time), ")"); -#endif + // Giving up. + DebugBreak(); + Print(GetFullName(), ": Missing candle after thorough search at shift ", _index, " (", TimeToString(_candle_time), "). Lowest timestamp in history is ", icdata.GetMin()); } return CandleToEntry(_candle_time, _candle); @@ -172,7 +189,7 @@ class IndicatorCandle : public Indicator { _candle.Update(_tick_timestamp, _price); } - icdata.Set(_candle_timestamp, _candle); + icdata.Add(_candle, _candle_timestamp); } /** diff --git a/Indicators/Indi_AMA.mqh b/Indicators/Indi_AMA.mqh index 819ee824f..ee9e75af9 100644 --- a/Indicators/Indi_AMA.mqh +++ b/Indicators/Indi_AMA.mqh @@ -177,6 +177,10 @@ class Indi_AMA : public IndicatorTickOrCandleSource { CalculateInit(InpPeriodAMA, InpFastPeriodEMA, InpSlowPeriodEMA, InpShiftAMA, ExtFastSC, ExtSlowSC, ExtPeriodAMA, ExtSlowPeriodEMA, ExtFastPeriodEMA); + for (int x = prev_calculated; x < rates_total; ++x) { + Print("price[", x, "] = ", price[x].Get(), ", O = ", iOpen(Symbol(), PERIOD_CURRENT, Bars(Symbol(), PERIOD_CURRENT) - x - 1)); + } + int i; // Check for rates count. if (rates_total < ExtPeriodAMA + begin) return (0); diff --git a/tests/IndicatorsTest.mq5 b/tests/IndicatorsTest.mq5 index e659d6c75..357984ae5 100644 --- a/tests/IndicatorsTest.mq5 +++ b/tests/IndicatorsTest.mq5 @@ -112,9 +112,10 @@ void OnTick() { IndicatorDataEntry _entry(_indi.GetEntry()); if (_indi.GetType() == INDI_AMA) { - // PrintFormat("%s: bar %d: %s", _indi.GetFullName(), bar_processed, _indi.ToString()); + PrintFormat("%s: bar %d: %s", _indi.GetFullName(), bar_processed, _indi.ToString()); + continue; } else { - // continue; + continue; } if (_indi.Get(STRUCT_ENUM(IndicatorState, INDICATOR_STATE_PROP_IS_READY))) { From 078af3aec1fbfc9911ee52aff17a07b134d20530 Mon Sep 17 00:00:00 2001 From: Adrian Kierzkowski Date: Thu, 13 Jan 2022 16:10:38 +0100 Subject: [PATCH 45/77] Looks like there is nothing more to do with AMA. Differences are marginal. We need to test some other, more simple indicator like MA(on SMA) in order to be 100% sure there's no differences at all, as there shouldn't be. AMA may differ if it has too many historic entries at start. --- Indicator/tests/IndicatorTf.test.mq5 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Indicator/tests/IndicatorTf.test.mq5 b/Indicator/tests/IndicatorTf.test.mq5 index 71385aecd..c9cb9d86f 100644 --- a/Indicator/tests/IndicatorTf.test.mq5 +++ b/Indicator/tests/IndicatorTf.test.mq5 @@ -107,6 +107,6 @@ void OnTick() { */ void OnDeinit(const int reason) { // Printing all grouped candles. - // Print(indi_tf.Ptr().GetName(), "'s all candles:"); - // Print(indi_tf.Ptr().CandlesToString()); + Print(indi_tf_orig_sim.Ptr().GetName(), "'s all candles:"); + Print(indi_tf_orig_sim.Ptr().CandlesToString()); } From 871cc70c2a48348b4d04f0ac26c972cd7cab7dc8 Mon Sep 17 00:00:00 2001 From: Adrian Kierzkowski Date: Tue, 18 Jan 2022 16:20:23 +0100 Subject: [PATCH 46/77] Fixed order of mode and shift when calling Indicator::GetValue(). Sometimes mode and shift was misordered. --- IndicatorBase.h | 4 ++-- Indicators/Bitwise/Indi_Candle.mqh | 8 ++++---- Indicators/Bitwise/Indi_Pattern.mqh | 8 ++++---- Indicators/Indi_Pivot.mqh | 8 ++++---- Indicators/Special/Indi_Math.mqh | 8 ++++---- Storage/ValueStorage.indicator.h | 2 +- tests/IndicatorTest.mq5 | 10 +++++----- 7 files changed, 24 insertions(+), 24 deletions(-) diff --git a/IndicatorBase.h b/IndicatorBase.h index d1f61d607..a5c35282f 100644 --- a/IndicatorBase.h +++ b/IndicatorBase.h @@ -424,9 +424,9 @@ class IndicatorBase : public Chart { } template - T GetValue(int _index = 0, int _mode = 0) { + T GetValue(int _mode = 0, int _index = 0) { T _out; - GetEntryValue(_index, _mode).Get(_out); + GetEntryValue(_mode, _index).Get(_out); return _out; } diff --git a/Indicators/Bitwise/Indi_Candle.mqh b/Indicators/Bitwise/Indi_Candle.mqh index a9b94aea1..d24d3eeb9 100644 --- a/Indicators/Bitwise/Indi_Candle.mqh +++ b/Indicators/Bitwise/Indi_Candle.mqh @@ -93,10 +93,10 @@ class Indi_Candle : public Indicator { break; } - _ohlcs[0].open = GetDataSource().GetValue(_ishift, PRICE_OPEN); - _ohlcs[0].high = GetDataSource().GetValue(_ishift, PRICE_HIGH); - _ohlcs[0].low = GetDataSource().GetValue(_ishift, PRICE_LOW); - _ohlcs[0].close = GetDataSource().GetValue(_ishift, PRICE_CLOSE); + _ohlcs[0].open = GetDataSource().GetValue(PRICE_OPEN, _ishift); + _ohlcs[0].high = GetDataSource().GetValue(PRICE_HIGH, _ishift); + _ohlcs[0].low = GetDataSource().GetValue(PRICE_LOW, _ishift); + _ohlcs[0].close = GetDataSource().GetValue(PRICE_CLOSE, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Bitwise/Indi_Pattern.mqh b/Indicators/Bitwise/Indi_Pattern.mqh index f9e014ec0..62e1b1a60 100644 --- a/Indicators/Bitwise/Indi_Pattern.mqh +++ b/Indicators/Bitwise/Indi_Pattern.mqh @@ -91,10 +91,10 @@ class Indi_Pattern : public Indicator { } for (i = 0; i < iparams.GetMaxModes(); ++i) { - _ohlcs[i].open = GetDataSource().GetValue(_ishift + i, PRICE_OPEN); - _ohlcs[i].high = GetDataSource().GetValue(_ishift + i, PRICE_HIGH); - _ohlcs[i].low = GetDataSource().GetValue(_ishift + i, PRICE_LOW); - _ohlcs[i].close = GetDataSource().GetValue(_ishift + i, PRICE_CLOSE); + _ohlcs[i].open = GetDataSource().GetValue(PRICE_OPEN, _ishift + i); + _ohlcs[i].high = GetDataSource().GetValue(PRICE_HIGH, _ishift + i); + _ohlcs[i].low = GetDataSource().GetValue(PRICE_LOW, _ishift + i); + _ohlcs[i].close = GetDataSource().GetValue(PRICE_CLOSE, _ishift + i); if (!_ohlcs[i].IsValid()) { // Return empty entry on invalid candles. return WRONG_VALUE; diff --git a/Indicators/Indi_Pivot.mqh b/Indicators/Indi_Pivot.mqh index fd4c7cf4d..50e776a7d 100644 --- a/Indicators/Indi_Pivot.mqh +++ b/Indicators/Indi_Pivot.mqh @@ -148,10 +148,10 @@ class Indi_Pivot : public Indicator { // must have at least 4 buffers and define OHLC in the first 4 buffers. // Indi_Price is an example of such indicator. if (HasDataSource()) { - _ohlc.open = GetDataSource().GetValue(_shift, PRICE_OPEN); - _ohlc.high = GetDataSource().GetValue(_shift, PRICE_HIGH); - _ohlc.low = GetDataSource().GetValue(_shift, PRICE_LOW); - _ohlc.close = GetDataSource().GetValue(_shift, PRICE_CLOSE); + _ohlc.open = GetDataSource().GetValue(PRICE_OPEN, _shift); + _ohlc.high = GetDataSource().GetValue(PRICE_HIGH, _shift); + _ohlc.low = GetDataSource().GetValue(PRICE_LOW, _shift); + _ohlc.close = GetDataSource().GetValue(PRICE_CLOSE, _shift); } break; default: diff --git a/Indicators/Special/Indi_Math.mqh b/Indicators/Special/Indi_Math.mqh index 033377c04..5b13f1227 100644 --- a/Indicators/Special/Indi_Math.mqh +++ b/Indicators/Special/Indi_Math.mqh @@ -132,16 +132,16 @@ class Indi_Math : public Indicator { static double iMathOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, ENUM_MATH_OP op, unsigned int _mode_1, unsigned int _mode_2, unsigned int _shift_1, unsigned int _shift_2, unsigned int _mode, int _shift, Indi_Math *_obj) { - double _val_1 = _indi.GetValue(_shift_1, _mode_1); - double _val_2 = _indi.GetValue(_shift_2, _mode_2); + double _val_1 = _indi.GetValue(_mode_1, _shift_1); + double _val_2 = _indi.GetValue(_mode_2, _shift_2); return Math::Op(op, _val_1, _val_2); } static double iMathOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, MathCustomOpFunction _op, unsigned int _mode_1, unsigned int _mode_2, unsigned int _shift_1, unsigned int _shift_2, unsigned int _mode, int _shift, Indi_Math *_obj) { - double _val_1 = _indi.GetValue(_shift_1, _mode_1); - double _val_2 = _indi.GetValue(_shift_2, _mode_2); + double _val_1 = _indi.GetValue(_mode_1, _shift_1); + double _val_2 = _indi.GetValue(_mode_2, _shift_2); return _op(_val_1, _val_2); } diff --git a/Storage/ValueStorage.indicator.h b/Storage/ValueStorage.indicator.h index 4dc6aacb0..e363559b2 100644 --- a/Storage/ValueStorage.indicator.h +++ b/Storage/ValueStorage.indicator.h @@ -57,5 +57,5 @@ class IndicatorBufferValueStorage : public HistoryValueStorage { /** * Fetches value from a given shift. Takes into consideration as-series flag. */ - virtual C Fetch(int _shift) { return indicator.GetValue(RealShift(_shift), mode); } + virtual C Fetch(int _shift) { return indicator.GetValue(mode, RealShift(_shift)); } }; diff --git a/tests/IndicatorTest.mq5 b/tests/IndicatorTest.mq5 index fde4800ce..79b70758c 100644 --- a/tests/IndicatorTest.mq5 +++ b/tests/IndicatorTest.mq5 @@ -45,14 +45,14 @@ int OnInit() { entry.integer_value = 1; for (uint i = 0; i < in.GetBufferSize() * 2; i++) { in.AddValue(entry); - Print("Index ", i, ": Curr: ", in.GetValue(0).integer_value, "; Prev: ", in.GetValue(1).integer_value); - assertTrueOrFail(in.GetValue(0).integer_value == entry.integer_value, + Print("Index ", i, ": Curr: ", in.GetValue(0, 0).integer_value, "; Prev: ", in.GetValue(0, 1).integer_value); + assertTrueOrFail(in.GetValue(0, 0).integer_value == entry.integer_value, StringFormat("Wrong latest value (%d <> %d)!", - in.GetValue(0).integer_value, + in.GetValue(0, 0).integer_value, entry.integer_value)); - assertTrueOrFail(in.GetValue(1).integer_value == entry.integer_value - 1, + assertTrueOrFail(in.GetValue(0, 1).integer_value == entry.integer_value - 1, StringFormat("Wrong previous value (%d <> %d)!", - in.GetValue(1).integer_value, + in.GetValue(0, 1).integer_value, entry.integer_value - 1)); entry.integer_value++; } From 8e39201f4eb4cb546b529122ec543b0cd33450f5 Mon Sep 17 00:00:00 2001 From: Adrian Kierzkowski Date: Tue, 18 Jan 2022 16:20:23 +0100 Subject: [PATCH 47/77] Fixed order of mode and shift when calling Indicator::GetValue(). Sometimes mode and shift was misordered. --- IndicatorBase.h | 2 +- Indicators/Bitwise/Indi_Candle.mqh | 8 ++++---- Indicators/Bitwise/Indi_Pattern.mqh | 8 ++++---- Indicators/Indi_Pivot.mqh | 8 ++++---- Indicators/Special/Indi_Math.mqh | 8 ++++---- Storage/ValueStorage.indicator.h | 2 +- tests/IndicatorTest.mq5 | 10 +++++----- 7 files changed, 23 insertions(+), 23 deletions(-) diff --git a/IndicatorBase.h b/IndicatorBase.h index 6e5ec56b4..4feceb40d 100644 --- a/IndicatorBase.h +++ b/IndicatorBase.h @@ -565,7 +565,7 @@ class IndicatorBase : public Chart { virtual bool HasSpecificValueStorage(ENUM_INDI_VS_TYPE _type) { return false; } template - T GetValue(int _index = 0, int _mode = 0) { + T GetValue(int _mode = 0, int _index = 0) { T _out; GetEntryValue(_mode, _index).Get(_out); return _out; diff --git a/Indicators/Bitwise/Indi_Candle.mqh b/Indicators/Bitwise/Indi_Candle.mqh index 13c98aeed..3171251f7 100644 --- a/Indicators/Bitwise/Indi_Candle.mqh +++ b/Indicators/Bitwise/Indi_Candle.mqh @@ -94,10 +94,10 @@ class Indi_Candle : public IndicatorTickOrCandleSource { break; } - _ohlcs[0].open = GetDataSource().GetValue(_ishift, PRICE_OPEN); - _ohlcs[0].high = GetDataSource().GetValue(_ishift, PRICE_HIGH); - _ohlcs[0].low = GetDataSource().GetValue(_ishift, PRICE_LOW); - _ohlcs[0].close = GetDataSource().GetValue(_ishift, PRICE_CLOSE); + _ohlcs[0].open = GetDataSource().GetValue(PRICE_OPEN, _ishift); + _ohlcs[0].high = GetDataSource().GetValue(PRICE_HIGH, _ishift); + _ohlcs[0].low = GetDataSource().GetValue(PRICE_LOW, _ishift); + _ohlcs[0].close = GetDataSource().GetValue(PRICE_CLOSE, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Bitwise/Indi_Pattern.mqh b/Indicators/Bitwise/Indi_Pattern.mqh index 1e13c4217..dc5bdc958 100644 --- a/Indicators/Bitwise/Indi_Pattern.mqh +++ b/Indicators/Bitwise/Indi_Pattern.mqh @@ -92,10 +92,10 @@ class Indi_Pattern : public IndicatorTickOrCandleSource { } for (i = 0; i < iparams.GetMaxModes(); ++i) { - _ohlcs[i].open = GetDataSource().GetValue(_ishift + i, PRICE_OPEN); - _ohlcs[i].high = GetDataSource().GetValue(_ishift + i, PRICE_HIGH); - _ohlcs[i].low = GetDataSource().GetValue(_ishift + i, PRICE_LOW); - _ohlcs[i].close = GetDataSource().GetValue(_ishift + i, PRICE_CLOSE); + _ohlcs[i].open = GetDataSource().GetValue(PRICE_OPEN, _ishift + i); + _ohlcs[i].high = GetDataSource().GetValue(PRICE_HIGH, _ishift + i); + _ohlcs[i].low = GetDataSource().GetValue(PRICE_LOW, _ishift + i); + _ohlcs[i].close = GetDataSource().GetValue(PRICE_CLOSE, _ishift + i); if (!_ohlcs[i].IsValid()) { // Return empty entry on invalid candles. return WRONG_VALUE; diff --git a/Indicators/Indi_Pivot.mqh b/Indicators/Indi_Pivot.mqh index c4c785be6..75a737974 100644 --- a/Indicators/Indi_Pivot.mqh +++ b/Indicators/Indi_Pivot.mqh @@ -149,10 +149,10 @@ class Indi_Pivot : public IndicatorTickOrCandleSource { // must have at least 4 buffers and define OHLC in the first 4 buffers. // Indi_Price is an example of such indicator. if (HasDataSource()) { - _ohlc.open = GetDataSource().GetValue(_shift, PRICE_OPEN); - _ohlc.high = GetDataSource().GetValue(_shift, PRICE_HIGH); - _ohlc.low = GetDataSource().GetValue(_shift, PRICE_LOW); - _ohlc.close = GetDataSource().GetValue(_shift, PRICE_CLOSE); + _ohlc.open = GetDataSource().GetValue(PRICE_OPEN, _shift); + _ohlc.high = GetDataSource().GetValue(PRICE_HIGH, _shift); + _ohlc.low = GetDataSource().GetValue(PRICE_LOW, _shift); + _ohlc.close = GetDataSource().GetValue(PRICE_CLOSE, _shift); } break; default: diff --git a/Indicators/Special/Indi_Math.mqh b/Indicators/Special/Indi_Math.mqh index eaacecca5..098b4fc3f 100644 --- a/Indicators/Special/Indi_Math.mqh +++ b/Indicators/Special/Indi_Math.mqh @@ -133,16 +133,16 @@ class Indi_Math : public IndicatorTickOrCandleSource { static double iMathOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, ENUM_MATH_OP op, unsigned int _mode_1, unsigned int _mode_2, unsigned int _shift_1, unsigned int _shift_2, unsigned int _mode, int _shift, Indi_Math *_obj) { - double _val_1 = _indi.GetValue(_shift_1, _mode_1); - double _val_2 = _indi.GetValue(_shift_2, _mode_2); + double _val_1 = _indi.GetValue(_mode_1, _shift_1); + double _val_2 = _indi.GetValue(_mode_2, _shift_2); return Math::Op(op, _val_1, _val_2); } static double iMathOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, MathCustomOpFunction _op, unsigned int _mode_1, unsigned int _mode_2, unsigned int _shift_1, unsigned int _shift_2, unsigned int _mode, int _shift, Indi_Math *_obj) { - double _val_1 = _indi.GetValue(_shift_1, _mode_1); - double _val_2 = _indi.GetValue(_shift_2, _mode_2); + double _val_1 = _indi.GetValue(_mode_1, _shift_1); + double _val_2 = _indi.GetValue(_mode_2, _shift_2); return _op(_val_1, _val_2); } diff --git a/Storage/ValueStorage.indicator.h b/Storage/ValueStorage.indicator.h index 4dc6aacb0..e363559b2 100644 --- a/Storage/ValueStorage.indicator.h +++ b/Storage/ValueStorage.indicator.h @@ -57,5 +57,5 @@ class IndicatorBufferValueStorage : public HistoryValueStorage { /** * Fetches value from a given shift. Takes into consideration as-series flag. */ - virtual C Fetch(int _shift) { return indicator.GetValue(RealShift(_shift), mode); } + virtual C Fetch(int _shift) { return indicator.GetValue(mode, RealShift(_shift)); } }; diff --git a/tests/IndicatorTest.mq5 b/tests/IndicatorTest.mq5 index fde4800ce..79b70758c 100644 --- a/tests/IndicatorTest.mq5 +++ b/tests/IndicatorTest.mq5 @@ -45,14 +45,14 @@ int OnInit() { entry.integer_value = 1; for (uint i = 0; i < in.GetBufferSize() * 2; i++) { in.AddValue(entry); - Print("Index ", i, ": Curr: ", in.GetValue(0).integer_value, "; Prev: ", in.GetValue(1).integer_value); - assertTrueOrFail(in.GetValue(0).integer_value == entry.integer_value, + Print("Index ", i, ": Curr: ", in.GetValue(0, 0).integer_value, "; Prev: ", in.GetValue(0, 1).integer_value); + assertTrueOrFail(in.GetValue(0, 0).integer_value == entry.integer_value, StringFormat("Wrong latest value (%d <> %d)!", - in.GetValue(0).integer_value, + in.GetValue(0, 0).integer_value, entry.integer_value)); - assertTrueOrFail(in.GetValue(1).integer_value == entry.integer_value - 1, + assertTrueOrFail(in.GetValue(0, 1).integer_value == entry.integer_value - 1, StringFormat("Wrong previous value (%d <> %d)!", - in.GetValue(1).integer_value, + in.GetValue(0, 1).integer_value, entry.integer_value - 1)); entry.integer_value++; } From 71108dc08f7769469f0ea7d66fe416348851c4dd Mon Sep 17 00:00:00 2001 From: Adrian Kierzkowski Date: Tue, 18 Jan 2022 17:43:27 +0100 Subject: [PATCH 48/77] Fixed typo in auxiliary indicator fetching by ID. --- Indicators/Indi_BWZT.mqh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Indicators/Indi_BWZT.mqh b/Indicators/Indi_BWZT.mqh index 70675404e..5699beba3 100644 --- a/Indicators/Indi_BWZT.mqh +++ b/Indicators/Indi_BWZT.mqh @@ -129,7 +129,7 @@ class Indi_BWZT : public IndicatorTickOrCandleSource { case INDI_AC: return iparams.indi_ac.Ptr(); case INDI_AO: - return iparams.indi_ac.Ptr(); + return iparams.indi_ao.Ptr(); } return NULL; From 6ee889c0de8509bf015718bb383f7c222532f940 Mon Sep 17 00:00:00 2001 From: kenorb Date: Tue, 18 Jan 2022 17:10:19 +0000 Subject: [PATCH 49/77] Fixes EOL characters --- Indicator/IndicatorCandle.h | 8 ++++---- Indicators/Indi_AMA.mqh | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Indicator/IndicatorCandle.h b/Indicator/IndicatorCandle.h index 4293af43b..c0ff4637a 100644 --- a/Indicator/IndicatorCandle.h +++ b/Indicator/IndicatorCandle.h @@ -108,20 +108,20 @@ class IndicatorCandle : public Indicator { int i = 0; while (true) { _curr_candle_time = CalcCandleTimestamp(GetBarTime(i++)); - + if (_curr_candle_time < icdata.GetMin()) { // There is no older entries. break; } - + _candle = icdata.GetByKey(_curr_candle_time); - + if (_candle.IsValid()) { break; } } } - + if (!_candle.IsValid()) { // Giving up. DebugBreak(); diff --git a/Indicators/Indi_AMA.mqh b/Indicators/Indi_AMA.mqh index ee9e75af9..e72de2fdc 100644 --- a/Indicators/Indi_AMA.mqh +++ b/Indicators/Indi_AMA.mqh @@ -180,7 +180,7 @@ class Indi_AMA : public IndicatorTickOrCandleSource { for (int x = prev_calculated; x < rates_total; ++x) { Print("price[", x, "] = ", price[x].Get(), ", O = ", iOpen(Symbol(), PERIOD_CURRENT, Bars(Symbol(), PERIOD_CURRENT) - x - 1)); } - + int i; // Check for rates count. if (rates_total < ExtPeriodAMA + begin) return (0); From 74eb0367ab71e76aee55d754e5c747efc56125f0 Mon Sep 17 00:00:00 2001 From: Adrian Kierzkowski Date: Wed, 19 Jan 2022 12:53:48 +0100 Subject: [PATCH 50/77] IndicatorsTest was set to test only AMA or Pattern indicator. Now it should test all indicators. --- tests/IndicatorsTest.mq5 | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/tests/IndicatorsTest.mq5 b/tests/IndicatorsTest.mq5 index 357984ae5..22bb10ada 100644 --- a/tests/IndicatorsTest.mq5 +++ b/tests/IndicatorsTest.mq5 @@ -111,13 +111,6 @@ void OnTick() { _indi.OnTick(); IndicatorDataEntry _entry(_indi.GetEntry()); - if (_indi.GetType() == INDI_AMA) { - PrintFormat("%s: bar %d: %s", _indi.GetFullName(), bar_processed, _indi.ToString()); - continue; - } else { - continue; - } - if (_indi.Get(STRUCT_ENUM(IndicatorState, INDICATOR_STATE_PROP_IS_READY))) { if (_entry.IsValid()) { PrintFormat("%s: bar %d: %s", _indi.GetFullName(), bar_processed, _indi.ToString()); @@ -558,7 +551,7 @@ bool InitIndicators() { } // Push white-listed indicators here. - whitelisted_indis.Push(_indi_test); + // whitelisted_indis.Push(_indi_test); return GetLastError() == ERR_NO_ERROR; } From a53dbe7f8abe995522962b683e78cacdbfd6dc71 Mon Sep 17 00:00:00 2001 From: kenorb Date: Sun, 28 May 2023 14:08:14 +0100 Subject: [PATCH 51/77] Fixes C++ error: no matching function for call --- Array.mqh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Array.mqh b/Array.mqh index 8ab6c020c..451adf7b0 100644 --- a/Array.mqh +++ b/Array.mqh @@ -748,7 +748,7 @@ static int GetLowestArrDoubleValue(double& arr[][], int key) { * - https://www.mql5.com/en/docs/array/arraysize */ template - static int ArraySize(ARRAY_REF(X, array)) { + static int ArraySize(const ARRAY_REF(X, array)) { return ::ArraySize(array); } From f83f2a3baeac49f39a8df18889212791ffdc0c79 Mon Sep 17 00:00:00 2001 From: Adrian Kierzkowski Date: Tue, 7 Nov 2023 19:42:27 +0100 Subject: [PATCH 52/77] Refs #11. Renamed "index" variable names into "_idx" to prevent conflicts with global variables. Also added new CreateObject() specialization to Draw.mqh. Added #ifdef to Terminal.define.h to prevent redefinition of defines. --- Array.mqh | 8 ++++---- Chart.mqh | 10 +++++----- Chart.struct.tf.h | 4 ++-- Convert.mqh | 4 ++-- DictBase.mqh | 6 +++--- Draw.mqh | 25 ++++++++++++++----------- Indicator.struct.cache.h | 12 ++++++------ Log.mqh | 6 +++--- MiniMatrix.h | 6 +++--- Serializer.mqh | 2 +- SerializerJson.mqh | 16 ++++++++-------- SerializerNode.mqh | 8 ++++---- Terminal.define.h | 5 ++++- 13 files changed, 59 insertions(+), 53 deletions(-) diff --git a/Array.mqh b/Array.mqh index 8ab6c020c..e07e0d0a2 100644 --- a/Array.mqh +++ b/Array.mqh @@ -753,12 +753,12 @@ static int GetLowestArrDoubleValue(double& arr[][], int key) { } template - static void ArrayStore(ARRAY_REF(X, array), int index, X value, int reserve_size = 0) { - if (index >= ArraySize(array)) { - ArrayResize(array, MathMax(index + 1, ArraySize(array)), reserve_size); + static void ArrayStore(ARRAY_REF(X, array), int _idx, X value, int reserve_size = 0) { + if (_idx >= ArraySize(array)) { + ArrayResize(array, MathMax(_idx + 1, ArraySize(array)), reserve_size); } - array[index] = value; + array[_idx] = value; } }; diff --git a/Chart.mqh b/Chart.mqh index ba63a7750..47cf36d61 100644 --- a/Chart.mqh +++ b/Chart.mqh @@ -378,23 +378,23 @@ class Chart : public Market { * * In case of error, check it via GetLastError(). */ - double GetPeakPrice(int bars, int mode, int index, ENUM_TIMEFRAMES timeframe = PERIOD_CURRENT) { + double GetPeakPrice(int bars, int mode, int _idx, ENUM_TIMEFRAMES timeframe = PERIOD_CURRENT) { int ibar = -1; // @todo: Add symbol parameter. double peak_price = GetOpen(0); switch (mode) { case MODE_HIGH: - ibar = ChartStatic::iHighest(symbol, timeframe, MODE_HIGH, bars, index); + ibar = ChartStatic::iHighest(symbol, timeframe, MODE_HIGH, bars, _idx); return ibar >= 0 ? GetHigh(timeframe, ibar) : false; case MODE_LOW: - ibar = ChartStatic::iLowest(symbol, timeframe, MODE_LOW, bars, index); + ibar = ChartStatic::iLowest(symbol, timeframe, MODE_LOW, bars, _idx); return ibar >= 0 ? GetLow(timeframe, ibar) : false; default: return false; } } - double GetPeakPrice(int bars, int mode = MODE_HIGH, int index = 0) { - return GetPeakPrice(bars, mode, index, Get(CHART_PARAM_TF)); + double GetPeakPrice(int bars, int mode = MODE_HIGH, int _idx = 0) { + return GetPeakPrice(bars, mode, _idx, Get(CHART_PARAM_TF)); } /** diff --git a/Chart.struct.tf.h b/Chart.struct.tf.h index 49c7c88f3..fac322d0f 100644 --- a/Chart.struct.tf.h +++ b/Chart.struct.tf.h @@ -185,9 +185,9 @@ struct ChartTf { * @param * _tf ENUM_TIMEFRAMES_INDEX Specify timeframe index enum. */ - static ENUM_TIMEFRAMES const IndexToTf(ENUM_TIMEFRAMES_INDEX index) { + static ENUM_TIMEFRAMES const IndexToTf(ENUM_TIMEFRAMES_INDEX _idx) { // @todo: Convert it into a loop and using tf constant, see: TfToIndex(). - switch (index) { + switch (_idx) { case M1: return PERIOD_M1; // 1 minute. case M2: diff --git a/Convert.mqh b/Convert.mqh index 7d5f320c1..22352cfa2 100644 --- a/Convert.mqh +++ b/Convert.mqh @@ -298,8 +298,8 @@ class Convert { int i, j; len = StringLen(in); if (len % 4 != 0) len = len - len % 4; - int size = ArraySize(output); - if (size < len / 4) { + int _size = ArraySize(output); + if (_size < len / 4) { ArrayResize(output, len / 4); } for (i = 0, j = 0; j < len; i++, j += 4) { diff --git a/DictBase.mqh b/DictBase.mqh index daeaaae7a..6e80dd8ed 100644 --- a/DictBase.mqh +++ b/DictBase.mqh @@ -115,13 +115,13 @@ class DictBase { */ bool HasFlags(int flags) { return (_flags & flags) == flags; } - DictSlot* GetSlot(const unsigned int index) { - if (index >= GetSlotCount()) { + DictSlot* GetSlot(const unsigned int _idx) { + if (_idx >= GetSlotCount()) { // Index of out bounds. return NULL; } - return &_DictSlots_ref.DictSlots[index]; + return &_DictSlots_ref.DictSlots[_idx]; } /** diff --git a/Draw.mqh b/Draw.mqh index 350f89bf6..c915517eb 100644 --- a/Draw.mqh +++ b/Draw.mqh @@ -46,6 +46,9 @@ class Draw; bool ObjectCreate(string _name, ENUM_OBJECT _otype, int _swindow, datetime _t1, double _p1) { return Draw::ObjectCreate(0, _name, _otype, _swindow, _t1, _p1); } +bool ObjectCreate(string _name, ENUM_OBJECT _otype, int _swindow, datetime _t1, double _p1, datetime _t2, double _p2) { + return Draw::ObjectCreate(0, _name, _otype, _swindow, _t1, _p1, _t2, _p2); +} bool ObjectDelete(string _name) { return Draw::ObjectDelete(_name); } bool ObjectSet(string _name, int _prop_id, double _value) { return Draw::ObjectSet(_name, _prop_id, _value); } int ObjectsTotal(int _type = EMPTY) { return Draw::ObjectsTotal(); } @@ -126,14 +129,14 @@ class Draw : public Chart { * @return * If successful, returns true, otherwise false. */ - static bool SetIndexLabel(int index, string text) { + static bool SetIndexLabel(int _idx, string text) { #ifdef __MQL4__ // https://docs.mql4.com/customind/setindexlabel - ::SetIndexLabel(index, text); + ::SetIndexLabel(_idx, text); return true; #else // https://www.mql5.com/en/docs/customind/plotindexsetstring - return PlotIndexSetString(index, PLOT_LABEL, text); + return PlotIndexSetString(_idx, PLOT_LABEL, text); #endif } @@ -141,19 +144,19 @@ class Draw : public Chart { * Sets the new type, style, width and color for a given indicator line. * */ - static void SetIndexStyle(int index, int type, int style = EMPTY, int width = EMPTY, color clr = CLR_NONE) { + static void SetIndexStyle(int _idx, int type, int style = EMPTY, int width = EMPTY, color clr = CLR_NONE) { #ifdef __MQL4__ // https://docs.mql4.com/customind/setindexstyle - ::SetIndexStyle(index, type, style, width, clr); + ::SetIndexStyle(_idx, type, style, width, clr); #else if (width != EMPTY) { - PlotIndexSetInteger(index, PLOT_LINE_WIDTH, width); + PlotIndexSetInteger(_idx, PLOT_LINE_WIDTH, width); } if (clr != CLR_NONE) { - PlotIndexSetInteger(index, PLOT_LINE_COLOR, clr); + PlotIndexSetInteger(_idx, PLOT_LINE_COLOR, clr); } - PlotIndexSetInteger(index, PLOT_DRAW_TYPE, type); - PlotIndexSetInteger(index, PLOT_LINE_STYLE, style); + PlotIndexSetInteger(_idx, PLOT_DRAW_TYPE, type); + PlotIndexSetInteger(_idx, PLOT_LINE_STYLE, style); #endif } @@ -299,9 +302,9 @@ class Draw : public Chart { /** * Draw a line given the price. */ - void ShowLine(string oname, double price, int colour = Yellow) { + void ShowLine(string oname, double price, int _colour = Yellow) { Draw::ObjectCreate(chart_id, oname, OBJ_HLINE, 0, GetBarTime(), price); - Draw::ObjectSet(oname, OBJPROP_COLOR, colour); + Draw::ObjectSet(oname, OBJPROP_COLOR, _colour); Draw::ObjectMove(oname, 0, GetBarTime(), price); } diff --git a/Indicator.struct.cache.h b/Indicator.struct.cache.h index 2c4df7097..9264f8e6e 100644 --- a/Indicator.struct.cache.h +++ b/Indicator.struct.cache.h @@ -123,16 +123,16 @@ class IndicatorCalculateCache : public Dynamic { * Returns existing or new cache as a child of current one. Useful when indicator uses other indicators and requires * unique caches for them. */ - IndicatorCalculateCache *GetSubCache(int index) { - if (index >= ArraySize(subcaches)) { - ArrayResize(subcaches, index + 1, 10); + IndicatorCalculateCache *GetSubCache(int _idx) { + if (_idx >= ArraySize(subcaches)) { + ArrayResize(subcaches, _idx + 1, 10); } - if (subcaches[index] == NULL) { - subcaches[index] = new IndicatorCalculateCache(); + if (subcaches[_idx] == NULL) { + subcaches[_idx] = new IndicatorCalculateCache(); } - return subcaches[index]; + return subcaches[_idx]; } /** diff --git a/Log.mqh b/Log.mqh index 9e7781d31..c5fa1cd1f 100644 --- a/Log.mqh +++ b/Log.mqh @@ -308,10 +308,10 @@ class Log : public Object { } bool DeleteByTimestamp(datetime timestamp) { - int size = ArraySize(data); - if (size > 0) { + int _size = ArraySize(data); + if (_size > 0) { int offset = 0; - for (int i = 0; i < size; i++) { + for (int i = 0; i < _size; i++) { if (data[i].timestamp == timestamp) { Erase(data, i); return true; diff --git a/MiniMatrix.h b/MiniMatrix.h index 3ceaaa5ab..716af79e4 100644 --- a/MiniMatrix.h +++ b/MiniMatrix.h @@ -43,13 +43,13 @@ class MiniMatrix2d { T Get(int _x, int _y) { return data[(size_x * _y) + _x]; } void Set(int _x, int _y, T _value) { - int index = (size_x * _y) + _x; + int _idx = (size_x * _y) + _x; - if (index < 0 || index >= (size_x * size_y)) { + if (_idx < 0 || _idx >= (size_x * size_y)) { Alert("Array out of range!"); } - data[index] = _value; + data[_idx] = _value; } int SizeX() { return size_x; } diff --git a/Serializer.mqh b/Serializer.mqh index eabe14739..3cc513e78 100644 --- a/Serializer.mqh +++ b/Serializer.mqh @@ -171,7 +171,7 @@ class Serializer { /** * Returns child node for a given index or NULL. */ - SerializerNode* GetChild(unsigned int index) { return _node ? PTR_ATTRIB(_node, GetChild(index)) : NULL; } + SerializerNode* GetChild(unsigned int _idx) { return _node ? PTR_ATTRIB(_node, GetChild(_idx)) : NULL; } /** * Returns floating-point precision. diff --git a/SerializerJson.mqh b/SerializerJson.mqh index 6d7524140..82cb7bc98 100644 --- a/SerializerJson.mqh +++ b/SerializerJson.mqh @@ -326,9 +326,9 @@ class SerializerJson { return root; } - static SerializerNode* GracefulReturn(string error, unsigned int index, SerializerNode* root, + static SerializerNode* GracefulReturn(string error, unsigned int _idx, SerializerNode* root, SerializerNodeParam* key) { - Print(error + " at index ", index); + Print(error + " at index ", _idx); if (root != NULL) delete root; @@ -337,10 +337,10 @@ class SerializerJson { return NULL; } - static bool ExtractNumber(string& data, unsigned int index, string& number) { + static bool ExtractNumber(string& data, unsigned int _idx, string& number) { string str; - for (unsigned int i = index; i < (unsigned int)StringLen(data); ++i) { + for (unsigned int i = _idx; i < (unsigned int)StringLen(data); ++i) { #ifdef __MQL5__ unsigned short ch = StringGetCharacter(data, i); #else @@ -350,7 +350,7 @@ class SerializerJson { if (ch >= '0' && ch <= '9') { str += ShortToString(ch); } else if (ch == '.') { - if (i == index) { + if (i == _idx) { return false; } str += ShortToString(ch); @@ -364,12 +364,12 @@ class SerializerJson { return true; } - static string ExtractString(string& data, unsigned int index) { - for (unsigned int i = index; i < (unsigned int)StringLen(data); ++i) { + static string ExtractString(string& data, unsigned int _idx) { + for (unsigned int i = _idx; i < (unsigned int)StringLen(data); ++i) { unsigned short ch = StringGetCharacter(data, i); if (ch == '"') { - return StringSubstr(data, index, i - index); + return StringSubstr(data, _idx, i - _idx); } } diff --git a/SerializerNode.mqh b/SerializerNode.mqh index 143c79c0f..bc373dcd8 100644 --- a/SerializerNode.mqh +++ b/SerializerNode.mqh @@ -279,15 +279,15 @@ class SerializerNode { /** * Returns pointer to the child node at given index or NULL. */ - SerializerNode* GetChild(unsigned int index) { return index >= _numChildren ? NULL : _children[index]; } + SerializerNode* GetChild(unsigned int _idx) { return _idx >= _numChildren ? NULL : _children[index]; } /** * Removes child with given index. */ - void RemoveChild(unsigned int index) { - delete _children[index]; + void RemoveChild(unsigned int _idx) { + delete _children[_idx]; - for (unsigned int i = ArraySize(_children) - 2; i >= index; --i) { + for (unsigned int i = ArraySize(_children) - 2; i >= _idx; --i) { _children[i] = _children[i + 1]; } } diff --git a/Terminal.define.h b/Terminal.define.h index d5105b86d..54c8f94fa 100644 --- a/Terminal.define.h +++ b/Terminal.define.h @@ -31,11 +31,14 @@ // @docs // - https://docs.mql4.com/common/setusererror // - https://www.mql5.com/en/docs/common/SetUserError + +#ifndef __MQL5__ #define ERR_USER_ARRAY_IS_EMPTY 1 -#define ERR_USER_INVALID_ARG 2 #define ERR_USER_INVALID_BUFF_NUM 3 #define ERR_USER_INVALID_HANDLE 4 #define ERR_USER_ITEM_NOT_FOUND 5 +#endif +#define ERR_USER_INVALID_ARG 2 #define ERR_USER_NOT_SUPPORTED 6 // Return codes of the trade server. From 30ed4a82f092a943a1ae3e75df4a0c6b0e32222f Mon Sep 17 00:00:00 2001 From: Adrian Kierzkowski Date: Wed, 22 Nov 2023 19:00:24 +0100 Subject: [PATCH 53/77] Refs EA31337/EA31337-indicators-other#8. Added underscores to some function parameter names to prevent conflicts with global variables. --- Indicator.define.h | 1 + IndicatorBase.h | 12 ++++++------ Object.mqh | 4 ++++ SerializerNode.mqh | 2 +- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/Indicator.define.h b/Indicator.define.h index d5056e91f..9987ff427 100644 --- a/Indicator.define.h +++ b/Indicator.define.h @@ -32,6 +32,7 @@ // Defines macros. #define COMMA , +#define SEMICOLON ; #define DUMMY #define ICUSTOM_DEF(SET_HANDLE, PARAMS) \ diff --git a/IndicatorBase.h b/IndicatorBase.h index d883e49db..4f94f73d2 100644 --- a/IndicatorBase.h +++ b/IndicatorBase.h @@ -835,11 +835,11 @@ class IndicatorBase : public Chart { * Returns shift at which the last known valid entry exists for a given * period (or from the start, when period is not specified). */ - bool GetLastValidEntryShift(int& out_shift, int period = 0) { + bool GetLastValidEntryShift(int& out_shift, int _period = 0) { out_shift = 0; while (true) { - if ((period != 0 && out_shift >= period) || !HasValidEntry(out_shift + 1)) + if ((_period != 0 && out_shift >= _period) || !HasValidEntry(out_shift + 1)) return out_shift > 0; // Current shift is always invalid. ++out_shift; @@ -852,10 +852,10 @@ class IndicatorBase : public Chart { * Returns shift at which the oldest known valid entry exists for a given * period (or from the start, when period is not specified). */ - bool GetOldestValidEntryShift(int& out_shift, int& out_num_valid, int shift = 0, int period = 0) { + bool GetOldestValidEntryShift(int& out_shift, int& out_num_valid, int shift = 0, int _period = 0) { bool found = false; // Counting from previous up to previous - period. - for (out_shift = shift + 1; out_shift < shift + period + 1; ++out_shift) { + for (out_shift = shift + 1; out_shift < shift + _period + 1; ++out_shift) { if (!HasValidEntry(out_shift)) { --out_shift; out_num_valid = out_shift - shift; @@ -873,8 +873,8 @@ class IndicatorBase : public Chart { * Checks whether indicator has valid at least given number of last entries * (counting from given shift or 0). */ - bool HasAtLeastValidLastEntries(int period, int shift = 0) { - for (int i = 0; i < period; ++i) + bool HasAtLeastValidLastEntries(int _period, int shift = 0) { + for (int i = 0; i < _period; ++i) if (!HasValidEntry(shift + i)) return false; return true; diff --git a/Object.mqh b/Object.mqh index 36f69ec28..64467c821 100644 --- a/Object.mqh +++ b/Object.mqh @@ -24,6 +24,10 @@ #ifndef OBJECT_MQH #define OBJECT_MQH +#ifdef __MQL4__ +#define nullptr NULL +#endif + // Includes. #include "Refs.mqh" #include "String.mqh" diff --git a/SerializerNode.mqh b/SerializerNode.mqh index bc373dcd8..ef75ec19a 100644 --- a/SerializerNode.mqh +++ b/SerializerNode.mqh @@ -279,7 +279,7 @@ class SerializerNode { /** * Returns pointer to the child node at given index or NULL. */ - SerializerNode* GetChild(unsigned int _idx) { return _idx >= _numChildren ? NULL : _children[index]; } + SerializerNode* GetChild(unsigned int _idx) { return _idx >= _numChildren ? NULL : _children[_idx]; } /** * Removes child with given index. From 0ddfa5869f45ad189070b95f7f6004daeff79abb Mon Sep 17 00:00:00 2001 From: Adrian Kierzkowski Date: Wed, 22 Nov 2023 19:06:32 +0100 Subject: [PATCH 54/77] Refs EA31337/EA31337-indicators-other#8. Added IndicatorLegacy.h file to allow using MQL5 versions of iNAME() indicators like iMA(), iRSI() in MQL4. Used to run MQL5 indicators in MQL4. --- IndicatorLegacy.h | 369 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 369 insertions(+) create mode 100644 IndicatorLegacy.h diff --git a/IndicatorLegacy.h b/IndicatorLegacy.h new file mode 100644 index 000000000..0a5ef4dd6 --- /dev/null +++ b/IndicatorLegacy.h @@ -0,0 +1,369 @@ +/** + * @file + * Wrappers to be used by MQL4 code to allow calling MQL5's indicator functions like iMA() in MQL4. + */ + +#ifndef __MQL__ +#pragma once +#endif + +#ifdef __MQL4__ + +#include +#include +#include +#include + +/** + * Replacement for future OnCalculate(). Currently not used, but could be handy in the future. + */ +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[]) { + int _num_calculated = + OnCalculateMT5(rates_total, prev_calculated, time, open, high, low, close, tick_volume, volume, spread); + + return _num_calculated; +} + +#define OnCalculate OnCalculateMT5 + +/** + * Wrapper class to be used by MQL4 code to allow calling MQL5's indicator functions like iMA() in MQL4. + */ +class IndicatorLegacy : public Dynamic { + // Handle to be used by BarsCalculated(), CopyBuffer() and so on. + int handle; + + // Name of the indicator. + string name; + + public: + /** + * Constructor. + */ + IndicatorLegacy(string _name) : name(_name) { handle = indis.Size(); } + + /** + * Returns indicator's handle. + */ + int GetHandle() { return handle; } + + /** + * Returns name of the indicator. + */ + string GetName() { return name; } + + /** + * Returns value for a given shift. + */ + virtual double GetValue(int _shift) = 0; + + /** + * Returns number of bars calculated for this indicator. + */ + int GetBarsCalculated() { + // @todo We probably need to replace it with some more specific check per indicator. + return Bars; + } + + // Dictionary of registered indicators (key -> indicator). + static DictStruct> indis; + + // Dictionary of registered indicators (handle -> indicator). + static DictStruct> indis_handles; + + /** + * Returns number of bars calculated for a given indicator's handle. + */ + static int GetBarsCalculated(int _handle) { + if (_handle < 0 || _handle >= (int)indis.Size()) { + Print("Error: Given handle index is out of bounds! Given handle index ", _handle, " and there is ", indis.Size(), + " handles available."); + DebugBreak(); + return 0; + } + + IndicatorLegacy* _indi = indis_handles[_handle].Ptr(); + return PTR_ATTRIB(_indi, GetBarsCalculated()); + } +}; + +DictStruct> IndicatorLegacy::indis; +DictStruct> IndicatorLegacy::indis_handles; + +/** + * MQL4 wrapper of MQL5's BarsCalculated(). + */ +int BarsCalculated(int _handle) { return IndicatorLegacy::GetBarsCalculated(_handle); } + +/** + * MQL4 wrapper of MQL5's CopyBuffer(). + */ +int CopyBuffer(int _handle, int _mode, int _start, int _count, double& _buffer[]) { + IndicatorLegacy* _indi = IndicatorLegacy::indis_handles[_handle].Ptr(); + + if (_mode != 0) { + Print("Only mode 0 is supported for ", PTR_ATTRIB(_indi, GetName()), + " legacy indicator as MQL4 supports only a single mode."); + DebugBreak(); + return 0; + } + + int _num_copied = 0; + int _buffer_size = ArraySize(_buffer); + + if (_buffer_size < _count) { + _buffer_size = ArrayResize(_buffer, _count); + } + + for (int i = 0; i < _count; ++i) { + double _value = PTR_ATTRIB(_indi, GetValue(_start + i)); + + if (_value == WRONG_VALUE) { + break; + } + + _buffer[_buffer_size - i - 1] = _value; + ++_num_copied; + } + + return _num_copied; +} + +/** + * Defines wrapper class and global iNAME() indicator function (e.g., iMA(), iATR()). + */ +// Print(#FN_NAME " key = ", _key); \ +#define DEFINE_LEGACY_INDICATOR(FN_NAME, BUILTIN_NAME, TYPED_PARAMS_COMMA, TYPED_PARAMS_NO_UDL_SEMICOLON, UNTYPED_PARAMS_COMMA_KEY, UNTYPED_PARAMS_COMMA_VALUES, ASSIGNMENTS_COMMA, UNTYPED_PARAMS_NO_UDL_COMMA_VALUES) \ +class BUILTIN_NAME##Legacy : public IndicatorLegacy { \ + TYPED_PARAMS_NO_UDL_SEMICOLON; \ +public: \ + BUILTIN_NAME##Legacy(string _name, TYPED_PARAMS_COMMA) : IndicatorLegacy(_name), ASSIGNMENTS_COMMA {} \ + virtual double GetValue(int _shift) { \ + double _value = ::BUILTIN_NAME(UNTYPED_PARAMS_NO_UDL_COMMA_VALUES, _shift); \ + if (false) Print(GetName(), "[-", _shift, "]: ", _value); \ + return _value; \ + } \ +}; \ +int FN_NAME(TYPED_PARAMS_COMMA) { \ + Ref _indi; \ + int _handle = INVALID_HANDLE; \ + string _key = Util::MakeKey(#FN_NAME, UNTYPED_PARAMS_COMMA_KEY); \ + if (IndicatorLegacy::indis.KeyExists(_key)) { \ + _indi = IndicatorLegacy::indis[_key]; \ + } \ + else { \ + _indi = new BUILTIN_NAME##Legacy(#BUILTIN_NAME, UNTYPED_PARAMS_COMMA_VALUES); \ + IndicatorLegacy::indis.Set(_key, _indi); \ + IndicatorLegacy::indis_handles.Set(PTR_ATTRIB(_indi.Ptr(), GetHandle()), _indi); \ + } \ + return PTR_ATTRIB(_indi.Ptr(), GetHandle()); \ +} + +/** + * 1-parameter helper for DEFINE_LEGACY_INDICATOR. + */ +#define DEFINE_LEGACY_INDICATOR_1(FN_NAME, INDI_NAME, T1, N1) \ + DEFINE_LEGACY_INDICATOR(INDI_NAME, T1 _##N1, T1 N1, _##N1, _##N1, N1(_##N1), N1); + +/** + * 2-parameter helper for DEFINE_LEGACY_INDICATOR. + */ +#define DEFINE_LEGACY_INDICATOR_2(FN_NAME, INDI_NAME, T1, N1, T2, N2) \ + DEFINE_LEGACY_INDICATOR(FN_NAME, INDI_NAME, T1 _##N1 COMMA T2 _##N2, T1 N1 SEMICOLON T2 N2, _##N1 COMMA _##N2, \ + _##N1 COMMA _##N2, N1(_##N1) COMMA N2(_##N2), N1 COMMA N2); + +/** + * 3-parameter helper for DEFINE_LEGACY_INDICATOR. + */ +#define DEFINE_LEGACY_INDICATOR_3(FN_NAME, INDI_NAME, T1, N1, T2, N2, T3, N3) \ + DEFINE_LEGACY_INDICATOR(FN_NAME, INDI_NAME, T1 _##N1 COMMA T2 _##N2 COMMA T3 _##N3, \ + T1 N1 SEMICOLON T2 N2 SEMICOLON T3 N3, _##N1 COMMA _##N2 COMMA _##N3, \ + _##N1 COMMA _##N2 COMMA _##N3, N1(_##N1) COMMA N2(_##N2) COMMA N3(_##N3), \ + N1 COMMA N2 COMMA N3); + +/** + * 4-parameter helper for DEFINE_LEGACY_INDICATOR. + */ +#define DEFINE_LEGACY_INDICATOR_4(FN_NAME, INDI_NAME) \ + DEFINE_LEGACY_INDICATOR(FN_NAME, INDI_NAME, T1 _##N1 COMMA T2 _##N2 COMMA T3 _##N3 COMMA T4 _##N4, \ + T1 N1 SEMICOLON T2 N2 SEMICOLON T3 N3 SEMICOLON T4 N4, \ + _##N1 COMMA _##N2 COMMA _##N3 COMMA _##N4, _##N1 COMMA _##N2 COMMA _##N3 COMMA _##N4, \ + N1(_##N1) COMMA N2(_##N2) COMMA N3(_##N3) COMMA N4(_##N4), N1 COMMA N2 COMMA N3 COMMA N4); + +/** + * 5-parameter helper for DEFINE_LEGACY_INDICATOR. + */ +#define DEFINE_LEGACY_INDICATOR_5(FN_NAME, INDI_NAME) \ + DEFINE_LEGACY_INDICATOR(FN_NAME, INDI_NAME, T1 _##N1 COMMA T2 _##N2 COMMA T3 _##N3 COMMA T4 _##N4 COMMA T5 _##N5, \ + T1 N1 SEMICOLON T2 N2 SEMICOLON T3 N3 SEMICOLON T4 N4 SEMICOLON T5 N5, \ + _##N1 COMMA _##N2 COMMA _##N3 COMMA _##N4 COMMA _##N5, \ + _##N1 COMMA _##N2 COMMA _##N3 COMMA _##N4 COMMA _##N5, \ + N1(_##N1) COMMA N2(_##N2) COMMA N3(_##N3) COMMA N4(_##N4) COMMA N5(_##N5), \ + N1 COMMA N2 COMMA N3 COMMA N4 COMMA N5); + +/** + * 6-parameter helper for DEFINE_LEGACY_INDICATOR. + */ +#define DEFINE_LEGACY_INDICATOR_6(FN_NAME, INDI_NAME) \ + DEFINE_LEGACY_INDICATOR(FN_NAME, INDI_NAME, \ + T1 _##N1 COMMA T2 _##N2 COMMA T3 _##N3 COMMA T4 _##N4 COMMA T5 _##N5 COMMA T6 _##N6, \ + T1 N1 SEMICOLON T2 N2 SEMICOLON T3 N3 SEMICOLON T4 N4 SEMICOLON T5 N5 SEMICOLON T6 N6, \ + _##N1 COMMA _##N2 COMMA _##N3 COMMA _##N4 COMMA _##N5 COMMA _##N6, \ + _##N1 COMMA _##N2 COMMA _##N3 COMMA _##N4 COMMA _##N5 COMMA _##N6, \ + N1(_##N1) COMMA N2(_##N2) COMMA N3(_##N3) COMMA N4(_##N4) COMMA N5(_##N5) COMMA N6(_##N6), \ + N1 COMMA N2 COMMA N3 COMMA N4 COMMA N5 COMMA N6); + +/** + * 7-parameter helper for DEFINE_LEGACY_INDICATOR. + */ +#define DEFINE_LEGACY_INDICATOR_7(FN_NAME, INDI_NAME) \ + DEFINE_LEGACY_INDICATOR( \ + FN_NAME, INDI_NAME, \ + T1 _##N1 COMMA T2 _##N2 COMMA T3 _##N3 COMMA T4 _##N4 COMMA T5 _##N5 COMMA T6 _##N6 COMMA T7 _##N7, \ + T1 N1 SEMICOLON T2 N2 SEMICOLON T3 N3 SEMICOLON T4 N4 SEMICOLON T5 N5 SEMICOLON T6 N6 SEMICOLON T7 N7, \ + _##N1 COMMA _##N2 COMMA _##N3 COMMA _##N4 COMMA _##N5 COMMA _##N6 COMMA _##N7, \ + _##N1 COMMA _##N2 COMMA _##N3 COMMA _##N4 COMMA _##N5 COMMA _##N6 COMMA _##N7, \ + N1(_##N1) COMMA N2(_##N2) COMMA N3(_##N3) COMMA N4(_##N4) COMMA N5(_##N5) COMMA N6(_##N6) COMMA N7(_##N7), \ + N1 COMMA N2 COMMA N3 COMMA N4 COMMA N5 COMMA N6 COMMA N7); + +/** + * 8-parameter helper for DEFINE_LEGACY_INDICATOR. + */ +#define DEFINE_LEGACY_INDICATOR_8(FN_NAME, INDI_NAME) \ + DEFINE_LEGACY_INDICATOR(FN_NAME, INDI_NAME, \ + T1 _##N1 COMMA T2 _##N2 COMMA T3 _##N3 COMMA T4 _##N4 COMMA T5 _##N5 COMMA T6 _##N6 COMMA T7 \ + _##N7 COMMA T8 _##N8, \ + T1 N1 SEMICOLON T2 N2 SEMICOLON T3 N3 SEMICOLON T4 N4 SEMICOLON T5 N5 SEMICOLON T6 N6 \ + SEMICOLON T7 N7 SEMICOLON T8 N8, \ + _##N1 COMMA _##N2 COMMA _##N3 COMMA _##N4 COMMA _##N5 COMMA _##N6 COMMA _##N7 COMMA _##N8, \ + _##N1 COMMA _##N2 COMMA _##N3 COMMA _##N4 COMMA _##N5 COMMA _##N6 COMMA _##N7 COMMA _##N8, \ + N1(_##N1) COMMA N2(_##N2) COMMA N3(_##N3) COMMA N4(_##N4) COMMA N5(_##N5) COMMA N6(_##N6) \ + COMMA N7(_##N7) COMMA N8(_##N8), \ + N1 COMMA N2 COMMA N3 COMMA N4 COMMA N5 COMMA N6 COMMA N7 COMMA N8); + +/** + * Replacement for future StringConcatenate(). + */ +#define StringConcatenate StringConcatenateMT5 + +/** + * MQL4 wrapper of MQL5's StringConcatenate(). + */ +template +int StringConcatenateMT5(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) { + _result = (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; + return StringLen(_result); +} +template +int StringConcatenateMT5(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) { + _result = (string)_a + (string)_b + (string)_c + (string)_d + (string)_e + (string)_f + (string)_g + (string)_h + + (string)_i + (string)_j + (string)_k + (string)_l; + return StringLen(_result); +} +template +int StringConcatenateMT5(string& _result, A _a, B _b, C _c, D _d, E _e, F _f, G _g, H _h, I _i, J _j, K _k) { + _result = (string)_a + (string)_b + (string)_c + (string)_d + (string)_e + (string)_f + (string)_g + (string)_h + + (string)_i + (string)_j + (string)_k; + return StringLen(_result); +} +template +int StringConcatenateMT5(string& _result, A _a, B _b, C _c, D _d, E _e, F _f, G _g, H _h, I _i, J _j) { + _result = (string)_a + (string)_b + (string)_c + (string)_d + (string)_e + (string)_f + (string)_g + (string)_h + + (string)_i + (string)_j; + return StringLen(_result); +} +template +int StringConcatenateMT5(string& _result, A _a, B _b, C _c, D _d, E _e, F _f, G _g, H _h, I _i) { + _result = (string)_a + (string)_b + (string)_c + (string)_d + (string)_e + (string)_f + (string)_g + (string)_h + + (string)_i; + return StringLen(_result); +} +template +int StringConcatenateMT5(string& _result, A _a, B _b, C _c, D _d, E _e, F _f, G _g, H _h) { + _result = (string)_a + (string)_b + (string)_c + (string)_d + (string)_e + (string)_f + (string)_g + (string)_h; + return StringLen(_result); +} +template +int StringConcatenateMT5(string& _result, A _a, B _b, C _c, D _d, E _e, F _f, G _g) { + _result = (string)_a + (string)_b + (string)_c + (string)_d + (string)_e + (string)_f + (string)_g; + return StringLen(_result); +} +template +int StringConcatenateMT5(string& _result, A _a, B _b, C _c, D _d, E _e, F _f) { + _result = (string)_a + (string)_b + (string)_c + (string)_d + (string)_e + (string)_f; + return StringLen(_result); +} +template +int StringConcatenateMT5(string& _result, A _a, B _b, C _c, D _d, E _e) { + _result = (string)_a + (string)_b + (string)_c + (string)_d + (string)_e; + return StringLen(_result); +} +template +int StringConcatenateMT5(string& _result, A _a, B _b, C _c, D _d) { + _result = (string)_a + (string)_b + (string)_c + (string)_d; + return StringLen(_result); +} +template +int StringConcatenateMT5(string& _result, A _a, B _b, C _c) { + _result = (string)_a + (string)_b + (string)_c; + return StringLen(_result); +} +template +int StringConcatenateMT5(string& _result, A _a, B _b) { + _result = (string)_a + (string)_b; + return StringLen(_result); +} +template +int StringConcatenateMT5(string& _result, A _a) { + _result = (string)_a; + return StringLen(_result); +} + +// ----- LEGACY INDICATOR DEFINITIONS + +// int iAC(string symbol, ENUM_TIMEFRAMES period); +DEFINE_LEGACY_INDICATOR_2(iAC, iAC, string, symbol, int, period); + +// int iAD(string symbol, ENUM_TIMEFRAMES period, ENUM_APPLIED_VOLUME applied_volume); +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 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 +#define N2 period +#define T3 int +#define N3 ma_period +#define T4 int +#define N4 ma_shift +#define T5 int +#define N5 ma_method +#define T6 int +#define N6 applied_price +DEFINE_LEGACY_INDICATOR_6(iMA, iMA) +#undef T1 +#undef N1 +#undef T2 +#undef N2 +#undef T3 +#undef N3 +#undef T4 +#undef N4 +#undef T5 +#undef N5 +#undef T6 +#undef N6 + +#endif From acbac38b5e86d29cf841c5dc9d1258e1b2f2ecbd Mon Sep 17 00:00:00 2001 From: Adrian Kierzkowski Date: Mon, 8 Jan 2024 16:28:57 +0100 Subject: [PATCH 55/77] Refs EA31337/Strategy-TDI#1. MA-targeted changes regarding input MA method and iMAOnArray implementation which input is now changed to native array (from ValueStorage). Also changed Array::ArraySize() to use non-const input. --- Array.mqh | 2 +- Indicators/Indi_MA.mqh | 95 ++++++++++++++++++++++++++++++++++++-- Indicators/Indi_RSI.mqh | 4 +- Indicators/Indi_StdDev.mqh | 3 +- 4 files changed, 95 insertions(+), 9 deletions(-) diff --git a/Array.mqh b/Array.mqh index 451adf7b0..8ab6c020c 100644 --- a/Array.mqh +++ b/Array.mqh @@ -748,7 +748,7 @@ static int GetLowestArrDoubleValue(double& arr[][], int key) { * - https://www.mql5.com/en/docs/array/arraysize */ template - static int ArraySize(const ARRAY_REF(X, array)) { + static int ArraySize(ARRAY_REF(X, array)) { return ::ArraySize(array); } diff --git a/Indicators/Indi_MA.mqh b/Indicators/Indi_MA.mqh index c2675a21a..a7b725ee9 100644 --- a/Indicators/Indi_MA.mqh +++ b/Indicators/Indi_MA.mqh @@ -141,11 +141,96 @@ class Indi_MA : public Indicator { #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 *_array_storage = Singleton>::Get(); - _array_storage.SetData(price); - - return iMAOnArray((ValueStorage *)_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 *_array_storage = Singleton>::Get(); + _array_storage.SetData(price); + + return iMAOnArray((ValueStorage *)_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 } diff --git a/Indicators/Indi_RSI.mqh b/Indicators/Indi_RSI.mqh index c900e6680..919676377 100644 --- a/Indicators/Indi_RSI.mqh +++ b/Indicators/Indi_RSI.mqh @@ -33,9 +33,9 @@ #ifndef __MQL4__ // Defines global functions (for MQL4 backward compability). -double iRSI(string _symbol, int _tf, int _period, int _ap, int _shift) { +double iRSI(string _symbol, int _tf, int _period, ENUM_APPLIED_PRICE _ap, int _shift) { ResetLastError(); - return Indi_RSI::iRSI(_symbol, (ENUM_TIMEFRAMES)_tf, _period, (ENUM_APPLIED_PRICE)_ap, _shift); + return Indi_RSI::iRSI(_symbol, (ENUM_TIMEFRAMES)_tf, _period, _ap, _shift); } double iRSIOnArray(double &_arr[], int _total, int _period, int _shift) { ResetLastError(); diff --git a/Indicators/Indi_StdDev.mqh b/Indicators/Indi_StdDev.mqh index 46be6a1ac..80a54c9e9 100644 --- a/Indicators/Indi_StdDev.mqh +++ b/Indicators/Indi_StdDev.mqh @@ -157,7 +157,8 @@ class Indi_StdDev : public Indicator { return MathSqrt(std_dev / period); } - static double iStdDevOnArray(double &array[], int total, int ma_period, int ma_shift, int ma_method, int shift) { + static double iStdDevOnArray(double &array[], int total, int ma_period, int ma_shift, ENUM_MA_METHOD ma_method, + int shift) { #ifdef __MQL4__ return ::iStdDevOnArray(array, total, ma_period, ma_shift, ma_method, shift); #endif From 67e428ab5a6b2c88aef971c1db6a8e577d9f4774 Mon Sep 17 00:00:00 2001 From: kenorb Date: Sun, 18 Feb 2024 22:43:07 +0000 Subject: [PATCH 56/77] GHA: Fixes compilation workflows --- .github/workflows/compile.yml | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/.github/workflows/compile.yml b/.github/workflows/compile.yml index ee997c3c7..754641b8d 100644 --- a/.github/workflows/compile.yml +++ b/.github/workflows/compile.yml @@ -12,15 +12,39 @@ on: jobs: - Compile: + mt4: + name: Installs platform (4) + uses: EA31337/EA-Tester/.github/workflows/platform-linux.yml@dev + with: + artifact_name: mt4 + version: 4 + mt5: + name: Installs platform (5) + uses: EA31337/EA-Tester/.github/workflows/platform-linux.yml@dev + with: + artifact_name: mt5 + version: 5 + + compile: + name: Compile + needs: [mt4, mt5] runs-on: windows-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + - uses: actions/download-artifact@v4 + with: + name: mt${{ matrix.version }} + path: .mt${{ matrix.version }} - name: Compile uses: fx31337/mql-compile-action@master with: init-platform: true + mt-path: .mt${{ matrix.version }} verbose: true - name: Print compiled files run: '(Get-ChildItem -Recurse -Path . -Include *.ex[45]).fullname' shell: powershell + + strategy: + matrix: + version: [4, 5] From 0125d31fda5a5e9c0e3a71a64706cad2118870d9 Mon Sep 17 00:00:00 2001 From: kenorb Date: Fri, 19 Apr 2024 12:50:49 +0000 Subject: [PATCH 57/77] Adds initial config for .devcontainer/devcontainer.json --- .devcontainer/devcontainer.json | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 .devcontainer/devcontainer.json diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 000000000..3f4966db4 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,16 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/ubuntu +{ + // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile + "image": "mcr.microsoft.com/devcontainers/base:jammy", + "name": "EA31337", + // Features to add to the dev container. More info: https://containers.dev/features. + "features": { + "ghcr.io/devcontainers-contrib/features/actionlint:1": {}, + "ghcr.io/devcontainers-contrib/features/ansible:2": {}, + "ghcr.io/guiyomh/features/vim:0": {}, + "ghcr.io/jungaretti/features/make:1": {}, + "ghcr.io/prulloac/devcontainer-features/pre-commit:1": {}, + "ghcr.io/hspaans/devcontainer-features/ansible-lint:1": {} + } +} \ No newline at end of file From 7b5996a8e63b1d1d8675be7b732ba19935d6c98a Mon Sep 17 00:00:00 2001 From: kenorb Date: Fri, 19 Apr 2024 13:43:21 +0000 Subject: [PATCH 58/77] Adds vscode's extensions for devcontainer --- .devcontainer/devcontainer.json | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 3f4966db4..7389048a9 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,9 +1,16 @@ // For format details, see https://aka.ms/devcontainer.json. For config options, see the // README at: https://github.com/devcontainers/templates/tree/main/src/ubuntu { - // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile - "image": "mcr.microsoft.com/devcontainers/base:jammy", - "name": "EA31337", + // Configure tool-specific properties. + "customizations": { + "vscode": { + "extensions": [ + "L-I-V.mql-tools", + "ms-vscode.cpptools", + "vscodevim.vim" + ], + } + }, // Features to add to the dev container. More info: https://containers.dev/features. "features": { "ghcr.io/devcontainers-contrib/features/actionlint:1": {}, @@ -12,5 +19,8 @@ "ghcr.io/jungaretti/features/make:1": {}, "ghcr.io/prulloac/devcontainer-features/pre-commit:1": {}, "ghcr.io/hspaans/devcontainer-features/ansible-lint:1": {} - } + }, + // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile + "image": "mcr.microsoft.com/devcontainers/base:jammy", + "name": "EA31337" } \ No newline at end of file From 37fbb72f5b093164bde75e69bcb36bd6c51e42b5 Mon Sep 17 00:00:00 2001 From: kenorb Date: Tue, 23 Apr 2024 22:00:04 +0100 Subject: [PATCH 59/77] GHA: Compile: Skips clean-up by default --- .github/workflows/compile.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/compile.yml b/.github/workflows/compile.yml index 754641b8d..6c99f4d95 100644 --- a/.github/workflows/compile.yml +++ b/.github/workflows/compile.yml @@ -17,12 +17,14 @@ jobs: uses: EA31337/EA-Tester/.github/workflows/platform-linux.yml@dev with: artifact_name: mt4 + skip_cleanup: true version: 4 mt5: name: Installs platform (5) uses: EA31337/EA-Tester/.github/workflows/platform-linux.yml@dev with: artifact_name: mt5 + skip_cleanup: true version: 5 compile: From 13c20e3719cf3263701d4d7bfaca9454020bcf38 Mon Sep 17 00:00:00 2001 From: kenorb Date: Tue, 23 Apr 2024 22:53:54 +0100 Subject: [PATCH 60/77] GHA: Compile: Support for workflow calls --- .github/workflows/compile.yml | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/.github/workflows/compile.yml b/.github/workflows/compile.yml index 6c99f4d95..be1bff979 100644 --- a/.github/workflows/compile.yml +++ b/.github/workflows/compile.yml @@ -1,6 +1,9 @@ --- name: Compile +env: + ARTIFACT_PREFIX: ${{ inputs.artifact_prefix || 'mt' }} + # yamllint disable-line rule:truthy on: pull_request: @@ -9,6 +12,18 @@ on: push: paths-ignore: - '**.md' + workflow_call: + inputs: + artifact_prefix: + default: mt + description: Artifact prefix. + required: false + type: string + skip_cleanup: + default: false + description: Whether to skip a clean-up job. + required: false + type: boolean jobs: @@ -16,14 +31,16 @@ jobs: name: Installs platform (4) uses: EA31337/EA-Tester/.github/workflows/platform-linux.yml@dev with: - artifact_name: mt4 + artifact_name: ${{ inputs.artifact_prefix || 'mt' }}4 + artifact_overwrite: true skip_cleanup: true version: 4 mt5: name: Installs platform (5) uses: EA31337/EA-Tester/.github/workflows/platform-linux.yml@dev with: - artifact_name: mt5 + artifact_name: ${{ inputs.artifact_prefix || 'mt' }}5 + artifact_overwrite: true skip_cleanup: true version: 5 @@ -50,3 +67,13 @@ jobs: strategy: matrix: version: [4, 5] + + cleanup: + if: inputs.skip_cleanup != true + name: Clean-up + needs: [compile] + runs-on: ubuntu-latest + steps: + - uses: geekyeggo/delete-artifact@v5 + with: + name: ${{ env.ARTIFACT_PREFIX }}* From 0ad14d18b343560a0beca1114c0f144ea4f68f98 Mon Sep 17 00:00:00 2001 From: kenorb Date: Tue, 23 Apr 2024 23:02:50 +0100 Subject: [PATCH 61/77] Fixes new lines [end-of-file-fixer] --- .devcontainer/devcontainer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 7389048a9..5c48782df 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -23,4 +23,4 @@ // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile "image": "mcr.microsoft.com/devcontainers/base:jammy", "name": "EA31337" -} \ No newline at end of file +} From 0be260ba9d498437f6691d7212b2035d0d5e8061 Mon Sep 17 00:00:00 2001 From: kenorb Date: Tue, 23 Apr 2024 23:22:22 +0100 Subject: [PATCH 62/77] GHA: Test: Includes compile workflow --- .github/workflows/compile.yml | 10 ++++++++++ .github/workflows/test.yml | 30 +++++++----------------------- 2 files changed, 17 insertions(+), 23 deletions(-) diff --git a/.github/workflows/compile.yml b/.github/workflows/compile.yml index be1bff979..ab5c37fd2 100644 --- a/.github/workflows/compile.yml +++ b/.github/workflows/compile.yml @@ -63,6 +63,16 @@ jobs: - name: Print compiled files run: '(Get-ChildItem -Recurse -Path . -Include *.ex[45]).fullname' shell: powershell + - name: Upload artifacts (MQL4) + uses: actions/upload-artifact@v2 + with: + name: files-ex4 + path: '**/*.ex4' + - name: Upload artifacts (MQL5) + uses: actions/upload-artifact@v2 + with: + name: files-ex5 + path: '**/*.ex5' strategy: matrix: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ca02328a3..14b3e9dd7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -20,35 +20,19 @@ on: jobs: - Compile: - runs-on: windows-latest - steps: - - uses: actions/checkout@v2 - - name: Compile - uses: fx31337/mql-compile-action@master - with: - mt-version: 4.0.0.1349 - verbose: true - - name: Print compiled files - run: '(Get-ChildItem -Recurse -Path . -Include *.ex[45]).fullname' - shell: powershell - - name: Upload artifacts (MQL4) - uses: actions/upload-artifact@v2 - with: - name: files-ex4 - path: '**/*.ex4' - - name: Upload artifacts (MQL5) - uses: actions/upload-artifact@v2 - with: - name: files-ex5 - path: '**/*.ex5' + compile: + name: Compile + uses: ./.github/workflows/compile.yml + with: + artifact_prefix: mt + skip_cleanup: true Experts-MQL4: defaults: run: shell: bash working-directory: tests - needs: Compile + needs: compile runs-on: ubuntu-latest strategy: matrix: From d66d89c016249a832db19da0eb8841997cb0403b Mon Sep 17 00:00:00 2001 From: kenorb Date: Tue, 23 Apr 2024 23:36:44 +0100 Subject: [PATCH 63/77] Fixes compilation errors on build 4275 --- Indicator.define.h | 3 +++ Order.mqh | 1 + Terminal.define.h | 4 ++-- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Indicator.define.h b/Indicator.define.h index a61dd3e29..8cb8c3086 100644 --- a/Indicator.define.h +++ b/Indicator.define.h @@ -25,6 +25,9 @@ * Includes Indicator's defines. */ +// Includes. +#include "Terminal.define.h" + #ifndef __MQL__ // Allows the preprocessor to include a header file when it is needed. #pragma once diff --git a/Order.mqh b/Order.mqh index 3ea5c20cb..7d371acb5 100644 --- a/Order.mqh +++ b/Order.mqh @@ -44,6 +44,7 @@ #include "Std.h" #include "String.mqh" #include "SymbolInfo.mqh" +#include "Terminal.define.h" /* Defines for backward compatibility. */ diff --git a/Terminal.define.h b/Terminal.define.h index 54c8f94fa..b68e5561c 100644 --- a/Terminal.define.h +++ b/Terminal.define.h @@ -34,11 +34,11 @@ #ifndef __MQL5__ #define ERR_USER_ARRAY_IS_EMPTY 1 +#endif +#define ERR_USER_INVALID_ARG 2 #define ERR_USER_INVALID_BUFF_NUM 3 #define ERR_USER_INVALID_HANDLE 4 #define ERR_USER_ITEM_NOT_FOUND 5 -#endif -#define ERR_USER_INVALID_ARG 2 #define ERR_USER_NOT_SUPPORTED 6 // Return codes of the trade server. From 8df6c7089b29f479849a00d0afa08010a40bfab0 Mon Sep 17 00:00:00 2001 From: Adrian Kierzkowski Date: Thu, 15 Jun 2023 18:13:54 +0200 Subject: [PATCH 64/77] Fixing CompileTest --- 3D/Cube.h | 4 ++-- 3D/Device.h | 29 +++++++++++++++++------------ 3D/Devices/MTDX/MTDXDevice.h | 14 +++++--------- 3D/Mesh.h | 4 ++-- tests/3DTest.mq5 | 4 ++-- 5 files changed, 28 insertions(+), 27 deletions(-) diff --git a/3D/Cube.h b/3D/Cube.h index 0bc9038ff..5ed20a8b9 100644 --- a/3D/Cube.h +++ b/3D/Cube.h @@ -77,8 +77,8 @@ class Cube : public Mesh { * Initializes graphics device-related things. */ virtual void Initialize(Device* _device) { - SetShaderVS(_device.VertexShader(ShaderCubeSourceVS, T::Layout)); - SetShaderPS(_device.PixelShader(ShaderCubeSourcePS)); + SetShaderVS(_device.CreateVertexShader(ShaderCubeSourceVS, T::Layout)); + SetShaderPS(_device.CreatePixelShader(ShaderCubeSourcePS)); } #endif }; diff --git a/3D/Device.h b/3D/Device.h index d7b64f94f..5124a22ac 100644 --- a/3D/Device.h +++ b/3D/Device.h @@ -138,20 +138,25 @@ class Device : public Dynamic { /** * Creates vertex shader to be used by current graphics device. */ - virtual Shader* VertexShader(string _source_code, const ShaderVertexLayout& _layout[], - string _entry_point = "main") = NULL; + virtual Shader* CreateVertexShader(string _source_code, const ShaderVertexLayout& _layout[], + string _entry_point = "main") = NULL; /** * Creates pixel shader to be used by current graphics device. */ - virtual Shader* PixelShader(string _source_code, string _entry_point = "main") = NULL; + virtual Shader* CreatePixelShader(string _source_code, string _entry_point = "main") = 0; + + /** + * Creates vertex buffer to be used by current graphics device. + */ + virtual VertexBuffer* CreateVertexBuffer() = 0; /** * Creates vertex buffer to be used by current graphics device. */ template - VertexBuffer* VertexBuffer(T& data[]) { - VertexBuffer* _buff = VertexBuffer(); + VertexBuffer* CreateVertexBuffer(T& data[]) { + VertexBuffer* _buff = CreateVertexBuffer(); // Unfortunately we can't make this method virtual. if (dynamic_cast(_buff) != NULL) { // MT5's DirectX. @@ -165,15 +170,10 @@ class Device : public Dynamic { return _buff; } - /** - * Creates vertex buffer to be used by current graphics device. - */ - virtual VertexBuffer* VertexBuffer() = NULL; - /** * Creates index buffer to be used by current graphics device. */ - virtual IndexBuffer* IndexBuffer(unsigned int& _indices[]) = NULL; + virtual IndexBuffer* CreateIndexBuffer(unsigned int& _indices[]) = 0; /** * Renders vertex buffer with optional point indices. @@ -183,7 +183,7 @@ class Device : public Dynamic { /** * Renders vertex buffer with optional point indices. */ - virtual void RenderBuffers(VertexBuffer* _vertices, IndexBuffer* _indices = NULL) = NULL; + virtual void RenderBuffers(VertexBuffer* _vertices, IndexBuffer* _indices = NULL) = 0; /** * Renders given mesh. @@ -233,6 +233,11 @@ class Device : public Dynamic { int Height() { return frontend.Ptr().Height(); } void SetCameraOrtho3D(float _pos_x = 0.0f, float _pos_y = 0.0f, float _pos_z = 0.0f) { + if (Width() <= 0 || Height() <= 0) { + Print("Cannot set 2D camera as width or height of the viewport is zero!"); + DebugBreak(); + return; + } DXMatrixOrthoLH(mtx_projection, 1.0f * _pos_z, 1.0f / Width() * Height() * _pos_z, -10000, 10000); } diff --git a/3D/Devices/MTDX/MTDXDevice.h b/3D/Devices/MTDX/MTDXDevice.h index 7bb1c93b8..166a924ed 100644 --- a/3D/Devices/MTDX/MTDXDevice.h +++ b/3D/Devices/MTDX/MTDXDevice.h @@ -93,15 +93,11 @@ class MTDXDevice : public Device { } } - /** - * Creates index buffer to be used by current graphics device. - */ - IndexBuffer* IndexBuffer() { return NULL; } - /** * Creates vertex shader to be used by current graphics device. */ - virtual Shader* VertexShader(string _source_code, const ShaderVertexLayout& _layout[], string _entry_point = "main") { + Shader* CreateVertexShader(string _source_code, const ShaderVertexLayout& _layout[], + string _entry_point = "main") override { MTDXShader* _shader = new MTDXShader(&this); _shader.Create(SHADER_TYPE_VS, _source_code, _entry_point); _shader.SetDataLayout(_layout); @@ -111,7 +107,7 @@ class MTDXDevice : public Device { /** * Creates pixel shader to be used by current graphics device. */ - virtual Shader* PixelShader(string _source_code, string _entry_point = "main") { + Shader* CreatePixelShader(string _source_code, string _entry_point = "main") override { MTDXShader* _shader = new MTDXShader(&this); _shader.Create(SHADER_TYPE_PS, _source_code, _entry_point); return _shader; @@ -120,12 +116,12 @@ class MTDXDevice : public Device { /** * Creates vertex buffer to be used by current graphics device. */ - VertexBuffer* VertexBuffer() { return new MTDXVertexBuffer(&this); } + VertexBuffer* CreateVertexBuffer() override { return new MTDXVertexBuffer(&this); } /** * Creates index buffer to be used by current graphics device. */ - virtual IndexBuffer* IndexBuffer(unsigned int& _indices[]) { + IndexBuffer* CreateIndexBuffer(unsigned int& _indices[]) override { IndexBuffer* _buffer = new MTDXIndexBuffer(&this); _buffer.Fill(_indices); return _buffer; diff --git a/3D/Mesh.h b/3D/Mesh.h index 0ee82c0dc..c6eaf1f78 100644 --- a/3D/Mesh.h +++ b/3D/Mesh.h @@ -249,8 +249,8 @@ class Mesh : public Dynamic { Print("Indices: ", _s_indices); #endif - vbuff = _vbuff = _device.VertexBuffer(_vertices); - ibuff = _ibuff = _device.IndexBuffer(_indices); + vbuff = _vbuff = _device.CreateVertexBuffer(_vertices); + ibuff = _ibuff = _device.CreateIndexBuffer(_indices); return true; } }; diff --git a/tests/3DTest.mq5 b/tests/3DTest.mq5 index 63390f3da..dd9ac7d5f 100644 --- a/tests/3DTest.mq5 +++ b/tests/3DTest.mq5 @@ -80,8 +80,8 @@ int OnInit() { gfx.Start(new MT5Frontend()); - Ref _shader_v = gfx.VertexShader(ShaderSourceVS, Vertex::Layout); - Ref _shader_p = gfx.PixelShader(ShaderSourcePS); + Ref _shader_v = gfx.CreateVertexShader(ShaderSourceVS, Vertex::Layout); + Ref _shader_p = gfx.CreatePixelShader(ShaderSourcePS); Ref> _mesh = new Cube(1.0f, 1.0f, 1.0f); _mesh.Ptr().SetShaderVS(_shader_v.Ptr()); From d8c2aef011b83a700884f1882b8e2ce849bbcea3 Mon Sep 17 00:00:00 2001 From: kenorb Date: Wed, 24 Apr 2024 00:18:05 +0100 Subject: [PATCH 65/77] GHA: Compile: Ignores compiling platform files --- .github/workflows/compile.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/compile.yml b/.github/workflows/compile.yml index ab5c37fd2..3fb1b6e82 100644 --- a/.github/workflows/compile.yml +++ b/.github/workflows/compile.yml @@ -59,6 +59,8 @@ jobs: with: init-platform: true mt-path: .mt${{ matrix.version }} + path-ignore: .mt${{ matrix.version }} + path: '**/*.mq${{ matrix.version }}' verbose: true - name: Print compiled files run: '(Get-ChildItem -Recurse -Path . -Include *.ex[45]).fullname' From b9aed53b3538f91db3d84104a0d8d560d1fe6b6b Mon Sep 17 00:00:00 2001 From: kenorb Date: Wed, 24 Apr 2024 01:21:08 +0100 Subject: [PATCH 66/77] GHA: Compile: Fixes uploading artifacts after compilation --- .github/workflows/compile.yml | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/.github/workflows/compile.yml b/.github/workflows/compile.yml index 3fb1b6e82..183b7b569 100644 --- a/.github/workflows/compile.yml +++ b/.github/workflows/compile.yml @@ -65,16 +65,11 @@ jobs: - name: Print compiled files run: '(Get-ChildItem -Recurse -Path . -Include *.ex[45]).fullname' shell: powershell - - name: Upload artifacts (MQL4) + - name: Upload artifacts uses: actions/upload-artifact@v2 with: - name: files-ex4 - path: '**/*.ex4' - - name: Upload artifacts (MQL5) - uses: actions/upload-artifact@v2 - with: - name: files-ex5 - path: '**/*.ex5' + name: files-ex${{ matrix.version }} + path: '**/*.ex[45]' strategy: matrix: From 07a8183b2929e24c99e04fa6d5a8d23f341b1e21 Mon Sep 17 00:00:00 2001 From: kenorb Date: Wed, 24 Apr 2024 01:31:28 +0100 Subject: [PATCH 67/77] GHA: Test: Fixes compilation and disables non-working runs --- .github/workflows/test-account.yml | 32 +++++-------------- .github/workflows/test-buffer.yml | 32 +++++-------------- .github/workflows/test-indicators-special.yml | 32 +++++-------------- .github/workflows/test-indicators-tick.yml | 32 +++++-------------- .github/workflows/test-indicators.yml | 32 +++++-------------- .github/workflows/test-tick.yml | 31 +++++------------- .github/workflows/test-trade.yml | 32 +++++-------------- .github/workflows/test.yml | 12 ++++--- 8 files changed, 64 insertions(+), 171 deletions(-) diff --git a/.github/workflows/test-account.yml b/.github/workflows/test-account.yml index 3ac99f1f5..e9f5aff12 100644 --- a/.github/workflows/test-account.yml +++ b/.github/workflows/test-account.yml @@ -14,36 +14,20 @@ on: jobs: - Compile: - runs-on: windows-latest - steps: - - uses: actions/checkout@v2 - - name: Compile - uses: fx31337/mql-compile-action@master - with: - init-platform: true - path: 'Account/tests' - verbose: true - - name: Print compiled files - run: '(Get-ChildItem -Recurse -Path . -Include *.ex[45]).fullname' - shell: powershell - - name: Upload artifacts (MQL4) - uses: actions/upload-artifact@v2 - with: - name: files-ex4 - path: '**/*.ex4' - - name: Upload artifacts (MQL5) - uses: actions/upload-artifact@v2 - with: - name: files-ex5 - path: '**/*.ex5' + compile: + name: Compile + uses: ./.github/workflows/compile.yml + with: + artifact_prefix: mt + skip_cleanup: true Account-Tests-MQL4: defaults: run: shell: bash working-directory: Account/tests - needs: Compile + if: false + needs: compile runs-on: ubuntu-latest strategy: matrix: diff --git a/.github/workflows/test-buffer.yml b/.github/workflows/test-buffer.yml index bf23d92e7..441677f22 100644 --- a/.github/workflows/test-buffer.yml +++ b/.github/workflows/test-buffer.yml @@ -14,36 +14,20 @@ on: jobs: - Compile: - runs-on: windows-latest - steps: - - uses: actions/checkout@v2 - - name: Compile - uses: fx31337/mql-compile-action@master - with: - init-platform: true - path: 'Buffer/tests' - verbose: true - - name: Print compiled files - run: '(Get-ChildItem -Recurse -Path . -Include *.ex[45]).fullname' - shell: powershell - - name: Upload artifacts (MQL4) - uses: actions/upload-artifact@v2 - with: - name: files-ex4 - path: '**/*.ex4' - - name: Upload artifacts (MQL5) - uses: actions/upload-artifact@v2 - with: - name: files-ex5 - path: '**/*.ex5' + compile: + name: Compile + uses: ./.github/workflows/compile.yml + with: + artifact_prefix: mt + skip_cleanup: true Buffer-Tests-MQL4: defaults: run: shell: bash working-directory: Buffer/tests - needs: Compile + if: false + needs: compile runs-on: ubuntu-latest strategy: matrix: diff --git a/.github/workflows/test-indicators-special.yml b/.github/workflows/test-indicators-special.yml index 6e3cfc6e0..95764a543 100644 --- a/.github/workflows/test-indicators-special.yml +++ b/.github/workflows/test-indicators-special.yml @@ -16,36 +16,20 @@ on: jobs: - Compile: - runs-on: windows-latest - steps: - - uses: actions/checkout@v2 - - name: Compile - uses: fx31337/mql-compile-action@master - with: - init-platform: true - path: 'Indicators/Special/tests' - verbose: true - - name: Print compiled files - run: '(Get-ChildItem -Recurse -Path . -Include *.ex[45]).fullname' - shell: powershell - - name: Upload artifacts (MQL4) - uses: actions/upload-artifact@v2 - with: - name: files-ex4 - path: '**/*.ex4' - - name: Upload artifacts (MQL5) - uses: actions/upload-artifact@v2 - with: - name: files-ex5 - path: '**/*.ex5' + compile: + name: Compile + uses: ./.github/workflows/compile.yml + with: + artifact_prefix: mt + skip_cleanup: true Indicators-Tests-MQL4: defaults: run: shell: bash working-directory: Indicators/tests - needs: Compile + if: false + needs: compile runs-on: ubuntu-latest strategy: matrix: diff --git a/.github/workflows/test-indicators-tick.yml b/.github/workflows/test-indicators-tick.yml index 25eabe43c..5553a41a4 100644 --- a/.github/workflows/test-indicators-tick.yml +++ b/.github/workflows/test-indicators-tick.yml @@ -16,36 +16,20 @@ on: jobs: - Compile: - runs-on: windows-latest - steps: - - uses: actions/checkout@v2 - - name: Compile - uses: fx31337/mql-compile-action@master - with: - init-platform: true - path: 'Indicators/Tick/tests' - verbose: true - - name: Print compiled files - run: '(Get-ChildItem -Recurse -Path . -Include *.ex[45]).fullname' - shell: powershell - - name: Upload artifacts (MQL4) - uses: actions/upload-artifact@v2 - with: - name: files-ex4 - path: '**/*.ex4' - - name: Upload artifacts (MQL5) - uses: actions/upload-artifact@v2 - with: - name: files-ex5 - path: '**/*.ex5' + compile: + name: Compile + uses: ./.github/workflows/compile.yml + with: + artifact_prefix: mt + skip_cleanup: true Indicators-Tests-MQL4: defaults: run: shell: bash working-directory: Indicators/tests - needs: Compile + if: false + needs: compile runs-on: ubuntu-latest strategy: matrix: diff --git a/.github/workflows/test-indicators.yml b/.github/workflows/test-indicators.yml index 081413a3d..6c794d8e4 100644 --- a/.github/workflows/test-indicators.yml +++ b/.github/workflows/test-indicators.yml @@ -16,36 +16,20 @@ on: jobs: - Compile: - runs-on: windows-latest - steps: - - uses: actions/checkout@v2 - - name: Compile - uses: fx31337/mql-compile-action@master - with: - init-platform: true - path: 'Indicators/tests' - verbose: true - - name: Print compiled files - run: '(Get-ChildItem -Recurse -Path . -Include *.ex[45]).fullname' - shell: powershell - - name: Upload artifacts (MQL4) - uses: actions/upload-artifact@v2 - with: - name: files-ex4 - path: '**/*.ex4' - - name: Upload artifacts (MQL5) - uses: actions/upload-artifact@v2 - with: - name: files-ex5 - path: '**/*.ex5' + compile: + name: Compile + uses: ./.github/workflows/compile.yml + with: + artifact_prefix: mt + skip_cleanup: true Indicators-Tests-MQL4: defaults: run: shell: bash working-directory: Indicators/tests - needs: Compile + if: false + needs: compile runs-on: ubuntu-latest strategy: matrix: diff --git a/.github/workflows/test-tick.yml b/.github/workflows/test-tick.yml index 941fe371a..37fa2c019 100644 --- a/.github/workflows/test-tick.yml +++ b/.github/workflows/test-tick.yml @@ -14,35 +14,20 @@ on: jobs: - Compile: - runs-on: windows-latest - steps: - - uses: actions/checkout@v2 - - name: Compile - uses: fx31337/mql-compile-action@master - with: - path: 'Tick/tests' - verbose: true - - name: Print compiled files - run: '(Get-ChildItem -Recurse -Path . -Include *.ex[45]).fullname' - shell: powershell - - name: Upload artifacts (MQL4) - uses: actions/upload-artifact@v2 - with: - name: files-ex4 - path: '**/*.ex4' - - name: Upload artifacts (MQL5) - uses: actions/upload-artifact@v2 - with: - name: files-ex5 - path: '**/*.ex5' + compile: + name: Compile + uses: ./.github/workflows/compile.yml + with: + artifact_prefix: mt + skip_cleanup: true Tick-Tests-MQL4: defaults: run: shell: bash working-directory: Tick/tests - needs: Compile + if: false + needs: compile runs-on: ubuntu-latest strategy: matrix: diff --git a/.github/workflows/test-trade.yml b/.github/workflows/test-trade.yml index 4ab779efd..a6dea035d 100644 --- a/.github/workflows/test-trade.yml +++ b/.github/workflows/test-trade.yml @@ -14,36 +14,20 @@ on: jobs: - Compile: - runs-on: windows-latest - steps: - - uses: actions/checkout@v2 - - name: Compile - uses: fx31337/mql-compile-action@master - with: - init-platform: true - path: 'Trade/tests' - verbose: true - - name: Print compiled files - run: '(Get-ChildItem -Recurse -Path . -Include *.ex[45]).fullname' - shell: powershell - - name: Upload artifacts (MQL4) - uses: actions/upload-artifact@v2 - with: - name: files-ex4 - path: '**/*.ex4' - - name: Upload artifacts (MQL5) - uses: actions/upload-artifact@v2 - with: - name: files-ex5 - path: '**/*.ex5' + compile: + name: Compile + uses: ./.github/workflows/compile.yml + with: + artifact_prefix: mt + skip_cleanup: true Trade-Tests-MQL4: defaults: run: shell: bash working-directory: Trade/tests - needs: Compile + if: false + needs: compile runs-on: ubuntu-latest strategy: matrix: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 14b3e9dd7..0906e11aa 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -32,6 +32,7 @@ jobs: run: shell: bash working-directory: tests + if: false needs: compile runs-on: ubuntu-latest strategy: @@ -73,7 +74,7 @@ jobs: BtDays: 1-8 BtMonths: 1 BtYears: 2020 - MtVersion: 4.0.0.1349 + Version: 4 TestExpert: ${{ matrix.test }} timeout-minutes: 10 @@ -82,7 +83,8 @@ jobs: run: shell: bash working-directory: tests - needs: Compile + if: false + needs: compile runs-on: ubuntu-latest strategy: matrix: @@ -118,7 +120,8 @@ jobs: run: shell: bash working-directory: tests - needs: Compile + if: false + needs: compile runs-on: ubuntu-latest strategy: matrix: @@ -143,7 +146,8 @@ jobs: run: shell: bash working-directory: Trade/tests - needs: Compile + if: false + needs: compile runs-on: ubuntu-latest strategy: matrix: From d6bde7079070365cea6676af442a45a533f84eef Mon Sep 17 00:00:00 2001 From: kenorb Date: Wed, 24 Apr 2024 01:50:02 +0100 Subject: [PATCH 68/77] IndicatorBase: Adds missing setter for ENUM_INDICATOR_STATE_PROP --- IndicatorBase.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/IndicatorBase.h b/IndicatorBase.h index 478b4c4c2..c0a4e3569 100644 --- a/IndicatorBase.h +++ b/IndicatorBase.h @@ -427,6 +427,14 @@ class IndicatorBase : public Chart { Chart::Set(_param, _value); } + /** + * Sets an indicator's state property value. + */ + template + void Set(STRUCT_ENUM(IndicatorState, ENUM_INDICATOR_STATE_PROP) _prop, T _value) { + istate.Set(_prop, _value); + } + /** * Sets indicator data source. */ From 761b3d7f8396f6846237347da565b6104065e02b Mon Sep 17 00:00:00 2001 From: kenorb Date: Wed, 24 Apr 2024 01:52:25 +0100 Subject: [PATCH 69/77] GHA: Fixes compilation for indicator test workflow --- .github/workflows/test-indicator.yml | 32 +++++++--------------------- 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/.github/workflows/test-indicator.yml b/.github/workflows/test-indicator.yml index 87b68aa41..af8e3eb45 100644 --- a/.github/workflows/test-indicator.yml +++ b/.github/workflows/test-indicator.yml @@ -16,36 +16,20 @@ on: jobs: - Compile: - runs-on: windows-latest - steps: - - uses: actions/checkout@v2 - - name: Compile - uses: fx31337/mql-compile-action@master - with: - init-platform: true - path: 'Indicator/tests' - verbose: true - - name: Print compiled files - run: '(Get-ChildItem -Recurse -Path . -Include *.ex[45]).fullname' - shell: powershell - - name: Upload artifacts (MQL4) - uses: actions/upload-artifact@v2 - with: - name: files-ex4 - path: '**/*.ex4' - - name: Upload artifacts (MQL5) - uses: actions/upload-artifact@v2 - with: - name: files-ex5 - path: '**/*.ex5' + compile: + name: Compile + uses: ./.github/workflows/compile.yml + with: + artifact_prefix: mt + skip_cleanup: true Indicator-Tests-MQL4: defaults: run: shell: bash working-directory: Indicator/tests - needs: Compile + if: false + needs: compile runs-on: ubuntu-latest strategy: matrix: From 7840f19a053284ade3639fe6f67ba492790e8a2d Mon Sep 17 00:00:00 2001 From: kenorb Date: Wed, 24 Apr 2024 20:40:16 +0100 Subject: [PATCH 70/77] GHA: Compile: Adds support for path input GHA: Compile: Adds support for skip_init input GHA: Compile: Fixes wrong path on missing inputs EBUSY: resource busy or locked, scandir 'D:/DumpStack.log.tmp' GHA: Compile: Fixes init-platform boolean condition GHA: Compile: Fixes init-platform condition to compare with string, not boolean --- .github/workflows/compile.yml | 18 +++++++++++++++--- .github/workflows/test-account.yml | 1 + .github/workflows/test-buffer.yml | 1 + .github/workflows/test-indicator.yml | 1 + .github/workflows/test-indicators-special.yml | 1 + .github/workflows/test-indicators-tick.yml | 1 + .github/workflows/test-indicators.yml | 1 + .github/workflows/test-tick.yml | 1 + .github/workflows/test-trade.yml | 1 + .github/workflows/test.yml | 1 + 10 files changed, 24 insertions(+), 3 deletions(-) diff --git a/.github/workflows/compile.yml b/.github/workflows/compile.yml index 183b7b569..f6efc2b35 100644 --- a/.github/workflows/compile.yml +++ b/.github/workflows/compile.yml @@ -3,6 +3,8 @@ name: Compile env: ARTIFACT_PREFIX: ${{ inputs.artifact_prefix || 'mt' }} + COMPILE_PATH: ${{ inputs.path || '*' }} + SKIP_INIT: ${{ inputs.skip_init || false }} # yamllint disable-line rule:truthy on: @@ -19,9 +21,19 @@ on: description: Artifact prefix. required: false type: string + path: + default: '*' + description: Path to compile. + required: false + type: string skip_cleanup: default: false - description: Whether to skip a clean-up job. + description: Skips a clean-up job. + required: false + type: boolean + skip_init: + default: true + description: Skips initialization of the platform. required: false type: boolean @@ -57,10 +69,10 @@ jobs: - name: Compile uses: fx31337/mql-compile-action@master with: - init-platform: true + init-platform: ${{ env.SKIP_INIT == 'false' }} mt-path: .mt${{ matrix.version }} path-ignore: .mt${{ matrix.version }} - path: '**/*.mq${{ matrix.version }}' + path: '${{ env.COMPILE_PATH }}/**/*.mq${{ matrix.version }}' verbose: true - name: Print compiled files run: '(Get-ChildItem -Recurse -Path . -Include *.ex[45]).fullname' diff --git a/.github/workflows/test-account.yml b/.github/workflows/test-account.yml index e9f5aff12..c2a6cccbe 100644 --- a/.github/workflows/test-account.yml +++ b/.github/workflows/test-account.yml @@ -19,6 +19,7 @@ jobs: uses: ./.github/workflows/compile.yml with: artifact_prefix: mt + path: Account skip_cleanup: true Account-Tests-MQL4: diff --git a/.github/workflows/test-buffer.yml b/.github/workflows/test-buffer.yml index 441677f22..140293213 100644 --- a/.github/workflows/test-buffer.yml +++ b/.github/workflows/test-buffer.yml @@ -19,6 +19,7 @@ jobs: uses: ./.github/workflows/compile.yml with: artifact_prefix: mt + path: Buffer skip_cleanup: true Buffer-Tests-MQL4: diff --git a/.github/workflows/test-indicator.yml b/.github/workflows/test-indicator.yml index af8e3eb45..4a89f6a28 100644 --- a/.github/workflows/test-indicator.yml +++ b/.github/workflows/test-indicator.yml @@ -21,6 +21,7 @@ jobs: uses: ./.github/workflows/compile.yml with: artifact_prefix: mt + path: Indicator skip_cleanup: true Indicator-Tests-MQL4: diff --git a/.github/workflows/test-indicators-special.yml b/.github/workflows/test-indicators-special.yml index 95764a543..4198d8d66 100644 --- a/.github/workflows/test-indicators-special.yml +++ b/.github/workflows/test-indicators-special.yml @@ -21,6 +21,7 @@ jobs: uses: ./.github/workflows/compile.yml with: artifact_prefix: mt + path: Indicators/Special skip_cleanup: true Indicators-Tests-MQL4: diff --git a/.github/workflows/test-indicators-tick.yml b/.github/workflows/test-indicators-tick.yml index 5553a41a4..de3ca8db4 100644 --- a/.github/workflows/test-indicators-tick.yml +++ b/.github/workflows/test-indicators-tick.yml @@ -21,6 +21,7 @@ jobs: uses: ./.github/workflows/compile.yml with: artifact_prefix: mt + path: Indicators/Tick skip_cleanup: true Indicators-Tests-MQL4: diff --git a/.github/workflows/test-indicators.yml b/.github/workflows/test-indicators.yml index 6c794d8e4..0e10579d0 100644 --- a/.github/workflows/test-indicators.yml +++ b/.github/workflows/test-indicators.yml @@ -21,6 +21,7 @@ jobs: uses: ./.github/workflows/compile.yml with: artifact_prefix: mt + path: Indicators skip_cleanup: true Indicators-Tests-MQL4: diff --git a/.github/workflows/test-tick.yml b/.github/workflows/test-tick.yml index 37fa2c019..5e5770b60 100644 --- a/.github/workflows/test-tick.yml +++ b/.github/workflows/test-tick.yml @@ -19,6 +19,7 @@ jobs: uses: ./.github/workflows/compile.yml with: artifact_prefix: mt + path: Tick skip_cleanup: true Tick-Tests-MQL4: diff --git a/.github/workflows/test-trade.yml b/.github/workflows/test-trade.yml index a6dea035d..b5c83391a 100644 --- a/.github/workflows/test-trade.yml +++ b/.github/workflows/test-trade.yml @@ -19,6 +19,7 @@ jobs: uses: ./.github/workflows/compile.yml with: artifact_prefix: mt + path: Trade skip_cleanup: true Trade-Tests-MQL4: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0906e11aa..1094421a8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -26,6 +26,7 @@ jobs: with: artifact_prefix: mt skip_cleanup: true + skip_init: false Experts-MQL4: defaults: From c827e6a9abf5abd4d5acb5d020b0f45692b16b03 Mon Sep 17 00:00:00 2001 From: Adrian Kierzkowski Date: Fri, 1 Dec 2023 19:38:01 +0100 Subject: [PATCH 71/77] Refs EA31337-classes/EA31337-indicators-other#13, EA31337-classes/EA31337-indicators-other#15. WIP. TDI-RT-Clone and Heiken_Ashi_Smoothed indicators made to work in MT5. --- Indicator.define.h | 3 +- IndicatorLegacy.h | 119 +++++++++++++++++++++++++++++++++- Storage/ValueStorage.native.h | 16 ++++- 3 files changed, 132 insertions(+), 6 deletions(-) diff --git a/Indicator.define.h b/Indicator.define.h index 8cb8c3086..dc2d23d8a 100644 --- a/Indicator.define.h +++ b/Indicator.define.h @@ -119,7 +119,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); \ @@ -131,6 +131,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]; diff --git a/IndicatorLegacy.h b/IndicatorLegacy.h index 0a5ef4dd6..471e84676 100644 --- a/IndicatorLegacy.h +++ b/IndicatorLegacy.h @@ -7,6 +7,19 @@ #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 @@ -14,6 +27,8 @@ #include #include +#ifdef INDICATOR_LEGACY_VERSION_MT5 + /** * Replacement for future OnCalculate(). Currently not used, but could be handy in the future. */ @@ -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 @@ -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 +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 +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 +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 +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 +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 +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 +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 +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 +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 +string StringConcatenateMT4(string& _result, A _a, B _b, C _c, D _d) { + return (string)_a + (string)_b + (string)_c + (string)_d; +} +template +string StringConcatenateMT4(string& _result, A _a, B _b, C _c) { + return (string)_a + (string)_b + (string)_c; +} +template +string StringConcatenateMT4(string& _result, A _a, B _b) { + return (string)_a + (string)_b; +} +template +string StringConcatenateMT4(string& _result, A _a) { + return (string)_a; +} + +#endif // INDICATOR_LEGACY_VERSION_MT4 +#endif // __MQL5__ diff --git a/Storage/ValueStorage.native.h b/Storage/ValueStorage.native.h index ea7ebb4ab..f13271087 100644 --- a/Storage/ValueStorage.native.h +++ b/Storage/ValueStorage.native.h @@ -34,6 +34,7 @@ template class NativeValueStorage : public ValueStorage { // Dynamic native array. C _values[]; + int _values_size; public: /** @@ -49,7 +50,16 @@ class NativeValueStorage : public ValueStorage { /** * 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. @@ -60,7 +70,7 @@ class NativeValueStorage : public ValueStorage { * 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(); @@ -77,7 +87,7 @@ class NativeValueStorage : public ValueStorage { /** * 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. From c8889dc790f14795b240b60f1782e16ab9872ea2 Mon Sep 17 00:00:00 2001 From: kenorb Date: Sat, 19 Feb 2022 23:16:24 +0000 Subject: [PATCH 72/77] Account/AccountMt: Fixes zero division --- Account.mqh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Account.mqh b/Account.mqh index ec5bac686..49578410f 100644 --- a/Account.mqh +++ b/Account.mqh @@ -427,7 +427,10 @@ class Account { /** * Get current account drawdown in percent. */ - static double GetDrawdownInPct() { return (100 / AccountTotalBalance()) * (AccountTotalBalance() - AccountEquity()); } + static double GetDrawdownInPct() { + double _balance_total = AccountTotalBalance(); + return _balance_total != 0 ? (100 / AccountTotalBalance()) * (AccountTotalBalance() - AccountEquity()) : 0.0; + } /** * Get current account risk margin level. From d4a12c746504c55120530bddbe58f062448436b3 Mon Sep 17 00:00:00 2001 From: kenorb Date: Mon, 25 Jul 2022 23:17:55 +0100 Subject: [PATCH 73/77] Trade: Disables filling modes for MQL4 --- Trade.mqh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Trade.mqh b/Trade.mqh index c55a92caa..121347014 100644 --- a/Trade.mqh +++ b/Trade.mqh @@ -196,7 +196,10 @@ class Trade { _request.symbol = GetChart().Get(CHART_PARAM_SYMBOL); _request.price = SymbolInfoStatic::GetOpenOffer(_request.symbol, _type); _request.type = _type; +#ifndef __MQL4__ + // Filling modes not supported under MQL4. _request.type_filling = Order::GetOrderFilling(_request.symbol); +#endif _request.volume = _volume > 0 ? _volume : tparams.Get(TRADE_PARAM_LOT_SIZE); _request.volume = NormalizeLots(fmax(_request.volume, SymbolInfoStatic::GetVolumeMin(_request.symbol))); return _request; From 0d62e8039bc4afd305150b203d1059192a809395 Mon Sep 17 00:00:00 2001 From: kenorb Date: Sat, 22 Jul 2023 00:15:28 +0100 Subject: [PATCH 74/77] Order: Refresh order after modification --- Order.mqh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Order.mqh b/Order.mqh index 7d371acb5..c649263ce 100644 --- a/Order.mqh +++ b/Order.mqh @@ -1087,6 +1087,7 @@ class Order : public SymbolInfo { GetLogger().Warning(StringFormat("Failed to modify order (#%d/p:%g/sl:%g/tp:%g/code:%d).", odata.Get(ORDER_PROP_TICKET), _price, _sl, _tp, _last_error), __FUNCTION_LINE__, ToCSV()); + Refresh(ORDER_PRICE_CURRENT); Refresh(ORDER_SL); Refresh(ORDER_TP); // TODO: Refresh(ORDER_PRI) @@ -1102,6 +1103,7 @@ class Order : public SymbolInfo { __FUNCTION_LINE__, ToCSV()); } } + Refresh(); return _result; } From d4490198fe1cafe039cf6f7efd6e9f95fea1cf2a Mon Sep 17 00:00:00 2001 From: kenorb Date: Fri, 21 Jul 2023 21:08:33 +0100 Subject: [PATCH 75/77] Order: Fixes the current volume value when data in orequest is missing --- Order.mqh | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Order.mqh b/Order.mqh index c649263ce..be7803c3a 100644 --- a/Order.mqh +++ b/Order.mqh @@ -931,7 +931,7 @@ class Order : public SymbolInfo { _request.type_filling = GetOrderFilling(orequest.symbol); _request.position = odata.Get(ORDER_PROP_TICKET); _request.price = SymbolInfo::GetCloseOffer(orequest.type); - _request.volume = orequest.volume; + _request.volume = odata.Get(ORDER_VOLUME_CURRENT); Order::OrderSend(_request, oresult, oresult_check); if (oresult.retcode == TRADE_RETCODE_DONE) { // For now, sets the current time. @@ -1579,6 +1579,7 @@ class Order : public SymbolInfo { #endif // Update double values. _result &= Refresh(ORDER_PRICE_OPEN); + _result &= Refresh(ORDER_VOLUME_INITIAL); // Update string values. _result &= Refresh(ORDER_SYMBOL); _result &= Refresh(ORDER_COMMENT); @@ -1590,9 +1591,6 @@ class Order : public SymbolInfo { // _result &= Refresh(ORDER_STATE); // @fixme: Error 69539 // _result &= Refresh(ORDER_TYPE_TIME); // @fixme: Error 69539 // _result &= Refresh(ORDER_TYPE_FILLING); // @fixme: Error 69539 - // Update double values. - // _result &= Refresh(ORDER_VOLUME_INITIAL); // @fixme: false - // _result &= Refresh(ORDER_VOLUME_CURRENT); // @fixme: Error 69539 } // Updates whether order is open or closed. @@ -1606,6 +1604,7 @@ class Order : public SymbolInfo { _result &= Refresh(ORDER_PRICE_CURRENT); _result &= Refresh(ORDER_SL); _result &= Refresh(ORDER_TP); + _result &= Refresh(ORDER_VOLUME_CURRENT); } //} else if (IsPending()) // _result &= Refresh(ORDER_PRICE_STOPLIMIT); // @fixme: Error 69539 @@ -1795,6 +1794,9 @@ class Order : public SymbolInfo { case ORDER_VOLUME_CURRENT: _result = Order::OrderGetDouble(ORDER_VOLUME_CURRENT, _value); break; + case ORDER_VOLUME_INITIAL: + _result = Order::OrderGetDouble(ORDER_VOLUME_INITIAL, _value); + break; default: return false; } @@ -2136,10 +2138,10 @@ class Order : public SymbolInfo { #endif switch (property_id) { case ORDER_VOLUME_INITIAL: - _result = ::OrderLots(); // @fixit Are we sure? + _result = ::OrderLots(); break; case ORDER_VOLUME_CURRENT: - _result = ::OrderLots(); // @fixit Are we sure? + _result = ::OrderLots(); break; case ORDER_PRICE_OPEN: _result = ::OrderOpenPrice(); @@ -2543,9 +2545,7 @@ class Order : public SymbolInfo { case ORDER_VOLUME_INITIAL: return OrderGetValue(POSITION_VOLUME, _type, _out); case ORDER_VOLUME_CURRENT: - // @fixme - SetUserError(ERR_INVALID_PARAMETER); - return NULL; + return OrderGetValue(POSITION_VOLUME, _type, _out); case ORDER_PRICE_OPEN: return OrderGetValue(POSITION_PRICE_OPEN, _type, _out); case ORDER_SL: From c3a65a3b0d07a079432eccd1438f75af858374d1 Mon Sep 17 00:00:00 2001 From: kenorb Date: Fri, 22 Jul 2022 19:13:06 +0100 Subject: [PATCH 76/77] Trade: TradeParams: Adds max_spread --- Trade.enum.h | 1 + Trade.struct.h | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/Trade.enum.h b/Trade.enum.h index 0c4fa402d..38a52cb39 100644 --- a/Trade.enum.h +++ b/Trade.enum.h @@ -77,6 +77,7 @@ enum ENUM_TRADE_PARAM { TRADE_PARAM_BARS_MIN = 0, // Bars minimum TRADE_PARAM_LOT_SIZE, // Lot size TRADE_PARAM_MAGIC_NO, // Magic number + TRADE_PARAM_MAX_SPREAD, // Maximum spread TRADE_PARAM_ORDER_COMMENT, // Order comment TRADE_PARAM_RISK_MARGIN, // Risk margin TRADE_PARAM_SLIPPAGE, // Slippage diff --git a/Trade.struct.h b/Trade.struct.h index 13ce9724a..226815833 100644 --- a/Trade.struct.h +++ b/Trade.struct.h @@ -40,6 +40,7 @@ struct TradeStats; /* Structure for trade parameters. */ struct TradeParams { float lot_size; // Default lot size. + float max_spread; // Maximum spread to trade (in pips). float risk_margin; // Maximum account margin to risk (in %). string order_comment; // Order comment. unsigned int limits_stats[FINAL_ENUM_TRADE_STAT_TYPE][FINAL_ENUM_TRADE_STAT_PERIOD]; @@ -72,6 +73,8 @@ struct TradeParams { return (T)lot_size; case TRADE_PARAM_MAGIC_NO: return (T)magic_no; + case TRADE_PARAM_MAX_SPREAD: + return (T)max_spread; case TRADE_PARAM_ORDER_COMMENT: return (T)order_comment; case TRADE_PARAM_RISK_MARGIN: @@ -130,6 +133,9 @@ struct TradeParams { case TRADE_PARAM_MAGIC_NO: magic_no = (unsigned long)_value; return; + case TRADE_PARAM_MAX_SPREAD: + max_spread = (float)_value; + return; case TRADE_PARAM_ORDER_COMMENT: order_comment = (string)_value; return; From ae5d3dfb8f9a700a7b300bc93ecbd0f931a0c2e2 Mon Sep 17 00:00:00 2001 From: kenorb Date: Sat, 12 Aug 2023 01:24:57 +0100 Subject: [PATCH 77/77] Workaround for closing order conditions after orders are loaded from active pool (GH-705) --- EA.mqh | 15 ++++++++++++++- Strategy.mqh | 45 +++++++++++++++++++++++++++++++++++++++++++++ Trade.mqh | 4 ++-- 3 files changed, 61 insertions(+), 3 deletions(-) diff --git a/EA.mqh b/EA.mqh index 55b6f4130..63368f947 100644 --- a/EA.mqh +++ b/EA.mqh @@ -765,8 +765,21 @@ class EA { * Loads existing trades for the given strategy. */ bool StrategyLoadTrades(Strategy *_strat) { + bool _result = true; Trade *_trade = trade.GetByKey(_Symbol); - return _trade.OrdersLoadByMagic(_strat.Get(STRAT_PARAM_ID)); + // Load active trades. + _result &= _trade.OrdersLoadByMagic(_strat.Get(STRAT_PARAM_ID)); + // Load strategy-specific order parameters (e.g. conditions). + // This is a temporary workaround for GH-705. + // @todo: To move to Strategy class. + Ref _order; + for (DictStructIterator> iter = _trade.GetOrdersActive().Begin(); iter.IsValid(); ++iter) { + _order = iter.Value(); + if (_order.IsSet() && _order.Ptr().IsOpen()) { + _strat.OnOrderLoad(_order.Ptr()); + } + } + return _result; } /* Trade methods */ diff --git a/Strategy.mqh b/Strategy.mqh index 0e2e6c979..624ea4654 100644 --- a/Strategy.mqh +++ b/Strategy.mqh @@ -865,6 +865,51 @@ class Strategy : public Object { virtual void OnInit() { SetStops(GetPointer(this), GetPointer(this)); // trade.SetStrategy(&this); // @fixme + // Sets strategy's trade spread limit. + trade.Set(TRADE_PARAM_MAX_SPREAD, sparams.Get(STRAT_PARAM_MAX_SPREAD)); + // Load active trades. + if (Get(STRAT_PARAM_ID) > 0) { + trade.OrdersLoadByMagic(Get(STRAT_PARAM_ID)); + } + Ref _order; + for (DictStructIterator> iter = trade.GetOrdersActive().Begin(); iter.IsValid(); ++iter) { + _order = iter.Value(); + if (_order.IsSet() && _order.Ptr().IsOpen()) { + Strategy::OnOrderLoad(_order.Ptr()); + } + } + } + + /** + * Event on strategy's order load. + * + * @param + * _oparams Order parameters to update. + */ + virtual void OnOrderLoad(Order *_order) { + int _index = 0; + ENUM_TIMEFRAMES _stf = Get(STRAT_PARAM_TF); + unsigned int _stf_secs = ChartTf::TfToSeconds(_stf); + if (sparams.order_close_time != 0) { + long _close_time_arg = sparams.order_close_time > 0 ? sparams.order_close_time * 60 + : (int)round(-sparams.order_close_time * _stf_secs); + _order.Set(ORDER_PARAM_COND_CLOSE, ORDER_COND_LIFETIME_GT_ARG, _index); + _order.Set(ORDER_PARAM_COND_CLOSE_ARG_VALUE, _close_time_arg, _index); + _index++; + } + if (sparams.order_close_loss != 0.0f) { + float _loss_limit = sparams.order_close_loss; + _order.Set(ORDER_PARAM_COND_CLOSE, ORDER_COND_IN_LOSS, _index); + _order.Set(ORDER_PARAM_COND_CLOSE_ARG_VALUE, _loss_limit, _index); + _index++; + } + if (sparams.order_close_profit != 0.0f) { + float _profit_limit = sparams.order_close_profit; + _order.Set(ORDER_PARAM_COND_CLOSE, ORDER_COND_IN_PROFIT, _index); + _order.Set(ORDER_PARAM_COND_CLOSE_ARG_VALUE, _profit_limit, _index); + _index++; + } + _order.Set(ORDER_PARAM_UPDATE_FREQ, _stf_secs); } /** diff --git a/Trade.mqh b/Trade.mqh index 121347014..bdd048743 100644 --- a/Trade.mqh +++ b/Trade.mqh @@ -845,8 +845,8 @@ HistorySelect(0, TimeCurrent()); // Select history for access. OrderMoveToHistory(_order.Ptr()); order_last = _order; } else { - logger.AddLastError(__FUNCTION_LINE__, _order.Ptr().Get(ORDER_PROP_LAST_ERROR)); - return -1; + logger.AddLastError(__FUNCTION_LINE__, _order.Ptr().Get(ORDER_PROP_LAST_ERROR)); + continue; } } else { OrderMoveToHistory(_order.Ptr());