diff --git a/.github/workflows/cleanup.yml b/.github/workflows/cleanup.yml new file mode 100644 index 000000000..cc033f27f --- /dev/null +++ b/.github/workflows/cleanup.yml @@ -0,0 +1,23 @@ +--- +name: Clean-up + +# yamllint disable-line rule:truthy +on: + workflow_call: + inputs: + artifact_prefix: + default: mt + description: Artifact prefix to clean up. + required: false + type: string + +jobs: + + cleanup: + name: Clean-up + runs-on: ubuntu-latest + steps: + - uses: geekyeggo/delete-artifact@v5 + with: + name: ${{ inputs.artifact_prefix }}* + timeout-minutes: 5 diff --git a/.github/workflows/compile-cpp.yml b/.github/workflows/compile-cpp.yml new file mode 100644 index 000000000..085b4f3e0 --- /dev/null +++ b/.github/workflows/compile-cpp.yml @@ -0,0 +1,44 @@ +--- +name: Compile C++ + +# yamllint disable-line rule:truthy +on: + pull_request: + paths-ignore: + - '**.md' + push: + paths-ignore: + - '**.md' + +jobs: + + FileList: + outputs: + filelist: ${{ steps.get-files.outputs.filelist }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Set output with list of files + id: get-files + run: | + import glob, json, os + files = glob.glob("**/tests/*.cpp") + print("::set-output name=filelist::{}".format(json.dumps(files))) + shell: python + - name: Display output + run: echo ${{ steps.get-files.outputs.filelist }} + + Compile: + runs-on: ubuntu-latest + needs: [FileList] + strategy: + matrix: + file: ${{ fromJson(needs.FileList.outputs.filelist) }} + steps: + - uses: actions/checkout@v2 + - name: Install compiler + uses: rlalik/setup-cpp-compiler@v1.1 + with: + compiler: gcc-latest + - name: Compile ${{ matrix.file }} + run: g++ "${{ matrix.file }}" diff --git a/.github/workflows/compile.yml b/.github/workflows/compile.yml index f6efc2b35..a5b9c6875 100644 --- a/.github/workflows/compile.yml +++ b/.github/workflows/compile.yml @@ -91,8 +91,4 @@ jobs: 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 }}* + uses: ./.github/workflows/cleanup.yml diff --git a/.github/workflows/test-account.yml b/.github/workflows/test-account.yml index c2a6cccbe..bc240f5d1 100644 --- a/.github/workflows/test-account.yml +++ b/.github/workflows/test-account.yml @@ -44,3 +44,8 @@ jobs: with: Script: ${{ matrix.test }} timeout-minutes: 10 + + cleanup: + name: Clean-up + needs: [compile] + uses: ./.github/workflows/cleanup.yml diff --git a/.github/workflows/test-buffer.yml b/.github/workflows/test-buffer.yml index 140293213..82b627a14 100644 --- a/.github/workflows/test-buffer.yml +++ b/.github/workflows/test-buffer.yml @@ -44,3 +44,8 @@ jobs: with: Script: ${{ matrix.test }} timeout-minutes: 10 + + cleanup: + name: Clean-up + needs: [compile] + uses: ./.github/workflows/cleanup.yml diff --git a/.github/workflows/test-exchange.yml b/.github/workflows/test-exchange.yml new file mode 100644 index 000000000..408fb5ed0 --- /dev/null +++ b/.github/workflows/test-exchange.yml @@ -0,0 +1,47 @@ +--- +name: Test Exchange + +# yamllint disable-line rule:truthy +on: + pull_request: + paths: + - 'Exchange/**.h' + - 'Exchange/**.mq?' + - '.github/workflows/test-exchange.yml' + push: + paths: + - 'Exchange/**.h' + - 'Exchange/**.mq?' + - '.github/workflows/test-exchange.yml' + +jobs: + + compile: + name: Compile + uses: ./.github/workflows/compile.yml + with: + artifact_prefix: mt + path: Exchange + skip_cleanup: true + + Exchange-Tests-MQL4: + defaults: + run: + shell: bash + working-directory: Exchange/tests + if: false + needs: compile + runs-on: ubuntu-latest + strategy: + matrix: + test: + - Exchange.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/.github/workflows/test-indicator.yml b/.github/workflows/test-indicator.yml index 4a89f6a28..a3900e527 100644 --- a/.github/workflows/test-indicator.yml +++ b/.github/workflows/test-indicator.yml @@ -50,3 +50,8 @@ jobs: BtYears: 2020 TestExpert: ${{ matrix.test }} timeout-minutes: 10 + + cleanup: + name: Clean-up + needs: [compile] + uses: ./.github/workflows/cleanup.yml diff --git a/.github/workflows/test-indicators-special.yml b/.github/workflows/test-indicators-special.yml index 4198d8d66..50cbfe1f6 100644 --- a/.github/workflows/test-indicators-special.yml +++ b/.github/workflows/test-indicators-special.yml @@ -48,3 +48,8 @@ jobs: BtYears: 2020 TestExpert: ${{ matrix.test }} timeout-minutes: 10 + + cleanup: + name: Clean-up + needs: [compile] + uses: ./.github/workflows/cleanup.yml diff --git a/.github/workflows/test-indicators-tick.yml b/.github/workflows/test-indicators-tick.yml index de3ca8db4..516ade6ea 100644 --- a/.github/workflows/test-indicators-tick.yml +++ b/.github/workflows/test-indicators-tick.yml @@ -48,3 +48,8 @@ jobs: BtYears: 2020 TestExpert: ${{ matrix.test }} timeout-minutes: 10 + + cleanup: + name: Clean-up + needs: [compile] + uses: ./.github/workflows/cleanup.yml diff --git a/.github/workflows/test-indicators.yml b/.github/workflows/test-indicators.yml index 0e10579d0..ea3df37e8 100644 --- a/.github/workflows/test-indicators.yml +++ b/.github/workflows/test-indicators.yml @@ -113,3 +113,8 @@ jobs: BtYears: 2020 TestExpert: ${{ matrix.test }} timeout-minutes: 10 + + cleanup: + name: Clean-up + needs: [compile] + uses: ./.github/workflows/cleanup.yml diff --git a/.github/workflows/test-tick.yml b/.github/workflows/test-tick.yml index 5e5770b60..335a30a51 100644 --- a/.github/workflows/test-tick.yml +++ b/.github/workflows/test-tick.yml @@ -42,3 +42,8 @@ jobs: uses: fx31337/mql-tester-action@master with: Script: ${{ matrix.test }} + + cleanup: + name: Clean-up + needs: [compile] + uses: ./.github/workflows/cleanup.yml diff --git a/.github/workflows/test-trade.yml b/.github/workflows/test-trade.yml index b5c83391a..6c4dd0c95 100644 --- a/.github/workflows/test-trade.yml +++ b/.github/workflows/test-trade.yml @@ -44,3 +44,8 @@ jobs: with: Script: ${{ matrix.test }} timeout-minutes: 10 + + cleanup: + name: Clean-up + needs: [compile] + uses: ./.github/workflows/cleanup.yml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1094421a8..a222d90a5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -47,7 +47,7 @@ jobs: - CompileIndicatorsTest - ConditionTest - DatabaseTest - - DrawIndicatorTest + # - DrawIndicatorTest - EATest - IndicatorDataTest - IndicatorTest @@ -163,3 +163,8 @@ jobs: with: Script: ${{ matrix.test }} timeout-minutes: 10 + + cleanup: + name: Clean-up + needs: [compile] + uses: ./.github/workflows/cleanup.yml diff --git a/Account.mqh b/Account.mqh index 49578410f..8c0393ef4 100644 --- a/Account.mqh +++ b/Account.mqh @@ -30,6 +30,7 @@ class Account; // Includes. #include "Account/Account.define.h" #include "Account/Account.enum.h" +#include "Account/Account.extern.h" #include "Account/Account.struct.h" #include "Array.mqh" #include "BufferStruct.mqh" @@ -63,6 +64,11 @@ class Account { */ Account() : init_balance(CalcInitDeposit()), start_balance(GetBalance()), start_credit(GetCredit()) {} + /** + * Class copy constructor. + */ + Account(const Account &_account) {} + /** * Class deconstructor. */ diff --git a/Account/Account.extern.h b/Account/Account.extern.h new file mode 100644 index 000000000..28aa8909d --- /dev/null +++ b/Account/Account.extern.h @@ -0,0 +1,29 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2022, 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 "Account.enum.h" + +// Define external global functions. +#ifndef __MQL__ +extern string AccountInfoString(ENUM_ACCOUNT_INFO_STRING property_id); +#endif diff --git a/Account/Account.struct.h b/Account/Account.struct.h index 63c4ca53a..7f70c1498 100644 --- a/Account/Account.struct.h +++ b/Account/Account.struct.h @@ -36,6 +36,7 @@ class Serializer; // Includes. #include "../Serializer.mqh" +#include "../Terminal.define.h" // Struct for account entries. struct AccountEntry { diff --git a/Account/AccountBase.struct.h b/Account/AccountBase.struct.h index 535d3cae7..f58e25e7f 100644 --- a/Account/AccountBase.struct.h +++ b/Account/AccountBase.struct.h @@ -36,6 +36,7 @@ class Serializer; // Includes. #include "../Serializer.mqh" +#include "../Terminal.define.h" // Struct for account entries. struct AccountBaseEntry { diff --git a/Account/AccountForex.struct.h b/Account/AccountForex.struct.h index 9bf5c8901..64aacffa3 100644 --- a/Account/AccountForex.struct.h +++ b/Account/AccountForex.struct.h @@ -36,6 +36,7 @@ class Serializer; // Includes. #include "../Serializer.mqh" +#include "../Terminal.define.h" // Struct for account entries. struct AccountForexEntry : public AccountBaseEntry { diff --git a/Account/tests/Account.test.mq5 b/Account/tests/Account.test.mq5 index 6ed1a1263..a52e8c076 100644 --- a/Account/tests/Account.test.mq5 +++ b/Account/tests/Account.test.mq5 @@ -35,7 +35,7 @@ int OnInit() { bool _result = true; Account acc1; // ... - return _result && GetLastError() == ERR_NO_ERROR ? INIT_SUCCEEDED : INIT_FAILED; + return _result && GetLastError() == 0 ? INIT_SUCCEEDED : INIT_FAILED; } /** diff --git a/Account/tests/AccountForex.test.mq5 b/Account/tests/AccountForex.test.mq5 index 826aa4235..fb10957ea 100644 --- a/Account/tests/AccountForex.test.mq5 +++ b/Account/tests/AccountForex.test.mq5 @@ -35,7 +35,7 @@ int OnInit() { bool _result = true; Account acc1; // ... - return _result && GetLastError() == ERR_NO_ERROR ? INIT_SUCCEEDED : INIT_FAILED; + return _result && GetLastError() == 0 ? INIT_SUCCEEDED : INIT_FAILED; } /** diff --git a/Array.extern.h b/Array.extern.h new file mode 100644 index 000000000..b09748d67 --- /dev/null +++ b/Array.extern.h @@ -0,0 +1,57 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2022, 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 . + * + */ + +// Define external global functions. +#ifndef __MQL__ +#pragma once + +template +extern int ArraySize(const ARRAY_REF(T, _array)); + +template +extern constexpr int ArraySize(const T REF(_array)[size]); + +template +extern int ArrayResize(ARRAY_REF(T, _array), int _new_size, int _reserve_size = 0); + +template +extern bool ArraySetAsSeries(ARRAY_REF(T, _array), bool _flag); + +template +extern int ArrayMaximum(const ARRAY_REF(T, _array), int _start = 0, unsigned int _count = WHOLE_ARRAY); + +template +extern int ArrayMinimum(const ARRAY_REF(T, _array), int _start = 0, unsigned int _count = WHOLE_ARRAY); + +template +extern int ArrayFree(const ARRAY_REF(T, _array)); + +template +extern int ArrayReverse(const ARRAY_REF(T, _array)); + +template +extern int ArrayInitialize(ARRAY_REF(T, array), char value); + +template +extern int ArraySort(ARRAY_REF(T, array)); + +#endif diff --git a/Array.mqh b/Array.mqh index e07e0d0a2..c844c8c4e 100644 --- a/Array.mqh +++ b/Array.mqh @@ -26,7 +26,12 @@ #endif // Includes. +#include "Array.extern.h" +#include "Common.extern.h" +#include "Convert.extern.h" +#include "Math.extern.h" #include "Std.h" +#include "String.extern.h" // Defines. #ifndef MODE_ASCEND @@ -529,7 +534,7 @@ static int GetLowestArrDoubleValue(double& arr[][], int key) { */ template void ArrayPrint(ARRAY_REF(T, _arr), // Printed array. - int _digits = NULL, // Number of decimal places. + int _digits = 0, // Number of decimal places. const string _dlm = NULL, // Separator of the structure field values. long _start = 0, // First printed element index. long _count = WHOLE_ARRAY, // Number of printed elements. @@ -539,7 +544,7 @@ static int GetLowestArrDoubleValue(double& arr[][], int key) { #else int i; string output = ""; - for (i = _start; i < _count == WHOLE_ARRAY ? ArraySize(_arr) : _count; i++) { + for (i = _start; i < (_count == WHOLE_ARRAY ? ArraySize(_arr) : _count); i++) { output += (string)_arr[i] + _dlm; } Print(output); @@ -635,7 +640,7 @@ static int GetLowestArrDoubleValue(double& arr[][], int key) { * if error occured). */ template - static int ArrayResizeFill(ARRAY_REF(X, array), int new_size, int reserve_size = 0, Y fill_value = EMPTY_VALUE) { + static int ArrayResizeFill(ARRAY_REF(X, array), int new_size, int reserve_size = 0, Y fill_value = NULL) { const int old_size = ArrayRange(array, 0); if (new_size <= old_size) return old_size; @@ -686,7 +691,7 @@ static int GetLowestArrDoubleValue(double& arr[][], int key) { * - https://www.mql5.com/en/docs/array/arraymaximum */ template - static int ArrayMinimum(const ARRAY_REF(X, _array), int _start = 0, int _count = WHOLE_ARRAY) { + static int ArrayMinimum(ARRAY_REF(X, _array), int _start = 0, int _count = WHOLE_ARRAY) { #ifdef __MQL__ return ::ArrayMinimum(_array); #else @@ -719,7 +724,7 @@ static int GetLowestArrDoubleValue(double& arr[][], int key) { * - https://www.mql5.com/en/docs/array/arraymaximum */ template - static int ArrayMaximum(const ARRAY_REF(X, _array), int start = 0, int count = WHOLE_ARRAY) { + static int ArrayMaximum(ARRAY_REF(X, _array), int start = 0, int count = WHOLE_ARRAY) { #ifdef __MQL__ return ::ArrayMaximum(_array); #else diff --git a/Chart.struct.tf.h b/Chart.struct.tf.h index 70231bf47..521ea3e6c 100644 --- a/Chart.struct.tf.h +++ b/Chart.struct.tf.h @@ -33,6 +33,7 @@ // Includes. #include "Chart.enum.h" #include "Serializer.mqh" +#include "Terminal.define.h" /* Defines struct for chart timeframe. */ struct ChartTf { diff --git a/Common.define.h b/Common.define.h new file mode 100644 index 000000000..09f7d754a --- /dev/null +++ b/Common.define.h @@ -0,0 +1,35 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2022, 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 + * Defines common defines. + */ +#ifndef __MQL__ +// Data types. +#include +typedef std::string string; +typedef unsigned char uchar; +typedef unsigned int uint; +typedef unsigned long ulong; +typedef unsigned short ushort; +#endif diff --git a/Common.extern.h b/Common.extern.h new file mode 100644 index 000000000..2092a4c16 --- /dev/null +++ b/Common.extern.h @@ -0,0 +1,47 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2022, 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 . + * + */ + +// Define external global functions. +#ifndef __MQL__ +#pragma once +#include "Chart.enum.h" +#include "DateTime.enum.h" + +extern void DebugBreak(); +// Errors. +extern void SetUserError(ushort user_error); +// Exceptions. +extern int NotImplementedException(); +// Print-related functions. +template +extern std::string StringFormat(const std::string& format, Args... args); + +template +extern std::string PrintFormat(const std::string& format, Args... args); + +template +extern void Print(Args... args); + +template +extern void Alert(Args... args); + +#endif diff --git a/Condition.mqh b/Condition.mqh index 862d20264..9118becab 100644 --- a/Condition.mqh +++ b/Condition.mqh @@ -109,13 +109,13 @@ class Condition { if (_entry.IsActive()) { switch (_entry.next_statement) { case COND_AND: - _curr_result = _prev_result && this.Test(_entry); + _curr_result = _prev_result && this PTR_DEREF Test(_entry); break; case COND_OR: - _curr_result = _prev_result || this.Test(_entry); + _curr_result = _prev_result || this PTR_DEREF Test(_entry); break; case COND_SEQ: - _curr_result = this.Test(_entry); + _curr_result = this PTR_DEREF Test(_entry); if (!_curr_result) { // Do not check further conditions when the current condition is false. return false; diff --git a/Convert.extern.h b/Convert.extern.h new file mode 100644 index 000000000..353a96b6b --- /dev/null +++ b/Convert.extern.h @@ -0,0 +1,34 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2022, 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 __MQL__ +#pragma once +#endif + +// Define external global functions. +#ifndef __MQL__ +extern double NormalizeDouble(double value, int digits); +extern string CharToString(uchar char_code); +extern string DoubleToString(double value, int digits = 8); +extern string ShortToString(ushort symbol_code); +#endif diff --git a/Convert.mqh b/Convert.mqh index 22352cfa2..9c0fbae7e 100644 --- a/Convert.mqh +++ b/Convert.mqh @@ -24,11 +24,20 @@ #ifndef CONVERT_MQH #define CONVERT_MQH +// Prevents processing this includes file for the second time. +#ifndef __MQL__ +#pragma once +#endif + // Includes. #include "Account/Account.enum.h" +#include "Account/Account.extern.h" #include "Array.mqh" +#include "Convert.extern.h" +#include "Math.extern.h" #include "Order.enum.h" #include "SymbolInfo.enum.h" +#include "SymbolInfo.extern.h" #include "SymbolInfo.struct.static.h" /** @@ -58,7 +67,7 @@ class Convert { case ORDER_TYPE_BUY_STOP: return ORDER_TYPE_BUY; default: - return (ENUM_ORDER_TYPE)WRONG_VALUE; + return InvalidEnumValue::value(); } } @@ -73,7 +82,7 @@ class Convert { * Returns OP_BUY when value is positive, OP_SELL when negative, otherwise -1. */ static ENUM_ORDER_TYPE ValueToOp(int value) { - return value == 0 ? (ENUM_ORDER_TYPE)-1 : (value > 0 ? ORDER_TYPE_BUY : ORDER_TYPE_SELL); + return value == 0 ? InvalidEnumValue::value() : (value > 0 ? ORDER_TYPE_BUY : ORDER_TYPE_SELL); } /** @@ -87,13 +96,13 @@ class Convert { * Returns OP_BUY when value is positive, OP_SELL when negative, otherwise -1. */ static ENUM_ORDER_TYPE ValueToOp(double value) { - return value == 0 ? (ENUM_ORDER_TYPE)-1 : (value > 0 ? ORDER_TYPE_BUY : ORDER_TYPE_SELL); + return value == 0 ? InvalidEnumValue::value() : (value > 0 ? ORDER_TYPE_BUY : ORDER_TYPE_SELL); } /** * Points per pip given digits after decimal point of a symbol price. */ - static uint PointsPerPip(uint digits) { return (uint)pow(10, digits - (digits < 4 ? 2 : 4)); } + static uint PointsPerPip(uint digits) { return (uint)pow((unsigned int)10, digits - (digits < 4 ? 2 : 4)); } /** * Returns number of points per pip. @@ -172,19 +181,19 @@ class Convert { switch (mode) { case 0: // Forex. // In currencies a tick is a point. - return pts * SymbolInfoStatic::SymbolInfoDouble(_symbol, SYMBOL_TRADE_TICK_SIZE); + return (double)pts * SymbolInfoStatic::SymbolInfoDouble(_symbol, SYMBOL_TRADE_TICK_SIZE); case 1: // CFD. // In metals a Tick is still the smallest change, but is larger than a point. // If price can change from 123.25 to 123.50, // you have a TickSize of 0.25 and a point of 0.01. Pip has no meaning. // @todo - return pts * SymbolInfoStatic::SymbolInfoDouble(_symbol, SYMBOL_TRADE_TICK_SIZE); + return (double)pts * SymbolInfoStatic::SymbolInfoDouble(_symbol, SYMBOL_TRADE_TICK_SIZE); case 2: // Futures. // @todo - return pts * SymbolInfoStatic::SymbolInfoDouble(_symbol, SYMBOL_TRADE_TICK_SIZE); + return (double)pts * SymbolInfoStatic::SymbolInfoDouble(_symbol, SYMBOL_TRADE_TICK_SIZE); case 3: // CFD for indices. // @todo - return pts * SymbolInfoStatic::SymbolInfoDouble(_symbol, SYMBOL_TRADE_TICK_SIZE); + return (double)pts * SymbolInfoStatic::SymbolInfoDouble(_symbol, SYMBOL_TRADE_TICK_SIZE); } return false; } @@ -243,7 +252,7 @@ class Convert { /** * Get the difference between two price values (in pips). */ - static double GetValueDiffInPips(double price1, double price2, bool abs = false, int digits = NULL, + static double GetValueDiffInPips(double price1, double price2, bool abs = false, int digits = 0, string _symbol = NULL) { digits = digits ? digits : (int)SymbolInfoStatic::SymbolInfoInteger(_symbol, SYMBOL_DIGITS); return ValueToPips(abs ? fabs(price1 - price2) : (price1 - price2), digits); @@ -263,7 +272,7 @@ class Convert { else if (currency == "EUR") sign = (unsigned char)0x80; // ANSI code. else { - sign = NULL; + sign = ' '; prefix = false; } return prefix ? CharToString(sign) + DoubleToString(value, digits) diff --git a/DateTime.extern.h b/DateTime.extern.h new file mode 100644 index 000000000..87d156d81 --- /dev/null +++ b/DateTime.extern.h @@ -0,0 +1,79 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2022, 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 "DateTime.enum.h" + +/** + * @file + * Includes external declarations related to date and time. + */ +#ifndef __MQL__ +#pragma once +// Forward declarations. +struct MqlDateTime; + +/** + * MQL's "datetime" type. + */ +class datetime { + time_t dt; + + public: + datetime(); + datetime(const long& _time); + datetime(const int& _time); + bool operator==(const int& _time) const; + bool operator==(const datetime& _time) const; + bool operator<(const int& _time) const; + bool operator>(const int& _time) const; + bool operator<(const datetime& _time); + bool operator>(const datetime& _time); + operator long() const; +}; + +extern datetime TimeCurrent(); +extern datetime TimeCurrent(MqlDateTime& dt_struct); + +extern int CopyTime(string symbol_name, ENUM_TIMEFRAMES timeframe, int start_pos, int count, + ARRAY_REF(datetime, time_array)); + +extern int CopyTime(string symbol_name, ENUM_TIMEFRAMES timeframe, datetime start_time, int count, + ARRAY_REF(datetime, time_array)); + +extern int CopyTime(string symbol_name, ENUM_TIMEFRAMES timeframe, datetime start_time, datetime stop_time, + ARRAY_REF(datetime, time_array)); + +extern datetime StructToTime(MqlDateTime& dt_struct); +extern bool TimeToStruct(datetime dt, MqlDateTime& dt_struct); +extern datetime TimeGMT(); +extern datetime TimeGMT(MqlDateTime& dt_struct); +extern datetime TimeTradeServer(); +extern datetime TimeTradeServer(MqlDateTime& dt_struct); +extern datetime StringToTime(const string& value); +extern string TimeToString(datetime value, int mode = TIME_DATE | TIME_MINUTES); + +template +extern datetime operator"" _D(); + +#define DATETIME_LITERAL(STR) _D " ## STR ## " +#endif diff --git a/DateTime.mqh b/DateTime.mqh index 49502d55f..fd26c7021 100644 --- a/DateTime.mqh +++ b/DateTime.mqh @@ -40,6 +40,7 @@ struct DataParamEntry; #include "Array.mqh" #include "Data.struct.h" #include "DateTime.enum.h" +#include "DateTime.extern.h" #include "DateTime.struct.h" #ifndef __MQL4__ @@ -113,9 +114,14 @@ class DateTime { _result |= DATETIME_SECOND; } - if (dt_curr.GetValue(DATETIME_DAY | DATETIME_WEEK) != dt_last.GetValue(DATETIME_DAY | DATETIME_WEEK)) { - // New week started. - _result |= DATETIME_WEEK; + if (dt_curr.GetValue(DATETIME_DAY | DATETIME_WEEK) == 0) { + // It's the first day of the week (Sunday). + // Note that GetValue() for the above flags just returns value of GetDayOfWeek(). + // @see https://docs.mql4.com/dateandtime/dayofweek + if (dt_curr.GetValue(DATETIME_DAY | DATETIME_WEEK) != dt_last.GetValue(DATETIME_DAY | DATETIME_WEEK)) { + // New week started. + _result |= DATETIME_WEEK; + } } #ifdef __debug__ diff --git a/Dict.enum.h b/Dict.enum.h index 33887918c..080a50271 100644 --- a/Dict.enum.h +++ b/Dict.enum.h @@ -32,3 +32,24 @@ #define DICT_GROW_UP_PERCENT_DEFAULT 25 #define DICT_PERFORMANCE_PROBLEM_AVG_CONFLICTS 10 + +/** + * Whether Dict operates in yet uknown mode, as dict or as list. + */ +enum DictMode { DictModeUnknown, DictModeDict, DictModeList }; + +/** + * Reason of call to overflow listener. + */ +enum ENUM_DICT_OVERFLOW_REASON { + DICT_OVERFLOW_REASON_FULL, + DICT_OVERFLOW_REASON_TOO_MANY_CONFLICTS, +}; + +/** + * Dictionary flags. + */ +enum ENUM_DICT_FLAG { + DICT_FLAG_NONE = 0, + DICT_FLAG_FILL_HOLES_UNSORTED = 1, +}; diff --git a/Dict.mqh b/Dict.mqh index 26bd9705a..4a3b2ec04 100644 --- a/Dict.mqh +++ b/Dict.mqh @@ -28,6 +28,7 @@ #include "DictBase.mqh" #include "Matrix.mqh" #include "Serializer.mqh" +#include "SerializerNodeIterator.mqh" template class DictIterator : public DictIteratorBase { diff --git a/DictBase.mqh b/DictBase.mqh index 6e80dd8ed..7993e1afc 100644 --- a/DictBase.mqh +++ b/DictBase.mqh @@ -31,27 +31,6 @@ #include "DictSlot.mqh" #include "Serializer.mqh" -/** - * Whether Dict operates in yet uknown mode, as dict or as list. - */ -enum DictMode { DictModeUnknown, DictModeDict, DictModeList }; - -/** - * Reason of call to overflow listener. - */ -enum ENUM_DICT_OVERFLOW_REASON { - DICT_OVERFLOW_REASON_FULL, - DICT_OVERFLOW_REASON_TOO_MANY_CONFLICTS, -}; - -/** - * Dictionary flags. - */ -enum ENUM_DICT_FLAG { - DICT_FLAG_NONE = 0, - DICT_FLAG_FILL_HOLES_UNSORTED = 1, -}; - /** * Dictionary overflow listener. arguments are: * - ENUM_DICT_OVERFLOW_REASON overflow_reason @@ -225,7 +204,7 @@ class DictBase { if (_DictSlots_ref.DictSlots[position].IsUsed()) { if (GetMode() == DictModeList) { - _should_be_removed = position == (int)key; + _should_be_removed = position == (unsigned int)key; } else { _should_be_removed = _DictSlots_ref.DictSlots[position].HasKey() && _DictSlots_ref.DictSlots[position].key == key; @@ -274,7 +253,7 @@ class DictBase { */ void FillHoleUnsorted(int _hole_slot_idx) { // After moving last element to fill the hole we - if (_hole_slot_idx == Size() - 1) { + if ((unsigned int)_hole_slot_idx == Size() - 1) { // We've just removed last element, thus don't need to do anything. } else { // Moving last slot into given one. @@ -378,10 +357,10 @@ class DictBase { * Specialization of hashing function. */ unsigned int Hash(const string& x) { - unsigned char c[]; + ARRAY(unsigned char, c); unsigned int h = 0; - if (x != NULL) { + if (!IsNull(x)) { h = 5381; int n = StringToCharArray(x, c); for (int i = 0; i < n; i++) { diff --git a/DictIteratorBase.mqh b/DictIteratorBase.mqh index 16fafb8a8..329fc5cb8 100644 --- a/DictIteratorBase.mqh +++ b/DictIteratorBase.mqh @@ -60,7 +60,7 @@ class DictIteratorBase { */ DictIteratorBase(const DictIteratorBase& right) : _dict(right._dict), - _hash(right._dict ? right._dict.GetHash() : 0), + _hash(right._dict ? right._dict PTR_DEREF GetHash() : 0), _slotIdx(right._slotIdx), _index(right._index) { _invalid_until_incremented = false; @@ -75,24 +75,24 @@ class DictIteratorBase { ++_index; _invalid_until_incremented = false; - DictSlot* slot = _dict.GetSlot(_slotIdx); + DictSlot* slot = _dict PTR_DEREF GetSlot(_slotIdx); // Iterating until we find valid, used slot. - while (slot != NULL && !slot.IsUsed()) { - slot = _dict.GetSlot(++_slotIdx); + while (slot != NULL && !slot PTR_DEREF IsUsed()) { + slot = _dict PTR_DEREF GetSlot(++_slotIdx); } - if (!slot || !slot.IsValid()) { + if (!slot || !slot PTR_DEREF IsValid()) { // Invalidating iterator. _dict = NULL; } } - bool HasKey() { return _dict.GetSlot(_slotIdx).HasKey(); } + bool HasKey() { return _dict PTR_DEREF GetSlot(_slotIdx) PTR_DEREF HasKey(); } K Key() { CheckValidity(); - return _dict.GetMode() == DictModeList ? (K)_slotIdx : _dict.GetSlot(_slotIdx).key; + return PTR_ATTRIB(_dict, GetMode()) == DictModeList ? (K)_slotIdx : _dict PTR_DEREF GetSlot(_slotIdx) PTR_DEREF key; } string KeyAsString(bool includeQuotes = false) { @@ -106,7 +106,7 @@ class DictIteratorBase { V Value() { CheckValidity(); - return _dict.GetSlot(_slotIdx).value; + return _dict PTR_DEREF GetSlot(_slotIdx) PTR_DEREF value; } void CheckValidity() { @@ -121,15 +121,15 @@ class DictIteratorBase { bool IsLast() { if (!IsValid()) return true; - if (_dict.GetMode() == DictModeUnknown || _dict.Size() == 0) { + if (_dict PTR_DEREF GetMode() == DictModeUnknown || _dict.Size() == 0) { return false; } - if (_dict.GetMode() != DictModeList) { + if (_dict PTR_DEREF GetMode() != DictModeList) { Alert("Dict iterator's IsLast() method may be used only when elements are added via Push() method."); } - return _index == _dict.Size() - 1; + return _index == _dict PTR_DEREF Size() - 1; } void ShiftPosition(int shift, bool invalid_until_incremented = false) { diff --git a/DictObject.mqh b/DictObject.mqh index 59ba0410a..fbfd681aa 100644 --- a/DictObject.mqh +++ b/DictObject.mqh @@ -27,6 +27,7 @@ #include "Convert.mqh" #include "DictBase.mqh" #include "Serializer.mqh" +#include "SerializerNodeIterator.mqh" template class DictObjectIterator : public DictIteratorBase { @@ -39,14 +40,14 @@ class DictObjectIterator : public DictIteratorBase { /** * Constructor. */ - DictObjectIterator(DictBase& dict, unsigned int slotIdx) : DictIteratorBase(dict, slotIdx) {} + DictObjectIterator(DictBase& dict, unsigned int slotIdx) : DictIteratorBase(dict, slotIdx) {} /** * Copy constructor. */ - DictObjectIterator(const DictObjectIterator& right) : DictIteratorBase(right) {} + DictObjectIterator(const DictObjectIterator& right) : DictIteratorBase(right) {} - V* Value() { return &_dict.GetSlot(_slotIdx).value; } + V* Value() { return &(this PTR_DEREF _dict PTR_DEREF GetSlot(this PTR_DEREF _slotIdx) PTR_DEREF value); } }; /** @@ -71,37 +72,50 @@ class DictObject : public DictBase { Clear(); Resize(right.GetSlotCount()); for (unsigned int i = 0; i < (unsigned int)ArraySize(right._DictSlots_ref.DictSlots); ++i) { - _DictSlots_ref.DictSlots[i] = right._DictSlots_ref.DictSlots[i]; + this PTR_DEREF _DictSlots_ref.DictSlots[i] = right._DictSlots_ref.DictSlots[i]; } - _DictSlots_ref._num_used = right._DictSlots_ref._num_used; - _current_id = right._current_id; - _mode = right._mode; + this PTR_DEREF _DictSlots_ref._num_used = right._DictSlots_ref._num_used; + this PTR_DEREF _current_id = right._current_id; + this PTR_DEREF _mode = right._mode; + } + + DictObjectIterator Begin() { + // Searching for first item index. + for (unsigned int i = 0; i < (unsigned int)ArraySize(this PTR_DEREF _DictSlots_ref.DictSlots); ++i) { + if (this PTR_DEREF _DictSlots_ref.DictSlots[i].IsValid() && this PTR_DEREF _DictSlots_ref.DictSlots[i].IsUsed()) { + DictObjectIterator iter(THIS_REF, i); + return iter; + } + } + // No items found. + DictObjectIterator invalid; + return invalid; } void operator=(const DictObject& right) { Clear(); Resize(right.GetSlotCount()); for (unsigned int i = 0; i < (unsigned int)ArraySize(right._DictSlots_ref.DictSlots); ++i) { - _DictSlots_ref.DictSlots[i] = right._DictSlots_ref.DictSlots[i]; + this PTR_DEREF _DictSlots_ref.DictSlots[i] = right._DictSlots_ref.DictSlots[i]; } - _DictSlots_ref._num_used = right._DictSlots_ref._num_used; - _current_id = right._current_id; - _mode = right._mode; + this PTR_DEREF _DictSlots_ref._num_used = right._DictSlots_ref._num_used; + this PTR_DEREF _current_id = right._current_id; + this PTR_DEREF _mode = right._mode; } void Clear() { - for (unsigned int i = 0; i < (unsigned int)ArraySize(_DictSlots_ref.DictSlots); ++i) { - _DictSlots_ref.DictSlots[i].SetFlags(0); + for (unsigned int i = 0; i < (unsigned int)ArraySize(this PTR_DEREF _DictSlots_ref.DictSlots); ++i) { + this PTR_DEREF _DictSlots_ref.DictSlots[i].SetFlags(0); } - _DictSlots_ref._num_used = 0; + this PTR_DEREF _DictSlots_ref._num_used = 0; } /** * Inserts value using hashless key. */ bool Push(V& value) { - if (!InsertInto(_DictSlots_ref, value)) return false; + if (!InsertInto(this PTR_DEREF _DictSlots_ref, value)) return false; return true; } @@ -114,7 +128,7 @@ class DictObject : public DictBase { * Inserts or replaces value for a given key. */ bool Set(K key, V& value) { - if (!InsertInto(_DictSlots_ref, key, value, true)) return false; + if (!InsertInto(this PTR_DEREF _DictSlots_ref, key, value, true)) return false; return true; } @@ -123,10 +137,10 @@ class DictObject : public DictBase { unsigned int position; - if (_mode == DictModeList) - slot = GetSlot((unsigned int)key); + if (this PTR_DEREF _mode == DictModeList) + slot = this PTR_DEREF GetSlot((unsigned int)key); else - slot = GetSlotByKey(_DictSlots_ref, key, position); + slot = GetSlotByKey(this PTR_DEREF _DictSlots_ref, key, position); if (slot == NULL || !slot.IsUsed()) return NULL; @@ -138,7 +152,7 @@ class DictObject : public DictBase { */ V* GetByKey(const K _key) { unsigned int position; - DictSlot* slot = GetSlotByKey(_DictSlots_ref, _key, position); + DictSlot* slot = GetSlotByKey(this PTR_DEREF _DictSlots_ref, _key, position); if (!slot) return NULL; @@ -149,7 +163,7 @@ class DictObject : public DictBase { * Returns value for a given position. */ V* GetByPos(unsigned int _position) { - DictSlot* slot = GetSlotByPos(_DictSlots_ref, _position); + DictSlot* slot = this PTR_DEREF GetSlotByPos(this PTR_DEREF _DictSlots_ref, _position); if (!slot) { Alert("Invalid DictStruct position \"", _position, "\" (called by GetByPos()). Returning empty structure."); @@ -163,10 +177,12 @@ class DictObject : public DictBase { /** * Checks whether dictionary contains given key => value pair. */ +#ifdef __MQL__ template <> +#endif bool Contains(const K key, const V& value) { unsigned int position; - DictSlot* slot = GetSlotByKey(_DictSlots_ref, key, position); + DictSlot* slot = GetSlotByKey(this PTR_DEREF _DictSlots_ref, key, position); if (!slot) return false; @@ -176,7 +192,9 @@ class DictObject : public DictBase { /** * Returns index of dictionary's value or -1 if value doesn't exist. */ +#ifdef __MQL__ template <> +#endif int IndexOf(V& value) { for (DictIteratorBase i(Begin()); i.IsValid(); ++i) { if (i.Value() == value) { @@ -192,37 +210,37 @@ class DictObject : public DictBase { * Inserts value into given array of DictSlots. */ bool InsertInto(DictSlotsRef& dictSlotsRef, const K key, V& value, bool allow_resize) { - if (_mode == DictModeUnknown) - _mode = DictModeDict; - else if (_mode != DictModeDict) { + if (this PTR_DEREF _mode == DictModeUnknown) + this PTR_DEREF _mode = DictModeDict; + else if (this PTR_DEREF _mode != DictModeDict) { Alert("Warning: Dict already operates as a list, not a dictionary!"); return false; } unsigned int position; - DictSlot* keySlot = GetSlotByKey(dictSlotsRef, key, position); + DictSlot* keySlot = this PTR_DEREF GetSlotByKey(dictSlotsRef, key, position); - if (keySlot == NULL && !IsGrowUpAllowed()) { + if (keySlot == NULL && !this PTR_DEREF IsGrowUpAllowed()) { // Resize is prohibited. return false; } // Will resize dict if there were performance problems before. - if (allow_resize && IsGrowUpAllowed() && !dictSlotsRef.IsPerformant()) { + if (allow_resize && this PTR_DEREF IsGrowUpAllowed() && !dictSlotsRef.IsPerformant()) { if (!GrowUp()) { return false; } // We now have new positions of slots, so we have to take the corrent slot again. - keySlot = GetSlotByKey(dictSlotsRef, key, position); + keySlot = this PTR_DEREF GetSlotByKey(dictSlotsRef, key, position); } if (keySlot == NULL && dictSlotsRef._num_used == ArraySize(dictSlotsRef.DictSlots)) { // No DictSlotsRef.DictSlots available. - if (overflow_listener != NULL) { - if (!overflow_listener(DICT_OVERFLOW_REASON_FULL, dictSlotsRef._num_used, 0)) { + if (this PTR_DEREF overflow_listener != NULL) { + if (!this PTR_DEREF overflow_listener(DICT_OVERFLOW_REASON_FULL, dictSlotsRef._num_used, 0)) { // Overwriting slot pointed exactly by key's position in the hash table (we don't check for possible // conflicts). - keySlot = &dictSlotsRef.DictSlots[Hash(key) % ArraySize(dictSlotsRef.DictSlots)]; + keySlot = &dictSlotsRef.DictSlots[this PTR_DEREF Hash(key) % ArraySize(dictSlotsRef.DictSlots)]; } } @@ -233,18 +251,20 @@ class DictObject : public DictBase { } if (keySlot == NULL) { - position = Hash(key) % ArraySize(dictSlotsRef.DictSlots); + position = this PTR_DEREF Hash(key) % ArraySize(dictSlotsRef.DictSlots); unsigned int _starting_position = position; - int _num_conflicts = 0; + unsigned int _num_conflicts = 0; bool _overwrite_slot = false; // Searching for empty DictSlot or used one with the matching key. It skips used, hashless DictSlots. while (dictSlotsRef.DictSlots[position].IsUsed() && (!dictSlotsRef.DictSlots[position].HasKey() || dictSlotsRef.DictSlots[position].key != key)) { - if (overflow_listener_max_conflicts != 0 && ++_num_conflicts == overflow_listener_max_conflicts) { - if (overflow_listener != NULL) { - if (!overflow_listener(DICT_OVERFLOW_REASON_TOO_MANY_CONFLICTS, dictSlotsRef._num_used, _num_conflicts)) { + if (this PTR_DEREF overflow_listener_max_conflicts != 0 && + ++_num_conflicts == this PTR_DEREF overflow_listener_max_conflicts) { + if (this PTR_DEREF overflow_listener != NULL) { + if (!this PTR_DEREF overflow_listener(DICT_OVERFLOW_REASON_TOO_MANY_CONFLICTS, dictSlotsRef._num_used, + _num_conflicts)) { // Overflow listener returned false so we won't search for further empty slot. _overwrite_slot = true; break; @@ -282,9 +302,9 @@ class DictObject : public DictBase { * Inserts hashless value into given array of DictSlots. */ bool InsertInto(DictSlotsRef& dictSlotsRef, V& value) { - if (_mode == DictModeUnknown) - _mode = DictModeList; - else if (_mode != DictModeList) { + if (this PTR_DEREF _mode == DictModeUnknown) + this PTR_DEREF _mode = DictModeList; + else if (this PTR_DEREF _mode != DictModeList) { Alert("Warning: Dict already operates as a dictionary, not a list!"); DebugBreak(); return false; @@ -295,7 +315,8 @@ class DictObject : public DictBase { if (!GrowUp()) return false; } - unsigned int position = Hash((unsigned int)dictSlotsRef._list_index) % ArraySize(dictSlotsRef.DictSlots); + unsigned int position = + this PTR_DEREF Hash((unsigned int)dictSlotsRef._list_index) % ArraySize(dictSlotsRef.DictSlots); // Searching for empty DictSlot. while (dictSlotsRef.DictSlots[position].IsUsed()) { @@ -315,14 +336,16 @@ class DictObject : public DictBase { * Expands array of DictSlots by given percentage value. */ bool GrowUp(int percent = DICT_GROW_UP_PERCENT_DEFAULT) { - return Resize(MathMax(10, (int)((float)ArraySize(_DictSlots_ref.DictSlots) * ((float)(percent + 100) / 100.0f)))); + return Resize(MathMax( + 10, (int)((float)ArraySize(this PTR_DEREF _DictSlots_ref.DictSlots) * ((float)(percent + 100) / 100.0f)))); } /** * Shrinks or expands array of DictSlots. */ bool Resize(int new_size) { - if (new_size <= MathMin(_DictSlots_ref._num_used, ArraySize(_DictSlots_ref.DictSlots))) { + if (new_size <= + MathMin(this PTR_DEREF _DictSlots_ref._num_used, ArraySize(this PTR_DEREF _DictSlots_ref.DictSlots))) { // We already use minimum number of slots possible. return true; } @@ -338,20 +361,21 @@ class DictObject : public DictBase { } // Copies entire array of DictSlots into new array of DictSlots. Hashes will be rehashed. - for (i = 0; i < ArraySize(_DictSlots_ref.DictSlots); ++i) { - if (!_DictSlots_ref.DictSlots[i].IsUsed()) continue; + for (i = 0; i < ArraySize(this PTR_DEREF _DictSlots_ref.DictSlots); ++i) { + if (!this PTR_DEREF _DictSlots_ref.DictSlots[i].IsUsed()) continue; - if (_DictSlots_ref.DictSlots[i].HasKey()) { - if (!InsertInto(new_DictSlots, _DictSlots_ref.DictSlots[i].key, _DictSlots_ref.DictSlots[i].value, false)) + if (this PTR_DEREF _DictSlots_ref.DictSlots[i].HasKey()) { + if (!InsertInto(new_DictSlots, this PTR_DEREF _DictSlots_ref.DictSlots[i].key, + this PTR_DEREF _DictSlots_ref.DictSlots[i].value, false)) return false; } else { - if (!InsertInto(new_DictSlots, _DictSlots_ref.DictSlots[i].value)) return false; + if (!InsertInto(new_DictSlots, this PTR_DEREF _DictSlots_ref.DictSlots[i].value)) return false; } } // Freeing old DictSlots array. - ArrayFree(_DictSlots_ref.DictSlots); + ArrayFree(this PTR_DEREF _DictSlots_ref.DictSlots); - _DictSlots_ref = new_DictSlots; + this PTR_DEREF _DictSlots_ref = new_DictSlots; return true; } @@ -362,10 +386,12 @@ class DictObject : public DictBase { #endif SerializerNodeType Serialize(Serializer& s) { if (s.IsWriting()) { - for (DictIteratorBase i(Begin()); i.IsValid(); ++i) - s.PassObject(this, GetMode() == DictModeDict ? i.KeyAsString() : "", i.Value()); + for (DictObjectIterator i(Begin()); i.IsValid(); ++i) { + V* _value = i.Value(); + s.PassObject(THIS_REF, this PTR_DEREF GetMode() == DictModeDict ? i.KeyAsString() : "", PTR_TO_REF(_value)); + } - return (GetMode() == DictModeDict) ? SerializerNodeObject : SerializerNodeArray; + return (this PTR_DEREF GetMode() == DictModeDict) ? SerializerNodeObject : SerializerNodeArray; } else { if (s.IsArray()) { unsigned int num_items = s.NumArrayItems(); @@ -394,9 +420,11 @@ class DictObject : public DictBase { // Note that we're retrieving value by a key (as we are in an // object!). - Set(key, i.Struct(i.Key())); + V _prop = i.Struct(i.Key()); + Set(key, _prop); } else { - Push(i.Struct()); + V _prop = i.Struct(); + Push(_prop); } } return i.ParentNodeType(); @@ -407,7 +435,9 @@ class DictObject : public DictBase { /** * Initializes object with given number of elements. Could be skipped for non-containers. */ +#ifdef __MQL__ template <> +#endif void SerializeStub(int _n1 = 1, int _n2 = 1, int _n3 = 1, int _n4 = 1, int _n5 = 1) { V _child; diff --git a/DictSlot.mqh b/DictSlot.mqh index c64aa3eda..3c1fe29e1 100644 --- a/DictSlot.mqh +++ b/DictSlot.mqh @@ -52,7 +52,7 @@ class DictSlot { void AddFlags(unsigned char flags) { _flags |= flags; } - void RemoveFlags(unsigned char flags) { _flags &= ~flags; } + void RemoveFlags(unsigned char flags) { _flags &= (unsigned char)~flags; } }; #endif diff --git a/DictSlotsRef.h b/DictSlotsRef.h index 140140c49..e5ae9ee58 100644 --- a/DictSlotsRef.h +++ b/DictSlotsRef.h @@ -38,7 +38,7 @@ class DictSlot; template struct DictSlotsRef { - DictSlot DictSlots[]; + ARRAY(DictSlot, DictSlots); // Incremental index for dict operating in list mode. int _list_index; @@ -61,7 +61,7 @@ struct DictSlotsRef { */ void AddConflicts(int num) { if (num != 0) { - _avg_conflicts += float(num) / ++_num_conflicts; + _avg_conflicts += (float)num / (float)++_num_conflicts; } } diff --git a/DictStruct.mqh b/DictStruct.mqh index b4cb0d747..405dcee7a 100644 --- a/DictStruct.mqh +++ b/DictStruct.mqh @@ -31,6 +31,7 @@ class Log; #include "DictBase.mqh" #include "DictIteratorBase.mqh" #include "Serializer.mqh" +#include "SerializerNodeIterator.mqh" // DictIterator could be used as DictStruct iterator. #define DictStructIterator DictIteratorBase diff --git a/EA.mqh b/EA.mqh index 63368f947..0fb8a1051 100644 --- a/EA.mqh +++ b/EA.mqh @@ -343,6 +343,12 @@ class EA { _strat.OnOrderOpen(_oparams); // Send the request. _result = _trade.RequestSend(_request, _oparams); + if (!_result) { + logger.Debug( + StringFormat("Error while sending a trade request! Entry: %s", + SerializerConverter::FromObject(MqlTradeRequestProxy(_request)).ToString()), + __FUNCTION_LINE__, StringFormat("Code: %d, Msg: %s", _LastError, Terminal::GetErrorText(_LastError))); + } return _result; } @@ -426,7 +432,7 @@ class EA { if (eparams.CheckFlagDataStore(EA_DATA_STORE_INDICATOR)) { for (DictStructIterator> iter = strats.Begin(); iter.IsValid(); ++iter) { Strategy *_strati = iter.Value().Ptr(); - IndicatorBase *_indi = _strati.GetIndicator(); + IndicatorData *_indi = _strati.GetIndicator(); if (_indi != NULL) { ENUM_TIMEFRAMES _itf = _indi.GetParams().tf.GetTf(); IndicatorDataEntry _ientry = _indi.GetEntry(); @@ -485,7 +491,7 @@ class EA { string _key_chart = "Chart"; _key_chart += StringFormat("-%d-%d", data_chart.GetMin(), data_chart.GetMax()); - SerializerConverter _stub = Serializer::MakeStubObject>(_serializer_flags); + SerializerConverter _stub = SerializerConverter::MakeStubObject>(_serializer_flags); SerializerConverter _obj = SerializerConverter::FromObject(data_chart, _serializer_flags); if ((_methods & EA_DATA_EXPORT_CSV) != 0) { @@ -505,7 +511,8 @@ class EA { _obj.Clean(); } if (eparams.CheckFlagDataStore(EA_DATA_STORE_INDICATOR)) { - SerializerConverter _stub = Serializer::MakeStubObject>(_serializer_flags); + SerializerConverter _stub = + SerializerConverter::MakeStubObject>(_serializer_flags); /* for (DictStructIterator> iter = strats.Begin(); iter.IsValid(); ++iter) { @@ -540,7 +547,7 @@ class EA { _stub.Clean(); } if (eparams.CheckFlagDataStore(EA_DATA_STORE_STRATEGY)) { - SerializerConverter _stub = Serializer::MakeStubObject>(_serializer_flags); + SerializerConverter _stub = SerializerConverter::MakeStubObject>(_serializer_flags); /* @fixme for (DictStructIterator> iter = strats.Begin(); iter.IsValid(); ++iter) { @@ -570,7 +577,7 @@ class EA { _stub.Clean(); } if (eparams.CheckFlagDataStore(EA_DATA_STORE_SYMBOL)) { - SerializerConverter _stub = Serializer::MakeStubObject>(_serializer_flags); + SerializerConverter _stub = SerializerConverter::MakeStubObject>(_serializer_flags); SerializerConverter _obj = SerializerConverter::FromObject(data_symbol, _serializer_flags); string _key_sym = "Symbol"; diff --git a/Exchange/Exchange.h b/Exchange/Exchange.h new file mode 100644 index 000000000..85b9e9202 --- /dev/null +++ b/Exchange/Exchange.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 . + * + */ + +/** + * Exchange class. + */ +#ifndef EXCHANGE_H +#define EXCHANGE_H + +// Includes. +#include "../Account.mqh" +#include "../DictObject.mqh" +#include "../SymbolInfo.mqh" +#include "../Trade.mqh" +#include "Exchange.struct.h" + +class Exchange { + protected: + DictObject accounts; + DictObject symbols; + DictObject trades; + ExchangeParams eparams; + + public: + /** + * Class constructor without parameters. + */ + Exchange(){}; + + /** + * Class constructor with parameters. + */ + Exchange(ExchangeParams &_eparams) : eparams(_eparams){}; + + /** + * Class deconstructor. + */ + ~Exchange() {} + + /* Adders */ + + /** + * Adds account to the list. + */ + void AccountAdd(Account &_account, string _name) { accounts.Set(_name, _account); } + + /** + * Adds symbol to the list. + */ + void SymbolAdd(SymbolInfo &_sinfo, string _name) { symbols.Set(_name, _sinfo); } + + /* Removers */ + + /** + * Removes account from the list. + */ + void AccountRemove(string _name) { accounts.Unset(_name); } + + /** + * Removes symbol from the list. + */ + void SymbolRemove(string _name) { symbols.Unset(_name); } +}; +#endif // EXCHANGE_H diff --git a/Exchange/Exchange.struct.h b/Exchange/Exchange.struct.h new file mode 100644 index 000000000..d63290d4f --- /dev/null +++ b/Exchange/Exchange.struct.h @@ -0,0 +1,42 @@ +//+------------------------------------------------------------------+ +//| 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 Exchange's structs. + */ + +#ifndef __MQL__ +// Allows the preprocessor to include a header file when it is needed. +#pragma once +#endif + +// Forward class declaration. +class Exchange; + +/* Defines struct for Exchange parameters. */ +struct ExchangeParams { + // Constructors. + ExchangeParams() {} + ExchangeParams(const ExchangeParams &_eparams) {} + long id; +}; diff --git a/Exchange/tests/Exchange.test.mq4 b/Exchange/tests/Exchange.test.mq4 new file mode 100644 index 000000000..2b3fdf2da --- /dev/null +++ b/Exchange/tests/Exchange.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 Exchange class. + */ + +// Includes. +#include "Exchange.test.mq5" diff --git a/Exchange/tests/Exchange.test.mq5 b/Exchange/tests/Exchange.test.mq5 new file mode 100644 index 000000000..1c9d1c39b --- /dev/null +++ b/Exchange/tests/Exchange.test.mq5 @@ -0,0 +1,43 @@ +//+------------------------------------------------------------------+ +//| 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 Exchange class. + */ + +// Includes. +#include "../../Test.mqh" +#include "../Exchange.h" + +// Test classes. +class ExchangeDummy : public Exchange {}; + +// Global variables. +ExchangeDummy ex_dummy; + +/** + * Implements OnInit(). + */ +int OnInit() { + bool _result = true; + return _result && GetLastError() == ERR_NO_ERROR ? INIT_SUCCEEDED : INIT_FAILED; +} diff --git a/File.define.h b/File.define.h new file mode 100644 index 000000000..e932ab836 --- /dev/null +++ b/File.define.h @@ -0,0 +1,31 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2022, 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 . + * + */ + +// Defines. +#ifndef __MQL__ +// File constants to read the whole value of char, short or int type. +#define CHAR_VALUE 1 +#define INT_VALUE 4 +#define SHORT_VALUE 2 +// Used for checking file handles (see FileOpen() and FileFindFirst()). +#define INVALID_HANDLE -1 +#endif diff --git a/File.extern.h b/File.extern.h new file mode 100644 index 000000000..52e15849a --- /dev/null +++ b/File.extern.h @@ -0,0 +1,36 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2022, 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 "File.define.h" +#include "Terminal.define.h" + +// Define external global functions. +#ifndef __MQL__ +extern bool FileIsEnding(int file_handle); +extern bool FileIsExist(const string file_name, int common_flag = 0); +extern int FileClose(int file_handle); +extern int FileOpen(string file_name, int open_flags, short delimiter = '\t', uint codepage = CP_ACP); +extern int FileReadInteger(int file_handle, int size = INT_VALUE); +extern string FileReadString(int file_handle, int length = -1); +extern uint FileWriteString(int file_handle, const string text_string, int length = -1); +#endif diff --git a/File.mqh b/File.mqh index 4fe3dcb6b..56c33bd57 100644 --- a/File.mqh +++ b/File.mqh @@ -30,7 +30,10 @@ */ // Includes. +#include "File.define.h" +#include "File.extern.h" #include "Terminal.define.h" +#include "Terminal.extern.h" #include "Terminal.enum.h" #ifndef __MQL__ diff --git a/Indicator.define.h b/Indicator.define.h index dc2d23d8a..74e3727fe 100644 --- a/Indicator.define.h +++ b/Indicator.define.h @@ -119,7 +119,7 @@ class DrawIndicator; _obj.SetHandle(_handle); \ } \ } \ - if (false && Terminal::IsVisualMode()) { \ + if (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); \ diff --git a/Indicator.enum.h b/Indicator.enum.h index 8bf58e7b1..bce168e60 100644 --- a/Indicator.enum.h +++ b/Indicator.enum.h @@ -132,28 +132,6 @@ enum ENUM_INDICATOR_TYPE { FINAL_INDICATOR_TYPE_ENTRY }; -/* Defines type of source data for */ -enum ENUM_IDATA_SOURCE_TYPE { - IDATA_BUILTIN = 0, // Platform built-in - IDATA_CHART, // Chart calculation - IDATA_ICUSTOM, // iCustom: Custom indicator file - IDATA_ICUSTOM_LEGACY, // iCustom: Custom, legacy, provided by MT indicator file - IDATA_INDICATOR, // OnIndicator: Another indicator as a source of data - IDATA_ONCALCULATE, // OnCalculate: Custom calculation function - IDATA_MATH // Math-based indicator -}; - -/* Defines range value data type for indicator storage. */ -enum ENUM_IDATA_VALUE_RANGE { - IDATA_RANGE_ARROW, // Value is non-zero on signal. - IDATA_RANGE_BINARY, // E.g. 0 or 1. - IDATA_RANGE_BITWISE, // Bitwise - IDATA_RANGE_MIXED, - IDATA_RANGE_PRICE, // Values represent price. - IDATA_RANGE_RANGE, // E.g. 0 to 100. - IDATA_RANGE_UNKNOWN -}; - // Indicator line identifiers used in ADX and ADXW enum ENUM_INDI_ADX_LINE { #ifdef __MQL4__ diff --git a/Indicator.mqh b/Indicator.mqh index 58f6d3744..49670df3e 100644 --- a/Indicator.mqh +++ b/Indicator.mqh @@ -38,8 +38,7 @@ class Chart; #include "Indicator.struct.cache.h" #include "Indicator.struct.h" #include "Indicator.struct.serialize.h" -#include "Indicator.struct.signal.h" -#include "IndicatorBase.h" +#include "IndicatorData.mqh" #include "Math.h" #include "Object.mqh" #include "Refs.mqh" @@ -74,37 +73,32 @@ double iCustom5(string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C 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); } +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, K _k, L _l, M _m, 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, _k, _l, _m); + 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 COMMA _k COMMA _l COMMA _m); +} #endif /** * Class to deal with indicators. */ template -class Indicator : public IndicatorBase { +class Indicator : public IndicatorData { protected: DrawIndicator* draw; - 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.IsSet() == NULL) { - // Indi_Price* _indi_price = Indi_Price::GetCached(GetSymbol(), GetTf(), iparams.GetShift()); - // SetDataSource(_indi_price, true, PRICE_OPEN); - } - break; - } - return InitDraw(); - } + bool Init() { return InitDraw(); } /** * Initialize indicator data drawing on custom data. @@ -144,21 +138,19 @@ class Indicator : public IndicatorBase { /** * Class constructor. */ - Indicator(const TS& _iparams, IndicatorBase* _indi_src = NULL, int _indi_mode = 0) - : IndicatorBase(_iparams.GetTf(), NULL) { + Indicator(const TS& _iparams, const IndicatorDataParams& _idparams, IndicatorData* _indi_src = NULL, + int _indi_mode = 0) + : IndicatorData(_idparams, _indi_src, _indi_mode) { iparams = _iparams; - 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) { + Indicator(const TS& _iparams, const IndicatorDataParams& _idparams, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) + : IndicatorData(_idparams) { iparams = _iparams; Init(); } Indicator(ENUM_INDICATOR_TYPE _itype, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0, string _name = "") - : IndicatorBase(_tf) { + : IndicatorData(IndicatorDataParams::GetInstance()) { iparams.SetIndicatorType(_itype); iparams.SetShift(_shift); Init(); @@ -172,11 +164,29 @@ class Indicator : public IndicatorBase { /* Getters */ /** - * Gets an indicator property flag. + * Gets a value from IndicatorDataParams struct. + */ + template + T Get(STRUCT_ENUM_IDATA_PARAM _param) { + return idparams.Get(_param); + } + + /** + * Gets a value from IndicatorState struct. + */ + template + T Get(STRUCT_ENUM_INDICATOR_STATE_PROP _param) { + return istate.Get(_param); + } + + /* Setters */ + + /** + * Sets the value for IndicatorDataParams struct. */ - bool GetFlag(INDICATOR_ENTRY_FLAGS _prop, int _shift = 0) { - IndicatorDataEntry _entry = GetEntry(_shift >= 0 ? _shift : iparams.GetShift()); - return _entry.CheckFlag(_prop); + template + void Set(STRUCT_ENUM_IDATA_PARAM _param, T _value) { + idparams.Set(_param, _value); } /* Buffer methods */ @@ -268,48 +278,6 @@ class Indicator : public IndicatorBase { return GetIndicatorBuffers() > 0 && GetIndicatorBuffers() <= 512; } - /** - * Gets indicator data from a buffer and copy into struct array. - * - * @return - * Returns true of successful copy. - * Returns false on invalid values. - */ - bool CopyEntries(IndicatorDataEntry& _data[], int _count, int _start_shift = 0) { - bool _is_valid = true; - if (ArraySize(_data) < _count) { - _is_valid &= ArrayResize(_data, _count) > 0; - } - for (int i = 0; i < _count; i++) { - IndicatorDataEntry _entry = GetEntry(_start_shift + i); - _is_valid &= _entry.IsValid(); - _data[i] = _entry; - } - return _is_valid; - } - - /** - * Gets indicator data from a buffer and copy into array of values. - * - * @return - * Returns true of successful copy. - * Returns false on invalid values. - */ - template - bool CopyValues(T& _data[], int _count, int _start_shift = 0, int _mode = 0) { - bool _is_valid = true; - if (ArraySize(_data) < _count) { - _count = ArrayResize(_data, _count); - _count = _count > 0 ? _count : ArraySize(_data); - } - for (int i = 0; i < _count; i++) { - IndicatorDataEntry _entry = GetEntry(_start_shift + i); - _is_valid &= _entry.IsValid(); - _data[i] = (T)_entry[_mode]; - } - return _is_valid; - } - /** * CopyBuffer() method to be used on Indicator instance with ValueStorage buffer. * @@ -340,52 +308,6 @@ class Indicator : public IndicatorBase { } */ - /** - * Validates currently selected indicator used as data source. - */ - void ValidateSelectedDataSource() { - if (HasDataSource()) { - ValidateDataSource(THIS_PTR, GetDataSourceRaw()); - } - } - - /** - * Loads and validates built-in indicators whose can be used as data source. - */ - void ValidateDataSource(IndicatorBase* _target, IndicatorBase* _source) { - if (_target == NULL) { - Alert("Internal Error! _target is NULL in ", __FUNCTION_LINE__, "."); - DebugBreak(); - return; - } - - if (_source == NULL) { - Alert("Error! You have to select source indicator's via SetDataSource()."); - DebugBreak(); - return; - } - - if (!_target.IsDataSourceModeSelectable()) { - // We don't validate source mode as it will use all modes. - return; - } - - if (_source.GetModeCount() > 1 && _target.GetDataSourceMode() == -1) { - // Mode must be selected if source indicator has more that one mode. - Alert("Warning! ", GetName(), - " must select source indicator's mode via SetDataSourceMode(int). Defaulting to mode 0."); - _target.SetDataSourceMode(0); - DebugBreak(); - } else if (_source.GetModeCount() == 1 && _target.GetDataSourceMode() == -1) { - _target.SetDataSourceMode(0); - } else if (_target.GetDataSourceMode() < 0 || _target.GetDataSourceMode() > _source.GetModeCount()) { - Alert("Error! ", _target.GetName(), - " must select valid source indicator's mode via SetDataSourceMode(int) between 0 and ", - _source.GetModeCount(), "."); - DebugBreak(); - } - } - /** * Checks whether indicator have given mode index. * @@ -394,13 +316,13 @@ class Indicator : public IndicatorBase { void ValidateDataSourceMode(int& _out_mode) { if (_out_mode == -1) { // First mode will be used by default, or, if selected indicator has more than one mode, error will happen. - if (iparams.GetMaxModes() != 1) { + if (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES)) != 1) { Alert("Error: ", GetName(), " must have exactly one possible mode in order to skip using SetDataSourceMode()!"); DebugBreak(); } _out_mode = 0; - } else if (_out_mode + 1 > (int)iparams.GetMaxModes()) { - Alert("Error: ", GetName(), " have ", iparams.GetMaxModes(), + } else if (_out_mode + 1 > Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES))) { + Alert("Error: ", GetName(), " have ", Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES)), " mode(s) buy you tried to reference mode with index ", _out_mode, "! Ensure that you properly set mode via SetDataSourceMode()."); DebugBreak(); @@ -412,302 +334,21 @@ 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 */ - - /** - * Get pointer to data of indicator. - */ - BufferStruct* GetData() { return GetPointer(idata); } - - /** - * Returns the highest bar's index (shift). - */ - template - int GetHighest(int count = WHOLE_ARRAY, int start_bar = 0) { - int max_idx = -1; - double max = -DBL_MAX; - int last_bar = count == WHOLE_ARRAY ? (int)(GetBarShift(GetLastBarTime())) : (start_bar + count - 1); - - for (int shift = start_bar; shift <= last_bar; ++shift) { - double value = GetEntry(shift).GetMax(GetModeCount()); - if (value > max) { - max = value; - max_idx = shift; - } - } - - return max_idx; - } - - /** - * Returns the lowest bar's index (shift). - */ - template - int GetLowest(int count = WHOLE_ARRAY, int start_bar = 0) { - int min_idx = -1; - double min = DBL_MAX; - int last_bar = count == WHOLE_ARRAY ? (int)(GetBarShift(GetLastBarTime())) : (start_bar + count - 1); - - for (int shift = start_bar; shift <= last_bar; ++shift) { - double value = GetEntry(shift).GetMin(GetModeCount()); - if (value < min) { - min = value; - min_idx = shift; - } - } - - return min_idx; - } - - /** - * Returns the highest value. - */ - template - double GetMax(int start_bar = 0, int count = WHOLE_ARRAY) { - double max = NULL; - int last_bar = count == WHOLE_ARRAY ? (int)(GetBarShift(GetLastBarTime())) : (start_bar + count - 1); - - for (int shift = start_bar; shift <= last_bar; ++shift) { - double value = GetEntry(shift).GetMax(iparams.GetMaxModes()); - if (max == NULL || value > max) { - max = value; - } - } - - return max; - } - - /** - * Returns the lowest value. - */ - template - double GetMin(int start_bar, int count = WHOLE_ARRAY) { - double min = NULL; - int last_bar = count == WHOLE_ARRAY ? (int)(GetBarShift(GetLastBarTime())) : (start_bar + count - 1); - - for (int shift = start_bar; shift <= last_bar; ++shift) { - double value = GetEntry(shift).GetMin(iparams.GetMaxModes()); - if (min == NULL || value < min) { - min = value; - } - } - - return min; - } - - /** - * Returns average value. - */ - template - double GetAvg(int start_bar, int count = WHOLE_ARRAY) { - int num_values = 0; - double sum = 0; - int last_bar = count == WHOLE_ARRAY ? (int)(GetBarShift(GetLastBarTime())) : (start_bar + count - 1); - - for (int shift = start_bar; shift <= last_bar; ++shift) { - double value_min = GetEntry(shift).GetMin(iparams.GetMaxModes()); - double value_max = GetEntry(shift).GetMax(iparams.GetMaxModes()); - - sum += value_min + value_max; - num_values += 2; - } - - return sum / num_values; - } - - /** - * Returns median of values. - */ - template - double GetMed(int start_bar, int count = WHOLE_ARRAY) { - double array[]; - - int last_bar = count == WHOLE_ARRAY ? (int)(GetBarShift(GetLastBarTime())) : (start_bar + count - 1); - int num_bars = last_bar - start_bar + 1; - int index = 0; - - ArrayResize(array, num_bars); - - for (int shift = start_bar; shift <= last_bar; ++shift) { - array[index++] = GetEntry(shift).GetAvg(iparams.GetMaxModes()); - } - - ArraySort(array); - double median; - int len = ArraySize(array); - if (len % 2 == 0) { - median = (array[len / 2] + array[(len / 2) - 1]) / 2; - } else { - median = array[len / 2]; - } - - 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. */ - IndicatorBase* GetDataSource() { - IndicatorBase* _result = NULL; + IndicatorData* GetDataSource() { + IndicatorData* _result = NULL; if (GetDataSourceRaw() != NULL) { _result = GetDataSourceRaw(); - } else if (iparams.GetDataSourceId() != -1) { - int _source_id = iparams.GetDataSourceId(); + } else if (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_SRC_ID)) != -1) { + int _source_id = Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_SRC_ID)); if (indicators.KeyExists(_source_id)) { _result = indicators[_source_id].Ptr(); } else { - Ref _source = FetchDataSource((ENUM_INDICATOR_TYPE)_source_id); + Ref _source = FetchDataSource((ENUM_INDICATOR_TYPE)_source_id); if (!_source.IsSet()) { Alert(GetName(), " has no built-in source indicator ", _source_id); @@ -718,16 +359,16 @@ class Indicator : public IndicatorBase { _result = _source.Ptr(); } } - } else if (iparams.GetDataSourceType() == IDATA_INDICATOR) { + } else if (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE)) == 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(); + IndicatorData* _ds = OnDataSourceRequest(); if (_ds != NULL) { // Initializing with new data source. SetDataSource(_ds); - iparams.SetDataSourceType(IDATA_INDICATOR); + Set(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE), IDATA_INDICATOR); } } @@ -745,11 +386,12 @@ class Indicator : public IndicatorBase { * Whether data source is selected. */ virtual bool HasDataSource(bool _try_initialize = false) { - if (iparams.GetDataSourceId() != -1) { + if (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_SRC_ID)) != -1) { return true; } - if (iparams.GetDataSourceType() == IDATA_INDICATOR && GetDataSourceRaw() == NULL && _try_initialize) { + if (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE)) == IDATA_INDICATOR && + GetDataSourceRaw() == NULL && _try_initialize) { SetDataSource(OnDataSourceRequest()); } @@ -764,12 +406,17 @@ class Indicator : public IndicatorBase { /** * Gets indicator's symbol. */ - string GetSymbol() { return Get(CHART_PARAM_SYMBOL); } + // string GetSymbol() { return Get(CHART_PARAM_SYMBOL); } /** * Gets indicator's time-frame. */ - ENUM_TIMEFRAMES GetTf() { return Get(CHART_PARAM_TF); } + // ENUM_TIMEFRAMES GetTf() { return Get(CHART_PARAM_TF); } + + /** + * Gets indicator's time-frame. + */ + ENUM_TIMEFRAMES GetTf() { return iparams.tf.GetTf(); } /** * Gets indicator's signals. @@ -785,7 +432,7 @@ class Indicator : public IndicatorBase { return _signals; } // Returns signals. - IndicatorSignal _signals(_data, iparams, cparams, _mode1, _mode2); + IndicatorSignal _signals(_data, idparams, cparams, _mode1, _mode2); return _signals; } @@ -800,9 +447,10 @@ class Indicator : public IndicatorBase { * Get more descriptive name of the indicator. */ string GetDescriptiveName() { + int _max_modes = Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES)); string name = iparams.name + " ("; - switch (iparams.GetDataSourceType()) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: name += "built-in, "; break; @@ -814,7 +462,7 @@ class Indicator : public IndicatorBase { break; } - name += IntegerToString(iparams.GetMaxModes()) + (iparams.GetMaxModes() == 1 ? " mode" : " modes"); + name += IntegerToString(_max_modes) + (_max_modes == 1 ? " mode" : " modes"); return name + ")"; } @@ -970,9 +618,11 @@ class Indicator : public IndicatorBase { Chart::OnTick(); if (iparams.is_draw) { + int _max_modes = Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES)); // Print("Drawing ", GetName(), iparams.indi_data != NULL ? (" (over " + iparams.indi_data.GetName() + ")") : ""); - for (int i = 0; i < (int)iparams.GetMaxModes(); ++i) - draw.DrawLineTo(GetName() + "_" + IntegerToString(i) + "_" + IntegerToString(iparams.GetDataSourceMode()), + for (int i = 0; i < _max_modes; ++i) + draw.DrawLineTo(GetName() + "_" + IntegerToString(i) + "_" + + Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_SRC_MODE)), GetBarTime(0), GetEntry(0)[i], iparams.draw_window); } } @@ -980,7 +630,7 @@ class Indicator : public IndicatorBase { /** * Sets indicator data source. */ - void SetDataSource(IndicatorBase* _indi, int _input_mode = -1) override { + void SetDataSource(IndicatorData* _indi, int _input_mode = -1) override { if (indi_src.IsSet()) { if (bool(flags | INDI_FLAG_SOURCE_REQ_INDEXABLE_BY_SHIFT) && !bool(_indi.GetFlags() | INDI_FLAG_INDEXABLE_BY_SHIFT)) { @@ -1004,7 +654,8 @@ class Indicator : public IndicatorBase { indi_src = _indi; if (_indi != NULL) { indi_src.Ptr().AddListener(THIS_PTR); - iparams.SetDataSource(-1, _input_mode); + Set(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_SRC_ID), -1); + Set(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_SRC_MODE), _input_mode); indi_src.Ptr().OnBecomeDataSourceFor(THIS_PTR); } } @@ -1067,7 +718,7 @@ class Indicator : public IndicatorBase { * Get full name of the indicator (with "over ..." part). */ string GetFullName() override { - return GetName() + "[" + IntegerToString(iparams.GetMaxModes()) + "]" + + return GetName() + "[" + Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES)) + "]" + (HasDataSource() ? (" (over " + GetDataSource().GetFullName() + ")") : ""); } @@ -1098,7 +749,8 @@ class Indicator : public IndicatorBase { long _bar_time = GetBarTime(_ishift); IndicatorDataEntry _entry = idata.GetByKey(_bar_time); if (_bar_time > 0 && !_entry.IsValid() && !_entry.CheckFlag(INDI_ENTRY_FLAG_INSUFFICIENT_DATA)) { - _entry.Resize(iparams.GetMaxModes()); + int _max_modes = Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES)); + _entry.Resize(_max_modes); _entry.timestamp = GetBarTime(_ishift); #ifndef __MQL4__ if (IndicatorBase::Get(STRUCT_ENUM(IndicatorState, INDICATOR_STATE_PROP_IS_CHANGED))) { @@ -1107,8 +759,8 @@ class Indicator : public IndicatorBase { IndicatorBase::Set(STRUCT_ENUM(IndicatorState, INDICATOR_STATE_PROP_IS_CHANGED), false); } #endif - for (int _mode = 0; _mode < (int)iparams.GetMaxModes(); _mode++) { - switch (iparams.GetDataValueType()) { + for (int _mode = 0; _mode < _max_modes; _mode++) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_DTYPE))) { case TYPE_BOOL: case TYPE_CHAR: case TYPE_INT: @@ -1160,8 +812,10 @@ class Indicator : 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(iparams.GetDataValueType())); + ENUM_DATATYPE _dtype = Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_DTYPE)); + _entry.AddFlags(_entry.GetDataTypeFlags(_dtype)); }; + /** * Returns the indicator's entry value for the given shift and mode. * diff --git a/Indicator.struct.h b/Indicator.struct.h index d9ecc205a..7f90435ea 100644 --- a/Indicator.struct.h +++ b/Indicator.struct.h @@ -1,6 +1,6 @@ //+------------------------------------------------------------------+ //| EA31337 framework | -//| Copyright 2016-2021, EA31337 Ltd | +//| Copyright 2016-2022, EA31337 Ltd | //| https://github.com/EA31337 | //+------------------------------------------------------------------+ @@ -35,6 +35,9 @@ template class Indicator; struct ChartParams; +// Defines. +#define STRUCT_ENUM_INDICATOR_STATE_PROP STRUCT_ENUM(IndicatorState, ENUM_INDICATOR_STATE_PROP) + // Includes. #include "Array.mqh" #include "Chart.struct.tf.h" @@ -45,379 +48,15 @@ struct ChartParams; #include "SerializerNode.enum.h" #include "Storage/ValueStorage.indicator.h" -// Type-less value for IndicatorDataEntryValue structure. -union IndicatorDataEntryTypelessValue { - double vdbl; - float vflt; - int vint; - long vlong; -}; - -// Type-aware value for IndicatorDataEntry class. -struct IndicatorDataEntryValue { - unsigned char flags; - IndicatorDataEntryTypelessValue value; - - // Returns type of the value. - ENUM_DATATYPE GetDataType() { return (ENUM_DATATYPE)((flags & 0xF0) >> 4); } - - // Sets type of the value. - void SetDataType(ENUM_DATATYPE _type) { - // Clearing type. - flags &= 0x0F; - - // Setting type. - flags |= (unsigned char)_type << 4; - } - - // Union operators. - template - T operator*(const T _value) { - return Get() * _value; - } - template - T operator+(const T _value) { - return Get() + _value; - } - template - T operator-(const T _value) { - return Get() - _value; - } - template - T operator/(const T _value) { - return Get() / _value; - } - template - bool operator!=(const T _value) { - return Get() != _value; - } - template - bool operator<(const T _value) { - return Get() < _value; - } - template - bool operator<=(const T _value) { - return Get() <= _value; - } - template - bool operator==(const T _value) { - return Get() == _value; - } - template - bool operator>(const T _value) { - return Get() > _value; - } - template - bool operator>=(const T _value) { - return Get() >= _value; - } - template - void operator=(const T _value) { - Set(_value); - } - // Checkers. - template - bool IsGt(T _value) { - return Get() > _value; - } - template - bool IsLt(T _value) { - return Get() < _value; - } - // Getters. - double GetDbl() { return value.vdbl; } - float GetFloat() { return value.vflt; } - int GetInt() { return value.vint; } - long GetLong() { return value.vlong; } - template - void Get(T &_out) { - _out = Get(); - } - template - T Get() { - T _v; - Get(_v); - return _v; - } - void Get(double &_out) { _out = value.vdbl; } - void Get(float &_out) { _out = value.vflt; } - void Get(int &_out) { _out = value.vint; } - void Get(unsigned int &_out) { _out = (unsigned int)value.vint; } - void Get(long &_out) { _out = value.vlong; } - void Get(unsigned long &_out) { _out = (unsigned long)value.vint; } - // Setters. - template - void Set(T _value) { - Set(_value); - } - void Set(double _value) { - value.vdbl = _value; - SetDataType(TYPE_DOUBLE); - } - void Set(float _value) { - value.vflt = _value; - SetDataType(TYPE_FLOAT); - } - void Set(int _value) { - value.vint = _value; - SetDataType(TYPE_INT); - } - void Set(unsigned int _value) { - value.vint = (int)_value; - SetDataType(TYPE_UINT); - } - void Set(long _value) { - value.vlong = _value; - SetDataType(TYPE_LONG); - } - void Set(unsigned long _value) { - value.vlong = (long)_value; - SetDataType(TYPE_ULONG); - } - // Serializers. - // SERIALIZER_EMPTY_STUB - SerializerNodeType Serialize(Serializer &_s); - // To string - template - string ToString() { - return (string)Get(); - } -}; - -/* Structure for indicator data entry. */ -struct IndicatorDataEntry { - long timestamp; // Timestamp of the entry's bar. - unsigned short flags; // Indicator entry flags. - ARRAY(IndicatorDataEntryValue, values); - - // Constructors. - IndicatorDataEntry(int _size = 1) : flags(INDI_ENTRY_FLAG_NONE), timestamp(0) { Resize(_size); } - IndicatorDataEntry(IndicatorDataEntry &_entry) { THIS_REF = _entry; } - int GetSize() { return ArraySize(values); } - // Operator overloading methods. - template - T operator*(const T _value) { - return values[0].Get() * _value; - } - template - T operator+(const T _value) { - return values[0].Get() + _value; - } - template - T operator-(const T _value) { - return values[0].Get() - _value; - } - template - T operator/(const T _value) { - return values[0].Get() / _value; - } - template - T operator[](I _index) { - return values[(int)_index].Get(); - } - template <> - double operator[](int _index) { - if (_index >= ArraySize(values)) { - return 0; - } - double _value; - values[_index].Get(_value); - return _value; - } - // Checkers. - template - bool HasValue(T _value) { - bool _result = false; - int _asize = ArraySize(values); - T _value2; - for (int i = 0; i < _asize; i++) { - values[i].Get(_value2); - if (_value == _value2) { - _result = true; - break; - } - } - return _result; - } - template - bool IsGe(T _value) { - return GetMin() >= _value; - } - template - bool IsGt(T _value) { - return GetMin() > _value; - } - template - bool IsLe(T _value) { - return GetMax() <= _value; - } - template - bool IsLt(T _value) { - return GetMax() < _value; - } - template - bool IsWithinRange(T _min, T _max) { - return GetMin() >= _min && GetMax() <= _max; - } - // Getters. - template - void GetArray(ARRAY_REF(T, _out), int _size = 0) { - int _asize = _size > 0 ? _size : ArraySize(_out); - for (int i = 0; i < _asize; i++) { - values[i].Get(_out[i]); - } - }; - template - T GetAvg(int _size = 0) { - int _asize = _size > 0 ? _size : ArraySize(values); - T _avg = GetSum() / _asize; - return _avg; - }; - template - T GetMin(int _size = 0) { - int _asize = _size > 0 ? _size : ArraySize(values); - int _index = 0; - for (int i = 1; i < _asize; i++) { - _index = values[i].Get() < values[_index].Get() ? i : _index; - } - return values[_index].Get(); - }; - template - T GetMax(int _size = 0) { - int _asize = _size > 0 ? _size : ArraySize(values); - int _index = 0; - for (int i = 1; i < _asize; i++) { - _index = values[i].Get() > values[_index].Get() ? i : _index; - } - return values[_index].Get(); - }; - template - T GetSum(int _size = 0) { - int _asize = _size > 0 ? _size : ArraySize(values); - T _sum = 0; - for (int i = 1; i < _asize; i++) { - _sum = +values[i].Get(); - } - return _sum; - }; - template - T GetValue(int _index = 0) { - return values[_index].Get(); - }; - template - void GetValues(T &_out1, T &_out2) { - values[0].Get(_out1); - values[1].Get(_out2); - }; - template - void GetValues(T &_out1, T &_out2, T &_out3) { - values[0].Get(_out1); - values[1].Get(_out2); - values[2].Get(_out3); - }; - template - void GetValues(T &_out1, T &_out2, T &_out3, T &_out4) { - values[0].Get(_out1); - values[1].Get(_out2); - values[2].Get(_out3); - values[3].Get(_out4); - }; - - // Getters. - int GetDayOfYear() { return DateTimeStatic::DayOfYear(timestamp); } - int GetMonth() { return DateTimeStatic::Month(timestamp); } - int GetYear() { return DateTimeStatic::Year(timestamp); } - long GetTime() { return timestamp; }; - ENUM_DATATYPE GetDataType(int _mode) { return values[_mode].GetDataType(); } - ushort GetDataTypeFlags(ENUM_DATATYPE _dt) { - switch (_dt) { - case TYPE_BOOL: - case TYPE_CHAR: - SetUserError(ERR_INVALID_PARAMETER); - break; - case TYPE_INT: - return INDI_ENTRY_FLAG_NONE; - case TYPE_LONG: - return INDI_ENTRY_FLAG_IS_DOUBLED; - case TYPE_UINT: - return INDI_ENTRY_FLAG_IS_UNSIGNED; - case TYPE_ULONG: - return INDI_ENTRY_FLAG_IS_UNSIGNED | INDI_ENTRY_FLAG_IS_DOUBLED; - case TYPE_DOUBLE: - return INDI_ENTRY_FLAG_IS_REAL | INDI_ENTRY_FLAG_IS_DOUBLED; - case TYPE_FLOAT: - return INDI_ENTRY_FLAG_IS_REAL; - case TYPE_STRING: - case TYPE_UCHAR: - SetUserError(ERR_INVALID_PARAMETER); - break; - default: - SetUserError(ERR_INVALID_PARAMETER); - break; - } - SetUserError(ERR_INVALID_PARAMETER); - return INDI_ENTRY_FLAG_NONE; - } - // Setters. - bool Resize(int _size = 0) { return _size > 0 ? ArrayResize(values, _size) > 0 : true; } - // Value flag methods for bitwise operations. - bool CheckFlag(INDICATOR_ENTRY_FLAGS _prop) { return CheckFlags(_prop); } - bool CheckFlags(unsigned short _flags) { return (flags & _flags) != 0; } - bool CheckFlagsAll(unsigned short _flags) { return (flags & _flags) == _flags; } - void AddFlags(unsigned short _flags) { flags |= _flags; } - void RemoveFlags(unsigned short _flags) { flags &= ~_flags; } - void SetFlag(INDICATOR_ENTRY_FLAGS _flag, bool _value) { - if (_value) { - AddFlags(_flag); - } else { - RemoveFlags(_flag); - } - } - void SetFlags(unsigned short _flags) { flags = _flags; } - unsigned short GetFlags() { return flags; } - // Converters. - // State checkers. - bool IsValid() { return CheckFlags(INDI_ENTRY_FLAG_IS_VALID); } - // Serializers. - void SerializeStub(int _n1 = 1, int _n2 = 1, int _n3 = 1, int _n4 = 1, int _n5 = 1) { - ArrayResize(values, _n1); - for (int i = 0; i < _n1; ++i) { - values[i] = (int)1; - } - } - SerializerNodeType Serialize(Serializer &_s); - template - string ToCSV() { - int _asize = ArraySize(values); - string _result = ""; - for (int i = 0; i < _asize; i++) { - _result += StringFormat("%s%s", (string)values[i].Get(), i < _asize ? "," : ""); - } - return _result; - } - template - string ToString() { - return ToCSV(); - } -}; - /* Structure for indicator parameters. */ struct IndicatorParams { - public: // @todo: Change it to protected. - string name; // Name of the indicator. - int shift; // Shift (relative to the current bar, 0 - default). - unsigned int max_buffers; // Max buffers to store. - unsigned int max_modes; // Max supported indicator modes (values per entry). - unsigned int max_params; // Max supported input params. - ChartTf tf; // Chart's timeframe. - ENUM_INDICATOR_TYPE itype; // Indicator type (e.g. INDI_RSI). - ENUM_IDATA_SOURCE_TYPE idstype; // Indicator's data source type (e.g. IDATA_BUILTIN, IDATA_ICUSTOM). - ENUM_IDATA_VALUE_RANGE idvrange; // Indicator's range value data type. - // ENUM_IDATA_VALUE_TYPE idvtype; // Indicator's data value type (e.g. TDBL1, TDBL2, TINT1). - ENUM_DATATYPE dtype; // Type of basic data to store values (DTYPE_DOUBLE, DTYPE_INT). + public: // @todo: Change it to protected. + string name; // Name of the indicator. + int shift; // Shift (relative to the current bar, 0 - default). + unsigned int max_params; // Max supported input params. + ChartTf tf; // Chart's timeframe. + ENUM_INDICATOR_TYPE itype; // Indicator type (e.g. INDI_RSI). color indi_color; // Indicator color. - int indi_data_source_id; // Id of the indicator to be used as data source. - int indi_data_source_mode; // Mode used as input from data source. ARRAY(DataParamEntry, input_params); // Indicator input params. bool is_draw; // Draw active. int draw_window; // Drawing window. @@ -425,19 +64,16 @@ struct IndicatorParams { public: /* Special methods */ // Constructor. - IndicatorParams(ENUM_INDICATOR_TYPE _itype = INDI_NONE, unsigned int _max_modes = 1, - ENUM_DATATYPE _dtype = TYPE_DOUBLE, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, - ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, string _name = "") + IndicatorParams(ENUM_INDICATOR_TYPE _itype = INDI_NONE, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, string _name = "") : custom_indi_name(""), - dtype(_dtype), name(_name), shift(0), - max_modes(_max_modes), - max_buffers(10), - idstype(_idstype), - idvrange(IDATA_RANGE_UNKNOWN), - indi_data_source_id(-1), - indi_data_source_mode(-1), + // max_modes(_max_modes), + // max_buffers(10), + // idstype(_idstype), + // idvrange(IDATA_RANGE_UNKNOWN), + // indi_data_source_id(-1), + // indi_data_source_mode(-1), itype(_itype), is_draw(false), indi_color(clrNONE), @@ -445,16 +81,16 @@ struct IndicatorParams { tf(_tf) { Init(); }; - IndicatorParams(string _name, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN) + IndicatorParams(string _name) : custom_indi_name(""), name(_name), shift(0), - max_modes(1), - max_buffers(10), - idstype(_idstype), - idvrange(IDATA_RANGE_UNKNOWN), - indi_data_source_id(-1), - indi_data_source_mode(-1), + // max_modes(1), + // max_buffers(10), + // idstype(_idstype), + // idvrange(IDATA_RANGE_UNKNOWN), + // indi_data_source_id(-1), + // indi_data_source_mode(-1), is_draw(false), indi_color(clrNONE), draw_window(0) { @@ -470,15 +106,10 @@ struct IndicatorParams { void Init() {} /* Getters */ string GetCustomIndicatorName() const { return custom_indi_name; } - int GetDataSourceId() const { return indi_data_source_id; } - int GetDataSourceMode() const { return indi_data_source_mode; } color GetIndicatorColor() const { return indi_color; } - int GetMaxModes() const { return (int)max_modes; } int GetMaxParams() const { return (int)max_params; } int GetShift() const { return shift; } - ENUM_DATATYPE GetDataValueType() const { return dtype; } - ENUM_IDATA_SOURCE_TYPE GetDataSourceType() const { return idstype; } - ENUM_IDATA_VALUE_RANGE GetIDataValueRange() const { return idvrange; } + ENUM_INDICATOR_TYPE GetIndicatorType() { return itype; } ENUM_TIMEFRAMES GetTf() const { return tf.GetTf(); } template T GetInputParam(int _index, T _default) const { @@ -507,10 +138,6 @@ struct IndicatorParams { } /* Setters */ void SetCustomIndicatorName(string _name) { custom_indi_name = _name; } - void SetDataSourceMode(int _mode) { indi_data_source_mode = _mode; } - void SetDataSourceType(ENUM_IDATA_SOURCE_TYPE _idstype) { idstype = _idstype; } - void SetDataValueRange(ENUM_IDATA_VALUE_RANGE _idvrange) { idvrange = _idvrange; } - void SetDataValueType(ENUM_DATATYPE _dtype) { dtype = _dtype; } void SetDraw(bool _draw = true, int _window = 0) { is_draw = _draw; draw_window = _window; @@ -521,11 +148,6 @@ struct IndicatorParams { draw_window = _window; } void SetIndicatorColor(color _clr) { indi_color = _clr; } - void SetDataSource(int _id, int _input_mode = -1) { - indi_data_source_id = _id; - indi_data_source_mode = _input_mode; - idstype = IDATA_INDICATOR; - } void SetIndicatorType(ENUM_INDICATOR_TYPE _itype) { itype = _itype; } void SetInputParams(ARRAY_REF(DataParamEntry, _params)) { int _asize = ArraySize(_params); @@ -534,14 +156,12 @@ struct IndicatorParams { input_params[i] = _params[i]; } } - void SetMaxModes(int _value) { max_modes = _value; } void SetMaxParams(int _value) { max_params = _value; ArrayResize(input_params, max_params); } void SetName(string _name) { name = _name; }; void SetShift(int _shift) { shift = _shift; } - void SetSize(int _size) { max_buffers = _size; }; void SetTf(ENUM_TIMEFRAMES _tf) { tf.SetTf(_tf); } // Serializers. // SERIALIZER_EMPTY_STUB; @@ -551,14 +171,16 @@ struct IndicatorParams { /* Structure for indicator state. */ struct IndicatorState { + public: // @todo: Change it to protected. + int handle; // Indicator handle (MQL5 only). + bool is_changed; // Set when params has been recently changed. + bool is_ready; // Set when indicator is ready (has valid values). + public: enum ENUM_INDICATOR_STATE_PROP { INDICATOR_STATE_PROP_HANDLE, INDICATOR_STATE_PROP_IS_CHANGED, INDICATOR_STATE_PROP_IS_READY, }; - int handle; // Indicator handle (MQL5 only). - bool is_changed; // Set when params has been recently changed. - bool is_ready; // Set when indicator is ready (has valid values). // Constructor. IndicatorState() : handle(INVALID_HANDLE), is_changed(true), is_ready(false) {} // Getters. diff --git a/Indicator.struct.serialize.h b/Indicator.struct.serialize.h index 98e262c60..e9a68a534 100644 --- a/Indicator.struct.serialize.h +++ b/Indicator.struct.serialize.h @@ -30,81 +30,16 @@ // Forward class declaration. class Serializer; -/* Method to serialize IndicatorDataEntry structure. */ -SerializerNodeType IndicatorDataEntry::Serialize(Serializer &_s) { - int _asize = ArraySize(values); - _s.Pass(THIS_REF, "datetime", timestamp, SERIALIZER_FIELD_FLAG_DYNAMIC); - _s.Pass(THIS_REF, "flags", flags, SERIALIZER_FIELD_FLAG_DYNAMIC); - for (int i = 0; i < _asize; i++) { - // _s.Pass(THIS_REF, (string)i, values[i], SERIALIZER_FIELD_FLAG_DYNAMIC | SERIALIZER_FIELD_FLAG_FEATURE); // Can - // this work? _s.Pass(THIS_REF, (string)i, GetEntry(i), SERIALIZER_FIELD_FLAG_DYNAMIC | - // SERIALIZER_FIELD_FLAG_FEATURE); // Can this work? - - switch (values[i].GetDataType()) { - case TYPE_DOUBLE: - _s.Pass(THIS_REF, (string)i, values[i].value.vdbl, - SERIALIZER_FIELD_FLAG_DYNAMIC | SERIALIZER_FIELD_FLAG_FEATURE); - break; - case TYPE_FLOAT: - _s.Pass(THIS_REF, (string)i, values[i].value.vflt, - SERIALIZER_FIELD_FLAG_DYNAMIC | SERIALIZER_FIELD_FLAG_FEATURE); - break; - case TYPE_INT: - case TYPE_UINT: - if (CheckFlags(INDI_ENTRY_FLAG_IS_BITWISE)) { - // Split for each bit and pass 0 or 1. - for (int j = 0; j < sizeof(int) * 8; ++j) { - int _value = (values[i].value.vint & (1 << j)) != 0; - _s.Pass(THIS_REF, StringFormat("%d@%d", i, j), _value, SERIALIZER_FIELD_FLAG_FEATURE); - } - } else { - _s.Pass(THIS_REF, (string)i, values[i].value.vint, - SERIALIZER_FIELD_FLAG_DYNAMIC | SERIALIZER_FIELD_FLAG_FEATURE); - } - break; - case TYPE_LONG: - case TYPE_ULONG: - if (CheckFlags(INDI_ENTRY_FLAG_IS_BITWISE)) { - // Split for each bit and pass 0 or 1. - /* @fixme: j, j already defined. - for (int j = 0; j < sizeof(int) * 8; ++j) { - int _value = (values[i].vlong & (1 << j)) != 0; - _s.Pass(THIS_REF, StringFormat("%d@%d", i, j), _value, SERIALIZER_FIELD_FLAG_FEATURE); - } - */ - SetUserError(ERR_INVALID_PARAMETER); - } else { - _s.Pass(THIS_REF, (string)i, values[i].value.vlong, - SERIALIZER_FIELD_FLAG_DYNAMIC | SERIALIZER_FIELD_FLAG_FEATURE); - } - break; - default: - SetUserError(ERR_INVALID_PARAMETER); - break; - } - } - return SerializerNodeObject; -} - -/* Method to serialize IndicatorDataEntry's IndicatorDataEntryValue union. */ -SerializerNodeType IndicatorDataEntryValue::Serialize(Serializer &_s) { - _s.Pass(THIS_REF, "flags", flags); - _s.Pass(THIS_REF, "vdbl", value.vdbl); - _s.Pass(THIS_REF, "vflt", value.vflt); - _s.Pass(THIS_REF, "vint", value.vint); - _s.Pass(THIS_REF, "vlong", value.vlong); - return SerializerNodeObject; -}; - /* Method to serialize IndicatorParams structure. */ SerializerNodeType IndicatorParams::Serialize(Serializer &s) { s.Pass(THIS_REF, "name", name); s.Pass(THIS_REF, "shift", shift); - s.Pass(THIS_REF, "max_modes", max_modes); - s.Pass(THIS_REF, "max_buffers", max_buffers); + // s.Pass(THIS_REF, "max_modes", max_modes); + // s.Pass(THIS_REF, "max_buffers", max_buffers); s.PassEnum(THIS_REF, "itype", itype); - s.PassEnum(THIS_REF, "idstype", idstype); - s.PassEnum(THIS_REF, "dtype", dtype); + // s.PassEnum(THIS_REF, "idstype", idstype); + // s.PassEnum(THIS_REF, "dtype", dtype); + // s.PassObject(this, "indicator", indi_data); // @todo // s.Pass(THIS_REF, "indi_data_ownership", indi_data_ownership); s.Pass(THIS_REF, "indi_color", indi_color, SERIALIZER_FIELD_FLAG_HIDDEN); diff --git a/Indicator/IndicatorCandle.h b/Indicator/IndicatorCandle.h index c0ff4637a..b5036d67e 100644 --- a/Indicator/IndicatorCandle.h +++ b/Indicator/IndicatorCandle.h @@ -31,8 +31,8 @@ // Includes. #include "../Buffer/BufferCandle.h" -#include "../Indicator.mqh" #include "../Candle.struct.h" +#include "../Indicator.mqh" // Indicator modes. enum ENUM_INDI_CANDLE_MODE { @@ -67,7 +67,6 @@ class IndicatorCandle : public Indicator { flags |= INDI_FLAG_INDEXABLE_BY_TIMESTAMP; icdata.AddFlags(DICT_FLAG_FILL_HOLES_UNSORTED); icdata.SetOverflowListener(IndicatorCandleOverflowListener, 10); - iparams.SetMaxModes(4); } public: @@ -76,8 +75,9 @@ class IndicatorCandle : public Indicator { /** * Class constructor. */ - IndicatorCandle(const TS& _icparams, IndicatorBase* _indi_src = NULL, int _indi_mode = 0) - : Indicator(_icparams, _indi_src, _indi_mode) { + IndicatorCandle(const TS& _icparams, const IndicatorDataParams& _idparams, IndicatorBase* _indi_src = NULL, + int _indi_mode = 0) + : Indicator(_icparams, _idparams, _indi_src, _indi_mode) { Init(); } IndicatorCandle(ENUM_INDICATOR_TYPE _itype = INDI_CANDLE, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0, @@ -125,7 +125,8 @@ class IndicatorCandle : public Indicator { if (!_candle.IsValid()) { // Giving up. DebugBreak(); - Print(GetFullName(), ": Missing candle after thorough search at shift ", _index, " (", TimeToString(_candle_time), "). Lowest timestamp in history is ", icdata.GetMin()); + 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); diff --git a/Indicator/IndicatorTf.h b/Indicator/IndicatorTf.h index 84fe4b7c0..fb0f714b9 100644 --- a/Indicator/IndicatorTf.h +++ b/Indicator/IndicatorTf.h @@ -79,7 +79,10 @@ class IndicatorTf : public IndicatorCandle { /** * Class constructor with parameters. */ - IndicatorTf(TFP &_params) : IndicatorCandle(_params) { Init(); } + IndicatorTf(TFP& _icparams, const IndicatorDataParams& _idparams) + : IndicatorCandle(_icparams, _idparams) { + Init(); + } }; #endif diff --git a/Indicator/IndicatorTick.h b/Indicator/IndicatorTick.h index e654dde70..afb1075ea 100644 --- a/Indicator/IndicatorTick.h +++ b/Indicator/IndicatorTick.h @@ -66,7 +66,7 @@ class IndicatorTick : public Indicator { itdata.AddFlags(DICT_FLAG_FILL_HOLES_UNSORTED); itdata.SetOverflowListener(IndicatorTickOverflowListener, 10); // Ask and Bid price. - itparams.SetMaxModes(2); + Set(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES), 2); } public: @@ -75,8 +75,9 @@ class IndicatorTick : public Indicator { /** * Class constructor. */ - IndicatorTick(const TS& _itparams, IndicatorBase* _indi_src = NULL, int _indi_mode = 0) - : Indicator(_itparams, _indi_src, _indi_mode) { + IndicatorTick(const TS& _itparams, const IndicatorDataParams& _idparams, IndicatorBase* _indi_src = NULL, + int _indi_mode = 0) + : Indicator(_itparams, _idparams, _indi_src, _indi_mode) { itparams = _itparams; if (_indi_src != NULL) { SetDataSource(_indi_src, _indi_mode); @@ -153,12 +154,13 @@ class IndicatorTick : public Indicator { TickAB _tick = itdata.GetByKey(_timestamp); return TickToEntry(_timestamp, _tick); } + int _max_modes = Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES)); // No tick at given timestamp. Returning invalid entry. - IndicatorDataEntry _entry(itparams.GetMaxModes()); + IndicatorDataEntry _entry(_max_modes); GetEntryAlter(_entry, _timestamp); - for (int i = 0; i < itparams.GetMaxModes(); ++i) { + for (int i = 0; i < _max_modes; ++i) { _entry.values[i] = (double)0; } @@ -173,7 +175,8 @@ class IndicatorTick : public Indicator { * 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())); + ENUM_DATATYPE _dtype = Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_DTYPE)); + _entry.AddFlags(_entry.GetDataTypeFlags(_dtype)); }; /** @@ -206,7 +209,8 @@ class IndicatorTick : public Indicator { */ void SetDataSource(IndicatorBase* _indi, int _input_mode = -1) { indi_src = _indi; - itparams.SetDataSource(-1, _input_mode); + Set(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_SRC_ID), -1); + Set(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_SRC_MODE), _input_mode); } /* Virtual methods */ diff --git a/Indicator/IndicatorTickOrCandleSource.h b/Indicator/IndicatorTickOrCandleSource.h index 45fce1acd..491766979 100644 --- a/Indicator/IndicatorTickOrCandleSource.h +++ b/Indicator/IndicatorTickOrCandleSource.h @@ -41,9 +41,12 @@ class IndicatorTickOrCandleSource : public Indicator { /** * 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(const TS& _iparams, const IndicatorDataParams& _idparams, IndicatorBase* _indi_src = NULL, + int _indi_mode = 0) + : Indicator(_iparams, _idparams, _indi_src, _indi_mode) {} + IndicatorTickOrCandleSource(const TS& _iparams, const IndicatorDataParams& _idparams, + ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) + : Indicator(_iparams, _idparams, _tf) {} IndicatorTickOrCandleSource(ENUM_INDICATOR_TYPE _itype, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0, string _name = "") : Indicator(_itype, _tf, _shift, _name) {} @@ -57,7 +60,7 @@ class IndicatorTickOrCandleSource : public Indicator { * 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 { + bool OnValidateDataSource(IndicatorData* _ds, string& _reason) override { // @todo Make use of this method. return true; } @@ -72,9 +75,9 @@ class IndicatorTickOrCandleSource : public Indicator { /** * Creates default, tick based indicator for given applied price. */ - IndicatorBase* DataSourceRequestReturnDefault(int _applied_price) override { + IndicatorData* DataSourceRequestReturnDefault(int _applied_price) override { // Returning real candle indicator. Thus way we can use SetAppliedPrice() and select Ask or Bid price. - IndicatorBase* _indi; + IndicatorData* _indi; switch (_applied_price) { case PRICE_ASK: diff --git a/Indicator/IndicatorTickSource.h b/Indicator/IndicatorTickSource.h index 6e1734f4c..8b47180a5 100644 --- a/Indicator/IndicatorTickSource.h +++ b/Indicator/IndicatorTickSource.h @@ -37,9 +37,11 @@ class IndicatorTickSource : public Indicator { /** * 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(const TS& _iparams, const IndicatorDataParams& _idparams, IndicatorData* _indi_src = NULL, + int _indi_mode = 0) + : Indicator(_iparams, _idparams, _indi_src, _indi_mode) {} + IndicatorTickSource(const TS& _iparams, const IndicatorDataParams& _idparams, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) + : Indicator(_iparams, _idparams, _tf) {} IndicatorTickSource(ENUM_INDICATOR_TYPE _itype, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0, string _name = "") : Indicator(_itype, _tf, _shift, _name) {} @@ -52,7 +54,7 @@ class IndicatorTickSource : public Indicator { /** * Sets indicator data source. */ - void SetDataSource(IndicatorBase* _indi, int _input_mode = -1) override { + void SetDataSource(IndicatorData* _indi, int _input_mode = -1) override { if (_indi == NULL) { // Just deselecting data source. Indicator::SetDataSource(_indi, _input_mode); @@ -112,7 +114,7 @@ class IndicatorTickSource : public Indicator { * 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 { + bool OnValidateDataSource(IndicatorData* _ds, string& _reason) override { // @todo Make use of this method. return true; } diff --git a/Indicator/tests/IndicatorTf.test.mq5 b/Indicator/tests/IndicatorTf.test.mq5 index c9cb9d86f..d09b77905 100644 --- a/Indicator/tests/IndicatorTf.test.mq5 +++ b/Indicator/tests/IndicatorTf.test.mq5 @@ -1,6 +1,6 @@ //+------------------------------------------------------------------+ //| EA31337 framework | -//| Copyright 2016-2021, EA31337 Ltd | +//| Copyright 2016-2022, EA31337 Ltd | //| https://github.com/EA31337 | //+------------------------------------------------------------------+ diff --git a/Indicator/tests/classes/IndicatorTickDummy.h b/Indicator/tests/classes/IndicatorTickDummy.h index 683025176..dcc473b88 100644 --- a/Indicator/tests/classes/IndicatorTickDummy.h +++ b/Indicator/tests/classes/IndicatorTickDummy.h @@ -35,18 +35,20 @@ // Params for dummy tick-based indicator. struct IndicatorTickDummyParams : IndicatorParams { - IndicatorTickDummyParams() : IndicatorParams(INDI_TICK, 2, TYPE_DOUBLE) {} + IndicatorTickDummyParams() : IndicatorParams(INDI_TICK) {} }; // Dummy tick-based indicator. class IndicatorTickDummy : public IndicatorTick { public: IndicatorTickDummy(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0, string _name = "") - : IndicatorTick(INDI_TICK, _tf, _shift, _name) {} + : IndicatorTick(INDI_TICK, _tf, _shift, _name) { + Set(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES), 2); + } string GetName() override { return "IndicatorTickDummy"; } - void OnBecomeDataSourceFor(IndicatorBase* _base_indi) override { + void OnBecomeDataSourceFor(IndicatorData* _base_indi) override { // Feeding base indicator with historic entries of this indicator. Print(GetName(), " became a data source for ", _base_indi.GetName()); diff --git a/Indicator/tests/classes/IndicatorTickReal.h b/Indicator/tests/classes/IndicatorTickReal.h index 977c5cc48..fc20d98c5 100644 --- a/Indicator/tests/classes/IndicatorTickReal.h +++ b/Indicator/tests/classes/IndicatorTickReal.h @@ -35,28 +35,30 @@ // Params for real tick-based indicator. struct IndicatorTickRealParams : IndicatorParams { - IndicatorTickRealParams() : IndicatorParams(INDI_TICK, 3, TYPE_DOUBLE) {} + IndicatorTickRealParams() : IndicatorParams(INDI_TICK) {} }; // Real tick-based indicator. class IndicatorTickReal : public IndicatorTick { public: IndicatorTickReal(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0, string _name = "") - : IndicatorTick(INDI_TICK, _tf, _shift, _name) {} + : IndicatorTick(INDI_TICK, _tf, _shift, _name) { + Set(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES), 3); + } string GetName() override { return "IndicatorTickReal"; } - void OnBecomeDataSourceFor(IndicatorBase* _base_indi) override { + void OnBecomeDataSourceFor(IndicatorData* _indi) override { // Feeding base indicator with historic entries of this indicator. #ifdef __debug__ - Print(GetFullName(), " became a data source for ", _base_indi.GetFullName()); + Print(GetFullName(), " became a data source for ", _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, + Print(_indi.GetFullName(), " will be now filled with ", _ticks_to_emit, " historical entries generated by " + GetFullName()); #endif @@ -82,7 +84,7 @@ class IndicatorTickReal : public IndicatorTick 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)); + _indi.OnDataSourceEntry(TickToEntry(_ticks[i].time, _tick)); } #endif } diff --git a/Indicator/tests/classes/Indicators.h b/Indicator/tests/classes/Indicators.h index f8258b555..1d1da2066 100644 --- a/Indicator/tests/classes/Indicators.h +++ b/Indicator/tests/classes/Indicators.h @@ -30,23 +30,23 @@ #endif // Includes. -#include "../../../IndicatorBase.h" +#include "../../../IndicatorData.mqh" #include "../../../Refs.mqh" /** * Helper class to store all indicators and call OnTick() on them. */ class Indicators { - Ref _indis[]; + Ref _indis[]; public: void Add(IndicatorBase* _indi) { - Ref _ref = _indi; + Ref _ref = _indi; ArrayPushObject(_indis, _ref); } - void Remove(IndicatorBase* _indi) { - Ref _ref = _indi; + void Remove(IndicatorData* _indi) { + Ref _ref = _indi; Util::ArrayRemoveFirst(_indis, _ref); } diff --git a/IndicatorBase.h b/IndicatorBase.h index c0a4e3569..94b662314 100644 --- a/IndicatorBase.h +++ b/IndicatorBase.h @@ -44,15 +44,11 @@ class Chart; #include "Indicator.struct.cache.h" #include "Indicator.struct.h" #include "Indicator.struct.serialize.h" -#include "Indicator.struct.signal.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" #include "Util.h" /** @@ -62,17 +58,10 @@ class IndicatorBase : public Chart { protected: IndicatorState istate; void* mydata; - bool is_fed; // Whether calc_start_bar is already calculated. - int calc_start_bar; // Index of the first valid bar (from 0). - DictStruct> indicators; // Indicators list keyed by id. + int calc_start_bar; // Index of the first valid bar (from 0). bool indicator_builtin; - ARRAY(ValueStorage*, value_storages); - 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. - long last_tick_time; // Time of the last Tick() call. - int flags; // Flags such as INDI_FLAG_INDEXABLE_BY_SHIFT. + long last_tick_time; // Time of the last Tick() call. + int flags; // Flags such as INDI_FLAG_INDEXABLE_BY_SHIFT. public: /* Indicator enumerations */ @@ -92,12 +81,10 @@ class IndicatorBase : public Chart { /** * Class constructor. */ - IndicatorBase(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, string _symbol = NULL) : indi_src(NULL), Chart(_tf, _symbol) { + IndicatorBase(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, string _symbol = 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; last_tick_time = 0; } @@ -108,53 +95,13 @@ class IndicatorBase : public Chart { // 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; last_tick_time = 0; } /** * Class deconstructor. */ - virtual ~IndicatorBase() { - ReleaseHandle(); - - for (int i = 0; i < ArraySize(value_storages); ++i) { - if (value_storages[i] != NULL) { - delete value_storages[i]; - } - } - } - - /* Operator overloading methods */ - - /** - * Access indicator entry data using [] operator via shift. - */ - 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); } + virtual ~IndicatorBase() { ReleaseHandle(); } /* Buffer methods */ @@ -231,120 +178,6 @@ class IndicatorBase : public Chart { } */ - /** - * Gets indicator data from a buffer and copy into struct array. - * - * @return - * Returns true of successful copy. - * Returns false on invalid values. - */ - bool CopyEntries(IndicatorDataEntry& _data[], int _count, int _start_shift = 0) { - bool _is_valid = true; - if (ArraySize(_data) < _count) { - _is_valid &= ArrayResize(_data, _count) > 0; - } - for (int i = 0; i < _count; i++) { - IndicatorDataEntry _entry = GetEntry(_start_shift + i); - _is_valid &= _entry.IsValid(); - _data[i] = _entry; - } - return _is_valid; - } - - /** - * Gets indicator data from a buffer and copy into array of values. - * - * @return - * Returns true of successful copy. - * Returns false on invalid values. - */ - template - bool CopyValues(T& _data[], int _count, int _start_shift = 0, int _mode = 0) { - bool _is_valid = true; - if (ArraySize(_data) < _count) { - _count = ArrayResize(_data, _count); - _count = _count > 0 ? _count : ArraySize(_data); - } - for (int i = 0; i < _count; i++) { - IndicatorDataEntry _entry = GetEntry(_start_shift + i); - _is_valid &= _entry.IsValid(); - _data[i] = (T)_entry[_mode]; - } - return _is_valid; - } - - /** - * Validates currently selected indicator used as data source. - */ - void ValidateSelectedDataSource() { - if (HasDataSource()) { - ValidateDataSource(THIS_PTR, GetDataSourceRaw()); - } - } - - /** - * Loads and validates built-in indicators whose can be used as data source. - */ - virtual void ValidateDataSource(IndicatorBase* _target, IndicatorBase* _source) {} - - /** - * Checks whether indicator have given mode index. - * - * If given mode is -1 (default one) and indicator has exactly one mode, then mode index will be replaced by 0. - */ - virtual void ValidateDataSourceMode(int& _out_mode) {} - - /** - * Provides built-in indicators whose can be used as data source. - */ - virtual IndicatorBase* FetchDataSource(ENUM_INDICATOR_TYPE _id) { return NULL; } - - /** - * Returns currently selected data source without any validation. - */ - 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; - } - - /** - * 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() { - 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. - */ - virtual IndicatorBase* DataSourceRequestReturnDefault(int _applied_price) { - DebugBreak(); - return NULL; - } - /* Getters */ /** @@ -352,11 +185,6 @@ class IndicatorBase : public Chart { */ int GetFlags() { return flags; } - /** - * Returns buffers' cache. - */ - IndicatorCalculateCache* GetCache() { return &cache; } - /** * Gets an indicator's chart parameter value. */ @@ -369,7 +197,7 @@ class IndicatorBase : public Chart { * Gets an indicator's state property value. */ template - T Get(STRUCT_ENUM(IndicatorState, ENUM_INDICATOR_STATE_PROP) _prop) { + T Get(STRUCT_ENUM_INDICATOR_STATE_PROP _prop) { return istate.Get(_prop); } @@ -390,8 +218,6 @@ class IndicatorBase : public Chart { */ virtual IndicatorBase* GetDataSource() { return NULL; } - int GetDataSourceMode() { return indi_src_mode; } - /** * Get indicator type. */ @@ -435,16 +261,6 @@ class IndicatorBase : public Chart { istate.Set(_prop, _value); } - /** - * Sets indicator data source. - */ - virtual void SetDataSource(IndicatorBase* _indi, int _input_mode = -1) = NULL; - - /** - * Sets data source's input mode. - */ - void SetDataSourceMode(int _mode) { indi_src_mode = _mode; } - /** * Sets name of the indicator. */ @@ -464,22 +280,6 @@ class IndicatorBase : public Chart { /* Other methods */ - /** - * 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); - } - /** * Releases indicator's handle. * @@ -495,226 +295,10 @@ class IndicatorBase : public Chart { istate.is_changed = true; } - 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); - } - 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; - } - - 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: - 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; - } - } - - 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. - */ - virtual bool HasSpecificValueStorage(ENUM_INDI_VS_TYPE _type) { return false; } - - template - T GetValue(int _mode = 0, int _index = 0) { - T _out; - GetEntryValue(_mode, _index).Get(_out); - return _out; - } - - /** - * Returns values for a given shift. - * - * Note: Remember to check if shift exists by HasValidEntry(shift). - */ - template - bool GetValues(int _index, T& _out1, T& _out2) { - IndicatorDataEntry _entry = GetEntry(_index); - _out1 = _entry.values[0]; - _out2 = _entry.values[1]; - bool _result = GetLastError() != 4401; - ResetLastError(); - return _result; - } - - template - 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]; - bool _result = GetLastError() != 4401; - ResetLastError(); - return _result; - } - - template - 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]; - _out4 = _entry.values[3]; - bool _result = GetLastError() != 4401; - ResetLastError(); - return _result; - } - - void Tick() { - long _current_time = TimeCurrent(); - - if (last_tick_time == _current_time) { - // We've already ticked. - return; - } - - last_tick_time = _current_time; - - // Checking and potentially initializing new data source. - if (HasDataSource(true) != NULL) { - // Ticking data source if not yet ticked. - 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(); - } - - // Overridable OnTick() method. - OnTick(); - } - - virtual void OnTick() {} - /* Data representation methods */ /* Virtual methods */ - /** - * Returns the indicator's struct value. - */ - 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. - * - * 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) = NULL; - - // virtual ENUM_IDATA_VALUE_RANGE GetIDataValueRange() = NULL; - - /** - * Returns the indicator's entry value. - */ - virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) = 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){}; - - /** - * 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. */ @@ -736,71 +320,11 @@ class IndicatorBase : public Chart { */ // virtual bool ToString() = NULL; // @fixme? - /** - * Whether we can and have to select mode when specifying data source. - */ - virtual bool IsDataSourceModeSelectable() { return true; } - - /** - * Update indicator. - */ - virtual bool Update() { - // @todo - return false; - }; - - /** - * Returns the indicator's value in plain format. - */ - 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; - - IndicatorDataEntry _stub_entry; - _stub_entry.AddFlags(_entry.GetFlags()); - SerializerConverter _stub = SerializerConverter::MakeStubObject(_stub_entry, _serializer_flags, _entry.GetSize()); - return SerializerConverter::FromObject(_entry, _serializer_flags).ToString(0, &_stub); - } - - int GetBarsCalculated() { - int _bars = Bars(GetSymbol(), GetTf()); - - if (!is_fed) { - // Calculating start_bar. - for (; calc_start_bar < _bars; ++calc_start_bar) { - // Iterating from the oldest or previously iterated. - IndicatorDataEntry _entry = GetEntry(_bars - calc_start_bar - 1); - - if (_entry.IsValid()) { - // From this point we assume that future entries will be all valid. - is_fed = true; - return _bars - calc_start_bar; - } - } - } - - if (!is_fed) { - Print("Can't find valid bars for ", GetFullName()); - return 0; - } - - // 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); } - /* Defines MQL backward compatible methods */ double iCustom(int& _handle, string _symbol, ENUM_TIMEFRAMES _tf, string _name, int _mode, int _shift) { @@ -933,41 +457,3 @@ class IndicatorBase : public Chart { #endif } }; - -/** - * CopyBuffer() method to be used on Indicator instance with ValueStorage buffer. - * - * Note that data will be copied so that the oldest element will be located at the start of the physical memory - * allocated for the array - */ -template -int CopyBuffer(IndicatorBase* _indi, int _mode, int _start, int _count, ValueStorage& _buffer, int _rates_total) { - int _num_copied = 0; - int _buffer_size = ArraySize(_buffer); - - if (_buffer_size < _rates_total) { - _buffer_size = ArrayResize(_buffer, _rates_total); - } - - for (int i = _start; i < _count; ++i) { - IndicatorDataEntry _entry = _indi.GetEntry(i); - - if (!_entry.IsValid()) { - break; - } - - T _value = _entry.GetValue(_mode); - - // Print(_value); - - _buffer[_buffer_size - i - 1] = _value; - ++_num_copied; - } - - return _num_copied; -} - -/** - * BarsCalculated()-compatible method to be used on Indicator instance. - */ -int BarsCalculated(IndicatorBase* _indi) { return _indi.GetBarsCalculated(); } diff --git a/IndicatorData.enum.h b/IndicatorData.enum.h new file mode 100644 index 000000000..12193a557 --- /dev/null +++ b/IndicatorData.enum.h @@ -0,0 +1,54 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2022, 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 IndicatorData's enums. + */ + +#ifndef __MQL__ +// Allows the preprocessor to include a header file when it is needed. +#pragma once +#endif + +/* Defines type of source data for */ +enum ENUM_IDATA_SOURCE_TYPE { + IDATA_BUILTIN = 0, // Platform built-in + IDATA_CHART, // Chart calculation + IDATA_ICUSTOM, // iCustom: Custom indicator file + IDATA_ICUSTOM_LEGACY, // iCustom: Custom, legacy, provided by MT indicator file + IDATA_INDICATOR, // OnIndicator: Another indicator as a source of data + IDATA_ONCALCULATE, // OnCalculate: Custom calculation function + IDATA_MATH // Math-based indicator +}; + +/* Defines range value data type for indicator storage. */ +enum ENUM_IDATA_VALUE_RANGE { + IDATA_RANGE_BINARY, // E.g. 0 or 1. + IDATA_RANGE_BITWISE, // Bitwise + IDATA_RANGE_MIXED, + IDATA_RANGE_PRICE, // Values represent price. + IDATA_RANGE_PRICE_DIFF, // Values represent price differences. + IDATA_RANGE_PRICE_ON_SIGNAL, // Values represent price on signal, otherwise zero. + IDATA_RANGE_RANGE, // E.g. 0 to 100. + IDATA_RANGE_UNKNOWN +}; diff --git a/IndicatorData.mqh b/IndicatorData.mqh index 242eb038a..9e0442f67 100644 --- a/IndicatorData.mqh +++ b/IndicatorData.mqh @@ -1,6 +1,6 @@ //+------------------------------------------------------------------+ //| EA31337 framework | -//| Copyright 2016-2021, EA31337 Ltd | +//| Copyright 2016-2022, EA31337 Ltd | //| https://github.com/EA31337 | //+------------------------------------------------------------------+ @@ -21,277 +21,948 @@ */ // Includes. -#include "Chart.mqh" -#include "Indicator.mqh" -#include "Log.mqh" - -#define TO_STRING_LIMIT_DEFAULT 3 -#define INDICATOR_BUFFERS_COUNT_MIN 1 -#define BUFFER_MAX_SIZE_DEFAULT 50 +#include "IndicatorBase.h" +#include "IndicatorData.enum.h" +#include "IndicatorData.struct.h" +#include "IndicatorData.struct.serialize.h" +#include "IndicatorData.struct.signal.h" +#include "Storage/ValueStorage.h" +#include "Storage/ValueStorage.indicator.h" +#include "Storage/ValueStorage.native.h" /** - * Class to store indicator value. + * Implements class to store indicator data. */ -class IndicatorValue { +class IndicatorData : public IndicatorBase { + protected: + // Class variables. + ARRAY(ValueStorage*, value_storages); + ARRAY(WeakRef, listeners); // List of indicators that listens for events from this one. + BufferStruct idata; + DictStruct> indicators; // Indicators list keyed by id. + IndicatorCalculateCache cache; + IndicatorDataParams idparams; // Indicator data params. + Ref indi_src; // Indicator used as data source. + + protected: + /* Protected methods */ + + bool Init() { + ArrayResize(value_storages, idparams.Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES))); + if (indi_src.IsSet()) { + // SetDataSource(_indi_src, _indi_mode); + idparams.Set(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE), IDATA_INDICATOR); + } + switch (idparams.Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { + case IDATA_BUILTIN: + break; + case IDATA_ICUSTOM: + break; + case IDATA_INDICATOR: + if (indi_src.IsSet() == NULL) { + // Indi_Price* _indi_price = Indi_Price::GetCached(GetSymbol(), GetTf(), iparams.GetShift()); + // SetDataSource(_indi_price, true, PRICE_OPEN); + } + break; + } + return true; + } + public: - datetime bt; // bar time - MqlParam value; // Contains value based on the data type (real, integer or string type). + /* Special methods */ - // double linked list attrs - IndicatorValue* prev; - IndicatorValue* next; + /** + * Class constructor. + */ + IndicatorData(const IndicatorDataParams& _idparams, IndicatorData* _indi_src = NULL, int _indi_mode = 0) + : idparams(_idparams), indi_src(_indi_src) {} + IndicatorData(const IndicatorDataParams& _idparams, ENUM_TIMEFRAMES _tf, string _symbol = NULL) + : idparams(_idparams), IndicatorBase(_tf, _symbol) {} - void IndicatorValue() : bt(NULL), prev(NULL), next(NULL) {} + /** + * Class deconstructor. + */ + virtual ~IndicatorData() { + for (int i = 0; i < ArraySize(value_storages); ++i) { + if (value_storages[i] != NULL) { + delete value_storages[i]; + } + } + } - // double linked list methods - void Prev(IndicatorValue* p) { - if (CheckPointer(p) == POINTER_INVALID) return; - prev = p; - p.next = GetPointer(this); + /* Operator overloading methods */ + + /** + * Access indicator entry data using [] operator via shift. + */ + 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); } - void Next(IndicatorValue* p) { - if (CheckPointer(p) == POINTER_INVALID) return; - next = p; - p.prev = GetPointer(this); + + /** + * 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); } -}; -/** - * Class to manage data buffer. - */ -class IndicatorBuffer { - protected: - int size; - int max_size; - IndicatorValue* _head; - IndicatorValue* _tail; + IndicatorDataEntry operator[](ENUM_INDICATOR_INDEX _index) { return GetEntry((int)_index); } - public: - IndicatorBuffer(int _max_size = BUFFER_MAX_SIZE_DEFAULT) : size(0), max_size(_max_size), _head(NULL), _tail(NULL) {} - ~IndicatorBuffer() { - IndicatorValue* it = NULL; - while (CheckPointer(_head) == POINTER_DYNAMIC) { - it = _head; - _head = _head.prev; - delete it; - } + /* Getters */ + + /** + * Gets a value from IndicatorDataParams struct. + */ + template + T Get(STRUCT_ENUM_IDATA_PARAM _param) { + return idparams.Get(_param); } - double GetDouble(datetime _bar_time) { - if (CheckPointer(_head) == POINTER_INVALID) return 0; + /** + * Gets an indicator's state property value. + */ + template + T Get(STRUCT_ENUM_INDICATOR_STATE_PROP _prop) { + return istate.Get(_prop); + } - IndicatorValue* _target = _head; - while (CheckPointer(_target) == POINTER_DYNAMIC && (_bar_time < _target.bt || _target.value.type != TYPE_DOUBLE)) { - _target = _target.prev; + /** + * Gets an indicator property flag. + */ + bool GetFlag(INDICATOR_ENTRY_FLAGS _prop, int _shift = 0) { + IndicatorDataEntry _entry = GetEntry(_shift); + return _entry.CheckFlag(_prop); + } + + /** + * 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; + ENUM_IDATA_VALUE_RANGE _idvrange = + Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDVRANGE)); + if (_idvrange != IDATA_RANGE_PRICE) { + _price = (float)GetPrice(_ap, _shift); + } else if (_idvrange == 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; + } - if (CheckPointer(_target) == POINTER_INVALID) return 0; + /* Setters */ - if (_target.bt == _bar_time && _target.value.type == TYPE_DOUBLE) - return _target.value.double_value; - else - return 0; + /** + * Sets the value for IndicatorDataParams struct. + */ + template + void Set(STRUCT_ENUM_IDATA_PARAM _param, T _value) { + idparams.Set(_param, _value); } - int GetInt(datetime _bar_time) { - if (CheckPointer(_head) == POINTER_INVALID) return 0; + /* State methods */ - IndicatorValue* _target = _head; - while (CheckPointer(_target) == POINTER_DYNAMIC && (_bar_time < _target.bt || _target.value.type != TYPE_INT)) { - _target = _target.prev; + /** + * 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; + } - if (CheckPointer(_target) == POINTER_INVALID) return 0; + /** + * 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; + } - if (_target.bt == _bar_time && _target.value.type == TYPE_INT) - return (int)_target.value.integer_value; - else - return 0; + /** + * 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; } - bool Add(double _value, datetime _bar_time, bool _force = false) { - IndicatorValue* new_value = new IndicatorValue(); - new_value.bt = _bar_time; - new_value.value.type = TYPE_DOUBLE; - new_value.value.double_value = _value; - return AddIndicatorValue(new_value, _force); + /** + * 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; } - bool Add(int _value, datetime _bar_time, bool _force = false) { - IndicatorValue* new_value = new IndicatorValue(); - new_value.bt = _bar_time; - new_value.value.type = TYPE_INT; - new_value.value.integer_value = _value; - return AddIndicatorValue(new_value, _force); + /* Getters */ + + /** + * Returns the highest bar's index (shift). + */ + template + int GetHighest(int count = WHOLE_ARRAY, int start_bar = 0) { + int max_idx = -1; + double max = -DBL_MAX; + int last_bar = count == WHOLE_ARRAY ? (int)(GetBarShift(GetLastBarTime())) : (start_bar + count - 1); + + for (int shift = start_bar; shift <= last_bar; ++shift) { + double value = GetEntry(shift).GetMax(GetModeCount()); + if (value > max) { + max = value; + max_idx = shift; + } + } + + return max_idx; } - bool AddIndicatorValue(IndicatorValue* _new_value, bool _force = false) { - if (CheckPointer(_new_value) == POINTER_INVALID) return false; + /** + * Returns the lowest bar's index (shift). + */ + template + int GetLowest(int count = WHOLE_ARRAY, int start_bar = 0) { + int min_idx = -1; + double min = DBL_MAX; + int last_bar = count == WHOLE_ARRAY ? (int)(GetBarShift(GetLastBarTime())) : (start_bar + count - 1); + + for (int shift = start_bar; shift <= last_bar; ++shift) { + double value = GetEntry(shift).GetMin(GetModeCount()); + if (value < min) { + min = value; + min_idx = shift; + } + } + + return min_idx; + } + + /** + * Returns the highest value. + */ + template + double GetMax(int start_bar = 0, int count = WHOLE_ARRAY) { + double max = NULL; + int last_bar = count == WHOLE_ARRAY ? (int)(GetBarShift(GetLastBarTime())) : (start_bar + count - 1); + int _max_modes = Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES)); + + for (int shift = start_bar; shift <= last_bar; ++shift) { + double value = GetEntry(shift).GetMax(_max_modes); + if (max == NULL || value > max) { + max = value; + } + } + + return max; + } - // first node for empty linked list - if (CheckPointer(_head) == POINTER_INVALID) { - _head = _new_value; - _tail = _new_value; - size = 1; - return true; + /** + * Returns the lowest value. + */ + template + double GetMin(int start_bar, int count = WHOLE_ARRAY) { + double min = NULL; + int last_bar = count == WHOLE_ARRAY ? (int)(GetBarShift(GetLastBarTime())) : (start_bar + count - 1); + int _max_modes = Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES)); + + for (int shift = start_bar; shift <= last_bar; ++shift) { + double value = GetEntry(shift).GetMin(_max_modes); + if (min == NULL || value < min) { + min = value; + } } - // find insert position - IndicatorValue* insert_pos = _head; - while (CheckPointer(insert_pos) == POINTER_DYNAMIC && _new_value.bt <= insert_pos.bt) { - insert_pos = insert_pos.prev; + return min; + } + + /** + * Returns average value. + */ + template + double GetAvg(int start_bar, int count = WHOLE_ARRAY) { + int num_values = 0; + double sum = 0; + int last_bar = count == WHOLE_ARRAY ? (int)(GetBarShift(GetLastBarTime())) : (start_bar + count - 1); + int _max_modes = Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES)); + + for (int shift = start_bar; shift <= last_bar; ++shift) { + double value_min = GetEntry(shift).GetMin(_max_modes); + double value_max = GetEntry(shift).GetMax(_max_modes); + + sum += value_min + value_max; + num_values += 2; } - // find existed value node(match both bt and value.type), force replace or not - if (CheckPointer(insert_pos) == POINTER_DYNAMIC && _new_value.bt == insert_pos.bt && - _new_value.value.type == insert_pos.value.type) { - if (_force) { - insert_pos.value.integer_value = _new_value.value.integer_value; - insert_pos.value.double_value = _new_value.value.double_value; - insert_pos.value.string_value = _new_value.value.string_value; - return true; - } else - return false; + return sum / num_values; + } + + /** + * Returns median of values. + */ + template + double GetMed(int start_bar, int count = WHOLE_ARRAY) { + double array[]; + + int last_bar = count == WHOLE_ARRAY ? (int)(GetBarShift(GetLastBarTime())) : (start_bar + count - 1); + int num_bars = last_bar - start_bar + 1; + int index = 0; + int _max_modes = Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES)); + + ArrayResize(array, num_bars); + + for (int shift = start_bar; shift <= last_bar; ++shift) { + array[index++] = GetEntry(shift).GetAvg(_max_modes); } - // find insert pos at end of linked list - if (CheckPointer(insert_pos) == POINTER_INVALID) { - _tail.Prev(_new_value); - _tail = _new_value; + ArraySort(array); + double median; + int len = ArraySize(array); + if (len % 2 == 0) { + median = (array[len / 2] + array[(len / 2) - 1]) / 2; + } else { + median = array[len / 2]; } - // find insert pos at begin of linked list - else if (insert_pos == _head) { - _head.Next(_new_value); - _head = _new_value; + + return median; + } + + /* Data methods */ + + /** + * Gets indicator data from a buffer and copy into struct array. + * + * @return + * Returns true of successful copy. + * Returns false on invalid values. + */ + bool CopyEntries(IndicatorDataEntry& _data[], int _count, int _start_shift = 0) { + bool _is_valid = true; + if (ArraySize(_data) < _count) { + _is_valid &= ArrayResize(_data, _count) > 0; } - // find insert pos at normal place - else { - insert_pos.Next(_new_value); + for (int i = 0; i < _count; i++) { + IndicatorDataEntry _entry = GetEntry(_start_shift + i); + _is_valid &= _entry.IsValid(); + _data[i] = _entry; } - size++; + return _is_valid; + } + + /** + * Gets indicator data from a buffer and copy into array of values. + * + * @return + * Returns true of successful copy. + * Returns false on invalid values. + */ + template + bool CopyValues(T& _data[], int _count, int _start_shift = 0, int _mode = 0) { + bool _is_valid = true; + if (ArraySize(_data) < _count) { + _count = ArrayResize(_data, _count); + _count = _count > 0 ? _count : ArraySize(_data); + } + for (int i = 0; i < _count; i++) { + IndicatorDataEntry _entry = GetEntry(_start_shift + i); + _is_valid &= _entry.IsValid(); + _data[i] = (T)_entry[_mode]; + } + return _is_valid; + } + + /* Getters */ + + int GetBarsCalculated(ENUM_TIMEFRAMES _tf = NULL) { + int _bars = Bars(GetSymbol(), _tf); - // truncate data out of max_size - if (size > max_size) { - for (int i = 0; i < (max_size - size); i++) { - _tail = _tail.next; - delete _tail.prev; - size--; + if (!idparams.Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IS_FED))) { + // Calculating start_bar. + for (; calc_start_bar < _bars; ++calc_start_bar) { + // Iterating from the oldest or previously iterated. + IndicatorDataEntry _entry = GetEntry(_bars - calc_start_bar - 1); + + if (_entry.IsValid()) { + // From this point we assume that future entries will be all valid. + idparams.Set(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IS_FED), true); + return _bars - calc_start_bar; + } } } - return true; + if (!idparams.Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IS_FED))) { + Print("Can't find valid bars for ", GetFullName()); + return 0; + } + + // Assuming all entries are calculated (even if have invalid values). + return _bars; } - string ToString(uint _limit = TO_STRING_LIMIT_DEFAULT) { - string out = NULL; - IndicatorValue* it = _head; - uint i = 0; - while (CheckPointer(it) == POINTER_DYNAMIC && i < _limit) { - if (out != NULL) - // add comma - out = StringFormat("%s, ", out); - else - out = ""; - - switch (it.value.type) { - case TYPE_INT: - out = StringFormat("%s[%d]%d", out, i, it.value.integer_value); - break; - case TYPE_DOUBLE: { - string strfmt = StringFormat("%%s[%%d]%%.%df", _Digits); - out = StringFormat(strfmt, out, i, it.value.double_value); - break; - } + /** + * Returns buffers' cache. + */ + IndicatorCalculateCache* GetCache() { return &cache; } + + /** + * Get pointer to data of indicator. + */ + BufferStruct* GetData() { return GetPointer(idata); } + + /** + * Returns given data source type. Used by i*OnIndicator methods if indicator's Calculate() uses other indicators. + */ + IndicatorData* GetDataSource(ENUM_INDICATOR_TYPE _type) { + IndicatorData* _result = NULL; + 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(), "!"); + DebugBreak(); + } else { + indicators.Set((int)_type, _indi); + _result = _indi.Ptr(); } - i++; - it = it.prev; } - if (out == "" || out == NULL) out = "[Empty]"; - return out; + return _result; } -}; -/** - * Implements class to store indicator data. - */ -class IndicatorData : public Chart { - protected: - // Struct variables. - IndicatorBuffer buffers[]; + // int GetDataSourceMode() { return indi_src_mode; } + + /** + * Returns currently selected data source without any validation. + */ + IndicatorBase* GetDataSourceRaw() { return indi_src.Ptr(); } + + /** + * Returns values for a given shift. + * + * Note: Remember to check if shift exists by HasValidEntry(shift). + */ + template + bool GetValues(int _index, T& _out1, T& _out2) { + IndicatorDataEntry _entry = GetEntry(_index); + _out1 = _entry.values[0]; + _out2 = _entry.values[1]; + bool _result = GetLastError() != 4401; + ResetLastError(); + return _result; + } - string iname; + template + 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]; + bool _result = GetLastError() != 4401; + ResetLastError(); + return _result; + } - // Logging. - Ref indi_logger; + template + 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]; + _out4 = _entry.values[3]; + bool _result = GetLastError() != 4401; + ResetLastError(); + return _result; + } - public: /** - * Class constructor. + * Provides built-in indicators whose can be used as data source. */ - void IndicatorData(string _name = NULL, uint _max_buffer = INDICATOR_BUFFERS_COUNT_MIN) : iname(_name) { - _max_buffer = fmax(_max_buffer, INDICATOR_BUFFERS_COUNT_MIN); - ArrayResize(buffers, _max_buffer); + virtual IndicatorBase* FetchDataSource(ENUM_INDICATOR_TYPE _id) { return NULL; } + + /* Checkers */ + + /** + * Whether we can and have to select mode when specifying data source. + */ + virtual bool IsDataSourceModeSelectable() { return true; } + + /* Setters */ + + /** + * Adds event listener. + */ + void AddListener(IndicatorData* _indi) { + WeakRef _ref = _indi; + ArrayPushObject(listeners, _ref); } /** - * Class deconstructor. + * Removes event listener. */ - void ~IndicatorData() {} + void RemoveListener(IndicatorData* _indi) { + WeakRef _ref = _indi; + Util::ArrayRemoveFirst(listeners, _ref); + } /** - * Store a new indicator value. + * Sets data source's input mode. */ - bool IsValidMode(uint _mode) { return _mode < (uint)ArraySize(buffers); } + // void SetDataSourceMode(int _mode) { indi_src_mode = _mode; } - bool Add(double _value, uint _mode = 0, uint _shift = CURR, bool _force = false) { - if (!IsValidMode(_mode)) return false; - return buffers[_mode].Add(_value, GetBarTime(_shift), _force); + /* Storage methods */ + + 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); + } + return value_storages[_mode]; } - bool Add(int _value, uint _mode = 0, uint _shift = CURR, bool _force = false) { - if (!IsValidMode(_mode)) return false; - return buffers[_mode].Add(_value, GetBarTime(_shift), _force); + /** + * 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; } - double GetDouble(uint _mode = 0, uint _shift = CURR) { - if (!IsValidMode(_mode)) return 0; - return buffers[_mode].GetDouble(GetBarTime(_shift)); + 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: + 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; + } } - int GetInt(uint _mode = 0, uint _shift = CURR) { - if (!IsValidMode(_mode)) return 0; - return buffers[_mode].GetInt(GetBarTime(_shift)); + 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; + } } /** - * Get name of the indicator. + * Checks whether indicator support given value storage type. */ - string GetName() { return iname != NULL ? iname : "Custom"; } + virtual bool HasSpecificValueStorage(ENUM_INDI_VS_TYPE _type) { return false; } + + /* Tick methods */ + + void Tick() { + long _current_time = TimeCurrent(); + + if (last_tick_time == _current_time) { + // We've already ticked. + return; + } + + last_tick_time = _current_time; + + // Checking and potentially initializing new data source. + if (HasDataSource(true) != NULL) { + // Ticking data source if not yet ticked. + 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(); + } + + // Overridable OnTick() method. + OnTick(); + } + + /* Validate methods */ /** - * Print stored data. + * Loads and validates built-in indicators whose can be used as data source. */ - string ToString(int mode = -1, uint _limit = TO_STRING_LIMIT_DEFAULT) { - string _out = StringFormat("%s DATA:\n", GetName()); - if (mode == -1) { // print all series - for (int m = 0; m < ArraySize(buffers); m++) { - _out = StringFormat("%s mode=%d %s\n", _out, m, buffers[m].ToString(_limit)); - } - } else if (mode < ArraySize(buffers)) { - _out = StringFormat("%s mode(%d) %s\n", _out, mode, buffers[mode].ToString(_limit)); - } else { - _out = StringFormat("%s [Err] mode(%d) is invalid", mode); + void ValidateDataSource(IndicatorData* _target, IndicatorData* _source) { + if (_target == NULL) { + Alert("Internal Error! _target is NULL in ", __FUNCTION_LINE__, "."); + DebugBreak(); + return; + } + + if (_source == NULL) { + Alert("Error! You have to select source indicator's via SetDataSource()."); + DebugBreak(); + return; + } + + if (!_target.IsDataSourceModeSelectable()) { + // We don't validate source mode as it will use all modes. + return; } + + if (_source.GetModeCount() > 1 && + _target.idparams.Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_DATA_SRC_MODE)) == -1) { + // Mode must be selected if source indicator has more that one mode. + Alert("Warning! ", GetName(), + " must select source indicator's mode via SetDataSourceMode(int). Defaulting to mode 0."); + _target.idparams.Set(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_DATA_SRC_MODE), 0); + DebugBreak(); + } else if (_source.Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_DATA_SRC_MODE)) == 1 && + _target.idparams.Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_DATA_SRC_MODE)) == -1) { + _target.idparams.Set(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_DATA_SRC_MODE), 0); + } else if (_target.idparams.Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_DATA_SRC_MODE)) < 0 || + _target.idparams.Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_DATA_SRC_MODE)) > + _source.Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES))) { + Alert("Error! ", _target.GetName(), + " must select valid source indicator's mode via SetDataSourceMode(int) between 0 and ", + _source.Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES)), "."); + DebugBreak(); + } + } + + /** + * Validates currently selected indicator used as data source. + */ + void ValidateSelectedDataSource() { + if (HasDataSource()) { + ValidateDataSource(THIS_PTR, GetDataSourceRaw()); + } + } + + /* Printers */ + + /** + * Returns the indicator's value in plain format. + */ + 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; + + IndicatorDataEntry _stub_entry; + _stub_entry.AddFlags(_entry.GetFlags()); + SerializerConverter _stub = SerializerConverter::MakeStubObject(_stub_entry, _serializer_flags, _entry.GetSize()); + return SerializerConverter::FromObject(_entry, _serializer_flags).ToString(0, &_stub); + } + + template + T GetValue(int _mode = 0, int _index = 0) { + T _out; + GetEntryValue(_mode, _index).Get(_out); return _out; } + /* Virtual methods */ + /** - * Print stored data. + * Returns currently selected data source doing validation. */ - void PrintData(int mode = -1, uint _limit = TO_STRING_LIMIT_DEFAULT) { Print(ToString(mode, _limit)); } + virtual IndicatorData* GetDataSource() { return 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; + } + + /** + * Returns the indicator's struct value. + */ + virtual IndicatorDataEntry GetEntry(int _index = 0) = NULL; + + /** + * 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 _index = -1) = NULL; + + // virtual ENUM_IDATA_VALUE_RANGE GetIDataValueRange() = NULL; + + /** + * Returns the indicator's entry value. + */ + virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) = NULL; + + /** + * 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) = 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 indicator became a data source for other indicator. + */ + virtual void OnBecomeDataSourceFor(IndicatorData* _base_indi){}; + + /** + * Called when data source emits new entry (historic or future one). + */ + virtual void OnDataSourceEntry(IndicatorDataEntry& entry){}; + + virtual void OnTick() {} + + /** + * 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 IndicatorData* 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. + */ + virtual IndicatorData* DataSourceRequestReturnDefault(int _applied_price) { + DebugBreak(); + return NULL; + } + + /** + * Called when user tries to set given data source. Could be used to check if indicator implements all required value + * storages. + */ + virtual bool OnValidateDataSource(IndicatorData* _ds, string& _reason) { + _reason = "Indicator " + GetName() + " does not implement OnValidateDataSource()"; + return false; + } + + /** + * Sets indicator data source. + */ + virtual void SetDataSource(IndicatorData* _indi, int _input_mode = -1) = NULL; /** * Update indicator. */ - bool Update() { return true; } + virtual bool Update() { + // @todo + return false; + }; + + /** + * Loads and validates built-in indicators whose can be used as data source. + */ + // virtual void ValidateDataSource(IndicatorData* _target, IndicatorData* _source) {} + + /** + * Checks whether indicator have given mode index. + * + * If given mode is -1 (default one) and indicator has exactly one mode, then mode index will be replaced by 0. + */ + virtual void ValidateDataSourceMode(int& _out_mode) {} }; + +/** + * BarsCalculated()-compatible method to be used on Indicator instance. + */ +int BarsCalculated(IndicatorData* _indi) { return _indi.GetBarsCalculated(); } + +/** + * CopyBuffer() method to be used on Indicator instance with ValueStorage buffer. + * + * Note that data will be copied so that the oldest element will be located at the start of the physical memory + * allocated for the array + */ +template +int CopyBuffer(IndicatorData* _indi, int _mode, int _start, int _count, ValueStorage& _buffer, int _rates_total) { + int _num_copied = 0; + int _buffer_size = ArraySize(_buffer); + + if (_buffer_size < _rates_total) { + _buffer_size = ArrayResize(_buffer, _rates_total); + } + + for (int i = _start; i < _count; ++i) { + IndicatorDataEntry _entry = _indi.GetEntry(i); + + if (!_entry.IsValid()) { + break; + } + + T _value = _entry.GetValue(_mode); + + _buffer[_buffer_size - i - 1] = _value; + ++_num_copied; + } + + return _num_copied; +} diff --git a/IndicatorData.struct.h b/IndicatorData.struct.h new file mode 100644 index 000000000..b6f942eb4 --- /dev/null +++ b/IndicatorData.struct.h @@ -0,0 +1,503 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2022, 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 IndicatorData's structs. + */ + +// Defines. +#define STRUCT_ENUM_IDATA_PARAM STRUCT_ENUM(IndicatorDataParams, ENUM_IDATA_PARAM) + +// Includes. +#include "SerializerNode.enum.h" + +// Type-less value for IndicatorDataEntryValue structure. +union IndicatorDataEntryTypelessValue { + double vdbl; + float vflt; + int vint; + long vlong; +}; + +// Type-aware value for IndicatorDataEntry class. +struct IndicatorDataEntryValue { + unsigned char flags; + IndicatorDataEntryTypelessValue value; + + // Returns type of the value. + ENUM_DATATYPE GetDataType() { return (ENUM_DATATYPE)((flags & 0xF0) >> 4); } + + // Sets type of the value. + void SetDataType(ENUM_DATATYPE _type) { + // Clearing type. + flags &= 0x0F; + + // Setting type. + flags |= (unsigned char)_type << 4; + } + + // Union operators. + template + T operator*(const T _value) { + return Get() * _value; + } + template + T operator+(const T _value) { + return Get() + _value; + } + template + T operator-(const T _value) { + return Get() - _value; + } + template + T operator/(const T _value) { + return Get() / _value; + } + template + bool operator!=(const T _value) { + return Get() != _value; + } + template + bool operator<(const T _value) { + return Get() < _value; + } + template + bool operator<=(const T _value) { + return Get() <= _value; + } + template + bool operator==(const T _value) { + return Get() == _value; + } + template + bool operator>(const T _value) { + return Get() > _value; + } + template + bool operator>=(const T _value) { + return Get() >= _value; + } + template + void operator=(const T _value) { + Set(_value); + } + // Checkers. + template + bool IsGt(T _value) { + return Get() > _value; + } + template + bool IsLt(T _value) { + return Get() < _value; + } + // Getters. + double GetDbl() { return value.vdbl; } + float GetFloat() { return value.vflt; } + int GetInt() { return value.vint; } + long GetLong() { return value.vlong; } + template + void Get(T &_out) { + _out = Get(); + } + template + T Get() { + T _v; + Get(_v); + return _v; + } + void Get(double &_out) { _out = value.vdbl; } + void Get(float &_out) { _out = value.vflt; } + void Get(int &_out) { _out = value.vint; } + void Get(unsigned int &_out) { _out = (unsigned int)value.vint; } + void Get(long &_out) { _out = value.vlong; } + void Get(unsigned long &_out) { _out = (unsigned long)value.vint; } + // Setters. + template + void Set(T _value) { + Set(_value); + } + void Set(double _value) { + value.vdbl = _value; + SetDataType(TYPE_DOUBLE); + } + void Set(float _value) { + value.vflt = _value; + SetDataType(TYPE_FLOAT); + } + void Set(int _value) { + value.vint = _value; + SetDataType(TYPE_INT); + } + void Set(unsigned int _value) { + value.vint = (int)_value; + SetDataType(TYPE_UINT); + } + void Set(long _value) { + value.vlong = _value; + SetDataType(TYPE_LONG); + } + void Set(unsigned long _value) { + value.vlong = (long)_value; + SetDataType(TYPE_ULONG); + } + // Serializers. + // SERIALIZER_EMPTY_STUB + SerializerNodeType Serialize(Serializer &_s); + // To string + template + string ToString() { + return (string)Get(); + } +}; + +/* Structure for indicator data entry. */ +struct IndicatorDataEntry { + long timestamp; // Timestamp of the entry's bar. + unsigned short flags; // Indicator entry flags. + ARRAY(IndicatorDataEntryValue, values); + + // Constructors. + IndicatorDataEntry(int _size = 1) : flags(INDI_ENTRY_FLAG_NONE), timestamp(0) { Resize(_size); } + IndicatorDataEntry(IndicatorDataEntry &_entry) { THIS_REF = _entry; } + int GetSize() { return ArraySize(values); } + // Operator overloading methods. + template + T operator*(const T _value) { + return values[0].Get() * _value; + } + template + T operator+(const T _value) { + return values[0].Get() + _value; + } + template + T operator-(const T _value) { + return values[0].Get() - _value; + } + template + T operator/(const T _value) { + return values[0].Get() / _value; + } + template + T operator[](I _index) { + return values[(int)_index].Get(); + } + template <> + double operator[](int _index) { + if (_index >= ArraySize(values)) { + return 0; + } + double _value; + values[_index].Get(_value); + return _value; + } + // Checkers. + template + bool HasValue(T _value) { + bool _result = false; + int _asize = ArraySize(values); + T _value2; + for (int i = 0; i < _asize; i++) { + values[i].Get(_value2); + if (_value == _value2) { + _result = true; + break; + } + } + return _result; + } + template + bool IsGe(T _value) { + return GetMin() >= _value; + } + template + bool IsGt(T _value) { + return GetMin() > _value; + } + template + bool IsLe(T _value) { + return GetMax() <= _value; + } + template + bool IsLt(T _value) { + return GetMax() < _value; + } + template + bool IsWithinRange(T _min, T _max) { + return GetMin() >= _min && GetMax() <= _max; + } + // Getters. + template + void GetArray(ARRAY_REF(T, _out), int _size = 0) { + int _asize = _size > 0 ? _size : ArraySize(_out); + for (int i = 0; i < _asize; i++) { + values[i].Get(_out[i]); + } + }; + template + T GetAvg(int _size = 0) { + int _asize = _size > 0 ? _size : ArraySize(values); + T _avg = GetSum() / _asize; + return _avg; + }; + template + T GetMin(int _size = 0) { + int _asize = _size > 0 ? _size : ArraySize(values); + int _index = 0; + for (int i = 1; i < _asize; i++) { + _index = values[i].Get() < values[_index].Get() ? i : _index; + } + return values[_index].Get(); + }; + template + T GetMax(int _size = 0) { + int _asize = _size > 0 ? _size : ArraySize(values); + int _index = 0; + for (int i = 1; i < _asize; i++) { + _index = values[i].Get() > values[_index].Get() ? i : _index; + } + return values[_index].Get(); + }; + template + T GetSum(int _size = 0) { + int _asize = _size > 0 ? _size : ArraySize(values); + T _sum = 0; + for (int i = 1; i < _asize; i++) { + _sum = +values[i].Get(); + } + return _sum; + }; + template + T GetValue(int _index = 0) { + return values[_index].Get(); + }; + template + void GetValues(T &_out1, T &_out2) { + values[0].Get(_out1); + values[1].Get(_out2); + }; + template + void GetValues(T &_out1, T &_out2, T &_out3) { + values[0].Get(_out1); + values[1].Get(_out2); + values[2].Get(_out3); + }; + template + void GetValues(T &_out1, T &_out2, T &_out3, T &_out4) { + values[0].Get(_out1); + values[1].Get(_out2); + values[2].Get(_out3); + values[3].Get(_out4); + }; + + // Getters. + int GetDayOfYear() { return DateTimeStatic::DayOfYear(timestamp); } + int GetMonth() { return DateTimeStatic::Month(timestamp); } + int GetYear() { return DateTimeStatic::Year(timestamp); } + long GetTime() { return timestamp; }; + ENUM_DATATYPE GetDataType(int _mode) { return values[_mode].GetDataType(); } + ushort GetDataTypeFlags(ENUM_DATATYPE _dt) { + switch (_dt) { + case TYPE_BOOL: + case TYPE_CHAR: + SetUserError(ERR_INVALID_PARAMETER); + break; + case TYPE_INT: + return INDI_ENTRY_FLAG_NONE; + case TYPE_LONG: + return INDI_ENTRY_FLAG_IS_DOUBLED; + case TYPE_UINT: + return INDI_ENTRY_FLAG_IS_UNSIGNED; + case TYPE_ULONG: + return INDI_ENTRY_FLAG_IS_UNSIGNED | INDI_ENTRY_FLAG_IS_DOUBLED; + case TYPE_DOUBLE: + return INDI_ENTRY_FLAG_IS_REAL | INDI_ENTRY_FLAG_IS_DOUBLED; + case TYPE_FLOAT: + return INDI_ENTRY_FLAG_IS_REAL; + case TYPE_STRING: + case TYPE_UCHAR: + SetUserError(ERR_INVALID_PARAMETER); + break; + default: + SetUserError(ERR_INVALID_PARAMETER); + break; + } + SetUserError(ERR_INVALID_PARAMETER); + return INDI_ENTRY_FLAG_NONE; + } + // Setters. + bool Resize(int _size = 0) { return _size > 0 ? ArrayResize(values, _size) > 0 : true; } + // Value flag methods for bitwise operations. + bool CheckFlag(INDICATOR_ENTRY_FLAGS _prop) { return CheckFlags(_prop); } + bool CheckFlags(unsigned short _flags) { return (flags & _flags) != 0; } + bool CheckFlagsAll(unsigned short _flags) { return (flags & _flags) == _flags; } + void AddFlags(unsigned short _flags) { flags |= _flags; } + void RemoveFlags(unsigned short _flags) { flags &= ~_flags; } + void SetFlag(INDICATOR_ENTRY_FLAGS _flag, bool _value) { + if (_value) { + AddFlags(_flag); + } else { + RemoveFlags(_flag); + } + } + void SetFlags(unsigned short _flags) { flags = _flags; } + unsigned short GetFlags() { return flags; } + // Converters. + // State checkers. + bool IsValid() { return CheckFlags(INDI_ENTRY_FLAG_IS_VALID); } + // Serializers. + void SerializeStub(int _n1 = 1, int _n2 = 1, int _n3 = 1, int _n4 = 1, int _n5 = 1) { + ArrayResize(values, _n1); + for (int i = 0; i < _n1; ++i) { + values[i] = (int)1; + } + } + SerializerNodeType Serialize(Serializer &_s); + template + string ToCSV() { + int _asize = ArraySize(values); + string _result = ""; + for (int i = 0; i < _asize; i++) { + _result += StringFormat("%s%s", (string)values[i].Get(), i < _asize ? "," : ""); + } + return _result; + } + template + string ToString() { + return ToCSV(); + } +}; + +/* Structure for indicator data parameters. */ +struct IndicatorDataParams { + protected: + /* Struct protected variables */ + bool is_fed; // Whether calc_start_bar is already calculated. + int data_src_mode; // Mode used as input from data source. + int src_id; // Id of the indicator to be used as data source. + int src_mode; // Mode of source indicator + unsigned int max_buffers; // Max buffers to store. + unsigned int max_modes; // Max supported indicator modes (values per entry). + ENUM_DATATYPE dtype; // Type of basic data to store values (DTYPE_DOUBLE, DTYPE_INT). + ENUM_IDATA_SOURCE_TYPE idstype; // Indicator's data source type (e.g. IDATA_BUILTIN, IDATA_ICUSTOM). + ENUM_IDATA_VALUE_RANGE idvrange; // Indicator's range value data type. + public: + /* Struct enumerations */ + enum ENUM_IDATA_PARAM { + IDATA_PARAM_IS_FED = 0, + IDATA_PARAM_DATA_SRC_MODE, + IDATA_PARAM_DTYPE, + IDATA_PARAM_IDSTYPE, + IDATA_PARAM_IDVRANGE, + IDATA_PARAM_MAX_BUFFERS, + IDATA_PARAM_MAX_MODES, + IDATA_PARAM_SRC_ID, + IDATA_PARAM_SRC_MODE, + }; + + public: + /* Special methods */ + // Constructor. + IndicatorDataParams(unsigned int _max_modes = 1, ENUM_DATATYPE _dtype = TYPE_DOUBLE, + ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, + ENUM_IDATA_VALUE_RANGE _idvrange = IDATA_RANGE_UNKNOWN, int _data_src_mode = 0) + : data_src_mode(_data_src_mode), + dtype(_dtype), + max_modes(_max_modes), + max_buffers(10), + idstype(_idstype), + idvrange(_idvrange), + is_fed(false), + src_id(-1), + src_mode(-1){}; + // Copy constructor. + IndicatorDataParams(const IndicatorDataParams &_idp) { THIS_REF = _idp; } + // Deconstructor. + ~IndicatorDataParams(){}; + /* Getters */ + template + T Get(STRUCT_ENUM_IDATA_PARAM _param) { + switch (_param) { + case IDATA_PARAM_IS_FED: + return (T)is_fed; + case IDATA_PARAM_DATA_SRC_MODE: + return (T)data_src_mode; + case IDATA_PARAM_DTYPE: + return (T)dtype; + case IDATA_PARAM_IDSTYPE: + return (T)idstype; + case IDATA_PARAM_IDVRANGE: + return (T)idvrange; + case IDATA_PARAM_MAX_BUFFERS: + return (T)max_buffers; + case IDATA_PARAM_MAX_MODES: + return (T)max_modes; + case IDATA_PARAM_SRC_ID: + return (T)src_id; + case IDATA_PARAM_SRC_MODE: + return (T)src_mode; + } + SetUserError(ERR_INVALID_PARAMETER); + return (T)WRONG_VALUE; + } + static IndicatorDataParams GetInstance(unsigned int _max_modes = 1, ENUM_DATATYPE _dtype = TYPE_DOUBLE, + ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, + ENUM_IDATA_VALUE_RANGE _idvrange = IDATA_RANGE_UNKNOWN, + int _data_src_mode = 0) { + IndicatorDataParams _instance(_max_modes, _dtype, _idstype, _idvrange, _data_src_mode); + return _instance; + } + /* Setters */ + template + void Set(STRUCT_ENUM_IDATA_PARAM _param, T _value) { + switch (_param) { + case IDATA_PARAM_IS_FED: + is_fed = (bool)_value; + return; + case IDATA_PARAM_DATA_SRC_MODE: + data_src_mode = (int)_value; + return; + case IDATA_PARAM_DTYPE: + dtype = (ENUM_DATATYPE)_value; + return; + case IDATA_PARAM_IDSTYPE: + idstype = (ENUM_IDATA_SOURCE_TYPE)_value; + return; + case IDATA_PARAM_IDVRANGE: + idvrange = (ENUM_IDATA_VALUE_RANGE)_value; + return; + case IDATA_PARAM_MAX_BUFFERS: + max_buffers = (unsigned int)_value; + return; + case IDATA_PARAM_MAX_MODES: + max_modes = (unsigned int)_value; + return; + case IDATA_PARAM_SRC_ID: + src_id = (int)_value; + return; + case IDATA_PARAM_SRC_MODE: + src_mode = (int)_value; + return; + } + SetUserError(ERR_INVALID_PARAMETER); + } +}; diff --git a/IndicatorData.struct.serialize.h b/IndicatorData.struct.serialize.h new file mode 100644 index 000000000..87020224e --- /dev/null +++ b/IndicatorData.struct.serialize.h @@ -0,0 +1,97 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2022, 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 IndicatorData's struct serializers. + */ + +#include "Serializer.mqh" + +// Forward class declaration. +class Serializer; + +/* Method to serialize IndicatorDataEntry structure. */ +SerializerNodeType IndicatorDataEntry::Serialize(Serializer &_s) { + int _asize = ArraySize(values); + _s.Pass(THIS_REF, "datetime", timestamp, SERIALIZER_FIELD_FLAG_DYNAMIC); + _s.Pass(THIS_REF, "flags", flags, SERIALIZER_FIELD_FLAG_DYNAMIC); + for (int i = 0; i < _asize; i++) { + // _s.Pass(THIS_REF, (string)i, values[i], SERIALIZER_FIELD_FLAG_DYNAMIC | SERIALIZER_FIELD_FLAG_FEATURE); // Can + // this work? _s.Pass(THIS_REF, (string)i, GetEntry(i), SERIALIZER_FIELD_FLAG_DYNAMIC | + // SERIALIZER_FIELD_FLAG_FEATURE); // Can this work? + + switch (values[i].GetDataType()) { + case TYPE_DOUBLE: + _s.Pass(THIS_REF, (string)i, values[i].value.vdbl, + SERIALIZER_FIELD_FLAG_DYNAMIC | SERIALIZER_FIELD_FLAG_FEATURE); + break; + case TYPE_FLOAT: + _s.Pass(THIS_REF, (string)i, values[i].value.vflt, + SERIALIZER_FIELD_FLAG_DYNAMIC | SERIALIZER_FIELD_FLAG_FEATURE); + break; + case TYPE_INT: + case TYPE_UINT: + if (CheckFlags(INDI_ENTRY_FLAG_IS_BITWISE)) { + // Split for each bit and pass 0 or 1. + for (int j = 0; j < sizeof(int) * 8; ++j) { + int _value = (values[i].value.vint & (1 << j)) != 0; + _s.Pass(THIS_REF, StringFormat("%d@%d", i, j), _value, SERIALIZER_FIELD_FLAG_FEATURE); + } + } else { + _s.Pass(THIS_REF, (string)i, values[i].value.vint, + SERIALIZER_FIELD_FLAG_DYNAMIC | SERIALIZER_FIELD_FLAG_FEATURE); + } + break; + case TYPE_LONG: + case TYPE_ULONG: + if (CheckFlags(INDI_ENTRY_FLAG_IS_BITWISE)) { + // Split for each bit and pass 0 or 1. + /* @fixme: j, j already defined. + for (int j = 0; j < sizeof(int) * 8; ++j) { + int _value = (values[i].vlong & (1 << j)) != 0; + _s.Pass(THIS_REF, StringFormat("%d@%d", i, j), _value, SERIALIZER_FIELD_FLAG_FEATURE); + } + */ + SetUserError(ERR_INVALID_PARAMETER); + } else { + _s.Pass(THIS_REF, (string)i, values[i].value.vlong, + SERIALIZER_FIELD_FLAG_DYNAMIC | SERIALIZER_FIELD_FLAG_FEATURE); + } + break; + default: + SetUserError(ERR_INVALID_PARAMETER); + break; + } + } + return SerializerNodeObject; +} + +/* Method to serialize IndicatorDataEntry's IndicatorDataEntryValue union. */ +SerializerNodeType IndicatorDataEntryValue::Serialize(Serializer &_s) { + _s.Pass(THIS_REF, "flags", flags); + _s.Pass(THIS_REF, "vdbl", value.vdbl); + _s.Pass(THIS_REF, "vflt", value.vflt); + _s.Pass(THIS_REF, "vint", value.vint); + _s.Pass(THIS_REF, "vlong", value.vlong); + return SerializerNodeObject; +}; diff --git a/Indicator.struct.signal.h b/IndicatorData.struct.signal.h similarity index 94% rename from Indicator.struct.signal.h rename to IndicatorData.struct.signal.h index 954e02172..d865e4129 100644 --- a/Indicator.struct.signal.h +++ b/IndicatorData.struct.signal.h @@ -33,10 +33,12 @@ // Forward declaration. struct ChartParams; struct IndicatorDataEntry; +struct IndicatorDataParams; struct IndicatorParams; // Includes. -#include "Indicator.struct.h" +//#include "IndicatorData.enum.h" +//#include "Indicator.struct.h" /* Structure for indicator signals. */ struct IndicatorSignal { @@ -56,14 +58,14 @@ struct IndicatorSignal { // Constructors. IndicatorSignal(int _signals = 0) : signals(_signals) {} - IndicatorSignal(ARRAY_REF(IndicatorDataEntry, _data), IndicatorParams &_ip, ChartParams &_cp, int _m1 = 0, + IndicatorSignal(ARRAY_REF(IndicatorDataEntry, _data), IndicatorDataParams &_idp, ChartParams &_cp, int _m1 = 0, int _m2 = 0) : signals(0) { - CalcSignals(_data, _ip, _cp, _m1, _m2); + CalcSignals(_data, _idp, _cp, _m1, _m2); } // Main methods. // Calculate signal values. - void CalcSignals(ARRAY_REF(IndicatorDataEntry, _data), IndicatorParams &_ip, ChartParams &_cp, int _m1 = 0, + void CalcSignals(ARRAY_REF(IndicatorDataEntry, _data), IndicatorDataParams &_idp, ChartParams &_cp, int _m1 = 0, int _m2 = 0) { int _size = ArraySize(_data); // INDICATOR_SIGNAL_CROSSOVER @@ -88,7 +90,7 @@ struct IndicatorSignal { ((_price_w0 - _price_w1) < 0 && (_data[0][_m1] - _data[_size - 1][_m1]) > 0)); // INDICATOR_SIGNAL_GT_PRICE bool _v_gt_p = false; - if (_ip.GetIDataValueRange() == IDATA_RANGE_PRICE) { + if (_idp.Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDVRANGE)) == IDATA_RANGE_PRICE) { _v_gt_p = _data[0][_m1] > _price_w0 || _data[0][_m2] > _price_w0; } else { // @todo diff --git a/Indicators/Bitwise/Indi_Candle.mqh b/Indicators/Bitwise/Indi_Candle.mqh index 3171251f7..7e4a4f5d3 100644 --- a/Indicators/Bitwise/Indi_Candle.mqh +++ b/Indicators/Bitwise/Indi_Candle.mqh @@ -32,9 +32,7 @@ // Structs. struct CandleParams : IndicatorParams { // Struct constructor. - CandleParams(int _shift = 0, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) : IndicatorParams(INDI_CANDLE, 1, TYPE_INT) { - SetDataValueRange(IDATA_RANGE_RANGE); - SetDataSourceType(IDATA_BUILTIN); + CandleParams(int _shift = 0, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) : IndicatorParams(INDI_CANDLE) { shift = _shift; tf = _tf; }; @@ -52,7 +50,11 @@ class Indi_Candle : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_Candle(CandleParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_Candle(CandleParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(1, TYPE_INT, _idstype, IDATA_RANGE_RANGE, _indi_src_mode), + _indi_src){}; Indi_Candle(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_CANDLE, _tf, _shift){}; @@ -72,7 +74,7 @@ class Indi_Candle : public IndicatorTickOrCandleSource { int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); BarOHLC _ohlcs[1]; - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: // In this mode, price is fetched from chart. _ohlcs[0] = Chart::GetOHLC(_ishift); diff --git a/Indicators/Bitwise/Indi_Pattern.mqh b/Indicators/Bitwise/Indi_Pattern.mqh index dc5bdc958..cc223770c 100644 --- a/Indicators/Bitwise/Indi_Pattern.mqh +++ b/Indicators/Bitwise/Indi_Pattern.mqh @@ -32,11 +32,7 @@ // Structs. struct IndiPatternParams : IndicatorParams { // Struct constructor. - IndiPatternParams(int _shift = 0) : IndicatorParams(INDI_PATTERN, 5, TYPE_UINT) { - SetDataValueType(TYPE_UINT); - SetDataValueRange(IDATA_RANGE_BITWISE); - shift = _shift; - }; + IndiPatternParams(int _shift = 0) : IndicatorParams(INDI_PATTERN) { shift = _shift; }; IndiPatternParams(IndiPatternParams& _params, ENUM_TIMEFRAMES _tf) { THIS_REF = _params; tf = _tf; @@ -51,7 +47,11 @@ class Indi_Pattern : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_Pattern(IndiPatternParams& _p, IndicatorBase* _indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_Pattern(IndiPatternParams& _p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData* _indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(5, TYPE_UINT, _idstype, IDATA_RANGE_BITWISE, _indi_src_mode), + _indi_src){}; Indi_Pattern(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_PATTERN, _tf, _shift){}; @@ -61,12 +61,13 @@ class Indi_Pattern : public IndicatorTickOrCandleSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { int i; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); + int _max_modes = Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES)); BarOHLC _ohlcs[8]; - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: // In this mode, price is fetched from chart. - for (i = 0; i < iparams.GetMaxModes(); ++i) { + for (i = 0; i < _max_modes; ++i) { _ohlcs[i] = Chart::GetOHLC(_ishift + i); if (!_ohlcs[i].IsValid()) { // Return empty entry on invalid candles. @@ -91,7 +92,7 @@ class Indi_Pattern : public IndicatorTickOrCandleSource { return WRONG_VALUE; } - for (i = 0; i < iparams.GetMaxModes(); ++i) { + for (i = 0; i < _max_modes; ++i) { _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); diff --git a/Indicators/Indi_AC.mqh b/Indicators/Indi_AC.mqh index 1ce0404d3..2d9e905f8 100644 --- a/Indicators/Indi_AC.mqh +++ b/Indicators/Indi_AC.mqh @@ -35,15 +35,9 @@ double iAC(string _symbol, int _tf, int _shift) { // Structs. struct IndiACParams : IndicatorParams { // Struct constructor. - IndiACParams(int _shift = 0) : IndicatorParams(INDI_AC, 1, TYPE_DOUBLE) { - SetDataValueRange(IDATA_RANGE_MIXED); + IndiACParams(int _shift = 0) : IndicatorParams(INDI_AC) { SetCustomIndicatorName("Examples\\Accelerator"); shift = _shift; - switch (idstype) { - case IDATA_ICUSTOM: - SetMaxModes(2); - break; - } }; IndiACParams(IndiACParams &_params, ENUM_TIMEFRAMES _tf) { THIS_REF = _params; @@ -55,12 +49,34 @@ struct IndiACParams : IndicatorParams { * Implements the Bill Williams' Accelerator/Decelerator oscillator. */ class Indi_AC : public IndicatorTickOrCandleSource { + protected: + /* Protected methods */ + + /** + * Initialize. + */ + void Init() { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { + case IDATA_ICUSTOM: + Set(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES), 2); + break; + } + } + public: /** * Class constructor. */ - 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){}; + Indi_AC(IndiACParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_MIXED, _indi_src_mode), + _indi_src) { + Init(); + }; + Indi_AC(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_AC, _tf, _shift) { + Init(); + }; /** * Returns the indicator value. @@ -70,11 +86,12 @@ class Indi_AC : public IndicatorTickOrCandleSource { * - https://www.mql5.com/en/docs/indicators/iac */ static double iAC(string _symbol = NULL, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0, - IndicatorBase *_obj = NULL) { + IndicatorData *_obj = NULL) { #ifdef __MQL4__ return ::iAC(_symbol, _tf, _shift); #else // __MQL5__ - int _handle = Object::IsValid(_obj) ? _obj.Get(IndicatorState::INDICATOR_STATE_PROP_HANDLE) : NULL; + int _handle = + Object::IsValid(_obj) ? _obj.Get(STRUCT_ENUM(IndicatorState, INDICATOR_STATE_PROP_HANDLE)) : NULL; double _res[]; if (_handle == NULL || _handle == INVALID_HANDLE) { if ((_handle = ::iAC(_symbol, _tf)) == INVALID_HANDLE) { @@ -108,7 +125,7 @@ class Indi_AC : public IndicatorTickOrCandleSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { IndicatorDataEntryValue _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_AC::iAC(GetSymbol(), GetTf(), _ishift, THIS_PTR); break; diff --git a/Indicators/Indi_AD.mqh b/Indicators/Indi_AD.mqh index 172eed9f5..279f380c4 100644 --- a/Indicators/Indi_AD.mqh +++ b/Indicators/Indi_AD.mqh @@ -34,8 +34,7 @@ double iAD(string _symbol, int _tf, int _shift) { // Structs. struct IndiADParams : IndicatorParams { // Struct constructor. - IndiADParams(int _shift = 0) : IndicatorParams(INDI_AD, 1, TYPE_DOUBLE) { - SetDataValueRange(IDATA_RANGE_MIXED); + IndiADParams(int _shift = 0) : IndicatorParams(INDI_AD) { SetCustomIndicatorName("Examples\\AD"); shift = _shift; }; @@ -53,7 +52,12 @@ class Indi_AD : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_AD(IndiADParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_AD(IndiADParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource(_p, + IndicatorDataParams::GetInstance(FINAL_INDI_ADX_LINE_ENTRY, TYPE_DOUBLE, _idstype, + IDATA_RANGE_MIXED, _indi_src_mode), + _indi_src){}; Indi_AD(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_AD, _tf, _shift) { iparams.SetTf(_tf); }; @@ -66,7 +70,7 @@ class Indi_AD : public IndicatorTickOrCandleSource { * - https://www.mql5.com/en/docs/indicators/iad */ static double iAD(string _symbol = NULL, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0, - IndicatorBase *_obj = NULL) { + IndicatorData *_obj = NULL) { #ifdef __MQL4__ return ::iAD(_symbol, _tf, _shift); #else // __MQL5__ @@ -104,7 +108,7 @@ class Indi_AD : public IndicatorTickOrCandleSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_AD::iAD(GetSymbol(), GetTf(), _ishift, THIS_PTR); break; diff --git a/Indicators/Indi_ADX.mqh b/Indicators/Indi_ADX.mqh index 1a3883d14..527749bc7 100644 --- a/Indicators/Indi_ADX.mqh +++ b/Indicators/Indi_ADX.mqh @@ -39,17 +39,11 @@ struct IndiADXParams : IndicatorParams { ENUM_APPLIED_PRICE applied_price; // Struct constructors. IndiADXParams(unsigned int _period = 14, ENUM_APPLIED_PRICE _ap = PRICE_TYPICAL, int _shift = 0, - ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN) - : period(_period), applied_price(_ap), IndicatorParams(INDI_ADX, FINAL_INDI_ADX_LINE_ENTRY, TYPE_DOUBLE) { - SetDataSourceType(_idstype); - SetDataValueRange(IDATA_RANGE_RANGE); + ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) + : period(_period), applied_price(_ap), IndicatorParams(INDI_ADX) { SetShift(_shift); - switch (idstype) { - case IDATA_ICUSTOM: - if (custom_indi_name == "") { - SetCustomIndicatorName("Examples\\ADX"); - } - break; + if (custom_indi_name == "") { + SetCustomIndicatorName("Examples\\ADX"); } }; IndiADXParams(IndiADXParams &_params, ENUM_TIMEFRAMES _tf) { @@ -62,12 +56,26 @@ struct IndiADXParams : IndicatorParams { * Implements the Average Directional Movement Index indicator. */ class Indi_ADX : public IndicatorTickOrCandleSource { + protected: + /* Protected methods */ + + void Init() {} + public: /** * Class constructor. */ - 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) {} + Indi_ADX(IndiADXParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource(_p, + IndicatorDataParams::GetInstance(FINAL_INDI_ADX_LINE_ENTRY, TYPE_DOUBLE, _idstype, + IDATA_RANGE_RANGE, _indi_src_mode), + _indi_src) { + Init(); + } + Indi_ADX(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_ADX, _tf, _shift) { + Init(); + } /** * Returns the indicator value. @@ -80,7 +88,7 @@ class Indi_ADX : public IndicatorTickOrCandleSource { ENUM_APPLIED_PRICE _applied_price, // (MT5): not used int _mode = LINE_MAIN_ADX, // (MT4/MT5): 0 - MODE_MAIN/MAIN_LINE, 1 - // MODE_PLUSDI/PLUSDI_LINE, 2 - MODE_MINUSDI/MINUSDI_LINE - int _shift = 0, IndicatorBase *_obj = NULL) { + int _shift = 0, IndicatorData *_obj = NULL) { #ifdef __MQL4__ return ::iADX(_symbol, _tf, _period, _applied_price, _mode, _shift); #else // __MQL5__ @@ -118,7 +126,7 @@ class Indi_ADX : public IndicatorTickOrCandleSource { 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) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_ADX::iADX(GetSymbol(), GetTf(), GetPeriod(), GetAppliedPrice(), _mode, _ishift, THIS_PTR); break; diff --git a/Indicators/Indi_ADXW.mqh b/Indicators/Indi_ADXW.mqh index b5b11d152..74f1c1f89 100644 --- a/Indicators/Indi_ADXW.mqh +++ b/Indicators/Indi_ADXW.mqh @@ -37,13 +37,11 @@ struct IndiADXWParams : IndiADXParams { // Struct constructor. IndiADXWParams(int _period = 14, ENUM_APPLIED_PRICE _ap = PRICE_TYPICAL, int _shift = 0, - ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN) - : IndiADXParams(_period, _ap, _shift, _tf, _idstype) { + ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) + : IndiADXParams(_period, _ap, _shift, _tf) { itype = itype == INDI_NONE || itype == INDI_ADX ? INDI_ADXW : itype; - switch (idstype) { - case IDATA_ICUSTOM: - SetCustomIndicatorName("Examples\\ADXW"); - break; + if (custom_indi_name == "") { + SetCustomIndicatorName("Examples\\ADXW"); } }; IndiADXWParams(IndiADXWParams &_params, ENUM_TIMEFRAMES _tf) { @@ -60,7 +58,12 @@ class Indi_ADXW : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_ADXW(IndiADXWParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_ADXW(IndiADXWParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource(_p, + IndicatorDataParams::GetInstance(FINAL_INDI_ADX_LINE_ENTRY, TYPE_DOUBLE, _idstype, + IDATA_RANGE_RANGE, _indi_src_mode), + _indi_src){}; Indi_ADXW(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_ADXW, _tf, _shift){}; @@ -68,7 +71,7 @@ class Indi_ADXW : public IndicatorTickOrCandleSource { * Built-in version of ADX Wilder. */ static double iADXWilder(string _symbol, ENUM_TIMEFRAMES _tf, int _ma_period, int _mode = LINE_MAIN_ADX, - int _shift = 0, IndicatorBase *_obj = NULL) { + int _shift = 0, IndicatorData *_obj = NULL) { #ifdef __MQL5__ INDICATOR_BUILTIN_CALL_AND_RETURN(::iADXWilder(_symbol, _tf, _ma_period), _mode, _shift); #else @@ -106,8 +109,8 @@ class Indi_ADXW : public IndicatorTickOrCandleSource { /** * 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) { + static double iADXWilderOnIndicator(IndicatorData *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _period, + int _mode = 0, int _shift = 0, IndicatorData *_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); @@ -229,7 +232,7 @@ class Indi_ADXW : public IndicatorTickOrCandleSource { 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) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_ADXW::iADXWilder(GetSymbol(), GetTf(), GetPeriod(), _mode, _ishift, THIS_PTR); break; diff --git a/Indicators/Indi_AMA.mqh b/Indicators/Indi_AMA.mqh index e72de2fdc..fa0428199 100644 --- a/Indicators/Indi_AMA.mqh +++ b/Indicators/Indi_AMA.mqh @@ -43,16 +43,10 @@ struct IndiAMAParams : IndicatorParams { slow_period(_slow_period), 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: - if (custom_indi_name == "") { - SetCustomIndicatorName("Examples\\AMA"); - } - break; + if (custom_indi_name == "") { + SetCustomIndicatorName("Examples\\AMA"); } }; IndiAMAParams(IndiAMAParams &_params, ENUM_TIMEFRAMES _tf) { @@ -69,8 +63,11 @@ class Indi_AMA : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_AMA(IndiAMAParams &_p, IndicatorBase *_indi_src = NULL, int _indi_mode = 0) - : IndicatorTickOrCandleSource(_p, _indi_src, _indi_mode) { + Indi_AMA(IndiAMAParams &_p, int _indi_mode = 0, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, + IndicatorData *_indi_src = NULL, int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_PRICE, _indi_src_mode), + _indi_src, _indi_mode) { iparams.SetIndicatorType(INDI_AMA); }; Indi_AMA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_AMA, _tf, _shift){}; @@ -80,7 +77,7 @@ class Indi_AMA : public IndicatorTickOrCandleSource { */ static double iAMA(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) { + IndicatorData *_obj = NULL) { #ifdef __MQL5__ INDICATOR_BUILTIN_CALL_AND_RETURN( ::iAMA(_symbol, _tf, _ama_period, _fast_ema_period, _slow_ema_period, _ama_shift, _ap), _mode, _shift); @@ -118,9 +115,9 @@ class Indi_AMA : public IndicatorTickOrCandleSource { /** * On-indicator version of AMA. */ - static double iAMAOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _ama_period, + static double iAMAOnIndicator(IndicatorData *_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) { + int _mode = 0, int _shift = 0, IndicatorData *_obj = NULL) { 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, @@ -177,9 +174,12 @@ class Indi_AMA : public IndicatorTickOrCandleSource { CalculateInit(InpPeriodAMA, InpFastPeriodEMA, InpSlowPeriodEMA, InpShiftAMA, ExtFastSC, ExtSlowSC, ExtPeriodAMA, ExtSlowPeriodEMA, ExtFastPeriodEMA); +#ifdef __debug__ 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)); + Print("price[", x, "] = ", price[x].Get(), + ", O = ", iOpen(Symbol(), PERIOD_CURRENT, Bars(Symbol(), PERIOD_CURRENT) - x - 1)); } +#endif int i; // Check for rates count. @@ -225,7 +225,7 @@ class Indi_AMA : public IndicatorTickOrCandleSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_AMA::iAMA(GetSymbol(), GetTf(), /*[*/ GetPeriod(), GetFastPeriod(), GetSlowPeriod(), GetAMAShift(), GetAppliedPrice() /*]*/, _mode, _ishift, THIS_PTR); @@ -258,7 +258,7 @@ class Indi_AMA : public IndicatorTickOrCandleSource { * 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()); } + virtual IndicatorData *OnDataSourceRequest() { return DataSourceRequestReturnDefault(GetAppliedPrice()); } /* Getters */ diff --git a/Indicators/Indi_AO.mqh b/Indicators/Indi_AO.mqh index 91b8e457c..783e48562 100644 --- a/Indicators/Indi_AO.mqh +++ b/Indicators/Indi_AO.mqh @@ -34,11 +34,7 @@ double iAO(string _symbol, int _tf, int _shift) { // Structs. struct IndiAOParams : IndicatorParams { // Struct constructor. - IndiAOParams(int _shift = 0) : IndicatorParams(INDI_AO, 2, TYPE_DOUBLE) { -#ifdef __MQL4__ - max_modes = 1; -#endif - SetDataValueRange(IDATA_RANGE_MIXED); + IndiAOParams(int _shift = 0) : IndicatorParams(INDI_AO) { SetCustomIndicatorName("Examples\\Awesome_Oscillator"); shift = _shift; }; @@ -52,12 +48,34 @@ struct IndiAOParams : IndicatorParams { * Implements the Awesome oscillator. */ class Indi_AO : public IndicatorTickOrCandleSource { + protected: + /* Protected methods */ + + /** + * Initialize. + */ + void Init() { +#ifdef __MQL4__ + Set(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES), 1); +#else + Set(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES), 2); +#endif + } + public: /** * Class constructor. */ - 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){}; + Indi_AO(IndiAOParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(2, TYPE_DOUBLE, _idstype, IDATA_RANGE_MIXED, _indi_src_mode), + _indi_src) { + Init(); + }; + Indi_AO(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_AO, _tf, _shift) { + Init(); + }; /** * Returns the indicator value. @@ -67,7 +85,7 @@ class Indi_AO : public IndicatorTickOrCandleSource { * - https://www.mql5.com/en/docs/indicators/iao */ static double iAO(string _symbol = NULL, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0, int _mode = 0, - IndicatorBase *_obj = NULL) { + IndicatorData *_obj = NULL) { #ifdef __MQL4__ // Note: In MQL4 _mode is not supported. return ::iAO(_symbol, _tf, _shift); @@ -106,7 +124,7 @@ class Indi_AO : public IndicatorTickOrCandleSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_AO::iAO(GetSymbol(), GetTf(), _ishift, _mode, THIS_PTR); break; diff --git a/Indicators/Indi_ASI.mqh b/Indicators/Indi_ASI.mqh index cccfc3a2a..d520cfb5d 100644 --- a/Indicators/Indi_ASI.mqh +++ b/Indicators/Indi_ASI.mqh @@ -30,9 +30,7 @@ struct IndiASIParams : IndicatorParams { unsigned int period; double mpc; // Struct constructor. - IndiASIParams(double _mpc = 300.0, int _shift = 0) - : IndicatorParams(INDI_ASI, 1, TYPE_DOUBLE, PERIOD_CURRENT, IDATA_ONCALCULATE) { - SetDataValueRange(IDATA_RANGE_MIXED); + IndiASIParams(double _mpc = 300.0, int _shift = 0) : IndicatorParams(INDI_ASI, PERIOD_CURRENT) { SetCustomIndicatorName("Examples\\ASI"); mpc = _mpc; shift = _shift; @@ -47,18 +45,38 @@ struct IndiASIParams : IndicatorParams { * Implements the Bill Williams' Accelerator/Decelerator oscillator. */ class Indi_ASI : public IndicatorTickOrCandleSource { + protected: + /* Protected methods */ + + /** + * Initialize. + */ + void Init() { + if (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE)) == IDATA_BUILTIN) { + Set(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE), IDATA_ONCALCULATE); + } + } + public: /** * Class constructor. */ - 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){}; + Indi_ASI(IndiASIParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_ONCALCULATE, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_MIXED, _indi_src_mode), + _indi_src) { + Init(); + }; + Indi_ASI(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_ASI, _tf, _shift) { + Init(); + }; /** * Built-in version of ASI. */ static double iASI(string _symbol, ENUM_TIMEFRAMES _tf, double _mpc, int _mode = 0, int _shift = 0, - IndicatorBase *_obj = NULL) { + IndicatorData *_obj = NULL) { INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG(_symbol, _tf, Util::MakeKey("Indi_ASI", _mpc)); return iASIOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _mpc, _mode, _shift, _cache); } @@ -87,8 +105,8 @@ class Indi_ASI : public IndicatorTickOrCandleSource { /** * 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) { + static double iASIOnIndicator(IndicatorData *_indi, string _symbol, ENUM_TIMEFRAMES _tf, double _mpc, int _mode = 0, + int _shift = 0, IndicatorData *_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); @@ -168,7 +186,7 @@ class Indi_ASI : public IndicatorTickOrCandleSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetMaximumPriceChanging() /*]*/, 0, _ishift); diff --git a/Indicators/Indi_ATR.mqh b/Indicators/Indi_ATR.mqh index 6ddcbd8bc..37641e945 100644 --- a/Indicators/Indi_ATR.mqh +++ b/Indicators/Indi_ATR.mqh @@ -35,10 +35,8 @@ double iATR(string _symbol, int _tf, int _period, int _shift) { struct IndiATRParams : IndicatorParams { unsigned int period; // Struct constructors. - IndiATRParams(unsigned int _period = 14, int _shift = 0) - : period(_period), IndicatorParams(INDI_ATR, 1, TYPE_DOUBLE) { + IndiATRParams(unsigned int _period = 14, int _shift = 0) : period(_period), IndicatorParams(INDI_ATR) { shift = _shift; - SetDataValueRange(IDATA_RANGE_MIXED); SetCustomIndicatorName("Examples\\ATR"); }; IndiATRParams(IndiATRParams &_params, ENUM_TIMEFRAMES _tf) { @@ -57,7 +55,11 @@ class Indi_ATR : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_ATR(IndiATRParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_ATR(IndiATRParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_MIXED, _indi_src_mode), + _indi_src) {} Indi_ATR(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_ATR, _tf, _shift){}; /** @@ -68,7 +70,7 @@ class Indi_ATR : public IndicatorTickOrCandleSource { * - https://www.mql5.com/en/docs/indicators/iatr */ static double iATR(string _symbol, ENUM_TIMEFRAMES _tf, unsigned int _period, int _shift = 0, - IndicatorBase *_obj = NULL) { + IndicatorData *_obj = NULL) { #ifdef __MQL4__ return ::iATR(_symbol, _tf, _period, _shift); #else // __MQL5__ @@ -106,7 +108,7 @@ class Indi_ATR : public IndicatorTickOrCandleSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_ATR::iATR(GetSymbol(), GetTf(), GetPeriod(), _ishift, THIS_PTR); break; diff --git a/Indicators/Indi_Alligator.mqh b/Indicators/Indi_Alligator.mqh index af6799596..c2f1b7532 100644 --- a/Indicators/Indi_Alligator.mqh +++ b/Indicators/Indi_Alligator.mqh @@ -81,9 +81,8 @@ struct IndiAlligatorParams : IndicatorParams { lips_shift(_ls), ma_method(_mm), applied_price(_ap), - IndicatorParams(INDI_ALLIGATOR, FINAL_ALLIGATOR_LINE_ENTRY, TYPE_DOUBLE) { + IndicatorParams(INDI_ALLIGATOR) { shift = _shift; - SetDataValueRange(IDATA_RANGE_PRICE); SetCustomIndicatorName("Examples\\Alligator"); }; IndiAlligatorParams(IndiAlligatorParams &_params, ENUM_TIMEFRAMES _tf) { @@ -100,8 +99,11 @@ class Indi_Alligator : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_Alligator(IndiAlligatorParams &_p, IndicatorBase *_indi_src = NULL) - : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_Alligator(IndiAlligatorParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, + IndicatorData *_indi_src = NULL, int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(FINAL_ALLIGATOR_LINE_ENTRY, TYPE_DOUBLE, _idstype, IDATA_RANGE_PRICE), + _indi_src, _indi_src_mode) {} Indi_Alligator(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_ADX, _tf, _shift){}; @@ -126,7 +128,7 @@ class Indi_Alligator : public IndicatorTickOrCandleSource { static double iAlligator(string _symbol, ENUM_TIMEFRAMES _tf, int _jaw_period, int _jaw_shift, int _teeth_period, int _teeth_shift, int _lips_period, int _lips_shift, ENUM_MA_METHOD _ma_method, ENUM_APPLIED_PRICE _applied_price, ENUM_ALLIGATOR_LINE _mode, int _shift = 0, - IndicatorBase *_obj = NULL) { + IndicatorData *_obj = NULL) { #ifdef __MQL4__ return ::iAlligator(_symbol, _tf, _jaw_period, _jaw_shift, _teeth_period, _teeth_shift, _lips_period, _lips_shift, _ma_method, _applied_price, _mode, _shift); @@ -172,7 +174,7 @@ class Indi_Alligator : public IndicatorTickOrCandleSource { return GetEntryValue((ENUM_ALLIGATOR_LINE)1, _ishift); } #endif - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_Alligator::iAlligator(GetSymbol(), GetTf(), GetJawPeriod(), GetJawShift(), GetTeethPeriod(), GetTeethShift(), GetLipsPeriod(), GetLipsShift(), GetMAMethod(), diff --git a/Indicators/Indi_AppliedPrice.mqh b/Indicators/Indi_AppliedPrice.mqh index 28d43b785..82a8399a9 100644 --- a/Indicators/Indi_AppliedPrice.mqh +++ b/Indicators/Indi_AppliedPrice.mqh @@ -30,9 +30,7 @@ struct IndiAppliedPriceParams : IndicatorParams { ENUM_APPLIED_PRICE applied_price; // Struct constructor. IndiAppliedPriceParams(ENUM_APPLIED_PRICE _applied_price = PRICE_OPEN, int _shift = 0) - : applied_price(_applied_price), IndicatorParams(INDI_APPLIED_PRICE, 1, TYPE_DOUBLE) { - SetDataSourceType(IDATA_INDICATOR); - SetDataValueRange(IDATA_RANGE_PRICE); + : applied_price(_applied_price), IndicatorParams(INDI_APPLIED_PRICE) { shift = _shift; }; IndiAppliedPriceParams(IndiAppliedPriceParams &_params, ENUM_TIMEFRAMES _tf) { @@ -57,8 +55,11 @@ class Indi_AppliedPrice : public IndicatorTickOrCandleSource= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_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()); + Set(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_SRC_MODE), GetAppliedPrice()); _value = Indi_AppliedPrice::iAppliedPriceOnIndicator(GetDataSource(), GetAppliedPrice(), _ishift); } break; @@ -102,7 +103,7 @@ class Indi_AppliedPrice : public IndicatorTickOrCandleSource::IsValidEntry(_entry); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_INDICATOR: if (!HasDataSource()) { GetLogger().Error("Indi_AppliedPrice requires source indicator to be set via SetDataSource()!"); diff --git a/Indicators/Indi_BWMFI.mqh b/Indicators/Indi_BWMFI.mqh index 963490f84..a0c71f4f7 100644 --- a/Indicators/Indi_BWMFI.mqh +++ b/Indicators/Indi_BWMFI.mqh @@ -48,8 +48,7 @@ enum ENUM_MFI_COLOR { struct IndiBWIndiMFIParams : IndicatorParams { ENUM_APPLIED_VOLUME ap; // @todo // Struct constructors. - IndiBWIndiMFIParams(int _shift = 0) : IndicatorParams(INDI_BWMFI, FINAL_BWMFI_BUFFER_ENTRY, TYPE_DOUBLE) { - SetDataValueRange(IDATA_RANGE_MIXED); + IndiBWIndiMFIParams(int _shift = 0) : IndicatorParams(INDI_BWMFI) { shift = _shift; SetCustomIndicatorName("Examples\\MarketFacilitationIndex"); }; @@ -63,13 +62,30 @@ struct IndiBWIndiMFIParams : IndicatorParams { * Implements the Market Facilitation Index by Bill Williams indicator. */ class Indi_BWMFI : public IndicatorTickOrCandleSource { + protected: + /* Protected methods */ + + /** + * Initialize. + */ + void Init() { Set(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES), FINAL_BWMFI_BUFFER_ENTRY); } + public: /** * Class constructor. */ - Indi_BWMFI(IndiBWIndiMFIParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_BWMFI(IndiBWIndiMFIParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource(_p, + IndicatorDataParams::GetInstance(FINAL_BWMFI_BUFFER_ENTRY, TYPE_DOUBLE, _idstype, + IDATA_RANGE_MIXED, _indi_src_mode), + _indi_src) { + Init(); + } Indi_BWMFI(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) - : IndicatorTickOrCandleSource(INDI_BWMFI, _tf, _shift) {} + : IndicatorTickOrCandleSource(INDI_BWMFI, _tf, _shift) { + Init(); + } /** * Returns the indicator value. @@ -79,7 +95,7 @@ class Indi_BWMFI : public IndicatorTickOrCandleSource { * - https://www.mql5.com/en/docs/indicators/ibwmfi */ static double iBWMFI(string _symbol = NULL, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0, - ENUM_BWMFI_BUFFER _mode = BWMFI_BUFFER, IndicatorBase *_obj = NULL) { + ENUM_BWMFI_BUFFER _mode = BWMFI_BUFFER, IndicatorData *_obj = NULL) { #ifdef __MQL4__ return ::iBWMFI(_symbol, _tf, _shift); #else // __MQL5__ @@ -119,7 +135,7 @@ class Indi_BWMFI : public IndicatorTickOrCandleSource { double _value = EMPTY_VALUE; - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_BWMFI::iBWMFI(GetSymbol(), GetTf(), _ishift, (ENUM_BWMFI_BUFFER)_mode, THIS_PTR); break; diff --git a/Indicators/Indi_BWZT.mqh b/Indicators/Indi_BWZT.mqh index 5699beba3..34a3f0df9 100644 --- a/Indicators/Indi_BWZT.mqh +++ b/Indicators/Indi_BWZT.mqh @@ -40,16 +40,15 @@ enum ENUM_INDI_BWZT_MODE { // Structs. struct IndiBWZTParams : IndicatorParams { - Ref indi_ac; - Ref indi_ao; + Ref indi_ac; + Ref 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) { + IndiBWZTParams(int _shift = 0) : IndicatorParams(INDI_BWZT) { indi_ac = NULL; indi_ao = NULL; - SetDataValueRange(IDATA_RANGE_MIXED); SetCustomIndicatorName("Examples\\BW-ZoneTrade"); shift = _shift; }; @@ -63,18 +62,35 @@ struct IndiBWZTParams : IndicatorParams { * Implements the Bill Williams' Zone Trade. */ class Indi_BWZT : public IndicatorTickOrCandleSource { + protected: + /* Protected methods */ + + /** + * Initialize. + */ + void Init() { Set(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES), FINAL_INDI_BWZT_MODE_ENTRY); } + public: /** * Class constructor. */ - Indi_BWZT(IndiBWZTParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_BWZT(IndiBWZTParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource(_p, + IndicatorDataParams::GetInstance(FINAL_INDI_BWZT_MODE_ENTRY, TYPE_DOUBLE, _idstype, + IDATA_RANGE_MIXED, _indi_src_mode), + _indi_src) { + Init(); + }; Indi_BWZT(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) - : IndicatorTickOrCandleSource(INDI_BWZT, _tf, _shift){}; + : IndicatorTickOrCandleSource(INDI_BWZT, _tf, _shift) { + Init(); + }; /** * Built-in version of BWZT. */ - static double iBWZT(string _symbol, ENUM_TIMEFRAMES _tf, int _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) { + static double iBWZT(string _symbol, ENUM_TIMEFRAMES _tf, int _mode = 0, int _shift = 0, IndicatorData *_obj = NULL) { INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG(_symbol, _tf, "Indi_BWZT"); Indi_AC *_indi_ac = Indi_AC::GetCached(_symbol, _tf); @@ -110,8 +126,8 @@ class Indi_BWZT : public IndicatorTickOrCandleSource { /** * On-indicator version of BWZT. */ - static double iBWZTOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _mode, int _shift, - IndicatorBase *_obj) { + static double iBWZTOnIndicator(IndicatorData *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _mode, int _shift, + IndicatorData *_obj) { INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS(_indi, _symbol, _tf, Util::MakeKey("Indi_BWZT_ON_" + _indi.GetFullName())); @@ -124,7 +140,7 @@ class Indi_BWZT : public IndicatorTickOrCandleSource { /** * Provides built-in indicators whose can be used as data source. */ - virtual IndicatorBase *FetchDataSource(ENUM_INDICATOR_TYPE _id) override { + virtual IndicatorData *FetchDataSource(ENUM_INDICATOR_TYPE _id) override { switch (_id) { case INDI_AC: return iparams.indi_ac.Ptr(); @@ -142,7 +158,7 @@ class Indi_BWZT : public IndicatorTickOrCandleSource { ValueStorage &ExtHBuffer, ValueStorage &ExtLBuffer, ValueStorage &ExtCBuffer, ValueStorage &ExtColorBuffer, ValueStorage &ExtAOBuffer, ValueStorage &ExtACBuffer, int DATA_LIMIT, - IndicatorBase *ExtACHandle, IndicatorBase *ExtAOHandle) { + IndicatorData *ExtACHandle, IndicatorData *ExtAOHandle) { if (rates_total < DATA_LIMIT) return (0); // Not all data may be calculated. int calculated = BarsCalculated(ExtACHandle); @@ -208,7 +224,7 @@ class Indi_BWZT : public IndicatorTickOrCandleSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_BWZT::iBWZT(GetSymbol(), GetTf(), _mode, _ishift, THIS_PTR); break; diff --git a/Indicators/Indi_Bands.mqh b/Indicators/Indi_Bands.mqh index 56b4099fb..440158315 100644 --- a/Indicators/Indi_Bands.mqh +++ b/Indicators/Indi_Bands.mqh @@ -68,13 +68,8 @@ struct IndiBandsParams : IndicatorParams { // Struct constructors. IndiBandsParams(unsigned int _period = 20, double _deviation = 2, int _bshift = 0, ENUM_APPLIED_PRICE _ap = PRICE_OPEN, int _shift = 0) - : period(_period), - deviation(_deviation), - bshift(_bshift), - applied_price(_ap), - IndicatorParams(INDI_BANDS, FINAL_BANDS_LINE_ENTRY, TYPE_DOUBLE) { + : period(_period), deviation(_deviation), bshift(_bshift), applied_price(_ap), IndicatorParams(INDI_BANDS) { shift = _shift; - SetDataValueRange(IDATA_RANGE_PRICE); SetCustomIndicatorName("Examples\\BB"); }; IndiBandsParams(IndiBandsParams &_params, ENUM_TIMEFRAMES _tf) { @@ -87,13 +82,29 @@ struct IndiBandsParams : IndicatorParams { * Implements the Bollinger Bands® indicator. */ class Indi_Bands : public IndicatorTickSource { + protected: + /* Protected methods */ + + /** + * Initialize. + */ + void Init() { Set(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES), FINAL_BANDS_LINE_ENTRY); } + public: /** * Class constructor. */ - Indi_Bands(IndiBandsParams &_p, IndicatorBase *_indi_src = NULL, int _mode = 0) - : IndicatorTickSource(_p, _indi_src, _mode) {} - Indi_Bands(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickSource(INDI_BANDS, _tf, _shift) {} + Indi_Bands(IndiBandsParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickSource(_p, + IndicatorDataParams::GetInstance(FINAL_BANDS_LINE_ENTRY, TYPE_DOUBLE, _idstype, + IDATA_RANGE_PRICE, _indi_src_mode), + _indi_src) { + Init(); + } + Indi_Bands(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickSource(INDI_BANDS, _tf, _shift) { + Init(); + } /** * Returns the indicator value. @@ -104,7 +115,7 @@ class Indi_Bands : public IndicatorTickSource { */ static double iBands(string _symbol, ENUM_TIMEFRAMES _tf, unsigned int _period, double _deviation, int _bands_shift, ENUM_APPLIED_PRICE _applied_price, ENUM_BANDS_LINE _mode = BAND_BASE, int _shift = 0, - IndicatorBase *_obj = NULL) { + IndicatorData *_obj = NULL) { #ifdef __MQL4__ return ::iBands(_symbol, _tf, _period, _deviation, _bands_shift, _applied_price, _mode, _shift); #else // __MQL5__ @@ -141,7 +152,7 @@ class Indi_Bands : public IndicatorTickSource { * * When _applied_price is set to -1, method will */ - static double iBandsOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, unsigned int _period, + static double iBandsOnIndicator(IndicatorData *_indi, string _symbol, ENUM_TIMEFRAMES _tf, unsigned int _period, double _deviation, int _bands_shift, ENUM_BANDS_LINE _mode, // (MT4/MT5): 0 - MODE_MAIN/BASE_LINE, 1 - // MODE_UPPER/UPPER_BAND, 2 - MODE_LOWER/LOWER_BAND @@ -156,7 +167,9 @@ class Indi_Bands : public IndicatorTickSource { int current_shift = _shift + (i - _bands_shift); // Getting current indicator value. _indi_value_buffer[i - _bands_shift] = - _indi[i - _bands_shift].values[_target != NULL ? _target.GetDataSourceMode() : 0].Get(); + _indi[i - _bands_shift] + .values[_target != NULL ? _target.Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_SRC_MODE)) : 0] + .Get(); } // Base band. @@ -242,7 +255,7 @@ class Indi_Bands : public IndicatorTickSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = BAND_BASE, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_Bands::iBands(GetSymbol(), GetTf(), GetPeriod(), GetDeviation(), GetBandsShift(), GetAppliedPrice(), (ENUM_BANDS_LINE)_mode, _ishift, THIS_PTR); @@ -271,7 +284,7 @@ class Indi_Bands : public IndicatorTickSource { /** * Provides built-in indicators whose can be used as data source. */ - virtual IndicatorBase *FetchDataSource(ENUM_INDICATOR_TYPE _id) { + virtual IndicatorData *FetchDataSource(ENUM_INDICATOR_TYPE _id) { if (_id == INDI_BANDS) { IndiBandsParams bands_params(); return new Indi_Bands(bands_params); @@ -295,7 +308,7 @@ class Indi_Bands : public IndicatorTickSource { return new Indi_StdDev(stddev_params); } - return IndicatorBase::FetchDataSource(_id); + return IndicatorData::FetchDataSource(_id); } /* Getters */ diff --git a/Indicators/Indi_BearsPower.mqh b/Indicators/Indi_BearsPower.mqh index 5ba1562a7..edaa5cdd6 100644 --- a/Indicators/Indi_BearsPower.mqh +++ b/Indicators/Indi_BearsPower.mqh @@ -37,9 +37,8 @@ struct IndiBearsPowerParams : IndicatorParams { ENUM_APPLIED_PRICE applied_price; // Struct constructors. IndiBearsPowerParams(unsigned int _period = 13, ENUM_APPLIED_PRICE _ap = PRICE_CLOSE, int _shift = 0) - : period(_period), applied_price(_ap), IndicatorParams(INDI_BEARS, 1, TYPE_DOUBLE) { + : period(_period), applied_price(_ap), IndicatorParams(INDI_BEARS) { shift = _shift; - SetDataValueRange(IDATA_RANGE_MIXED); SetCustomIndicatorName("Examples\\Bears"); }; IndiBearsPowerParams(IndiBearsPowerParams &_params, ENUM_TIMEFRAMES _tf) { @@ -56,8 +55,11 @@ class Indi_BearsPower : public IndicatorTickOrCandleSource /** * Class constructor. */ - Indi_BearsPower(IndiBearsPowerParams &_p, IndicatorBase *_indi_src = NULL) - : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_BearsPower(IndiBearsPowerParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, + IndicatorData *_indi_src = NULL, int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_MIXED, _indi_src_mode), + _indi_src) {} Indi_BearsPower(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_BEARS, _tf, _shift) {} @@ -70,7 +72,7 @@ class Indi_BearsPower : public IndicatorTickOrCandleSource */ static double iBearsPower(string _symbol, ENUM_TIMEFRAMES _tf, unsigned int _period, ENUM_APPLIED_PRICE _applied_price, // (MT5): not used - int _shift = 0, IndicatorBase *_obj = NULL) { + int _shift = 0, IndicatorData *_obj = NULL) { #ifdef __MQL4__ return ::iBearsPower(_symbol, _tf, _period, _applied_price, _shift); #else // __MQL5__ @@ -108,7 +110,7 @@ class Indi_BearsPower : public IndicatorTickOrCandleSource virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = _value = iBearsPower(GetSymbol(), GetTf(), GetPeriod(), GetAppliedPrice(), _ishift, THIS_PTR); break; diff --git a/Indicators/Indi_BullsPower.mqh b/Indicators/Indi_BullsPower.mqh index d1d0491fb..dfbc27119 100644 --- a/Indicators/Indi_BullsPower.mqh +++ b/Indicators/Indi_BullsPower.mqh @@ -37,9 +37,8 @@ struct IndiBullsPowerParams : IndicatorParams { ENUM_APPLIED_PRICE applied_price; // (MT5): not used // Struct constructor. IndiBullsPowerParams(unsigned int _period = 13, ENUM_APPLIED_PRICE _ap = PRICE_CLOSE, int _shift = 0) - : period(_period), applied_price(_ap), IndicatorParams(INDI_BULLS, 1, TYPE_DOUBLE) { + : period(_period), applied_price(_ap), IndicatorParams(INDI_BULLS) { shift = _shift; - SetDataValueRange(IDATA_RANGE_MIXED); SetCustomIndicatorName("Examples\\Bulls"); }; IndiBullsPowerParams(IndiBullsPowerParams &_params, ENUM_TIMEFRAMES _tf) { @@ -56,8 +55,11 @@ class Indi_BullsPower : public IndicatorTickOrCandleSource /** * Class constructor. */ - Indi_BullsPower(IndiBullsPowerParams &_p, IndicatorBase *_indi_src = NULL) - : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_BullsPower(IndiBullsPowerParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, + IndicatorData *_indi_src = NULL, int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_MIXED, _indi_src_mode), + _indi_src) {} Indi_BullsPower(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_BULLS, _tf, _shift) {} @@ -70,7 +72,7 @@ class Indi_BullsPower : public IndicatorTickOrCandleSource */ static double iBullsPower(string _symbol, ENUM_TIMEFRAMES _tf, unsigned int _period, ENUM_APPLIED_PRICE _applied_price, // (MT5): not used - int _shift = 0, IndicatorBase *_obj = NULL) { + int _shift = 0, IndicatorData *_obj = NULL) { #ifdef __MQL4__ return ::iBullsPower(_symbol, _tf, _period, _applied_price, _shift); #else // __MQL5__ @@ -108,7 +110,7 @@ class Indi_BullsPower : public IndicatorTickOrCandleSource virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = iBullsPower(GetSymbol(), GetTf(), GetPeriod(), GetAppliedPrice(), _ishift, THIS_PTR); break; diff --git a/Indicators/Indi_CCI.mqh b/Indicators/Indi_CCI.mqh index 43879b492..57775a615 100644 --- a/Indicators/Indi_CCI.mqh +++ b/Indicators/Indi_CCI.mqh @@ -44,9 +44,8 @@ struct IndiCCIParams : IndicatorParams { ENUM_APPLIED_PRICE applied_price; // Struct constructors. IndiCCIParams(unsigned int _period = 14, ENUM_APPLIED_PRICE _applied_price = PRICE_OPEN, int _shift = 0) - : period(_period), applied_price(_applied_price), IndicatorParams(INDI_CCI, 1, TYPE_DOUBLE) { + : period(_period), applied_price(_applied_price), IndicatorParams(INDI_CCI) { shift = _shift; - SetDataValueRange(IDATA_RANGE_MIXED); SetCustomIndicatorName("Examples\\CCI"); }; IndiCCIParams(IndiCCIParams &_params, ENUM_TIMEFRAMES _tf) { @@ -63,7 +62,11 @@ class Indi_CCI : public IndicatorTickSource { /** * Class constructor. */ - Indi_CCI(IndiCCIParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickSource(_p, _indi_src) {} + Indi_CCI(IndiCCIParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickSource( + _p, IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_MIXED, _indi_src_mode), + _indi_src) {} Indi_CCI(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickSource(INDI_CCI, _tf, _shift) {} /** @@ -74,7 +77,7 @@ class Indi_CCI : public IndicatorTickSource { * - https://www.mql5.com/en/docs/indicators/icci */ static double iCCI(string _symbol, ENUM_TIMEFRAMES _tf, unsigned int _period, ENUM_APPLIED_PRICE _applied_price, - int _shift = 0, IndicatorBase *_obj = NULL) { + int _shift = 0, IndicatorData *_obj = NULL) { #ifdef __MQL4__ return ::iCCI(_symbol, _tf, _period, _applied_price, _shift); #else // __MQL5__ @@ -82,7 +85,7 @@ class Indi_CCI : public IndicatorTickSource { #endif } - static double iCCIOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, unsigned int _period, + static double iCCIOnIndicator(IndicatorData *_indi, string _symbol, ENUM_TIMEFRAMES _tf, unsigned int _period, int _mode, int _shift = 0) { _indi.ValidateDataSourceMode(_mode); @@ -148,7 +151,7 @@ class Indi_CCI : public IndicatorTickSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); double _value = EMPTY_VALUE; - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: // @fixit Somehow shift isn't used neither in MT4 nor MT5. _value = Indi_CCI::iCCI(GetSymbol(), GetTf(), GetPeriod(), GetAppliedPrice(), _ishift /* + iparams.shift*/, @@ -162,7 +165,8 @@ class Indi_CCI : public IndicatorTickSource { ValidateSelectedDataSource(); // @fixit Somehow shift isn't used neither in MT4 nor MT5. - _value = Indi_CCI::iCCIOnIndicator(GetDataSource(), GetSymbol(), GetTf(), GetPeriod(), GetDataSourceMode(), + _value = Indi_CCI::iCCIOnIndicator(GetDataSource(), GetSymbol(), GetTf(), GetPeriod(), + Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_SRC_MODE)), _ishift /* + iparams.shift*/); break; } diff --git a/Indicators/Indi_CHO.mqh b/Indicators/Indi_CHO.mqh index 5366e2651..1e05734b0 100644 --- a/Indicators/Indi_CHO.mqh +++ b/Indicators/Indi_CHO.mqh @@ -36,10 +36,9 @@ struct IndiCHOParams : IndicatorParams { // Struct constructor. IndiCHOParams(int _fast_ma = 3, int _slow_ma = 10, ENUM_MA_METHOD _smooth_method = MODE_EMA, ENUM_APPLIED_VOLUME _input_volume = VOLUME_TICK, int _shift = 0) - : IndicatorParams(INDI_CHAIKIN, 1, TYPE_DOUBLE) { + : IndicatorParams(INDI_CHAIKIN) { fast_ma = _fast_ma; input_volume = _input_volume; - SetDataValueRange(IDATA_RANGE_MIXED); SetCustomIndicatorName("Examples\\CHO"); shift = _shift; slow_ma = _slow_ma; @@ -59,7 +58,11 @@ class Indi_CHO : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_CHO(IndiCHOParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_CHO(IndiCHOParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_MIXED, _indi_src_mode), + _indi_src){}; Indi_CHO(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_CHAIKIN, _tf, _shift){}; @@ -68,7 +71,7 @@ class Indi_CHO : public IndicatorTickOrCandleSource { */ static double iChaikin(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) { + IndicatorData *_obj = NULL) { #ifdef __MQL5__ INDICATOR_BUILTIN_CALL_AND_RETURN(::iChaikin(_symbol, _tf, _fast_ma_period, _slow_ma_period, _ma_method, _av), _mode, _shift); @@ -106,9 +109,9 @@ class Indi_CHO : public IndicatorTickOrCandleSource { /** * On-indicator version of Chaikin Oscillator. */ - static double iChaikinOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _fast_ma_period, + static double iChaikinOnIndicator(IndicatorData *_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) { + int _mode = 0, int _shift = 0, IndicatorData *_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, @@ -184,7 +187,7 @@ class Indi_CHO : public IndicatorTickOrCandleSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_CHO::iChaikin(GetSymbol(), GetTf(), /*[*/ GetSlowMA(), GetFastMA(), GetSmoothMethod(), GetInputVolume() /*]*/, _mode, _ishift, THIS_PTR); diff --git a/Indicators/Indi_CHV.mqh b/Indicators/Indi_CHV.mqh index 145a03f59..9d514d3f7 100644 --- a/Indicators/Indi_CHV.mqh +++ b/Indicators/Indi_CHV.mqh @@ -38,9 +38,8 @@ struct IndiCHVParams : IndicatorParams { // Struct constructor. IndiCHVParams(int _smooth_period = 10, int _chv_period = 10, ENUM_CHV_SMOOTH_METHOD _smooth_method = CHV_SMOOTH_METHOD_EMA, int _shift = 0) - : IndicatorParams(INDI_CHAIKIN_V, 1, TYPE_DOUBLE) { + : IndicatorParams(INDI_CHAIKIN_V) { chv_period = _chv_period; - SetDataValueRange(IDATA_RANGE_MIXED); SetCustomIndicatorName("Examples\\CHV"); shift = _shift; smooth_method = _smooth_method; @@ -60,7 +59,11 @@ class Indi_CHV : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_CHV(IndiCHVParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_CHV(IndiCHVParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_MIXED, _indi_src_mode), + _indi_src){}; Indi_CHV(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_CHAIKIN_V, _tf, _shift){}; @@ -68,7 +71,7 @@ class Indi_CHV : public IndicatorTickOrCandleSource { * Built-in version of Chaikin Volatility. */ static double iCHV(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) { + ENUM_CHV_SMOOTH_METHOD _smooth_method, int _mode = 0, int _shift = 0, IndicatorData *_obj = NULL) { INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG( _symbol, _tf, Util::MakeKey("Indi_CHV", _smooth_period, _chv_period, _smooth_method)); return iCHVOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _smooth_period, _chv_period, _smooth_method, _mode, @@ -103,9 +106,9 @@ class Indi_CHV : public IndicatorTickOrCandleSource { /** * On-indicator version of Chaikin Volatility. */ - static double iCHVOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _smooth_period, + static double iCHVOnIndicator(IndicatorData *_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) { + IndicatorData *_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)); @@ -179,7 +182,7 @@ class Indi_CHV : public IndicatorTickOrCandleSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_CHV::iCHV(GetSymbol(), GetTf(), /*[*/ GetSmoothPeriod(), GetCHVPeriod(), GetSmoothMethod() /*]*/, _mode, _ishift, THIS_PTR); diff --git a/Indicators/Indi_ColorBars.mqh b/Indicators/Indi_ColorBars.mqh index 7927d1fe2..cb920a588 100644 --- a/Indicators/Indi_ColorBars.mqh +++ b/Indicators/Indi_ColorBars.mqh @@ -28,8 +28,7 @@ // Structs. struct IndiColorBarsParams : IndicatorParams { // Struct constructor. - IndiColorBarsParams(int _shift = 0) : IndicatorParams(INDI_COLOR_BARS, 5, TYPE_DOUBLE) { - SetDataValueRange(IDATA_RANGE_MIXED); + IndiColorBarsParams(int _shift = 0) : IndicatorParams(INDI_COLOR_BARS) { SetCustomIndicatorName("Examples\\ColorBars"); shift = _shift; }; @@ -47,8 +46,11 @@ class Indi_ColorBars : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_ColorBars(IndiColorBarsParams &_p, IndicatorBase *_indi_src = NULL) - : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_ColorBars(IndiColorBarsParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, + IndicatorData *_indi_src = NULL, int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(5, TYPE_DOUBLE, _idstype, IDATA_RANGE_MIXED, _indi_src_mode), + _indi_src){}; Indi_ColorBars(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_COLOR_BARS, _tf, _shift){}; @@ -56,7 +58,7 @@ class Indi_ColorBars : public IndicatorTickOrCandleSource { * "Built-in" version of Color Bars. */ static double iColorBars(string _symbol, ENUM_TIMEFRAMES _tf, int _mode = 0, int _shift = 0, - IndicatorBase *_obj = NULL) { + IndicatorData *_obj = NULL) { INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG(_symbol, _tf, "Indi_ColorBars"); return iColorBarsOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _mode, _shift, _cache); } @@ -86,8 +88,8 @@ class Indi_ColorBars : public IndicatorTickOrCandleSource { /** * 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) { + static double iColorBarsOnIndicator(IndicatorData *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _mode = 0, + int _shift = 0, IndicatorData *_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); @@ -127,7 +129,7 @@ class Indi_ColorBars : public IndicatorTickOrCandleSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_ColorBars::iColorBars(GetSymbol(), GetTf(), _mode, _ishift, THIS_PTR); break; diff --git a/Indicators/Indi_ColorCandlesDaily.mqh b/Indicators/Indi_ColorCandlesDaily.mqh index 9348b8095..e848eb6f0 100644 --- a/Indicators/Indi_ColorCandlesDaily.mqh +++ b/Indicators/Indi_ColorCandlesDaily.mqh @@ -28,8 +28,7 @@ // Structs. struct IndiColorCandlesDailyParams : IndicatorParams { // Struct constructor. - IndiColorCandlesDailyParams(int _shift = 0) : IndicatorParams(INDI_COLOR_CANDLES_DAILY, 5, TYPE_DOUBLE) { - SetDataValueRange(IDATA_RANGE_MIXED); + IndiColorCandlesDailyParams(int _shift = 0) : IndicatorParams(INDI_COLOR_CANDLES_DAILY) { SetCustomIndicatorName("Examples\\ColorCandlesDaily"); shift = _shift; }; @@ -47,15 +46,18 @@ class Indi_ColorCandlesDaily : public IndicatorTickOrCandleSource= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_ColorCandlesDaily::iCCD(GetSymbol(), GetTf(), _mode, _ishift, THIS_PTR); break; diff --git a/Indicators/Indi_ColorLine.mqh b/Indicators/Indi_ColorLine.mqh index 64adcf9dc..a8f2b30bd 100644 --- a/Indicators/Indi_ColorLine.mqh +++ b/Indicators/Indi_ColorLine.mqh @@ -28,11 +28,10 @@ // Structs. struct IndiColorLineParams : IndicatorParams { - IndicatorBase *indi_ma; + IndicatorData *indi_ma; // Struct constructor. - IndiColorLineParams(int _shift = 0) : IndicatorParams(INDI_COLOR_LINE, 2, TYPE_DOUBLE) { + IndiColorLineParams(int _shift = 0) : IndicatorParams(INDI_COLOR_LINE) { indi_ma = NULL; - SetDataValueRange(IDATA_RANGE_MIXED); SetCustomIndicatorName("Examples\\ColorLine"); shift = _shift; }; @@ -50,8 +49,11 @@ class Indi_ColorLine : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_ColorLine(IndiColorLineParams &_p, IndicatorBase *_indi_src = NULL) - : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_ColorLine(IndiColorLineParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, + IndicatorData *_indi_src = NULL, int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(2, TYPE_DOUBLE, _idstype, IDATA_RANGE_MIXED, _indi_src_mode), + _indi_src){}; Indi_ColorLine(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_COLOR_LINE, _tf, _shift){}; @@ -59,7 +61,7 @@ class Indi_ColorLine : public IndicatorTickOrCandleSource { * "Built-in" version of Color Line. */ static double iColorLine(string _symbol, ENUM_TIMEFRAMES _tf, int _mode = 0, int _shift = 0, - IndicatorBase *_obj = NULL) { + IndicatorData *_obj = NULL) { INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG(_symbol, _tf, "Indi_ColorLine"); Indi_MA *_indi_ma = Indi_MA::GetCached(_symbol, _tf, 10, 0, MODE_EMA, PRICE_CLOSE); @@ -71,7 +73,7 @@ class Indi_ColorLine : public IndicatorTickOrCandleSource { * Calculates Color Line on the array of values. */ static double iColorLineOnArray(INDICATOR_CALCULATE_PARAMS_LONG, int _mode, int _shift, - IndicatorCalculateCache *_cache, IndicatorBase *_indi_ma, + IndicatorCalculateCache *_cache, IndicatorData *_indi_ma, bool _recalculate = false) { _cache.SetPriceBuffer(_open, _high, _low, _close); @@ -92,8 +94,8 @@ class Indi_ColorLine : public IndicatorTickOrCandleSource { /** * 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) { + static double iColorLineOnIndicator(IndicatorData *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _mode = 0, + int _shift = 0, IndicatorData *_obj = NULL) { INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG_DS(_indi, _symbol, _tf, Util::MakeKey("Indi_ColorLine_ON_" + _indi.GetFullName())); @@ -105,7 +107,7 @@ class Indi_ColorLine : public IndicatorTickOrCandleSource { /** * Provides built-in indicators whose can be used as data source. */ - virtual IndicatorBase *FetchDataSource(ENUM_INDICATOR_TYPE _id) override { + virtual IndicatorData *FetchDataSource(ENUM_INDICATOR_TYPE _id) override { switch (_id) { case INDI_MA: return iparams.indi_ma; @@ -117,7 +119,7 @@ class Indi_ColorLine : public IndicatorTickOrCandleSource { * OnCalculate() method for Color Line indicator. */ static int Calculate(INDICATOR_CALCULATE_METHOD_PARAMS_LONG, ValueStorage &ExtColorLineBuffer, - ValueStorage &ExtColorsBuffer, IndicatorBase *ExtMAHandle) { + ValueStorage &ExtColorsBuffer, IndicatorData *ExtMAHandle) { static int ticks = 0, modified = 0; // Check data. int i, calculated = BarsCalculated(ExtMAHandle); @@ -202,7 +204,7 @@ class Indi_ColorLine : public IndicatorTickOrCandleSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_ColorLine::iColorLine(GetSymbol(), GetTf(), _mode, _ishift, THIS_PTR); break; diff --git a/Indicators/Indi_CustomMovingAverage.mqh b/Indicators/Indi_CustomMovingAverage.mqh index e172c2b69..8e4b16e43 100644 --- a/Indicators/Indi_CustomMovingAverage.mqh +++ b/Indicators/Indi_CustomMovingAverage.mqh @@ -32,14 +32,14 @@ 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, 1, TYPE_DOUBLE) { - SetDataValueRange(IDATA_RANGE_MIXED); - SetDataSourceType(IDATA_ICUSTOM); + : IndicatorParams(INDI_CUSTOM_MOVING_AVG) { + if (custom_indi_name == "") { #ifdef __MQL5__ - SetCustomIndicatorName("Examples\\Custom Moving Average"); + SetCustomIndicatorName("Examples\\Custom Moving Average"); #else - SetCustomIndicatorName("Custom Moving Averages"); + SetCustomIndicatorName("Custom Moving Averages"); #endif + } shift = _shift; smooth_method = _smooth_method; smooth_period = _smooth_period; @@ -59,8 +59,11 @@ class Indi_CustomMovingAverage : public IndicatorTickOrCandleSource= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_ICUSTOM: _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetSmoothPeriod(), GetSmoothShift(), GetSmoothMethod() /*]*/, 0, _ishift); diff --git a/Indicators/Indi_DEMA.mqh b/Indicators/Indi_DEMA.mqh index ec5007d20..972d77f1c 100644 --- a/Indicators/Indi_DEMA.mqh +++ b/Indicators/Indi_DEMA.mqh @@ -42,16 +42,11 @@ struct IndiDEIndiMAParams : IndicatorParams { ENUM_APPLIED_PRICE applied_price; // Struct constructors. IndiDEIndiMAParams(unsigned int _period = 14, int _ma_shift = 0, ENUM_APPLIED_PRICE _ap = PRICE_CLOSE, int _shift = 0) - : period(_period), ma_shift(_ma_shift), applied_price(_ap), IndicatorParams(INDI_DEMA, 1, TYPE_DOUBLE) { + : period(_period), ma_shift(_ma_shift), applied_price(_ap), IndicatorParams(INDI_DEMA) { SetCustomIndicatorName("Examples\\DEMA"); - SetDataValueRange(IDATA_RANGE_PRICE); SetShift(_shift); - switch (idstype) { - case IDATA_ICUSTOM: - if (custom_indi_name == "") { - SetCustomIndicatorName("Examples\\DEMA"); - } - break; + if (custom_indi_name == "") { + SetCustomIndicatorName("Examples\\DEMA"); } }; IndiDEIndiMAParams(IndiDEIndiMAParams &_params, ENUM_TIMEFRAMES _tf) { @@ -68,7 +63,11 @@ class Indi_DEMA : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_DEMA(IndiDEIndiMAParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_DEMA(IndiDEIndiMAParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_PRICE, _indi_src_mode), + _indi_src) {} Indi_DEMA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_DEMA, _tf, _shift) {} @@ -79,7 +78,7 @@ class Indi_DEMA : public IndicatorTickOrCandleSource { * - https://www.mql5.com/en/docs/indicators/IDEMA */ static double iDEMA(string _symbol, ENUM_TIMEFRAMES _tf, unsigned int _period, unsigned int _ma_shift, - ENUM_APPLIED_PRICE _applied_price, int _shift = 0, int _mode = 0, IndicatorBase *_obj = NULL) { + ENUM_APPLIED_PRICE _applied_price, int _shift = 0, int _mode = 0, IndicatorData *_obj = NULL) { #ifdef __MQL5__ int _handle = Object::IsValid(_obj) ? _obj.Get(IndicatorState::INDICATOR_STATE_PROP_HANDLE) : NULL; double _res[]; @@ -113,7 +112,7 @@ class Indi_DEMA : public IndicatorTickOrCandleSource { #endif } - static double iDEMAOnIndicatorSlow(IndicatorCalculateCache *cache, IndicatorBase *_indi, int indi_mode, + static double iDEMAOnIndicatorSlow(IndicatorCalculateCache *cache, IndicatorData *_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); } @@ -148,8 +147,8 @@ class Indi_DEMA : public IndicatorTickOrCandleSource { /** * 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) { + static double iDEMAOnIndicator(IndicatorData *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _period, int _ma_shift, + ENUM_APPLIED_PRICE _ap, int _mode = 0, int _shift = 0, IndicatorData *_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); @@ -181,7 +180,7 @@ class Indi_DEMA : public IndicatorTickOrCandleSource { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: // We're getting DEMA from Price indicator. _value = Indi_DEMA::iDEMA(GetSymbol(), GetTf(), /*[*/ GetPeriod(), GetMAShift(), GetAppliedPrice() /*]*/, diff --git a/Indicators/Indi_DeMarker.mqh b/Indicators/Indi_DeMarker.mqh index 2e67aa4ea..d20b21dab 100644 --- a/Indicators/Indi_DeMarker.mqh +++ b/Indicators/Indi_DeMarker.mqh @@ -35,10 +35,8 @@ double iDeMarker(string _symbol, int _tf, int _period, int _shift) { struct IndiDeMarkerParams : IndicatorParams { unsigned int period; // Struct constructors. - IndiDeMarkerParams(unsigned int _period = 14, int _shift = 0) - : period(_period), IndicatorParams(INDI_DEMARKER, 1, TYPE_DOUBLE) { + IndiDeMarkerParams(unsigned int _period = 14, int _shift = 0) : period(_period), IndicatorParams(INDI_DEMARKER) { shift = _shift; - SetDataValueRange(IDATA_RANGE_RANGE); SetCustomIndicatorName("Examples\\DeMarker"); }; IndiDeMarkerParams(IndiDeMarkerParams &_params, ENUM_TIMEFRAMES _tf) { @@ -55,7 +53,11 @@ class Indi_DeMarker : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_DeMarker(IndiDeMarkerParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_DeMarker(IndiDeMarkerParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, + IndicatorData *_indi_src = NULL, int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_RANGE, _indi_src_mode), + _indi_src) {} Indi_DeMarker(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_DEMARKER, _tf, _shift) {} @@ -67,7 +69,7 @@ class Indi_DeMarker : public IndicatorTickOrCandleSource { * - https://www.mql5.com/en/docs/indicators/idemarker */ static double iDeMarker(string _symbol, ENUM_TIMEFRAMES _tf, unsigned int _period, int _shift = 0, - IndicatorBase *_obj = NULL) { + IndicatorData *_obj = NULL) { #ifdef __MQL4__ return ::iDeMarker(_symbol, _tf, _period, _shift); #else // __MQL5__ @@ -105,7 +107,7 @@ class Indi_DeMarker : public IndicatorTickOrCandleSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = _value = Indi_DeMarker::iDeMarker(GetSymbol(), GetTf(), GetPeriod(), _ishift, THIS_PTR); break; diff --git a/Indicators/Indi_Demo.mqh b/Indicators/Indi_Demo.mqh index 9fd756862..7adc7080e 100644 --- a/Indicators/Indi_Demo.mqh +++ b/Indicators/Indi_Demo.mqh @@ -33,15 +33,10 @@ // Structs. struct IndiDemoParams : IndicatorParams { // Struct constructors. - IndiDemoParams(int _shift = 0) : IndicatorParams(INDI_DEMO, 1, TYPE_DOUBLE) { - SetDataValueRange(IDATA_RANGE_MIXED); + IndiDemoParams(int _shift = 0) : IndicatorParams(INDI_DEMO) { SetShift(_shift); - switch (idstype) { - case IDATA_ICUSTOM: - if (custom_indi_name == "") { - SetCustomIndicatorName("Examples\\Demo"); - } - break; + if (custom_indi_name == "") { + SetCustomIndicatorName("Examples\\Demo"); } }; IndiDemoParams(IndiDemoParams &_params, ENUM_TIMEFRAMES _tf) { @@ -58,7 +53,11 @@ class Indi_Demo : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_Demo(IndiDemoParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_Demo(IndiDemoParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_MIXED, _indi_src_mode), + _indi_src){}; Indi_Demo(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_DEMO, _tf, _shift){}; @@ -66,7 +65,7 @@ class Indi_Demo : public IndicatorTickOrCandleSource { * Returns the indicator value. */ static double iDemo(string _symbol = NULL, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0, - IndicatorBase *_obj = NULL) { + IndicatorData *_obj = NULL) { return 0.1 + (0.1 * _obj.GetBarIndex()); } diff --git a/Indicators/Indi_DetrendedPrice.mqh b/Indicators/Indi_DetrendedPrice.mqh index 3f78bdddd..ab3195936 100644 --- a/Indicators/Indi_DetrendedPrice.mqh +++ b/Indicators/Indi_DetrendedPrice.mqh @@ -32,9 +32,8 @@ struct IndiDetrendedPriceParams : IndicatorParams { ENUM_APPLIED_PRICE applied_price; // Struct constructor. IndiDetrendedPriceParams(int _period = 12, ENUM_APPLIED_PRICE _ap = PRICE_CLOSE, int _shift = 0) - : IndicatorParams(INDI_DETRENDED_PRICE, 1, TYPE_DOUBLE) { + : IndicatorParams(INDI_DETRENDED_PRICE) { applied_price = _ap; - SetDataValueRange(IDATA_RANGE_MIXED); SetCustomIndicatorName("Examples\\DPO"); period = _period; shift = _shift; @@ -53,8 +52,11 @@ class Indi_DetrendedPrice : public IndicatorTickOrCandleSource= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_DetrendedPrice::iDPO(GetSymbol(), GetTf(), /*[*/ GetPeriod(), GetAppliedPrice() /*]*/, _mode, _ishift, THIS_PTR); diff --git a/Indicators/Indi_Drawer.mqh b/Indicators/Indi_Drawer.mqh index 893d62f65..f6ea7ecf7 100644 --- a/Indicators/Indi_Drawer.mqh +++ b/Indicators/Indi_Drawer.mqh @@ -41,8 +41,12 @@ class Indi_Drawer : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_Drawer(const IndiDrawerParams &_p, IndicatorBase *_indi_src = NULL) - : IndicatorTickOrCandleSource(_p, _indi_src), redis(true) { + Indi_Drawer(const IndiDrawerParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, + IndicatorData *_indi_src = NULL, int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(0, TYPE_DOUBLE, _idstype, IDATA_RANGE_UNKNOWN, _indi_src_mode), + _indi_src), + redis(true) { Init(); } Indi_Drawer(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) @@ -71,15 +75,16 @@ class Indi_Drawer : public IndicatorTickOrCandleSource { virtual bool ExecuteAction(ENUM_INDICATOR_ACTION _action, DataParamEntry &_args[]) { int num_args = ArraySize(_args), i; + int _max_modes = Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES)); IndicatorDataEntry entry(num_args - 1); // @fixit Not sure if we should enforce double. // entry.AddFlags(INDI_ENTRY_FLAG_IS_DOUBLE); if (_action == INDI_ACTION_SET_VALUE) { - iparams.SetMaxModes(num_args - 1); + Set(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES), num_args - 1); - if (num_args - 1 > iparams.GetMaxModes()) { + if (num_args - 1 > _max_modes) { GetLogger().Error( StringFormat("Too many data for buffers for action %s!", EnumToString(_action), __FUNCTION_LINE__)); return false; @@ -150,14 +155,14 @@ class Indi_Drawer : public IndicatorTickOrCandleSource { * - https://www.mql5.com/en/docs/indicators/irsi */ static double iDrawer(string _symbol = NULL, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0, - IndicatorBase *_obj = NULL) { + IndicatorData *_obj = NULL) { return 1.0; } /** * Performs drawing on data from other indicator. */ - static double iDrawerOnIndicator(IndicatorBase *_indi, Indi_Drawer *_obj, string _symbol = NULL, + static double iDrawerOnIndicator(IndicatorData *_indi, Indi_Drawer *_obj, string _symbol = NULL, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) { // This method is not yet implemented. return 1.0; @@ -173,10 +178,10 @@ class Indi_Drawer : public IndicatorTickOrCandleSource { /** * Returns the indicator's value. */ - virtual IndicatorDataEntryValue GetEntryValue(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) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_Drawer::iDrawer(GetSymbol(), GetTf(), _ishift, THIS_PTR); break; diff --git a/Indicators/Indi_Drawer.struct.h b/Indicators/Indi_Drawer.struct.h index e868d110e..b9f5f8287 100644 --- a/Indicators/Indi_Drawer.struct.h +++ b/Indicators/Indi_Drawer.struct.h @@ -36,7 +36,7 @@ struct IndiDrawerParams : IndicatorParams { ENUM_APPLIED_PRICE applied_price; IndiDrawerParams(unsigned int _period = 10, ENUM_APPLIED_PRICE _ap = PRICE_CLOSE) - : period(_period), applied_price(_ap), IndicatorParams(INDI_DRAWER, 0, TYPE_DOUBLE) { + : period(_period), applied_price(_ap), IndicatorParams(INDI_DRAWER) { // Fetching history data is not yet implemented. SetCustomIndicatorName("Examples\\Drawer"); }; diff --git a/Indicators/Indi_Envelopes.mqh b/Indicators/Indi_Envelopes.mqh index ecede2db4..431598d19 100644 --- a/Indicators/Indi_Envelopes.mqh +++ b/Indicators/Indi_Envelopes.mqh @@ -58,13 +58,8 @@ struct IndiEnvelopesParams : IndicatorParams { ma_method(_ma_method), applied_price(_ap), deviation(_deviation), - IndicatorParams(INDI_ENVELOPES, 2, TYPE_DOUBLE) { -#ifdef __MQL4__ - // There is extra LINE_MAIN in MQL4 for Envelopes. - max_modes = 3; -#endif + IndicatorParams(INDI_ENVELOPES) { shift = _shift; - SetDataValueRange(IDATA_RANGE_PRICE); SetCustomIndicatorName("Examples\\Envelopes"); }; IndiEnvelopesParams(IndiEnvelopesParams &_params, ENUM_TIMEFRAMES _tf) { @@ -77,14 +72,36 @@ struct IndiEnvelopesParams : IndicatorParams { * Implements the Envelopes indicator. */ class Indi_Envelopes : public IndicatorTickOrCandleSource { + protected: + /* Protected methods */ + + /** + * Initialize. + */ + void Init() { +#ifdef __MQL4__ + // There is extra LINE_MAIN in MQL4 for Envelopes. + Set(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES), 3); +#else + Set(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES), 2); +#endif + } + public: /** * Class constructor. */ - Indi_Envelopes(IndiEnvelopesParams &_p, IndicatorBase *_indi_src = NULL) - : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_Envelopes(IndiEnvelopesParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, + IndicatorData *_indi_src = NULL, int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(2, TYPE_DOUBLE, _idstype, IDATA_RANGE_PRICE, _indi_src_mode), + _indi_src) { + Init(); + } Indi_Envelopes(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) - : IndicatorTickOrCandleSource(INDI_ENVELOPES, _tf, _shift) {} + : IndicatorTickOrCandleSource(INDI_ENVELOPES, _tf, _shift) { + Init(); + }; /** * Returns the indicator value. @@ -97,7 +114,7 @@ class Indi_Envelopes : public IndicatorTickOrCandleSource { int _ma_shift, ENUM_APPLIED_PRICE _ap, double _deviation, int _mode, // (MT4 _mode): 0 - MODE_MAIN, 1 - MODE_UPPER, 2 - MODE_LOWER; (MT5 _mode): 0 - // UPPER_LINE, 1 - LOWER_LINE - int _shift = 0, IndicatorBase *_obj = NULL) { + int _shift = 0, IndicatorData *_obj = NULL) { #ifdef __MQL4__ return ::iEnvelopes(_symbol, _tf, _ma_period, _ma_method, _ma_shift, _ap, _deviation, _mode, _shift); #else // __MQL5__ @@ -138,7 +155,7 @@ class Indi_Envelopes : public IndicatorTickOrCandleSource { #endif } - static double iEnvelopesOnIndicator(IndicatorCalculateCache *_cache, IndicatorBase *_indi, string _symbol, + static double iEnvelopesOnIndicator(IndicatorCalculateCache *_cache, IndicatorData *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _ma_period, ENUM_MA_METHOD _ma_method, // (MT4/MT5): MODE_SMA, MODE_EMA, MODE_SMMA, MODE_LWMA int _indi_mode, // Source indicator's mode index. May be -1 to use first buffer @@ -201,7 +218,7 @@ class Indi_Envelopes : public IndicatorTickOrCandleSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_Envelopes::iEnvelopes(GetSymbol(), GetTf(), GetMAPeriod(), GetMAMethod(), GetMAShift(), GetAppliedPrice(), GetDeviation(), _mode, _ishift, THIS_PTR); @@ -212,8 +229,9 @@ class Indi_Envelopes : public IndicatorTickOrCandleSource { break; case IDATA_INDICATOR: _value = Indi_Envelopes::iEnvelopesOnIndicator(GetCache(), GetDataSource(), GetSymbol(), GetTf(), GetMAPeriod(), - GetMAMethod(), GetDataSourceMode(), GetMAShift(), GetDeviation(), - _mode, _ishift); + GetMAMethod(), + Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_SRC_MODE)), + GetMAShift(), GetDeviation(), _mode, _ishift); break; default: SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_Force.mqh b/Indicators/Indi_Force.mqh index 661bdc6a4..0880d6ee3 100644 --- a/Indicators/Indi_Force.mqh +++ b/Indicators/Indi_Force.mqh @@ -51,9 +51,8 @@ struct IndiForceParams : IndicatorParams { // Struct constructors. IndiForceParams(unsigned int _period = 13, ENUM_MA_METHOD _ma_method = MODE_SMA, ENUM_APPLIED_PRICE _ap = PRICE_CLOSE, int _shift = 0) - : period(_period), ma_method(_ma_method), applied_price(_ap), IndicatorParams(INDI_FORCE, 1, TYPE_DOUBLE) { + : period(_period), ma_method(_ma_method), applied_price(_ap), IndicatorParams(INDI_FORCE) { shift = _shift; - SetDataValueRange(IDATA_RANGE_MIXED); SetCustomIndicatorName("Examples\\Force_Index"); }; IndiForceParams(IndiForceParams &_params, ENUM_TIMEFRAMES _tf) { @@ -71,7 +70,11 @@ class Indi_Force : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_Force(IndiForceParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_Force(IndiForceParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_MIXED, _indi_src_mode), + _indi_src) {} Indi_Force(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_FORCE, _tf, _shift) {} @@ -83,7 +86,7 @@ class Indi_Force : public IndicatorTickOrCandleSource { * - https://www.mql5.com/en/docs/indicators/iforce */ static double iForce(string _symbol, ENUM_TIMEFRAMES _tf, unsigned int _period, ENUM_MA_METHOD _ma_method, - ENUM_APPLIED_PRICE _applied_price, int _shift = 0, IndicatorBase *_obj = NULL) { + ENUM_APPLIED_PRICE _applied_price, int _shift = 0, IndicatorData *_obj = NULL) { #ifdef __MQL4__ return ::iForce(_symbol, _tf, _period, _ma_method, _applied_price, _shift); #else // __MQL5__ @@ -121,7 +124,7 @@ class Indi_Force : public IndicatorTickOrCandleSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_Force::iForce(GetSymbol(), GetTf(), GetPeriod(), GetMAMethod(), GetAppliedPrice(), _ishift, THIS_PTR); diff --git a/Indicators/Indi_FractalAdaptiveMA.mqh b/Indicators/Indi_FractalAdaptiveMA.mqh index a0c69a60c..33a72fb83 100644 --- a/Indicators/Indi_FractalAdaptiveMA.mqh +++ b/Indicators/Indi_FractalAdaptiveMA.mqh @@ -33,9 +33,8 @@ struct IndiFrAIndiMAParams : IndicatorParams { // Struct constructor. IndiFrAIndiMAParams(int _period = 14, int _frama_shift = 0, ENUM_APPLIED_PRICE _ap = PRICE_CLOSE, int _shift = 0) - : IndicatorParams(INDI_FRAMA, 1, TYPE_DOUBLE) { + : IndicatorParams(INDI_FRAMA) { frama_shift = _frama_shift; - SetDataValueRange(IDATA_RANGE_MIXED); SetCustomIndicatorName("Examples\\FrAMA"); applied_price = _ap; period = _period; @@ -55,7 +54,11 @@ class Indi_FrAMA : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_FrAMA(IndiFrAIndiMAParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_FrAMA(IndiFrAIndiMAParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_MIXED, _indi_src_mode), + _indi_src){}; Indi_FrAMA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_FRAMA, _tf, _shift){}; @@ -63,7 +66,7 @@ class Indi_FrAMA : public IndicatorTickOrCandleSource { * Built-in version of FrAMA. */ static double iFrAMA(string _symbol, ENUM_TIMEFRAMES _tf, int _ma_period, int _ma_shift, ENUM_APPLIED_PRICE _ap, - int _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) { + int _mode = 0, int _shift = 0, IndicatorData *_obj = NULL) { #ifdef __MQL5__ INDICATOR_BUILTIN_CALL_AND_RETURN(::iFrAMA(_symbol, _tf, _ma_period, _ma_shift, _ap), _mode, _shift); #else @@ -98,9 +101,9 @@ class Indi_FrAMA : public IndicatorTickOrCandleSource { /** * On-indicator version of FrAMA. */ - static double iFrAMAOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _ma_period, + static double iFrAMAOnIndicator(IndicatorData *_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) { + IndicatorData *_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); @@ -148,7 +151,7 @@ class Indi_FrAMA : public IndicatorTickOrCandleSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_FrAMA::iFrAMA(GetSymbol(), GetTf(), /*[*/ GetPeriod(), GetFRAMAShift(), GetAppliedPrice() /*]*/, _mode, _ishift, THIS_PTR); diff --git a/Indicators/Indi_Fractals.mqh b/Indicators/Indi_Fractals.mqh index cb1922ff1..c34b745cb 100644 --- a/Indicators/Indi_Fractals.mqh +++ b/Indicators/Indi_Fractals.mqh @@ -34,8 +34,7 @@ double iFractals(string _symbol, int _tf, int _mode, int _shift) { // Structs. struct IndiFractalsParams : IndicatorParams { // Struct constructors. - IndiFractalsParams(int _shift = 0) : IndicatorParams(INDI_FRACTALS, FINAL_LO_UP_LINE_ENTRY, TYPE_DOUBLE) { - SetDataValueRange(IDATA_RANGE_ARROW); + IndiFractalsParams(int _shift = 0) : IndicatorParams(INDI_FRACTALS) { SetCustomIndicatorName("Examples\\Fractals"); shift = _shift; }; @@ -49,13 +48,30 @@ struct IndiFractalsParams : IndicatorParams { * Implements the Fractals indicator. */ class Indi_Fractals : public IndicatorTickOrCandleSource { + protected: + /* Protected methods */ + + /** + * Initialize. + */ + void Init() { Set(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES), FINAL_LO_UP_LINE_ENTRY); } + public: /** * Class constructor. */ - Indi_Fractals(IndiFractalsParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_Fractals(IndiFractalsParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, + IndicatorData *_indi_src = NULL, int _indi_src_mode = 0) + : IndicatorTickOrCandleSource(_p, + IndicatorDataParams::GetInstance(FINAL_LO_UP_LINE_ENTRY, TYPE_DOUBLE, _idstype, + IDATA_RANGE_PRICE_ON_SIGNAL, _indi_src_mode), + _indi_src) { + Init(); + } Indi_Fractals(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) - : IndicatorTickOrCandleSource(INDI_FRACTALS, _tf, _shift) {} + : IndicatorTickOrCandleSource(INDI_FRACTALS, _tf, _shift) { + Init(); + } /** * Returns the indicator value. @@ -67,7 +83,7 @@ class Indi_Fractals : public IndicatorTickOrCandleSource { static double iFractals(string _symbol, ENUM_TIMEFRAMES _tf, ENUM_LO_UP_LINE _mode, // (MT4 _mode): 1 - MODE_UPPER, 2 - MODE_LOWER int _shift = 0, // (MT5 _mode): 0 - UPPER_LINE, 1 - LOWER_LINE - IndicatorBase *_obj = NULL) { + IndicatorData *_obj = NULL) { #ifdef __MQL4__ return ::iFractals(_symbol, _tf, _mode, _shift); #else // __MQL5__ @@ -105,7 +121,7 @@ class Indi_Fractals : public IndicatorTickOrCandleSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_Fractals::iFractals(GetSymbol(), GetTf(), (ENUM_LO_UP_LINE)_mode, _ishift, THIS_PTR); break; diff --git a/Indicators/Indi_Gator.mqh b/Indicators/Indi_Gator.mqh index f87e8fc5a..dd0b06b7a 100644 --- a/Indicators/Indi_Gator.mqh +++ b/Indicators/Indi_Gator.mqh @@ -89,9 +89,8 @@ struct IndiGatorParams : IndicatorParams { lips_shift(_ls), ma_method(_mm), applied_price(_ap), - IndicatorParams(INDI_GATOR, FINAL_GATOR_LINE_HISTOGRAM_ENTRY, TYPE_DOUBLE) { + IndicatorParams(INDI_GATOR) { shift = _shift; - SetDataValueRange(IDATA_RANGE_MIXED); SetCustomIndicatorName("Examples\\Gator"); }; IndiGatorParams(IndiGatorParams &_params, ENUM_TIMEFRAMES _tf) { @@ -104,13 +103,30 @@ struct IndiGatorParams : IndicatorParams { * Implements the Gator oscillator. */ class Indi_Gator : public IndicatorTickOrCandleSource { + protected: + /* Protected methods */ + + /** + * Initialize. + */ + void Init() { Set(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES), FINAL_GATOR_LINE_HISTOGRAM_ENTRY); } + public: /** * Class constructor. */ - Indi_Gator(IndiGatorParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_Gator(IndiGatorParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource(_p, + IndicatorDataParams::GetInstance(FINAL_GATOR_LINE_HISTOGRAM_ENTRY, TYPE_DOUBLE, + _idstype, IDATA_RANGE_MIXED, _indi_src_mode), + _indi_src) { + Init(); + } Indi_Gator(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) - : IndicatorTickOrCandleSource(INDI_GATOR, _tf, _shift) {} + : IndicatorTickOrCandleSource(INDI_GATOR, _tf, _shift) { + Init(); + } /** * Returns the indicator value. @@ -133,7 +149,7 @@ class Indi_Gator : public IndicatorTickOrCandleSource { static double iGator(string _symbol, ENUM_TIMEFRAMES _tf, int _jaw_period, int _jaw_shift, int _teeth_period, int _teeth_shift, int _lips_period, int _lips_shift, ENUM_MA_METHOD _ma_method, ENUM_APPLIED_PRICE _applied_price, ENUM_GATOR_HISTOGRAM _mode, int _shift = 0, - IndicatorBase *_obj = NULL) { + IndicatorData *_obj = NULL) { #ifdef __MQL4__ return ::iGator(_symbol, _tf, _jaw_period, _jaw_shift, _teeth_period, _teeth_shift, _lips_period, _lips_shift, _ma_method, _applied_price, _mode, _shift); @@ -173,7 +189,7 @@ class Indi_Gator : public IndicatorTickOrCandleSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_Gator::iGator(GetSymbol(), GetTf(), GetJawPeriod(), GetJawShift(), GetTeethPeriod(), GetTeethShift(), GetLipsPeriod(), GetLipsShift(), GetMAMethod(), GetAppliedPrice(), diff --git a/Indicators/Indi_HeikenAshi.mqh b/Indicators/Indi_HeikenAshi.mqh index e3c3e33bc..637efb682 100644 --- a/Indicators/Indi_HeikenAshi.mqh +++ b/Indicators/Indi_HeikenAshi.mqh @@ -50,13 +50,14 @@ enum ENUM_HA_MODE { // Structs. struct IndiHeikenAshiParams : IndicatorParams { // Struct constructors. - IndiHeikenAshiParams(int _shift = 0) : IndicatorParams(INDI_HEIKENASHI, FINAL_HA_MODE_ENTRY, TYPE_DOUBLE) { - SetDataValueRange(IDATA_RANGE_MIXED); // @fixit It draws candles! + IndiHeikenAshiParams(int _shift = 0) : IndicatorParams(INDI_HEIKENASHI) { + if (custom_indi_name == "") { #ifdef __MQL4__ - SetCustomIndicatorName("Heiken Ashi"); + SetCustomIndicatorName("Heiken Ashi"); #else - SetCustomIndicatorName("Examples\\Heiken_Ashi"); + SetCustomIndicatorName("Examples\\Heiken_Ashi"); #endif + } shift = _shift; }; IndiHeikenAshiParams(IndiHeikenAshiParams &_params, ENUM_TIMEFRAMES _tf) { @@ -69,20 +70,36 @@ struct IndiHeikenAshiParams : IndicatorParams { * Implements the Heiken-Ashi indicator. */ class Indi_HeikenAshi : public IndicatorTickOrCandleSource { + protected: + /* Protected methods */ + + /** + * Initialize. + */ + void Init() { Set(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES), FINAL_HA_MODE_ENTRY); } + public: /** * Class constructor. */ - Indi_HeikenAshi(IndiHeikenAshiParams &_p, IndicatorBase *_indi_src = NULL) - : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_HeikenAshi(IndiHeikenAshiParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, + IndicatorData *_indi_src = NULL, int _indi_src_mode = 0) + : IndicatorTickOrCandleSource(_p, + IndicatorDataParams::GetInstance(FINAL_HA_MODE_ENTRY, TYPE_DOUBLE, _idstype, + IDATA_RANGE_PRICE, _indi_src_mode), + _indi_src) { + Init(); + } Indi_HeikenAshi(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) - : IndicatorTickOrCandleSource(INDI_HEIKENASHI, _tf, _shift) {} + : IndicatorTickOrCandleSource(INDI_HEIKENASHI, _tf, _shift) { + Init(); + } /** * Returns value for iHeikenAshi indicator. */ static double iCustomLegacyHeikenAshi(string _symbol, ENUM_TIMEFRAMES _tf, string _name, int _mode, int _shift = 0, - IndicatorBase *_obj = NULL) { + IndicatorData *_obj = NULL) { #ifdef __MQL4__ // Low and High prices could be in reverse order when using MT4's built-in indicator, so we need to retrieve both // and return correct one. @@ -161,8 +178,8 @@ class Indi_HeikenAshi : public IndicatorTickOrCandleSource /** * 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) { + static double iHeikenAshiOnIndicator(IndicatorData *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _mode = 0, + int _shift = 0, IndicatorData *_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); @@ -209,7 +226,7 @@ class Indi_HeikenAshi : public IndicatorTickOrCandleSource virtual IndicatorDataEntryValue GetEntryValue(int _mode = HA_OPEN, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: #ifdef __MQL4__ // Converting MQL4's enum into MQL5 one, as OnCalculate uses further one. diff --git a/Indicators/Indi_Ichimoku.mqh b/Indicators/Indi_Ichimoku.mqh index e87290e9e..16ceaab94 100644 --- a/Indicators/Indi_Ichimoku.mqh +++ b/Indicators/Indi_Ichimoku.mqh @@ -69,12 +69,8 @@ struct IndiIchimokuParams : IndicatorParams { unsigned int senkou_span_b; // Struct constructors. IndiIchimokuParams(unsigned int _ts = 9, unsigned int _ks = 26, unsigned int _ss_b = 52, int _shift = 0) - : tenkan_sen(_ts), - kijun_sen(_ks), - senkou_span_b(_ss_b), - IndicatorParams(INDI_ICHIMOKU, FINAL_ICHIMOKU_LINE_ENTRY, TYPE_DOUBLE) { + : tenkan_sen(_ts), kijun_sen(_ks), senkou_span_b(_ss_b), IndicatorParams(INDI_ICHIMOKU) { shift = _shift; - SetDataValueRange(IDATA_RANGE_PRICE); // @fixit Not sure if not mixed. SetCustomIndicatorName("Examples\\Ichimoku"); }; IndiIchimokuParams(IndiIchimokuParams &_params, ENUM_TIMEFRAMES _tf) { @@ -87,13 +83,30 @@ struct IndiIchimokuParams : IndicatorParams { * Implements the Ichimoku Kinko Hyo indicator. */ class Indi_Ichimoku : public IndicatorTickOrCandleSource { + protected: + /* Protected methods */ + + /** + * Initialize. + */ + void Init() { Set(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES), FINAL_ICHIMOKU_LINE_ENTRY); } + public: /** * Class constructor. */ - Indi_Ichimoku(IndiIchimokuParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_Ichimoku(IndiIchimokuParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, + IndicatorData *_indi_src = NULL, int _indi_src_mode = 0) + : IndicatorTickOrCandleSource(_p, + IndicatorDataParams::GetInstance(FINAL_ICHIMOKU_LINE_ENTRY, TYPE_DOUBLE, _idstype, + IDATA_RANGE_PRICE, _indi_src_mode), + _indi_src) { + Init(); + } Indi_Ichimoku(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) - : IndicatorTickOrCandleSource(INDI_ICHIMOKU, _tf, _shift) {} + : IndicatorTickOrCandleSource(INDI_ICHIMOKU, _tf, _shift) { + Init(); + } /** * Returns the indicator value. @@ -107,7 +120,7 @@ class Indi_Ichimoku : public IndicatorTickOrCandleSource { * - https://www.mql5.com/en/docs/indicators/iichimoku */ static double iIchimoku(string _symbol, ENUM_TIMEFRAMES _tf, int _tenkan_sen, int _kijun_sen, int _senkou_span_b, - int _mode, int _shift = 0, IndicatorBase *_obj = NULL) { + int _mode, int _shift = 0, IndicatorData *_obj = NULL) { #ifdef __MQL4__ return ::iIchimoku(_symbol, _tf, _tenkan_sen, _kijun_sen, _senkou_span_b, _mode, _shift); #else // __MQL5__ @@ -145,7 +158,7 @@ class Indi_Ichimoku : public IndicatorTickOrCandleSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_Ichimoku::iIchimoku(GetSymbol(), GetTf(), GetTenkanSen(), GetKijunSen(), GetSenkouSpanB(), _mode, _ishift, THIS_PTR); diff --git a/Indicators/Indi_Killzones.mqh b/Indicators/Indi_Killzones.mqh index 5fc584d03..68cbbfb28 100644 --- a/Indicators/Indi_Killzones.mqh +++ b/Indicators/Indi_Killzones.mqh @@ -49,10 +49,7 @@ enum ENUM_INDI_KILLZONES_MODE { struct IndiKillzonesParams : IndicatorParams { ENUM_PP_TYPE method; // Pivot point calculation method. // Struct constructor. - IndiKillzonesParams(int _shift = 0, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) - : IndicatorParams(INDI_PIVOT, FINAL_INDI_KILLZONES_MODE_ENTRY, TYPE_FLOAT) { - SetDataValueRange(IDATA_RANGE_MIXED); - SetDataSourceType(IDATA_CHART); + IndiKillzonesParams(int _shift = 0, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) : IndicatorParams(INDI_PIVOT) { SetShift(_shift); tf = _tf; }; @@ -99,8 +96,12 @@ class Indi_Killzones : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_Killzones(IndiKillzonesParams &_p, IndicatorBase *_indi_src = NULL) - : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_Killzones(IndiKillzonesParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_CHART, + IndicatorData *_indi_src = NULL, int _indi_src_mode = 0) + : IndicatorTickOrCandleSource(_p, + IndicatorDataParams::GetInstance(FINAL_INDI_KILLZONES_MODE_ENTRY, TYPE_FLOAT, + _idstype, IDATA_RANGE_PRICE, _indi_src_mode), + _indi_src) {} Indi_Killzones(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_KILLZONES, _tf, _shift) {} @@ -111,7 +112,7 @@ class Indi_Killzones : public IndicatorTickOrCandleSource { float _value = FLT_MAX; int _index = (int)_mode / 2; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: // Builtin mode not supported. SetUserError(ERR_INVALID_PARAMETER); diff --git a/Indicators/Indi_MA.mqh b/Indicators/Indi_MA.mqh index cf6b14aed..2d6c37d31 100644 --- a/Indicators/Indi_MA.mqh +++ b/Indicators/Indi_MA.mqh @@ -56,13 +56,8 @@ struct IndiMAParams : IndicatorParams { // Struct constructors. IndiMAParams(unsigned int _period = 13, int _ma_shift = 10, ENUM_MA_METHOD _ma_method = MODE_SMA, ENUM_APPLIED_PRICE _ap = PRICE_OPEN, int _shift = 0) - : period(_period), - ma_shift(_ma_shift), - ma_method(_ma_method), - applied_array(_ap), - IndicatorParams(INDI_MA, 1, TYPE_DOUBLE) { + : period(_period), ma_shift(_ma_shift), ma_method(_ma_method), applied_array(_ap), IndicatorParams(INDI_MA) { shift = _shift; - SetDataValueRange(IDATA_RANGE_PRICE); SetCustomIndicatorName("Examples\\Moving Average"); }; IndiMAParams(IndiMAParams &_params, ENUM_TIMEFRAMES _tf) { @@ -79,7 +74,11 @@ class Indi_MA : public IndicatorTickSource { /** * Class constructor. */ - Indi_MA(IndiMAParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickSource(_p, _indi_src) {} + Indi_MA(IndiMAParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickSource( + _p, IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_PRICE, _indi_src_mode), + _indi_src) {} Indi_MA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickSource(INDI_MA, _tf, _shift) {} /** @@ -91,7 +90,7 @@ class Indi_MA : public IndicatorTickSource { */ static double iMA(string _symbol, ENUM_TIMEFRAMES _tf, unsigned int _ma_period, unsigned int _ma_shift, ENUM_MA_METHOD _ma_method, ENUM_APPLIED_PRICE _applied_array, int _shift = 0, - IndicatorBase *_obj = NULL) { + IndicatorData *_obj = NULL) { #ifdef __MQL4__ return ::iMA(_symbol, _tf, _ma_period, _ma_shift, _ma_method, _applied_array, _shift); #else // __MQL5__ @@ -126,7 +125,7 @@ class Indi_MA : public IndicatorTickSource { /** * Calculates MA on another indicator. */ - static double iMAOnIndicator(IndicatorCalculateCache *cache, IndicatorBase *_indi, int indi_mode, + static double iMAOnIndicator(IndicatorCalculateCache *cache, IndicatorData *_indi, int indi_mode, string symbol, ENUM_TIMEFRAMES tf, unsigned int ma_period, unsigned int ma_shift, ENUM_MA_METHOD ma_method, // (MT4/MT5): MODE_SMA, MODE_EMA, MODE_SMMA, MODE_LWMA int shift = 0) { @@ -715,7 +714,7 @@ class Indi_MA : public IndicatorTickSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_MA::iMA(GetSymbol(), GetTf(), GetPeriod(), GetMAShift(), GetMAMethod(), GetAppliedPrice(), _ishift, THIS_PTR); @@ -726,10 +725,12 @@ class Indi_MA : public IndicatorTickSource { break; case IDATA_INDICATOR: // Calculating MA value from specified indicator. - _value = Indi_MA::iMAOnIndicator(GetCache(), GetDataSource(), GetDataSourceMode(), GetSymbol(), GetTf(), - GetPeriod(), GetMAShift(), GetMAMethod(), _ishift); + _value = Indi_MA::iMAOnIndicator(GetCache(), GetDataSource(), + Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_SRC_MODE)), GetSymbol(), + GetTf(), GetPeriod(), GetMAShift(), GetMAMethod(), _ishift); break; } + return _value; } diff --git a/Indicators/Indi_MACD.mqh b/Indicators/Indi_MACD.mqh index 445c9d8dd..4d9518d64 100644 --- a/Indicators/Indi_MACD.mqh +++ b/Indicators/Indi_MACD.mqh @@ -45,9 +45,8 @@ struct IndiMACDParams : IndicatorParams { ema_slow_period(_esp), signal_period(_sp), applied_price(_ap), - IndicatorParams(INDI_MACD, FINAL_SIGNAL_LINE_ENTRY, TYPE_DOUBLE) { + IndicatorParams(INDI_MACD) { shift = _shift; - SetDataValueRange(IDATA_RANGE_RANGE); SetCustomIndicatorName("Examples\\MACD"); }; IndiMACDParams(IndiMACDParams &_params, ENUM_TIMEFRAMES _tf) { @@ -64,7 +63,12 @@ class Indi_MACD : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_MACD(IndiMACDParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_MACD(IndiMACDParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource(_p, + IndicatorDataParams::GetInstance(FINAL_SIGNAL_LINE_ENTRY, TYPE_DOUBLE, _idstype, + IDATA_RANGE_RANGE, _indi_src_mode), + _indi_src) {} Indi_MACD(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_MACD, _tf, _shift) {} @@ -79,7 +83,7 @@ class Indi_MACD : public IndicatorTickOrCandleSource { string _symbol, ENUM_TIMEFRAMES _tf, unsigned int _ema_fast_period, unsigned int _ema_slow_period, unsigned int _signal_period, ENUM_APPLIED_PRICE _applied_price, ENUM_SIGNAL_LINE _mode = LINE_MAIN, // (MT4/MT5 _mode): 0 - MODE_MAIN/MAIN_LINE, 1 - MODE_SIGNAL/SIGNAL_LINE - int _shift = 0, IndicatorBase *_obj = NULL) { + int _shift = 0, IndicatorData *_obj = NULL) { #ifdef __MQL4__ return ::iMACD(_symbol, _tf, _ema_fast_period, _ema_slow_period, _signal_period, _applied_price, _mode, _shift); #else // __MQL5__ @@ -118,7 +122,7 @@ class Indi_MACD : public IndicatorTickOrCandleSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = LINE_MAIN, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_MACD::iMACD(GetSymbol(), GetTf(), GetEmaFastPeriod(), GetEmaSlowPeriod(), GetSignalPeriod(), GetAppliedPrice(), (ENUM_SIGNAL_LINE)_mode, _ishift, THIS_PTR); diff --git a/Indicators/Indi_MFI.mqh b/Indicators/Indi_MFI.mqh index f2ad316b1..2d8b4a800 100644 --- a/Indicators/Indi_MFI.mqh +++ b/Indicators/Indi_MFI.mqh @@ -37,9 +37,8 @@ struct IndiMFIParams : IndicatorParams { ENUM_APPLIED_VOLUME applied_volume; // Ignored in MT4. // Struct constructors. IndiMFIParams(unsigned int _ma_period = 14, ENUM_APPLIED_VOLUME _av = VOLUME_TICK, int _shift = 0) - : ma_period(_ma_period), applied_volume(_av), IndicatorParams(INDI_MFI, 1, TYPE_DOUBLE) { + : ma_period(_ma_period), applied_volume(_av), IndicatorParams(INDI_MFI) { shift = _shift; - SetDataValueRange(IDATA_RANGE_RANGE); SetCustomIndicatorName("Examples\\MFI"); }; IndiMFIParams(IndiMFIParams &_params, ENUM_TIMEFRAMES _tf) { @@ -56,7 +55,11 @@ class Indi_MFI : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_MFI(IndiMFIParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_MFI(IndiMFIParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_RANGE, _indi_src_mode), + _indi_src) {} Indi_MFI(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_MFI, _tf, _shift) {} /** @@ -67,7 +70,7 @@ class Indi_MFI : public IndicatorTickOrCandleSource { * - https://www.mql5.com/en/docs/indicators/imfi */ static double iMFI(string _symbol, ENUM_TIMEFRAMES _tf, unsigned int _period, int _shift = 0, - IndicatorBase *_obj = NULL) { + IndicatorData *_obj = NULL) { #ifdef __MQL4__ return ::iMFI(_symbol, _tf, _period, _shift); #else // __MQL5__ @@ -114,7 +117,7 @@ class Indi_MFI : public IndicatorTickOrCandleSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: #ifdef __MQL4__ _value = Indi_MFI::iMFI(GetSymbol(), GetTf(), GetPeriod(), _ishift); diff --git a/Indicators/Indi_MassIndex.mqh b/Indicators/Indi_MassIndex.mqh index b541f236e..dbd06b000 100644 --- a/Indicators/Indi_MassIndex.mqh +++ b/Indicators/Indi_MassIndex.mqh @@ -33,10 +33,9 @@ struct IndiMassIndexParams : IndicatorParams { int sum_period; // Struct constructor. IndiMassIndexParams(int _period = 9, int _second_period = 9, int _sum_period = 25, int _shift = 0) - : IndicatorParams(INDI_MASS_INDEX, 1, TYPE_DOUBLE) { + : IndicatorParams(INDI_MASS_INDEX) { period = _period; second_period = _second_period; - SetDataValueRange(IDATA_RANGE_MIXED); SetCustomIndicatorName("Examples\\MI"); shift = _shift; sum_period = _sum_period; @@ -55,8 +54,11 @@ class Indi_MassIndex : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_MassIndex(IndiMassIndexParams &_p, IndicatorBase *_indi_src = NULL) - : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_MassIndex(IndiMassIndexParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, + IndicatorData *_indi_src = NULL, int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_MIXED, _indi_src_mode), + _indi_src){}; Indi_MassIndex(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_MASS_INDEX, _tf, _shift){}; @@ -64,7 +66,7 @@ class Indi_MassIndex : public IndicatorTickOrCandleSource { * Built-in version of Mass Index. */ static double iMI(string _symbol, ENUM_TIMEFRAMES _tf, int _period, int _second_period, int _sum_period, - int _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) { + int _mode = 0, int _shift = 0, IndicatorData *_obj = NULL) { INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG( _symbol, _tf, Util::MakeKey("Indi_MassIndex", _period, _second_period, _sum_period)); return iMIOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _period, _second_period, _sum_period, _mode, _shift, @@ -96,9 +98,9 @@ class Indi_MassIndex : public IndicatorTickOrCandleSource { /** * On-indicator version of Mass Index. */ - static double iMIOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _period, + static double iMIOnIndicator(IndicatorData *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _period, int _second_period, int _sum_period, int _mode = 0, int _shift = 0, - IndicatorBase *_obj = NULL) { + IndicatorData *_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)); @@ -170,7 +172,7 @@ class Indi_MassIndex : public IndicatorTickOrCandleSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_MassIndex::iMI(GetSymbol(), GetTf(), /*[*/ GetPeriod(), GetSecondPeriod(), GetSumPeriod() /*]*/, _mode, _ishift, THIS_PTR); diff --git a/Indicators/Indi_Momentum.mqh b/Indicators/Indi_Momentum.mqh index 7dc6d01ea..e228e8224 100644 --- a/Indicators/Indi_Momentum.mqh +++ b/Indicators/Indi_Momentum.mqh @@ -47,9 +47,8 @@ struct IndiMomentumParams : IndicatorParams { ENUM_APPLIED_PRICE applied_price; // Struct constructors. IndiMomentumParams(unsigned int _period = 12, ENUM_APPLIED_PRICE _ap = PRICE_OPEN, int _shift = 0) - : period(_period), applied_price(_ap), IndicatorParams(INDI_MOMENTUM, 1, TYPE_DOUBLE) { + : period(_period), applied_price(_ap), IndicatorParams(INDI_MOMENTUM) { shift = _shift; - SetDataValueRange(IDATA_RANGE_MIXED); SetCustomIndicatorName("Examples\\Momentum"); }; IndiMomentumParams(IndiMomentumParams &_params, ENUM_TIMEFRAMES _tf) { @@ -66,7 +65,11 @@ class Indi_Momentum : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_Momentum(IndiMomentumParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_Momentum(IndiMomentumParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, + IndicatorData *_indi_src = NULL, int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_MIXED, _indi_src_mode), + _indi_src) {} Indi_Momentum(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_MOMENTUM, _tf, _shift) {} @@ -78,7 +81,7 @@ class Indi_Momentum : public IndicatorTickOrCandleSource { * - https://www.mql5.com/en/docs/indicators/imomentum */ static double iMomentum(string _symbol, ENUM_TIMEFRAMES _tf, unsigned int _period, ENUM_APPLIED_PRICE _ap, - int _shift = 0, IndicatorBase *_obj = NULL) { + int _shift = 0, IndicatorData *_obj = NULL) { #ifdef __MQL4__ return ::iMomentum(_symbol, _tf, _period, _ap, _shift); #else // __MQL5__ @@ -110,7 +113,7 @@ class Indi_Momentum : public IndicatorTickOrCandleSource { #endif } - static double iMomentumOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, unsigned int _period, + static double iMomentumOnIndicator(IndicatorData *_indi, string _symbol, ENUM_TIMEFRAMES _tf, unsigned int _period, int _mode, int _shift = 0) { double _indi_value_buffer[]; IndicatorDataEntry _entry(_indi.GetModeCount()); @@ -144,7 +147,7 @@ class Indi_Momentum : public IndicatorTickOrCandleSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: // @fixit Somehow shift isn't used neither in MT4 nor MT5. _value = Indi_Momentum::iMomentum(GetSymbol(), GetTf(), GetPeriod(), GetAppliedPrice(), iparams.shift + _ishift, @@ -159,7 +162,8 @@ class Indi_Momentum : public IndicatorTickOrCandleSource { // @fixit Somehow shift isn't used neither in MT4 nor MT5. _value = Indi_Momentum::iMomentumOnIndicator(GetDataSource(), GetSymbol(), GetTf(), GetPeriod(), - GetDataSourceMode(), iparams.shift + _shift); + Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_SRC_MODE)), + iparams.shift + _shift); if (iparams.is_draw) { draw.DrawLineTo(StringFormat("%s", GetName()), GetBarTime(iparams.shift + _shift), _value, 1); } diff --git a/Indicators/Indi_OBV.mqh b/Indicators/Indi_OBV.mqh index dddc611e3..7410d831a 100644 --- a/Indicators/Indi_OBV.mqh +++ b/Indicators/Indi_OBV.mqh @@ -36,21 +36,16 @@ struct IndiOBVParams : IndicatorParams { ENUM_APPLIED_PRICE applied_price; // MT4 only. ENUM_APPLIED_VOLUME applied_volume; // MT5 only. // Struct constructors. - IndiOBVParams(int _shift = 0) : IndicatorParams(INDI_OBV, 1, TYPE_DOUBLE) { + IndiOBVParams(int _shift = 0) : IndicatorParams(INDI_OBV) { shift = _shift; - SetDataValueRange(IDATA_RANGE_MIXED); SetCustomIndicatorName("Examples\\OBV"); applied_price = PRICE_CLOSE; applied_volume = VOLUME_TICK; } - IndiOBVParams(ENUM_APPLIED_VOLUME _av, int _shift = 0) - : applied_volume(_av), IndicatorParams(INDI_OBV, 1, TYPE_DOUBLE) { - max_modes = 1; + IndiOBVParams(ENUM_APPLIED_VOLUME _av, int _shift = 0) : applied_volume(_av), IndicatorParams(INDI_OBV) { shift = _shift; }; - IndiOBVParams(ENUM_APPLIED_PRICE _ap, int _shift = 0) - : applied_price(_ap), IndicatorParams(INDI_OBV, 1, TYPE_DOUBLE) { - max_modes = 1; + IndiOBVParams(ENUM_APPLIED_PRICE _ap, int _shift = 0) : applied_price(_ap), IndicatorParams(INDI_OBV) { shift = _shift; }; IndiOBVParams(IndiOBVParams &_params, ENUM_TIMEFRAMES _tf) { @@ -67,7 +62,11 @@ class Indi_OBV : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_OBV(IndiOBVParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_OBV(IndiOBVParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_MIXED, _indi_src_mode), + _indi_src) {} Indi_OBV(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_OBV, _tf, _shift) {} /** @@ -83,7 +82,7 @@ class Indi_OBV : public IndicatorTickOrCandleSource { #else ENUM_APPLIED_VOLUME _applied = VOLUME_TICK, // MT5 only. #endif - int _shift = 0, IndicatorBase *_obj = NULL) { + int _shift = 0, IndicatorData *_obj = NULL) { #ifdef __MQL4__ return ::iOBV(_symbol, _tf, _applied, _shift); #else // __MQL5__ @@ -121,7 +120,7 @@ class Indi_OBV : public IndicatorTickOrCandleSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: #ifdef __MQL4__ _value = Indi_OBV::iOBV(GetSymbol(), GetTf(), GetAppliedPrice(), _ishift); diff --git a/Indicators/Indi_OsMA.mqh b/Indicators/Indi_OsMA.mqh index 22520384c..0a81f2308 100644 --- a/Indicators/Indi_OsMA.mqh +++ b/Indicators/Indi_OsMA.mqh @@ -44,9 +44,8 @@ struct IndiOsMAParams : IndicatorParams { ema_slow_period(_esp), signal_period(_sp), applied_price(_ap), - IndicatorParams(INDI_OSMA, 1, TYPE_DOUBLE) { + IndicatorParams(INDI_OSMA) { shift = _shift; - SetDataValueRange(IDATA_RANGE_MIXED); SetCustomIndicatorName("Examples\\OsMA"); }; IndiOsMAParams(IndiOsMAParams &_params, ENUM_TIMEFRAMES _tf) { @@ -63,7 +62,11 @@ class Indi_OsMA : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_OsMA(IndiOsMAParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_OsMA(IndiOsMAParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_MIXED, _indi_src_mode), + _indi_src) {} Indi_OsMA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_OSMA, _tf, _shift) {} @@ -76,7 +79,7 @@ class Indi_OsMA : public IndicatorTickOrCandleSource { */ static double iOsMA(string _symbol, ENUM_TIMEFRAMES _tf, int _ema_fast_period, int _ema_slow_period, int _signal_period, ENUM_APPLIED_PRICE _applied_price, int _shift = 0, - IndicatorBase *_obj = NULL) { + IndicatorData *_obj = NULL) { #ifdef __MQL4__ return ::iOsMA(_symbol, _tf, _ema_fast_period, _ema_slow_period, _signal_period, _applied_price, _shift); #else // __MQL5__ @@ -115,7 +118,7 @@ class Indi_OsMA : public IndicatorTickOrCandleSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); double _value = EMPTY_VALUE; - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_OsMA::iOsMA(GetSymbol(), GetTf(), GetEmaFastPeriod(), GetEmaSlowPeriod(), GetSignalPeriod(), GetAppliedPrice(), _ishift, THIS_PTR); diff --git a/Indicators/Indi_Pivot.mqh b/Indicators/Indi_Pivot.mqh index 75a737974..e9f98d642 100644 --- a/Indicators/Indi_Pivot.mqh +++ b/Indicators/Indi_Pivot.mqh @@ -30,9 +30,8 @@ struct IndiPivotParams : IndicatorParams { ENUM_PP_TYPE method; // Pivot point calculation method. // Struct constructor. - IndiPivotParams(ENUM_PP_TYPE _method = PP_CLASSIC, int _shift = 0) : IndicatorParams(INDI_PIVOT, 9, TYPE_FLOAT) { + IndiPivotParams(ENUM_PP_TYPE _method = PP_CLASSIC, int _shift = 0) : IndicatorParams(INDI_PIVOT) { method = _method; - SetDataValueRange(IDATA_RANGE_MIXED); shift = _shift; }; IndiPivotParams(IndiPivotParams& _params, ENUM_TIMEFRAMES _tf) { @@ -45,14 +44,29 @@ struct IndiPivotParams : IndicatorParams { * Implements Pivot Detector. */ class Indi_Pivot : public IndicatorTickOrCandleSource { + protected: + /* Protected methods */ + + /** + * Initialize. + */ + void Init() { Set(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES), 9); } + public: /** * Class constructor. */ - Indi_Pivot(IndiPivotParams& _p, IndicatorBase* _indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_Pivot(IndiPivotParams& _p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData* _indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(9, TYPE_FLOAT, _idstype, IDATA_RANGE_MIXED, _indi_src_mode), + _indi_src) { + Init(); + }; Indi_Pivot(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_PIVOT, _tf, _shift) { iparams.tf = _tf; + Init(); }; /** @@ -72,7 +86,7 @@ class Indi_Pivot : public IndicatorTickOrCandleSource { BarOHLC _ohlc = GetOHLC(_ishift); _entry.timestamp = GetBarTime(_ishift); if (_ohlc.IsValid()) { - _entry.Resize(iparams.GetMaxModes()); + _entry.Resize(Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES))); _ohlc.GetPivots(GetMethod(), _entry.values[0].value.vflt, _entry.values[1].value.vflt, _entry.values[2].value.vflt, _entry.values[3].value.vflt, _entry.values[4].value.vflt, _entry.values[5].value.vflt, _entry.values[6].value.vflt, _entry.values[7].value.vflt, @@ -111,7 +125,7 @@ class Indi_Pivot : public IndicatorTickOrCandleSource { */ virtual bool IsValidEntry(IndicatorDataEntry& _entry) { bool _is_valid = Indicator::IsValidEntry(_entry); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: break; case IDATA_INDICATOR: @@ -139,7 +153,7 @@ class Indi_Pivot : public IndicatorTickOrCandleSource { */ BarOHLC GetOHLC(int _shift = 0) { BarOHLC _ohlc; - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: // In this mode, price is fetched from chart. _ohlc = Chart::GetOHLC(_shift); diff --git a/Indicators/Indi_PriceChannel.mqh b/Indicators/Indi_PriceChannel.mqh index 97fbe41d2..4d9729599 100644 --- a/Indicators/Indi_PriceChannel.mqh +++ b/Indicators/Indi_PriceChannel.mqh @@ -29,10 +29,8 @@ struct IndiPriceChannelParams : IndicatorParams { unsigned int period; // Struct constructor. - IndiPriceChannelParams(unsigned int _period = 22, int _shift = 0) - : IndicatorParams(INDI_PRICE_CHANNEL, 3, TYPE_DOUBLE) { + IndiPriceChannelParams(unsigned int _period = 22, int _shift = 0) : IndicatorParams(INDI_PRICE_CHANNEL) { period = _period; - SetDataValueRange(IDATA_RANGE_MIXED); SetCustomIndicatorName("Examples\\Price_Channel"); shift = _shift; }; @@ -50,8 +48,11 @@ class Indi_PriceChannel : public IndicatorTickOrCandleSource= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_PriceChannel::iPriceChannel(GetSymbol(), GetTf(), GetPeriod(), _mode, _ishift, THIS_PTR); break; diff --git a/Indicators/Indi_PriceFeeder.mqh b/Indicators/Indi_PriceFeeder.mqh index 9dfc075ea..0f0677de9 100644 --- a/Indicators/Indi_PriceFeeder.mqh +++ b/Indicators/Indi_PriceFeeder.mqh @@ -32,15 +32,14 @@ struct IndiPriceFeederParams : IndicatorParams { /** * Struct constructor. */ - IndiPriceFeederParams(int _shift = 0) : IndicatorParams(INDI_PRICE_FEEDER, 1, TYPE_DOUBLE) { shift = _shift; } + IndiPriceFeederParams(int _shift = 0) : IndicatorParams(INDI_PRICE_FEEDER) { shift = _shift; } /** * Struct constructor. * * @todo Use more modes (full OHCL). */ - IndiPriceFeederParams(const double& _price_data[], int _total = 0) - : IndicatorParams(INDI_PRICE_FEEDER, 1, TYPE_DOUBLE) { + IndiPriceFeederParams(const double& _price_data[], int _total = 0) : IndicatorParams(INDI_PRICE_FEEDER) { tf = PERIOD_CURRENT; ArrayCopy(price_data, _price_data, 0, 0, _total == 0 ? WHOLE_ARRAY : _total); }; @@ -58,8 +57,11 @@ class Indi_PriceFeeder : public IndicatorTickOrCandleSource::OnTick(); if (iparams.is_draw) { + int _max_modes = Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES)); IndicatorDataEntry _entry = GetEntry(0); - for (int i = 0; i < (int)iparams.GetMaxModes(); ++i) { + for (int i = 0; i < _max_modes; ++i) { draw.DrawLineTo(GetName() + "_" + IntegerToString(i), GetBarTime(0), _entry.values[i].GetDbl()); } } diff --git a/Indicators/Indi_PriceVolumeTrend.mqh b/Indicators/Indi_PriceVolumeTrend.mqh index 9f4899142..41e642607 100644 --- a/Indicators/Indi_PriceVolumeTrend.mqh +++ b/Indicators/Indi_PriceVolumeTrend.mqh @@ -30,9 +30,8 @@ struct IndiPriceVolumeTrendParams : IndicatorParams { ENUM_APPLIED_VOLUME applied_volume; // Struct constructor. IndiPriceVolumeTrendParams(ENUM_APPLIED_VOLUME _applied_volume = VOLUME_TICK, int _shift = 0) - : IndicatorParams(INDI_PRICE_VOLUME_TREND, 1, TYPE_DOUBLE) { + : IndicatorParams(INDI_PRICE_VOLUME_TREND) { applied_volume = _applied_volume; - SetDataValueRange(IDATA_RANGE_MIXED); SetCustomIndicatorName("Examples\\PVT"); shift = _shift; }; @@ -50,8 +49,11 @@ class Indi_PriceVolumeTrend : public IndicatorTickOrCandleSource= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_PriceVolumeTrend::iPVT(GetSymbol(), GetTf(), /*[*/ GetAppliedVolume() /*]*/, _mode, _ishift, THIS_PTR); diff --git a/Indicators/Indi_RS.mqh b/Indicators/Indi_RS.mqh index ef81af539..c564e6e6a 100644 --- a/Indicators/Indi_RS.mqh +++ b/Indicators/Indi_RS.mqh @@ -30,11 +30,8 @@ struct IndiRSParams : IndicatorParams { ENUM_APPLIED_VOLUME applied_volume; // Struct constructor. - IndiRSParams(ENUM_APPLIED_VOLUME _applied_volume = VOLUME_TICK, int _shift = 0) - : IndicatorParams(INDI_RS, 2, TYPE_DOUBLE) { + IndiRSParams(ENUM_APPLIED_VOLUME _applied_volume = VOLUME_TICK, int _shift = 0) : IndicatorParams(INDI_RS) { applied_volume = _applied_volume; - SetDataValueRange(IDATA_RANGE_MIXED); - SetDataSourceType(IDATA_MATH); shift = _shift; }; IndiRSParams(IndiRSParams &_params, ENUM_TIMEFRAMES _tf) { @@ -53,13 +50,19 @@ class Indi_RS : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_RS(IndiRSParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) { Init(); }; + Indi_RS(IndiRSParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_MATH, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(2, TYPE_DOUBLE, _idstype, IDATA_RANGE_PRICE_DIFF, _indi_src_mode), + _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) { + if (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE)) == IDATA_MATH) { IndiOHLCParams _iohlc_params(); // @todo Symbol should be already defined for a chart. // @todo If it's not, move initialization to GetValue()/GetEntry() method. @@ -82,7 +85,7 @@ class Indi_RS : public IndicatorTickOrCandleSource { */ virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_MATH: return imath[_mode].Ptr().GetEntryValue(); break; diff --git a/Indicators/Indi_RSI.mqh b/Indicators/Indi_RSI.mqh index c2fe083e1..fd212543c 100644 --- a/Indicators/Indi_RSI.mqh +++ b/Indicators/Indi_RSI.mqh @@ -51,10 +51,8 @@ struct IndiRSIParams : IndicatorParams { public: IndiRSIParams(int _period = 14, ENUM_APPLIED_PRICE _ap = PRICE_OPEN, int _shift = 0) - : applied_price(_ap), IndicatorParams(INDI_RSI, 1, TYPE_DOUBLE) { + : applied_price(_ap), IndicatorParams(INDI_RSI) { shift = _shift; - SetDataValueRange(IDATA_RANGE_RANGE); - // SetDataSourceType(IDATA_ICUSTOM); SetCustomIndicatorName("Examples\\RSI"); SetPeriod(_period); }; @@ -96,7 +94,11 @@ class Indi_RSI : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_RSI(IndiRSIParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_RSI(IndiRSIParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_RANGE, _indi_src_mode), + _indi_src) {} Indi_RSI(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_RSI, _tf, _shift) {} /** @@ -107,7 +109,7 @@ class Indi_RSI : public IndicatorTickOrCandleSource { * - https://www.mql5.com/en/docs/indicators/irsi */ static double iRSI(string _symbol = NULL, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, unsigned int _period = 14, - ENUM_APPLIED_PRICE _applied_price = PRICE_CLOSE, int _shift = 0, IndicatorBase *_obj = NULL) { + ENUM_APPLIED_PRICE _applied_price = PRICE_CLOSE, int _shift = 0, IndicatorData *_obj = NULL) { #ifdef __MQL4__ return ::iRSI(_symbol, _tf, _period, _applied_price, _shift); #else // __MQL5__ @@ -119,7 +121,7 @@ class Indi_RSI : public IndicatorTickOrCandleSource { * Calculates non-SMMA version of RSI on another indicator (uses iRSIOnArray). */ template - static double iRSIOnArrayOnIndicator(IndicatorBase *_indi, string _symbol = NULL, + static double iRSIOnArrayOnIndicator(IndicatorData *_indi, string _symbol = NULL, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, unsigned int _period = 14, ENUM_APPLIED_PRICE _applied_price = PRICE_CLOSE, int _shift = 0, Indi_RSI *_obj = NULL) { @@ -153,7 +155,7 @@ class Indi_RSI : public IndicatorTickOrCandleSource { * RSI values. To exactly replicate our RSI numbers, a formula will need at * least 250 data points." */ - static double iRSIOnIndicator(IndicatorBase *_indi, Indi_RSI *_obj, string _symbol = NULL, + static double iRSIOnIndicator(IndicatorData *_indi, Indi_RSI *_obj, string _symbol = NULL, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, unsigned int _period = 14, ENUM_APPLIED_PRICE _applied_price = PRICE_CLOSE, int _shift = 0) { long _bar_time_curr = _obj.GetBarTime(_shift); @@ -173,7 +175,7 @@ class Indi_RSI : public IndicatorTickOrCandleSource { RSIGainLossData last_data, new_data; unsigned int data_position; double diff; - int _mode = _obj.GetDataSourceMode(); + int _mode = _obj.Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_SRC_MODE)); if (!_obj.aux_data.KeyExists(_bar_time_prev, data_position)) { // No previous SMMA-based average gain and loss. Calculating SMA-based ones. @@ -293,7 +295,7 @@ class Indi_RSI : public IndicatorTickOrCandleSource { double _value = EMPTY_VALUE; double _res[]; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_RSI::iRSI(GetSymbol(), GetTf(), iparams.GetPeriod(), iparams.GetAppliedPrice(), _ishift, THIS_PTR); @@ -314,7 +316,7 @@ class Indi_RSI : public IndicatorTickOrCandleSource { /** * Provides built-in indicators whose can be used as data source. */ - virtual IndicatorBase *FetchDataSource(ENUM_INDICATOR_TYPE _id) { + virtual IndicatorData *FetchDataSource(ENUM_INDICATOR_TYPE _id) { if (_id == INDI_BANDS) { IndiBandsParams bands_params; return new Indi_Bands(bands_params); @@ -338,6 +340,6 @@ class Indi_RSI : public IndicatorTickOrCandleSource { return new Indi_StdDev(stddev_params); } - return IndicatorBase::FetchDataSource(_id); + return IndicatorData::FetchDataSource(_id); } }; diff --git a/Indicators/Indi_RVI.mqh b/Indicators/Indi_RVI.mqh index e19867e8a..4b1458276 100644 --- a/Indicators/Indi_RVI.mqh +++ b/Indicators/Indi_RVI.mqh @@ -35,10 +35,8 @@ double iRVI(string _symbol, int _tf, int _period, int _mode, int _shift) { struct IndiRVIParams : IndicatorParams { unsigned int period; // Struct constructors. - IndiRVIParams(unsigned int _period = 10, int _shift = 0) - : period(_period), IndicatorParams(INDI_RVI, FINAL_SIGNAL_LINE_ENTRY, TYPE_DOUBLE) { + IndiRVIParams(unsigned int _period = 10, int _shift = 0) : period(_period), IndicatorParams(INDI_RVI) { shift = _shift; - SetDataValueRange(IDATA_RANGE_MIXED); SetCustomIndicatorName("Examples\\RVI"); }; IndiRVIParams(IndiRVIParams &_params, ENUM_TIMEFRAMES _tf) { @@ -55,7 +53,12 @@ class Indi_RVI : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_RVI(const IndiRVIParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_RVI(const IndiRVIParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource(_p, + IndicatorDataParams::GetInstance(FINAL_SIGNAL_LINE_ENTRY, TYPE_DOUBLE, _idstype, + IDATA_RANGE_MIXED, _indi_src_mode), + _indi_src) {} Indi_RVI(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_RVI, _tf, _shift) {} /** @@ -68,7 +71,7 @@ class Indi_RVI : public IndicatorTickOrCandleSource { static double iRVI( string _symbol = NULL, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, unsigned int _period = 10, ENUM_SIGNAL_LINE _mode = LINE_MAIN, // (MT4/MT5): 0 - MODE_MAIN/MAIN_LINE, 1 - MODE_SIGNAL/SIGNAL_LINE - int _shift = 0, IndicatorBase *_obj = NULL) { + int _shift = 0, IndicatorData *_obj = NULL) { #ifdef __MQL4__ return ::iRVI(_symbol, _tf, _period, _mode, _shift); #else // __MQL5__ @@ -106,7 +109,7 @@ class Indi_RVI : public IndicatorTickOrCandleSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = LINE_MAIN, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_RVI::iRVI(GetSymbol(), GetTf(), GetPeriod(), (ENUM_SIGNAL_LINE)_mode, _ishift, THIS_PTR); break; diff --git a/Indicators/Indi_RateOfChange.mqh b/Indicators/Indi_RateOfChange.mqh index 2f0d5b061..a6c37dd26 100644 --- a/Indicators/Indi_RateOfChange.mqh +++ b/Indicators/Indi_RateOfChange.mqh @@ -31,9 +31,8 @@ struct IndiRateOfChangeParams : IndicatorParams { ENUM_APPLIED_PRICE applied_price; // Struct constructor. IndiRateOfChangeParams(int _period = 12, ENUM_APPLIED_PRICE _ap = PRICE_CLOSE, int _shift = 0) - : IndicatorParams(INDI_RATE_OF_CHANGE, 1, TYPE_DOUBLE) { + : IndicatorParams(INDI_RATE_OF_CHANGE) { applied_price = _ap; - SetDataValueRange(IDATA_RANGE_MIXED); SetCustomIndicatorName("Examples\\ROC"); period = _period; shift = _shift; @@ -52,8 +51,11 @@ class Indi_RateOfChange : public IndicatorTickOrCandleSource= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_RateOfChange::iROC(GetSymbol(), GetTf(), /*[*/ GetPeriod(), GetAppliedPrice() /*]*/, _mode, _ishift, THIS_PTR); diff --git a/Indicators/Indi_SAR.mqh b/Indicators/Indi_SAR.mqh index ba8d7c499..c8a36e4c9 100644 --- a/Indicators/Indi_SAR.mqh +++ b/Indicators/Indi_SAR.mqh @@ -37,9 +37,8 @@ struct IndiSARParams : IndicatorParams { double max; // Struct constructors. IndiSARParams(double _step = 0.02, double _max = 0.2, int _shift = 0) - : step(_step), max(_max), IndicatorParams(INDI_SAR, 1, TYPE_DOUBLE) { + : step(_step), max(_max), IndicatorParams(INDI_SAR) { shift = _shift; - SetDataValueRange(IDATA_RANGE_PRICE); // @fixit It draws single dot for each bar! SetCustomIndicatorName("Examples\\ParabolicSAR"); }; IndiSARParams(IndiSARParams &_params, ENUM_TIMEFRAMES _tf) { @@ -56,7 +55,11 @@ class Indi_SAR : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_SAR(IndiSARParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_SAR(IndiSARParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_PRICE, _indi_src_mode), + _indi_src) {} Indi_SAR(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_SAR, _tf, _shift) {} /** @@ -67,7 +70,7 @@ class Indi_SAR : public IndicatorTickOrCandleSource { * - https://www.mql5.com/en/docs/indicators/isar */ static double iSAR(string _symbol = NULL, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, double _step = 0.02, - double _max = 0.2, int _shift = 0, IndicatorBase *_obj = NULL) { + double _max = 0.2, int _shift = 0, IndicatorData *_obj = NULL) { #ifdef __MQL4__ return ::iSAR(_symbol, _tf, _step, _max, _shift); #else // __MQL5__ @@ -105,7 +108,7 @@ class Indi_SAR : public IndicatorTickOrCandleSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_SAR::iSAR(GetSymbol(), GetTf(), GetStep(), GetMax(), _ishift, THIS_PTR); break; diff --git a/Indicators/Indi_StdDev.mqh b/Indicators/Indi_StdDev.mqh index aa2e77603..563f68f80 100644 --- a/Indicators/Indi_StdDev.mqh +++ b/Indicators/Indi_StdDev.mqh @@ -59,9 +59,8 @@ struct IndiStdDevParams : IndicatorParams { ma_shift(_ma_shift), ma_method(_ma_method), applied_price(_ap), - IndicatorParams(INDI_STDDEV, 1, TYPE_DOUBLE) { + IndicatorParams(INDI_STDDEV) { shift = _shift; - SetDataValueRange(IDATA_RANGE_MIXED); SetCustomIndicatorName("Examples\\StdDev"); }; IndiStdDevParams(IndiStdDevParams &_params, ENUM_TIMEFRAMES _tf) { @@ -78,7 +77,11 @@ class Indi_StdDev : public IndicatorTickSource { /** * Class constructor. */ - Indi_StdDev(IndiStdDevParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickSource(_p, _indi_src) {} + Indi_StdDev(IndiStdDevParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickSource( + _p, IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_MIXED, _indi_src_mode), + _indi_src) {} Indi_StdDev(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickSource(INDI_STDDEV, _tf, _shift) {} /** @@ -89,7 +92,7 @@ class Indi_StdDev : public IndicatorTickSource { * - https://www.mql5.com/en/docs/indicators/istddev */ static double iStdDev(string _symbol, ENUM_TIMEFRAMES _tf, int _ma_period, int _ma_shift, ENUM_MA_METHOD _ma_method, - ENUM_APPLIED_PRICE _applied_price, int _shift = 0, IndicatorBase *_obj = NULL) { + ENUM_APPLIED_PRICE _applied_price, int _shift = 0, IndicatorData *_obj = NULL) { #ifdef __MQL4__ return ::iStdDev(_symbol, _tf, _ma_period, _ma_shift, _ma_method, _applied_price, _shift); #else // __MQL5__ @@ -124,13 +127,13 @@ class Indi_StdDev : public IndicatorTickSource { /** * Note that this method operates on current price (set by _applied_price). */ - static double iStdDevOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _ma_period, + static double iStdDevOnIndicator(IndicatorData *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _ma_period, int _ma_shift, ENUM_APPLIED_PRICE _applied_price, int _shift = 0, Indi_StdDev *_obj = NULL) { double _indi_value_buffer[]; double _std_dev; int i; - int _mode = _obj != NULL ? _obj.GetDataSourceMode() : 0; + int _mode = _obj != NULL ? _obj.Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_SRC_MODE)) : 0; ArrayResize(_indi_value_buffer, _ma_period); @@ -230,15 +233,14 @@ class Indi_StdDev : public IndicatorTickSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_StdDev::iStdDev(GetSymbol(), GetTf(), GetMAPeriod(), GetMAShift(), GetMAMethod(), 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, - _ishift); + _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.GetCustomIndicatorName(), /*[*/ GetMAPeriod(), + GetMAShift(), GetMAMethod() /*]*/, 0, _ishift); break; case IDATA_INDICATOR: _value = Indi_StdDev::iStdDevOnIndicator(GetDataSource(), GetSymbol(), GetTf(), GetMAPeriod(), GetMAShift(), diff --git a/Indicators/Indi_Stochastic.mqh b/Indicators/Indi_Stochastic.mqh index f93c4cbce..3a5ec7444 100644 --- a/Indicators/Indi_Stochastic.mqh +++ b/Indicators/Indi_Stochastic.mqh @@ -48,9 +48,8 @@ struct IndiStochParams : IndicatorParams { slowing(_slowing), ma_method(_ma_method), price_field(_pf), - IndicatorParams(INDI_STOCHASTIC, FINAL_SIGNAL_LINE_ENTRY, TYPE_DOUBLE) { + IndicatorParams(INDI_STOCHASTIC) { shift = _shift; - SetDataValueRange(IDATA_RANGE_RANGE); SetCustomIndicatorName("Examples\\Stochastic"); }; IndiStochParams(IndiStochParams &_params, ENUM_TIMEFRAMES _tf) { @@ -67,7 +66,12 @@ class Indi_Stochastic : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_Stochastic(IndiStochParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_Stochastic(IndiStochParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource(_p, + IndicatorDataParams::GetInstance(FINAL_SIGNAL_LINE_ENTRY, TYPE_DOUBLE, _idstype, + IDATA_RANGE_RANGE, _indi_src_mode), + _indi_src) {} Indi_Stochastic(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_STOCHASTIC, _tf, _shift) {} @@ -84,7 +88,7 @@ class Indi_Stochastic : public IndicatorTickOrCandleSource { ENUM_STO_PRICE _price_field, // (MT4 _price_field): 0 - Low/High, 1 - Close/Close // (MT5 _price_field): STO_LOWHIGH - Low/High, STO_CLOSECLOSE - Close/Close int _mode, // (MT4): 0 - MODE_MAIN/MAIN_LINE, 1 - MODE_SIGNAL/SIGNAL_LINE - int _shift = 0, IndicatorBase *_obj = NULL) { + int _shift = 0, IndicatorData *_obj = NULL) { #ifdef __MQL4__ return ::iStochastic(_symbol, _tf, _kperiod, _dperiod, _slowing, _ma_method, _price_field, _mode, _shift); #else // __MQL5__ @@ -123,7 +127,7 @@ class Indi_Stochastic : public IndicatorTickOrCandleSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = LINE_MAIN, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_Stochastic::iStochastic(GetSymbol(), GetTf(), GetKPeriod(), GetDPeriod(), GetSlowing(), GetMAMethod(), GetPriceField(), _mode, _ishift, THIS_PTR); diff --git a/Indicators/Indi_TEMA.mqh b/Indicators/Indi_TEMA.mqh index 5954a9804..73c71241c 100644 --- a/Indicators/Indi_TEMA.mqh +++ b/Indicators/Indi_TEMA.mqh @@ -33,9 +33,8 @@ struct IndiTEMAParams : IndicatorParams { ENUM_APPLIED_PRICE applied_price; // Struct constructor. IndiTEMAParams(int _period = 14, int _tema_shift = 0, ENUM_APPLIED_PRICE _ap = PRICE_CLOSE, int _shift = 0) - : IndicatorParams(INDI_TEMA, 1, TYPE_DOUBLE) { + : IndicatorParams(INDI_TEMA) { applied_price = _ap; - SetDataValueRange(IDATA_RANGE_MIXED); SetCustomIndicatorName("Examples\\TEMA"); period = _period; shift = _shift; @@ -55,7 +54,11 @@ class Indi_TEMA : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_TEMA(IndiTEMAParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_TEMA(IndiTEMAParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_MIXED, _indi_src_mode), + _indi_src){}; Indi_TEMA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_TEMA, _tf, _shift){}; @@ -98,9 +101,9 @@ class Indi_TEMA : public IndicatorTickOrCandleSource { /** * On-indicator version of TEMA. */ - static double iTEMAOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _ma_period, + static double iTEMAOnIndicator(IndicatorData *_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) { + IndicatorData *_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)); @@ -142,7 +145,7 @@ class Indi_TEMA : public IndicatorTickOrCandleSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_TEMA::iTEMA(GetSymbol(), GetTf(), /*[*/ GetPeriod(), GetTEMAShift(), GetAppliedPrice() /*]*/, 0, _ishift, THIS_PTR); diff --git a/Indicators/Indi_TRIX.mqh b/Indicators/Indi_TRIX.mqh index 86caabb0d..c8be21d65 100644 --- a/Indicators/Indi_TRIX.mqh +++ b/Indicators/Indi_TRIX.mqh @@ -32,10 +32,8 @@ struct IndiTRIXParams : IndicatorParams { unsigned int tema_shift; ENUM_APPLIED_PRICE applied_price; // Struct constructor. - IndiTRIXParams(int _period = 14, ENUM_APPLIED_PRICE _ap = PRICE_CLOSE, int _shift = 0) - : IndicatorParams(INDI_TRIX, 1, TYPE_DOUBLE) { + IndiTRIXParams(int _period = 14, ENUM_APPLIED_PRICE _ap = PRICE_CLOSE, int _shift = 0) : IndicatorParams(INDI_TRIX) { applied_price = _ap; - SetDataValueRange(IDATA_RANGE_MIXED); SetCustomIndicatorName("Examples\\TRIX"); period = _period; shift = _shift; @@ -54,7 +52,11 @@ class Indi_TRIX : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_TRIX(IndiTRIXParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_TRIX(IndiTRIXParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_MIXED, _indi_src_mode), + _indi_src){}; Indi_TRIX(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_TRIX, _tf, _shift){}; @@ -62,7 +64,7 @@ class Indi_TRIX : public IndicatorTickOrCandleSource { * Built-in version of TriX. */ static double iTriX(string _symbol, ENUM_TIMEFRAMES _tf, int _ma_period, ENUM_APPLIED_PRICE _ap, int _mode = 0, - int _shift = 0, IndicatorBase *_obj = NULL) { + int _shift = 0, IndicatorData *_obj = NULL) { #ifdef __MQL5__ INDICATOR_BUILTIN_CALL_AND_RETURN(::iTriX(_symbol, _tf, _ma_period, _ap), _mode, _shift); #else @@ -97,8 +99,8 @@ class Indi_TRIX : public IndicatorTickOrCandleSource { /** * 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) { + static double iTriXOnIndicator(IndicatorData *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _ma_period, + ENUM_APPLIED_PRICE _ap, int _mode = 0, int _shift = 0, IndicatorData *_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); @@ -141,7 +143,7 @@ class Indi_TRIX : public IndicatorTickOrCandleSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_TRIX::iTriX(GetSymbol(), GetTf(), /*[*/ GetPeriod(), GetAppliedPrice() /*]*/, _mode, _ishift, THIS_PTR); diff --git a/Indicators/Indi_UltimateOscillator.mqh b/Indicators/Indi_UltimateOscillator.mqh index 98a7f9e1f..906a79de3 100644 --- a/Indicators/Indi_UltimateOscillator.mqh +++ b/Indicators/Indi_UltimateOscillator.mqh @@ -29,9 +29,9 @@ // Structs. struct IndiUltimateOscillatorParams : IndicatorParams { - Ref indi_atr_fast; - Ref indi_atr_middle; - Ref indi_atr_slow; + Ref indi_atr_fast; + Ref indi_atr_middle; + Ref indi_atr_slow; int fast_period; int middle_period; int slow_period; @@ -42,12 +42,11 @@ struct IndiUltimateOscillatorParams : IndicatorParams { // Struct constructor. IndiUltimateOscillatorParams(int _fast_period = 7, int _middle_period = 14, int _slow_period = 28, int _fast_k = 4, int _middle_k = 2, int _slow_k = 1, int _shift = 0) - : IndicatorParams(INDI_ULTIMATE_OSCILLATOR, 1, TYPE_DOUBLE) { + : IndicatorParams(INDI_ULTIMATE_OSCILLATOR) { fast_k = _fast_k; fast_period = _fast_period; middle_k = _middle_k; middle_period = _middle_period; - SetDataValueRange(IDATA_RANGE_MIXED); SetCustomIndicatorName("Examples\\Ultimate_Oscillator"); shift = _shift; slow_k = _slow_k; @@ -67,8 +66,11 @@ class Indi_UltimateOscillator : public IndicatorTickOrCandleSource *_cache, IndicatorBase *_indi_atr_fast, - IndicatorBase *_indi_atr_middle, IndicatorBase *_indi_atr_slow, bool _recalculate = false) { + IndicatorCalculateCache *_cache, IndicatorData *_indi_atr_fast, + IndicatorData *_indi_atr_middle, IndicatorData *_indi_atr_slow, bool _recalculate = false) { _cache.SetPriceBuffer(_open, _high, _low, _close); if (!_cache.HasBuffers()) { @@ -119,9 +121,9 @@ class Indi_UltimateOscillator : public IndicatorTickOrCandleSource= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_UltimateOscillator::iUO(GetSymbol(), GetTf(), /*[*/ GetFastPeriod(), GetMiddlePeriod(), GetSlowPeriod(), GetFastK(), GetMiddleK(), GetSlowK() /*]*/, _mode, diff --git a/Indicators/Indi_VIDYA.mqh b/Indicators/Indi_VIDYA.mqh index 4e98a6254..cf799aa28 100644 --- a/Indicators/Indi_VIDYA.mqh +++ b/Indicators/Indi_VIDYA.mqh @@ -35,11 +35,10 @@ struct IndiVIDYAParams : IndicatorParams { // Struct constructor. IndiVIDYAParams(unsigned int _cmo_period = 9, unsigned int _ma_period = 14, unsigned int _vidya_shift = 0, ENUM_APPLIED_PRICE _ap = PRICE_CLOSE, int _shift = 0) - : IndicatorParams(INDI_VIDYA, 1, TYPE_DOUBLE) { + : IndicatorParams(INDI_VIDYA) { applied_price = _ap; cmo_period = _cmo_period; ma_period = _ma_period; - SetDataValueRange(IDATA_RANGE_MIXED); SetCustomIndicatorName("Examples\\VIDYA"); shift = _shift; vidya_shift = _vidya_shift; @@ -58,7 +57,11 @@ class Indi_VIDYA : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_VIDYA(IndiVIDYAParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_VIDYA(IndiVIDYAParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_MIXED, _indi_src_mode), + _indi_src){}; Indi_VIDYA(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_VIDYA, _tf, _shift){}; @@ -66,7 +69,7 @@ class Indi_VIDYA : public IndicatorTickOrCandleSource { * Built-in version of iVIDyA. */ static double iVIDyA(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) { + ENUM_APPLIED_PRICE _ap, int _mode = 0, int _shift = 0, IndicatorData *_obj = NULL) { #ifdef __MQL5__ INDICATOR_BUILTIN_CALL_AND_RETURN(::iVIDyA(_symbol, _tf, _cmo_period, _ema_period, _ma_shift, _ap), _mode, _shift); #else @@ -102,9 +105,9 @@ class Indi_VIDYA : public IndicatorTickOrCandleSource { /** * On-indicator version of VIDya indicator. */ - static double iVIDyAOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _cmo_period, + static double iVIDyAOnIndicator(IndicatorData *_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) { + IndicatorData *_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)); @@ -164,7 +167,7 @@ class Indi_VIDYA : public IndicatorTickOrCandleSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_VIDYA::iVIDyA(GetSymbol(), GetTf(), /*[*/ GetCMOPeriod(), GetMAPeriod(), GetVIDYAShift(), GetAppliedPrice() /*]*/, 0, _ishift, THIS_PTR); diff --git a/Indicators/Indi_VROC.mqh b/Indicators/Indi_VROC.mqh index cacf2861c..98433c611 100644 --- a/Indicators/Indi_VROC.mqh +++ b/Indicators/Indi_VROC.mqh @@ -31,10 +31,9 @@ struct IndiVROCParams : IndicatorParams { ENUM_APPLIED_VOLUME applied_volume; // Struct constructor. IndiVROCParams(unsigned int _period = 25, ENUM_APPLIED_VOLUME _applied_volume = VOLUME_TICK, int _shift = 0) - : IndicatorParams(INDI_VROC, 1, TYPE_DOUBLE) { + : IndicatorParams(INDI_VROC) { applied_volume = _applied_volume; period = _period; - SetDataValueRange(IDATA_RANGE_MIXED); SetCustomIndicatorName("Examples\\VROC"); shift = _shift; }; @@ -52,7 +51,11 @@ class Indi_VROC : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_VROC(IndiVROCParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_VROC(IndiVROCParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_MIXED, _indi_src_mode), + _indi_src){}; Indi_VROC(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_VROC, _tf, _shift){}; @@ -60,7 +63,7 @@ class Indi_VROC : public IndicatorTickOrCandleSource { * Built-in version of VROC. */ static double iVROC(string _symbol, ENUM_TIMEFRAMES _tf, int _period, ENUM_APPLIED_VOLUME _av, int _mode = 0, - int _shift = 0, IndicatorBase *_obj = NULL) { + int _shift = 0, IndicatorData *_obj = NULL) { INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG(_symbol, _tf, Util::MakeKey("Indi_VROC", _period, (int)_av)); return iVROCOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _period, _av, _mode, _shift, _cache); } @@ -89,8 +92,8 @@ class Indi_VROC : public IndicatorTickOrCandleSource { /** * 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) { + static double iVROCOnIndicator(IndicatorData *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _period, + ENUM_APPLIED_VOLUME _av, int _mode = 0, int _shift = 0, IndicatorData *_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); @@ -144,7 +147,7 @@ class Indi_VROC : public IndicatorTickOrCandleSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_VROC::iVROC(GetSymbol(), GetTf(), /*[*/ GetPeriod(), GetAppliedVolume() /*]*/, _mode, _ishift, THIS_PTR); diff --git a/Indicators/Indi_Volumes.mqh b/Indicators/Indi_Volumes.mqh index c46671424..46a12532c 100644 --- a/Indicators/Indi_Volumes.mqh +++ b/Indicators/Indi_Volumes.mqh @@ -29,12 +29,9 @@ struct IndiVolumesParams : IndicatorParams { ENUM_APPLIED_VOLUME applied_volume; // Struct constructor. - IndiVolumesParams(ENUM_APPLIED_VOLUME _applied_volume = VOLUME_TICK, int _shift = 0) - : IndicatorParams(INDI_VOLUMES, 2, TYPE_DOUBLE) { + IndiVolumesParams(ENUM_APPLIED_VOLUME _applied_volume = VOLUME_TICK, int _shift = 0) : IndicatorParams(INDI_VOLUMES) { applied_volume = _applied_volume; - SetDataValueRange(IDATA_RANGE_MIXED); SetCustomIndicatorName("Examples\\Volumes"); - SetDataSourceType(IDATA_BUILTIN); shift = _shift; }; IndiVolumesParams(IndiVolumesParams &_params, ENUM_TIMEFRAMES _tf) { @@ -51,7 +48,11 @@ class Indi_Volumes : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_Volumes(IndiVolumesParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_Volumes(IndiVolumesParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(2, TYPE_DOUBLE, _idstype, IDATA_RANGE_MIXED, _indi_src_mode), + _indi_src){}; Indi_Volumes(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_VOLUMES, _tf, _shift){}; @@ -59,7 +60,7 @@ class Indi_Volumes : public IndicatorTickOrCandleSource { * Built-in version of Volumes. */ static double iVolumes(string _symbol, ENUM_TIMEFRAMES _tf, ENUM_APPLIED_VOLUME _av, int _mode = 0, int _shift = 0, - IndicatorBase *_obj = NULL) { + IndicatorData *_obj = NULL) { INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG(_symbol, _tf, Util::MakeKey("Indi_Volumes", (int)_av)); return iVolumesOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _av, _mode, _shift, _cache); } @@ -88,8 +89,8 @@ class Indi_Volumes : public IndicatorTickOrCandleSource { /** * 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) { + static double iVolumesOnIndicator(IndicatorData *_indi, string _symbol, ENUM_TIMEFRAMES _tf, ENUM_APPLIED_VOLUME _av, + int _mode = 0, int _shift = 0, IndicatorData *_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); @@ -138,7 +139,7 @@ class Indi_Volumes : public IndicatorTickOrCandleSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_Volumes::iVolumes(GetSymbol(), GetTf(), /*[*/ GetAppliedVolume() /*]*/, _mode, _ishift, THIS_PTR); break; diff --git a/Indicators/Indi_WPR.mqh b/Indicators/Indi_WPR.mqh index b202f3535..f53c655ec 100644 --- a/Indicators/Indi_WPR.mqh +++ b/Indicators/Indi_WPR.mqh @@ -35,10 +35,8 @@ double iWPR(string _symbol, int _tf, int _period, int _shift) { struct IndiWPRParams : IndicatorParams { unsigned int period; // Struct constructors. - IndiWPRParams(unsigned int _period = 14, int _shift = 0) - : period(_period), IndicatorParams(INDI_WPR, 1, TYPE_DOUBLE) { + IndiWPRParams(unsigned int _period = 14, int _shift = 0) : period(_period), IndicatorParams(INDI_WPR) { shift = _shift; - SetDataValueRange(IDATA_RANGE_RANGE); SetCustomIndicatorName("Examples\\WPR"); }; IndiWPRParams(IndiWPRParams &_params, ENUM_TIMEFRAMES _tf) { @@ -55,7 +53,11 @@ class Indi_WPR : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_WPR(IndiWPRParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_WPR(IndiWPRParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_RANGE, _indi_src_mode), + _indi_src) {} Indi_WPR(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_WPR, _tf, _shift) {} /** @@ -66,7 +68,7 @@ class Indi_WPR : public IndicatorTickOrCandleSource { * - https://www.mql5.com/en/docs/indicators/iwpr */ static double iWPR(string _symbol = NULL, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, unsigned int _period = 14, - int _shift = 0, IndicatorBase *_obj = NULL) { + int _shift = 0, IndicatorData *_obj = NULL) { #ifdef __MQL4__ return ::iWPR(_symbol, _tf, _period, _shift); #else // __MQL5__ @@ -104,7 +106,7 @@ class Indi_WPR : public IndicatorTickOrCandleSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_WPR::iWPR(GetSymbol(), GetTf(), GetPeriod(), _ishift, THIS_PTR); break; diff --git a/Indicators/Indi_WilliamsAD.mqh b/Indicators/Indi_WilliamsAD.mqh index 7e2bf94e4..5a09d153c 100644 --- a/Indicators/Indi_WilliamsAD.mqh +++ b/Indicators/Indi_WilliamsAD.mqh @@ -28,8 +28,7 @@ // Structs. struct IndiWilliamsADParams : IndicatorParams { // Struct constructor. - IndiWilliamsADParams(int _shift = 0) : IndicatorParams(INDI_WILLIAMS_AD, 1, TYPE_DOUBLE) { - SetDataValueRange(IDATA_RANGE_MIXED); + IndiWilliamsADParams(int _shift = 0) : IndicatorParams(INDI_WILLIAMS_AD) { SetCustomIndicatorName("Examples\\W_AD"); shift = _shift; }; @@ -47,15 +46,18 @@ class Indi_WilliamsAD : public IndicatorTickOrCandleSource /** * Class constructor. */ - Indi_WilliamsAD(IndiWilliamsADParams &_p, IndicatorBase *_indi_src = NULL) - : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_WilliamsAD(IndiWilliamsADParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, + IndicatorData *_indi_src = NULL, int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_MIXED, _indi_src_mode), + _indi_src){}; Indi_WilliamsAD(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_WILLIAMS_AD, _tf, _shift){}; /** * Built-in version of Williams' AD. */ - static double iWAD(string _symbol, ENUM_TIMEFRAMES _tf, int _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) { + static double iWAD(string _symbol, ENUM_TIMEFRAMES _tf, int _mode = 0, int _shift = 0, IndicatorData *_obj = NULL) { INDICATOR_CALCULATE_POPULATE_PARAMS_AND_CACHE_LONG(_symbol, _tf, "Indi_WilliamsAD"); return iWADOnArray(INDICATOR_CALCULATE_POPULATED_PARAMS_LONG, _mode, _shift, _cache); } @@ -84,8 +86,8 @@ class Indi_WilliamsAD : public IndicatorTickOrCandleSource /** * 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) { + static double iWADOnIndicator(IndicatorData *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _mode = 0, + int _shift = 0, IndicatorData *_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); @@ -138,7 +140,7 @@ class Indi_WilliamsAD : public IndicatorTickOrCandleSource virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_WilliamsAD::iWAD(GetSymbol(), GetTf(), _mode, _ishift, THIS_PTR); break; diff --git a/Indicators/Indi_ZigZag.mqh b/Indicators/Indi_ZigZag.mqh index ec8147ee9..ad6effa22 100644 --- a/Indicators/Indi_ZigZag.mqh +++ b/Indicators/Indi_ZigZag.mqh @@ -35,13 +35,9 @@ struct IndiZigZagParams : IndicatorParams { unsigned int backstep; // Struct constructors. IndiZigZagParams(unsigned int _depth = 12, unsigned int _deviation = 5, unsigned int _backstep = 3, int _shift = 0) - : depth(_depth), - deviation(_deviation), - backstep(_backstep), - IndicatorParams(INDI_ZIGZAG, FINAL_ZIGZAG_LINE_ENTRY, TYPE_DOUBLE) { + : depth(_depth), deviation(_deviation), backstep(_backstep), IndicatorParams(INDI_ZIGZAG) { shift = _shift; SetCustomIndicatorName("Examples\\ZigZag"); - SetDataValueRange(IDATA_RANGE_PRICE); // @fixit Draws lines between lowest and highest prices! }; IndiZigZagParams(IndiZigZagParams &_params, ENUM_TIMEFRAMES _tf) { THIS_REF = _params; @@ -63,7 +59,12 @@ class Indi_ZigZag : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_ZigZag(IndiZigZagParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src) {} + Indi_ZigZag(IndiZigZagParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource(_p, + IndicatorDataParams::GetInstance(FINAL_ZIGZAG_LINE_ENTRY, TYPE_DOUBLE, _idstype, + IDATA_RANGE_PRICE_ON_SIGNAL), + _indi_src) {} Indi_ZigZag(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_ZIGZAG, _tf, _shift) {} @@ -71,7 +72,7 @@ class Indi_ZigZag : public IndicatorTickOrCandleSource { * Returns value for ZigZag indicator. */ static double iCustomZigZag(string _symbol, ENUM_TIMEFRAMES _tf, string _name, int _depth, int _deviation, - int _backstep, ENUM_ZIGZAG_LINE _mode = 0, int _shift = 0, IndicatorBase *_obj = NULL) { + int _backstep, ENUM_ZIGZAG_LINE _mode = 0, int _shift = 0, IndicatorData *_obj = NULL) { #ifdef __MQL5__ int _handle = Object::IsValid(_obj) ? _obj.Get(IndicatorState::INDICATOR_STATE_PROP_HANDLE) : NULL; double _res[]; @@ -139,9 +140,9 @@ class Indi_ZigZag : public IndicatorTickOrCandleSource { /** * On-indicator version of ZigZag indicator. */ - static double iZigZagOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _depth, + static double iZigZagOnIndicator(IndicatorData *_indi, string _symbol, ENUM_TIMEFRAMES _tf, int _depth, int _deviation, int _backstep, int _mode = 0, int _shift = 0, - IndicatorBase *_obj = NULL) { + IndicatorData *_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, @@ -350,7 +351,7 @@ class Indi_ZigZag : public IndicatorTickOrCandleSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_ZigZag::iZigZag(GetSymbol(), GetTf(), /*[*/ GetDepth(), GetDeviation(), GetBackstep() /*]*/, (ENUM_ZIGZAG_LINE)_mode, _ishift, THIS_PTR); diff --git a/Indicators/Indi_ZigZagColor.mqh b/Indicators/Indi_ZigZagColor.mqh index 6e8cf6d9a..4dd0303a4 100644 --- a/Indicators/Indi_ZigZagColor.mqh +++ b/Indicators/Indi_ZigZagColor.mqh @@ -35,11 +35,10 @@ struct IndiZigZagColorParams : IndicatorParams { // Struct constructor. IndiZigZagColorParams(unsigned int _depth = 12, unsigned int _deviation = 5, unsigned int _backstep = 3, int _shift = 0) - : IndicatorParams(INDI_ZIGZAG_COLOR, 3, TYPE_DOUBLE) { + : IndicatorParams(INDI_ZIGZAG_COLOR) { backstep = _backstep; depth = _depth; deviation = _deviation; - SetDataValueRange(IDATA_RANGE_MIXED); SetCustomIndicatorName("Examples\\ZigZagColor"); shift = _shift; }; @@ -57,8 +56,11 @@ class Indi_ZigZagColor : public IndicatorTickOrCandleSource= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_BUILTIN: _value = Indi_ZigZagColor::iZigZagColor(GetSymbol(), GetTf(), /*[*/ GetDepth(), GetDeviation(), GetBackstep() /*]*/, (ENUM_ZIGZAG_LINE)_mode, _ishift, THIS_PTR); diff --git a/Indicators/OHLC/Indi_OHLC.mqh b/Indicators/OHLC/Indi_OHLC.mqh index c7f9cc25c..21fa2319d 100644 --- a/Indicators/OHLC/Indi_OHLC.mqh +++ b/Indicators/OHLC/Indi_OHLC.mqh @@ -37,9 +37,7 @@ enum ENUM_INDI_OHLC_MODE { // Structs. struct IndiOHLCParams : IndicatorParams { // Struct constructor. - IndiOHLCParams(int _shift = 0) : IndicatorParams(INDI_OHLC, FINAL_INDI_OHLC_MODE_ENTRY, TYPE_DOUBLE) { - SetShift(_shift); - }; + IndiOHLCParams(int _shift = 0) : IndicatorParams(INDI_OHLC) { SetShift(_shift); }; IndiOHLCParams(IndiOHLCParams &_params, ENUM_TIMEFRAMES _tf) { THIS_REF = _params; tf = _tf; @@ -54,7 +52,12 @@ class Indi_OHLC : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_OHLC(IndiOHLCParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_OHLC(IndiOHLCParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource(_p, + IndicatorDataParams::GetInstance(FINAL_INDI_OHLC_MODE_ENTRY, TYPE_DOUBLE, _idstype, + IDATA_RANGE_PRICE, _indi_src_mode), + _indi_src){}; Indi_OHLC(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_PRICE, _tf, _shift){}; diff --git a/Indicators/Price/Indi_Price.mqh b/Indicators/Price/Indi_Price.mqh index b0cbcc6d3..e8a97a0c6 100644 --- a/Indicators/Price/Indi_Price.mqh +++ b/Indicators/Price/Indi_Price.mqh @@ -29,8 +29,7 @@ struct PriceIndiParams : IndicatorParams { ENUM_APPLIED_PRICE ap; // Struct constructor. - PriceIndiParams(ENUM_APPLIED_PRICE _ap = PRICE_TYPICAL, int _shift = 0) - : ap(_ap), IndicatorParams(INDI_PRICE, 1, TYPE_DOUBLE) { + PriceIndiParams(ENUM_APPLIED_PRICE _ap = PRICE_TYPICAL, int _shift = 0) : ap(_ap), IndicatorParams(INDI_PRICE) { SetShift(_shift); }; PriceIndiParams(PriceIndiParams &_params, ENUM_TIMEFRAMES _tf) { @@ -51,7 +50,11 @@ class Indi_Price : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_Price(PriceIndiParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_Price(PriceIndiParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_PRICE, _indi_src_mode), + _indi_src){}; Indi_Price(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_PRICE, _tf, _shift){}; diff --git a/Indicators/Special/Indi_Custom.mqh b/Indicators/Special/Indi_Custom.mqh index d35236289..c23a3c19f 100644 --- a/Indicators/Special/Indi_Custom.mqh +++ b/Indicators/Special/Indi_Custom.mqh @@ -33,7 +33,7 @@ #endif // Includes. -#include "../../Indicator.mqh" +#include "../../Indicator/IndicatorTickOrCandleSource.h" // Structs. @@ -41,9 +41,8 @@ struct IndiCustomParams : public IndicatorParams { DataParamEntry iargs[]; // Struct constructors. - IndiCustomParams(string _filepath = INDI_CUSTOM_PATH, int _shift = 0) : IndicatorParams(INDI_CUSTOM, 1, TYPE_DOUBLE) { + IndiCustomParams(string _filepath = INDI_CUSTOM_PATH, int _shift = 0) : IndicatorParams(INDI_CUSTOM) { custom_indi_name = _filepath; - SetDataSourceType(IDATA_ICUSTOM); } IndiCustomParams(IndiCustomParams &_params, ENUM_TIMEFRAMES _tf) { THIS_REF = _params; @@ -74,13 +73,18 @@ struct IndiCustomParams : public IndicatorParams { /** * Implements indicator class. */ -class Indi_Custom : public Indicator { +class Indi_Custom : public IndicatorTickOrCandleSource { public: /** * Class constructor. */ - Indi_Custom(IndiCustomParams &_p, IndicatorBase *_indi_src = NULL) : Indicator(_p, _indi_src) {} - Indi_Custom(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) : Indicator(INDI_CUSTOM, _tf){}; + Indi_Custom(IndiCustomParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_ICUSTOM, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_UNKNOWN, _indi_src_mode), + _indi_src) {} + Indi_Custom(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) + : IndicatorTickOrCandleSource(INDI_CUSTOM, _tf, _shift){}; /** * Returns the indicator's value. @@ -88,21 +92,20 @@ class Indi_Custom : public Indicator { IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = -1) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_ICUSTOM: switch (iparams.GetParamsSize()) { case 0: - _value = iCustom(istate.handle, Get(CHART_PARAM_SYMBOL), Get(CHART_PARAM_TF), - iparams.custom_indi_name, _mode, _ishift); + _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.custom_indi_name, _mode, _ishift); break; case 1: - _value = iCustom(istate.handle, Get(CHART_PARAM_SYMBOL), Get(CHART_PARAM_TF), - iparams.custom_indi_name, iparams.GetParam(1).ToValue(), _mode, _ishift); + _value = iCustom(istate.handle, GetSymbol(), GetTf(), iparams.custom_indi_name, + iparams.GetParam(1).ToValue(), _mode, _ishift); break; case 2: - _value = iCustom(istate.handle, Get(CHART_PARAM_SYMBOL), Get(CHART_PARAM_TF), - iparams.custom_indi_name, iparams.GetParam(1).ToValue(), - iparams.GetParam(2).ToValue(), _mode, _ishift); + _value = + iCustom(istate.handle, GetSymbol(), GetTf(), iparams.custom_indi_name, + iparams.GetParam(1).ToValue(), iparams.GetParam(2).ToValue(), _mode, _ishift); break; } break; diff --git a/Indicators/Special/Indi_Math.mqh b/Indicators/Special/Indi_Math.mqh index 098b4fc3f..dcf43f01b 100644 --- a/Indicators/Special/Indi_Math.mqh +++ b/Indicators/Special/Indi_Math.mqh @@ -43,13 +43,11 @@ struct IndiMathParams : IndicatorParams { IndiMathParams(ENUM_MATH_OP _op = MATH_OP_SUB, unsigned int _mode_1 = 0, unsigned int _mode_2 = 1, unsigned int _shift_1 = 0, unsigned int _shift_2 = 0, int _shift = 0, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) - : IndicatorParams(INDI_SPECIAL_MATH, 1, TYPE_DOUBLE) { + : IndicatorParams(INDI_SPECIAL_MATH) { mode_1 = _mode_1; mode_2 = _mode_2; op_builtin = _op; op_mode = MATH_OP_MODE_BUILTIN; - SetDataValueRange(IDATA_RANGE_MIXED); - SetDataSourceType(IDATA_INDICATOR); shift = _shift; shift_1 = _shift_1; shift_2 = _shift_2; @@ -60,14 +58,11 @@ struct IndiMathParams : IndicatorParams { IndiMathParams(MathCustomOpFunction _op, unsigned int _mode_1 = 0, unsigned int _mode_2 = 1, unsigned int _shift_1 = 0, unsigned int _shift_2 = 0, int _shift = 0, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT) - : IndicatorParams(INDI_SPECIAL_MATH, 1, TYPE_DOUBLE) { - max_modes = 1; + : IndicatorParams(INDI_SPECIAL_MATH) { mode_1 = _mode_1; mode_2 = _mode_2; op_fn = _op; op_mode = MATH_OP_MODE_CUSTOM_FUNCTION; - SetDataValueRange(IDATA_RANGE_MIXED); - SetDataSourceType(IDATA_INDICATOR); shift = _shift; shift_1 = _shift_1; shift_2 = _shift_2; @@ -87,7 +82,11 @@ class Indi_Math : public IndicatorTickOrCandleSource { /** * Class constructor. */ - Indi_Math(IndiMathParams &_p, IndicatorBase *_indi_src = NULL) : IndicatorTickOrCandleSource(_p, _indi_src){}; + Indi_Math(IndiMathParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_INDICATOR, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTickOrCandleSource( + _p, IndicatorDataParams::GetInstance(1, TYPE_DOUBLE, _idstype, IDATA_RANGE_MIXED, _indi_src_mode), + _indi_src){}; Indi_Math(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0) : IndicatorTickOrCandleSource(INDI_SPECIAL_MATH, _tf, _shift){}; @@ -97,7 +96,7 @@ class Indi_Math : public IndicatorTickOrCandleSource { virtual IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) { double _value = EMPTY_VALUE; int _ishift = _shift >= 0 ? _shift : iparams.GetShift(); - switch (iparams.idstype) { + switch (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE))) { case IDATA_INDICATOR: if (!indi_src.IsSet()) { GetLogger().Error( @@ -130,7 +129,7 @@ class Indi_Math : public IndicatorTickOrCandleSource { return _value; } - static double iMathOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, ENUM_MATH_OP op, + static double iMathOnIndicator(IndicatorData *_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(_mode_1, _shift_1); @@ -138,7 +137,7 @@ class Indi_Math : public IndicatorTickOrCandleSource { return Math::Op(op, _val_1, _val_2); } - static double iMathOnIndicator(IndicatorBase *_indi, string _symbol, ENUM_TIMEFRAMES _tf, MathCustomOpFunction _op, + static double iMathOnIndicator(IndicatorData *_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(_mode_1, _shift_1); diff --git a/Indicators/Tick/Indi_TickMt.mqh b/Indicators/Tick/Indi_TickMt.mqh index 9f03835b9..8b1b39d4a 100644 --- a/Indicators/Tick/Indi_TickMt.mqh +++ b/Indicators/Tick/Indi_TickMt.mqh @@ -27,7 +27,7 @@ struct IndiTickMtParams : IndicatorParams { string symbol; // Struct constructor. - IndiTickMtParams(string _symbol = NULL, int _shift = 0) : IndicatorParams(INDI_TICK, 3, TYPE_DOUBLE) { + IndiTickMtParams(string _symbol = NULL, int _shift = 0) : IndicatorParams(INDI_TICK) { SetShift(_shift); SetSymbol(_symbol); }; @@ -52,8 +52,10 @@ class Indi_TickMt : public IndicatorTick { /** * Class constructor. */ - Indi_TickMt(IndiTickMtParams &_p, IndicatorBase *_indi_src = NULL) - : IndicatorTick(_p, _indi_src){}; + Indi_TickMt(IndiTickMtParams &_p, ENUM_IDATA_SOURCE_TYPE _idstype = IDATA_BUILTIN, IndicatorData *_indi_src = NULL, + int _indi_src_mode = 0) + : IndicatorTick(_p, IndicatorDataParams::GetInstance(3, TYPE_DOUBLE, _idstype), + _indi_src){}; Indi_TickMt(ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0, string _name = "") : IndicatorTick(INDI_TICK, _tf, _shift, _name) {} diff --git a/MQL4.mqh b/MQL4.mqh index 42901ff73..b3e5c850c 100644 --- a/MQL4.mqh +++ b/MQL4.mqh @@ -155,29 +155,30 @@ class MT4HISTORY { const datetime LastTimeCurrent = ::TimeCurrent(); - if ((!MT4HISTORY::IsTester) && (LastTimeCurrent >= this.LastInitTime + DAY)) { - this.LastTime = 0; + if ((!MT4HISTORY::IsTester) && (LastTimeCurrent >= this PTR_DEREF LastInitTime + DAY)) { + this PTR_DEREF LastTime = 0; - this.LastTotalOrders = 0; - this.LastTotalDeals = 0; + this PTR_DEREF LastTotalOrders = 0; + this PTR_DEREF LastTotalDeals = 0; - this.Amount = 0; + this PTR_DEREF Amount = 0; - ::ArrayResize(this.Tickets, this.Amount, RESERVE_SIZE); + ::ArrayResize(this PTR_DEREF Tickets, this PTR_DEREF Amount, RESERVE_SIZE); - this.LastInitTime = LastTimeCurrent; + this PTR_DEREF LastInitTime = LastTimeCurrent; } - if (::HistorySelect(this.LastTime, ::MathMax(LastTimeCurrent, this.LastTime) + DAY)) // Daily stock. + if (::HistorySelect(this PTR_DEREF LastTime, + ::MathMax(LastTimeCurrent, this PTR_DEREF LastTime) + DAY)) // Daily stock. { const int TotalOrders = ::HistoryOrdersTotal(); const int TotalDeals = ::HistoryDealsTotal(); - Res = ((TotalOrders != this.LastTotalOrders) || (TotalDeals != this.LastTotalDeals)); + Res = ((TotalOrders != this PTR_DEREF LastTotalOrders) || (TotalDeals != this PTR_DEREF LastTotalDeals)); if (Res) { - int iOrder = MT4HISTORY::GetNextPosMT4Order(this.LastTotalOrders); - int iDeal = MT4HISTORY::GetNextPosMT4Deal(this.LastTotalDeals); + int iOrder = MT4HISTORY::GetNextPosMT4Order(this PTR_DEREF LastTotalOrders); + int iDeal = MT4HISTORY::GetNextPosMT4Deal(this PTR_DEREF LastTotalDeals); long TimeOrder = (iOrder < TotalOrders) ? ::HistoryOrderGetInteger(::HistoryOrderGetTicket(iOrder), ORDER_TIME_DONE /*_MSC*/) @@ -188,9 +189,9 @@ class MT4HISTORY { while ((iDeal < TotalDeals) || (iOrder < TotalOrders)) if (TimeOrder < TimeDeal) { - this.Amount = ::ArrayResize(this.Tickets, this.Amount + 1, RESERVE_SIZE); + this PTR_DEREF Amount = ::ArrayResize(this PTR_DEREF Tickets, this PTR_DEREF Amount + 1, RESERVE_SIZE); - this.Tickets[this.Amount - 1] = -(long)::HistoryOrderGetTicket(iOrder); + this PTR_DEREF Tickets[this PTR_DEREF Amount - 1] = -(long)::HistoryOrderGetTicket(iOrder); iOrder = MT4HISTORY::GetNextPosMT4Order(iOrder + 1); @@ -198,9 +199,9 @@ class MT4HISTORY { ? ::HistoryOrderGetInteger(::HistoryOrderGetTicket(iOrder), ORDER_TIME_DONE /*_MSC*/) : LONG_MAX; // ORDER_TIME_DONE_MSC returns zero in the tester (build 1470). } else { - this.Amount = ::ArrayResize(this.Tickets, this.Amount + 1, RESERVE_SIZE); + this PTR_DEREF Amount = ::ArrayResize(this PTR_DEREF Tickets, this PTR_DEREF Amount + 1, RESERVE_SIZE); - this.Tickets[this.Amount - 1] = (long)::HistoryDealGetTicket(iDeal); + this PTR_DEREF Tickets[this PTR_DEREF Amount - 1] = (long)::HistoryDealGetTicket(iDeal); iDeal = MT4HISTORY::GetNextPosMT4Deal(iDeal + 1); @@ -216,19 +217,19 @@ class MT4HISTORY { const long MaxTime = ::MathMax(TimeOrder, TimeDeal); - this.LastTotalOrders = 0; - this.LastTotalDeals = 0; + this PTR_DEREF LastTotalOrders = 0; + this PTR_DEREF LastTotalDeals = 0; if (LastTimeCurrent - HISTORY_PAUSE > MaxTime) - this.LastTime = LastTimeCurrent - HISTORY_PAUSE; + this PTR_DEREF LastTime = LastTimeCurrent - HISTORY_PAUSE; else { - this.LastTime = (datetime)MaxTime; + this PTR_DEREF LastTime = (datetime)MaxTime; if (TimeOrder == MaxTime) for (int i = TotalOrders - 1; i >= 0; i--) { if (TimeOrder > ::HistoryOrderGetInteger(::HistoryOrderGetTicket(i), ORDER_TIME_DONE /*_MSC*/)) break; - this.LastTotalOrders++; + this PTR_DEREF LastTotalOrders++; } if (TimeDeal == MaxTime) @@ -236,14 +237,14 @@ class MT4HISTORY { if (TimeDeal != ::HistoryDealGetInteger(::HistoryDealGetTicket(TotalDeals - 1), DEAL_TIME /*_MSC*/)) break; - this.LastTotalDeals++; + this PTR_DEREF LastTotalDeals++; } } - } else if (LastTimeCurrent - HISTORY_PAUSE > this.LastTime) { - this.LastTime = LastTimeCurrent - HISTORY_PAUSE; + } else if (LastTimeCurrent - HISTORY_PAUSE > this PTR_DEREF LastTime) { + this PTR_DEREF LastTime = LastTimeCurrent - HISTORY_PAUSE; - this.LastTotalOrders = 0; - this.LastTotalDeals = 0; + this PTR_DEREF LastTotalOrders = 0; + this PTR_DEREF LastTotalDeals = 0; } } @@ -264,26 +265,26 @@ class MT4HISTORY { } MT4HISTORY(void) : Amount(0), LastTime(0), LastTotalDeals(0), LastTotalOrders(0), LastInitTime(0) { - ::ArrayResize(this.Tickets, this.Amount, RESERVE_SIZE); + ::ArrayResize(this PTR_DEREF Tickets, this PTR_DEREF Amount, RESERVE_SIZE); - this.RefreshHistory(); + this PTR_DEREF RefreshHistory(); } int GetAmount(void) { - this.RefreshHistory(); + this PTR_DEREF RefreshHistory(); - return ((int)this.Amount); + return ((int)this PTR_DEREF Amount); } long operator[](const uint Pos) { long Res = 0; - if (Pos >= this.Amount) { - this.RefreshHistory(); + if (Pos >= this PTR_DEREF Amount) { + this PTR_DEREF RefreshHistory(); - if (Pos < this.Amount) Res = this.Tickets[Pos]; + if (Pos < this PTR_DEREF Amount) Res = this PTR_DEREF Tickets[Pos]; } else - Res = this.Tickets[Pos]; + Res = this PTR_DEREF Tickets[Pos]; return (Res); } @@ -325,16 +326,19 @@ struct MT4_ORDER { string ToString(void) const { static const string Types[] = {"buy", "sell", "buy limit", "sell limit", "buy stop", "sell stop", "balance"}; - const int digits = (int)::SymbolInfoInteger(this.Symbol, SYMBOL_DIGITS); - - return ("#" + (string)this.Ticket + " " + (string)this.OpenTime + " " + - ((this.Type < ::ArraySize(Types)) ? Types[this.Type] : "unknown") + " " + ::DoubleToString(this.Lots, 2) + - " " + this.Symbol + " " + ::DoubleToString(this.OpenPrice, digits) + " " + - ::DoubleToString(this.StopLoss, digits) + " " + ::DoubleToString(this.TakeProfit, digits) + " " + - ((this.CloseTime > 0) ? ((string)this.CloseTime + " ") : "") + ::DoubleToString(this.ClosePrice, digits) + - " " + ::DoubleToString(this.Commission, 2) + " " + ::DoubleToString(this.Swap, 2) + " " + - ::DoubleToString(this.Profit, 2) + " " + ((this.Comment == "") ? "" : (this.Comment + " ")) + - (string)this.MagicNumber + (((this.Expiration > 0) ? (" expiration " + (string)this.Expiration) : ""))); + const int digits = (int)::SymbolInfoInteger(this PTR_DEREF Symbol, SYMBOL_DIGITS); + + return ( + "#" + (string)this PTR_DEREF Ticket + " " + (string)this PTR_DEREF OpenTime + " " + + ((this PTR_DEREF Type < ::ArraySize(Types)) ? Types[this PTR_DEREF Type] : "unknown") + " " + + ::DoubleToString(this PTR_DEREF Lots, 2) + " " + this PTR_DEREF Symbol + " " + + ::DoubleToString(this PTR_DEREF OpenPrice, digits) + " " + ::DoubleToString(this PTR_DEREF StopLoss, digits) + + " " + ::DoubleToString(this PTR_DEREF TakeProfit, digits) + " " + + ((this PTR_DEREF CloseTime > 0) ? ((string)this PTR_DEREF CloseTime + " ") : "") + + ::DoubleToString(this PTR_DEREF ClosePrice, digits) + " " + ::DoubleToString(this PTR_DEREF Commission, 2) + + " " + ::DoubleToString(this PTR_DEREF Swap, 2) + " " + ::DoubleToString(this PTR_DEREF Profit, 2) + " " + + ((this PTR_DEREF Comment == "") ? "" : (this PTR_DEREF Comment + " ")) + (string)this PTR_DEREF MagicNumber + + (((this PTR_DEREF Expiration > 0) ? (" expiration " + (string)this PTR_DEREF Expiration) : ""))); } }; diff --git a/MQL5.mqh b/MQL5.mqh index e230f6f61..584a74fd2 100644 --- a/MQL5.mqh +++ b/MQL5.mqh @@ -307,92 +307,4 @@ #define ERR_USER_ERROR_FIRST 65536 // User defined errors start with this code. #endif -/** - * MQL5 wrapper to work in MQL4. - */ -class MQL5 { - - public: - // Enums. - #ifdef __MQL4__ - // Trading operations. - enum ENUM_TRADE_REQUEST_ACTIONS { - // @see: https://www.mql5.com/en/docs/constants/tradingconstants/enum_trade_request_actions - TRADE_ACTION_DEAL, // Place a trade order for an immediate execution with the specified parameters (market order). - TRADE_ACTION_PENDING, // Place a trade order for the execution under specified conditions (pending order). - TRADE_ACTION_SLTP, // Modify Stop Loss and Take Profit values of an opened position. - TRADE_ACTION_MODIFY, // Modify the parameters of the order placed previously. - TRADE_ACTION_REMOVE, // Delete the pending order placed previously. - TRADE_ACTION_CLOSE_BY // Close a position by an opposite one. - }; - // Fill Policy. - enum ENUM_SYMBOL_FILLING { - // @see: https://www.mql5.com/en/docs/constants/tradingconstants/orderproperties - SYMBOL_FILLING_FOK = 1, // A deal can be executed only with the specified volume. - SYMBOL_FILLING_IOC = 2 // Trader agrees to execute a deal with the volume maximally available in the market. - }; - enum ENUM_ORDER_TYPE_FILLING { - // @see: https://www.mql5.com/en/docs/constants/tradingconstants/orderproperties - ORDER_FILLING_FOK, // An order can be filled only in the specified amount. - ORDER_FILLING_IOC, // A trader agrees to execute a deal with the volume maximally available in the market. - ORDER_FILLING_RETURN // In case of partial filling a market or limit order with remaining volume is not canceled but processed further. - }; - enum ENUM_ORDER_TYPE_TIME { - // @see: https://www.mql5.com/en/docs/constants/tradingconstants/orderproperties - ORDER_TIME_GTC, // Good till cancel order. - ORDER_TIME_DAY, // Good till current trade day order. - ORDER_TIME_SPECIFIED, // Good till expired order. - ORDER_TIME_SPECIFIED_DAY // The order will be effective till 23:59:59 of the specified day. - }; - // An order status that describes its state. - enum ENUM_ORDER_STATE { - ORDER_STATE_STARTED, // Order checked, but not yet accepted by broker - ORDER_STATE_PLACED, // Order accepted - ORDER_STATE_CANCELED, // Order canceled by client - ORDER_STATE_PARTIAL, // Order partially executed - ORDER_STATE_FILLED, // Order fully executed - ORDER_STATE_REJECTED, // Order rejected - ORDER_STATE_EXPIRED, // Order expired - ORDER_STATE_REQUEST_ADD, // Order is being registered (placing to the trading system) - ORDER_STATE_REQUEST_MODIFY, // Order is being modified (changing its parameters) - ORDER_STATE_REQUEST_CANCEL // Order is being deleted (deleting from the trading system) - }; - #endif - - #ifdef __MQL4__ - // @see: https://www.mql5.com/en/docs/constants/structures/mqltraderequest - struct MqlTradeRequest { - ENUM_TRADE_REQUEST_ACTIONS action; // Trade operation type. - ulong magic; // Expert Advisor ID (magic number). - ulong order; // Order ticket. - string symbol; // Trade symbol. - double volume; // Requested volume for a deal in lots. - double price; // Price. - double stoplimit; // StopLimit level of the order. - double sl; // Stop Loss level of the order. - double tp; // Take Profit level of the order. - ulong deviation; // Maximal possible deviation from the requested price. - ENUM_ORDER_TYPE type; // Order type. - ENUM_ORDER_TYPE_FILLING type_filling; // Order execution type. - ENUM_ORDER_TYPE_TIME type_time; // Order expiration type. - datetime expiration; // Order expiration time (for the orders of ORDER_TIME_SPECIFIED type. - string comment; // Order comment. - ulong position; // Position ticket. - ulong position_by; // The ticket of an opposite position. - }; - // @see: https://www.mql5.com/en/docs/constants/structures/mqltraderesult - struct MqlTradeResult { - uint retcode; // Operation return code. - ulong deal; // Deal ticket, if it is performed. - ulong order; // Order ticket, if it is placed. - double volume; // Deal volume, confirmed by broker. - double price; // Deal price, confirmed by broker. - double bid; // Current Bid price. - double ask; // Current Ask price. - string comment; // Broker comment to operation (by default it is filled by description of trade server return code). - uint request_id; // Request ID set by the terminal during the dispatch. - uint retcode_external; // Return code of an external trading system. - }; - #endif -}; #endif // MQL5_MQH diff --git a/Mail.mqh b/Mail.mqh index 9ff20a1b1..f41078561 100644 --- a/Mail.mqh +++ b/Mail.mqh @@ -44,10 +44,10 @@ class Mail { * Constructor. */ Mail(string _subject_prefix = "Trading Info: ") { - this.string_dlm = " "; - this.string_nl = "
\n"; - this.subject_execute_order = __FILE__; - this.subject_prefix = _subject_prefix; + this PTR_DEREF string_dlm = " "; + this PTR_DEREF string_nl = "
\n"; + this PTR_DEREF subject_execute_order = __FILE__; + this PTR_DEREF subject_prefix = _subject_prefix; } /* Getters */ @@ -55,12 +55,12 @@ class Mail { /** * Gets subject prefix. */ - string GetMailSubjectPrefix() { return this.subject_prefix; } + string GetMailSubjectPrefix() { return this PTR_DEREF subject_prefix; } /** * Gets subject on execute order. */ - string GetMailSubjectExecuteOrder() { return this.subject_execute_order; } + string GetMailSubjectExecuteOrder() { return this PTR_DEREF subject_execute_order; } /** * Get content of e-mail for executing order. @@ -87,41 +87,45 @@ class Mail { /** * Gets string delimiter. */ - string GetStringDlm() { return this.string_dlm; } + string GetStringDlm() { return this PTR_DEREF string_dlm; } /** * Gets string new line separator. */ - string GetStringNl() { return this.string_nl; } + string GetStringNl() { return this PTR_DEREF string_nl; } /** * Get subject of e-mail for executing order. * * Note: Order needs to be selected before calling this function. */ - string GetSubjectExecuteOrder() { return GetMailSubjectPrefix() + this.string_dlm + GetMailSubjectExecuteOrder(); } + string GetSubjectExecuteOrder() { + return GetMailSubjectPrefix() + this PTR_DEREF string_dlm + GetMailSubjectExecuteOrder(); + } /* Setters */ /** * Sets subject prefix. */ - void SetSubjectPrefix(string _subject_prefix) { this.subject_prefix = _subject_prefix; } + void SetSubjectPrefix(string _subject_prefix) { this PTR_DEREF subject_prefix = _subject_prefix; } /** * Sets subject on execute order. */ - void SetSubjectExecuteOrder(string _subject_execute_order) { this.subject_execute_order = _subject_execute_order; } + void SetSubjectExecuteOrder(string _subject_execute_order) { + this PTR_DEREF subject_execute_order = _subject_execute_order; + } /** * Sets string delimiter. */ - void SetStringDlm(string _dlm) { this.string_dlm = _dlm; } + void SetStringDlm(string _dlm) { this PTR_DEREF string_dlm = _dlm; } /** * Sets string new line separator. */ - void SetStringNl(string _nl) { this.string_nl = _nl; } + void SetStringNl(string _nl) { this PTR_DEREF string_nl = _nl; } /* Mailing methods */ diff --git a/Math.define.h b/Math.define.h index 82ac071dd..8e519a71f 100644 --- a/Math.define.h +++ b/Math.define.h @@ -36,3 +36,25 @@ #define fmin4(_v1, _v2, _v3, _v4) fmin(fmin(fmin(_v1, _v2), _v3), _v4) #define fmin5(_v1, _v2, _v3, _v4, _v5) fmin(fmin(fmin(fmin(_v1, _v2), _v3), _v4), _v5) #define fmin6(_v1, _v2, _v3, _v4, _v5, _v6) fmin(fmin(fmin(fmin(fmin(_v1, _v2), _v3), _v4), _v5), _v6) + +#ifdef __cplusplus +#include + +#define CHAR_MIN std::numeric_limits::min() +#define CHAR_MAX std::numeric_limits::max() +#define UCHAR_MAX std::numeric_limits::max() +#define SHORT_MAX std::numeric_limits::max() +#define SHORT_MIN std::numeric_limits::min() +#define USHORT_MAX std::numeric_limits::max() +#define INT_MIN std::numeric_limits::min() +#define INT_MAX std::numeric_limits::max() +#define UINT_MAX std::numeric_limits::max() +#define LONG_MIN std::numeric_limits::min() +#define LONG_MAX std::numeric_limits::max() +#define ULONG_MAX std::numeric_limits::max() +#define FLT_MIN std::numeric_limits::min() +#define FLT_MAX std::numeric_limits::max() +#define DBL_MIN std::numeric_limits::min() +#define DBL_MAX std::numeric_limits::max() + +#endif diff --git a/Math.extern.h b/Math.extern.h new file mode 100644 index 000000000..4dce9bfe7 --- /dev/null +++ b/Math.extern.h @@ -0,0 +1,49 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2022, 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 . + * + */ + +// Define external global functions. +#ifndef __MQL__ +template +extern T MathAbs(T value); +template +extern T fabs(T value); +template +extern T pow(T base, T exponent); +template +extern T MathPow(T base, T exponent); +template +extern T round(T value); +template +extern T MathRound(T value); +template +extern T fmax(T value1, T value2); +template +extern T MathMax(T value1, T value2); +template +extern T fmin(T value1, T value2); +template +extern T MathMin(T value1, T value2); +template +extern T MathLog10(T value1); +template +extern T log10(T value); +#endif diff --git a/Math.h b/Math.h index 4edd25801..691837b31 100644 --- a/Math.h +++ b/Math.h @@ -30,6 +30,7 @@ #include "Indicator.struct.h" #include "Math.define.h" #include "Math.enum.h" +#include "Math.extern.h" #include "Math.struct.h" /** diff --git a/Matrix.mqh b/Matrix.mqh index 069588d7f..59f3eef39 100644 --- a/Matrix.mqh +++ b/Matrix.mqh @@ -1494,8 +1494,9 @@ class Matrix { return NULL; } - if (_weights != NULL && _weights.GetDimensions() > this.GetDimensions()) { - Print("MeanAbsolute(): Shape ", Repr(), ": Weights must be a tensor level <= ", this.GetDimensions(), "!"); + if (_weights != NULL && _weights.GetDimensions() > this PTR_DEREF GetDimensions()) { + Print("MeanAbsolute(): Shape ", Repr(), ": Weights must be a tensor level <= ", this PTR_DEREF GetDimensions(), + "!"); return NULL; } diff --git a/Object.enum.h b/Object.enum.h new file mode 100644 index 000000000..68d22f513 --- /dev/null +++ b/Object.enum.h @@ -0,0 +1,38 @@ +//+------------------------------------------------------------------+ +//| EA31337 - multi-strategy advanced trading robot. | +//| Copyright 2016-2022, 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 enumerations used for objects. + */ + +#ifndef __MQLBUILD__ +// Used for checking the type of the object pointer. +// @docs +// - https://docs.mql4.com/constants/namedconstants/enum_pointer_type +// - https://www.mql5.com/en/docs/constants/namedconstants/enum_pointer_type +enum ENUM_POINTER_TYPE { + POINTER_INVALID, // Incorrect pointer. + POINTER_DYNAMIC, // Pointer of the object created by the new() operator. + POINTER_AUTOMATIC // Pointer of any objects created automatically (not using new()). +}; +#endif diff --git a/Object.extern.h b/Object.extern.h new file mode 100644 index 000000000..f8b97dbd8 --- /dev/null +++ b/Object.extern.h @@ -0,0 +1,29 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2022, 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 external declarations related to objects. + */ +#ifndef __MQL__ +extern void *GetPointer(void *anyobject); +#endif diff --git a/Object.mqh b/Object.mqh index 64467c821..ed889e2a8 100644 --- a/Object.mqh +++ b/Object.mqh @@ -29,146 +29,114 @@ #endif // Includes. +#include "Object.enum.h" +#include "Object.extern.h" #include "Refs.mqh" +#include "Refs.struct.h" #include "String.mqh" -#ifndef __MQLBUILD__ -// Used for checking the type of the object pointer. -// @docs -// - https://docs.mql4.com/constants/namedconstants/enum_pointer_type -// - https://www.mql5.com/en/docs/constants/namedconstants/enum_pointer_type -enum ENUM_POINTER_TYPE { - POINTER_INVALID, // Incorrect pointer. - POINTER_DYNAMIC, // Pointer of the object created by the new() operator. - POINTER_AUTOMATIC // Pointer of any objects created automatically (not using new()). -}; -#endif - /** * Class to deal with objects. */ class Object : public Dynamic { - - protected: - - void *obj; - long id; - - public: - - /** - * Class constructor. - */ - Object() - : id(rand()), obj(THIS_PTR) - { - } - Object(void *_obj, long _id = __LINE__) { - obj = _obj; - id = _id; - } - - /* Getters */ - - /** - * Get ID of the object. - */ - virtual long GetId() { - return id; - } - - /* Setters */ - - /** - * Set ID of the object. - */ - void SetId(long _id) { - id = _id; - } - - /** - * Get the object handler. - */ - static void *Get(void *_obj) { - return Object::IsValid(_obj) ? _obj : NULL; - } - void *Get() { - return IsValid(obj) ? obj : NULL; - } - - /** - * Check whether pointer is valid. - * @docs: https://docs.mql4.com/constants/namedconstants/enum_pointer_type - */ - static bool IsValid(void *_obj) { - #ifdef __MQL__ - return CheckPointer(_obj) != POINTER_INVALID; - #else - return _obj != nullptr; - #endif - } - bool IsValid() { - return IsValid(obj); - } - - /** - * Check whether pointer is dynamic. - * @docs: https://docs.mql4.com/constants/namedconstants/enum_pointer_type - */ - static bool IsDynamic(void *_obj) { - #ifdef __MQL__ - return CheckPointer(_obj) == POINTER_DYNAMIC; - #else - // In C++ we can't check it. - // @fixme We should fire a warning here so user won't use this method anymore. - return true; - #endif - } - bool IsDynamic() { - return IsDynamic(obj); - } - - /** - * Returns text representation of the object. - */ - virtual const string ToString() { - return StringFormat("[Object #%04x]", GetPointer(this)); - } - - /** - * Returns text representation of the object. - */ - virtual const string ToJSON() { - return StringFormat("{ \"type\": \"%s\" }", typename(this)); - } - - /** - * Safely delete the object. - */ - static void Delete(void *_obj) { - #ifdef __MQL__ - if (CheckPointer(_obj) == POINTER_DYNAMIC) { - #else - if (true) { - #endif - delete _obj; - } - } - void Delete() { - Delete(obj); + protected: + void *obj; + long id; + + public: + /** + * Class constructor. + */ + Object() : obj(THIS_PTR), id(rand()) {} + Object(void *_obj, long _id = __LINE__) { + obj = _obj; + id = _id; + } + + /* Getters */ + + /** + * Get ID of the object. + */ + virtual long GetId() { return id; } + + /* Setters */ + + /** + * Set ID of the object. + */ + void SetId(long _id) { id = _id; } + + /** + * Get the object handler. + */ + static void *Get(void *_obj) { return Object::IsValid(_obj) ? _obj : NULL; } + void *Get() { return IsValid(obj) ? obj : NULL; } + + /** + * Check whether pointer is valid. + * @docs: https://docs.mql4.com/constants/namedconstants/enum_pointer_type + */ + static bool IsValid(void *_obj) { +#ifdef __MQL__ + return CheckPointer(_obj) != POINTER_INVALID; +#else + return _obj != nullptr; +#endif + } + bool IsValid() { return IsValid(obj); } + + /** + * Check whether pointer is dynamic. + * @docs: https://docs.mql4.com/constants/namedconstants/enum_pointer_type + */ + static bool IsDynamic(void *_obj) { +#ifdef __MQL__ + return CheckPointer(_obj) == POINTER_DYNAMIC; +#else + // In C++ we can't check it. + // @fixme We should fire a warning here so user won't use this method anymore. + return true; +#endif + } + bool IsDynamic() { return IsDynamic(obj); } + + /** + * Returns text representation of the object. + */ + virtual const string ToString() { return StringFormat("[Object #%04x]", GetPointer(this)); } + + /** + * Returns text representation of the object. + */ + virtual const string ToJSON() { return StringFormat("{ \"type\": \"%s\" }", typename(this)); } + + /** + * Safely delete the object. + */ + template + static void Delete(T *_obj) { +#ifdef __cplusplus + static_assert(!std::is_same::value, + "Please avoid deleting void* pointers as no destructor will be called!"); +#endif +#ifdef __MQL__ + if (CheckPointer(_obj) == POINTER_DYNAMIC) { +#else + if (true) { +#endif + delete _obj; } + } - /* Virtual methods */ - - /** - * Weight of the object. - */ - virtual double GetWeight() { - return 0; - }; + /* Virtual methods */ + /** + * Weight of the object. + */ + virtual double GetWeight() { return 0; }; }; // Initialize static global variables. -//Object *Object::list = { 0 }; -#endif // OBJECT_MQH +// Object *Object::list = { 0 }; +#endif // OBJECT_MQH diff --git a/Order.enum.h b/Order.enum.h index 385aebb30..c6489a73d 100644 --- a/Order.enum.h +++ b/Order.enum.h @@ -114,6 +114,33 @@ enum ENUM_ORDER_REASON { ORDER_REASON_TP, // The order was placed as a result of Take Profit activation. ORDER_REASON_WEB, // The order was placed from a web platform. }; +// An order status that describes its state. +enum ENUM_ORDER_STATE { + ORDER_STATE_STARTED, // Order checked, but not yet accepted by broker + ORDER_STATE_PLACED, // Order accepted + ORDER_STATE_CANCELED, // Order canceled by client + ORDER_STATE_PARTIAL, // Order partially executed + ORDER_STATE_FILLED, // Order fully executed + ORDER_STATE_REJECTED, // Order rejected + ORDER_STATE_EXPIRED, // Order expired + ORDER_STATE_REQUEST_ADD, // Order is being registered (placing to the trading system) + ORDER_STATE_REQUEST_MODIFY, // Order is being modified (changing its parameters) + ORDER_STATE_REQUEST_CANCEL // Order is being deleted (deleting from the trading system) +}; +enum ENUM_ORDER_TYPE_FILLING { + // @see: https://www.mql5.com/en/docs/constants/tradingconstants/orderproperties + ORDER_FILLING_FOK, // An order can be filled only in the specified amount. + ORDER_FILLING_IOC, // A trader agrees to execute a deal with the volume maximally available in the market. + ORDER_FILLING_RETURN // In case of partial filling a market or limit order with remaining volume is not canceled but + // processed further. +}; +enum ENUM_ORDER_TYPE_TIME { + // @see: https://www.mql5.com/en/docs/constants/tradingconstants/orderproperties + ORDER_TIME_GTC, // Good till cancel order. + ORDER_TIME_DAY, // Good till current trade day order. + ORDER_TIME_SPECIFIED, // Good till expired order. + ORDER_TIME_SPECIFIED_DAY // The order will be effective till 23:59:59 of the specified day. +}; #endif #ifndef __MQ4__ @@ -294,4 +321,15 @@ enum ENUM_POSITION_TYPE { POSITION_TYPE_BUY, // Buy position. POSITION_TYPE_SELL // Sell position. }; + +// Trading operations. +enum ENUM_TRADE_REQUEST_ACTIONS { + // @see: https://www.mql5.com/en/docs/constants/tradingconstants/enum_trade_request_actions + TRADE_ACTION_DEAL, // Place a trade order for an immediate execution with the specified parameters (market order). + TRADE_ACTION_PENDING, // Place a trade order for the execution under specified conditions (pending order). + TRADE_ACTION_SLTP, // Modify Stop Loss and Take Profit values of an opened position. + TRADE_ACTION_MODIFY, // Modify the parameters of the order placed previously. + TRADE_ACTION_REMOVE, // Delete the pending order placed previously. + TRADE_ACTION_CLOSE_BY // Close a position by an opposite one. +}; #endif diff --git a/Order.mqh b/Order.mqh index be7803c3a..a2437d9ba 100644 --- a/Order.mqh +++ b/Order.mqh @@ -39,7 +39,7 @@ #include "Order.define.h" #include "Order.enum.h" #include "Order.struct.h" -#include "Serializer.mqh" +#include "SerializerConverter.mqh" #include "SerializerJson.mqh" #include "Std.h" #include "String.mqh" @@ -2740,7 +2740,7 @@ class Order : public SymbolInfo { * Returns order details in text. */ string const ToString() { - SerializerConverter stub(Serializer::MakeStubObject(SERIALIZER_FLAG_SKIP_HIDDEN)); + SerializerConverter stub(SerializerConverter::MakeStubObject(SERIALIZER_FLAG_SKIP_HIDDEN)); return SerializerConverter::FromObject(THIS_REF, SERIALIZER_FLAG_SKIP_HIDDEN) .ToString(SERIALIZER_FLAG_SKIP_HIDDEN, &stub); } diff --git a/Order.struct.h b/Order.struct.h index d2bda532e..dfc4792d2 100644 --- a/Order.struct.h +++ b/Order.struct.h @@ -54,6 +54,41 @@ struct MqlTradeCheckResult { double margin_level; // Margin level. string comment; // Comment to the reply code (description of the error). }; + +// @see: https://www.mql5.com/en/docs/constants/structures/mqltraderequest +struct MqlTradeRequest { + ENUM_TRADE_REQUEST_ACTIONS action; // Trade operation type. + ulong magic; // Expert Advisor ID (magic number). + ulong order; // Order ticket. + string symbol; // Trade symbol. + double volume; // Requested volume for a deal in lots. + double price; // Price. + double stoplimit; // StopLimit level of the order. + double sl; // Stop Loss level of the order. + double tp; // Take Profit level of the order. + ulong deviation; // Maximal possible deviation from the requested price. + ENUM_ORDER_TYPE type; // Order type. + ENUM_ORDER_TYPE_FILLING type_filling; // Order execution type. + ENUM_ORDER_TYPE_TIME type_time; // Order expiration type. + datetime expiration; // Order expiration time (for the orders of ORDER_TIME_SPECIFIED type. + string comment; // Order comment. + ulong position; // Position ticket. + ulong position_by; // The ticket of an opposite position. +}; + +// @see: https://www.mql5.com/en/docs/constants/structures/mqltraderesult +struct MqlTradeResult { + uint retcode; // Operation return code. + ulong deal; // Deal ticket, if it is performed. + ulong order; // Order ticket, if it is placed. + double volume; // Deal volume, confirmed by broker. + double price; // Deal price, confirmed by broker. + double bid; // Current Bid price. + double ask; // Current Ask price. + string comment; // Broker comment to operation (by default it is filled by description of trade server return code). + uint request_id; // Request ID set by the terminal during the dispatch. + uint retcode_external; // Return code of an external trading system. +}; #endif /** diff --git a/Orders.mqh b/Orders.mqh index 57afd15a5..b245450c4 100644 --- a/Orders.mqh +++ b/Orders.mqh @@ -550,9 +550,9 @@ class Orders { double GetRealizedPL() const { double profit = 0; for (int i = 0; i <= numberOrders; ++i) { - if (this.orders[i].getOrderType() == ORDER_FINAL) { + if (this PTR_DEREF orders[i].getOrderType() == ORDER_FINAL) { // @todo - // profit += this.orders[i].getOrderProfit(); + // profit += this PTR_DEREF orders[i].getOrderProfit(); } } return profit; @@ -569,8 +569,8 @@ class Orders { double GetUnrealizedPL() const { double profit = 0; for (int i = 0; i <= numberOrders; ++i) { - if (this.orders[i].getOrderType() != ORDER_FINAL) { - profit += this.orders[i].getOrderProfit(); + if (this PTR_DEREF orders[i].getOrderType() != ORDER_FINAL) { + profit += this PTR_DEREF orders[i].getOrderProfit(); } } return profit; @@ -579,7 +579,7 @@ class Orders { double GetTotalEquity() const { double profit = 0; for (int i = 0; i <= numberOrders; ++i) { - profit += this.orders[i].GetOrderProfit(); + profit += this PTR_DEREF orders[i].GetOrderProfit(); } return profit; } @@ -587,7 +587,7 @@ class Orders { double GetTotalCommission() const { double commission = 0; for (int i = 0; i <= numberOrders; ++i) { - commission += this.orders[i].GetOrderCommission(); + commission += this PTR_DEREF orders[i].GetOrderCommission(); } return commission; } @@ -595,7 +595,7 @@ class Orders { double GetTotalSwap() const { double swap = 0; for (int i = 0; i <= numberOrders; ++i) { - swap += this.orders[i].GetOrderSwap(); + swap += this PTR_DEREF orders[i].GetOrderSwap(); } return swap; } diff --git a/Pattern.struct.h b/Pattern.struct.h index 2297c7c51..83422f4a6 100644 --- a/Pattern.struct.h +++ b/Pattern.struct.h @@ -32,8 +32,8 @@ // Includes. #include "Bar.struct.h" -#include "Pattern.enum.h" #include "Math.define.h" +#include "Pattern.enum.h" // Defines structure for bitwise pattern values. struct PatternBitwise { diff --git a/Refs.mqh b/Refs.mqh index bc71b2138..07b530ff4 100644 --- a/Refs.mqh +++ b/Refs.mqh @@ -25,7 +25,7 @@ #define REFS_MQH // Includes. -#include "Refs.struct.h" +#include "Refs.rc.h" #include "Std.h" /** @@ -66,54 +66,6 @@ // Forward class declaration. class Dynamic; -class ReferenceCounter { - public: - /** - * Number of weak references to target object. - */ - unsigned int num_weak_refs; - - /** - * Number of strong references to target object. - */ - unsigned int num_strong_refs; - - /** - * Target object pointer. - */ - Dynamic* ptr_object; - - /** - * Whether object has been deleted (but still have weak references). - */ - bool deleted; - - /** - * Constructor. - */ - ReferenceCounter() { - num_weak_refs = 0; - num_strong_refs = 0; - ptr_object = NULL; - deleted = false; - } - - string Debug() { return StringFormat("%d: %d strong, %d weak", ptr_object, num_strong_refs, num_weak_refs); } - - /** - * ReferenceCounter class allocator. - */ - static ReferenceCounter* alloc(); -}; - -/** - * ReferenceCounter class allocator. - */ -ReferenceCounter* ReferenceCounter::alloc() { - // @todo Enhance with linked-list object reuse. - return new ReferenceCounter(); -} - /** * Base class for reference-counted objects. */ diff --git a/Refs.rc.h b/Refs.rc.h new file mode 100644 index 000000000..c24c32b0f --- /dev/null +++ b/Refs.rc.h @@ -0,0 +1,82 @@ +//+------------------------------------------------------------------+ +//| 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 Refs' ReferenceCounter struct. + */ + +#ifndef __MQL__ +// Allows the preprocessor to include a header file when it is needed. +#pragma once +#endif + +// Forward declarations. +class Dynamic; + +class ReferenceCounter { + public: + /** + * Number of weak references to target object. + */ + unsigned int num_weak_refs; + + /** + * Number of strong references to target object. + */ + unsigned int num_strong_refs; + + /** + * Target object pointer. + */ + Dynamic* ptr_object; + + /** + * Whether object has been deleted (but still have weak references). + */ + bool deleted; + + /** + * Constructor. + */ + ReferenceCounter() { + num_weak_refs = 0; + num_strong_refs = 0; + ptr_object = NULL; + deleted = false; + } + + string Debug() { return StringFormat("%d: %d strong, %d weak", ptr_object, num_strong_refs, num_weak_refs); } + + /** + * ReferenceCounter class allocator. + */ + static ReferenceCounter* alloc(); +}; + +/** + * ReferenceCounter class allocator. + */ +ReferenceCounter* ReferenceCounter::alloc() { + // @todo Enhance with linked-list object reuse. + return new ReferenceCounter(); +} diff --git a/Refs.struct.h b/Refs.struct.h index 60ad53306..c63b4322f 100644 --- a/Refs.struct.h +++ b/Refs.struct.h @@ -30,9 +30,12 @@ #pragma once #endif +// Includes. +#include "Refs.rc.h" +#include "Std.h" + +class Dynamic; // Forward class declaration. -class Refs; -class ReferenceCounter; template struct WeakRef; @@ -140,19 +143,19 @@ struct Ref { ptr_object = NULL; return; } - if (ptr_object.ptr_ref_counter == NULL) { + if (PTR_ATTRIB(ptr_object, ptr_ref_counter) == NULL) { // Object is not reference counted. Maybe a stack-based one? return; } // Dropping strong reference. - if (!--ptr_object.ptr_ref_counter.num_strong_refs) { + if (!--PTR_ATTRIB2(ptr_object, ptr_ref_counter, num_strong_refs)) { #ifdef __debug_ref__ Print(ptr_object.ptr_ref_counter.Debug()); #endif // No more strong references. - if (!ptr_object.ptr_ref_counter.num_weak_refs) { - if (CheckPointer(ptr_object.ptr_ref_counter) == POINTER_INVALID) { + if (!PTR_ATTRIB2(ptr_object, ptr_ref_counter, num_weak_refs)) { + if (CheckPointer(PTR_ATTRIB(ptr_object, ptr_ref_counter)) == POINTER_INVALID) { // Serious problem. #ifndef __MQL4__ // Bug: Avoid calling in MQL4 due to 'global initialization failed' error. @@ -162,11 +165,11 @@ struct Ref { } // Also no more weak references. - delete ptr_object.ptr_ref_counter; - ptr_object.ptr_ref_counter = NULL; + delete PTR_ATTRIB(ptr_object, ptr_ref_counter); + PTR_ATTRIB(ptr_object, ptr_ref_counter) = NULL; } else { // Object becomes deleted, but there are some weak references. - ptr_object.ptr_ref_counter.deleted = true; + PTR_ATTRIB(PTR_ATTRIB(ptr_object, ptr_ref_counter), deleted) = true; } // Avoiding delete loop for cyclic references. @@ -182,7 +185,7 @@ struct Ref { } // Avoiding double deletion in Dynamic's destructor. - ptr_object.ptr_ref_counter = NULL; + PTR_ATTRIB(ptr_object, ptr_ref_counter) = NULL; ptr_object = NULL; #ifdef __debug__ @@ -210,11 +213,11 @@ struct Ref { ptr_object = _ptr; if (ptr_object != NULL) { - if (CheckPointer(ptr_object) == POINTER_INVALID || ptr_object.ptr_ref_counter == NULL) { + if (CheckPointer(ptr_object) == POINTER_INVALID || PTR_ATTRIB(ptr_object, ptr_ref_counter) == NULL) { // Double check the pointer for invalid references. Can happen very rarely. return Ptr(); } - ++ptr_object.ptr_ref_counter.num_strong_refs; + ++PTR_ATTRIB(PTR_ATTRIB(ptr_object, ptr_ref_counter), num_strong_refs); #ifdef __debug_ref__ Print(ptr_object.ptr_ref_counter.Debug()); #endif @@ -276,15 +279,15 @@ struct WeakRef { */ ~WeakRef() { Unset(); } - bool ObjectExists() { return ptr_ref_counter != NULL && !ptr_ref_counter.deleted; } + bool ObjectExists() { return ptr_ref_counter != NULL && !PTR_ATTRIB(ptr_ref_counter, deleted); } - X* Ptr() { return ObjectExists() ? (X*)ptr_ref_counter.ptr_object : NULL; } + X* Ptr() { return ObjectExists() ? (X*)PTR_ATTRIB(ptr_ref_counter, ptr_object) : NULL; } /** * Makes a strong reference to the given object. */ X* operator=(X* _ptr) { - if (ptr_ref_counter == (_ptr == NULL ? NULL : _ptr.ptr_ref_counter)) { + if (ptr_ref_counter == (_ptr == NULL ? NULL : PTR_ATTRIB(_ptr, ptr_ref_counter))) { // Assigning the same object or the same NULL. return Ptr(); } @@ -296,20 +299,19 @@ struct WeakRef { return Ptr(); } - if (_ptr.ptr_ref_counter.deleted) { + if (PTR_ATTRIB2(_ptr, ptr_ref_counter, deleted)) { // Assigning already deleted object. ptr_ref_counter = NULL; return Ptr(); } - ptr_ref_counter = _ptr.ptr_ref_counter; + ptr_ref_counter = PTR_ATTRIB(_ptr, ptr_ref_counter); #ifdef __debug_ref__ Print(ptr_ref_counter.Debug()); #endif - ++ptr_ref_counter.num_weak_refs; - + ++PTR_ATTRIB(ptr_ref_counter, num_weak_refs); return Ptr(); } @@ -340,25 +342,27 @@ struct WeakRef { void Unset() { if (ptr_ref_counter != NULL) { // Dropping weak reference. - if (!--ptr_ref_counter.num_weak_refs) { + if (!--PTR_ATTRIB(ptr_ref_counter, num_weak_refs)) { // No more weak references. #ifdef __debug_ref__ Print(ptr_ref_counter.Debug()); #endif - if (!ptr_ref_counter.num_strong_refs) { + if (!PTR_ATTRIB(ptr_ref_counter, num_strong_refs)) { // There are also no strong references. ReferenceCounter* stored_ptr_ref_counter = ptr_ref_counter; - if (!ptr_ref_counter.deleted) { + if (!ptr_ref_counter PTR_DEREF deleted) { // It is safe to delete object and reference counter object. // Avoiding double deletion in Dynamic's destructor. - ptr_ref_counter.ptr_object.ptr_ref_counter = NULL; + ptr_ref_counter PTR_DEREF ptr_object PTR_DEREF ptr_ref_counter = NULL; #ifdef __debug_ref__ Print("Refs: Deleting object ", ptr_ref_counter.ptr_object); #endif - if (CheckPointer(ptr_ref_counter.ptr_object) == POINTER_INVALID) { +#ifdef __MQL__ + // We can't check pointer validity in C++ (other than check for NULL). + if (CheckPointer(ptr_ref_counter PTR_DEREF ptr_object) == POINTER_INVALID) { // Serious problem. #ifndef __MQL4__ // Bug: Avoid calling in MQL4 due to 'global initialization failed' error. @@ -366,10 +370,12 @@ struct WeakRef { #endif return; } - - delete ptr_ref_counter.ptr_object; +#endif + delete ptr_ref_counter PTR_DEREF ptr_object; } +#ifdef __MQL__ + // We can't check pointer validity in C++ (other than check for NULL). if (CheckPointer(stored_ptr_ref_counter) == POINTER_INVALID) { // Serious problem. #ifndef __MQL4__ @@ -378,6 +384,7 @@ struct WeakRef { #endif return; } +#endif delete stored_ptr_ref_counter; } diff --git a/Serializer.mqh b/Serializer.mqh index 3cc513e78..af006b1df 100644 --- a/Serializer.mqh +++ b/Serializer.mqh @@ -28,13 +28,16 @@ #include "Convert.mqh" #include "Serializer.define.h" #include "Serializer.enum.h" -#include "SerializerConverter.mqh" #include "SerializerNode.mqh" -#include "SerializerNodeIterator.mqh" #include "SerializerNodeParam.mqh" +#include "Terminal.define.h" #define SERIALIZER_DEFAULT_FP_PRECISION 8 +// Forward declarations. +template +class SerializerIterator; + class Serializer { protected: SerializerNode* _node; @@ -72,7 +75,7 @@ class Serializer { template SerializerIterator Begin() { - SerializerIterator iter(&this, _node); + SerializerIterator iter(THIS_PTR, _node); return iter; } @@ -200,9 +203,9 @@ class Serializer { value.Serialize(this); fp_precision = SERIALIZER_DEFAULT_FP_PRECISION; - SerializerNode* obj = _node.GetChild(_node.NumChildren() - 1); + SerializerNode* obj = _node PTR_DEREF GetChild(PTR_ATTRIB(_node, NumChildren()) - 1); - obj.SetKey(name); + obj PTR_DEREF SetKey(name); } else { _single_value_name = name; value.Serialize(this); @@ -345,7 +348,7 @@ class Serializer { if (si.HasKey()) { // Should not happen. } else { - _node = parent.GetChild(si.Index()); + _node = parent PTR_DEREF GetChild(si.Index()); array[si.Index()] = si.Struct(); } } @@ -429,7 +432,8 @@ class Serializer { Convert::StringToType(PTR_ATTRIB(PTR_ATTRIB(child, GetValueParam()), _string), value); break; default: - Print("Error: Wrong param type ", EnumToString(paramType), "!"); + Print("Error: Wrong param type!"); + SetUserError(ERR_INVALID_PARAMETER); DebugBreak(); } @@ -440,19 +444,6 @@ class Serializer { return NULL; } - - template - static SerializerConverter MakeStubObject(int _serializer_flags = SERIALIZER_FLAG_INCLUDE_ALL, int _n1 = 1, - int _n2 = 1, int _n3 = 1, int _n4 = 1, int _n5 = 1) { - if (_serializer_flags == 0) { - // Avoiding flags misuse. - _serializer_flags = SERIALIZER_FLAG_INCLUDE_ALL; - } - - X stub; - stub.SerializeStub(_n1, _n2, _n3, _n4, _n5); - return SerializerConverter::FromObject(stub, _serializer_flags); - } }; #endif // End: SERIALIZER_MQH diff --git a/SerializerConversions.h b/SerializerConversions.h index 6dbdb1a73..4f5454a5e 100644 --- a/SerializerConversions.h +++ b/SerializerConversions.h @@ -30,6 +30,8 @@ #pragma once #endif +#include "Convert.extern.h" +#include "DateTime.extern.h" #include "Object.mqh" #include "Refs.struct.h" diff --git a/SerializerConverter.mqh b/SerializerConverter.mqh index 89f615609..c92bd14c2 100644 --- a/SerializerConverter.mqh +++ b/SerializerConverter.mqh @@ -23,6 +23,7 @@ // Prevents processing this includes file for the second time. #ifndef SERIALIZER_CONVERTER_MQH #define SERIALIZER_CONVERTER_MQH +#include "SerializerDict.mqh" // Forward declarations. class SerializerNode; @@ -30,6 +31,7 @@ class SerializerNode; // Includes. #include "File.mqh" #include "Serializer.enum.h" +#include "Serializer.mqh" #include "SerializerNode.mqh" class SerializerConverter { @@ -52,7 +54,7 @@ class SerializerConverter { return ""; } - return root_node.ToString(_json_flags); + return root_node PTR_DEREF ToString(_json_flags); } template @@ -118,7 +120,7 @@ class SerializerConverter { template string ToString(unsigned int stringify_flags = 0, void* stringify_aux_arg = NULL) { - string result = ((R*)NULL).Stringify(root_node, stringify_flags, stringify_aux_arg); + string result = ((R*)NULL)PTR_DEREF Stringify(root_node, stringify_flags, stringify_aux_arg); if ((_serializer_flags & SERIALIZER_FLAG_REUSE_OBJECT) == 0) { Clean(); } diff --git a/SerializerDict.mqh b/SerializerDict.mqh index 68ebde3fc..ddef3e957 100644 --- a/SerializerDict.mqh +++ b/SerializerDict.mqh @@ -33,16 +33,16 @@ class SerializerDict { public: template static void Extract(SerializerNode* _root, D& _dict, unsigned int extractor_flags = 0) { - if (_root.IsContainer()) { - for (unsigned int _data_entry_idx = 0; _data_entry_idx < _root.NumChildren(); ++_data_entry_idx) { - Extract(_root.GetChild(_data_entry_idx), _dict, extractor_flags); + if (_root PTR_DEREF IsContainer()) { + for (unsigned int _data_entry_idx = 0; _data_entry_idx < _root PTR_DEREF NumChildren(); ++_data_entry_idx) { + Extract(_root PTR_DEREF GetChild(_data_entry_idx), _dict, extractor_flags); } } else { - SerializerNodeParam* _value_param = _root.GetValueParam(); + SerializerNodeParam* _value_param = _root PTR_DEREF GetValueParam(); V _aux = (V)NULL; - _dict.Push(_value_param.ConvertTo(_aux)); + _dict.Push(_value_param PTR_DEREF ConvertTo(_aux)); } } }; diff --git a/SerializerJson.mqh b/SerializerJson.mqh index 82cb7bc98..f72daa01a 100644 --- a/SerializerJson.mqh +++ b/SerializerJson.mqh @@ -29,6 +29,7 @@ #include "Object.mqh" #include "Serializer.mqh" #include "SerializerNode.mqh" +#include "String.extern.h" class Log; @@ -64,10 +65,12 @@ class SerializerJson { repr += ident; - if (PTR_ATTRIB(_node, GetKeyParam()) != NULL && PTR_ATTRIB(PTR_ATTRIB(_node, GetKeyParam()), AsString(false, false)) != "") + if (PTR_ATTRIB(_node, GetKeyParam()) != NULL && + PTR_ATTRIB(PTR_ATTRIB(_node, GetKeyParam()), AsString(false, false)) != "") repr += PTR_ATTRIB(PTR_ATTRIB(_node, GetKeyParam()), AsString(false, true)) + ":" + (trimWhitespaces ? "" : " "); - if (PTR_ATTRIB(_node, GetValueParam()) != NULL) repr += PTR_ATTRIB(PTR_ATTRIB(_node, GetValueParam()), AsString(false, true)); + if (PTR_ATTRIB(_node, GetValueParam()) != NULL) + repr += PTR_ATTRIB(PTR_ATTRIB(_node, GetValueParam()), AsString(false, true)); switch (PTR_ATTRIB(_node, GetType())) { case SerializerNodeObject: @@ -76,6 +79,12 @@ class SerializerJson { case SerializerNodeArray: repr += string("[") + (trimWhitespaces ? "" : "\n"); break; + case SerializerNodeUnknown: + case SerializerNodeValue: + case SerializerNodeObjectProperty: + case SerializerNodeArrayItem: + break; + default:; } if (PTR_ATTRIB(_node, HasChildren())) { @@ -91,6 +100,11 @@ class SerializerJson { case SerializerNodeArray: repr += ident + "]"; break; + case SerializerNodeUnknown: + case SerializerNodeValue: + case SerializerNodeObjectProperty: + case SerializerNodeArrayItem: + default:; } if (!PTR_ATTRIB(_node, IsLast())) repr += ","; @@ -115,9 +129,7 @@ class SerializerJson { return false; } - Serializer serializer(node, JsonUnserialize); - - if (logger != NULL) serializer.Logger().Link(logger); + Serializer serializer(node, Unserialize); // We don't use result. We parse data as it is. obj.Serialize(serializer); @@ -126,11 +138,10 @@ class SerializerJson { } static SerializerNode* Parse(string data, unsigned int converter_flags = 0) { - SerializerNodeType type; if (StringGetCharacter(data, 0) == '{') - type = SerializerNodeObject; + ; else if (StringGetCharacter(data, 0) == '[') - type = SerializerNodeArray; + ; else { return GracefulReturn("Failed to parse JSON. It must start with either \"{\" or \"[\".", 0, NULL, NULL); } @@ -141,7 +152,6 @@ class SerializerJson { string extracted; - bool isOuterScope = true; bool expectingKey = false; bool expectingValue = false; bool expectingSemicolon = false; @@ -177,9 +187,10 @@ class SerializerJson { expectingKey = false; expectingSemicolon = true; } else if (expectingValue) { - PTR_ATTRIB(current, AddChild(new SerializerNode( - PTR_ATTRIB(current, GetType()) == SerializerNodeObject ? SerializerNodeObjectProperty : SerializerNodeArrayItem, - current, key, SerializerNodeParam::FromString(extracted)))); + PTR_ATTRIB(current, AddChild(new SerializerNode(PTR_ATTRIB(current, GetType()) == SerializerNodeObject + ? SerializerNodeObjectProperty + : SerializerNodeArrayItem, + current, key, SerializerNodeParam::FromString(extracted)))); #ifdef __debug__ Print("SerializerJson: Value \"" + extracted + "\" for key " + @@ -216,7 +227,6 @@ class SerializerJson { current = node; - isOuterScope = false; expectingValue = false; expectingKey = ch2 != '}'; key = NULL; @@ -250,7 +260,6 @@ class SerializerJson { current = node; expectingValue = ch2 != ']'; - isOuterScope = false; key = NULL; } else if (ch == ']') { #ifdef __debug__ @@ -279,9 +288,10 @@ class SerializerJson { (key != NULL ? ("\"" + key.ToString() + "\"") : "")); #endif - PTR_ATTRIB(current, AddChild(new SerializerNode( - PTR_ATTRIB(current, GetType()) == SerializerNodeObject ? SerializerNodeObjectProperty : SerializerNodeArrayItem, current, - key, value))); + PTR_ATTRIB(current, AddChild(new SerializerNode(PTR_ATTRIB(current, GetType()) == SerializerNodeObject + ? SerializerNodeObjectProperty + : SerializerNodeArrayItem, + current, key, value))); expectingValue = false; // Skipping value. @@ -302,9 +312,10 @@ class SerializerJson { // Skipping value. i += ch == 't' ? 3 : 4; - PTR_ATTRIB(current, AddChild(new SerializerNode( - PTR_ATTRIB(current, GetType()) == SerializerNodeObject ? SerializerNodeObjectProperty : SerializerNodeArrayItem, current, - key, value))); + PTR_ATTRIB(current, AddChild(new SerializerNode(PTR_ATTRIB(current, GetType()) == SerializerNodeObject + ? SerializerNodeObjectProperty + : SerializerNodeArrayItem, + current, key, value))); expectingValue = false; // We don't want to delete it twice. @@ -341,7 +352,7 @@ class SerializerJson { string str; for (unsigned int i = _idx; i < (unsigned int)StringLen(data); ++i) { -#ifdef __MQL5__ +#ifndef __MQL4__ unsigned short ch = StringGetCharacter(data, i); #else unsigned short ch = StringGetChar(data, i); diff --git a/SerializerNode.mqh b/SerializerNode.mqh index ef75ec19a..0b835c08c 100644 --- a/SerializerNode.mqh +++ b/SerializerNode.mqh @@ -25,8 +25,10 @@ #define JSON_NODE_MQH // Includes. +#include "Math.extern.h" #include "SerializerNode.enum.h" #include "SerializerNodeParam.mqh" +#include "Terminal.define.h" class SerializerNode { protected: @@ -137,7 +139,8 @@ class SerializerNode { _result += StringLen(PTR_ATTRIB(_value, _string)) + 1; break; default: - Print("Error: Wrong value type ", EnumToString(GetType()), "!"); + Print("Error: Wrong value type!"); + SetUserError(ERR_INVALID_PARAMETER); DebugBreak(); } } @@ -260,7 +263,7 @@ class SerializerNode { * Adds child to this node. */ void AddChild(SerializerNode* child) { - if (_numChildren == ArraySize(_children)) ArrayResize(_children, _numChildren + 10); + if (_numChildren == (unsigned int)ArraySize(_children)) ArrayResize(_children, _numChildren + 10); PTR_ATTRIB(child, _index) = (int)_numChildren; _children[_numChildren++] = child; @@ -329,6 +332,11 @@ class SerializerNode { case SerializerNodeArray: repr += string("[") + (trimWhitespaces ? "" : "\n"); break; + case SerializerNodeUnknown: + case SerializerNodeValue: + case SerializerNodeObjectProperty: + case SerializerNodeArrayItem: + default:; } if (HasChildren()) { @@ -344,6 +352,11 @@ class SerializerNode { case SerializerNodeArray: repr += ident + "]"; break; + case SerializerNodeUnknown: + case SerializerNodeValue: + case SerializerNodeObjectProperty: + case SerializerNodeArrayItem: + default:; } if (!IsLast()) repr += ","; diff --git a/SerializerNodeIterator.mqh b/SerializerNodeIterator.mqh index 3a1f0f00f..57acc5265 100644 --- a/SerializerNodeIterator.mqh +++ b/SerializerNodeIterator.mqh @@ -24,6 +24,7 @@ #ifndef JSON_ITERATOR_MQH #define JSON_ITERATOR_MQH +#include "Serializer.mqh" #include "SerializerNode.mqh" class SerializerNode; @@ -54,8 +55,7 @@ class SerializerNodeIterator { /** * Returns current node or NULL. */ - SerializerNode* Node() { return !IsValid() ? NULL : PTR_ATTRIB(_collection, GetChild(_index)); - } + SerializerNode* Node() { return !IsValid() ? NULL : PTR_ATTRIB(_collection, GetChild(_index)); } /** * Returns current node index. @@ -70,25 +70,23 @@ class SerializerNodeIterator { /** * Checks whether iterator is still valid. */ - bool IsValid() { return _index < PTR_ATTRIB(_collection, NumChildren()); - } + bool IsValid() { return _index < PTR_ATTRIB(_collection, NumChildren()); } /** * Returns current's child key or empty string. */ - const string Key() { return !IsValid() ? "" : PTR_ATTRIB(PTR_ATTRIB(_collection, GetChild(_index)), Key()); - } + const string Key() { return !IsValid() ? "" : PTR_ATTRIB(PTR_ATTRIB(_collection, GetChild(_index)), Key()); } /** * Checks whether current child has key. */ - bool HasKey() { return !IsValid() ? false : PTR_ATTRIB(PTR_ATTRIB(_collection, GetChild(_index)), HasKey()); - } + bool HasKey() { return !IsValid() ? false : PTR_ATTRIB(PTR_ATTRIB(_collection, GetChild(_index)), HasKey()); } /** * Checks whether current child is a container. */ - bool IsContainer() { return !IsValid() ? false : PTR_ATTRIB(PTR_ATTRIB(_collection, GetChild(_index)), IsContainer()); + bool IsContainer() { + return !IsValid() ? false : PTR_ATTRIB(PTR_ATTRIB(_collection, GetChild(_index)), IsContainer()); } }; @@ -114,17 +112,21 @@ class SerializerIterator : public SerializerNodeIterator { /** * Returns next value or value by given key. */ +#ifdef __MQL__ template <> +#endif X Value(string key = "") { X value; - _serializer.Pass(_serializer, key, value); + _serializer PTR_DEREF Pass(PTR_TO_REF(_serializer), key, value); return value; } /** * Returns next object or object by given key. */ +#ifdef __MQL__ template <> +#endif X Object(string key = "") { return Struct(key); } @@ -132,14 +134,16 @@ class SerializerIterator : public SerializerNodeIterator { /** * Returns next structure or structure by given key. */ +#ifdef __MQL__ template <> +#endif X Struct(string key = "") { X value; - _serializer.PassStruct(_serializer, key, value); + _serializer PTR_DEREF PassStruct(PTR_TO_REF(_serializer), key, value); return value; } - SerializerNodeType ParentNodeType() { return _collection.GetType(); } + SerializerNodeType ParentNodeType() { return _collection PTR_DEREF GetType(); } }; #endif diff --git a/Std.h b/Std.h index 1b7d70ab2..cd268432c 100644 --- a/Std.h +++ b/Std.h @@ -23,6 +23,7 @@ #ifndef __MQL__ // Allows the preprocessor to include a header file when it is needed. #pragma once +#include "Math.define.h" #endif // Data types. @@ -31,13 +32,6 @@ #include #include #include - -// Data types. -typedef std::string string; -typedef unsigned int uint; -typedef unsigned long datetime; -typedef unsigned long ulong; -typedef unsigned short ushort; #endif #ifdef __MQL__ @@ -50,13 +44,17 @@ typedef unsigned short ushort; #ifdef __MQL__ #define THIS_PTR (&this) #define THIS_REF this +#define PTR_DEREF . #define PTR_ATTRIB(O, A) O.A +#define PTR_ATTRIB2(O, A, B) O.A.B #define PTR_TO_REF(PTR) PTR #define MAKE_REF_FROM_PTR(TYPE, NAME, PTR) TYPE* NAME = PTR #else #define THIS_PTR (this) #define THIS_REF (*this) +#define PTR_DEREF -> #define PTR_ATTRIB(O, A) O->A +#define PTR_ATTRIB2(O, A, B) O->A->B #define PTR_TO_REF(PTR) (*PTR) #define MAKE_REF_FROM_PTR(TYPE, NAME, PTR) TYPE& NAME = PTR #endif @@ -69,6 +67,7 @@ typedef unsigned short ushort; #endif // Arrays and references to arrays. +#define _COMMA , #ifdef __MQL__ #define ARRAY_DECLARATION_BRACKETS [] #else @@ -157,7 +156,7 @@ class _cpp_array { /** * Returns number of elements in the array. */ - int size() const { return m_data.size(); } + int size() const { return (int)m_data.size(); } /** * Checks whether @@ -191,11 +190,6 @@ class color { }; #endif -// GetPointer(ptr). -#ifndef __MQL__ -unsigned int GetPointer(void* _ptr) { return (unsigned int)_ptr; } -#endif - // MQL defines. #ifndef __MQL__ #define WHOLE_ARRAY -1 // For processing the entire array. @@ -210,6 +204,12 @@ unsigned int GetPointer(void* _ptr) { return (unsigned int)_ptr; } const char* cstring_from(const std::string& _value) { return _value.c_str(); } #endif +#ifdef __cplusplus +using std::string; +#endif + +bool IsNull(const string& str) { return str == ""; } + /** * Referencing struct's enum. * @@ -223,224 +223,6 @@ const char* cstring_from(const std::string& _value) { return _value.c_str(); } #endif #ifndef __MQL__ -/** - * @file - * Includes MQL-compatible enumerations. - */ -enum ENUM_TRADE_REQUEST_ACTIONS { - // @see: https://www.mql5.com/en/docs/constants/tradingconstants/enum_trade_request_actions - TRADE_ACTION_DEAL, // Place a trade order for an immediate execution with the specified parameters (market order). - TRADE_ACTION_PENDING, // Place a trade order for the execution under specified conditions (pending order). - TRADE_ACTION_SLTP, // Modify Stop Loss and Take Profit values of an opened position. - TRADE_ACTION_MODIFY, // Modify the parameters of the order placed previously. - TRADE_ACTION_REMOVE, // Delete the pending order placed previously. - TRADE_ACTION_CLOSE_BY // Close a position by an opposite one. -}; -// Fill Policy. -enum ENUM_SYMBOL_FILLING { - // @see: https://www.mql5.com/en/docs/constants/tradingconstants/orderproperties - SYMBOL_FILLING_FOK = 1, // A deal can be executed only with the specified volume. - SYMBOL_FILLING_IOC = 2 // Trader agrees to execute a deal with the volume maximally available in the market. -}; -enum ENUM_ORDER_TYPE_FILLING { - // @see: https://www.mql5.com/en/docs/constants/tradingconstants/orderproperties - ORDER_FILLING_FOK, // An order can be filled only in the specified amount. - ORDER_FILLING_IOC, // A trader agrees to execute a deal with the volume maximally available in the market. - ORDER_FILLING_RETURN // In case of partial filling a market or limit order with remaining volume is not canceled but - // processed further. -}; -enum ENUM_ORDER_TYPE_TIME { - // @see: https://www.mql5.com/en/docs/constants/tradingconstants/orderproperties - ORDER_TIME_GTC, // Good till cancel order. - ORDER_TIME_DAY, // Good till current trade day order. - ORDER_TIME_SPECIFIED, // Good till expired order. - ORDER_TIME_SPECIFIED_DAY // The order will be effective till 23:59:59 of the specified day. -}; -// An order status that describes its state. -enum ENUM_ORDER_STATE { - ORDER_STATE_STARTED, // Order checked, but not yet accepted by broker - ORDER_STATE_PLACED, // Order accepted - ORDER_STATE_CANCELED, // Order canceled by client - ORDER_STATE_PARTIAL, // Order partially executed - ORDER_STATE_FILLED, // Order fully executed - ORDER_STATE_REJECTED, // Order rejected - ORDER_STATE_EXPIRED, // Order expired - ORDER_STATE_REQUEST_ADD, // Order is being registered (placing to the trading system) - ORDER_STATE_REQUEST_MODIFY, // Order is being modified (changing its parameters) - ORDER_STATE_REQUEST_CANCEL // Order is being deleted (deleting from the trading system) -}; - -// @see: https://www.mql5.com/en/docs/constants/structures/mqltraderequest -struct MqlTradeRequest { - ENUM_TRADE_REQUEST_ACTIONS action; // Trade operation type. - ulong magic; // Expert Advisor ID (magic number). - ulong order; // Order ticket. - string symbol; // Trade symbol. - double volume; // Requested volume for a deal in lots. - double price; // Price. - double stoplimit; // StopLimit level of the order. - double sl; // Stop Loss level of the order. - double tp; // Take Profit level of the order. - ulong deviation; // Maximal possible deviation from the requested price. - ENUM_ORDER_TYPE type; // Order type. - ENUM_ORDER_TYPE_FILLING type_filling; // Order execution type. - ENUM_ORDER_TYPE_TIME type_time; // Order expiration type. - datetime expiration; // Order expiration time (for the orders of ORDER_TIME_SPECIFIED type. - string comment; // Order comment. - ulong position; // Position ticket. - ulong position_by; // The ticket of an opposite position. -}; -// @see: https://www.mql5.com/en/docs/constants/structures/mqltraderesult -struct MqlTradeResult { - uint retcode; // Operation return code. - ulong deal; // Deal ticket, if it is performed. - ulong order; // Order ticket, if it is placed. - double volume; // Deal volume, confirmed by broker. - double price; // Deal price, confirmed by broker. - double bid; // Current Bid price. - double ask; // Current Ask price. - string comment; // Broker comment to operation (by default it is filled by description of trade server return code). - uint request_id; // Request ID set by the terminal during the dispatch. - uint retcode_external; // Return code of an external trading system. -}; - -#define ERR_USER_ERROR_FIRST 65536 // User defined errors start with this code. - -#define AliceBlue 0xFFF8F0 -#define AntiqueWhite 0xD7EBFA -#define Aqua 0xFFFF00 -#define Aquamarine 0xD4FF7F -#define Beige 0xDCF5F5 -#define Bisque 0xC4E4FF -#define Black 0x000000 -#define BlanchedAlmond 0xCDEBFF -#define Blue 0xFF0000 -#define BlueViolet 0xE22B8A -#define Brown 0x2A2AA5 -#define BurlyWood 0x87B8DE -#define CadetBlue 0xA09E5F -#define Chartreuse 0x00FF7F -#define Chocolate 0x1E69D2 -#define Coral 0x507FFF -#define CornflowerBlue 0xED9564 -#define Cornsilk 0xDCF8FF -#define Crimson 0x3C14DC -#define DarkBlue 0x8B0000 -#define DarkGoldenrod 0x0B86B8 -#define DarkGray 0xA9A9A9 -#define DarkGreen 0x006400 -#define DarkKhaki 0x6BB7BD -#define DarkOliveGreen 0x2F6B55 -#define DarkOrange 0x008CFF -#define DarkOrchid 0xCC3299 -#define DarkSalmon 0x7A96E9 -#define DarkSeaGreen 0x8BBC8F -#define DarkSlateBlue 0x8B3D48 -#define DarkSlateGray 0x4F4F2F -#define DarkTurquoise 0xD1CE00 -#define DarkViolet 0xD30094 -#define DeepPink 0x9314FF -#define DeepSkyBlue 0xFFBF00 -#define DimGray 0x696969 -#define DodgerBlue 0xFF901E -#define FireBrick 0x2222B2 -#define ForestGreen 0x228B22 -#define Gainsboro 0xDCDCDC -#define Gold 0x00D7FF -#define Goldenrod 0x20A5DA -#define Gray 0x808080 -#define Green 0x008000 -#define GreenYellow 0x2FFFAD -#define Honeydew 0xF0FFF0 -#define HotPink 0xB469FF -#define IndianRed 0x5C5CCD -#define Indigo 0x82004B -#define Ivory 0xF0FFFF -#define Khaki 0x8CE6F0 -#define Lavender 0xFAE6E6 -#define LavenderBlush 0xF5F0FF -#define LawnGreen 0x00FC7C -#define LemonChiffon 0xCDFAFF -#define LightBlue 0xE6D8AD -#define LightCoral 0x8080F0 -#define LightCyan 0xFFFFE0 -#define LightGoldenrod 0xD2FAFA -#define LightGray 0xD3D3D3 -#define LightGreen 0x90EE90 -#define LightPink 0xC1B6FF -#define LightSalmon 0x7AA0FF -#define LightSeaGreen 0xAAB220 -#define LightSkyBlue 0xFACE87 -#define LightSlateGray 0x998877 -#define LightSteelBlue 0xDEC4B0 -#define LightYellow 0xE0FFFF -#define Lime 0x00FF00 -#define LimeGreen 0x32CD32 -#define Linen 0xE6F0FA -#define Magenta 0xFF00FF -#define Maroon 0x000080 -#define MediumAquamarine 0xAACD66 -#define MediumBlue 0xCD0000 -#define MediumOrchid 0xD355BA -#define MediumPurple 0xDB7093 -#define MediumSeaGreen 0x71B33C -#define MediumSlateBlue 0xEE687B -#define MediumSpringGreen 0x9AFA00 -#define MediumTurquoise 0xCCD148 -#define MediumVioletRed 0x8515C7 -#define MidnightBlue 0x701919 -#define MintCream 0xFAFFF5 -#define MistyRose 0xE1E4FF -#define Moccasin 0xB5E4FF -#define NavajoWhite 0xADDEFF -#define Navy 0x800000 -#define OldLace 0xE6F5FD -#define Olive 0x008080 -#define OliveDrab 0x238E6B -#define Orange 0x00A5FF -#define OrangeRed 0x0045FF -#define Orchid 0xD670DA -#define PaleGoldenrod 0xAAE8EE -#define PaleGreen 0x98FB98 -#define PaleTurquoise 0xEEEEAF -#define PaleVioletRed 0x9370DB -#define PapayaWhip 0xD5EFFF -#define PeachPuff 0xB9DAFF -#define Peru 0x3F85CD -#define Pink 0xCBC0FF -#define Plum 0xDDA0DD -#define PowderBlue 0xE6E0B0 -#define Purple 0x800080 -#define Red 0x0000FF -#define RosyBrown 0x8F8FBC -#define RoyalBlue 0xE16941 -#define SaddleBrown 0x13458B -#define Salmon 0x7280FA -#define SandyBrown 0x60A4F4 -#define SeaGreen 0x578B2E -#define Seashell 0xEEF5FF -#define Sienna 0x2D52A0 -#define Silver 0xC0C0C0 -#define SkyBlue 0xEBCE87 -#define SlateBlue 0xCD5A6A -#define SlateGray 0x908070 -#define Snow 0xFAFAFF -#define SpringGreen 0x7FFF00 -#define SteelBlue 0xB48246 -#define Tan 0x8CB4D2 -#define Teal 0x808000 -#define Thistle 0xD8BFD8 -#define Tomato 0x4763FF -#define Turquoise 0xD0E040 -#define Violet 0xEE82EE -#define Wheat 0xB3DEF5 -#define White 0xFFFFFF -#define WhiteSmoke 0xF5F5F5 -#define Yellow 0x00FFFF -#define YellowGreen 0x32CD9A -#define clrNONE -1 -#define CLR_NONE -1 - // Additional enum values for ENUM_SYMBOL_INFO_DOUBLE #define SYMBOL_MARGIN_LIMIT ((ENUM_SYMBOL_INFO_DOUBLE)46) #define SYMBOL_MARGIN_MAINTENANCE ((ENUM_SYMBOL_INFO_DOUBLE)43) @@ -448,44 +230,14 @@ struct MqlTradeResult { #define SYMBOL_MARGIN_SHORT ((ENUM_SYMBOL_INFO_DOUBLE)45) #define SYMBOL_MARGIN_STOP ((ENUM_SYMBOL_INFO_DOUBLE)47) #define SYMBOL_MARGIN_STOPLIMIT ((ENUM_SYMBOL_INFO_DOUBLE)48) - -#define TRADE_RETCODE_REQUOTE 10004 // Requote -#define TRADE_RETCODE_REJECT 10006 // Request rejected -#define TRADE_RETCODE_CANCEL 10007 // Request canceled by trader -#define TRADE_RETCODE_PLACED 10008 // Order placed -#define TRADE_RETCODE_DONE 10009 // Request completed -#define TRADE_RETCODE_DONE_PARTIAL 10010 // Only part of the request was completed -#define TRADE_RETCODE_ERROR 10011 // Request processing error -#define TRADE_RETCODE_TIMEOUT 10012 // Request canceled by timeout -#define TRADE_RETCODE_INVALID 10013 // Invalid request -#define TRADE_RETCODE_INVALID_VOLUME 10014 // Invalid volume in the request -#define TRADE_RETCODE_INVALID_PRICE 10015 // Invalid price in the request -#define TRADE_RETCODE_INVALID_STOPS 10016 // Invalid stops in the request -#define TRADE_RETCODE_TRADE_DISABLED 10017 // Trade is disabled -#define TRADE_RETCODE_MARKET_CLOSED 10018 // Market is closed -#define TRADE_RETCODE_NO_MONEY 10019 // There is not enough money to complete the request -#define TRADE_RETCODE_PRICE_CHANGED 10020 // Prices changed -#define TRADE_RETCODE_PRICE_OFF 10021 // There are no quotes to process the request -#define TRADE_RETCODE_INVALID_EXPIRATION 10022 // Invalid order expiration date in the request -#define TRADE_RETCODE_ORDER_CHANGED 10023 // Order state changed -#define TRADE_RETCODE_TOO_MANY_REQUESTS 10024 // Too frequent requests -#define TRADE_RETCODE_NO_CHANGES 10025 // No changes in request -#define TRADE_RETCODE_SERVER_DISABLES_AT 10026 // Autotrading disabled by server -#define TRADE_RETCODE_CLIENT_DISABLES_AT 10027 // Autotrading disabled by client terminal -#define TRADE_RETCODE_LOCKED 10028 // Request locked for processing -#define TRADE_RETCODE_FROZEN 10029 // Order or position frozen -#define TRADE_RETCODE_INVALID_FILL 10030 // Invalid order filling type -#define TRADE_RETCODE_CONNECTION 10031 // No connection with the trade server -#define TRADE_RETCODE_ONLY_REAL 10032 // Operation is allowed only for live accounts -#define TRADE_RETCODE_LIMIT_ORDERS 10033 // The number of pending orders has reached the limit -#define TRADE_RETCODE_LIMIT_VOLUME 10034 // The volume of orders and positions for the symbol has reached the limit -#define TRADE_RETCODE_INVALID_ORDER 10035 // Incorrect or prohibited order type -#define TRADE_RETCODE_POSITION_CLOSED 10036 // Position with the specified POSITION_IDENTIFIER has already been closed -#define TRADE_RETCODE_INVALID_CLOSE_VOLUME 10038 // A close volume exceeds the current position volume -#define TRADE_RETCODE_CLOSE_ORDER_EXIST 10039 // A close order already exists. -#define TRADE_RETCODE_LIMIT_POSITIONS 10040 // The number of open positions can be limited (e.g. Netting, Hedging). #endif +template +class InvalidEnumValue { + public: + static T value() { return (T)INT_MAX; } +}; + #ifndef __MQL__ // Converter of NULL_VALUE into expected type. e.g., "int x = NULL_VALUE" will end up with "x = 0". struct _NULL_VALUE { diff --git a/Storage/ValueStorage.indicator.h b/Storage/ValueStorage.indicator.h index e363559b2..6744660e6 100644 --- a/Storage/ValueStorage.indicator.h +++ b/Storage/ValueStorage.indicator.h @@ -31,7 +31,7 @@ #endif // Forward declarations. -class IndicatorBase; +class IndicatorData; // Includes. #include "ValueStorage.history.h" @@ -42,7 +42,7 @@ class IndicatorBase; template class IndicatorBufferValueStorage : public HistoryValueStorage { // Pointer to indicator to access data from. - IndicatorBase *indicator; + IndicatorData *indicator; // Mode of the target indicator. int mode; @@ -51,8 +51,8 @@ class IndicatorBufferValueStorage : public HistoryValueStorage { /** * Constructor. */ - IndicatorBufferValueStorage(IndicatorBase *_indi, int _mode = 0, bool _is_series = false) - : indicator(_indi), mode(_mode), HistoryValueStorage(_indi.GetSymbol(), _indi.GetTf()) {} + IndicatorBufferValueStorage(IndicatorData *_indi, int _mode = 0, ENUM_TIMEFRAMES _tf = NULL, bool _is_series = false) + : indicator(_indi), mode(_mode), HistoryValueStorage(_indi.GetSymbol(), _tf) {} /** * Fetches value from a given shift. Takes into consideration as-series flag. diff --git a/Strategy.mqh b/Strategy.mqh index 624ea4654..2e79fe926 100644 --- a/Strategy.mqh +++ b/Strategy.mqh @@ -1251,13 +1251,12 @@ class Strategy : public Object { int _count = (int)fmax(fabs(_level), fabs(_method)); int _direction = Order::OrderDirection(_cmd, _mode); Chart *_chart = trade.GetChart(); - IndicatorBase *_indi = GetIndicators().Begin().Value().Ptr(); + IndicatorData *_indi = GetIndicators().Begin().Value().Ptr(); StrategyPriceStop _psm(_method); _psm.SetChartParams(_chart.GetParams()); if (Object::IsValid(_indi)) { int _ishift = 12; // @todo: Make it dynamic or as variable. - float _value = 0.0f; // @todo - //float _value = _indi.GetValuePrice(_ishift, 0, _direction > 0 ? PRICE_HIGH : PRICE_LOW); + 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); /* diff --git a/String.extern.h b/String.extern.h new file mode 100644 index 000000000..04f359fef --- /dev/null +++ b/String.extern.h @@ -0,0 +1,42 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2022, 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 __MQL__ +#pragma once +#include "Terminal.define.h" +#endif + +// Define external global functions. +#ifndef __MQL__ +extern double StringToDouble(string value); +extern int StringFind(string string_value, string match_substring, int start_pos = 0); +extern int StringLen(string string_value); +extern int StringSplit(const string& string_value, const unsigned short separator, ARRAY_REF(string, result)); +extern long StringToInteger(string value); +extern string IntegerToString(long number, int str_len = 0, ushort fill_symbol = ' '); +extern string StringFormat(string format, ...); +extern string StringSubstr(string string_value, int start_pos, int length = -1); +extern ushort StringGetCharacter(string string_value, int pos); +int StringToCharArray(string text_string, ARRAY_REF(uchar, array), int start = 0, int count = -1, + uint codepage = CP_ACP); +#endif diff --git a/String.mqh b/String.mqh index 3acccfd30..ab240c4db 100644 --- a/String.mqh +++ b/String.mqh @@ -25,7 +25,9 @@ #define STRING_MQH // Includes. +#include "Array.extern.h" #include "Std.h" +#include "String.extern.h" // Defines. #define NL "\n" // New line: 0x0A (MQL file functions auto-convert 0x0A to 0x0D0A). diff --git a/SymbolInfo.define.h b/SymbolInfo.define.h index 68ef4c107..960369f2d 100644 --- a/SymbolInfo.define.h +++ b/SymbolInfo.define.h @@ -32,3 +32,13 @@ #define Point _Point #define Digits _Digits #endif + +#ifndef __MQL__ +// Additional enum values for ENUM_SYMBOL_INFO_DOUBLE +#define SYMBOL_MARGIN_LIMIT ((ENUM_SYMBOL_INFO_DOUBLE)46) +#define SYMBOL_MARGIN_MAINTENANCE ((ENUM_SYMBOL_INFO_DOUBLE)43) +#define SYMBOL_MARGIN_LONG ((ENUM_SYMBOL_INFO_DOUBLE)44) +#define SYMBOL_MARGIN_SHORT ((ENUM_SYMBOL_INFO_DOUBLE)45) +#define SYMBOL_MARGIN_STOP ((ENUM_SYMBOL_INFO_DOUBLE)47) +#define SYMBOL_MARGIN_STOPLIMIT ((ENUM_SYMBOL_INFO_DOUBLE)48) +#endif diff --git a/SymbolInfo.enum.h b/SymbolInfo.enum.h index 59a3ffdfc..43b625853 100644 --- a/SymbolInfo.enum.h +++ b/SymbolInfo.enum.h @@ -31,6 +31,13 @@ #endif #ifndef __MQL5__ +// Fill Policy. +enum ENUM_SYMBOL_FILLING { + // @see: https://www.mql5.com/en/docs/constants/tradingconstants/orderproperties + SYMBOL_FILLING_FOK = 1, // A deal can be executed only with the specified volume. + SYMBOL_FILLING_IOC = 2 // Trader agrees to execute a deal with the volume maximally available in the market. +}; + // Methods of swap calculation at position transfer. // @see: https://www.mql5.com/en/docs/constants/environment_state/marketinfoconstants#enum_symbol_swap_mode enum ENUM_SYMBOL_SWAP_MODE { diff --git a/SymbolInfo.extern.h b/SymbolInfo.extern.h new file mode 100644 index 000000000..801c47fb1 --- /dev/null +++ b/SymbolInfo.extern.h @@ -0,0 +1,37 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2022, 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 "Order.enum.h" +#include "SymbolInfo.enum.h" +#include "Tick.struct.h" + +// Define external global functions. +#ifndef __MQL__ +extern long SymbolInfoInteger(string name, ENUM_SYMBOL_INFO_INTEGER prop_id); +extern bool SymbolInfoMarginRate(string name, ENUM_ORDER_TYPE order_type, double &initial_margin_rate, + double &maintenance_margin_rate); +extern bool SymbolInfoTick(string symbol, MqlTick &tick); + +// Define external global variables. +extern string _Symbol; +#endif diff --git a/SymbolInfo.mqh b/SymbolInfo.mqh index 226ace580..92377deb6 100644 --- a/SymbolInfo.mqh +++ b/SymbolInfo.mqh @@ -31,6 +31,7 @@ class SymbolInfo; #include "SymbolInfo.define.h" #include "SymbolInfo.enum.h" #include "SymbolInfo.enum.symbols.h" +#include "SymbolInfo.extern.h" #include "SymbolInfo.struct.h" #include "SymbolInfo.struct.static.h" @@ -58,7 +59,7 @@ class SymbolInfo : public Object { public: /** - * Implements class constructor with a parameter. + * Class constructor given a symbol string. */ SymbolInfo(string _symbol = NULL) : symbol(_symbol), pip_size(GetPipSize()), symbol_digits(GetDigits()) { Select(); @@ -73,6 +74,16 @@ class SymbolInfo : public Object { } } + /** + * Class constructor with symbol properties. + */ + SymbolInfo(const SymbolInfoProp &_sip) : sprops(_sip) {} + + /** + * Class copy constructor. + */ + SymbolInfo(const SymbolInfo &_si) : s_entry(_si.s_entry), sprops(_si.sprops) {} + ~SymbolInfo() {} /** diff --git a/SymbolInfo.struct.h b/SymbolInfo.struct.h index 3e7b94bc8..731a2562a 100644 --- a/SymbolInfo.struct.h +++ b/SymbolInfo.struct.h @@ -32,8 +32,9 @@ // Includes. #include "ISerializable.h" -#include "Tick.struct.h" +#include "Std.h" #include "SymbolInfo.struct.static.h" +#include "Tick.struct.h" // Defines struct to store symbol data. struct SymbolInfoEntry @@ -46,7 +47,7 @@ struct SymbolInfoEntry double last; // Price of the last deal. double spread; // Current spread. unsigned long volume; // Volume for the current last price. - // Constructor. + // Constructors. SymbolInfoEntry() : bid(0), ask(0), last(0), spread(0), volume(0) {} SymbolInfoEntry(const MqlTick& _tick, const string _symbol = "") { bid = _tick.bid; @@ -55,6 +56,8 @@ struct SymbolInfoEntry volume = _tick.volume; spread = (unsigned int)round((ask - bid) * pow(10, SymbolInfoStatic::SymbolInfoInteger(_symbol, SYMBOL_DIGITS))); } + // Copy constructor. + SymbolInfoEntry(const SymbolInfoEntry& _sie) { this = _sie; } // Getters string ToCSV() { return StringFormat("%g,%g,%g,%g,%d", bid, ask, last, spread, volume); } // Serializers. @@ -72,6 +75,9 @@ struct SymbolInfoProp { unsigned int pip_digits; // Pip digits (precision). unsigned int pts_per_pip; // Points per pip. unsigned int vol_digits; // Volume digits. + // Constructors. + SymbolInfoProp() {} + SymbolInfoProp(const SymbolInfoProp& _sip) {} // Serializers. void SerializeStub(int _n1 = 1, int _n2 = 1, int _n3 = 1, int _n4 = 1, int _n5 = 1) {} SerializerNodeType Serialize(Serializer& _s); diff --git a/SymbolInfo.struct.static.h b/SymbolInfo.struct.static.h index 19c54c378..be343fb7b 100644 --- a/SymbolInfo.struct.static.h +++ b/SymbolInfo.struct.static.h @@ -26,8 +26,9 @@ #endif #include "MQL5.mqh" -#include "Tick.struct.h" +#include "Order.enum.h" #include "Std.h" +#include "Tick.struct.h" /** * Struct to provide symbol information. @@ -135,9 +136,8 @@ struct SymbolInfoStatic { * */ static unsigned int GetPointsPerPip(string _symbol) { - // To be used to replace Point for trade parameters calculations. - // See: https://www.mql5.com/en/forum/124692 - return (unsigned int)pow(10, SymbolInfoStatic::GetDigits(_symbol) - SymbolInfoStatic::GetPipDigits(_symbol)); + return (unsigned int)pow((unsigned int)10, + SymbolInfoStatic::GetDigits(_symbol) - SymbolInfoStatic::GetPipDigits(_symbol)); } /** @@ -263,7 +263,7 @@ struct SymbolInfoStatic { * Get real spread based on the ask and bid price (in points). */ static unsigned int GetRealSpread(double _bid, double _ask, unsigned int _digits) { - return (unsigned int)round((_ask - _bid) * pow(10, _digits)); + return (unsigned int)round((_ask - _bid) * pow((unsigned int)10, _digits)); } static unsigned int GetRealSpread(string _symbol) { return GetRealSpread(SymbolInfoStatic::GetBid(_symbol), SymbolInfoStatic::GetAsk(_symbol), diff --git a/Terminal.define.h b/Terminal.define.h index b68e5561c..a1bbda2d1 100644 --- a/Terminal.define.h +++ b/Terminal.define.h @@ -27,6 +27,154 @@ /* Defines */ +// Codepages. +// @see: https://www.mql5.com/en/docs/constants/io_constants/codepageusage +#define CP_ACP 0 // The current Windows ANSI code page. +#define CP_OEMCP 1 // The current system OEM code page. +#define CP_MACCP 2 // The current system Macintosh code page. +#define CP_THREAD_ACP 3 // The Windows ANSI code page for the current thread. +#define CP_SYMBOL 42 // Symbol code page +#define CP_UTF7 65000 // UTF-7 code page. +#define CP_UTF8 65001 // UTF-8 code page. + +// Colors. +#define AliceBlue 0xFFF8F0 +#define AntiqueWhite 0xD7EBFA +#define Aqua 0xFFFF00 +#define Aquamarine 0xD4FF7F +#define Beige 0xDCF5F5 +#define Bisque 0xC4E4FF +#define Black 0x000000 +#define BlanchedAlmond 0xCDEBFF +#define Blue 0xFF0000 +#define BlueViolet 0xE22B8A +#define Brown 0x2A2AA5 +#define BurlyWood 0x87B8DE +#define CadetBlue 0xA09E5F +#define Chartreuse 0x00FF7F +#define Chocolate 0x1E69D2 +#define Coral 0x507FFF +#define CornflowerBlue 0xED9564 +#define Cornsilk 0xDCF8FF +#define Crimson 0x3C14DC +#define DarkBlue 0x8B0000 +#define DarkGoldenrod 0x0B86B8 +#define DarkGray 0xA9A9A9 +#define DarkGreen 0x006400 +#define DarkKhaki 0x6BB7BD +#define DarkOliveGreen 0x2F6B55 +#define DarkOrange 0x008CFF +#define DarkOrchid 0xCC3299 +#define DarkSalmon 0x7A96E9 +#define DarkSlateBlue 0x8B3D48 +#define DarkSlateGray 0x4F4F2F +#define DarkTurquoise 0xD1CE00 +#define DarkViolet 0xD30094 +#define DeepPink 0x9314FF +#define DeepSkyBlue 0xFFBF00 +#define DimGray 0x696969 +#define DodgerBlue 0xFF901E +#define FireBrick 0x2222B2 +#define ForestGreen 0x228B22 +#define Gainsboro 0xDCDCDC +#define Gold 0x00D7FF +#define Goldenrod 0x20A5DA +#define Gray 0x808080 +#define Green 0x008000 +#define GreenYellow 0x2FFFAD +#define Honeydew 0xF0FFF0 +#define HotPink 0xB469FF +#define IndianRed 0x5C5CCD +#define Indigo 0x82004B +#define Ivory 0xF0FFFF +#define Khaki 0x8CE6F0 +#define Lavender 0xFAE6E6 +#define LavenderBlush 0xF5F0FF +#define LawnGreen 0x00FC7C +#define LemonChiffon 0xCDFAFF +#define LightBlue 0xE6D8AD +#define LightCoral 0x8080F0 +#define LightCyan 0xFFFFE0 +#define LightGoldenrod 0xD2FAFA +#define LightGray 0xD3D3D3 +#define LightGreen 0x90EE90 +#define LightPink 0xC1B6FF +#define LightSalmon 0x7AA0FF +#define LightSeaGreen 0xAAB220 +#define LightSkyBlue 0xFACE87 +#define LightSlateGray 0x998877 +#define LightSteelBlue 0xDEC4B0 +#define LightYellow 0xE0FFFF +#define Lime 0x00FF00 +#define LimeGreen 0x32CD32 +#define Linen 0xE6F0FA +#define Magenta 0xFF00FF +#define Maroon 0x000080 +#define MediumAquamarine 0xAACD66 +#define MediumBlue 0xCD0000 +#define MediumOrchid 0xD355BA +#define MediumPurple 0xDB7093 +#define MediumSeaGreen 0x71B33C +#define MediumSlateBlue 0xEE687B +#define MediumSpringGreen 0x9AFA00 +#define MediumTurquoise 0xCCD148 +#define MediumVioletRed 0x8515C7 +#define MidnightBlue 0x701919 +#define MintCream 0xFAFFF5 +#define MistyRose 0xE1E4FF +#define Moccasin 0xB5E4FF +#define NavajoWhite 0xADDEFF +#define Navy 0x800000 +#define OldLace 0xE6F5FD +#define Olive 0x008080 +#define OliveDrab 0x238E6B +#define Orange 0x00A5FF +#define OrangeRed 0x0045FF +#define Orchid 0xD670DA +#define PaleGoldenrod 0xAAE8EE +#define PaleGreen 0x98FB98 +#define PaleTurquoise 0xEEEEAF +#define PaleVioletRed 0x9370DB +#define PapayaWhip 0xD5EFFF +#define PeachPuff 0xB9DAFF +#define Peru 0x3F85CD +#define Pink 0xCBC0FF +#define Plum 0xDDA0DD +#define PowderBlue 0xE6E0B0 +#define Purple 0x800080 +#define Red 0x0000FF +#define RosyBrown 0x8F8FBC +#define RoyalBlue 0xE16941 +#define SaddleBrown 0x13458B +#define Salmon 0x7280FA +#define SandyBrown 0x60A4F4 +#define SeaGreen 0x578B2E +#define Seashell 0xEEF5FF +#define Sienna 0x2D52A0 +#define Silver 0xC0C0C0 +#define SkyBlue 0xEBCE87 +#define SlateBlue 0xCD5A6A +#define SlateGray 0x908070 +#define Snow 0xFAFAFF +#define SpringGreen 0x7FFF00 +#define SteelBlue 0xB48246 +#define Tan 0x8CB4D2 +#define Teal 0x808000 +#define Thistle 0xD8BFD8 +#define Tomato 0x4763FF +#define Turquoise 0xD0E040 +#define Violet 0xEE82EE +#define Wheat 0xB3DEF5 +#define White 0xFFFFFF +#define WhiteSmoke 0xF5F5F5 +#define Yellow 0x00FFFF +#define YellowGreen 0x32CD9A +#ifndef __MQL__ +#define clrNONE -1 +#define CLR_NONE -1 +#define DarkSeaGreen 0x8BBC8F +#endif + // Custom user errors. // @docs // - https://docs.mql4.com/common/setusererror @@ -40,6 +188,7 @@ #define ERR_USER_INVALID_HANDLE 4 #define ERR_USER_ITEM_NOT_FOUND 5 #define ERR_USER_NOT_SUPPORTED 6 +#define ERR_USER_ERROR_FIRST 65536 // User defined errors start with this code. // Return codes of the trade server. #define ERR_NO_ERROR 0 @@ -75,6 +224,46 @@ #define ERR_TRADE_HEDGE_PROHIBITED 149 #define ERR_TRADE_PROHIBITED_BY_FIFO 150 +#ifndef __MQL__ +// Return Codes of the Trade Server. +// @see: https://www.mql5.com/en/docs/constants/errorswarnings/enum_trade_return_codes +#define TRADE_RETCODE_REQUOTE 10004 // Requote +#define TRADE_RETCODE_REJECT 10006 // Request rejected +#define TRADE_RETCODE_CANCEL 10007 // Request canceled by trader +#define TRADE_RETCODE_PLACED 10008 // Order placed +#define TRADE_RETCODE_DONE 10009 // Request completed +#define TRADE_RETCODE_DONE_PARTIAL 10010 // Only part of the request was completed +#define TRADE_RETCODE_ERROR 10011 // Request processing error +#define TRADE_RETCODE_TIMEOUT 10012 // Request canceled by timeout +#define TRADE_RETCODE_INVALID 10013 // Invalid request +#define TRADE_RETCODE_INVALID_VOLUME 10014 // Invalid volume in the request +#define TRADE_RETCODE_INVALID_PRICE 10015 // Invalid price in the request +#define TRADE_RETCODE_INVALID_STOPS 10016 // Invalid stops in the request +#define TRADE_RETCODE_TRADE_DISABLED 10017 // Trade is disabled +#define TRADE_RETCODE_MARKET_CLOSED 10018 // Market is closed +#define TRADE_RETCODE_NO_MONEY 10019 // There is not enough money to complete the request +#define TRADE_RETCODE_PRICE_CHANGED 10020 // Prices changed +#define TRADE_RETCODE_PRICE_OFF 10021 // There are no quotes to process the request +#define TRADE_RETCODE_INVALID_EXPIRATION 10022 // Invalid order expiration date in the request +#define TRADE_RETCODE_ORDER_CHANGED 10023 // Order state changed +#define TRADE_RETCODE_TOO_MANY_REQUESTS 10024 // Too frequent requests +#define TRADE_RETCODE_NO_CHANGES 10025 // No changes in request +#define TRADE_RETCODE_SERVER_DISABLES_AT 10026 // Autotrading disabled by server +#define TRADE_RETCODE_CLIENT_DISABLES_AT 10027 // Autotrading disabled by client terminal +#define TRADE_RETCODE_LOCKED 10028 // Request locked for processing +#define TRADE_RETCODE_FROZEN 10029 // Order or position frozen +#define TRADE_RETCODE_INVALID_FILL 10030 // Invalid order filling type +#define TRADE_RETCODE_CONNECTION 10031 // No connection with the trade server +#define TRADE_RETCODE_ONLY_REAL 10032 // Operation is allowed only for live accounts +#define TRADE_RETCODE_LIMIT_ORDERS 10033 // The number of pending orders has reached the limit +#define TRADE_RETCODE_LIMIT_VOLUME 10034 // The volume of orders and positions for the symbol has reached the limit +#define TRADE_RETCODE_INVALID_ORDER 10035 // Incorrect or prohibited order type +#define TRADE_RETCODE_POSITION_CLOSED 10036 // Position with the specified POSITION_IDENTIFIER has already been closed +#define TRADE_RETCODE_INVALID_CLOSE_VOLUME 10038 // A close volume exceeds the current position volume +#define TRADE_RETCODE_CLOSE_ORDER_EXIST 10039 // A close order already exists. +#define TRADE_RETCODE_LIMIT_POSITIONS 10040 // The number of open positions can be limited (e.g. Netting, Hedging). +#endif + // Missing error handling constants in MQL4. // @see: https://docs.mql4.com/constants/errorswarnings/errorcodes // @see: https://www.mql5.com/en/docs/constants/errorswarnings diff --git a/Terminal.extern.h b/Terminal.extern.h new file mode 100644 index 000000000..65582439f --- /dev/null +++ b/Terminal.extern.h @@ -0,0 +1,28 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2022, 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 . + * + */ + +// Define external global functions. +#ifndef __MQL__ +extern int GetLastError(); +extern string TerminalInfoString(int property_id); +extern void ResetLastError(); +#endif diff --git a/Terminal.mqh b/Terminal.mqh index d408480a3..77aa28d13 100644 --- a/Terminal.mqh +++ b/Terminal.mqh @@ -43,6 +43,7 @@ class Terminal; #include "Refs.mqh" #include "String.mqh" #include "Terminal.define.h" +#include "Terminal.extern.h" #include "Terminal.enum.h" #include "Terminal.struct.h" diff --git a/Tick.struct.h b/Tick.struct.h index 0d36f8095..dbb226a4f 100644 --- a/Tick.struct.h +++ b/Tick.struct.h @@ -29,6 +29,27 @@ #pragma once #endif +// Includes. +#include "DateTime.extern.h" + +#ifndef __MQL__ +/** + * Structure for storing the latest prices of the symbol. + * @docs + * https://www.mql5.com/en/docs/constants/structures/mqltick + */ +struct MqlTick { + datetime time; // Time of the last prices update. + double ask; // Current Ask price. + double bid; // Current Bid price. + double last; // Price of the last deal (last). + double volume_real; // Volume for the current last price with greater accuracy. + long time_msc; // Time of a price last update in milliseconds. + unsigned int flags; // Tick flags. + unsigned long volume; // Volume for the current last price. +}; +#endif + /** * Structure for storing ask and bid prices of the symbol. */ @@ -48,24 +69,6 @@ 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) {} - TickTAB(MqlTick &_tick) : time(_tick.time), TickAB(_tick) {} + TickTAB(datetime _time = 0, T _ask = 0, T _bid = 0) : time(_time), TickAB(_ask, _bid) {} + TickTAB(MqlTick &_tick) : time(_tick.time), TickAB(_tick) {} }; - -#ifndef __MQL__ -/** - * Structure for storing the latest prices of the symbol. - * @docs - * https://www.mql5.com/en/docs/constants/structures/mqltick - */ -struct MqlTick { - datetime time; // Time of the last prices update. - double ask; // Current Ask price. - double bid; // Current Bid price. - double last; // Price of the last deal (last). - double volume_real; // Volume for the current last price with greater accuracy. - long time_msc; // Time of a price last update in milliseconds. - unsigned int flags; // Tick flags. - unsigned long volume; // Volume for the current last price. -}; -#endif diff --git a/Tick/tests/TickManager.test.mq5 b/Tick/tests/TickManager.test.mq5 index a2b36637a..1c54f9b2a 100644 --- a/Tick/tests/TickManager.test.mq5 +++ b/Tick/tests/TickManager.test.mq5 @@ -36,7 +36,7 @@ TickManager tm; int OnInit() { bool _result = true; // ... - return _result && GetLastError() == ERR_NO_ERROR ? INIT_SUCCEEDED : INIT_FAILED; + return _result && GetLastError() == 0 ? INIT_SUCCEEDED : INIT_FAILED; } /** diff --git a/Ticker.mqh b/Ticker.mqh index 0e56e424d..a02bccd5c 100644 --- a/Ticker.mqh +++ b/Ticker.mqh @@ -145,7 +145,7 @@ class Ticker { return true; } bool Add() { - MqlTick _tick = this.symbol.GetTick(); + MqlTick _tick = this PTR_DEREF symbol.GetTick(); return Add(_tick); } @@ -172,8 +172,8 @@ class Ticker { FileWrite(_handle, "Datatime", "Bid", "Ask", "Volume"); for (int i = 0; i < index; i++) { if (data[i].time > 0) { - FileWrite(_handle, DateTimeStatic::TimeToStr(data[i].time, TIME_DATE | TIME_MINUTES | TIME_SECONDS), data[i].bid, - data[i].ask, data[i].volume); + FileWrite(_handle, DateTimeStatic::TimeToStr(data[i].time, TIME_DATE | TIME_MINUTES | TIME_SECONDS), + data[i].bid, data[i].ask, data[i].volume); total_saved++; } } diff --git a/Timer.mqh b/Timer.mqh index e772306d7..986556b08 100644 --- a/Timer.mqh +++ b/Timer.mqh @@ -28,140 +28,115 @@ * Class to provide functions to deal with the timer. */ class Timer : public Object { - - protected: - - // Variables. - string name; - int index; - uint data[]; - uint start, end; - ulong max; - - public: - - /** - * Class constructor. - */ - Timer(string _name = "") : index(-1), name(_name) { }; - - /* Main methods */ - - /** - * Start the timer. - */ - void Start() { - start = GetTickCount(); - } - - /** - * Stop the timer. - */ - Timer *Stop() { - end = GetTickCount(); - ArrayResize(this.data, ++this.index + 1, 10000); - data[this.index] = fabs(this.end - this.start); - max = fmax(data[this.index], this.max); - return GetPointer(this); - } - - /* Misc */ - - /** - * Print the current timer times. - */ - Timer *PrintSummary() { - Print(ToString()); - return GetPointer(this); - } - - /** - * Print the current timer times when maximum value is reached. - */ - Timer *PrintOnMax(ulong _min = 1) { - return - data[index] > _min && data[this.index] >= this.max - ? PrintSummary() - : GetPointer(this); - } - - /* Getters */ - - /** - * Stop the timer. - */ - uint GetTime(uint _index) { - return data[_index]; + protected: + // Variables. + string name; + int index; + uint data[]; + uint start, end; + ulong max; + + public: + /** + * Class constructor. + */ + Timer(string _name = "") : index(-1), name(_name){}; + + /* Main methods */ + + /** + * Start the timer. + */ + void Start() { start = GetTickCount(); } + + /** + * Stop the timer. + */ + Timer *Stop() { + end = GetTickCount(); + ArrayResize(this PTR_DEREF data, ++this PTR_DEREF index + 1, 10000); + data[this PTR_DEREF index] = fabs(this PTR_DEREF end - this PTR_DEREF start); + max = fmax(data[this PTR_DEREF index], this PTR_DEREF max); + return GetPointer(this); + } + + /* Misc */ + + /** + * Print the current timer times. + */ + Timer *PrintSummary() { + Print(ToString()); + return GetPointer(this); + } + + /** + * Print the current timer times when maximum value is reached. + */ + Timer *PrintOnMax(ulong _min = 1) { + return data[index] > _min && data[this PTR_DEREF index] >= this PTR_DEREF max ? PrintSummary() : GetPointer(this); + } + + /* Getters */ + + /** + * Stop the timer. + */ + uint GetTime(uint _index) { return data[_index]; } + uint GetTime() { return GetTickCount() - this PTR_DEREF start; } + + /** + * Returns timer name. + */ + string GetName() { return this PTR_DEREF name; } + + /** + * Get the sum of all values. + */ + ulong GetSum() { + uint _size = ArraySize(this PTR_DEREF data); + ulong _sum = 0; + for (uint _i = 0; _i < _size; _i++) { + _sum += data[_i]; } - uint GetTime() { - return GetTickCount() - this.start; + return _sum; + } + + /** + * Get the median of all values. + */ + uint GetMedian() { + if (this PTR_DEREF index >= 0) { + ArraySort(this PTR_DEREF data); } - - /** - * Returns timer name. - */ - string GetName() { - return this.name; - } - - /** - * Get the sum of all values. - */ - ulong GetSum() { - uint _size = ArraySize(this.data); - ulong _sum = 0; - for (uint _i = 0; _i < _size; _i++) { - _sum += data[_i]; - } - return _sum; - } - - /** - * Get the median of all values. - */ - uint GetMedian() { - if (this.index >= 0) { - ArraySort(this.data); - } - return this.index >= 0 ? this.data[this.index / 2] : 0; - } - - /** - * Get the minimum time value. - */ - uint GetMin() { - return this.index >= 0 ? this.data[ArrayMinimum(this.data)] : 0; - } - - /** - * Get the maximal time value. - */ - uint GetMax() { - int _index = this.index >= 0 ? ArrayMaximum(this.data) : -1; - return _index >= 0 ? data[_index] : 0; - } - - /* Inherited methods */ - - /** - * Print timer times. - */ - virtual const string ToString() { - return StringFormat("%s(%d)=%d-%dms,med=%dms,sum=%dms", - GetName(), - ArraySize(this.data), - GetMin(), - GetMax(), - GetMedian(), - GetSum() - ); - } - - /** - * Returns weight of the object. - */ - virtual double GetWeight() { - return (double) GetSum(); - } - + return this PTR_DEREF index >= 0 ? this PTR_DEREF data[this PTR_DEREF index / 2] : 0; + } + + /** + * Get the minimum time value. + */ + uint GetMin() { return this PTR_DEREF index >= 0 ? this PTR_DEREF data[ArrayMinimum(this PTR_DEREF data)] : 0; } + + /** + * Get the maximal time value. + */ + uint GetMax() { + int _index = this PTR_DEREF index >= 0 ? ArrayMaximum(this PTR_DEREF data) : -1; + return _index >= 0 ? data[_index] : 0; + } + + /* Inherited methods */ + + /** + * Print timer times. + */ + virtual const string ToString() { + return StringFormat("%s(%d)=%d-%dms,med=%dms,sum=%dms", GetName(), ArraySize(this PTR_DEREF data), GetMin(), + GetMax(), GetMedian(), GetSum()); + } + + /** + * Returns weight of the object. + */ + virtual double GetWeight() { return (double)GetSum(); } }; diff --git a/Trade/TradeSignal.struct.h b/Trade/TradeSignal.struct.h index 77918c1fd..5b8221cce 100644 --- a/Trade/TradeSignal.struct.h +++ b/Trade/TradeSignal.struct.h @@ -26,7 +26,7 @@ */ // Includes. -#include "../Serializer.mqh" +#include "../Chart.enum.h" #include "../SerializerConverter.mqh" #include "../SerializerJson.mqh" @@ -53,12 +53,12 @@ // Structure for a trade signal. struct TradeSignalEntry { protected: - ENUM_TIMEFRAMES tf; // Timeframe. - float strength; // Signal strength. - float weight; // Signal weight. long magic_id; // Magic identifier. - long timestamp; // Creation timestamp unsigned int signals; // Store signals (@see: ENUM_TRADE_SIGNAL_FLAG). + float strength; // Signal strength. + ENUM_TIMEFRAMES tf; // Timeframe. + long timestamp; // Creation timestamp + float weight; // Signal weight. public: /* Struct's enumerations */ @@ -115,7 +115,7 @@ struct TradeSignalEntry { TradeSignalEntry(unsigned int _signals = 0, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, long _magic_id = 0, float _strength = 0.0f, float _weight = 0.0f, long _time = 0) : magic_id(_magic_id), signals(_signals), strength(_strength), tf(_tf), timestamp(_time), weight(_weight) {} - TradeSignalEntry(const TradeSignalEntry &_entry) { this = _entry; } + TradeSignalEntry(const TradeSignalEntry &_entry) { THIS_REF = _entry; } /* Getters */ template T Get(STRUCT_ENUM(TradeSignalEntry, ENUM_TRADE_SIGNAL_PROP) _prop) { @@ -134,7 +134,7 @@ struct TradeSignalEntry { return (T)weight; } SetUserError(ERR_INVALID_PARAMETER); - return (T)WRONG_VALUE; + return (T)NULL; } bool Get(STRUCT_ENUM(TradeSignalEntry, ENUM_TRADE_SIGNAL_FLAG) _prop) { return CheckSignals(_prop); } /* Setters */ @@ -189,7 +189,7 @@ struct TradeSignalEntry { int _size = sizeof(int) * 8; for (int i = 0; i < _size; i++) { int _value = CheckSignals(1 << i) ? 1 : 0; - _s.Pass(THIS_REF, (string)(i + 1), _value, SERIALIZER_FIELD_FLAG_DYNAMIC | SERIALIZER_FIELD_FLAG_FEATURE); + _s.Pass(THIS_REF, IntegerToString(i + 1), _value, SERIALIZER_FIELD_FLAG_DYNAMIC | SERIALIZER_FIELD_FLAG_FEATURE); } return SerializerNodeObject; } diff --git a/Trade/TradeSignalManager.h b/Trade/TradeSignalManager.h index e3e9060a1..87dd5c017 100644 --- a/Trade/TradeSignalManager.h +++ b/Trade/TradeSignalManager.h @@ -124,14 +124,14 @@ class TradeSignalManager : Dynamic { void Refresh() { for (DictObjectIterator iter = GetIterSignalsActive(); iter.IsValid(); ++iter) { TradeSignal *_signal = iter.Value(); - if (_signal.Get(STRUCT_ENUM(TradeSignalEntry, TRADE_SIGNAL_FLAG_PROCESSED))) { + if (_signal PTR_DEREF Get(STRUCT_ENUM(TradeSignalEntry, TRADE_SIGNAL_FLAG_PROCESSED))) { signals_active.Unset(iter); - signals_processed.Push(_signal); + signals_processed.Push(PTR_TO_REF(_signal)); continue; } - if (_signal.Get(STRUCT_ENUM(TradeSignalEntry, TRADE_SIGNAL_FLAG_EXPIRED))) { + if (_signal PTR_DEREF Get(STRUCT_ENUM(TradeSignalEntry, TRADE_SIGNAL_FLAG_EXPIRED))) { signals_active.Unset(iter); - signals_expired.Push(_signal); + signals_expired.Push(PTR_TO_REF(_signal)); continue; } } diff --git a/Trade/TradeSignalManager.struct.h b/Trade/TradeSignalManager.struct.h index 7e492a21d..d4be49393 100644 --- a/Trade/TradeSignalManager.struct.h +++ b/Trade/TradeSignalManager.struct.h @@ -34,8 +34,8 @@ */ struct TradeSignalManagerParams { protected: - long last_check; // Last check. short freq; // Signal process refresh frequency (in sec). + long last_check; // Last check. public: /* Struct's enumerations */ @@ -67,7 +67,7 @@ struct TradeSignalManagerParams { return (T)last_check; } SetUserError(ERR_INVALID_PARAMETER); - return (T)WRONG_VALUE; + return (T)NULL; } /* Setters */ diff --git a/Trade/tests/TradeSignal.test.cpp b/Trade/tests/TradeSignal.test.cpp new file mode 100644 index 000000000..696ec4422 --- /dev/null +++ b/Trade/tests/TradeSignal.test.cpp @@ -0,0 +1,34 @@ +//+------------------------------------------------------------------+ +//| 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 C++ compilation of TradeSignal class. + */ + +// Includes. +#include "../../Common.define.h" +#include "../../Common.extern.h" +#include "../../Std.h" +#include "../../String.extern.h" +#include "../TradeSignal.h" + +int main(int argc, char **argv) {} diff --git a/Trade/tests/TradeSignalManager.test.cpp b/Trade/tests/TradeSignalManager.test.cpp new file mode 100644 index 000000000..7ca976d9f --- /dev/null +++ b/Trade/tests/TradeSignalManager.test.cpp @@ -0,0 +1,34 @@ +//+------------------------------------------------------------------+ +//| 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 C++ compilation of TradeSignalManager class. + */ + +// Includes. +#include "../../Common.define.h" +#include "../../Common.extern.h" +#include "../../Std.h" +#include "../../String.extern.h" +#include "../TradeSignalManager.h" + +int main(int argc, char **argv) {} diff --git a/Util.h b/Util.h index 904fde211..a4a012cda 100644 --- a/Util.h +++ b/Util.h @@ -304,6 +304,65 @@ class Util { SerializerConversions::ValueToString(_l) + SerializerConversions::ValueToString(_m); } + /** + * Creates string-based key using given variables. + */ + template + static string MakeKey(const A _a, const B _b, const C _c, const D _d, const E _e, const F _f, const G _g, const H _h, + const I _i, const J _j, const K _k, const L _l, const M _m, const N _n) { + return SeparatedMaybe(SerializerConversions::ValueToString(_a)) + + SeparatedMaybe(SerializerConversions::ValueToString(_b)) + + SeparatedMaybe(SerializerConversions::ValueToString(_c)) + + SeparatedMaybe(SerializerConversions::ValueToString(_d)) + + SeparatedMaybe(SerializerConversions::ValueToString(_e)) + + SeparatedMaybe(SerializerConversions::ValueToString(_f)) + SerializerConversions::ValueToString(_g) + + SerializerConversions::ValueToString(_h) + SerializerConversions::ValueToString(_i) + + SerializerConversions::ValueToString(_j) + SerializerConversions::ValueToString(_k) + + SerializerConversions::ValueToString(_l) + SerializerConversions::ValueToString(_m) + + SerializerConversions::ValueToString(_n); + } + + /** + * Creates string-based key using given variables. + */ + template + static string MakeKey(const A _a, const B _b, const C _c, const D _d, const E _e, const F _f, const G _g, const H _h, + const I _i, const J _j, const K _k, const L _l, const M _m, const N _n, const O _o) { + return SeparatedMaybe(SerializerConversions::ValueToString(_a)) + + SeparatedMaybe(SerializerConversions::ValueToString(_b)) + + SeparatedMaybe(SerializerConversions::ValueToString(_c)) + + SeparatedMaybe(SerializerConversions::ValueToString(_d)) + + SeparatedMaybe(SerializerConversions::ValueToString(_e)) + + SeparatedMaybe(SerializerConversions::ValueToString(_f)) + SerializerConversions::ValueToString(_g) + + SerializerConversions::ValueToString(_h) + SerializerConversions::ValueToString(_i) + + SerializerConversions::ValueToString(_j) + SerializerConversions::ValueToString(_k) + + SerializerConversions::ValueToString(_l) + SerializerConversions::ValueToString(_m) + + SerializerConversions::ValueToString(_n) + SerializerConversions::ValueToString(_o); + } + + /** + * Creates string-based key using given variables. + */ + template + static string MakeKey(const A _a, const B _b, const C _c, const D _d, const E _e, const F _f, const G _g, const H _h, + const I _i, const J _j, const K _k, const L _l, const M _m, const N _n, const O _o, + const P _p) { + return SeparatedMaybe(SerializerConversions::ValueToString(_a)) + + SeparatedMaybe(SerializerConversions::ValueToString(_b)) + + SeparatedMaybe(SerializerConversions::ValueToString(_c)) + + SeparatedMaybe(SerializerConversions::ValueToString(_d)) + + SeparatedMaybe(SerializerConversions::ValueToString(_e)) + + SeparatedMaybe(SerializerConversions::ValueToString(_f)) + SerializerConversions::ValueToString(_g) + + SerializerConversions::ValueToString(_h) + SerializerConversions::ValueToString(_i) + + SerializerConversions::ValueToString(_j) + SerializerConversions::ValueToString(_k) + + SerializerConversions::ValueToString(_l) + SerializerConversions::ValueToString(_m) + + SerializerConversions::ValueToString(_n) + SerializerConversions::ValueToString(_o) + + SerializerConversions::ValueToString(_p); + } + /** * Creates string with separator if string was not empty. */ diff --git a/tests/BufferStructTest.mq5 b/tests/BufferStructTest.mq5 index a55ed6baa..f5881fb70 100644 --- a/tests/BufferStructTest.mq5 +++ b/tests/BufferStructTest.mq5 @@ -28,6 +28,7 @@ #include "../BufferStruct.mqh" #include "../Data.define.h" #include "../Data.struct.h" +#include "../SerializerConverter.mqh" #include "../SerializerJSON.mqh" #include "../Std.h" #include "../Test.mqh" diff --git a/tests/CompileTest.mq5 b/tests/CompileTest.mq5 index dea9802e4..ef6ceeab7 100644 --- a/tests/CompileTest.mq5 +++ b/tests/CompileTest.mq5 @@ -62,6 +62,7 @@ #include "../ISerializable.h" #include "../Indicator.define.h" #include "../Indicator.mqh" +#include "../IndicatorBase.h" #include "../IndicatorData.mqh" #include "../Inet.mqh" #include "../Log.mqh" diff --git a/tests/DrawIndicatorTest.mq5 b/tests/DrawIndicatorTest.mq5 index 0ec2fc83b..2770d7db5 100644 --- a/tests/DrawIndicatorTest.mq5 +++ b/tests/DrawIndicatorTest.mq5 @@ -1,6 +1,6 @@ //+------------------------------------------------------------------+ //| EA31337 framework | -//| Copyright 2016-2021, EA31337 Ltd | +//| Copyright 2016-2022, EA31337 Ltd | //| https://github.com/EA31337 | //+------------------------------------------------------------------+ @@ -36,7 +36,7 @@ // Global variables. Chart *chart; -Dict indis; +Dict indis; int bar_processed; /** @@ -64,8 +64,8 @@ void OnTick() { if (chart.IsNewBar()) { bar_processed++; - for (DictIterator iter = indis.Begin(); iter.IsValid(); ++iter) { - IndicatorBase *_indi = iter.Value(); + for (DictIterator iter = indis.Begin(); iter.IsValid(); ++iter) { + IndicatorData *_indi = iter.Value(); _indi.OnTick(); IndicatorDataEntry _entry = _indi.GetEntry(); if (_indi.Get(STRUCT_ENUM(IndicatorState, INDICATOR_STATE_PROP_IS_READY)) && _entry.IsValid()) { @@ -81,7 +81,7 @@ void OnTick() { void OnDeinit(const int reason) { delete chart; - for (DictIterator iter = indis.Begin(); iter.IsValid(); ++iter) { + for (DictIterator iter = indis.Begin(); iter.IsValid(); ++iter) { delete iter.Value(); } } @@ -98,7 +98,7 @@ bool InitIndicators() { // Moving Average. IndiMAParams ma_params(13, 10, MODE_SMA, PRICE_OPEN); - IndicatorBase *indi_ma = new Indi_MA(ma_params); + IndicatorData *indi_ma = new Indi_MA(ma_params); indis.Set(INDI_MA, indi_ma); // Relative Strength Index (RSI). @@ -109,40 +109,40 @@ bool InitIndicators() { // Demo/Dummy Indicator. IndiDemoParams demo_params; - IndicatorBase *indi_demo = new Indi_Demo(demo_params); + IndicatorData *indi_demo = new Indi_Demo(demo_params); indis.Set(INDI_DEMO, indi_demo); // Current Price (used by custom indicators) . PriceIndiParams price_params(); price_params.SetDraw(clrGreenYellow); - IndicatorBase *indi_price = new Indi_Price(price_params); + IndicatorData *indi_price = new Indi_Price(price_params); indis.Set(INDI_PRICE, indi_price); + /* @fixme: Array out of range. // Bollinger Bands over Price indicator. PriceIndiParams price_params_4_bands(); - IndicatorBase *indi_price_4_bands = new Indi_Price(price_params_4_bands); + IndicatorData *indi_price_4_bands = new Indi_Price(price_params_4_bands); IndiBandsParams bands_on_price_params(); bands_on_price_params.SetDraw(clrCadetBlue); - // bands_on_price_params.SetDataSource(indi_price_4_bands, true, INDI_PRICE_MODE_OPEN); - indis.Set(INDI_BANDS_ON_PRICE, new Indi_Bands(bands_on_price_params, indi_price_4_bands, true)); + indis.Set(INDI_BANDS_ON_PRICE, new Indi_Bands(bands_on_price_params, IDATA_INDICATOR, indi_price_4_bands)); // Moving Average (MA) over Price indicator. PriceIndiParams price_params_4_ma(); - IndicatorBase *indi_price_4_ma = new Indi_Price(price_params_4_ma); + IndicatorData *indi_price_4_ma = new Indi_Price(price_params_4_ma); IndiMAParams ma_on_price_params(); ma_on_price_params.SetDraw(clrYellowGreen); - // ma_on_price_params.SetDataSource(indi_price_4_ma, true, INDI_PRICE_MODE_OPEN); ma_on_price_params.SetIndicatorType(INDI_MA_ON_PRICE); - IndicatorBase *indi_ma_on_price = new Indi_MA(ma_on_price_params, indi_price_4_ma); + IndicatorData *indi_ma_on_price = new Indi_MA(ma_on_price_params, IDATA_INDICATOR, indi_price_4_ma); indis.Set(INDI_MA_ON_PRICE, indi_ma_on_price); // Relative Strength Index (RSI) over Price indicator. PriceIndiParams price_params_4_rsi(); - IndicatorBase *indi_price_4_rsi = new Indi_Price(price_params_4_rsi); + IndicatorData *indi_price_4_rsi = new Indi_Price(price_params_4_rsi); IndiRSIParams rsi_on_price_params(); - // rsi_on_price_params.SetDataSource(indi_price_4_rsi, true, INDI_PRICE_MODE_OPEN); rsi_on_price_params.SetDraw(clrBisque, 1); - indis.Set(INDI_RSI_ON_PRICE, indi_price_4_rsi); + IndicatorBase *indi_rsi_on_price = new Indi_RSI(rsi_on_price_params, IDATA_INDICATOR, indi_price_4_rsi); + indis.Set(INDI_RSI_ON_PRICE, indi_rsi_on_price); + */ return _LastError == ERR_NO_ERROR; } @@ -152,8 +152,8 @@ bool InitIndicators() { */ bool PrintIndicators(string _prefix = "") { ResetLastError(); - for (DictIterator iter = indis.Begin(); iter.IsValid(); ++iter) { - IndicatorBase *_indi = iter.Value(); + for (DictIterator iter = indis.Begin(); iter.IsValid(); ++iter) { + IndicatorData *_indi = iter.Value(); if (_indi.Get(STRUCT_ENUM(IndicatorState, INDICATOR_STATE_PROP_IS_READY))) { PrintFormat("%s: %s: %s", _prefix, _indi.GetName(), _indi.ToString()); } diff --git a/tests/IndicatorBaseTest.mq4 b/tests/IndicatorBaseTest.mq4 new file mode 100644 index 000000000..167dec35e --- /dev/null +++ b/tests/IndicatorBaseTest.mq4 @@ -0,0 +1,28 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2022, 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 IndicatorBase class. + */ + +// Includes. +#include "IndicatorBaseTest.mq5" diff --git a/tests/IndicatorBaseTest.mq5 b/tests/IndicatorBaseTest.mq5 new file mode 100644 index 000000000..8ca89f936 --- /dev/null +++ b/tests/IndicatorBaseTest.mq5 @@ -0,0 +1,37 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2022, 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 IndicatorBase class. + */ + +// Includes. +#include "../IndicatorBase.h" +#include "../Test.mqh" + +/** + * Implements OnInit(). + */ +int OnInit() { + // @todo + return (INIT_SUCCEEDED); +} diff --git a/tests/IndicatorDataTest.mq4 b/tests/IndicatorDataTest.mq4 index dd6581caa..ec907afe1 100644 --- a/tests/IndicatorDataTest.mq4 +++ b/tests/IndicatorDataTest.mq4 @@ -1,6 +1,6 @@ //+------------------------------------------------------------------+ //| EA31337 framework | -//| Copyright 2016-2021, EA31337 Ltd | +//| Copyright 2016-2022, EA31337 Ltd | //| https://github.com/EA31337 | //+------------------------------------------------------------------+ @@ -25,184 +25,4 @@ */ // Includes. -#include "../IndicatorData.mqh" - -// User inputs. -#ifdef __input__ input #endif string __MA_Parameters__ = "-- Settings for the Moving Average indicator --"; // >>> MA <<< -#ifdef __input__ input #endif int MA_Period_Fast = 14; // Period Fast -#ifdef __input__ input #endif int MA_Period_Medium = 20; // Period Medium -#ifdef __input__ input #endif int MA_Period_Slow = 48; // Period Slow -#ifdef __input__ input #endif double MA_Period_Ratio = 1.0; // Period ratio between timeframes (0.5-1.5) -#ifdef __input__ input #endif int MA_Shift = 0; // Shift -#ifdef __input__ input #endif int MA_Shift_Fast = 0; // Shift Fast (+1) -#ifdef __input__ input #endif int MA_Shift_Medium = 0; // Shift Medium (+1) -#ifdef __input__ input #endif int MA_Shift_Slow = 1; // Shift Slow (+1) -#ifdef __input__ input #endif int MA_Shift_Far = 4; // Shift Far (+2) -#ifdef __input__ input #endif ENUM_MA_METHOD MA_Method = 1; // MA Method -#ifdef __input__ input #endif ENUM_APPLIED_PRICE MA_Applied_Price = 3; // Applied Price - -class I_MA : public IndicatorData { - protected: - // Indicator Buffers. - enum ENUM_MA_MODE { - MODE_MA_FAST = 0, - MODE_MA_MEDIUM = 1, - MODE_MA_SLOW = 2, - MAX_OF_ENUM_MA_MODE // Buffers count - }; - - public: - /** - * Class constructor. - */ - void I_MA() : IndicatorData("Custom MA Indicator", MAX_OF_ENUM_MA_MODE) {} - - /** - * Returns the indicator value. - * - * @docs - * - https://docs.mql4.com/indicators/ima - * - https://www.mql5.com/en/docs/indicators/ima - */ - static double iMA(string _symbol, ENUM_TIMEFRAMES _tf, uint _ma_period, int _ma_shift, - ENUM_MA_METHOD _ma_method, // (MT4/MT5): MODE_SMA, MODE_EMA, MODE_SMMA, MODE_LWMA - ENUM_APPLIED_PRICE _applied_price, // (MT4/MT5): PRICE_CLOSE, PRICE_OPEN, PRICE_HIGH, PRICE_LOW, - // PRICE_MEDIAN, PRICE_TYPICAL, PRICE_WEIGHTED - int _shift = 0) { -#ifdef __MQL4__ - return ::iMA(_symbol, _tf, _ma_period, _ma_shift, _ma_method, _applied_price, _shift); -#else // __MQL5__ - double _res[]; - int _handle = ::iMA(_symbol, _tf, _ma_period, _ma_shift, _ma_method, _applied_price); - return CopyBuffer(_handle, 0, _shift, 1, _res) > 0 ? _res[0] : EMPTY_VALUE; -#endif - } - double iMA(uint _ma_period, int _ma_shift, ENUM_MA_METHOD _ma_method, ENUM_APPLIED_PRICE _applied_price, - int _shift = 0) { - double _value = iMA(Get(CHART_PARAM_SYMBOL), Get(CHART_PARAM_TF), _ma_period, _ma_shift, - _ma_method, _applied_price, _shift); - return _value; - } - - /** - * Get period value from settings. - */ - int GetPeriod(ENUM_MA_MODE _ma_type) { - switch (_ma_type) { - default: - case MODE_MA_FAST: - return MA_Period_Fast; - case MODE_MA_MEDIUM: - return MA_Period_Medium; - case MODE_MA_SLOW: - return MA_Period_Slow; - } - } - - /** - * Get shift value from settings. - */ - int GetShift(ENUM_MA_MODE _ma_type) { - switch (_ma_type) { - default: - case MODE_MA_FAST: - return MA_Shift_Fast; - case MODE_MA_MEDIUM: - return MA_Shift_Medium; - case MODE_MA_SLOW: - return MA_Shift_Slow; - } - } - - /** - * Get method value from settings. - */ - ENUM_MA_METHOD GetMethod(ENUM_MA_MODE _ma_type) { - switch (_ma_type) { - default: - case MODE_MA_FAST: - return MA_Method; - case MODE_MA_MEDIUM: - return MA_Method; - case MODE_MA_SLOW: - return MA_Method; - } - } - - /** - * Get applied price value from settings. - */ - ENUM_APPLIED_PRICE GetAppliedPrice(ENUM_MA_MODE _ma_type) { - switch (_ma_type) { - default: - case MODE_MA_FAST: - return MA_Applied_Price; - case MODE_MA_MEDIUM: - return MA_Applied_Price; - case MODE_MA_SLOW: - return MA_Applied_Price; - } - } - - /** - * Calculates the Moving Average indicator. - */ - bool Update(int shift = CURR) { - bool _res = true; - double _ma_value; - for (ENUM_MA_MODE mode = 0; mode <= MODE_MA_SLOW; mode++) { - _ma_value = iMA(Get(CHART_PARAM_SYMBOL), Get(CHART_PARAM_TF), GetPeriod(mode), - GetShift(mode), GetMethod(mode), GetAppliedPrice(mode), shift); - _res &= Add(_ma_value, mode, shift); - } - return _res; - } -}; - -////////////////////////////////////////////////////////////////////////// -// create a custom mt4 indicator to show values on mt4 chart -////////////////////////////////////////////////////////////////////////// - -#property indicator_chart_window -#property indicator_buffers MAX_OF_ENUM_MA_MODE - -double FastMa[]; -double MediumMa[]; -double SlowMa[]; - -I_MA myMa; - -/** - * Implements OnInit(). - */ -int OnInit() { - IndicatorBuffers(MAX_OF_ENUM_MA_MODE); - SetIndexBuffer(MODE_MA_FAST, FastMa); - SetIndexBuffer(MODE_MA_MEDIUM, MediumMa); - SetIndexBuffer(MODE_MA_SLOW, SlowMa); - - SetIndexStyle(MODE_MA_FAST, DRAW_LINE, STYLE_SOLID, 1, clrRed); - SetIndexStyle(MODE_MA_MEDIUM, DRAW_LINE, STYLE_SOLID, 1, clrGreen); - SetIndexStyle(MODE_MA_SLOW, DRAW_LINE, STYLE_SOLID, 1, clrGreen); - return (INIT_SUCCEEDED); -} - -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[]) { - uint start_at = GetTickCount(); - - int oldest_bar = rates_total - prev_calculated - 1; - for (int i = oldest_bar; i >= 0; i--) { - bool ok = myMa.Update(i); - if (!ok) continue; - - FastMa[i] = myMa.GetDouble(MODE_MA_FAST, i); - MediumMa[i] = myMa.GetDouble(MODE_MA_MEDIUM, i); - SlowMa[i] = myMa.GetDouble(MODE_MA_SLOW, i); - } - - PrintFormat("elapse %dms", GetTickCount() - start_at); - - return (rates_total); -} +#include "IndicatorDataTest.mq5" diff --git a/tests/IndicatorDataTest.mq5 b/tests/IndicatorDataTest.mq5 new file mode 100644 index 000000000..bd6a17c11 --- /dev/null +++ b/tests/IndicatorDataTest.mq5 @@ -0,0 +1,37 @@ +//+------------------------------------------------------------------+ +//| EA31337 framework | +//| Copyright 2016-2022, 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 IndicatorData class. + */ + +// Includes. +#include "../IndicatorData.mqh" +#include "../Test.mqh" + +/** + * Implements OnInit(). + */ +int OnInit() { + // @todo + return (INIT_SUCCEEDED); +} diff --git a/tests/IndicatorsTest.mq5 b/tests/IndicatorsTest.mq5 index ada301677..6ec22c545 100644 --- a/tests/IndicatorsTest.mq5 +++ b/tests/IndicatorsTest.mq5 @@ -1,6 +1,6 @@ //+------------------------------------------------------------------+ //| EA31337 framework | -//| Copyright 2016-2021, EA31337 Ltd | +//| Copyright 2016-2022, EA31337 Ltd | //| https://github.com/EA31337 | //+------------------------------------------------------------------+ @@ -46,15 +46,15 @@ enum ENUM_CUSTOM_INDICATORS { INDI_SPECIAL_MATH_CUSTOM = FINAL_INDICATOR_TYPE_EN // Global variables. Chart* chart; -DictStruct> indis; -DictStruct> whitelisted_indis; +DictStruct> indis; +DictStruct> whitelisted_indis; Dict tested; int bar_processed; double test_values[] = {1.245, 1.248, 1.254, 1.264, 1.268, 1.261, 1.256, 1.250, 1.242, 1.240, 1.235, 1.240, 1.234, 1.245, 1.265, 1.274, 1.285, 1.295, 1.300, 1.312, 1.315, 1.320, 1.325, 1.335, 1.342, 1.348, 1.352, 1.357, 1.359, 1.422, 1.430, 1.435}; Ref _indi_drawer; -Ref _indi_test; +Ref _indi_test; /** * Implements Init event handler. @@ -85,8 +85,8 @@ 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().Tick(); + for (DictStructIterator> iter = indis.Begin(); iter.IsValid(); ++iter) { + // iter.Value().Ptr().Tick(); // @fixme } if (chart.IsNewBar()) { @@ -95,7 +95,7 @@ void OnTick() { return; } - for (DictStructIterator> iter = indis.Begin(); iter.IsValid(); ++iter) { + for (DictStructIterator> iter = indis.Begin(); iter.IsValid(); ++iter) { if (whitelisted_indis.Size() == 0) { if (tested.GetByKey(iter.Key())) { // Indicator is already tested, skipping. @@ -107,8 +107,8 @@ void OnTick() { } } - IndicatorBase* _indi = iter.Value().Ptr(); - _indi.OnTick(); + IndicatorData* _indi = iter.Value().Ptr(); + // _indi.OnTick(); // @fixme IndicatorDataEntry _entry(_indi.GetEntry()); if (_indi.Get(STRUCT_ENUM(IndicatorState, INDICATOR_STATE_PROP_IS_READY))) { @@ -164,7 +164,8 @@ bool InitIndicators() { indis.Push(new Indi_AO()); // Accumulation Swing Index (ASI). - indis.Push(new Indi_ASI()); + IndiASIParams _asi_params; + indis.Push(new Indi_ASI(_asi_params)); // Average True Range (ATR). IndiATRParams atr_params(14); @@ -172,13 +173,15 @@ bool InitIndicators() { // Bollinger Bands. IndiBandsParams bands_params(20, 2, 0, PRICE_OPEN); - Ref indi_bands = new Indi_Bands(bands_params); + Ref indi_bands = new Indi_Bands(bands_params); indis.Push(indi_bands); // Bollinger Bands over RSI. + /* @todo: Convert into new syntax. IndiBandsParams bands_over_rsi_params(20, 2, 0, PRICE_OPEN); - bands_over_rsi_params.SetDataSource(INDI_RSI); + // bands_over_rsi_params.SetDataSource(INDI_RSI); indis.Push(new Indi_Bands(bands_over_rsi_params)); + */ // Bears Power. IndiBearsPowerParams bears_params(13, PRICE_CLOSE); @@ -220,7 +223,8 @@ bool InitIndicators() { indis.Push(new Indi_Gator(gator_params)); // Heiken Ashi. - indis.Push(new Indi_HeikenAshi()); + IndiHeikenAshiParams _ha_params(); + indis.Push(new Indi_HeikenAshi(_ha_params)); // Ichimoku Kinko Hyo. IndiIchimokuParams ichi_params(9, 26, 52); @@ -228,17 +232,17 @@ bool InitIndicators() { // Moving Average. IndiMAParams ma_params(13, 0, MODE_SMA, PRICE_OPEN); - Ref indi_ma = new Indi_MA(ma_params); + Ref indi_ma = new Indi_MA(ma_params); indis.Push(indi_ma); // DEMA. IndiDEIndiMAParams dema_params(13, 2, PRICE_OPEN); - Ref indi_dema = new Indi_DEMA(dema_params); + Ref indi_dema = new Indi_DEMA(dema_params); indis.Push(indi_dema); // MACD. IndiMACDParams macd_params(12, 26, 9, PRICE_CLOSE); - Ref macd = new Indi_MACD(macd_params); + Ref macd = new Indi_MACD(macd_params); indis.Push(macd); // Money Flow Index (MFI). @@ -261,9 +265,11 @@ bool InitIndicators() { indis.Push(new Indi_RSI(rsi_params)); // Relative Strength Index (RSI). + /* @todo: Convert into new syntax. IndiRSIParams rsi_over_blt_stddev_params(); - rsi_over_blt_stddev_params.SetDataSource(INDI_STDDEV); + // rsi_over_blt_stddev_params.SetDataSource(INDI_STDDEV); indis.Push(new Indi_RSI(rsi_over_blt_stddev_params)); + */ // Relative Vigor Index (RVI). IndiRVIParams rvi_params(14); @@ -278,12 +284,11 @@ bool InitIndicators() { indis.Push(new Indi_StdDev(stddev_params)); // Standard Deviation (StdDev). - Ref indi_price_for_stdev = new Indi_Price(PriceIndiParams()); + Ref indi_price_for_stdev = new Indi_Price(PriceIndiParams()); IndiStdDevParams stddev_on_price_params(); stddev_on_price_params.SetDraw(clrBlue, 1); - Ref indi_stddev_on_price = new Indi_StdDev(stddev_on_price_params); - indi_stddev_on_price.Ptr().SetDataSource(indi_price_for_stdev.Ptr(), PRICE_OPEN); + Ref indi_stddev_on_price = new Indi_StdDev(stddev_on_price_params, IDATA_BUILTIN, indi_price_for_stdev.Ptr()); indis.Push(indi_stddev_on_price.Ptr()); // Stochastic Oscillator. @@ -306,108 +311,99 @@ bool InitIndicators() { // Current Price. PriceIndiParams price_params(); // price_params.SetDraw(clrAzure); - Ref indi_price = new Indi_Price(price_params); + Ref indi_price = new Indi_Price(price_params); indis.Push(indi_price); // Bollinger Bands over Price indicator. PriceIndiParams price_params_4_bands(); - Ref indi_price_4_bands = new Indi_Price(price_params_4_bands); + Ref indi_price_4_bands = new Indi_Price(price_params_4_bands); IndiBandsParams bands_on_price_params(); bands_on_price_params.SetDraw(clrCadetBlue); - Ref indi_bands_on_price = new Indi_Bands(bands_on_price_params); - indi_bands_on_price.Ptr().SetDataSource(indi_price_4_bands.Ptr()); + Ref indi_bands_on_price = new Indi_Bands(bands_on_price_params, IDATA_BUILTIN, indi_price_4_bands.Ptr()); indis.Push(indi_bands_on_price.Ptr()); // Standard Deviation (StdDev) over MA(SMA). // NOTE: If you set ma_shift parameter for MA, then StdDev will no longer // match built-in StdDev indicator (as it doesn't use ma_shift for averaging). IndiMAParams ma_sma_params_for_stddev(); - Ref indi_ma_sma_for_stddev = new Indi_MA(ma_sma_params_for_stddev); + Ref indi_ma_sma_for_stddev = new Indi_MA(ma_sma_params_for_stddev); IndiStdDevParams stddev_params_on_ma_sma(13, 10); 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()); + Ref indi_stddev_on_ma_sma = new Indi_StdDev(stddev_params_on_ma_sma, IDATA_BUILTIN, indi_ma_sma_for_stddev.Ptr()); indis.Push(indi_stddev_on_ma_sma.Ptr()); // Standard Deviation (StdDev) in SMA mode over Price. PriceIndiParams price_params_for_stddev_sma(); - Ref indi_price_for_stddev_sma = new Indi_Price(price_params_for_stddev_sma); + Ref indi_price_for_stddev_sma = new Indi_Price(price_params_for_stddev_sma); IndiStdDevParams stddev_sma_on_price_params(); stddev_sma_on_price_params.SetDraw(true, 1); - Ref indi_stddev_on_sma = new Indi_StdDev(stddev_sma_on_price_params); - indi_stddev_on_sma.Ptr().SetDataSource(indi_price_for_stddev_sma.Ptr()); + Ref indi_stddev_on_sma = new Indi_StdDev(stddev_sma_on_price_params, IDATA_BUILTIN, indi_price_for_stddev_sma.Ptr()); indis.Push(indi_stddev_on_sma.Ptr()); // Moving Average (MA) over Price indicator. PriceIndiParams price_params_4_ma(); - Ref indi_price_4_ma = new Indi_Price(price_params_4_ma); + Ref indi_price_4_ma = new Indi_Price(price_params_4_ma); IndiMAParams ma_on_price_params(13, 0, MODE_SMA, PRICE_OPEN, 0); ma_on_price_params.SetDraw(clrYellowGreen); ma_on_price_params.SetIndicatorType(INDI_MA_ON_PRICE); - Ref indi_ma_on_price = new Indi_MA(ma_on_price_params); - indi_ma_on_price.Ptr().SetDataSource(indi_price_4_ma.Ptr()); + Ref indi_ma_on_price = new Indi_MA(ma_on_price_params, IDATA_BUILTIN, indi_price_4_ma.Ptr()); indis.Push(indi_ma_on_price.Ptr()); // Commodity Channel Index (CCI) over Price indicator. PriceIndiParams price_params_4_cci(); - Ref indi_price_4_cci = new Indi_Price(price_params_4_cci); + Ref indi_price_4_cci = new Indi_Price(price_params_4_cci); IndiCCIParams cci_on_price_params(); cci_on_price_params.SetDraw(clrYellowGreen, 1); - Ref indi_cci_on_price = new Indi_CCI(cci_on_price_params); - indi_cci_on_price.Ptr().SetDataSource(indi_price_4_cci.Ptr()); + Ref indi_cci_on_price = new Indi_CCI(cci_on_price_params, IDATA_BUILTIN, indi_price_4_cci.Ptr()); indis.Push(indi_cci_on_price.Ptr()); // Envelopes over Price indicator. PriceIndiParams price_params_4_envelopes(); - Ref indi_price_4_envelopes = new Indi_Price(price_params_4_envelopes); + Ref indi_price_4_envelopes = new Indi_Price(price_params_4_envelopes); IndiEnvelopesParams env_on_price_params(); env_on_price_params.SetDraw(clrBrown); - Ref indi_envelopes_on_price = new Indi_Envelopes(env_on_price_params); - indi_envelopes_on_price.Ptr().SetDataSource(indi_price_4_envelopes.Ptr()); + Ref indi_envelopes_on_price = new Indi_Envelopes(env_on_price_params, IDATA_BUILTIN, indi_price_4_envelopes.Ptr()); indis.Push(indi_envelopes_on_price.Ptr()); // DEMA over Price indicator. PriceIndiParams price_params_4_dema(); - Ref indi_price_4_dema = new Indi_Price(price_params_4_dema); + Ref indi_price_4_dema = new Indi_Price(price_params_4_dema); IndiDEIndiMAParams dema_on_price_params(13, 2, PRICE_OPEN); dema_on_price_params.SetDraw(clrRed); - Ref indi_dema_on_price = new Indi_DEMA(dema_on_price_params); - indi_dema_on_price.Ptr().SetDataSource(indi_price_4_dema.Ptr()); + Ref indi_dema_on_price = new Indi_DEMA(dema_on_price_params, IDATA_BUILTIN, indi_price_4_dema.Ptr()); indis.Push(indi_dema_on_price.Ptr()); // Momentum over Price indicator. - Ref indi_price_4_momentum = new Indi_Price(); + Ref indi_price_4_momentum = new Indi_Price(); IndiMomentumParams mom_on_price_params(); mom_on_price_params.SetDraw(clrDarkCyan); - Ref indi_momentum_on_price = new Indi_Momentum(mom_on_price_params); - indi_momentum_on_price.Ptr().SetDataSource(indi_price_4_momentum.Ptr(), 0); + Ref indi_momentum_on_price = new Indi_Momentum(mom_on_price_params, IDATA_BUILTIN, indi_price_4_momentum.Ptr()); indis.Push(indi_momentum_on_price.Ptr()); // Relative Strength Index (RSI) over Price indicator. PriceIndiParams price_params_4_rsi(); - Ref indi_price_4_rsi = new Indi_Price(price_params_4_rsi); + Ref indi_price_4_rsi = new Indi_Price(price_params_4_rsi); IndiRSIParams rsi_on_price_params(); rsi_on_price_params.SetDraw(clrBisque, 1); - Ref indi_rsi_on_price = new Indi_RSI(rsi_on_price_params); - indi_rsi_on_price.Ptr().SetDataSource(indi_price_4_rsi.Ptr()); + Ref indi_rsi_on_price = new Indi_RSI(rsi_on_price_params, IDATA_BUILTIN, indi_price_4_rsi.Ptr()); indis.Push(indi_rsi_on_price.Ptr()); +#ifndef __MQL4__ // @fixme: Fix it for MQL4. // Drawer (socket-based) indicator over RSI over Price. IndiDrawerParams drawer_params(14, /*unused*/ PRICE_OPEN); drawer_params.SetDraw(clrBisque, 0); - Ref indi_drawer_on_rsi = new Indi_Drawer(drawer_params); - indi_drawer_on_rsi.Ptr().SetDataSource(indi_rsi_on_price.Ptr(), PRICE_OPEN); + Ref indi_drawer_on_rsi = new Indi_Drawer(drawer_params, IDATA_BUILTIN, indi_rsi_on_price.Ptr()); indis.Push(indi_drawer_on_rsi.Ptr()); +#endif // Applied Price over OHCL indicator. IndiAppliedPriceParams applied_price_params(); applied_price_params.SetDraw(clrAquamarine, 0); - IndiOHLCParams applied_price_ohlc_params; - Ref indi_applied_price_on_price = new Indi_AppliedPrice(applied_price_params); - indi_applied_price_on_price.Ptr().SetDataSource(new Indi_OHLC(applied_price_ohlc_params), PRICE_TYPICAL); + IndiOHLCParams applied_price_ohlc_params(PRICE_TYPICAL); + Ref indi_applied_price_on_price = new Indi_AppliedPrice(applied_price_params, IDATA_INDICATOR, new Indi_OHLC(applied_price_ohlc_params)); indis.Push(indi_applied_price_on_price.Ptr()); // ADXW. @@ -415,18 +411,19 @@ bool InitIndicators() { indis.Push(new Indi_ADXW(adxw_params)); // AMA. + /* @fixme IndiAMAParams ama_params(); - // Will use Candle indicator by default. However, in that case we need to specifiy applied price (excluding ASK and - // BID). + // 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); _indi_ama.SetAppliedPrice(PRICE_OPEN); indis.Push(_indi_ama); + */ // 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. @@ -517,16 +514,14 @@ bool InitIndicators() { IndiMathParams math_params(MATH_OP_SUB, BAND_UPPER, BAND_LOWER, 0, 0); math_params.SetDraw(clrBlue); math_params.SetName("Bands(UP - LO)"); - Ref indi_math_1 = new Indi_Math(math_params); - indi_math_1.Ptr().SetDataSource(indi_bands.Ptr(), 0); + Ref indi_math_1 = new Indi_Math(math_params, IDATA_INDICATOR, indi_bands.Ptr()); indis.Push(indi_math_1.Ptr()); // Math (specialized indicator) via custom math method. IndiMathParams math_custom_params(MathCustomOp, BAND_UPPER, BAND_LOWER, 0, 0); math_custom_params.SetDraw(clrBeige); math_custom_params.SetName("Bands(Custom math fn)"); - Ref indi_math_2 = new Indi_Math(math_custom_params); - indi_math_2.Ptr().SetDataSource(indi_bands.Ptr(), 0); + Ref indi_math_2 = new Indi_Math(math_custom_params, IDATA_INDICATOR, indi_bands.Ptr()); indis.Push(indi_math_2.Ptr()); // RS (Math-based) indicator. @@ -546,7 +541,7 @@ bool InitIndicators() { indis.Push(new Indi_Candle(candle_params)); // Mark all as untested. - for (DictIterator> iter = indis.Begin(); iter.IsValid(); ++iter) { + for (DictIterator> iter = indis.Begin(); iter.IsValid(); ++iter) { tested.Set(iter.Key(), false); } @@ -562,12 +557,12 @@ double MathCustomOp(double a, double b) { return 1.11 + (b - a) * 2.0; } * Print indicators. */ bool PrintIndicators(string _prefix = "") { - for (DictIterator> iter = indis.Begin(); iter.IsValid(); ++iter) { + for (DictIterator> iter = indis.Begin(); iter.IsValid(); ++iter) { if (whitelisted_indis.Size() != 0 && !whitelisted_indis.Contains(iter.Value())) { continue; } - IndicatorBase* _indi = iter.Value().Ptr(); + IndicatorData* _indi = iter.Value().Ptr(); if (_indi.GetModeCount() == 0) { // Indicator has no modes. diff --git a/tests/SerializerTest.mq5 b/tests/SerializerTest.mq5 index 5f10e70e5..fb619c193 100644 --- a/tests/SerializerTest.mq5 +++ b/tests/SerializerTest.mq5 @@ -246,7 +246,7 @@ int OnInit() { SerializerConverter::FromObject(configs1).ToFile("configs.json"); - SerializerConverter stub3(Serializer::MakeStubObject>(0, 1, configs1[0].Size())); + SerializerConverter stub3(SerializerConverter::MakeStubObject>(0, 1, configs1[0].Size())); SerializerConverter::FromObject(configs1).ToFile("configs.csv", SERIALIZER_CSV_INCLUDE_TITLES, &stub3); string configs1_json = SerializerConverter::FromObject(configs1).ToString(); @@ -284,7 +284,7 @@ int OnInit() { string configs2_imported = SerializerConverter::FromObject(configs2).ToString(); Print("configs2 imported: ", configs2_imported); - SerializerConverter stub4(Serializer::MakeStubObject>(0, 1, 6)); + SerializerConverter stub4(SerializerConverter::MakeStubObject>(0, 1, 6)); SerializerConverter::FromObject(entries_map) .ToFile("configs_key.csv", SERIALIZER_CSV_INCLUDE_TITLES_TREE | SERIALIZER_CSV_INCLUDE_KEY, &stub4);