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/test-buffer.yml b/.github/workflows/test-buffer.yml
new file mode 100644
index 000000000..bf23d92e7
--- /dev/null
+++ b/.github/workflows/test-buffer.yml
@@ -0,0 +1,61 @@
+---
+name: Test Buffer
+
+# yamllint disable-line rule:truthy
+on:
+ pull_request:
+ paths:
+ - 'Buffer/**'
+ - '.github/workflows/test-buffer.yml'
+ push:
+ paths:
+ - 'Buffer/**'
+ - '.github/workflows/test-buffer.yml'
+
+jobs:
+
+ Compile:
+ runs-on: windows-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: Compile
+ uses: fx31337/mql-compile-action@master
+ with:
+ init-platform: true
+ path: 'Buffer/tests'
+ verbose: true
+ - name: Print compiled files
+ run: '(Get-ChildItem -Recurse -Path . -Include *.ex[45]).fullname'
+ shell: powershell
+ - name: Upload artifacts (MQL4)
+ uses: actions/upload-artifact@v2
+ with:
+ name: files-ex4
+ path: '**/*.ex4'
+ - name: Upload artifacts (MQL5)
+ uses: actions/upload-artifact@v2
+ with:
+ name: files-ex5
+ path: '**/*.ex5'
+
+ Buffer-Tests-MQL4:
+ defaults:
+ run:
+ shell: bash
+ working-directory: Buffer/tests
+ needs: Compile
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ test:
+ - BufferCandle.test
+ - BufferTick.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-exchange.yml b/.github/workflows/test-exchange.yml
new file mode 100644
index 000000000..b4c0ed3c9
--- /dev/null
+++ b/.github/workflows/test-exchange.yml
@@ -0,0 +1,62 @@
+---
+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:
+ runs-on: windows-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: Compile
+ uses: fx31337/mql-compile-action@master
+ with:
+ init-platform: true
+ path: 'Exchange/tests'
+ verbose: true
+ - name: Print compiled files
+ run: '(Get-ChildItem -Recurse -Path . -Include *.ex[45]).fullname'
+ shell: powershell
+ - name: Upload artifacts (MQL4)
+ uses: actions/upload-artifact@v2
+ with:
+ name: files-ex4
+ path: '**/*.ex4'
+ - name: Upload artifacts (MQL5)
+ uses: actions/upload-artifact@v2
+ with:
+ name: files-ex5
+ path: '**/*.ex5'
+
+ Exchange-Tests-MQL4:
+ defaults:
+ run:
+ shell: bash
+ working-directory: Exchange/tests
+ 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
new file mode 100644
index 000000000..87b68aa41
--- /dev/null
+++ b/.github/workflows/test-indicator.yml
@@ -0,0 +1,67 @@
+---
+name: Test Indicator
+
+# yamllint disable-line rule:truthy
+on:
+ pull_request:
+ paths:
+ - 'Indicator**'
+ - 'Indicator/**'
+ - '.github/workflows/test-indicator.yml'
+ push:
+ paths:
+ - 'Indicator**'
+ - 'Indicator/**'
+ - '.github/workflows/test-indicator.yml'
+
+jobs:
+
+ Compile:
+ runs-on: windows-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: Compile
+ uses: fx31337/mql-compile-action@master
+ with:
+ init-platform: true
+ path: 'Indicator/tests'
+ verbose: true
+ - name: Print compiled files
+ run: '(Get-ChildItem -Recurse -Path . -Include *.ex[45]).fullname'
+ shell: powershell
+ - name: Upload artifacts (MQL4)
+ uses: actions/upload-artifact@v2
+ with:
+ name: files-ex4
+ path: '**/*.ex4'
+ - name: Upload artifacts (MQL5)
+ uses: actions/upload-artifact@v2
+ with:
+ name: files-ex5
+ path: '**/*.ex5'
+
+ Indicator-Tests-MQL4:
+ defaults:
+ run:
+ shell: bash
+ working-directory: Indicator/tests
+ needs: Compile
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ test:
+ - IndicatorCandle.test
+ - IndicatorTf.test
+ - IndicatorTick.test
+ steps:
+ - uses: actions/download-artifact@v2
+ with:
+ name: files-ex4
+ - name: Run ${{ matrix.test }}
+ uses: fx31337/mql-tester-action@master
+ with:
+ BtDays: 4-8
+ BtMonths: 1
+ BtYears: 2020
+ TestExpert: ${{ matrix.test }}
+ timeout-minutes: 10
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index ca02328a3..5f4fe16e8 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -61,7 +61,7 @@ jobs:
- CompileIndicatorsTest
- ConditionTest
- DatabaseTest
- - DrawIndicatorTest
+ # - DrawIndicatorTest
- EATest
- IndicatorDataTest
- IndicatorTest
diff --git a/Account.mqh b/Account.mqh
index ec5bac686..bef93c4fe 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/Action.mqh b/Action.mqh
index c14fc5fea..65dc92f3b 100644
--- a/Action.mqh
+++ b/Action.mqh
@@ -139,14 +139,16 @@ class Action {
break;
#endif
#ifdef INDICATOR_MQH
- case ACTION_TYPE_INDICATOR:
- if (Object::IsValid(_entry.obj)) {
- _result = ((IndicatorBase *)_entry.obj).ExecuteAction((ENUM_INDICATOR_ACTION)_entry.action_id);
- } else {
- _result = false;
- _entry.AddFlags(ACTION_ENTRY_FLAG_IS_INVALID);
- }
- break;
+ /*
+ case ACTION_TYPE_INDICATOR:
+ if (Object::IsValid(_entry.obj)) {
+ _result = ((IndicatorBase *)_entry.obj).ExecuteAction((ENUM_INDICATOR_ACTION)_entry.action_id);
+ } else {
+ _result = false;
+ _entry.AddFlags(ACTION_ENTRY_FLAG_IS_INVALID);
+ }
+ break;
+ */
#endif
#ifdef STRATEGY_MQH
case ACTION_TYPE_STRATEGY:
diff --git a/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 0a8a08635..d71b044d0 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;
diff --git a/Buffer/BufferCandle.h b/Buffer/BufferCandle.h
new file mode 100644
index 000000000..8401ee3f8
--- /dev/null
+++ b/Buffer/BufferCandle.h
@@ -0,0 +1,79 @@
+//+------------------------------------------------------------------+
+//| EA31337 framework |
+//| Copyright 2016-2021, EA31337 Ltd |
+//| https://github.com/EA31337 |
+//+------------------------------------------------------------------+
+
+/*
+ * This file is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+// Prevents processing this includes file for the second time.
+#ifndef BUFFER_CANDLE_H
+#define BUFFER_CANDLE_H
+
+// Includes.
+#include "../BufferStruct.mqh"
+#include "../Candle.struct.h"
+
+/**
+ * Class to store struct data.
+ */
+template
+class BufferCandle : public BufferStruct> {
+ protected:
+ protected:
+ /* Protected methods */
+
+ /**
+ * Initialize class.
+ *
+ * Called on constructor.
+ */
+ void Init() { SetOverflowListener(BufferCandleOverflowListener, 10); }
+
+ public:
+ /* Constructors */
+
+ /**
+ * Constructor.
+ */
+ BufferCandle() { Init(); }
+ BufferCandle(BufferCandle& _right) {
+ THIS_REF = _right;
+ Init();
+ }
+
+ /* Callback methods */
+
+ /**
+ * Function should return true if resize can be made, or false to overwrite current slot.
+ */
+ static bool BufferCandleOverflowListener(ENUM_DICT_OVERFLOW_REASON _reason, int _size, int _num_conflicts) {
+ static int cache_limit = 86400;
+ switch (_reason) {
+ case DICT_OVERFLOW_REASON_FULL:
+ // We allow resize if dictionary size is less than 86400 slots.
+ return _size < cache_limit;
+ case DICT_OVERFLOW_REASON_TOO_MANY_CONFLICTS:
+ default:
+ // When there is too many conflicts, we just reject doing resize, so first conflicting slot will be reused.
+ break;
+ }
+ return false;
+ }
+};
+
+#endif // BUFFER_CANDLE_H
diff --git a/Buffer/BufferTick.h b/Buffer/BufferTick.h
new file mode 100644
index 000000000..d3eb35dab
--- /dev/null
+++ b/Buffer/BufferTick.h
@@ -0,0 +1,169 @@
+//+------------------------------------------------------------------+
+//| EA31337 framework |
+//| Copyright 2016-2021, EA31337 Ltd |
+//| https://github.com/EA31337 |
+//+------------------------------------------------------------------+
+
+/*
+ * This file is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+// Prevents processing this includes file for the second time.
+#ifndef BUFFER_TICK_H
+#define BUFFER_TICK_H
+
+// Includes.
+#include "../BufferStruct.mqh"
+#include "../Chart.enum.h"
+#include "../Storage/IValueStorage.h"
+#include "../Tick.struct.h"
+
+template
+class BufferTickValueStorage : ValueStorage {
+ // Poiner to buffer to take tick from.
+ BufferTick *buffer_tick;
+
+ // PRICE_ASK or PRICE_BID.
+ int applied_price;
+
+ public:
+ /**
+ * Constructor.
+ */
+ BufferTickValueStorage(BufferTick *_buffer_tick, int _applied_price)
+ : buffer_tick(_buffer_tick), applied_price(_applied_price) {}
+
+ /**
+ * Fetches value from a given shift. Takes into consideration as-series flag.
+ */
+ TV Fetch(int _shift) override {
+ Print("BufferTickValueStorage: Fetching " + (applied_price == PRICE_ASK ? "Ask" : "Bid") + " price from shift ",
+ _shift);
+ return 0;
+ }
+
+ /**
+ * Returns number of values available to fetch (size of the values buffer).
+ */
+ int Size() const override { return (int)buffer_tick.Size(); }
+};
+
+/**
+ * Class to store struct data.
+ */
+template
+class BufferTick : public BufferStruct> {
+ protected:
+ // Ask prices ValueStorage proxy.
+ BufferTickValueStorage *_vs_ask;
+
+ // Bid prices ValueStorage proxy.
+ BufferTickValueStorage *_vs_bid;
+
+ protected:
+ /* Protected methods */
+
+ /**
+ * Initialize class.
+ *
+ * Called on constructor.
+ */
+ void Init() {
+ _vs_ask = NULL;
+ _vs_bid = NULL;
+ SetOverflowListener(BufferTickOverflowListener, 10);
+ }
+
+ public:
+ /* Constructors */
+
+ /**
+ * Constructor.
+ */
+ BufferTick() { Init(); }
+ BufferTick(BufferTick &_right) {
+ THIS_REF = _right;
+ Init();
+ }
+
+ /**
+ * Destructor.
+ */
+ ~BufferTick() {
+ if (_vs_ask != NULL) {
+ delete _vs_ask;
+ }
+ if (_vs_bid != NULL) {
+ delete _vs_bid;
+ }
+ }
+
+ /**
+ * Returns Ask prices ValueStorage proxy.
+ */
+ BufferTickValueStorage *GetAskValueStorage() {
+ if (_vs_ask == NULL) {
+ _vs_ask = new BufferTickValueStorage(THIS_PTR, PRICE_ASK);
+ }
+ return _vs_ask;
+ }
+
+ /**
+ * Returns Bid prices ValueStorage proxy.
+ */
+ BufferTickValueStorage *GetBidValueStorage() {
+ if (_vs_bid == NULL) {
+ _vs_bid = new BufferTickValueStorage(THIS_PTR, PRICE_BID);
+ }
+ return _vs_bid;
+ }
+
+ /* Grouping methods */
+
+ /**
+ * Group ticks by seconds.
+ */
+ DictStruct>> GroupBySecs(uint _spc) {
+ // DictStruct>> _result;
+ // @todo: for each iter
+ // for (DictStructIterator>> iter(Begin()); iter.IsValid(); ++iter) {
+ // Load timestamp from key, TickAB from value
+ // foreach some timestamp mod % _spc - calculate shift
+ // _result.Push(_shift, TickAB)
+ // Convert to OHLC in upper method
+ return NULL;
+ }
+
+ /* Callback methods */
+
+ /**
+ * Function should return true if resize can be made, or false to overwrite current slot.
+ */
+ static bool BufferTickOverflowListener(ENUM_DICT_OVERFLOW_REASON _reason, int _size, int _num_conflicts) {
+ static int cache_limit = 86400;
+ switch (_reason) {
+ case DICT_OVERFLOW_REASON_FULL:
+ // We allow resize if dictionary size is less than 86400 slots.
+ return _size < cache_limit;
+ case DICT_OVERFLOW_REASON_TOO_MANY_CONFLICTS:
+ default:
+ // When there is too many conflicts, we just reject doing resize, so first conflicting slot will be reused.
+ break;
+ }
+ return false;
+ }
+};
+
+#endif // BUFFER_TICK_H
diff --git a/Buffer/tests/BufferCandle.test.mq4 b/Buffer/tests/BufferCandle.test.mq4
new file mode 100644
index 000000000..fe6c0a00d
--- /dev/null
+++ b/Buffer/tests/BufferCandle.test.mq4
@@ -0,0 +1,28 @@
+//+------------------------------------------------------------------+
+//| EA31337 framework |
+//| Copyright 2016-2021, EA31337 Ltd |
+//| https://github.com/EA31337 |
+//+------------------------------------------------------------------+
+
+/*
+ * This file is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+/**
+ * @file
+ * Test functionality of BufferCandle class.
+ */
+
+// Includes.
+#include "BufferCandle.test.mq5"
diff --git a/Buffer/tests/BufferCandle.test.mq5 b/Buffer/tests/BufferCandle.test.mq5
new file mode 100644
index 000000000..ab76d8da8
--- /dev/null
+++ b/Buffer/tests/BufferCandle.test.mq5
@@ -0,0 +1,59 @@
+//+------------------------------------------------------------------+
+//| EA31337 framework |
+//| Copyright 2016-2021, EA31337 Ltd |
+//| https://github.com/EA31337 |
+//+------------------------------------------------------------------+
+
+/*
+ * This file is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+/**
+ * @file
+ * Test functionality of BufferCandle class.
+ */
+
+// Includes
+#include "../../Test.mqh"
+#include "../BufferCandle.h"
+
+/**
+ * Implements OnInit().
+ */
+int OnInit() {
+ BufferCandle buffer1; // 128
+ CandleOHLC _ohlc_d; // 32
+ CandleOHLC _ohlc_f; // 16
+ CandleTOHLC _tohlc_d; // 32
+ CandleTOHLC _tohlc_f; // 16
+ // CandleEntry _centry_d; // 40
+ // CandleEntry _centry_f; // 24
+ Print("buffer1: ", sizeof(buffer1));
+ Print("_ohlc_d: ", sizeof(_ohlc_d));
+ Print("_ohlc_f: ", sizeof(_ohlc_f));
+ Print("_tohlc_d: ", sizeof(_tohlc_d));
+ Print("_tohlc_f: ", sizeof(_tohlc_f));
+ // @todo
+ return (GetLastError() > 0 ? INIT_FAILED : INIT_SUCCEEDED);
+}
+
+/**
+ * Implements OnTick().
+ */
+void OnTick() {}
+
+/**
+ * Implements OnDeinit().
+ */
+void OnDeinit(const int reason) {}
diff --git a/Buffer/tests/BufferTick.test.mq4 b/Buffer/tests/BufferTick.test.mq4
new file mode 100644
index 000000000..5a45ef4fa
--- /dev/null
+++ b/Buffer/tests/BufferTick.test.mq4
@@ -0,0 +1,28 @@
+//+------------------------------------------------------------------+
+//| EA31337 framework |
+//| Copyright 2016-2021, EA31337 Ltd |
+//| https://github.com/EA31337 |
+//+------------------------------------------------------------------+
+
+/*
+ * This file is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+/**
+ * @file
+ * Test functionality of BufferTick class.
+ */
+
+// Includes.
+#include "BufferTick.test.mq5"
diff --git a/Buffer/tests/BufferTick.test.mq5 b/Buffer/tests/BufferTick.test.mq5
new file mode 100644
index 000000000..1daf2ea7b
--- /dev/null
+++ b/Buffer/tests/BufferTick.test.mq5
@@ -0,0 +1,57 @@
+//+------------------------------------------------------------------+
+//| EA31337 framework |
+//| Copyright 2016-2021, EA31337 Ltd |
+//| https://github.com/EA31337 |
+//+------------------------------------------------------------------+
+
+/*
+ * This file is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+/**
+ * @file
+ * Test functionality of BufferTick class.
+ */
+
+// Includes
+#include "../../Test.mqh"
+#include "../BufferTick.h"
+
+/**
+ * Implements OnInit().
+ */
+int OnInit() {
+ MqlTick mql_tick; // 60
+ TickAB _tick_ab_d; // 16
+ TickAB _tick_ab_f; // 8
+ TickTAB _tick_tab_d; // 24
+ TickTAB _tick_tab_f; // 16
+ Print("mql_tick: ", sizeof(mql_tick));
+ Print("_tick_ab_d: ", sizeof(_tick_ab_d));
+ Print("_tick_ab_f: ", sizeof(_tick_ab_f));
+ Print("_tick_tab_d: ", sizeof(_tick_tab_d));
+ Print("_tick_tab_f: ", sizeof(_tick_tab_f));
+ // @todo
+ return (GetLastError() > 0 ? INIT_FAILED : INIT_SUCCEEDED);
+}
+
+/**
+ * Implements OnTick().
+ */
+void OnTick() {}
+
+/**
+ * Implements OnDeinit().
+ */
+void OnDeinit(const int reason) {}
diff --git a/Candle.struct.h b/Candle.struct.h
new file mode 100644
index 000000000..4d4e03dfb
--- /dev/null
+++ b/Candle.struct.h
@@ -0,0 +1,288 @@
+//+------------------------------------------------------------------+
+//| EA31337 framework |
+//| Copyright 2016-2021, EA31337 Ltd |
+//| https://github.com/EA31337 |
+//+------------------------------------------------------------------+
+
+/*
+ * This file is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+/**
+ * @file
+ * Includes Bar's structs.
+ */
+
+#ifndef __MQL__
+// Allows the preprocessor to include a header file when it is needed.
+#pragma once
+#endif
+
+// Forward class declaration.
+class Serializer;
+
+// Includes.
+#include "Bar.enum.h"
+#include "Chart.enum.h"
+#include "ISerializable.h"
+#include "Serializer.enum.h"
+#include "SerializerNode.enum.h"
+#include "Std.h"
+
+/* Structure for storing OHLC values. */
+template
+struct CandleOHLC
+#ifndef __MQL__
+ : public ISerializable
+#endif
+{
+ T open, high, low, close;
+
+ // Struct constructors.
+ CandleOHLC(T _open = 0, T _high = 0, T _low = 0, T _close = 0) : open(_open), high(_high), low(_low), close(_close) {}
+ CandleOHLC(ARRAY_REF(T, _prices)) {
+ int _size = ArraySize(_prices);
+ close = _prices[0];
+ open = _prices[_size - 1];
+ high = fmax(close, open);
+ low = fmin(close, open);
+ for (int i = 0; i < _size; i++) {
+ high = fmax(high, _prices[i]);
+ low = fmin(low, _prices[i]);
+ }
+ }
+ // Struct methods.
+ // Getters
+ bool GetPivots(ENUM_PP_TYPE _type, T &_pp, T &_r1, T &_r2, T &_r3, T &_r4, T &_s1, T &_s2, T &_s3, T &_s4) {
+ T _range = GetRange();
+ switch (_type) {
+ case PP_CAMARILLA:
+ // A set of eight very probable levels which resemble support and resistance values for a current trend.
+ _pp = GetPivot();
+ _r1 = (T)(close + _range * 1.1 / 12);
+ _r2 = (T)(close + _range * 1.1 / 6);
+ _r3 = (T)(close + _range * 1.1 / 4);
+ _r4 = (T)(close + _range * 1.1 / 2);
+ _s1 = (T)(close - _range * 1.1 / 12);
+ _s2 = (T)(close - _range * 1.1 / 6);
+ _s3 = (T)(close - _range * 1.1 / 4);
+ _s4 = (T)(close - _range * 1.1 / 2);
+ break;
+ case PP_CLASSIC:
+ _pp = GetPivot();
+ _r1 = (2 * _pp) - low; // R1 = (H - L) * 1.1 / 12 + C (1.0833)
+ _r2 = _pp + _range; // R2 = (H - L) * 1.1 / 6 + C (1.1666)
+ _r3 = _pp + _range * 2; // R3 = (H - L) * 1.1 / 4 + C (1.25)
+ _r4 = _pp + _range * 3; // R4 = (H - L) * 1.1 / 2 + C (1.5)
+ _s1 = (2 * _pp) - high; // S1 = C - (H - L) * 1.1 / 12 (1.0833)
+ _s2 = _pp - _range; // S2 = C - (H - L) * 1.1 / 6 (1.1666)
+ _s3 = _pp - _range * 2; // S3 = C - (H - L) * 1.1 / 4 (1.25)
+ _s4 = _pp - _range * 3; // S4 = C - (H - L) * 1.1 / 2 (1.5)
+ break;
+ case PP_FIBONACCI:
+ _pp = GetPivot();
+ _r1 = (float)(_pp + 0.382 * _range);
+ _r2 = (float)(_pp + 0.618 * _range);
+ _r3 = _pp + _range;
+ _r4 = _r1 + _range; // ?
+ _s1 = (float)(_pp - 0.382 * _range);
+ _s2 = (float)(_pp - 0.618 * _range);
+ _s3 = _pp - _range;
+ _s4 = _s1 - _range; // ?
+ break;
+ case PP_FLOOR:
+ // Most basic and popular type of pivots used in Forex trading technical analysis.
+ _pp = GetPivot(); // Pivot (P) = (H + L + C) / 3
+ _r1 = (2 * _pp) - low; // Resistance (R1) = (2 * P) - L
+ _r2 = _pp + _range; // R2 = P + H - L
+ _r3 = high + 2 * (_pp - low); // R3 = H + 2 * (P - L)
+ _r4 = _r3;
+ _s1 = (2 * _pp) - high; // Support (S1) = (2 * P) - H
+ _s2 = _pp - _range; // S2 = P - H + L
+ _s3 = low - 2 * (high - _pp); // S3 = L - 2 * (H - P)
+ _s4 = _s3; // ?
+ break;
+ case PP_TOM_DEMARK:
+ // Tom DeMark's pivot point (predicted lows and highs of the period).
+ _pp = GetPivotDeMark();
+ _r1 = (2 * _pp) - low; // New High = X / 2 - L.
+ _r2 = _pp + _range;
+ _r3 = _r1 + _range;
+ _r4 = _r2 + _range; // ?
+ _s1 = (2 * _pp) - high; // New Low = X / 2 - H.
+ _s2 = _pp - _range;
+ _s3 = _s1 - _range;
+ _s4 = _s2 - _range; // ?
+ break;
+ case PP_WOODIE:
+ // Woodie's pivot point are giving more weight to the Close price of the previous period.
+ // They are similar to floor pivot points, but are calculated in a somewhat different way.
+ _pp = GetWeighted(); // Pivot (P) = (H + L + 2 * C) / 4
+ _r1 = (2 * _pp) - low; // Resistance (R1) = (2 * P) - L
+ _r2 = _pp + _range; // R2 = P + H - L
+ _r3 = _r1 + _range;
+ _r4 = _r2 + _range; // ?
+ _s1 = (2 * _pp) - high; // Support (S1) = (2 * P) - H
+ _s2 = _pp - _range; // S2 = P - H + L
+ _s3 = _s1 - _range;
+ _s4 = _s2 - _range; // ?
+ break;
+ default:
+ break;
+ }
+ return _r4 > _r3 && _r3 > _r2 && _r2 > _r1 && _r1 > _pp && _pp > _s1 && _s1 > _s2 && _s2 > _s3 && _s3 > _s4;
+ }
+ T GetAppliedPrice(ENUM_APPLIED_PRICE _ap) const { return CandleOHLC::GetAppliedPrice(_ap, open, high, low, close); }
+ T GetBody() const { return close - open; }
+ T GetBodyAbs() const { return fabs(close - open); }
+ T GetBodyInPct(int _hundreds = 100) const { return GetRange() > 0 ? _hundreds / GetRange() * GetBodyAbs() : 0; }
+ T GetChangeInPct(int _hundreds = 100) const { return (close - open) / open * _hundreds; }
+ T GetClose() const { return close; }
+ T GetHigh() const { return high; }
+ T GetLow() const { return low; }
+ T GetMaxOC() const { return fmax(open, close); }
+ T GetMedian() const { return (high + low) / 2; }
+ T GetMinOC() const { return fmin(open, close); }
+ T GetOpen() const { return open; }
+ T GetPivot() const { return GetTypical(); }
+ T GetPivotDeMark() const {
+ // If Close < Open Then X = H + 2 * L + C
+ // If Close > Open Then X = 2 * H + L + C
+ // If Close = Open Then X = H + L + 2 * C
+ T _pp = open > close ? (high + (2 * low) + close) / 4 : ((2 * high) + low + close) / 4;
+ return open == close ? (high + low + (2 * close)) / 4 : _pp;
+ }
+ T GetPivotWithOpen() const { return (open + high + low + close) / 4; }
+ T GetPivotWithOpen(float _open) const { return (_open + high + low + close) / 4; }
+ T GetRange() const { return high - low; }
+ T GetRangeChangeInPct(int _hundreds = 100) const { return _hundreds - (_hundreds / open * fabs(open - GetRange())); }
+ T GetRangeInPips(float _ppp) const { return GetRange() / _ppp; }
+ T GetTypical() const { return (high + low + close) / 3; }
+ T GetWeighted() const { return (high + low + close + close) / 4; }
+ T GetWickMin() const { return fmin(GetWickLower(), GetWickUpper()); }
+ T GetWickLower() const { return GetMinOC() - low; }
+ T GetWickLowerInPct() const { return GetRange() > 0 ? 100 / GetRange() * GetWickLower() : 0; }
+ T GetWickMax() const { return fmax(GetWickLower(), GetWickUpper()); }
+ T GetWickSum() const { return GetWickLower() + GetWickUpper(); }
+ T GetWickUpper() const { return high - GetMaxOC(); }
+ T GetWickUpperInPct() const { return GetRange() > 0 ? 100 / GetRange() * GetWickUpper() : 0; }
+ short GetType() const { return IsBull() ? 1 : (IsBear() ? -1 : 0); }
+ void GetValues(ARRAY_REF(T, _out)) {
+ ArrayResize(_out, 4);
+ int _index = ArraySize(_out) - 4;
+ _out[_index++] = open;
+ _out[_index++] = high;
+ _out[_index++] = low;
+ _out[_index++] = close;
+ }
+ static T GetAppliedPrice(ENUM_APPLIED_PRICE _ap, T _o, T _h, T _l, T _c) {
+ switch (_ap) {
+ case PRICE_CLOSE:
+ return _c;
+ case PRICE_OPEN:
+ return _o;
+ case PRICE_HIGH:
+ return _h;
+ case PRICE_LOW:
+ return _l;
+ case PRICE_MEDIAN:
+ return (_h + _l) / 2;
+ case PRICE_TYPICAL:
+ return (_h + _l + _c) / 3;
+ case PRICE_WEIGHTED:
+ return (_h + _l + _c + _c) / 4;
+ default:
+ return _o;
+ }
+ }
+ // State checkers.
+ bool IsBear() const { return open > close; }
+ bool IsBull() const { return open < close; }
+ bool IsValid() const { return high >= low && fmin(open, close) > 0; }
+ // Serializers.
+ SerializerNodeType Serialize(Serializer &s);
+ // Converters.
+ string ToCSV() { return StringFormat("%g,%g,%g,%g", open, high, low, close); }
+};
+
+/* Structure for storing OHLC values with open and close timestamp. */
+template
+struct CandleOCTOHLC : CandleOHLC {
+ long open_timestamp, close_timestamp;
+
+ // Struct constructors.
+ CandleOCTOHLC(T _open = 0, T _high = 0, T _low = 0, T _close = 0, long _open_timestamp = -1,
+ long _close_timestamp = -1)
+ : CandleOHLC(_open, _high, _low, _close), open_timestamp(_open_timestamp), close_timestamp(_close_timestamp) {}
+
+ // Updates OHLC values taking into consideration tick's timestamp.
+ void Update(long _timestamp, T _price) {
+ if (_timestamp < open_timestamp) {
+ open_timestamp = _timestamp;
+ open = _price;
+ }
+ if (_timestamp > close_timestamp) {
+ close_timestamp = _timestamp;
+ close = _price;
+ }
+ high = MathMax(high, _price);
+ low = MathMin(low, _price);
+ }
+
+ // Returns timestamp of open price.
+ long GetOpenTimestamp() { return open_timestamp; }
+
+ // Returns timestamp of close price.
+ long GetCloseTimestamp() { return close_timestamp; }
+};
+
+/* Structore for storing OHLC values with timestamp. */
+template
+struct CandleTOHLC : CandleOHLC {
+ datetime time;
+ // Struct constructors.
+ CandleTOHLC(datetime _time = 0, T _open = 0, T _high = 0, T _low = 0, T _close = 0)
+ : time(_time), CandleOHLC(_open, _high, _low, _close) {}
+ // Getters.
+ datetime GetTime() { return time; }
+ // Serializers.
+ SerializerNodeType Serialize(Serializer &s);
+ // Converters.
+ string ToCSV() { return StringFormat("%d,%g,%g,%g,%g", time, open, high, low, close); }
+};
+
+#include "Serializer.mqh"
+
+/* Method to serialize CandleEntry structure. */
+template
+SerializerNodeType CandleOHLC::Serialize(Serializer &s) {
+ // s.Pass(THIS_REF, "time", TimeToString(time));
+ s.Pass(THIS_REF, "open", open, SERIALIZER_FIELD_FLAG_DYNAMIC);
+ s.Pass(THIS_REF, "high", high, SERIALIZER_FIELD_FLAG_DYNAMIC);
+ s.Pass(THIS_REF, "low", low, SERIALIZER_FIELD_FLAG_DYNAMIC);
+ s.Pass(THIS_REF, "close", close, SERIALIZER_FIELD_FLAG_DYNAMIC);
+ return SerializerNodeObject;
+}
+
+/* Method to serialize CandleEntry structure. */
+template
+SerializerNodeType CandleTOHLC::Serialize(Serializer &s) {
+ s.Pass(THIS_REF, "time", time);
+ s.Pass(THIS_REF, "open", open, SERIALIZER_FIELD_FLAG_DYNAMIC);
+ s.Pass(THIS_REF, "high", high, SERIALIZER_FIELD_FLAG_DYNAMIC);
+ s.Pass(THIS_REF, "low", low, SERIALIZER_FIELD_FLAG_DYNAMIC);
+ s.Pass(THIS_REF, "close", close, SERIALIZER_FIELD_FLAG_DYNAMIC);
+ return SerializerNodeObject;
+}
diff --git a/Chart.enum.h b/Chart.enum.h
index e7e68247c..5835ba3da 100644
--- a/Chart.enum.h
+++ b/Chart.enum.h
@@ -43,9 +43,14 @@ enum ENUM_APPLIED_PRICE {
PRICE_MEDIAN, // Median price (H+L)/2
PRICE_TYPICAL, // Typical price, (H+L+C)/3
PRICE_WEIGHTED, // Weighted close price (H+L+C+C)/4
+ FINAL_APPLIED_PRICE_ENTRY
};
#endif
+// Additional modes for applied price.
+#define PRICE_ASK ((ENUM_APPLIED_PRICE)128)
+#define PRICE_BID ((ENUM_APPLIED_PRICE)129)
+
// Defines enumeration for chart parameters.
enum ENUM_CHART_PARAM {
CHART_PARAM_NONE = 0, // None
diff --git a/Chart.mqh b/Chart.mqh
index ba63a7750..356b734db 100644
--- a/Chart.mqh
+++ b/Chart.mqh
@@ -224,7 +224,7 @@ class Chart : public Market {
* @return
* Returns ChartEntry struct.
*/
- ChartEntry GetEntry(unsigned int _shift = 0) {
+ ChartEntry GetEntry(int _shift = 0) {
ChartEntry _chart_entry;
BarOHLC _ohlc = GetOHLC(_shift);
if (_ohlc.open > 0) {
diff --git a/Chart.struct.tf.h b/Chart.struct.tf.h
index 49c7c88f3..625fa74ae 100644
--- a/Chart.struct.tf.h
+++ b/Chart.struct.tf.h
@@ -32,6 +32,8 @@
// Includes.
#include "Chart.enum.h"
+#include "Serializer.mqh"
+#include "Terminal.define.h"
/* Defines struct for chart timeframe. */
struct ChartTf {
@@ -346,8 +348,6 @@ struct ChartTf {
SerializerNodeType Serialize(Serializer& s);
};
-#include "Serializer.mqh"
-
/* Method to serialize ChartTf structure. */
SerializerNodeType ChartTf::Serialize(Serializer& s) {
s.PassEnum(THIS_REF, "tf", tf);
diff --git a/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 915cbcd4e..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;
@@ -165,15 +165,17 @@ class Condition {
}
break;
#ifdef INDICATOR_MQH
- case COND_TYPE_INDICATOR:
- if (Object::IsValid(_entry.obj)) {
- _result = ((IndicatorBase *)_entry.obj).CheckCondition((ENUM_INDICATOR_CONDITION)_entry.cond_id, _entry.args);
- } else {
- // Static method not supported.
- _result = false;
- _entry.AddFlags(COND_ENTRY_FLAG_IS_INVALID);
- }
- break;
+ /*
+ case COND_TYPE_INDICATOR:
+ if (Object::IsValid(_entry.obj)) {
+ _result = ((IndicatorBase *)_entry.obj).CheckCondition((ENUM_INDICATOR_CONDITION)_entry.cond_id,
+ _entry.args); } else {
+ // Static method not supported.
+ _result = false;
+ _entry.AddFlags(COND_ENTRY_FLAG_IS_INVALID);
+ }
+ break;
+ */
#endif
case COND_TYPE_MARKET:
if (Object::IsValid(_entry.obj)) {
diff --git a/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 7d5f320c1..010a358e4 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 156c78831..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__
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 cd55d66ba..8da1f31e7 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 daeaaae7a..e7f0b8a75 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 8bcc9d412..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,31 +361,37 @@ 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;
}
+ public:
+#ifdef __MQL__
template <>
+#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();
@@ -391,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();
@@ -404,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/DrawIndicator.mqh b/DrawIndicator.mqh
index 7017a81eb..2888b77cf 100644
--- a/DrawIndicator.mqh
+++ b/DrawIndicator.mqh
@@ -32,7 +32,6 @@
// Includes.
#include "DictObject.mqh"
#include "Draw.mqh"
-#include "Indicator.mqh"
#include "Object.mqh"
// Forward declaration.
diff --git a/EA.mqh b/EA.mqh
index 69d39f812..8fba5ff06 100644
--- a/EA.mqh
+++ b/EA.mqh
@@ -149,7 +149,7 @@ class EA {
* @return
* Returns TradeSignalEntry struct.
*/
- TradeSignalEntry GetStrategySignalEntry(Strategy *_strat, bool _trade_allowed = true, int _shift = -1) {
+ TradeSignalEntry GetStrategySignalEntry(Strategy *_strat, bool _trade_allowed = true, int _shift = 0) {
// float _bf = 1.0;
float _scl = _strat.Get(STRAT_PARAM_SCL);
float _sol = _strat.Get(STRAT_PARAM_SOL);
@@ -426,7 +426,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 +485,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 +505,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 +541,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 +571,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 d5056e91f..ab51a433d 100644
--- a/Indicator.define.h
+++ b/Indicator.define.h
@@ -44,7 +44,7 @@
SET_HANDLE; \
} \
if (Terminal::IsVisualMode()) { \
- int _bars_calc = BarsCalculated(_handle); \
+ int _bars_calc = ::BarsCalculated(_handle); \
if (GetLastError() > 0) { \
return EMPTY_VALUE; \
} else if (_bars_calc <= 2) { \
diff --git a/Indicator.enum.h b/Indicator.enum.h
index 375064b34..bce168e60 100644
--- a/Indicator.enum.h
+++ b/Indicator.enum.h
@@ -40,117 +40,99 @@ enum ENUM_INDICATOR_ACTION {
FINAL_INDICATOR_ACTION_ENTRY
};
-/* Define type of indicators. */
+/* Define type of */
enum ENUM_INDICATOR_TYPE {
- INDI_NONE = 0, // (None)
- INDI_AC, // Accelerator Oscillator
- INDI_AD, // Accumulation/Distribution
- INDI_ADX, // Average Directional Index
- INDI_ADXW, // ADX by Welles Wilder
- INDI_ALLIGATOR, // Alligator
- INDI_AMA, // Adaptive Moving Average
- INDI_APPLIED_PRICE, // Applied Price over OHLC Indicator
- INDI_AO, // Awesome Oscillator
- INDI_ASI, // Accumulation Swing Index
- INDI_ATR, // Average True Range
- INDI_BANDS, // Bollinger Bands
- INDI_BANDS_ON_PRICE, // Bollinger Bands (on Price)
- INDI_BEARS, // Bears Power
- INDI_BULLS, // Bulls Power
- INDI_BWMFI, // Market Facilitation Index
- INDI_BWZT, // Bill Williams' Zone Trade
- INDI_CANDLE, // Candle Pattern Detector
- INDI_CCI, // Commodity Channel Index
- INDI_CCI_ON_PRICE, // Commodity Channel Index (CCI) (on Price)
- INDI_CHAIKIN, // Chaikin Oscillator
- INDI_CHAIKIN_V, // Chaikin Volatility
- INDI_COLOR_BARS, // Color Bars
- INDI_COLOR_CANDLES_DAILY, // Color Candles Daily
- INDI_COLOR_LINE, // Color Line
- INDI_CUSTOM, // Custom indicator
- INDI_CUSTOM_MOVING_AVG, // Custom Moving Average
- INDI_DEMA, // Double Exponential Moving Average
- INDI_DEMARKER, // DeMarker
- INDI_DEMO, // Demo/Dummy Indicator
- INDI_DETRENDED_PRICE, // Detrended Price Oscillator
- INDI_DRAWER, // Drawer (Socket-based) Indicator
- INDI_ENVELOPES, // Envelopes
- INDI_ENVELOPES_ON_PRICE, // Evelopes (on Price)
- INDI_FORCE, // Force Index
- INDI_FRACTALS, // Fractals
- INDI_FRAMA, // Fractal Adaptive Moving Average
- INDI_GATOR, // Gator Oscillator
- INDI_HEIKENASHI, // Heiken Ashi
- INDI_ICHIMOKU, // Ichimoku Kinko Hyo
- INDI_KILLZONES, // Killzones
- INDI_MA, // Moving Average
- INDI_MACD, // MACD
- INDI_MA_ON_PRICE, // Moving Average (on Price).
- INDI_MARKET_FI, // Market Facilitation Index
- INDI_MASS_INDEX, // Mass Index
- INDI_MFI, // Money Flow Index
- INDI_MOMENTUM, // Momentum
- INDI_MOMENTUM_ON_PRICE, // Momentum (on Price)
- INDI_OBV, // On Balance Volume
- INDI_OHLC, // OHLC (Open-High-Low-Close)
- INDI_OSMA, // OsMA
- INDI_PATTERN, // Pattern Detector
- INDI_PIVOT, // Pivot Detector
- INDI_PRICE, // Price
- INDI_PRICE_CHANNEL, // Price Channel
- INDI_PRICE_FEEDER, // Indicator which returns prices from custom array
- INDI_PRICE_VOLUME_TREND, // Price and Volume Trend
- INDI_RATE_OF_CHANGE, // Rate of Change
- INDI_RS, // Indi_Math-based RSI indicator.
- INDI_RSI, // Relative Strength Index
- INDI_RSI_ON_PRICE, // Relative Strength Index (RSI) (on Price)
- INDI_RVI, // Relative Vigor Index
- INDI_SAR, // Parabolic SAR
- INDI_SPECIAL_MATH, // Math operations over given indicator.
- INDI_STDDEV, // Standard Deviation
- INDI_STDDEV_ON_MA_SMA, // Standard Deviation on Moving Average in SMA mode
- INDI_STDDEV_ON_PRICE, // Standard Deviation (on Price)
- INDI_STDDEV_SMA_ON_PRICE, // Standard Deviation in SMA mode (on Price)
- INDI_STOCHASTIC, // Stochastic Oscillator
- INDI_SVE_BB, // SVE Bollinger Bands
- INDI_TEMA, // Triple Exponential Moving Average
- INDI_TICK, // Tick
- INDI_TMA_TRUE, // Triangular Moving Average True
- INDI_TRIX, // Triple Exponential Moving Averages Oscillator
- INDI_ULTIMATE_OSCILLATOR, // Ultimate Oscillator
- INDI_VIDYA, // Variable Index Dynamic Average
- INDI_VOLUMES, // Volumes
- INDI_VROC, // Volume Rate of Change
- INDI_WILLIAMS_AD, // Larry Williams' Accumulation/Distribution
- INDI_WPR, // Williams' Percent Range
- INDI_ZIGZAG, // ZigZag
- INDI_ZIGZAG_COLOR, // ZigZag Color
+ INDI_NONE = 0, // (None)
+ INDI_AC, // Accelerator Oscillator
+ INDI_AD, // Accumulation/Distribution
+ INDI_ADX, // Average Directional Index
+ INDI_ADXW, // ADX by Welles Wilder
+ INDI_ALLIGATOR, // Alligator
+ INDI_AMA, // Adaptive Moving Average
+ INDI_APPLIED_PRICE, // Applied Price over OHLC Indicator
+ INDI_AO, // Awesome Oscillator
+ INDI_ASI, // Accumulation Swing Index
+ INDI_ATR, // Average True Range
+ INDI_BANDS, // Bollinger Bands
+ INDI_BANDS_ON_PRICE, // Bollinger Bands (on Price)
+ INDI_BEARS, // Bears Power
+ INDI_BULLS, // Bulls Power
+ INDI_BWMFI, // Market Facilitation Index
+ INDI_BWZT, // Bill Williams' Zone Trade
+ INDI_CANDLE, // Candle Pattern Detector
+ INDI_CCI, // Commodity Channel Index
+ INDI_CCI_ON_PRICE, // Commodity Channel Index (CCI) (on Price)
+ INDI_CHAIKIN, // Chaikin Oscillator
+ INDI_CHAIKIN_V, // Chaikin Volatility
+ INDI_COLOR_BARS, // Color Bars
+ INDI_COLOR_CANDLES_DAILY, // Color Candles Daily
+ INDI_COLOR_LINE, // Color Line
+ INDI_CUSTOM, // Custom indicator
+ INDI_CUSTOM_MOVING_AVG, // Custom Moving Average
+ INDI_DEMA, // Double Exponential Moving Average
+ INDI_DEMARKER, // DeMarker
+ INDI_DEMO, // Demo/Dummy Indicator
+ INDI_DETRENDED_PRICE, // Detrended Price Oscillator
+ INDI_DRAWER, // Drawer (Socket-based) Indicator
+ INDI_ENVELOPES, // Envelopes
+ INDI_ENVELOPES_ON_PRICE, // Evelopes (on Price)
+ INDI_FORCE, // Force Index
+ INDI_FRACTALS, // Fractals
+ INDI_FRAMA, // Fractal Adaptive Moving Average
+ INDI_GATOR, // Gator Oscillator
+ INDI_HEIKENASHI, // Heiken Ashi
+ INDI_ICHIMOKU, // Ichimoku Kinko Hyo
+ INDI_KILLZONES, // Killzones
+ INDI_MA, // Moving Average
+ INDI_MACD, // MACD
+ INDI_MA_ON_PRICE, // Moving Average (on Price).
+ INDI_MARKET_FI, // Market Facilitation Index
+ INDI_MASS_INDEX, // Mass Index
+ INDI_MFI, // Money Flow Index
+ INDI_MOMENTUM, // Momentum
+ INDI_MOMENTUM_ON_PRICE, // Momentum (on Price)
+ INDI_OBV, // On Balance Volume
+ INDI_OHLC, // OHLC (Open-High-Low-Close)
+ INDI_OSMA, // OsMA
+ INDI_PATTERN, // Pattern Detector
+ INDI_PIVOT, // Pivot Detector
+ INDI_PRICE, // Price
+ INDI_PRICE_CHANNEL, // Price Channel
+ INDI_PRICE_FEEDER, // Indicator which returns prices from custom array
+ INDI_PRICE_VOLUME_TREND, // Price and Volume Trend
+ INDI_RATE_OF_CHANGE, // Rate of Change
+ INDI_RS, // Indi_Math-based RSI
+ INDI_RSI, // Relative Strength Index
+ INDI_RSI_ON_PRICE, // Relative Strength Index (RSI) (on Price)
+ INDI_RVI, // Relative Vigor Index
+ INDI_SAR, // Parabolic SAR
+ INDI_SPECIAL_MATH, // Math operations over given
+ INDI_STDDEV, // Standard Deviation
+ INDI_STDDEV_ON_MA_SMA, // Standard Deviation on Moving Average in SMA mode
+ INDI_STDDEV_ON_PRICE, // Standard Deviation (on Price)
+ INDI_STDDEV_SMA_ON_PRICE, // Standard Deviation in SMA mode (on Price)
+ INDI_STOCHASTIC, // Stochastic Oscillator
+ INDI_SVE_BB, // SVE Bollinger Bands
+ INDI_TEMA, // Triple Exponential Moving Average
+ INDI_TF, // Timeframe
+ INDI_TICK, // Tick
+ INDI_TMA_TRUE, // Triangular Moving Average True
+ INDI_TRIX, // Triple Exponential Moving Averages Oscillator
+ INDI_ULTIMATE_OSCILLATOR, // Ultimate Oscillator
+ INDI_ULTIMATE_OSCILLATOR_ATR_FAST, // Ultimate Oscillator's ATR, Fast
+ INDI_ULTIMATE_OSCILLATOR_ATR_MIDDLE, // Ultimate Oscillator's ATR, Middle
+ INDI_ULTIMATE_OSCILLATOR_ATR_SLOW, // Ultimate Oscillator's ATR, Slow
+ INDI_VIDYA, // Variable Index Dynamic Average
+ INDI_VOLUMES, // Volumes
+ INDI_VROC, // Volume Rate of Change
+ INDI_WILLIAMS_AD, // Larry Williams' Accumulation/Distribution
+ INDI_WPR, // Williams' Percent Range
+ INDI_ZIGZAG, // ZigZag
+ INDI_ZIGZAG_COLOR, // ZigZag Color
FINAL_INDICATOR_TYPE_ENTRY
};
-/* Defines type of source data for indicator. */
-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 indicators.
+// Indicator line identifiers used in ADX and ADXW
enum ENUM_INDI_ADX_LINE {
#ifdef __MQL4__
LINE_MAIN_ADX = MODE_MAIN, // Base indicator line.
@@ -172,7 +154,7 @@ enum ENUM_INDICATOR_INDEX {
FINAL_ENUM_INDICATOR_INDEX = 3 // Should be the last one. Used to calculate the number of enum items.
};
-/* Indicator line identifiers used in Envelopes and Fractals indicators. */
+/* Indicator line identifiers used in Envelopes and Fractals */
enum ENUM_LO_UP_LINE {
#ifdef __MQL4__
LINE_UPPER = MODE_UPPER, // Upper line.
@@ -185,7 +167,7 @@ enum ENUM_LO_UP_LINE {
};
/**
- * Indicator line identifiers used in MACD, RVI and Stochastic indicators.
+ * Indicator line identifiers used in MACD, RVI and Stochastic
*
* @see:
* - https://docs.mql4.com/constants/indicatorconstants/lines
@@ -227,3 +209,28 @@ enum INDICATOR_ENTRY_FLAGS {
INDI_ENTRY_FLAG_IS_VALID = 1 << 6,
INDI_ENTRY_FLAG_INSUFFICIENT_DATA = 1 << 7, // Entry has missing value for that shift and probably won't ever have.
};
+
+// Storage type for IndicatorBase::GetSpecificValueStorage().
+enum ENUM_INDI_VS_TYPE {
+ INDI_VS_TYPE_TIME, // Candle.
+ INDI_VS_TYPE_TICK_VOLUME, // Candle.
+ INDI_VS_TYPE_VOLUME, // Candle.
+ INDI_VS_TYPE_SPREAD, // Candle.
+ INDI_VS_TYPE_PRICE_OPEN, // Candle.
+ INDI_VS_TYPE_PRICE_HIGH, // Candle.
+ INDI_VS_TYPE_PRICE_LOW, // Candle.
+ INDI_VS_TYPE_PRICE_CLOSE, // Candle.
+ INDI_VS_TYPE_PRICE_MEDIAN, // Candle.
+ INDI_VS_TYPE_PRICE_TYPICAL, // Candle.
+ INDI_VS_TYPE_PRICE_WEIGHTED, // Candle.
+ INDI_VS_TYPE_PRICE_BID, // Tick.
+ INDI_VS_TYPE_PRICE_ASK, // Tick.
+};
+
+// Indicator flags.
+enum ENUM_INDI_FLAGS {
+ INDI_FLAG_INDEXABLE_BY_SHIFT, // Indicator supports indexation by shift.
+ INDI_FLAG_INDEXABLE_BY_TIMESTAMP, // Indicator supports indexation by shift.
+ INDI_FLAG_SOURCE_REQ_INDEXABLE_BY_SHIFT, // Source indicator must be indexable by shift.
+ INDI_FLAG_SOURCE_REQ_INDEXABLE_BY_TIMESTAMP // Source indicator must be indexable by timestamp.
+};
diff --git a/Indicator.mqh b/Indicator.mqh
index b5b0f3c6f..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"
@@ -50,36 +49,75 @@ class Chart;
#include "Storage/ValueStorage.indicator.h"
#include "Storage/ValueStorage.native.h"
+#ifndef __MQL4__
+// Defines global functions (for MQL4 backward compatibility).
+bool IndicatorBuffers(int _count) { return Indicator::SetIndicatorBuffers(_count); }
+int IndicatorCounted(int _value = 0) {
+ static int prev_calculated = 0;
+ // https://docs.mql4.com/customind/indicatorcounted
+ prev_calculated = _value > 0 ? _value : prev_calculated;
+ return prev_calculated;
+}
+#endif
+
+#ifdef __MQL5__
+// Defines global functions (for MQL5 forward compatibility).
+template
+double iCustom5(string _symbol, ENUM_TIMEFRAMES _tf, string _name, A _a, B _b, C _c, D _d, E _e, F _f, G _g, H _h, I _i,
+ J _j, int _mode, int _shift) {
+ ResetLastError();
+ static Dict _handlers;
+ string _key = Util::MakeKey(_symbol, (string)_tf, _name, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j);
+ int _handle = _handlers.GetByKey(_key);
+ ICUSTOM_DEF(_handlers.Set(_key, _handle),
+ COMMA _a COMMA _b COMMA _c COMMA _d COMMA _e COMMA _f COMMA _g COMMA _h COMMA _i COMMA _j);
+}
+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:
- // Structs.
+ DrawIndicator* draw;
TS iparams;
protected:
/* Protected methods */
+ bool Init() { return InitDraw(); }
+
/**
- * It's called on class initialization.
+ * Initialize indicator data drawing on custom data.
*/
- 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()) {
- // Indi_Price* _indi_price = Indi_Price::GetCached(GetSymbol(), GetTf(), iparams.GetShift());
- // SetDataSource(_indi_price, true, PRICE_OPEN);
- }
- break;
+ bool InitDraw() {
+ if (iparams.is_draw && !Object::IsValid(draw)) {
+ draw = new DrawIndicator(THIS_PTR);
+ draw.SetColorLine(iparams.indi_color);
+ }
+ return iparams.is_draw;
+ }
+
+ /**
+ * Deinitialize drawing.
+ */
+ void DeinitDraw() {
+ if (draw) {
+ delete draw;
}
- return InitDraw();
}
public:
@@ -100,25 +138,21 @@ 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;
- SetName(_iparams.name != "" ? _iparams.name : EnumToString(iparams.itype));
- if (_indi_src != NULL) {
- SetDataSource(_indi_src, _indi_mode);
- }
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;
- SetName(_iparams.name != "" ? _iparams.name : EnumToString(iparams.itype));
Init();
}
Indicator(ENUM_INDICATOR_TYPE _itype, ENUM_TIMEFRAMES _tf = PERIOD_CURRENT, int _shift = 0, string _name = "")
- : IndicatorBase(_tf) {
+ : IndicatorData(IndicatorDataParams::GetInstance()) {
iparams.SetIndicatorType(_itype);
iparams.SetShift(_shift);
- SetName(_name != "" ? _name : EnumToString(iparams.itype));
Init();
}
@@ -127,41 +161,37 @@ class Indicator : public IndicatorBase {
*/
~Indicator() { DeinitDraw(); }
+ /* Getters */
+
/**
- * Initialize indicator data drawing on custom data.
+ * Gets a value from IndicatorDataParams struct.
*/
- bool InitDraw() {
- if (iparams.is_draw && !Object::IsValid(draw)) {
- draw = new DrawIndicator(THIS_PTR);
- draw.SetColorLine(iparams.indi_color);
- }
- return iparams.is_draw;
+ template
+ T Get(STRUCT_ENUM_IDATA_PARAM _param) {
+ return idparams.Get(_param);
}
- /* Deinit methods */
-
/**
- * Deinitialize drawing.
+ * Gets a value from IndicatorState struct.
*/
- void DeinitDraw() {
- if (draw) {
- delete draw;
- }
+ template
+ T Get(STRUCT_ENUM_INDICATOR_STATE_PROP _param) {
+ return istate.Get(_param);
}
- /* Getters */
+ /* Setters */
/**
- * Gets an indicator property flag.
+ * Sets the value for IndicatorDataParams struct.
*/
- bool GetFlag(INDICATOR_ENTRY_FLAGS _prop, int _shift = -1) {
- 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 */
- virtual string CacheKey() { return GetName(); }
+ virtual string CacheKey() { return GetFullName(); }
/**
* Initializes a cached proxy between i*OnArray() methods and OnCalculate()
@@ -248,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.
*
@@ -320,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.
*
@@ -374,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();
@@ -392,157 +334,21 @@ class Indicator : public IndicatorBase {
*/
virtual IndicatorBase* FetchDataSource(ENUM_INDICATOR_TYPE _id) { return NULL; }
- /* Operator overloading methods */
-
- /**
- * Access indicator entry data using [] operator.
- */
- IndicatorDataEntry operator[](int _shift) { return GetEntry(_shift); }
- IndicatorDataEntry operator[](ENUM_INDICATOR_INDEX _shift) { return GetEntry(_shift); }
- IndicatorDataEntry operator[](datetime _dt) { return idata[_dt]; }
-
- /* Getters */
-
- /**
- * 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 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);
@@ -553,6 +359,17 @@ class Indicator : public IndicatorBase {
_result = _source.Ptr();
}
}
+ } 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.
+ IndicatorData* _ds = OnDataSourceRequest();
+
+ if (_ds != NULL) {
+ // Initializing with new data source.
+ SetDataSource(_ds);
+ Set(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE), IDATA_INDICATOR);
+ }
}
ValidateDataSource(&this, _result);
@@ -568,7 +385,18 @@ class Indicator : public IndicatorBase {
/**
* Whether data source is selected.
*/
- virtual bool HasDataSource() { return GetDataSourceRaw() != NULL || iparams.GetDataSourceId() != -1; }
+ virtual bool HasDataSource(bool _try_initialize = false) {
+ if (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_SRC_ID)) != -1) {
+ return true;
+ }
+
+ if (Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_IDSTYPE)) == IDATA_INDICATOR &&
+ GetDataSourceRaw() == NULL && _try_initialize) {
+ SetDataSource(OnDataSourceRequest());
+ }
+
+ return GetDataSourceRaw() != NULL;
+ }
/**
* Gets indicator's params.
@@ -578,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); }
/**
* Gets indicator's time-frame.
*/
- ENUM_TIMEFRAMES GetTf() { return Get(CHART_PARAM_TF); }
+ ENUM_TIMEFRAMES GetTf() { return iparams.tf.GetTf(); }
/**
* Gets indicator's signals.
@@ -599,35 +432,25 @@ class Indicator : public IndicatorBase {
return _signals;
}
// Returns signals.
- IndicatorSignal _signals(_data, iparams, cparams, _mode1, _mode2);
+ IndicatorSignal _signals(_data, idparams, cparams, _mode1, _mode2);
return _signals;
}
- /**
- * Get pointer to data of indicator.
- */
- BufferStruct* GetData() { return GetPointer(idata); }
-
/**
* Get name of the indicator.
*/
- string GetName() { return iparams.name; }
-
- /**
- * Get full name of the indicator (with "over ..." part).
- */
- string GetFullName() {
- return iparams.name + "[" + IntegerToString(iparams.GetMaxModes()) + "]" +
- (HasDataSource() ? (" (over " + GetDataSource().GetFullName() + ")") : "");
+ string GetName() override {
+ return "(" + EnumToString(GetType()) + ")" + (iparams.name != "" ? (" " + iparams.name) : "");
}
/**
* 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;
@@ -639,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 + ")";
}
@@ -654,14 +477,6 @@ class Indicator : public IndicatorBase {
Chart::Set(_param, _value);
}
- /**
- * Sets indicator data source.
- */
- void SetDataSource(IndicatorBase* _indi, int _input_mode = 0) {
- indi_src = _indi;
- iparams.SetDataSource(-1, _input_mode);
- }
-
/**
* Sets name of the indicator.
*/
@@ -799,65 +614,49 @@ class Indicator : public IndicatorBase {
return true;
}
- /**
- * Returns shift at which the last known valid entry exists for a given
- * period (or from the start, when period is not specified).
- */
- bool GetLastValidEntryShift(int& out_shift, int period = 0) {
- out_shift = 0;
-
- while (true) {
- if ((period != 0 && out_shift >= period) || !HasValidEntry(out_shift + 1))
- return out_shift > 0; // Current shift is always invalid.
+ void OnTick() override {
+ Chart::OnTick();
- ++out_shift;
+ 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 < _max_modes; ++i)
+ draw.DrawLineTo(GetName() + "_" + IntegerToString(i) + "_" +
+ Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_SRC_MODE)),
+ GetBarTime(0), GetEntry(0)[i], iparams.draw_window);
}
-
- return out_shift > 0;
}
/**
- * Returns shift at which the oldest known valid entry exists for a given
- * period (or from the start, when period is not specified).
+ * Sets indicator data source.
*/
- bool GetOldestValidEntryShift(int& out_shift, int& out_num_valid, int shift = 0, int period = 0) {
- bool found = false;
- // Counting from previous up to previous - period.
- for (out_shift = shift + 1; out_shift < shift + period + 1; ++out_shift) {
- if (!HasValidEntry(out_shift)) {
- --out_shift;
- out_num_valid = out_shift - shift;
- return found;
- } else
- found = true;
+ 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)) {
+ Print(GetFullName(), ": Cannot set data source to ", _indi.GetFullName(),
+ ", because source indicator isn't indexable by shift!");
+ DebugBreak();
+ return;
+ }
+ if (bool(flags | INDI_FLAG_SOURCE_REQ_INDEXABLE_BY_TIMESTAMP) &&
+ !bool(_indi.GetFlags() | INDI_FLAG_INDEXABLE_BY_TIMESTAMP)) {
+ Print(GetFullName(), ": Cannot set data source to ", _indi.GetFullName(),
+ ", because source indicator isn't indexable by timestamp!");
+ DebugBreak();
+ return;
+ }
}
- --out_shift;
- out_num_valid = out_shift - shift;
- return found;
- }
-
- /**
- * Checks whether indicator has valid at least given number of last entries
- * (counting from given shift or 0).
- */
- bool HasAtLeastValidLastEntries(int period, int shift = 0) {
- for (int i = 0; i < period; ++i)
- if (!HasValidEntry(shift + i)) return false;
-
- return true;
- }
-
- ENUM_IDATA_VALUE_RANGE GetIDataValueRange() { return iparams.idvrange; }
-
- virtual void OnTick() {
- Chart::OnTick();
-
- if (iparams.is_draw) {
- // 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()),
- GetBarTime(0), GetEntry(0)[i], iparams.draw_window);
+ if (indi_src.IsSet() && indi_src.Ptr() != _indi) {
+ indi_src.Ptr().RemoveListener(THIS_PTR);
+ }
+ indi_src = _indi;
+ if (_indi != NULL) {
+ indi_src.Ptr().AddListener(THIS_PTR);
+ 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);
}
}
@@ -915,6 +714,19 @@ class Indicator : public IndicatorBase {
return _result;
}
+ /**
+ * Get full name of the indicator (with "over ..." part).
+ */
+ string GetFullName() override {
+ return GetName() + "[" + Get(STRUCT_ENUM(IndicatorDataParams, IDATA_PARAM_MAX_MODES)) + "]" +
+ (HasDataSource() ? (" (over " + GetDataSource().GetFullName() + ")") : "");
+ }
+
+ /**
+ * Get indicator type.
+ */
+ ENUM_INDICATOR_TYPE GetType() override { return iparams.itype; }
+
/**
* Update indicator.
*/
@@ -931,13 +743,14 @@ class Indicator : public IndicatorBase {
* @return
* Returns IndicatorDataEntry struct filled with indicator values.
*/
- virtual IndicatorDataEntry GetEntry(int _shift = -1) {
+ IndicatorDataEntry GetEntry(int _index = -1) override {
ResetLastError();
- int _ishift = _shift >= 0 ? _shift : iparams.GetShift();
+ int _ishift = _index >= 0 ? _index : iparams.GetShift();
long _bar_time = GetBarTime(_ishift);
IndicatorDataEntry _entry = idata.GetByKey(_bar_time);
if (_bar_time > 0 && !_entry.IsValid() && !_entry.CheckFlag(INDI_ENTRY_FLAG_INSUFFICIENT_DATA)) {
- _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))) {
@@ -946,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:
@@ -998,9 +811,23 @@ class Indicator : public IndicatorBase {
* This method allows user to modify the struct entry before it's added to cache.
* This method is called on GetEntry() right after values are set.
*/
- virtual void GetEntryAlter(IndicatorDataEntry& _entry, int _shift = -1) {
- _entry.AddFlags(_entry.GetDataTypeFlags(iparams.GetDataValueType()));
+ virtual void GetEntryAlter(IndicatorDataEntry& _entry, int _timestamp = -1) {
+ 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.
+ *
+ * @see: DataParamEntry.
+ *
+ * @return
+ * Returns DataParamEntry struct filled with a single value.
+ */
+ IndicatorDataEntryValue GetEntryValue(int _mode = 0, int _shift = 0) override {
+ int _ishift = _shift >= 0 ? _shift : iparams.GetShift();
+ return GetEntry(_ishift)[_mode];
+ }
};
#endif
diff --git a/Indicator.struct.h b/Indicator.struct.h
index 99bc74b84..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(0),
+ // 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(0),
+ // 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