From 135e38c305230bf3f1ec070c91b38827fbcdaae6 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Wed, 5 Jun 2024 13:53:58 +0330 Subject: [PATCH] bkp workspace ... --- .../Classes/x-saherelm.base.class.ex5 | Bin 0 -> 5610 bytes .../Classes/x-saherelm.base.class.mq5 | 49 + .../Classes/x-saherelm.x121.xmcycle.class.ex5 | Bin 0 -> 10718 bytes .../Classes/x-saherelm.x121.xmcycle.class.mq5 | 5761 ++++++++++++ .../Classes/x-saherelm.xaccount.class.ex5 | Bin 0 -> 5854 bytes .../Classes/x-saherelm.xaccount.class.mq5 | 398 + .../Classes/x-saherelm.xalert.class.ex5 | Bin 0 -> 6186 bytes .../Classes/x-saherelm.xalert.class.mq5 | 1575 ++++ .../x-saherelm.xdata-collector.class.ex5 | Bin 0 -> 6550 bytes .../x-saherelm.xdata-collector.class.mq5 | 481 + .../14030316/Classes/x-saherelm.xea.class.ex5 | Bin 0 -> 10716 bytes .../14030316/Classes/x-saherelm.xea.class.mq5 | 3906 ++++++++ .../Classes/x-saherelm.xhelper.class.ex5 | Bin 0 -> 5112 bytes .../Classes/x-saherelm.xhelper.class.mq5 | 148 + .../Classes/x-saherelm.xhttp.class.ex5 | Bin 0 -> 5870 bytes .../Classes/x-saherelm.xhttp.class.mq5 | 373 + .../Classes/x-saherelm.xmd5.class.ex5 | Bin 0 -> 4620 bytes .../Classes/x-saherelm.xmd5.class.mq5 | 441 + .../Classes/x-saherelm.xprovider.class.ex5 | Bin 0 -> 7658 bytes .../Classes/x-saherelm.xprovider.class.mq5 | 171 + .../Classes/x-saherelm.xtrade.class.ex5 | Bin 0 -> 8020 bytes .../Classes/x-saherelm.xtrade.class.mq5 | 3682 ++++++++ .../BKPS/14030316/Documents/.gitkeep | 0 .../Documents/JsModules/x-color.tools.js | 506 + .../Documents/JsModules/x-file.tools.js | 830 ++ .../Documents/JsModules/x-shell.tools.js | 219 + .../JsModules/x-type-detector.tools.js | 268 + .../Documents/JsModules/x-value.tools.js | 1528 +++ .../BKPS/14030316/Experts/x-sample.ea.mq5 | 1941 ++++ .../Helpers/x-saherelm.xama.helper.ex5 | Bin 0 -> 5700 bytes .../Helpers/x-saherelm.xama.helper.mq5 | 317 + .../Helpers/x-saherelm.xcc.helper.ex5 | Bin 0 -> 6562 bytes .../Helpers/x-saherelm.xcc.helper.mq5 | 245 + .../Helpers/x-saherelm.xche.helper.ex5 | Bin 0 -> 6366 bytes .../Helpers/x-saherelm.xche.helper.mq5 | 514 + .../Helpers/x-saherelm.xct.helper.ex5 | Bin 0 -> 6130 bytes .../Helpers/x-saherelm.xct.helper.mq5 | 220 + .../Helpers/x-saherelm.xdon.helper.ex5 | Bin 0 -> 6374 bytes .../Helpers/x-saherelm.xdon.helper.mq5 | 1075 +++ .../Helpers/x-saherelm.xhk.helper.ex5 | Bin 0 -> 6010 bytes .../Helpers/x-saherelm.xhk.helper.mq5 | 1014 ++ .../Helpers/x-saherelm.xhull.helper.ex5 | Bin 0 -> 5986 bytes .../Helpers/x-saherelm.xhull.helper.mq5 | 399 + .../Helpers/x-saherelm.xich.helper.ex5 | Bin 0 -> 5740 bytes .../Helpers/x-saherelm.xich.helper.mq5 | 827 ++ .../Helpers/x-saherelm.xmc.helper.ex5 | Bin 0 -> 5906 bytes .../Helpers/x-saherelm.xmc.helper.mq5 | 496 + .../Helpers/x-saherelm.xmrb.helper.ex5 | Bin 0 -> 6378 bytes .../Helpers/x-saherelm.xmrb.helper.mq5 | 1411 +++ .../Helpers/x-saherelm.xosc.helper.ex5 | Bin 0 -> 5542 bytes .../Helpers/x-saherelm.xosc.helper.mq5 | 1321 +++ .../Helpers/x-saherelm.xpv.helper.ex5 | Bin 0 -> 5714 bytes .../Helpers/x-saherelm.xpv.helper.mq5 | 1870 ++++ .../Helpers/x-saherelm.xsslc.helper.ex5 | Bin 0 -> 5652 bytes .../Helpers/x-saherelm.xsslc.helper.mq5 | 408 + .../Helpers/x-saherelm.xstr.helper.ex5 | Bin 0 -> 5368 bytes .../Helpers/x-saherelm.xstr.helper.mq5 | 421 + .../Helpers/x-saherelm.xtd.helper.ex5 | Bin 0 -> 5978 bytes .../Helpers/x-saherelm.xtd.helper.mq5 | 458 + .../Helpers/x-saherelm.xtm.helper.ex5 | Bin 0 -> 5424 bytes .../Helpers/x-saherelm.xtm.helper.mq5 | 310 + .../Helpers/x-saherelm.xzg.helper.ex5 | Bin 0 -> 5796 bytes .../Helpers/x-saherelm.xzg.helper.mq5 | 527 ++ .../14030316/Indicators/x-saherelm.xama.mq5 | 348 + .../14030316/Indicators/x-saherelm.xcc.mq5 | 458 + .../14030316/Indicators/x-saherelm.xche.mq5 | 631 ++ .../14030316/Indicators/x-saherelm.xcss.mq5 | 666 ++ .../14030316/Indicators/x-saherelm.xct.mq5 | 261 + .../14030316/Indicators/x-saherelm.xdon.mq5 | 366 + .../14030316/Indicators/x-saherelm.xhk.mq5 | 479 + .../14030316/Indicators/x-saherelm.xhull.mq5 | 583 ++ .../14030316/Indicators/x-saherelm.xich.mq5 | 846 ++ .../14030316/Indicators/x-saherelm.xmc.mq5 | 446 + .../14030316/Indicators/x-saherelm.xmrb.mq5 | 855 ++ .../14030316/Indicators/x-saherelm.xosc.mq5 | 721 ++ .../14030316/Indicators/x-saherelm.xpv.mq5 | 1211 +++ .../14030316/Indicators/x-saherelm.xsslc.mq5 | 440 + .../14030316/Indicators/x-saherelm.xstr.mq5 | 580 ++ .../14030316/Indicators/x-saherelm.xtd.mq5 | 457 + .../Indicators/x-saherelm.xtd.osc.mq5 | 457 + .../14030316/Indicators/x-saherelm.xtm.mq5 | 351 + .../14030316/Indicators/x-saherelm.xzg.mq5 | 750 ++ .../Libraries/x-saherelm.common.lib.mq5 | 8270 +++++++++++++++++ .../Libraries/x-saherelm.draw.lib.mq5 | 2443 +++++ .../Libraries/x-saherelm.xtrade.lib.mq5 | 4260 +++++++++ 85 files changed, 59989 insertions(+) create mode 100644 MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.base.class.ex5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.base.class.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.x121.xmcycle.class.ex5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.x121.xmcycle.class.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xaccount.class.ex5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xaccount.class.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xalert.class.ex5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xalert.class.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xdata-collector.class.ex5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xdata-collector.class.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xea.class.ex5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xea.class.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xhelper.class.ex5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xhelper.class.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xhttp.class.ex5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xhttp.class.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xmd5.class.ex5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xmd5.class.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xprovider.class.ex5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xprovider.class.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xtrade.class.ex5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xtrade.class.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Documents/.gitkeep create mode 100644 MQLTestWorkspace/BKPS/14030316/Documents/JsModules/x-color.tools.js create mode 100644 MQLTestWorkspace/BKPS/14030316/Documents/JsModules/x-file.tools.js create mode 100644 MQLTestWorkspace/BKPS/14030316/Documents/JsModules/x-shell.tools.js create mode 100644 MQLTestWorkspace/BKPS/14030316/Documents/JsModules/x-type-detector.tools.js create mode 100644 MQLTestWorkspace/BKPS/14030316/Documents/JsModules/x-value.tools.js create mode 100644 MQLTestWorkspace/BKPS/14030316/Experts/x-sample.ea.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xama.helper.ex5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xama.helper.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xcc.helper.ex5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xcc.helper.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xche.helper.ex5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xche.helper.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xct.helper.ex5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xct.helper.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xdon.helper.ex5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xdon.helper.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xhk.helper.ex5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xhk.helper.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xhull.helper.ex5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xhull.helper.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xich.helper.ex5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xich.helper.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xmc.helper.ex5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xmc.helper.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xmrb.helper.ex5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xmrb.helper.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xosc.helper.ex5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xosc.helper.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xpv.helper.ex5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xpv.helper.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xsslc.helper.ex5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xsslc.helper.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xstr.helper.ex5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xstr.helper.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xtd.helper.ex5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xtd.helper.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xtm.helper.ex5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xtm.helper.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xzg.helper.ex5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xzg.helper.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xama.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xcc.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xche.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xcss.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xct.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xdon.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xhk.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xhull.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xich.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xmc.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xmrb.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xosc.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xpv.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xsslc.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xstr.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xtd.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xtd.osc.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xtm.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xzg.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Libraries/x-saherelm.common.lib.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Libraries/x-saherelm.draw.lib.mq5 create mode 100644 MQLTestWorkspace/BKPS/14030316/Libraries/x-saherelm.xtrade.lib.mq5 diff --git a/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.base.class.ex5 b/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.base.class.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..d02756abc4de47b0aa5d1cd72a2ae8bd3922cc9b GIT binary patch literal 5610 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 literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.base.class.mq5 b/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.base.class.mq5 new file mode 100644 index 0000000..3178250 --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.base.class.mq5 @@ -0,0 +1,49 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XBaseClass +// Description: provides all based classes for use ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// XBase Class ... +class XSCBase +{ + // + // Public ... +public: + // + // Protected ... + + // + // Represent Basic Unique Tag ... + virtual string GetTag(); + + // + // Retrieve Class Token ... + virtual string GetToken(); + +protected: + // + // Private ... +private: +}; + +// \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.x121.xmcycle.class.ex5 b/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.x121.xmcycle.class.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..a2872ade0ac6ebd4b1a1b10329aac27ef765f1f1 GIT binary patch literal 10718 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 literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.x121.xmcycle.class.mq5 b/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.x121.xmcycle.class.mq5 new file mode 100644 index 0000000..af49181 --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.x121.xmcycle.class.mq5 @@ -0,0 +1,5761 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSC121MCycle +// Description: provides all requirements for +// Handling Specified Market Cycle Analysis... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... + +// +#include "../Libraries/x-saherelm.draw.lib.mq5" +#include "../Libraries/x-saherelm.xtrade.lib.mq5" + +// +#include "../Helpers/x-saherelm.xtd.helper.mq5" +#include "../Helpers/x-saherelm.xhk.helper.mq5" +#include "../Helpers/x-saherelm.xmc.helper.mq5" +#include "../Helpers/x-saherelm.xpv.helper.mq5" +#include "../Helpers/x-saherelm.xzg.helper.mq5" +#include "../Helpers/x-saherelm.xmrb.helper.mq5" +#include "../Helpers/x-saherelm.xdon.helper.mq5" +#include "../Helpers/x-saherelm.xche.helper.mq5" +#include "../Helpers/x-saherelm.xosc.helper.mq5" +#include "../Helpers/x-saherelm.xstr.helper.mq5" +#include "../Helpers/x-saherelm.xich.helper.mq5" + +// +#include "../Classes/x-saherelm.xalert.class.mq5" + +// +// Definitions ... + +// +// Signallers ... +enum ENUM_XSIGNAL_PROVIDERS +{ + // + PROVIDER_NONE, + XSP, + XTEST, + X786, + X121, + X110, + X92, + X128, +}; + +// +void GetAllXSignalProviders(ENUM_XSIGNAL_PROVIDERS &result[]) +{ + // + Clean(result); + + // + Add(XSP, result); + Add(XTEST, result); + Add(X786, result); + Add(X121, result); + Add(X110, result); + Add(X92, result); + Add(X128, result); +} + +// +string ToString(ENUM_XSIGNAL_PROVIDERS value) +{ + return EnumToString(value); +} + +// +ENUM_XSIGNAL_PROVIDERS ToXSignalProvider(string content) +{ + // + ENUM_XSIGNAL_PROVIDERS result = PROVIDER_NONE; + + // + if (!IsValid(content)) + { + return result; + } + + // + if (content == ToString(PROVIDER_NONE)) + { + result = PROVIDER_NONE; + } + else if (content == ToString(XSP)) + { + result = XSP; + } + else if (content == ToString(XTEST)) + { + result = XTEST; + } + else if (content == ToString(X786)) + { + result = X786; + } + else if (content == ToString(X121)) + { + result = X121; + } + else if (content == ToString(X110)) + { + result = X110; + } + else if (content == ToString(X92)) + { + result = X92; + } + else if (content == ToString(X128)) + { + result = X128; + } + + // + return result; +} + +// +// X121 Specified Market Cycle Structure ... +class X121MCycleInputs : public XSCBase +{ + // + // Public ... +public: + // + // Props ... + + // + XMarketCycle cycle; // Cycle Descriptor ... + + // + // Draw Props ... + + // + XDrawSpecifications cBarMidDrawSpecs; // Current Bar MidLine Draw Specifications + XOHCLDrawSpecification cBarDrawSpecs; // Current Bar Draw Specifications + + // + XDrawSpecifications pBarMidDrawSpecs; // Previous Bar MidLine Draw Specifications + XOHCLDrawSpecification pBarDrawSpecs; // Previous Bar Draw Specifications + + // + bool drawLabels; // Draw Labels + bool drawCBar; // Draw Current Bar + bool drawPBar; // Draw Previous Bar + bool drawCBarMid; // Draw Current Bar Mid Line + bool drawPBarMid; // Draw Previous Bar Mid Line + + // + XHKInputs hkInputs; // HK Inputs ... + XMCInputs mcInputs; // MC Inputs ... + XPVInputs pvInputs; // PV Inputs ... + XZGInputs zgInputs; // ZG Inputs ... + XTDInputs tdInputs; // TD Inputs ... + XMRBInputs mrbInputs; // MRB Inputs ... + XSTRInputs strInputs; // STR Inputs ... + XOSCInputs oscInputs; // OSC Inputs ... + XCHEInputs cheInputs; // CHE Inputs ... + XICHInputs ichInputs; // ICH Inputs ... + XDONInputs donInputs; // DON Inputs ... + + // + // Constructor ... + + // + // Tools ... + + // + // Initialize Market Cycle ... + bool Init( + string mSymbol, // Trading Symbol + ENUM_TIMEFRAMES mHostPeriod, // Host Period + ENUM_X_MARKET_CYCLES mCycle, // Init Cycle + ENUM_TIMEFRAMES mPeriod, // Cycle Period + ENUM_X_PERIOD_METHOD mPeriodMethod, // Cycle Period Method + string mPrefix = "", // Prefix + bool useDefaults = true // Use Inputs Default Settings ... + ) + { + // + bool result = false; + + // + cycle.period = mPeriod; + cycle.method = mPeriodMethod; + + // + // Initial Cycle Model ... + result = cycle.Init( + mSymbol, + mHostPeriod, + mCycle, + mPrefix + // + ); + if (!result) + { + return result; + } + + // + if (useDefaults) + { + // + hkInputs.Default(); + mcInputs.Default(); + pvInputs.Default(); + zgInputs.Default(); + mrbInputs.Default(); + strInputs.Default(); + oscInputs.Default(); + cheInputs.Default(); + ichInputs.Default(); + donInputs.Default(); + } + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + return result; + } + + // + // Initialize Market Cycle ... + bool Init( + string mSymbol, // Trading Symbol + ENUM_TIMEFRAMES mHostPeriod, // Host Period + ENUM_X_MARKET_CYCLES mCycle, // Init Cycle + XHKInputs &mHkInputs, // HK Inputs + XMCInputs &mMcInputs, // MC Inputs + XPVInputs &mPvInputs, // PV Inputs ... + XZGInputs &mZgInputs, // ZG Inputs ... + XTDInputs &mTdInputs, // TD Inputs ... + XMRBInputs &mMrbInputs, // MRB Inputs ... + XSTRInputs &mStrInputs, // STR Inputs + XOSCInputs &mOscInputs, // OSC Inputs + XCHEInputs &mCheInputs, // CHE Inputs + XICHInputs &mIchInputs, // ICH Inputs ... + XDONInputs &mDonInputs, // DON Inputs ... + int mHostBarIndex = 0, // Specified Host Period Bar Index + string mPrefix = "" // Prefix + ) + { + // + bool result = false; + + // + // Initial Cycle Model ... + result = cycle.Init( + mSymbol, + mHostPeriod, + mCycle, + mPrefix + // + ); + if (!result) + { + return result; + } + + // + hkInputs = mHkInputs; + mcInputs = mMcInputs; + pvInputs = mPvInputs; + zgInputs = mZgInputs; + tdInputs = mTdInputs; + mrbInputs = mMrbInputs; + strInputs = mStrInputs; + oscInputs = mOscInputs; + cheInputs = mCheInputs; + ichInputs = mIchInputs; + donInputs = mDonInputs; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + return result; + } + + // + // Cleanup ... + virtual void Clean() + { + // + cycle.Clean(); + + // + hkInputs.Clean(); + mcInputs.Clean(); + pvInputs.Clean(); + zgInputs.Clean(); + tdInputs.Clean(); + mrbInputs.Clean(); + strInputs.Clean(); + oscInputs.Clean(); + cheInputs.Clean(); + ichInputs.Clean(); + donInputs.Clean(); + + // + cBarDrawSpecs.Clean(); + pBarDrawSpecs.Clean(); + cBarMidDrawSpecs.Clean(); + pBarMidDrawSpecs.Clean(); + + // + drawLabels = false; + drawCBar = false; + drawPBar = false; + drawCBarMid = false; + drawPBarMid = false; + } + + // + // Default ... + virtual void Default() + { + // + hkInputs.Default(); + mcInputs.Default(); + pvInputs.Default(); + zgInputs.Default(); + tdInputs.Default(); + mrbInputs.Default(); + strInputs.Default(); + oscInputs.Default(); + cheInputs.Default(); + ichInputs.Default(); + donInputs.Default(); + + // + drawLabels = false; + drawCBar = false; + drawPBar = false; + drawCBarMid = false; + drawPBarMid = false; + } + + // + // Validation ... + virtual bool IsValid() + { + // + bool result = false; + + // + result = cycle.IsValid(); + if (!result) + { + return result; + } + + // + result = hkInputs.IsValid(); + if (!result) + { + return result; + } + + // + result = mcInputs.IsValid(); + if (!result) + { + return result; + } + + // + result = pvInputs.IsValid(); + if (!result) + { + return result; + } + + // + result = zgInputs.IsValid(); + if (!result) + { + return result; + } + + // + result = tdInputs.IsValid(); + if (!result) + { + return result; + } + + // + result = mrbInputs.IsValid(); + if (!result) + { + return result; + } + + // + result = strInputs.IsValid(); + if (!result) + { + return result; + } + + // + result = oscInputs.IsValid(); + if (!result) + { + return result; + } + + // + result = cheInputs.IsValid(); + if (!result) + { + return result; + } + + // + result = ichInputs.IsValid(); + if (!result) + { + return result; + } + + // + result = donInputs.IsValid(); + if (!result) + { + return result; + } + + // + return result; + } + + // + // Max ... + virtual int Max() + { + // + int result = 0; + + // + result = MathMax(mcInputs.Max(), strInputs.Max()); + + // + result = MathMax(result, hkInputs.Max()); + result = MathMax(result, mcInputs.Max()); + result = MathMax(result, pvInputs.Max()); + result = MathMax(result, zgInputs.Max()); + result = MathMax(result, tdInputs.Max()); + result = MathMax(result, mrbInputs.Max()); + result = MathMax(result, strInputs.Max()); + result = MathMax(result, oscInputs.Max()); + result = MathMax(result, cheInputs.Max()); + result = MathMax(result, ichInputs.Max()); + result = MathMax(result, donInputs.Max()); + + // + return result; + } +}; + +// +// Specific Market Sense Based on Specified Bar Index on Host Period ... +class X121MCycleConditions : public XSCBase +{ + // + // Public ... +public: + // + // Props ... + datetime time; // Time + string symbol; // Symbol + ENUM_TIMEFRAMES period; // Period + + // + string prefix; // Cycle Prefix + ENUM_X_MARKET_CYCLES cycle; // Init Cycle + ENUM_TIMEFRAMES hostPeriod; // Hosting Time Frame + + // + XOHCL bars[]; // Number of Bars + + // + // Candlestic Conditions ... + bool isLastBullish; + bool isLastBearish; + bool isCurrentBullish; + bool isCurrentBearish; + bool isCurrentMidLineOverLastHigh; + bool isCurrentMidLineUnderLastLow; + bool isCurrentMidLineOverLastUp; + bool isCurrentMidLineUnderLastDown; + bool isCurrentMidLineOverLastMidLine; + bool isCurrentMidLineUnderLastMidLine; + + // + // Buffers ... + + // + XOHCL hkBars[]; + XOHCL smHKBars[]; + + // + // XICH ... + double ichTenkanSens[]; + double ichKijunSens[]; + double ichChikouSpans[]; + double ichSenkouSpanAs[]; + double ichSenkouSpanBs[]; + double ichFutureSenkouSpanAs[]; + double ichFutureSenkouSpanBs[]; + + // + // XMC ... + double mcFasts[]; + double mcSlows[]; + double mcVerifiers[]; + + // + // XSTR ... + double strTrends[]; + double strStates[]; + + // + // XZG ... + double zigzags[]; + double zigzagPVs[]; + + // + // XMRB ... + + // + double mrbFasts[]; + double mrb1Fasts[]; + double mrb2Fasts[]; + double mrb3Fasts[]; + double mrb4Fasts[]; + double mrb5Fasts[]; + double mrb6Fasts[]; + + // + double mrbSlows[]; + double mrb1Slows[]; + double mrb2Slows[]; + double mrb3Slows[]; + double mrb4Slows[]; + double mrb5Slows[]; + double mrb6Slows[]; + + // + // XCHE ... + double cheLongExit1s[]; + double cheLongExit2s[]; + double cheShortExit1s[]; + double cheShortExit2s[]; + + // + // XDON ... + double donUpperOs[]; + double donLowerOs[]; + double donUpperCs[]; + double donLowerCs[]; + double donUpperHs[]; + double donLowerHs[]; + double donUpperLs[]; + double donLowerLs[]; + + // + // XPV ... + double pvPeaks[]; + double pvVales[]; + double pvResistances[]; + double pvSupports[]; + double pvFib1s[]; + double pvFib2s[]; + double pvFib3s[]; + double pvFib4s[]; + double pvFib5s[]; + double pvSCHHs[]; + double pvSCLLs[]; + double pvMCHHs[]; + double pvMCLLs[]; + double pvLCHHs[]; + double pvLCLLs[]; + double pvHCHHs[]; + double pvHCLLs[]; + + // + // XOSC ... + double oscAtrs[]; + double oscRviMains[]; + double oscRviSignals[]; + double oscBullPs[]; + double oscBearPs[]; + double oscVolumes[]; + double oscRsis[]; + double oscCcis[]; + double oscMomentums[]; + double oscSars[]; + double oscMacdMains[]; + double oscMacdSignals[]; + double oscStochMains[]; + double oscStochSignals[]; + double oscStddevs[]; + + // + // XTD ... + double tdBullishs[]; + double tdBearishs[]; + double tdSignals[]; + + // + // General Conditions ... + + // + // XZG ... + bool isZigZagInPeak; + bool isZigZagInVale; + + // + // XPV ... + + // + bool isNewPeak; + bool isNewPeakOverLast; + bool isNewPeakUnderLast; + + // + bool isNewVale; + bool isNewValeOverLast; + bool isNewValeUnderLast; + + // + bool isFiboIncreased; + bool isFiboDecreased; + bool isFiboSectionChanged; + + // + // SC ... + + // + bool isSCBullish; + bool isSCHHBullish; + bool isSCLLBullish; + bool isSCSwitchedToBullish; + bool isSCHHSwitchedToBullish; + bool isSCLLSwitchedToBullish; + + // + bool isSCBearish; + bool isSCHHBearish; + bool isSCLLBearish; + bool isSCSwitchedToBearish; + bool isSCHHSwitchedToBearish; + bool isSCLLSwitchedToBeraish; + + // + // MC ... + + // + bool isMCBullish; + bool isMCHHBullish; + bool isMCLLBullish; + bool isMCSwitchedToBullish; + bool isMCHHSwitchedToBullish; + bool isMCLLSwitchedToBullish; + + // + bool isMCBearish; + bool isMCHHBearish; + bool isMCLLBearish; + bool isMCSwitchedToBearish; + bool isMCHHSwitchedToBearish; + bool isMCLLSwitchedToBeraish; + + // + // LC ... + + // + bool isLCBullish; + bool isLCHHBullish; + bool isLCLLBullish; + bool isLCSwitchedToBullish; + bool isLCHHSwitchedToBullish; + bool isLCLLSwitchedToBullish; + // + bool isLCBearish; + bool isLCHHBearish; + bool isLCLLBearish; + bool isLCSwitchedToBearish; + bool isLCHHSwitchedToBearish; + bool isLCLLSwitchedToBeraish; + + // + // HC ... + + // + bool isHCBullish; + bool isHCHHBullish; + bool isHCLLBullish; + bool isHCSwitchedToBullish; + bool isHCHHSwitchedToBullish; + bool isHCLLSwitchedToBullish; + + // + bool isHCBearish; + bool isHCHHBearish; + bool isHCLLBearish; + bool isHCSwitchedToBearish; + bool isHCHHSwitchedToBearish; + bool isHCLLSwitchedToBeraish; + + // + // XHK ... + + // + bool isHKBullish; + bool isHKBearish; + bool isClosedOverHK; + bool isClosedUnderHK; + bool isHKSwitchedToBullish; + bool isHKSwitchedToBearish; + + // + bool isSMHKBullish; + bool isSMHKBearish; + bool isClosedOverSMHK; + bool isClosedUnderSMHK; + bool isSMHKSwitchedToBullish; + bool isSMHKSwitchedToBearish; + + // + // XSTR ... + bool isTrendBullish; + bool isTrendBearish; + bool isTrendSwitchedToBullish; + bool isTrendSwitchedToBearish; + + // + // XTD ... + bool isTDBullish; + bool isTDBearish; + bool isTDSwitchedToBullish; + bool isTDSwitchedToBearish; + + // + // XCHE ... + bool isCHEBullish; + bool isCHEBearish; + bool isCHESwitchedToBullish; + bool isCHESwitchedToBearish; + + // + // XMC ... + bool isMCFastOverSlow; + bool isMCFastUnderSlow; + bool isMCFastOverVerifier; + bool isMCFastUnderVerifier; + bool isMCSlowOverVerifier; + bool isMCSlowUnderVerifier; + bool isMCFastCrossedOverSlow; + bool isMCFastCrossedUnderSlow; + bool isMCFastCrossedOverVerifier; + bool isMCFastCrossedUnderVerifier; + bool isMCSlowCrossedOverVerifier; + bool isMCSlowCrossedUnderVerifier; + + // + // XMRB ... + bool isMRBFastOverSlow; + bool isMRBFastUnderSlow; + bool isMRBFastCrossedOverSlow; + bool isMRBFastCrossedUnderSlow; + bool isMRBFastOverVerifier; + bool isMRBFastUnderVerifier; + bool isMRBFastCrossedtOverVerifier; + bool isMRBFastCrossedUnderVerifier; + bool isMRBSlowOverVerifier; + bool isMRBSlowUnderVerifier; + bool isMRBSlowCrossedtOverVerifier; + bool isMRBSlowCrossedUnderVerifier; + + // + // XDON ... + + // + bool isDONAttachedMaxLower; + bool isDONAttachedMinLower; + bool isDONCrossedOverMaxLower; + bool isDONCrossedUnderMaxLower; + bool isDONCrossedOverMinLower; + bool isDONCrossedUnderMinLower; + + // + bool isDONAttachedMaxUpper; + bool isDONAttachedMinUpper; + bool isDONCrossedOverMaxUpper; + bool isDONCrossedUnderMaxUpper; + bool isDONCrossedOverMinUpper; + bool isDONCrossedUnderMinUpper; + + // + // XICH ... + + // + bool isClosedOverKijunSen; + bool isClosedUnderKijunSen; + bool isTenkanSenOverKijunSen; + bool isTenkanSenUnderKijunSen; + bool isTenkanSenCrossedOverKijunSen; + bool isTenkanSenCrossedUnderKijunSen; + + // + bool isSenkouSpanAOverB; + bool isSenkouSpanAUnderB; + bool isSenkouSpanAOverLast; + bool isSenkouSpanAUnderLast; + bool isFutureSenkouSpanAOverB; + bool isFutureSenkouSpanAUnderB; + bool isFutureSenkouSpanAOverLast; + bool isFutureSenkouSpanAUnderLast; + + // + bool isSenkouSpanACrossedOverB; + bool isSenkouSpanACrossedUnderB; + bool isSenkouSpanACrossedOverLast; + bool isSenkouSpanACrossedUnderLast; + bool isFutureSenkouSpanACrossedOverB; + bool isFutureSenkouSpanACrossedUnderB; + bool isFutureSenkouSpanACrossedOverLast; + bool isFutureSenkouSpanACrossedUnderLast; + + // + // XOSC ... + + // + // SAR ... + // ATR ... + // RVI ... + // RSI ... + // CCI ... + // MACD ... + // STOCH ... + // BULLP ... + // BEARP ... + // STDDEV ... + // VOLUME ... + // MOMENTUM ... + + // + // Tools ... + + // + void Clear() + { + // + // Commons ... + time = 0; + cycle = NULL; + prefix = NULL; + symbol = NULL; + period = NULL; + hostPeriod = NULL; + + // + Clean(bars); + + // + // Candlestic ... + isLastBullish = false; + isLastBearish = false; + isCurrentBullish = false; + isCurrentBearish = false; + isCurrentMidLineOverLastHigh = false; + isCurrentMidLineUnderLastLow = false; + isCurrentMidLineOverLastUp = false; + isCurrentMidLineUnderLastDown = false; + isCurrentMidLineOverLastMidLine = false; + isCurrentMidLineUnderLastMidLine = false; + + // + // Buffers ... + Clean(bars); + Clean(hkBars); + Clean(smHKBars); + Clean(ichTenkanSens); + Clean(ichKijunSens); + Clean(ichChikouSpans); + Clean(ichSenkouSpanAs); + Clean(ichSenkouSpanBs); + Clean(ichFutureSenkouSpanAs); + Clean(ichFutureSenkouSpanBs); + Clean(mcFasts); + Clean(mcSlows); + Clean(mcVerifiers); + Clean(strTrends); + Clean(strStates); + Clean(cheLongExit1s); + Clean(cheLongExit2s); + Clean(cheShortExit1s); + Clean(cheShortExit2s); + Clean(oscAtrs); + Clean(oscRviMains); + Clean(oscRviSignals); + Clean(oscBullPs); + Clean(oscBearPs); + Clean(oscVolumes); + Clean(oscRsis); + Clean(oscCcis); + Clean(oscMomentums); + Clean(oscSars); + Clean(oscMacdMains); + Clean(oscMacdSignals); + Clean(oscStochMains); + Clean(oscStochSignals); + Clean(oscStddevs); + Clean(zigzags); + Clean(zigzagPVs); + Clean(mrbFasts); + Clean(mrb1Fasts); + Clean(mrb2Fasts); + Clean(mrb3Fasts); + Clean(mrb4Fasts); + Clean(mrb5Fasts); + Clean(mrb6Fasts); + Clean(mrbSlows); + Clean(mrb1Slows); + Clean(mrb2Slows); + Clean(mrb3Slows); + Clean(mrb4Slows); + Clean(mrb5Slows); + Clean(mrb6Slows); + Clean(donUpperOs); + Clean(donLowerOs); + Clean(donUpperCs); + Clean(donLowerCs); + Clean(donUpperHs); + Clean(donLowerHs); + Clean(donUpperLs); + Clean(donLowerLs); + Clean(pvPeaks); + Clean(pvVales); + Clean(pvResistances); + Clean(pvSupports); + Clean(pvFib1s); + Clean(pvFib2s); + Clean(pvFib3s); + Clean(pvFib4s); + Clean(pvFib5s); + Clean(pvSCHHs); + Clean(pvSCLLs); + Clean(pvMCHHs); + Clean(pvMCLLs); + Clean(pvLCHHs); + Clean(pvLCLLs); + Clean(pvHCHHs); + Clean(pvHCLLs); + Clean(tdBullishs); + Clean(tdBearishs); + Clean(tdSignals); + + // + // Buffers ... + ArraySetAsSeries(bars, true); + ArraySetAsSeries(hkBars, true); + ArraySetAsSeries(smHKBars, true); + ArraySetAsSeries(ichTenkanSens, true); + ArraySetAsSeries(ichKijunSens, true); + ArraySetAsSeries(ichChikouSpans, true); + ArraySetAsSeries(ichSenkouSpanAs, true); + ArraySetAsSeries(ichSenkouSpanBs, true); + ArraySetAsSeries(ichFutureSenkouSpanAs, true); + ArraySetAsSeries(ichFutureSenkouSpanBs, true); + ArraySetAsSeries(mcFasts, true); + ArraySetAsSeries(mcSlows, true); + ArraySetAsSeries(mcVerifiers, true); + ArraySetAsSeries(strTrends, true); + ArraySetAsSeries(strStates, true); + ArraySetAsSeries(cheLongExit1s, true); + ArraySetAsSeries(cheLongExit2s, true); + ArraySetAsSeries(cheShortExit1s, true); + ArraySetAsSeries(cheShortExit2s, true); + ArraySetAsSeries(oscAtrs, true); + ArraySetAsSeries(oscRviMains, true); + ArraySetAsSeries(oscRviSignals, true); + ArraySetAsSeries(oscBullPs, true); + ArraySetAsSeries(oscBearPs, true); + ArraySetAsSeries(oscVolumes, true); + ArraySetAsSeries(oscRsis, true); + ArraySetAsSeries(oscCcis, true); + ArraySetAsSeries(oscMomentums, true); + ArraySetAsSeries(oscSars, true); + ArraySetAsSeries(oscMacdMains, true); + ArraySetAsSeries(oscMacdSignals, true); + ArraySetAsSeries(oscStochMains, true); + ArraySetAsSeries(oscStochSignals, true); + ArraySetAsSeries(oscStddevs, true); + ArraySetAsSeries(zigzags, true); + ArraySetAsSeries(zigzagPVs, true); + ArraySetAsSeries(mrbFasts, true); + ArraySetAsSeries(mrb1Fasts, true); + ArraySetAsSeries(mrb2Fasts, true); + ArraySetAsSeries(mrb3Fasts, true); + ArraySetAsSeries(mrb4Fasts, true); + ArraySetAsSeries(mrb5Fasts, true); + ArraySetAsSeries(mrb6Fasts, true); + ArraySetAsSeries(mrbSlows, true); + ArraySetAsSeries(mrb1Slows, true); + ArraySetAsSeries(mrb2Slows, true); + ArraySetAsSeries(mrb3Slows, true); + ArraySetAsSeries(mrb4Slows, true); + ArraySetAsSeries(mrb5Slows, true); + ArraySetAsSeries(mrb6Slows, true); + ArraySetAsSeries(donUpperOs, true); + ArraySetAsSeries(donLowerOs, true); + ArraySetAsSeries(donUpperCs, true); + ArraySetAsSeries(donLowerCs, true); + ArraySetAsSeries(donUpperHs, true); + ArraySetAsSeries(donLowerHs, true); + ArraySetAsSeries(donUpperLs, true); + ArraySetAsSeries(donLowerLs, true); + ArraySetAsSeries(pvPeaks, true); + ArraySetAsSeries(pvVales, true); + ArraySetAsSeries(pvResistances, true); + ArraySetAsSeries(pvSupports, true); + ArraySetAsSeries(pvFib1s, true); + ArraySetAsSeries(pvFib2s, true); + ArraySetAsSeries(pvFib3s, true); + ArraySetAsSeries(pvFib4s, true); + ArraySetAsSeries(pvFib5s, true); + ArraySetAsSeries(pvSCHHs, true); + ArraySetAsSeries(pvSCLLs, true); + ArraySetAsSeries(pvMCHHs, true); + ArraySetAsSeries(pvMCLLs, true); + ArraySetAsSeries(pvLCHHs, true); + ArraySetAsSeries(pvLCLLs, true); + ArraySetAsSeries(pvHCHHs, true); + ArraySetAsSeries(pvHCLLs, true); + ArraySetAsSeries(tdBullishs, true); + ArraySetAsSeries(tdBearishs, true); + ArraySetAsSeries(tdSignals, true); + + // + // XZG ... + isZigZagInPeak = false; + isZigZagInVale = false; + + // + // XPV ... + + // + isNewPeak = false; + isNewPeakOverLast = false; + isNewPeakUnderLast = false; + + // + isNewVale = false; + isNewValeOverLast = false; + isNewValeUnderLast = false; + + // + isFiboIncreased = false; + isFiboDecreased = false; + isFiboSectionChanged = false; + + // + // SC ... + + // + isSCBullish = false; + isSCHHBullish = false; + isSCLLBullish = false; + isSCSwitchedToBullish = false; + isSCHHSwitchedToBullish = false; + isSCLLSwitchedToBullish = false; + + // + isSCBearish = false; + isSCHHBearish = false; + isSCLLBearish = false; + isSCSwitchedToBearish = false; + isSCHHSwitchedToBearish = false; + isSCLLSwitchedToBeraish = false; + + // + // MC ... + + // + isMCBullish = false; + isMCHHBullish = false; + isMCLLBullish = false; + isMCSwitchedToBullish = false; + isMCHHSwitchedToBullish = false; + isMCLLSwitchedToBullish = false; + + // + isMCBearish = false; + isMCHHBearish = false; + isMCLLBearish = false; + isMCSwitchedToBearish = false; + isMCHHSwitchedToBearish = false; + isMCLLSwitchedToBeraish = false; + + // + // LC ... + + // + isLCBullish = false; + isLCHHBullish = false; + isLCLLBullish = false; + isLCSwitchedToBullish = false; + isLCHHSwitchedToBullish = false; + isLCLLSwitchedToBullish = false; + + // + isLCBearish = false; + isLCHHBearish = false; + isLCLLBearish = false; + isLCSwitchedToBearish = false; + isLCHHSwitchedToBearish = false; + isLCLLSwitchedToBeraish = false; + + // + // HC ... + + // + isHCBullish = false; + isHCHHBullish = false; + isHCLLBullish = false; + isHCSwitchedToBullish = false; + isHCHHSwitchedToBullish = false; + isHCLLSwitchedToBullish = false; + + // + isHCBearish = false; + isHCHHBearish = false; + isHCLLBearish = false; + isHCSwitchedToBearish = false; + isHCHHSwitchedToBearish = false; + isHCLLSwitchedToBeraish = false; + + // + // XHK ... + isHKBullish = false; + isHKBearish = false; + isClosedOverHK = false; + isClosedUnderHK = false; + isHKSwitchedToBullish = false; + isHKSwitchedToBearish = false; + + // + isSMHKBullish = false; + isSMHKBearish = false; + isClosedOverSMHK = false; + isClosedUnderSMHK = false; + isSMHKSwitchedToBullish = false; + isSMHKSwitchedToBearish = false; + + // + // XSTR ... + isTrendBullish = false; + isTrendBearish = false; + isTrendSwitchedToBullish = false; + isTrendSwitchedToBearish = false; + + // + // XTD ... + isTDBullish = false; + isTDBearish = false; + isTDSwitchedToBullish = false; + isTDSwitchedToBearish = false; + + // + // XCHE ... + isCHEBullish = false; + isCHEBearish = false; + isCHESwitchedToBullish = false; + isCHESwitchedToBearish = false; + + // + // XMC ... + isMCFastOverSlow = false; + isMCFastUnderSlow = false; + isMCFastOverVerifier = false; + isMCFastUnderVerifier = false; + isMCSlowOverVerifier = false; + isMCSlowUnderVerifier = false; + isMCFastCrossedOverSlow = false; + isMCFastCrossedUnderSlow = false; + isMCFastCrossedOverVerifier = false; + isMCFastCrossedUnderVerifier = false; + isMCSlowCrossedOverVerifier = false; + isMCSlowCrossedUnderVerifier = false; + + // + // XMRB ... + isMRBFastOverSlow = false; + isMRBFastUnderSlow = false; + isMRBFastCrossedOverSlow = false; + isMRBFastCrossedUnderSlow = false; + isMRBFastOverVerifier = false; + isMRBFastUnderVerifier = false; + isMRBFastCrossedtOverVerifier = false; + isMRBFastCrossedUnderVerifier = false; + isMRBSlowOverVerifier = false; + isMRBSlowUnderVerifier = false; + isMRBSlowCrossedtOverVerifier = false; + isMRBSlowCrossedUnderVerifier = false; + + // + // XDON ... + + // + isDONAttachedMaxLower = false; + isDONAttachedMinLower = false; + isDONCrossedOverMaxLower = false; + isDONCrossedUnderMaxLower = false; + isDONCrossedOverMinLower = false; + isDONCrossedUnderMinLower = false; + + // + isDONAttachedMaxUpper = false; + isDONAttachedMinUpper = false; + isDONCrossedOverMaxUpper = false; + isDONCrossedUnderMaxUpper = false; + isDONCrossedOverMinUpper = false; + isDONCrossedUnderMinUpper = false; + + // + // XICH ... + + // + isClosedOverKijunSen = false; + isClosedUnderKijunSen = false; + isTenkanSenOverKijunSen = false; + isTenkanSenUnderKijunSen = false; + isTenkanSenCrossedOverKijunSen = false; + isTenkanSenCrossedUnderKijunSen = false; + + // + isSenkouSpanAOverB = false; + isSenkouSpanAUnderB = false; + isSenkouSpanAOverLast = false; + isSenkouSpanAUnderLast = false; + isFutureSenkouSpanAOverB = false; + isFutureSenkouSpanAUnderB = false; + isFutureSenkouSpanAOverLast = false; + isFutureSenkouSpanAUnderLast = false; + + // + isSenkouSpanACrossedOverB = false; + isSenkouSpanACrossedUnderB = false; + isSenkouSpanACrossedOverLast = false; + isSenkouSpanACrossedUnderLast = false; + isFutureSenkouSpanACrossedOverB = false; + isFutureSenkouSpanACrossedUnderB = false; + isFutureSenkouSpanACrossedOverLast = false; + isFutureSenkouSpanACrossedUnderLast = false; + } + + // + // Generate Score ... + void GenerateScore( + double &bullishScore, // Holds Bullish Score ... + double &bearishScore, // Holds Bearish Score ... + double multiplier = 1 // Score Multiplier ... + ) + { + // + double bullScore = 0; + double bearScore = 0; + + // + if (multiplier <= 0) + { + multiplier = 1; + } + + // + // Candlestic ... + if (isLastBullish) + { + bullScore++; + } + if (isLastBearish) + { + bearScore++; + } + if (isCurrentBullish) + { + bullScore++; + } + if (isCurrentBearish) + { + bearScore++; + } + if (isCurrentMidLineOverLastHigh) + { + bullScore++; + } + if (isCurrentMidLineUnderLastLow) + { + bearScore++; + } + if (isCurrentMidLineOverLastUp) + { + bullScore++; + } + if (isCurrentMidLineUnderLastDown) + { + bearScore++; + } + if (isCurrentMidLineOverLastMidLine) + { + bullScore++; + } + if (isCurrentMidLineUnderLastMidLine) + { + bearScore++; + } + + // + // XZG ... + if (isZigZagInPeak) + { + bullScore++; + } + if (isZigZagInVale) + { + bearScore++; + } + + // + // XPV ... + + // + if (isNewPeak) + { + bearScore++; + } + if (isNewPeakOverLast) + { + } + if (isNewPeakUnderLast) + { + } + + // + if (isNewVale) + { + bullScore++; + } + if (isNewValeOverLast) + { + } + if (isNewValeUnderLast) + { + } + + // + if (isFiboIncreased) + { + bullScore++; + } + if (isFiboDecreased) + { + bearScore++; + } + if (isFiboSectionChanged) + { + } + + // + // SC ... + + // + if (isSCBullish) + { + bullScore++; + } + if (isSCHHBullish) + { + bullScore++; + } + if (isSCLLBullish) + { + bullScore++; + } + if (isSCSwitchedToBullish) + { + bullScore++; + } + if (isSCHHSwitchedToBullish) + { + bullScore++; + } + if (isSCLLSwitchedToBullish) + { + bullScore++; + } + + // + if (isSCBearish) + { + bearScore++; + } + if (isSCHHBearish) + { + bearScore++; + } + if (isSCLLBearish) + { + bearScore++; + } + if (isSCSwitchedToBearish) + { + bearScore++; + } + if (isSCHHSwitchedToBearish) + { + bearScore++; + } + if (isSCLLSwitchedToBeraish) + { + bearScore++; + } + + // + // MC ... + + // + if (isMCBullish) + { + bullScore++; + } + if (isMCHHBullish) + { + bullScore++; + } + if (isMCLLBullish) + { + bullScore++; + } + if (isMCSwitchedToBullish) + { + bullScore++; + } + if (isMCHHSwitchedToBullish) + { + bullScore++; + } + if (isMCLLSwitchedToBullish) + { + bullScore++; + } + + // + if (isMCBearish) + { + bearScore++; + } + if (isMCHHBearish) + { + bearScore++; + } + if (isMCLLBearish) + { + bearScore++; + } + if (isMCSwitchedToBearish) + { + bearScore++; + } + if (isMCHHSwitchedToBearish) + { + bearScore++; + } + if (isMCLLSwitchedToBeraish) + { + bearScore++; + } + + // + // LC ... + + // + if (isLCBullish) + { + bullScore++; + } + if (isLCHHBullish) + { + bullScore++; + } + if (isLCLLBullish) + { + bullScore++; + } + if (isLCSwitchedToBullish) + { + bullScore++; + } + if (isLCHHSwitchedToBullish) + { + bullScore++; + } + if (isLCLLSwitchedToBullish) + { + bullScore++; + } + + // + if (isLCBearish) + { + bearScore++; + } + if (isLCHHBearish) + { + bearScore++; + } + if (isLCLLBearish) + { + bearScore++; + } + if (isLCSwitchedToBearish) + { + bearScore++; + } + if (isLCHHSwitchedToBearish) + { + bearScore++; + } + if (isLCLLSwitchedToBeraish) + { + bearScore++; + } + + // + // HC ... + + // + if (isHCBullish) + { + bullScore++; + } + if (isHCHHBullish) + { + bullScore++; + } + if (isHCLLBullish) + { + bullScore++; + } + if (isHCSwitchedToBullish) + { + bullScore++; + } + if (isHCHHSwitchedToBullish) + { + bullScore++; + } + if (isHCLLSwitchedToBullish) + { + bullScore++; + } + + // + if (isHCBearish) + { + bearScore++; + } + if (isHCHHBearish) + { + bearScore++; + } + if (isHCLLBearish) + { + bearScore++; + } + if (isHCSwitchedToBearish) + { + bearScore++; + } + if (isHCHHSwitchedToBearish) + { + bearScore++; + } + if (isHCLLSwitchedToBeraish) + { + bearScore++; + } + + // + // XHK ... + + // + if (isHKBullish) + { + bullScore++; + } + if (isHKBearish) + { + bearScore++; + } + if (isClosedOverHK) + { + bullScore++; + } + if (isClosedUnderHK) + { + bearScore++; + } + if (isHKSwitchedToBullish) + { + bullScore++; + } + if (isHKSwitchedToBearish) + { + bearScore++; + } + + // + if (isSMHKBullish) + { + bullScore++; + } + if (isSMHKBearish) + { + bearScore++; + } + if (isClosedOverSMHK) + { + bullScore++; + } + if (isClosedUnderSMHK) + { + bearScore++; + } + if (isSMHKSwitchedToBullish) + { + bullScore++; + } + if (isSMHKSwitchedToBearish) + { + bearScore++; + } + + // + // XSTR ... + if (isTrendBullish) + { + bullScore++; + } + if (isTrendBearish) + { + bearScore++; + } + if (isTrendSwitchedToBullish) + { + bullScore++; + } + if (isTrendSwitchedToBearish) + { + bearScore++; + } + + // + // XTD ... + if (isTDBullish) + { + bullScore++; + } + if (isTDBearish) + { + bearScore++; + } + if (isTDSwitchedToBullish) + { + bullScore++; + } + if (isTDSwitchedToBearish) + { + bearScore++; + } + + // + // XCHE ... + if (isCHEBullish) + { + bullScore++; + } + if (isCHEBearish) + { + bearScore++; + } + if (isCHESwitchedToBullish) + { + bullScore++; + } + if (isCHESwitchedToBearish) + { + bearScore++; + } + + // + // XMC ... + if (isMCFastOverSlow) + { + bullScore++; + } + if (isMCFastUnderSlow) + { + bearScore++; + } + if (isMCFastOverVerifier) + { + bullScore++; + } + if (isMCFastUnderVerifier) + { + bearScore++; + } + if (isMCSlowOverVerifier) + { + bullScore++; + } + if (isMCSlowUnderVerifier) + { + bearScore++; + } + if (isMCFastCrossedOverSlow) + { + bullScore++; + } + if (isMCFastCrossedUnderSlow) + { + bearScore++; + } + if (isMCFastCrossedOverVerifier) + { + bullScore++; + } + if (isMCFastCrossedUnderVerifier) + { + bearScore++; + } + if (isMCSlowCrossedOverVerifier) + { + bullScore++; + } + if (isMCSlowCrossedUnderVerifier) + { + bearScore++; + } + + // + // XMRB ... + if (isMRBFastOverSlow) + { + bullScore++; + } + if (isMRBFastUnderSlow) + { + bearScore++; + } + if (isMRBFastCrossedOverSlow) + { + bullScore++; + } + if (isMRBFastCrossedUnderSlow) + { + bearScore++; + } + if (isMRBFastOverVerifier) + { + bullScore++; + } + if (isMRBFastUnderVerifier) + { + bearScore++; + } + if (isMRBFastCrossedtOverVerifier) + { + bullScore++; + } + if (isMRBFastCrossedUnderVerifier) + { + bearScore++; + } + if (isMRBSlowOverVerifier) + { + bullScore++; + } + if (isMRBSlowUnderVerifier) + { + bearScore++; + } + if (isMRBSlowCrossedtOverVerifier) + { + bullScore++; + } + if (isMRBSlowCrossedUnderVerifier) + { + bearScore++; + } + + // + // XDON ... + + // + if (isDONAttachedMaxLower) + { + bullScore++; + } + if (isDONAttachedMinLower) + { + bullScore++; + } + if (isDONCrossedOverMaxLower) + { + bullScore++; + } + if (isDONCrossedUnderMaxLower) + { + bullScore++; + } + if (isDONCrossedOverMinLower) + { + bullScore++; + } + if (isDONCrossedUnderMinLower) + { + bullScore++; + } + + // + if (isDONAttachedMaxUpper) + { + bearScore++; + } + if (isDONAttachedMinUpper) + { + bearScore++; + } + if (isDONCrossedOverMaxUpper) + { + bearScore++; + } + if (isDONCrossedUnderMaxUpper) + { + bearScore++; + } + if (isDONCrossedOverMinUpper) + { + bearScore++; + } + if (isDONCrossedUnderMinUpper) + { + bearScore++; + } + + // + // XICH ... + + // + if (isClosedOverKijunSen) + { + bullScore++; + } + if (isClosedUnderKijunSen) + { + bearScore++; + } + if (isTenkanSenOverKijunSen) + { + bullScore++; + } + if (isTenkanSenUnderKijunSen) + { + bearScore++; + } + if (isTenkanSenCrossedOverKijunSen) + { + bullScore++; + } + if (isTenkanSenCrossedUnderKijunSen) + { + bearScore++; + } + + // + if (isSenkouSpanAOverB) + { + bullScore++; + } + if (isSenkouSpanAUnderB) + { + bearScore++; + } + if (isSenkouSpanAOverLast) + { + bullScore++; + } + if (isSenkouSpanAUnderLast) + { + bearScore++; + } + if (isFutureSenkouSpanAOverB) + { + bullScore++; + } + if (isFutureSenkouSpanAUnderB) + { + bearScore++; + } + if (isFutureSenkouSpanAOverLast) + { + bullScore++; + } + if (isFutureSenkouSpanAUnderLast) + { + bearScore++; + } + + // + if (isSenkouSpanACrossedOverB) + { + bullScore++; + } + if (isSenkouSpanACrossedUnderB) + { + bearScore++; + } + if (isSenkouSpanACrossedOverLast) + { + bullScore++; + } + if (isSenkouSpanACrossedUnderLast) + { + bearScore++; + } + if (isFutureSenkouSpanACrossedOverB) + { + bullScore++; + } + if (isFutureSenkouSpanACrossedUnderB) + { + bearScore++; + } + if (isFutureSenkouSpanACrossedOverLast) + { + bullScore++; + } + if (isFutureSenkouSpanACrossedUnderLast) + { + bearScore++; + } + + // + bullishScore = bullScore * multiplier; + bearishScore = bearScore * multiplier; + } + + // + // Generate Summary ... + string GenerateSummary( + const bool onlySummary = false, // Only Generate Conditions Summary + double multiplier = 1, // Score Multiplier + const string separator = "\n", // Separator + const bool ignoreFalseConditions = true // Ignore False Conditions + ) + { + // + string result = NULL; + + // + result = GenerateSummaryBody( + onlySummary, + multiplier, + separator, + ignoreFalseConditions + // + ); + + // + // Generating Full Result by Combining parts ... + result = + // + GetTitle() + separator + + "-----------------------------" + separator + + result + + "" + // + ; + + // + return result; + } + + // + string GenerateSummaryBody( + const bool onlySummary = false, // Only Generate Conditions Summary + double multiplier = 1, // Score Multiplier + const string separator = "\n", // Separator + const bool ignoreFalseConditions = true // Ignore False Conditions + ) + { + // + string result = NULL; + + // + double bullScore = 0; + double bearScore = 0; + GenerateScore( + bullScore, + bearScore, + multiplier // + ); + + // + // Common ... + string commonStr = + // + (onlySummary ? "" : "Commons: " + separator) + + (onlySummary ? "" : "-----------------------------" + separator) + + "Time: " + ToString(TimeCurrent()) + separator + + "-----------" + separator + + "Scores: " + separator + + "-----------" + separator + + "Bullish: " + ToString(bullScore) + separator + + "Bearish: " + ToString(bearScore) + separator + + "-----------------------------" + separator + + // + // TODO: Add Scores Later ... + separator + + "" + // + ; + + // + // Candlestick ... + string candlestickStr = + // + ToString("isLastBullish", isLastBullish, ignoreFalseConditions, separator) + + ToString("isLastBearish", isLastBearish, ignoreFalseConditions, separator) + + ToString("isCurrentBullish", isCurrentBullish, ignoreFalseConditions, separator) + + ToString("isCurrentBearish", isCurrentBearish, ignoreFalseConditions, separator) + + ToString("isCurrentMidLineOverLastHigh", isCurrentMidLineOverLastHigh, ignoreFalseConditions, separator) + + ToString("isCurrentMidLineUnderLastLow", isCurrentMidLineUnderLastLow, ignoreFalseConditions, separator) + + ToString("isCurrentMidLineOverLastUp", isCurrentMidLineOverLastUp, ignoreFalseConditions, separator) + + ToString("isCurrentMidLineUnderLastDown", isCurrentMidLineUnderLastDown, ignoreFalseConditions, separator) + + ToString("isCurrentMidLineOverLastMidLine", isCurrentMidLineOverLastMidLine, ignoreFalseConditions, separator) + + ToString("isCurrentMidLineUnderLastMidLine", isCurrentMidLineUnderLastMidLine, ignoreFalseConditions, separator) + + "" + // + ; + candlestickStr = SetLabel(": ", candlestickStr, separator); + + // + // XZG ... + string zgStr = + // + ToString("isZigZagInPeak", isZigZagInPeak, ignoreFalseConditions, separator) + + ToString("isZigZagInVale", isZigZagInVale, ignoreFalseConditions, separator) + + "" + // + ; + zgStr = SetLabel(": ", zgStr, separator); + + // + // XSTR ... + string strStr = + // + ToString("isTrendBullish", isTrendBullish, ignoreFalseConditions, separator) + + ToString("isTrendBearish", isTrendBearish, ignoreFalseConditions, separator) + + ToString("isTrendSwitchedToBullish", isTrendSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isTrendSwitchedToBearish", isTrendSwitchedToBearish, ignoreFalseConditions, separator) + + "" + // + ; + strStr = SetLabel(": ", strStr, separator); + + // + // XCHE ... + string cheStr = + // + ToString("isCHEBullish", isCHEBullish, ignoreFalseConditions, separator) + + ToString("isCHEBearish", isCHEBearish, ignoreFalseConditions, separator) + + ToString("isCHESwitchedToBullish", isCHESwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isCHESwitchedToBearish", isCHESwitchedToBearish, ignoreFalseConditions, separator) + + "" + // + ; + cheStr = SetLabel(": ", cheStr, separator); + + // + // XTD ... + string tdStr = + // + ToString("isTDBullish", isTDBullish, ignoreFalseConditions, separator) + + ToString("isTDBearish", isTDBearish, ignoreFalseConditions, separator) + + ToString("isTDSwitchedToBullish", isTDSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isTDSwitchedToBearish", isTDSwitchedToBearish, ignoreFalseConditions, separator) + + "" + // + ; + tdStr = SetLabel(": ", tdStr, separator); + + // + // XHK ... + string hkStr = + // + ToString("isHKBullish", isHKBullish, ignoreFalseConditions, separator) + + ToString("isHKBearish", isHKBearish, ignoreFalseConditions, separator) + + ToString("isClosedOverHK", isClosedOverHK, ignoreFalseConditions, separator) + + ToString("isClosedUnderHK", isClosedUnderHK, ignoreFalseConditions, separator) + + ToString("isHKSwitchedToBullish", isHKSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isHKSwitchedToBearish", isHKSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isSMHKBullish", isSMHKBullish, ignoreFalseConditions, separator) + + ToString("isSMHKBearish", isSMHKBearish, ignoreFalseConditions, separator) + + ToString("isClosedOverSMHK", isClosedOverSMHK, ignoreFalseConditions, separator) + + ToString("isClosedUnderSMHK", isClosedUnderSMHK, ignoreFalseConditions, separator) + + ToString("isSMHKSwitchedToBullish", isSMHKSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isSMHKSwitchedToBearish", isSMHKSwitchedToBearish, ignoreFalseConditions, separator) + + "" + // + ; + hkStr = SetLabel(": ", hkStr, separator); + + // + // XDON ... + string donStr = + // + ToString("isDONAttachedMaxLower", isDONAttachedMaxLower, ignoreFalseConditions, separator) + + ToString("isDONAttachedMinLower", isDONAttachedMinLower, ignoreFalseConditions, separator) + + ToString("isDONCrossedOverMaxLower", isDONCrossedOverMaxLower, ignoreFalseConditions, separator) + + ToString("isDONCrossedUnderMaxLower", isDONCrossedUnderMaxLower, ignoreFalseConditions, separator) + + ToString("isDONCrossedOverMinLower", isDONCrossedOverMinLower, ignoreFalseConditions, separator) + + ToString("isDONCrossedUnderMinLower", isDONCrossedUnderMinLower, ignoreFalseConditions, separator) + + ToString("isDONAttachedMaxUpper", isDONAttachedMaxUpper, ignoreFalseConditions, separator) + + ToString("isDONAttachedMinUpper", isDONAttachedMinUpper, ignoreFalseConditions, separator) + + ToString("isDONCrossedOverMaxUpper", isDONCrossedOverMaxUpper, ignoreFalseConditions, separator) + + ToString("isDONCrossedUnderMaxUpper", isDONCrossedUnderMaxUpper, ignoreFalseConditions, separator) + + ToString("isDONCrossedOverMinUpper", isDONCrossedOverMinUpper, ignoreFalseConditions, separator) + + ToString("isDONCrossedUnderMinUpper", isDONCrossedUnderMinUpper, ignoreFalseConditions, separator) + + "" + // + ; + donStr = SetLabel(": ", donStr, separator); + + // + // XMC ... + string mcStr = + // + ToString("isMCFastOverSlow", isMCFastOverSlow, ignoreFalseConditions, separator) + + ToString("isMCFastUnderSlow", isMCFastUnderSlow, ignoreFalseConditions, separator) + + ToString("isMCFastOverVerifier", isMCFastOverVerifier, ignoreFalseConditions, separator) + + ToString("isMCFastUnderVerifier", isMCFastUnderVerifier, ignoreFalseConditions, separator) + + ToString("isMCSlowOverVerifier", isMCSlowOverVerifier, ignoreFalseConditions, separator) + + ToString("isMCSlowUnderVerifier", isMCSlowUnderVerifier, ignoreFalseConditions, separator) + + ToString("isMCFastCrossedOverSlow", isMCFastCrossedOverSlow, ignoreFalseConditions, separator) + + ToString("isMCFastCrossedUnderSlow", isMCFastCrossedUnderSlow, ignoreFalseConditions, separator) + + ToString("isMCFastCrossedOverVerifier", isMCFastCrossedOverVerifier, ignoreFalseConditions, separator) + + ToString("isMCFastCrossedUnderVerifier", isMCFastCrossedUnderVerifier, ignoreFalseConditions, separator) + + ToString("isMCSlowCrossedOverVerifier", isMCSlowCrossedOverVerifier, ignoreFalseConditions, separator) + + ToString("isMCSlowCrossedUnderVerifier", isMCSlowCrossedUnderVerifier, ignoreFalseConditions, separator) + + "" + // + ; + mcStr = SetLabel(": ", mcStr, separator); + + // + // XMRB ... + string mrbStr = + // + ToString("isMRBFastOverSlow", isMRBFastOverSlow, ignoreFalseConditions, separator) + + ToString("isMRBFastUnderSlow", isMRBFastUnderSlow, ignoreFalseConditions, separator) + + ToString("isMRBFastCrossedOverSlow", isMRBFastCrossedOverSlow, ignoreFalseConditions, separator) + + ToString("isMRBFastCrossedUnderSlow", isMRBFastCrossedUnderSlow, ignoreFalseConditions, separator) + + ToString("isMRBFastOverVerifier", isMRBFastOverVerifier, ignoreFalseConditions, separator) + + ToString("isMRBFastUnderVerifier", isMRBFastUnderVerifier, ignoreFalseConditions, separator) + + ToString("isMRBFastCrossedtOverVerifier", isMRBFastCrossedtOverVerifier, ignoreFalseConditions, separator) + + ToString("isMRBFastCrossedUnderVerifier", isMRBFastCrossedUnderVerifier, ignoreFalseConditions, separator) + + ToString("isMRBSlowOverVerifier", isMRBSlowOverVerifier, ignoreFalseConditions, separator) + + ToString("isMRBSlowUnderVerifier", isMRBSlowUnderVerifier, ignoreFalseConditions, separator) + + ToString("isMRBSlowCrossedtOverVerifier", isMRBSlowCrossedtOverVerifier, ignoreFalseConditions, separator) + + ToString("isMRBSlowCrossedUnderVerifier", isMRBSlowCrossedUnderVerifier, ignoreFalseConditions, separator) + + "" + // + ; + mrbStr = SetLabel(": ", mrbStr, separator); + + // + // XICH ... + string ichStr = + // + ToString("isClosedOverKijunSen", isClosedOverKijunSen, ignoreFalseConditions, separator) + + ToString("isClosedUnderKijunSen", isClosedUnderKijunSen, ignoreFalseConditions, separator) + + ToString("isTenkanSenOverKijunSen", isTenkanSenOverKijunSen, ignoreFalseConditions, separator) + + ToString("isTenkanSenUnderKijunSen", isTenkanSenUnderKijunSen, ignoreFalseConditions, separator) + + ToString("isTenkanSenCrossedOverKijunSen", isTenkanSenCrossedOverKijunSen, ignoreFalseConditions, separator) + + ToString("isTenkanSenCrossedUnderKijunSen", isTenkanSenCrossedUnderKijunSen, ignoreFalseConditions, separator) + + ToString("isSenkouSpanAOverB", isSenkouSpanAOverB, ignoreFalseConditions, separator) + + ToString("isSenkouSpanAUnderB", isSenkouSpanAUnderB, ignoreFalseConditions, separator) + + ToString("isSenkouSpanAOverLast", isSenkouSpanAOverLast, ignoreFalseConditions, separator) + + ToString("isSenkouSpanAUnderLast", isSenkouSpanAUnderLast, ignoreFalseConditions, separator) + + ToString("isFutureSenkouSpanAOverB", isFutureSenkouSpanAOverB, ignoreFalseConditions, separator) + + ToString("isFutureSenkouSpanAUnderB", isFutureSenkouSpanAUnderB, ignoreFalseConditions, separator) + + ToString("isFutureSenkouSpanAOverLast", isFutureSenkouSpanAOverLast, ignoreFalseConditions, separator) + + ToString("isFutureSenkouSpanAUnderLast", isFutureSenkouSpanAUnderLast, ignoreFalseConditions, separator) + + ToString("isSenkouSpanACrossedOverB", isSenkouSpanACrossedOverB, ignoreFalseConditions, separator) + + ToString("isSenkouSpanACrossedUnderB", isSenkouSpanACrossedUnderB, ignoreFalseConditions, separator) + + ToString("isSenkouSpanACrossedOverLast", isSenkouSpanACrossedOverLast, ignoreFalseConditions, separator) + + ToString("isSenkouSpanACrossedUnderLast", isSenkouSpanACrossedUnderLast, ignoreFalseConditions, separator) + + ToString("isFutureSenkouSpanACrossedOverB", isFutureSenkouSpanACrossedOverB, ignoreFalseConditions, separator) + + ToString("isFutureSenkouSpanACrossedUnderB", isFutureSenkouSpanACrossedUnderB, ignoreFalseConditions, separator) + + ToString("isFutureSenkouSpanACrossedOverLast", isFutureSenkouSpanACrossedOverLast, ignoreFalseConditions, separator) + + ToString("isFutureSenkouSpanACrossedUnderLast", isFutureSenkouSpanACrossedUnderLast, ignoreFalseConditions, separator) + + "" + // + ; + ichStr = SetLabel(": ", ichStr, separator); + + // + // XPV ... + string pvStr = + // + ToString("isNewPeak", isNewPeak, ignoreFalseConditions, separator) + + ToString("isNewPeakOverLast", isNewPeakOverLast, ignoreFalseConditions, separator) + + ToString("isNewPeakUnderLast", isNewPeakUnderLast, ignoreFalseConditions, separator) + + ToString("isNewVale", isNewVale, ignoreFalseConditions, separator) + + ToString("isNewValeOverLast", isNewValeOverLast, ignoreFalseConditions, separator) + + ToString("isNewValeUnderLast", isNewValeUnderLast, ignoreFalseConditions, separator) + + ToString("isFiboIncreased", isFiboIncreased, ignoreFalseConditions, separator) + + ToString("isFiboDecreased", isFiboDecreased, ignoreFalseConditions, separator) + + ToString("isFiboSectionChanged", isFiboSectionChanged, ignoreFalseConditions, separator) + + ToString("isSCBullish", isSCBullish, ignoreFalseConditions, separator) + + ToString("isSCHHBullish", isSCHHBullish, ignoreFalseConditions, separator) + + ToString("isSCLLBullish", isSCLLBullish, ignoreFalseConditions, separator) + + ToString("isSCSwitchedToBullish", isSCSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isSCHHSwitchedToBullish", isSCHHSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isSCLLSwitchedToBullish", isSCLLSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isSCBearish", isSCBearish, ignoreFalseConditions, separator) + + ToString("isSCHHBearish", isSCHHBearish, ignoreFalseConditions, separator) + + ToString("isSCLLBearish", isSCLLBearish, ignoreFalseConditions, separator) + + ToString("isSCSwitchedToBearish", isSCSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isSCHHSwitchedToBearish", isSCHHSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isSCLLSwitchedToBeraish", isSCLLSwitchedToBeraish, ignoreFalseConditions, separator) + + ToString("isMCBullish", isMCBullish, ignoreFalseConditions, separator) + + ToString("isMCHHBullish", isMCHHBullish, ignoreFalseConditions, separator) + + ToString("isMCLLBullish", isMCLLBullish, ignoreFalseConditions, separator) + + ToString("isMCSwitchedToBullish", isMCSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isMCHHSwitchedToBullish", isMCHHSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isMCLLSwitchedToBullish", isMCLLSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isMCBearish", isMCBearish, ignoreFalseConditions, separator) + + ToString("isMCHHBearish", isMCHHBearish, ignoreFalseConditions, separator) + + ToString("isMCLLBearish", isMCLLBearish, ignoreFalseConditions, separator) + + ToString("isMCSwitchedToBearish", isMCSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isMCHHSwitchedToBearish", isMCHHSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isMCLLSwitchedToBeraish", isMCLLSwitchedToBeraish, ignoreFalseConditions, separator) + + ToString("isLCBullish", isLCBullish, ignoreFalseConditions, separator) + + ToString("isLCHHBullish", isLCHHBullish, ignoreFalseConditions, separator) + + ToString("isLCLLBullish", isLCLLBullish, ignoreFalseConditions, separator) + + ToString("isLCSwitchedToBullish", isLCSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isLCHHSwitchedToBullish", isLCHHSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isLCLLSwitchedToBullish", isLCLLSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isLCBearish", isLCBearish, ignoreFalseConditions, separator) + + ToString("isLCHHBearish", isLCHHBearish, ignoreFalseConditions, separator) + + ToString("isLCLLBearish", isLCLLBearish, ignoreFalseConditions, separator) + + ToString("isLCSwitchedToBearish", isLCSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isLCHHSwitchedToBearish", isLCHHSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isLCLLSwitchedToBeraish", isLCLLSwitchedToBeraish, ignoreFalseConditions, separator) + + ToString("isHCBullish", isHCBullish, ignoreFalseConditions, separator) + + ToString("isHCHHBullish", isHCHHBullish, ignoreFalseConditions, separator) + + ToString("isHCLLBullish", isHCLLBullish, ignoreFalseConditions, separator) + + ToString("isHCSwitchedToBullish", isHCSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isHCHHSwitchedToBullish", isHCHHSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isHCLLSwitchedToBullish", isHCLLSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isHCBearish", isHCBearish, ignoreFalseConditions, separator) + + ToString("isHCHHBearish", isHCHHBearish, ignoreFalseConditions, separator) + + ToString("isHCLLBearish", isHCLLBearish, ignoreFalseConditions, separator) + + ToString("isHCSwitchedToBearish", isHCSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isHCHHSwitchedToBearish", isHCHHSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isHCLLSwitchedToBeraish", isHCLLSwitchedToBeraish, ignoreFalseConditions, separator) + + "" + // + ; + pvStr = SetLabel(": ", pvStr, separator); + + // + result = + onlySummary + ? commonStr + : (commonStr + + candlestickStr + + zgStr + + strStr + + cheStr + + tdStr + + hkStr + + donStr + + mcStr + + mrbStr + + ichStr + + pvStr + + "" // + ); + + // + return result; + } + + // + string GetTitle() + { + // + string result = NULL; + + // + result = + // + "[" + ToString(cycle) + "]: " + ToString(period) + // + ; + + // + return result; + } +}; + +// +// Signaller Class Base Implementation ... +class XSignallerDescriptor : public XSCBase +{ + // + // Public ... +public: + // + // Props ... + + // + ENUM_XSIGNAL_PROVIDERS name; + + // + bool enableLong; + bool enableShort; + + // + double r2r; + + // + double staticVolumeLong; + double staticVolumeShort; + + // + // Constructor ... + void XSignallerDescriptor() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + name = PROVIDER_NONE; + + // + enableLong = false; + enableShort = false; + + // + r2r = 0; + + // + staticVolumeLong = 0; + staticVolumeShort = 0; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + name != PROVIDER_NONE && + r2r > 0 && + (enableLong + ? staticVolumeLong > 0 + : true) && + (enableShort + ? staticVolumeShort > 0 + : true) + // + ; + + // + return result; + } + + // + string GetName() + { + return ToString(name); + } + + // + // Generate Signal ... + bool GenerateSignal( + XSignal &signal, // Result + string mSymbol, // Trading Symbol + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + ENUM_POSITION_TYPE mType, // Long (Buy) or Short (Sell) + ENUM_X_ORDER_MODES mMode, // Execution Mode + double mEntry, // Entry Price + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + bool result = false; + + // + signal.Clean(); + + // + // Validate Model ... + result = IsValid(); + if (!result) + { + return result; + } + + // + bool isLong = IsLong(mType); + + // + // Validate Signal Type ... + result = isLong + ? enableLong && staticVolumeLong > 0 + : enableShort && staticVolumeShort > 0; + if (!result) + { + return result; + } + + // + double mVolume = isLong + ? staticVolumeLong + : staticVolumeShort; + + // + result = signal.Prepare( + mSymbol, + GetName(), + mPeriod, + mType, + mMode, + mEntry, + mVolume, + mSL, + mTP // + ); + + // + return result; + } + + // + // Generate Market Signal ... + bool GenerateMarketSignal( + XSignal &signal, // Result + string mSymbol, // Trading Symbol + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + ENUM_POSITION_TYPE mType, // Long (Buy) or Short (Sell) + double mEntry, // Entry Price + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + bool result = false; + + // + signal.Clean(); + + // + // Validate Model ... + result = IsValid(); + if (!result) + { + return result; + } + + // + bool isLong = IsLong(mType); + + // + // Validate Signal Type ... + result = isLong + ? enableLong && staticVolumeLong > 0 + : enableShort && staticVolumeShort > 0; + if (!result) + { + return result; + } + + // + double mVolume = isLong + ? staticVolumeLong + : staticVolumeShort; + + // + result = signal.Prepare( + mSymbol, + GetName(), + mPeriod, + mType, + X_ORDER_MODE_MARKET, + mEntry, + mVolume, + mSL, + mTP // + ); + + // + return result; + } + + // + // Check Has Conditions opr Not ... + bool HasConditions( + const X121MCycleConditions &conditions, // Market Conditions + bool &hasLong, // Hold Long Conditions Result + bool &hasShort, // Hold Short Conditions Result + double &sl, // Hold SL ... + double &tp // Hold TP ... + ) + { + // + bool result = false; + + // + hasLong = HasLongConditions(conditions, sl, tp); + hasShort = HasShortConditions(conditions, sl, tp); + + // + result = hasLong || hasShort; + + // + return result; + } + + // + // Check Has Long Conditions opr Not ... + virtual bool HasLongConditions( + const X121MCycleConditions &conditions, // Market Conditions + double &sl, // Hold SL ... + double &tp // Hold TP ... + ) + { + return false; + } + + // + // Check Has Short Conditions opr Not ... + virtual bool HasShortConditions( + const X121MCycleConditions &conditions, // Market Conditions + double &sl, // Hold SL ... + double &tp // Hold TP ... + ) + { + return false; + } +}; + +// +// Market Class ... +class XSCX121Market : XSCBaseAlert +{ + // + // Public ... +public: + // + // Props ... + XSCXHKHelper hk; + XSCXMCHelper mc; + XSCXPVHelper pv; + XSCXZGHelper zg; + XSCXTDHelper td; + XSCXMRBHelper mrb; + XSCXSTRHelper str; + XSCXCHEHelper che; + XSCXOSCHelper osc; + XSCXICHHelper ich; + XSCXDONHelper don; + + // + // Properties ... + + // + // Retrieve Trading Symbol ... + string GetSymbol() + { + return mInputs.cycle.symbol; + } + + // + // Retrieve Cycle Time Frame ... + ENUM_TIMEFRAMES GetPeriod() + { + return mInputs.cycle.period; + } + + // + // Retrieve Market Host Time Frame ... + ENUM_TIMEFRAMES GetHostPeriod() + { + return mInputs.cycle.hostPeriod; + } + + // + // Count Total Available Bars in Market ... + int CountBars() + { + // + Update(0); + return mInputs.cycle.CountBars(); + } + + // + // Check Market is in new Bar ... + int IsNewBar() + { + // + Update(0); + return mInputs.cycle.IsNewBar(); + } + + // + // Retrieve Current Cycles Specific Bar ... + XOHCL GetBar(int barIndex) + { + // + Update(0); + return mInputs.cycle.GetBar(barIndex); + } + + // + // Retrieve Current Bar Index based on Host Period bar Index ... + int GetBarIndex(int barIndex) + { + // + Update(barIndex); + return mInputs.cycle.GetBarIndex(barIndex); + } + + // + // Retrieve Bar Time ... + datetime GetBarTime(int barIndex) + { + // + Update(0); + return mInputs.cycle.GetBarTime(barIndex); + } + + // + // Retrieve Current Market Config ... + bool GetInputs(X121MCycleInputs &inputs) + { + // + bool result = false; + + // + inputs = mInputs; + + // + result = inputs.IsValid(); + + // + return result; + } + + // + // Set Market Inputs and Re Initial ... + bool SetInputs( + X121MCycleInputs &inputs // Config + ) + { + // + return Init(inputs); + } + + // + bool AddSignaller( + XSignallerDescriptor &signaller // + ) + { + // + bool result = false; + + // + // Validate Signaller ... + result = signaller.IsValid(); + if (!result) + { + return result; + } + + // + AddRef( + signaller, + mSignallers // + ); + + // + return result; + } + + // + int AddSignallers( + XSignallerDescriptor &signallers[] // + ) + { + // + int result = 0; + + // + int count = ArraySize(signallers); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + bool isAdded = AddSignaller(signallers[i]); + if (isAdded) + { + result++; + } + } + + // + return result; + } + + // + // Tools ... + + // + void GetMarketConditions( + X121MCycleConditions &conditions, // Market Conditions Result + int barIndex = 0, // Specified Bar Index + int mNumberOfItems = 15 // Number of Reading Items + ) + { + // + conditions.Clear(); + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (barIndex >= CountBars()) + { + barIndex = CountBars() + 2; + } + + // + if (mNumberOfItems <= 0) + { + mNumberOfItems = 2; + } + + // + // Set Commons ... + conditions.time = GetBarTime(barIndex); + conditions.cycle = mInputs.cycle.cycle; + conditions.prefix = mInputs.cycle.prefix; + conditions.symbol = mInputs.cycle.symbol; + conditions.period = mInputs.cycle.period; + conditions.hostPeriod = mInputs.cycle.hostPeriod; + + // + Clean(conditions.bars); + GetBars( + conditions.bars, + conditions.symbol, + conditions.period, + barIndex, + mNumberOfItems + // + ); + + // + int zIndex = barIndex; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + int start = zIndex; + int count = mNumberOfItems; + + // + // Filling Buffers ... + + // + // XHK ... + + // + hk.CopyAsOHCL( + start, + count, + conditions.hkBars // + ); + + // + hk.CopySMAsOHCL( + start, + count, + conditions.smHKBars // + ); + + // + // XICH ... + + // + ich.CopyTenkanSen( + start, + count, + conditions.ichTenkanSens // + ); + + // + ich.CopyKijunSen( + start, + count, + conditions.ichKijunSens // + ); + + // + ich.CopyChikouSpan( + start, + count, + conditions.ichChikouSpans // + ); + + // + ich.CopySenkouSpanA( + start, + count, + conditions.ichSenkouSpanAs // + ); + + // + ich.CopySenkouSpanB( + start, + count, + conditions.ichSenkouSpanBs // + ); + + // + ich.CopyFutureSenkouSpanA( + start, + count, + conditions.ichFutureSenkouSpanAs // + ); + + // + ich.CopyFutureSenkouSpanB( + start, + count, + conditions.ichFutureSenkouSpanBs // + ); + + // + // XMC ... + + // + mc.CopyFast( + start, + count, + conditions.mcFasts // + ); + + // + mc.CopySlow( + start, + count, + conditions.mcSlows // + ); + + // + mc.CopyVerifier( + start, + count, + conditions.mcVerifiers // + ); + + // + // XSTR ... + + // + str.CopyTrend( + start, + count, + conditions.strTrends // + ); + + // + str.CopyState( + start, + count, + conditions.strStates // + ); + + // + // XZG ... + + // + zg.CopyMain( + start, + count, + conditions.zigzags // + ); + + // + zg.CopyPeaksAndVales( + start, + count, + conditions.zigzagPVs // + ); + + // + // XMRB ... + + // + mrb.CopyFast( + start, + count, + conditions.mrbFasts // + ); + + // + mrb.CopySlow( + start, + count, + conditions.mrbSlows // + ); + + // + // Ribbon 1 ... + + // + mrb.CopyR1Fast( + start, + count, + conditions.mrb1Fasts // + ); + + // + mrb.CopyR1Slow( + start, + count, + conditions.mrb1Slows // + ); + + // + // Ribbon 2 ... + + // + mrb.CopyR2Fast( + start, + count, + conditions.mrb2Fasts // + ); + + // + mrb.CopyR2Slow( + start, + count, + conditions.mrb2Slows // + ); + + // + // Ribbon 3 ... + + // + mrb.CopyR3Fast( + start, + count, + conditions.mrb3Fasts // + ); + + // + mrb.CopyR3Slow( + start, + count, + conditions.mrb3Slows // + ); + + // + // Ribbon 4 ... + + // + mrb.CopyR4Fast( + start, + count, + conditions.mrb4Fasts // + ); + + // + mrb.CopyR4Slow( + start, + count, + conditions.mrb4Slows // + ); + + // + // Ribbon 5 ... + + // + mrb.CopyR5Fast( + start, + count, + conditions.mrb5Fasts // + ); + + // + mrb.CopyR5Slow( + start, + count, + conditions.mrb5Slows // + ); + + // + // Ribbon 6 ... + + // + mrb.CopyR6Fast( + start, + count, + conditions.mrb6Fasts // + ); + + // + mrb.CopyR6Slow( + start, + count, + conditions.mrb6Slows // + ); + + // + // XCHE ... + + // + che.CopyLongExit1( + start, + count, + conditions.cheLongExit1s // + ); + + // + che.CopyLongExit2( + start, + count, + conditions.cheLongExit2s // + ); + + // + che.CopyShortExit1( + start, + count, + conditions.cheShortExit1s // + ); + + // + che.CopyShortExit2( + start, + count, + conditions.cheShortExit2s // + ); + + // + // XTD ... + + // + td.CopyBullish( + start, + count, + conditions.tdBullishs // + ); + + // + td.CopyBearish( + start, + count, + conditions.tdBearishs // + ); + + // + td.CopySignal( + start, + count, + conditions.tdSignals // + ); + + // + // XDON ... + + // + don.CopyUpperO( + start, + count, + conditions.donUpperOs // + ); + + // + don.CopyLowerO( + start, + count, + conditions.donLowerOs // + ); + + // + don.CopyUpperC( + start, + count, + conditions.donUpperCs // + ); + + // + don.CopyLowerC( + start, + count, + conditions.donLowerCs // + ); + + // + don.CopyUpperH( + start, + count, + conditions.donUpperHs // + ); + + // + don.CopyLowerH( + start, + count, + conditions.donLowerHs // + ); + + // + don.CopyUpperL( + start, + count, + conditions.donUpperLs // + ); + + // + don.CopyLowerL( + start, + count, + conditions.donLowerLs // + ); + + // + // XPV ... + + // + pv.CopyPeak( + start, + count, + conditions.pvPeaks // + ); + + // + pv.CopyVale( + start, + count, + conditions.pvVales // + ); + + // + pv.CopyResistance( + start, + count, + conditions.pvResistances // + ); + + // + pv.CopySupport( + start, + count, + conditions.pvSupports // + ); + + // + pv.CopyFib1( + start, + count, + conditions.pvFib1s // + ); + + // + pv.CopyFib2( + start, + count, + conditions.pvFib2s // + ); + + // + pv.CopyFib3( + start, + count, + conditions.pvFib3s // + ); + + // + pv.CopyFib4( + start, + count, + conditions.pvFib4s // + ); + + // + pv.CopyFib5( + start, + count, + conditions.pvFib5s // + ); + + // + pv.CopySCHH( + start, + count, + conditions.pvSCHHs // + ); + + // + pv.CopySCLL( + start, + count, + conditions.pvSCLLs // + ); + + // + pv.CopyMCHH( + start, + count, + conditions.pvMCHHs // + ); + + // + pv.CopyMCLL( + start, + count, + conditions.pvMCLLs // + ); + + // + pv.CopyLCHH( + start, + count, + conditions.pvLCHHs // + ); + + // + pv.CopyLCLL( + start, + count, + conditions.pvLCLLs // + ); + + // + pv.CopyHCHH( + start, + count, + conditions.pvHCHHs // + ); + + // + pv.CopyHCLL( + start, + count, + conditions.pvHCLLs // + ); + + // + // XOSC ... + + // + // ATR ... + osc.CopyATR( + start, + count, + conditions.oscAtrs // + ); + + // + // VOLUE ... + osc.CopyVolume( + start, + count, + conditions.oscVolumes // + ); + + // + // MOMENTUM ... + osc.CopyMomentum( + start, + count, + conditions.oscMomentums // + ); + + // + // SAR ... + osc.CopySAR( + start, + count, + conditions.oscSars // + ); + + // + // RSI ... + osc.CopyRSI( + start, + count, + conditions.oscRsis // + ); + + // + // CCI ... + osc.CopyCCI( + start, + count, + conditions.oscCcis // + ); + + // + // STDDEV ... + osc.CopySTDDEV( + start, + count, + conditions.oscStddevs // + ); + + // + // BULLPOWER ... + osc.CopyBullPower( + start, + count, + conditions.oscBullPs // + ); + + // + // BEARPOWER ... + osc.CopyBearPower( + start, + count, + conditions.oscBearPs // + ); + + // + // RVI ... + + // + osc.CopyRVI( + start, + count, + conditions.oscRviMains // + ); + + // + osc.CopyRVISignal( + start, + count, + conditions.oscRviSignals // + ); + + // + // MACD ... + + // + osc.CopyMACD( + start, + count, + conditions.oscMacdMains // + ); + + // + osc.CopyMACDSignal( + start, + count, + conditions.oscMacdSignals // + ); + + // + // STOCH ... + + // + osc.CopySTOCH( + start, + count, + conditions.oscStochMains // + ); + + // + osc.CopySTOCHSignal( + start, + count, + conditions.oscStochSignals // + ); + + // + // Now we Have all Buffers ... + // Going to Extract Market Conditions Variables ... + + // + XOHCL zBar = conditions.bars[zIndex]; + XOHCL cBar = conditions.bars[cIndex]; + XOHCL pBar = conditions.bars[pIndex]; + + // + // Candlestic ... + // + bool isLastBullish = + // + cBar.IsBullish() + // + ; + + // + bool isLastBearish = + // + cBar.IsBearish() + // + ; + + // + bool isCurrentBullish = + // + zBar.IsBullish() + // + ; + + // + bool isCurrentBearish = + // + zBar.IsBearish() + // + ; + + // + bool isCurrentMidLineOverLastHigh = + // + zBar.GetMid() > cBar.high; + // + ; + + // + bool isCurrentMidLineUnderLastLow = + // + zBar.GetMid() < cBar.low + // + ; + + // + bool isCurrentMidLineOverLastUp = + // + zBar.GetMid() > cBar.GetUp() + // + ; + + // + bool isCurrentMidLineUnderLastDown = + // + zBar.GetMid() < cBar.GetDown() + // + ; + + // + bool isCurrentMidLineOverLastMidLine = + // + zBar.GetMid() > cBar.GetMid() + // + ; + + // + bool isCurrentMidLineUnderLastMidLine = + // + zBar.GetMid() < cBar.GetMid() + // + ; + + // + // XHK ... + + // + XOHCL zHKBar = conditions.hkBars[zIndex]; + XOHCL cHKBar = conditions.hkBars[cIndex]; + XOHCL pHKBar = conditions.hkBars[pIndex]; + + // + bool isHKBullish = cHKBar.IsBullish(); + bool isHKBearish = cHKBar.IsBearish(); + bool isClosedOverHK = cBar.close > cHKBar.high; + bool isClosedUnderHK = cBar.close < cHKBar.low; + bool isHKSwitchedToBullish = cHKBar.IsBullish() && !pHKBar.IsBullish(); + bool isHKSwitchedToBearish = cHKBar.IsBearish() && !pHKBar.IsBearish(); + + // + XOHCL zSMHKBar = conditions.smHKBars[zIndex]; + XOHCL cSMHKBar = conditions.smHKBars[cIndex]; + XOHCL pSMHKBar = conditions.smHKBars[pIndex]; + + // + bool isSMHKBullish = cSMHKBar.IsBullish(); + bool isSMHKBearish = cSMHKBar.IsBearish(); + bool isClosedOverSMHK = cBar.close > cSMHKBar.high; + bool isClosedUnderSMHK = cBar.close < cSMHKBar.low; + bool isSMHKSwitchedToBullish = cSMHKBar.IsBullish() && !pSMHKBar.IsBullish(); + bool isSMHKSwitchedToBearish = cSMHKBar.IsBearish() && !pSMHKBar.IsBearish(); + + // + // XICH ... + + // + bool isClosedOverKijunSen = cBar.close > conditions.ichKijunSens[cIndex]; + bool isClosedUnderKijunSen = cBar.close < conditions.ichKijunSens[cIndex]; + bool isTenkanSenOverKijunSen = conditions.ichTenkanSens[cIndex] > conditions.ichKijunSens[cIndex]; + bool isTenkanSenUnderKijunSen = conditions.ichTenkanSens[cIndex] < conditions.ichKijunSens[cIndex]; + + // + bool isTenkanSenOverKijunSenPrev = conditions.ichTenkanSens[pIndex] > conditions.ichKijunSens[pIndex]; + bool isTenkanSenUnderKijunSenPrev = conditions.ichTenkanSens[pIndex] < conditions.ichKijunSens[pIndex]; + + // + bool isTenkanSenCrossedOverKijunSen = isTenkanSenOverKijunSen && + !isTenkanSenOverKijunSenPrev; + bool isTenkanSenCrossedUnderKijunSen = isTenkanSenUnderKijunSen && + !isTenkanSenUnderKijunSenPrev; + + // + bool isSenkouSpanAOverB = conditions.ichSenkouSpanAs[cIndex] > conditions.ichSenkouSpanBs[cIndex]; + bool isSenkouSpanAUnderB = conditions.ichSenkouSpanAs[cIndex] < conditions.ichSenkouSpanBs[cIndex]; + + // + bool isSenkouSpanAOverBPrev = conditions.ichSenkouSpanAs[pIndex] > conditions.ichSenkouSpanBs[pIndex]; + bool isSenkouSpanAUnderBPrev = conditions.ichSenkouSpanAs[pIndex] < conditions.ichSenkouSpanBs[pIndex]; + + // + bool isSenkouSpanAOverLast = conditions.ichSenkouSpanAs[cIndex] > conditions.ichSenkouSpanAs[pIndex]; + bool isSenkouSpanAUnderLast = conditions.ichSenkouSpanAs[cIndex] < conditions.ichSenkouSpanAs[pIndex]; + + // + bool isSenkouSpanAOverLastPrev = conditions.ichSenkouSpanAs[pIndex] > conditions.ichSenkouSpanAs[ppIndex]; + bool isSenkouSpanAUnderLastPrev = conditions.ichSenkouSpanAs[pIndex] < conditions.ichSenkouSpanAs[ppIndex]; + + // + bool isFutureSenkouSpanAOverB = conditions.ichFutureSenkouSpanAs[cIndex] > conditions.ichFutureSenkouSpanBs[cIndex]; + bool isFutureSenkouSpanAUnderB = conditions.ichFutureSenkouSpanAs[cIndex] < conditions.ichFutureSenkouSpanBs[cIndex]; + + // + bool isFutureSenkouSpanAOverBPrev = conditions.ichFutureSenkouSpanAs[pIndex] > conditions.ichFutureSenkouSpanBs[pIndex]; + bool isFutureSenkouSpanAUnderBPrev = conditions.ichFutureSenkouSpanAs[pIndex] < conditions.ichFutureSenkouSpanBs[pIndex]; + + // + bool isFutureSenkouSpanAOverLast = conditions.ichFutureSenkouSpanAs[cIndex] > conditions.ichFutureSenkouSpanAs[pIndex]; + bool isFutureSenkouSpanAUnderLast = conditions.ichFutureSenkouSpanAs[cIndex] < conditions.ichFutureSenkouSpanAs[pIndex]; + + // + bool isFutureSenkouSpanAOverLastPrev = conditions.ichFutureSenkouSpanAs[pIndex] > conditions.ichFutureSenkouSpanAs[ppIndex]; + bool isFutureSenkouSpanAUnderLastPrev = conditions.ichFutureSenkouSpanAs[pIndex] < conditions.ichFutureSenkouSpanAs[ppIndex]; + + // + bool isSenkouSpanACrossedOverB = isSenkouSpanAOverB && + !isSenkouSpanAOverBPrev; + bool isSenkouSpanACrossedUnderB = isSenkouSpanAUnderB && + !isSenkouSpanAUnderBPrev; + bool isSenkouSpanACrossedOverLast = isSenkouSpanAOverLast && + !isSenkouSpanAOverLastPrev; + bool isSenkouSpanACrossedUnderLast = isSenkouSpanAUnderLast && + !isSenkouSpanAUnderLastPrev; + bool isFutureSenkouSpanACrossedOverB = isFutureSenkouSpanAOverB && + !isFutureSenkouSpanAOverBPrev; + bool isFutureSenkouSpanACrossedUnderB = isFutureSenkouSpanAUnderB && + !isFutureSenkouSpanAUnderBPrev; + bool isFutureSenkouSpanACrossedOverLast = isFutureSenkouSpanAOverLast && + !isFutureSenkouSpanAOverLastPrev; + bool isFutureSenkouSpanACrossedUnderLast = isFutureSenkouSpanAUnderLast && + !isFutureSenkouSpanAUnderLastPrev; + + // + // XMC ... + + // + bool isMCFastOverSlow = conditions.mcFasts[cIndex] > conditions.mcSlows[cIndex]; + bool isMCFastUnderSlow = conditions.mcFasts[cIndex] < conditions.mcSlows[cIndex]; + + // + bool isMCFastOverSlowPrev = conditions.mcFasts[pIndex] > conditions.mcSlows[pIndex]; + bool isMCFastUnderSlowPrev = conditions.mcFasts[pIndex] < conditions.mcSlows[pIndex]; + + // + bool isMCFastOverVerifier = conditions.mcFasts[cIndex] > conditions.mcVerifiers[cIndex]; + bool isMCFastUnderVerifier = conditions.mcFasts[cIndex] < conditions.mcVerifiers[cIndex]; + + // + bool isMCFastOverVerifierPrev = conditions.mcFasts[pIndex] > conditions.mcVerifiers[pIndex]; + bool isMCFastUnderVerifierPrev = conditions.mcFasts[pIndex] < conditions.mcVerifiers[pIndex]; + + // + bool isMCSlowOverVerifier = conditions.mcSlows[cIndex] > conditions.mcVerifiers[cIndex]; + bool isMCSlowUnderVerifier = conditions.mcSlows[cIndex] < conditions.mcVerifiers[cIndex]; + + // + bool isMCSlowOverVerifierPrev = conditions.mcSlows[pIndex] > conditions.mcVerifiers[pIndex]; + bool isMCSlowUnderVerifierPrev = conditions.mcSlows[pIndex] < conditions.mcVerifiers[pIndex]; + + // + bool isMCFastCrossedOverSlow = isMCFastOverSlow && + !isMCFastOverSlowPrev; + bool isMCFastCrossedUnderSlow = isMCFastUnderSlow && + !isMCFastUnderSlowPrev; + bool isMCFastCrossedOverVerifier = isMCFastOverVerifier && + !isMCFastOverVerifierPrev; + bool isMCFastCrossedUnderVerifier = isMCFastUnderVerifier && + !isMCFastUnderVerifierPrev; + bool isMCSlowCrossedOverVerifier = isMCSlowOverVerifier && + !isMCSlowOverVerifierPrev; + bool isMCSlowCrossedUnderVerifier = isMCSlowUnderVerifier && + !isMCSlowUnderVerifierPrev; + + // + // XSTR ... + + // + bool isTrendBullish = str.IsBullish(conditions.strStates[cIndex]); + bool isTrendBearish = str.IsBearish(conditions.strStates[cIndex]); + bool isTrendSwitchedToBullish = str.IsBullish(conditions.strStates[cIndex]) && + !str.IsBullish(conditions.strStates[pIndex]); + bool isTrendSwitchedToBearish = str.IsBearish(conditions.strStates[cIndex]) && + !str.IsBearish(conditions.strStates[pIndex]); + + // + // XZG ... + + // + bool isZigZagInPeak = conditions.zigzags[cIndex] < conditions.zigzagPVs[cIndex]; + bool isZigZagInVale = conditions.zigzags[cIndex] > conditions.zigzagPVs[cIndex]; + + // + // XMRB ... + + // + bool isMRBFastOverSlow = conditions.mrbFasts[cIndex] > conditions.mrbSlows[cIndex]; + bool isMRBFastUnderSlow = conditions.mrbFasts[cIndex] < conditions.mrbSlows[cIndex]; + + // + bool isMRBFastOverSlowPrev = conditions.mrbFasts[pIndex] > conditions.mrbSlows[pIndex]; + bool isMRBFastUnderSlowPrev = conditions.mrbFasts[pIndex] < conditions.mrbSlows[pIndex]; + + // + bool isMRBFastCrossedOverSlow = isMRBFastOverSlow && + !isMRBFastOverSlowPrev; + bool isMRBFastCrossedUnderSlow = isMRBFastUnderSlow && + !isMRBFastUnderSlowPrev; + + // + bool isMRBFastOverVerifier = conditions.mrbFasts[cIndex] > conditions.mcVerifiers[cIndex]; + bool isMRBFastUnderVerifier = conditions.mrbFasts[cIndex] < conditions.mcVerifiers[cIndex]; + + // + bool isMRBFastOverVerifierPrev = conditions.mrbFasts[pIndex] > conditions.mcVerifiers[pIndex]; + bool isMRBFastUnderVerifierPrev = conditions.mrbFasts[pIndex] < conditions.mcVerifiers[pIndex]; + + // + bool isMRBFastCrossedtOverVerifier = isMRBFastOverVerifier && + !isMRBFastOverVerifierPrev; + bool isMRBFastCrossedUnderVerifier = isMRBFastUnderVerifier && + !isMRBFastUnderVerifierPrev; + + // + bool isMRBSlowOverVerifier = conditions.mrbSlows[cIndex] > conditions.mcVerifiers[cIndex]; + bool isMRBSlowUnderVerifier = conditions.mrbSlows[cIndex] < conditions.mcVerifiers[cIndex]; + + // + bool isMRBSlowOverVerifierPrev = conditions.mrbSlows[pIndex] > conditions.mcVerifiers[pIndex]; + bool isMRBSlowUnderVerifierPrev = conditions.mrbSlows[pIndex] < conditions.mcVerifiers[pIndex]; + + // + bool isMRBSlowCrossedtOverVerifier = isMRBSlowOverVerifier && + !isMRBSlowOverVerifierPrev; + bool isMRBSlowCrossedUnderVerifier = isMRBSlowUnderVerifier && + !isMRBSlowUnderVerifierPrev; + + // + // XCHE ... + + // + bool isCHEBullish = NotEmpty(conditions.cheLongExit1s[cIndex]) && + NotEmpty(conditions.cheLongExit2s[cIndex]); + bool isCHEBearish = NotEmpty(conditions.cheShortExit1s[cIndex]) && + NotEmpty(conditions.cheShortExit2s[cIndex]); + + // + bool isCHEBullishPrev = NotEmpty(conditions.cheLongExit1s[pIndex]) && + NotEmpty(conditions.cheLongExit2s[pIndex]); + bool isCHEBearishPrev = NotEmpty(conditions.cheShortExit1s[pIndex]) && + NotEmpty(conditions.cheShortExit2s[pIndex]); + + // + bool isCHESwitchedToBullish = isCHEBullish && + !isCHEBullishPrev; + bool isCHESwitchedToBearish = isCHEBearish && + !isCHEBearishPrev; + + // + // XTD ... + + // + bool isTDBullish = conditions.tdBullishs[cIndex] > conditions.tdBearishs[cIndex]; + bool isTDBearish = conditions.tdBearishs[cIndex] > conditions.tdBullishs[cIndex]; + + // + bool isTDBullishPrev = conditions.tdBullishs[pIndex] > conditions.tdBearishs[pIndex]; + bool isTDBearishPrev = conditions.tdBearishs[pIndex] > conditions.tdBullishs[pIndex]; + + // + bool isTDSwitchedToBullish = isTDBullish && + !isTDBullishPrev; + bool isTDSwitchedToBearish = isTDBearish && + !isTDBearishPrev; + + // + // XDON ... + + // + double cDonMaxUpper = don.GetMaxUpper(cIndex); + double pDonMaxUpper = don.GetMaxUpper(pIndex); + + // + double cDonMinUpper = don.GetMinUpper(cIndex); + double pDonMinUpper = don.GetMinUpper(pIndex); + + // + double cDonMaxLower = don.GetMaxLower(cIndex); + double pDonMaxLower = don.GetMaxLower(pIndex); + + // + double cDonMinLower = don.GetMinLower(cIndex); + double pDonMinLower = don.GetMinLower(pIndex); + + // + bool isDONAttachedMaxLower = cBar.low <= cDonMaxLower; + bool isDONAttachedMinLower = cBar.low <= cDonMinLower; + + // + bool isDONAttachedMaxLowerPrev = pBar.low <= pDonMaxLower; + bool isDONAttachedMinLowerPrev = pBar.low <= pDonMinLower; + + // + bool isDONCrossedOverMaxLower = !isDONAttachedMaxLower && + isDONAttachedMaxLowerPrev; + bool isDONCrossedUnderMaxLower = isDONAttachedMaxLower && + !isDONAttachedMaxLowerPrev; + + // + bool isDONCrossedOverMinLower = !isDONAttachedMinLower && + isDONAttachedMinLowerPrev; + bool isDONCrossedUnderMinLower = isDONAttachedMinLower && + !isDONAttachedMinLowerPrev; + + // + bool isDONAttachedMaxUpper = cBar.high >= cDonMaxUpper; + bool isDONAttachedMinUpper = cBar.high >= cDonMinUpper; + + // + bool isDONAttachedMaxUpperPrev = pBar.high >= pDonMaxUpper; + bool isDONAttachedMinUpperPrev = pBar.high >= pDonMinUpper; + + // + bool isDONCrossedOverMaxUpper = isDONAttachedMaxUpper && + !isDONAttachedMaxUpperPrev; + bool isDONCrossedUnderMaxUpper = !isDONAttachedMaxUpper && + isDONAttachedMaxUpperPrev; + + // + bool isDONCrossedOverMinUpper = isDONAttachedMinUpper && + !isDONAttachedMinUpperPrev; + bool isDONCrossedUnderMinUpper = !isDONAttachedMinUpper && + isDONAttachedMinUpperPrev; + + // + // XPV ... + + // + bool isNewPeak = conditions.pvPeaks[cIndex] != conditions.pvPeaks[pIndex]; + bool isNewPeakOverLast = isNewPeak && + conditions.pvPeaks[cIndex] > conditions.pvPeaks[pIndex]; + bool isNewPeakUnderLast = isNewPeak && + conditions.pvPeaks[cIndex] < conditions.pvPeaks[pIndex]; + + // + bool isNewVale = conditions.pvVales[cIndex] != conditions.pvVales[pIndex]; + bool isNewValeOverLast = isNewVale && + conditions.pvVales[cIndex] > conditions.pvVales[pIndex]; + bool isNewValeUnderLast = isNewVale && + conditions.pvVales[cIndex] < conditions.pvVales[pIndex]; + + // + bool isFiboIncreased = + // + conditions.pvFib1s[cIndex] > conditions.pvFib1s[pIndex] && + conditions.pvFib2s[cIndex] > conditions.pvFib2s[pIndex] && + conditions.pvFib3s[cIndex] > conditions.pvFib3s[pIndex] && + conditions.pvFib4s[cIndex] > conditions.pvFib4s[pIndex] && + conditions.pvFib5s[cIndex] > conditions.pvFib5s[pIndex] + // + ; + bool isFiboDecreased = + // + conditions.pvFib1s[cIndex] < conditions.pvFib1s[pIndex] && + conditions.pvFib2s[cIndex] < conditions.pvFib2s[pIndex] && + conditions.pvFib3s[cIndex] < conditions.pvFib3s[pIndex] && + conditions.pvFib4s[cIndex] < conditions.pvFib4s[pIndex] && + conditions.pvFib5s[cIndex] < conditions.pvFib5s[pIndex] + // + ; + + bool isFiboSectionChanged = + // + (isFiboDecreased && + isNewPeakUnderLast) + // + || + // + (isFiboIncreased && + isNewValeOverLast) + // + ; + + // + // SC ... + + // + bool isSCHHBullish = conditions.pvSCHHs[cIndex] > conditions.pvSCHHs[pIndex]; + bool isSCLLBullish = conditions.pvSCLLs[cIndex] > conditions.pvSCLLs[pIndex]; + + // + bool isSCHHBullishPrev = conditions.pvSCHHs[pIndex] > conditions.pvSCHHs[ppIndex]; + bool isSCLLBullishPrev = conditions.pvSCLLs[pIndex] > conditions.pvSCLLs[ppIndex]; + + // + bool isSCBullish = isSCHHBullish && + isSCLLBullish; + + // + bool isSCBullishPrev = isSCHHBullishPrev && + isSCLLBullishPrev; + + // + bool isSCHHSwitchedToBullish = isSCHHBullish && + !isSCHHBullishPrev; + bool isSCLLSwitchedToBullish = isSCLLBullish && + !isSCLLBullishPrev; + + // + bool isSCHHBearish = conditions.pvSCHHs[cIndex] < conditions.pvSCHHs[pIndex]; + bool isSCLLBearish = conditions.pvSCLLs[cIndex] < conditions.pvSCLLs[pIndex]; + + // + bool isSCHHBearishPrev = conditions.pvSCHHs[pIndex] < conditions.pvSCHHs[ppIndex]; + bool isSCLLBearishPrev = conditions.pvSCLLs[pIndex] < conditions.pvSCLLs[ppIndex]; + + // + bool isSCBearish = isSCHHBearish && + isSCLLBearish; + + // + bool isSCBearishPrev = isSCHHBearishPrev && + isSCLLBearishPrev; + + // + bool isSCHHSwitchedToBearish = isSCHHBearish && + !isSCHHBearishPrev; + bool isSCLLSwitchedToBeraish = isSCLLBearish && + !isSCLLBearishPrev; + + // + bool isSCSwitchedToBullish = + // + (isSCHHSwitchedToBullish && + !isSCLLBearish) + // + || + // + (isSCLLSwitchedToBullish && + !isSCHHBearish) + // + ; + + // + bool isSCSwitchedToBearish = + // + (isSCHHSwitchedToBearish && + !isSCLLBullish) + // + || + // + (isSCLLSwitchedToBeraish && + !isSCHHBullish) + // + ; + + // + // MC ... + + // + bool isMCHHBullish = conditions.pvMCHHs[cIndex] > conditions.pvMCHHs[pIndex]; + bool isMCLLBullish = conditions.pvMCLLs[cIndex] > conditions.pvMCLLs[pIndex]; + + // + bool isMCHHBullishPrev = conditions.pvMCHHs[pIndex] > conditions.pvMCHHs[ppIndex]; + bool isMCLLBullishPrev = conditions.pvMCLLs[pIndex] > conditions.pvMCLLs[ppIndex]; + + // + bool isMCBullish = isMCHHBullish && + isMCLLBullish; + + // + bool isMCBullishPrev = isMCHHBullishPrev && + isMCLLBullishPrev; + + // + bool isMCHHSwitchedToBullish = isMCHHBullish && + !isMCHHBullishPrev; + bool isMCLLSwitchedToBullish = isMCLLBullish && + !isMCLLBullishPrev; + + // + bool isMCHHBearish = conditions.pvMCHHs[cIndex] < conditions.pvMCHHs[pIndex]; + bool isMCLLBearish = conditions.pvMCLLs[cIndex] < conditions.pvMCLLs[pIndex]; + + // + bool isMCHHBearishPrev = conditions.pvMCHHs[pIndex] < conditions.pvMCHHs[ppIndex]; + bool isMCLLBearishPrev = conditions.pvMCLLs[pIndex] < conditions.pvMCLLs[ppIndex]; + + // + bool isMCBearish = isMCHHBearish && + isMCLLBearish; + + // + bool isMCBearishPrev = isMCHHBearishPrev && + isMCLLBearishPrev; + + // + bool isMCHHSwitchedToBearish = isMCHHBearish && + !isMCHHBearishPrev; + bool isMCLLSwitchedToBeraish = isMCLLBearish && + !isMCLLBearishPrev; + + // + bool isMCSwitchedToBullish = + // + (isMCHHSwitchedToBullish && + !isMCLLBearish) + // + || + // + (isMCLLSwitchedToBullish && + !isMCHHBearish) + // + ; + + // + bool isMCSwitchedToBearish = + // + (isMCHHSwitchedToBearish && + !isMCLLBullish) + // + || + // + (isMCLLSwitchedToBeraish && + !isMCHHBullish) + // + ; + + // + // LC ... + + // + bool isLCHHBullish = conditions.pvLCHHs[cIndex] > conditions.pvLCHHs[pIndex]; + bool isLCLLBullish = conditions.pvLCLLs[cIndex] > conditions.pvLCLLs[pIndex]; + + // + bool isLCHHBullishPrev = conditions.pvLCHHs[pIndex] > conditions.pvLCHHs[ppIndex]; + bool isLCLLBullishPrev = conditions.pvLCLLs[pIndex] > conditions.pvLCLLs[ppIndex]; + + // + bool isLCBullish = isLCHHBullish && + isLCLLBullish; + + // + bool isLCBullishPrev = isLCHHBullishPrev && + isLCLLBullishPrev; + + // + bool isLCHHSwitchedToBullish = isLCHHBullish && + !isLCHHBullishPrev; + bool isLCLLSwitchedToBullish = isLCLLBullish && + !isLCLLBullishPrev; + + // + bool isLCHHBearish = conditions.pvLCHHs[cIndex] < conditions.pvLCHHs[pIndex]; + bool isLCLLBearish = conditions.pvLCLLs[cIndex] < conditions.pvLCLLs[pIndex]; + + // + bool isLCHHBearishPrev = conditions.pvLCHHs[pIndex] < conditions.pvLCHHs[ppIndex]; + bool isLCLLBearishPrev = conditions.pvLCLLs[pIndex] < conditions.pvLCLLs[ppIndex]; + + // + bool isLCBearish = isLCHHBearish && + isLCLLBearish; + + // + bool isLCBearishPrev = isLCHHBearishPrev && + isLCLLBearishPrev; + + // + bool isLCHHSwitchedToBearish = isLCHHBearish && + !isLCHHBearishPrev; + bool isLCLLSwitchedToBeraish = isLCLLBearish && + !isLCLLBearishPrev; + + // + bool isLCSwitchedToBullish = + // + (isLCHHSwitchedToBullish && + !isLCLLBearish) + // + || + // + (isLCLLSwitchedToBullish && + !isLCHHBearish) + // + ; + + // + bool isLCSwitchedToBearish = + // + (isLCHHSwitchedToBearish && + !isLCLLBullish) + // + || + // + (isLCLLSwitchedToBeraish && + !isLCHHBullish) + // + ; + + // + // HC ... + + // + bool isHCHHBullish = conditions.pvHCHHs[cIndex] > conditions.pvHCHHs[pIndex]; + bool isHCLLBullish = conditions.pvHCLLs[cIndex] > conditions.pvHCLLs[pIndex]; + + // + bool isHCHHBullishPrev = conditions.pvHCHHs[pIndex] > conditions.pvHCHHs[ppIndex]; + bool isHCLLBullishPrev = conditions.pvHCLLs[pIndex] > conditions.pvHCLLs[ppIndex]; + + // + bool isHCBullish = isHCHHBullish && + isHCLLBullish; + + // + bool isHCBullishPrev = isHCHHBullishPrev && + isHCLLBullishPrev; + + // + bool isHCHHSwitchedToBullish = isHCHHBullish && + !isHCHHBullishPrev; + bool isHCLLSwitchedToBullish = isHCLLBullish && + !isHCLLBullishPrev; + + // + bool isHCHHBearish = conditions.pvHCHHs[cIndex] < conditions.pvHCHHs[pIndex]; + bool isHCLLBearish = conditions.pvHCLLs[cIndex] < conditions.pvHCLLs[pIndex]; + + // + bool isHCHHBearishPrev = conditions.pvHCHHs[pIndex] < conditions.pvHCHHs[ppIndex]; + bool isHCLLBearishPrev = conditions.pvHCLLs[pIndex] < conditions.pvHCLLs[ppIndex]; + + // + bool isHCBearish = isHCHHBearish && + isHCLLBearish; + + // + bool isHCBearishPrev = isHCHHBearishPrev && + isHCLLBearishPrev; + + // + bool isHCHHSwitchedToBearish = isHCHHBearish && + !isHCHHBearishPrev; + bool isHCLLSwitchedToBeraish = isHCLLBearish && + !isHCLLBearishPrev; + + // + bool isHCSwitchedToBullish = + // + (isHCHHSwitchedToBullish && + !isHCLLBearish) + // + || + // + (isHCLLSwitchedToBullish && + !isHCHHBearish) + // + ; + + // + bool isHCSwitchedToBearish = + // + (isHCHHSwitchedToBearish && + !isHCLLBullish) + // + || + // + (isHCLLSwitchedToBeraish && + !isHCHHBullish) + // + ; + + // + // Setting Conditional Variables ... + + // + conditions.isLastBullish = isLastBullish; + conditions.isLastBearish = isLastBearish; + conditions.isCurrentBullish = isCurrentBullish; + conditions.isCurrentBearish = isCurrentBearish; + conditions.isCurrentMidLineOverLastHigh = isCurrentMidLineOverLastHigh; + conditions.isCurrentMidLineUnderLastLow = isCurrentMidLineUnderLastLow; + conditions.isCurrentMidLineOverLastUp = isCurrentMidLineOverLastUp; + conditions.isCurrentMidLineUnderLastDown = isCurrentMidLineUnderLastDown; + conditions.isCurrentMidLineOverLastMidLine = isCurrentMidLineOverLastMidLine; + conditions.isCurrentMidLineUnderLastMidLine = isCurrentMidLineUnderLastMidLine; + + // + conditions.isHKBullish = isHKBullish; + conditions.isHKBearish = isHKBearish; + conditions.isClosedOverHK = isClosedOverHK; + conditions.isClosedUnderHK = isClosedUnderHK; + conditions.isHKSwitchedToBullish = isHKSwitchedToBullish; + conditions.isHKSwitchedToBearish = isHKSwitchedToBearish; + + // + conditions.isSMHKBullish = isSMHKBullish; + conditions.isSMHKBearish = isSMHKBearish; + conditions.isClosedOverSMHK = isClosedOverSMHK; + conditions.isClosedUnderSMHK = isClosedUnderSMHK; + conditions.isSMHKSwitchedToBullish = isSMHKSwitchedToBullish; + conditions.isSMHKSwitchedToBearish = isSMHKSwitchedToBearish; + + // + conditions.isClosedOverKijunSen = isClosedOverKijunSen; + conditions.isClosedUnderKijunSen = isClosedUnderKijunSen; + conditions.isTenkanSenOverKijunSen = isTenkanSenOverKijunSen; + conditions.isTenkanSenUnderKijunSen = isTenkanSenUnderKijunSen; + conditions.isTenkanSenCrossedOverKijunSen = isTenkanSenCrossedOverKijunSen; + conditions.isTenkanSenCrossedUnderKijunSen = isTenkanSenCrossedUnderKijunSen; + + // + conditions.isSenkouSpanAOverB = isSenkouSpanACrossedOverB; + conditions.isSenkouSpanAUnderB = isSenkouSpanACrossedUnderB; + conditions.isSenkouSpanAOverLast = isSenkouSpanACrossedOverLast; + conditions.isSenkouSpanAUnderLast = isSenkouSpanACrossedUnderLast; + conditions.isFutureSenkouSpanAOverB = isFutureSenkouSpanACrossedOverB; + conditions.isFutureSenkouSpanAUnderB = isFutureSenkouSpanACrossedUnderB; + conditions.isFutureSenkouSpanAOverLast = isFutureSenkouSpanACrossedOverLast; + conditions.isFutureSenkouSpanAUnderLast = isFutureSenkouSpanACrossedUnderLast; + + // + conditions.isSenkouSpanACrossedOverB = isSenkouSpanACrossedOverB; + conditions.isSenkouSpanACrossedUnderB = isSenkouSpanACrossedUnderB; + conditions.isSenkouSpanACrossedOverLast = isSenkouSpanACrossedOverLast; + conditions.isSenkouSpanACrossedUnderLast = isSenkouSpanACrossedUnderLast; + conditions.isFutureSenkouSpanACrossedOverB = isFutureSenkouSpanACrossedOverB; + conditions.isFutureSenkouSpanACrossedUnderB = isFutureSenkouSpanACrossedUnderB; + conditions.isFutureSenkouSpanACrossedOverLast = isFutureSenkouSpanACrossedOverLast; + conditions.isFutureSenkouSpanACrossedUnderLast = isFutureSenkouSpanACrossedUnderLast; + + // + conditions.isMCFastOverSlow = isMCFastOverSlow; + conditions.isMCFastUnderSlow = isMCFastUnderSlow; + conditions.isMCFastOverVerifier = isMCFastOverVerifier; + conditions.isMCFastUnderVerifier = isMCFastUnderVerifier; + conditions.isMCSlowOverVerifier = isMCSlowOverVerifier; + conditions.isMCSlowUnderVerifier = isMCSlowUnderVerifier; + conditions.isMCFastCrossedOverSlow = isMCFastCrossedOverSlow; + conditions.isMCFastCrossedUnderSlow = isMCFastCrossedUnderSlow; + conditions.isMCFastCrossedOverVerifier = isMCFastCrossedOverVerifier; + conditions.isMCFastCrossedUnderVerifier = isMCFastCrossedUnderVerifier; + conditions.isMCSlowCrossedOverVerifier = isMCSlowCrossedOverVerifier; + conditions.isMCSlowCrossedUnderVerifier = isMCSlowCrossedUnderVerifier; + + // + conditions.isTrendBullish = isTrendBullish; + conditions.isTrendBearish = isTrendBearish; + conditions.isTrendSwitchedToBullish = isTrendSwitchedToBullish; + conditions.isTrendSwitchedToBearish = isTrendSwitchedToBearish; + + // + conditions.isZigZagInPeak = isZigZagInPeak; + conditions.isZigZagInVale = isZigZagInVale; + + // + conditions.isMRBFastOverSlow = isMRBFastOverSlow; + conditions.isMRBFastUnderSlow = isMRBFastUnderSlow; + conditions.isMRBFastCrossedOverSlow = isMRBFastCrossedOverSlow; + conditions.isMRBFastCrossedUnderSlow = isMRBFastCrossedUnderSlow; + conditions.isMRBFastOverVerifier = isMRBFastOverVerifier; + conditions.isMRBFastUnderVerifier = isMRBFastUnderVerifier; + conditions.isMRBFastCrossedtOverVerifier = isMRBFastCrossedtOverVerifier; + conditions.isMRBFastCrossedUnderVerifier = isMRBFastCrossedUnderVerifier; + conditions.isMRBSlowOverVerifier = isMRBSlowOverVerifier; + conditions.isMRBSlowUnderVerifier = isMRBSlowUnderVerifier; + conditions.isMRBSlowCrossedtOverVerifier = isMRBSlowCrossedtOverVerifier; + conditions.isMRBSlowCrossedUnderVerifier = isMRBSlowCrossedUnderVerifier; + + // + conditions.isCHEBullish = isCHEBullish; + conditions.isCHEBearish = isCHEBearish; + conditions.isCHESwitchedToBullish = isCHESwitchedToBullish; + conditions.isCHESwitchedToBearish = isCHESwitchedToBearish; + + // + conditions.isTDBullish = isTDBullish; + conditions.isTDBearish = isTDBearish; + conditions.isTDSwitchedToBullish = isTDSwitchedToBullish; + conditions.isTDSwitchedToBearish = isTDSwitchedToBearish; + + // + conditions.isDONAttachedMaxLower = isDONAttachedMaxLower; + conditions.isDONAttachedMinLower = isDONAttachedMinLower; + conditions.isDONCrossedOverMaxLower = isDONCrossedOverMaxLower; + conditions.isDONCrossedUnderMaxLower = isDONCrossedUnderMaxLower; + conditions.isDONCrossedOverMinLower = isDONCrossedOverMinLower; + conditions.isDONCrossedUnderMinLower = isDONCrossedUnderMinLower; + + // + conditions.isDONAttachedMaxUpper = isDONAttachedMaxUpper; + conditions.isDONAttachedMinUpper = isDONAttachedMinUpper; + conditions.isDONCrossedOverMaxUpper = isDONCrossedOverMaxUpper; + conditions.isDONCrossedUnderMaxUpper = isDONCrossedUnderMaxUpper; + conditions.isDONCrossedOverMinUpper = isDONCrossedOverMinUpper; + conditions.isDONCrossedUnderMinUpper = isDONCrossedUnderMinUpper; + + // + conditions.isNewPeak = isNewPeak; + conditions.isNewPeakOverLast = isNewPeakOverLast; + conditions.isNewPeakUnderLast = isNewPeakUnderLast; + + // + conditions.isNewVale = isNewVale; + conditions.isNewValeOverLast = isNewValeOverLast; + conditions.isNewValeUnderLast = isNewValeUnderLast; + + // + conditions.isFiboIncreased = isFiboIncreased; + conditions.isFiboDecreased = isFiboDecreased; + conditions.isFiboSectionChanged = isFiboSectionChanged; + + // + conditions.isSCBullish = isSCBullish; + conditions.isSCHHBullish = isSCHHBullish; + conditions.isSCLLBullish = isSCLLBullish; + conditions.isSCSwitchedToBullish = isSCSwitchedToBullish; + conditions.isSCHHSwitchedToBullish = isSCHHSwitchedToBullish; + conditions.isSCLLSwitchedToBullish = isSCLLSwitchedToBullish; + + // + conditions.isSCBearish = isSCBearish; + conditions.isSCHHBearish = isSCHHBearish; + conditions.isSCLLBearish = isSCLLBearish; + conditions.isSCSwitchedToBearish = isSCSwitchedToBearish; + conditions.isSCHHSwitchedToBearish = isSCHHSwitchedToBearish; + conditions.isSCLLSwitchedToBeraish = isSCLLSwitchedToBeraish; + + // + conditions.isMCBullish = isMCBullish; + conditions.isMCHHBullish = isMCHHBullish; + conditions.isMCLLBullish = isMCLLBullish; + conditions.isMCSwitchedToBullish = isMCSwitchedToBullish; + conditions.isMCHHSwitchedToBullish = isMCHHSwitchedToBullish; + conditions.isMCLLSwitchedToBullish = isMCLLSwitchedToBullish; + + // + conditions.isMCBearish = isMCBearish; + conditions.isMCHHBearish = isMCHHBearish; + conditions.isMCLLBearish = isMCLLBearish; + conditions.isMCSwitchedToBearish = isMCSwitchedToBearish; + conditions.isMCHHSwitchedToBearish = isMCHHSwitchedToBearish; + conditions.isMCLLSwitchedToBeraish = isMCLLSwitchedToBeraish; + + // + conditions.isLCBullish = isLCBullish; + conditions.isLCHHBullish = isLCHHBullish; + conditions.isLCLLBullish = isLCLLBullish; + conditions.isLCSwitchedToBullish = isLCSwitchedToBullish; + conditions.isLCHHSwitchedToBullish = isLCHHSwitchedToBullish; + conditions.isLCLLSwitchedToBullish = isLCLLSwitchedToBullish; + + // + conditions.isLCBearish = isLCBearish; + conditions.isLCHHBearish = isLCHHBearish; + conditions.isLCLLBearish = isLCLLBearish; + conditions.isLCSwitchedToBearish = isLCSwitchedToBearish; + conditions.isLCHHSwitchedToBearish = isLCHHSwitchedToBearish; + conditions.isLCLLSwitchedToBeraish = isLCLLSwitchedToBeraish; + + // + conditions.isHCBullish = isHCBullish; + conditions.isHCHHBullish = isHCHHBullish; + conditions.isHCLLBullish = isHCLLBullish; + conditions.isHCSwitchedToBullish = isHCSwitchedToBullish; + conditions.isHCHHSwitchedToBullish = isHCHHSwitchedToBullish; + conditions.isHCLLSwitchedToBullish = isHCLLSwitchedToBullish; + + // + conditions.isHCBearish = isHCBearish; + conditions.isHCHHBearish = isHCHHBearish; + conditions.isHCLLBearish = isHCLLBearish; + conditions.isHCSwitchedToBearish = isHCSwitchedToBearish; + conditions.isHCHHSwitchedToBearish = isHCHHSwitchedToBearish; + conditions.isHCLLSwitchedToBeraish = isHCLLSwitchedToBeraish; + } + + // + // Market Parse Conditions ... + bool HasConditions( + XSignal &signal, // If Any Signal provided, Filled here ... + bool &hasLong, + int &longPusher, + bool &hasShort, + int &shortPusher // + ) + { + // + bool result = false; + + // + longPusher = 0; + shortPusher = 0; + hasLong = false; + hasShort = false; + + // + int count = CountSignallers(); + if (!IsValidSize(count)) + { + return result; + } + + // + X121MCycleConditions conditions; + GetMarketConditions(conditions); + + // + for (int i = 0; i < count; i++) + { + // + bool iHasLong = false; + bool iHasShort = false; + + // + double iTP = 0; + double iTPProvided = 0; + double iSL = 0; + double iSLProvided = 0; + double iEntry = 0; + ENUM_POSITION_TYPE iType; + string iSymbol = GetSymbol(); + double iR2R = mSignallers[i].r2r; + ENUM_TIMEFRAMES iPeriod = GetPeriod(); + string iProvider = mSignallers[i].GetName(); + + // + bool iHasSignal = mSignallers[i].HasConditions( + conditions, + iHasLong, + iHasShort, + iTPProvided, + iSLProvided // + ); + if (iHasSignal) + { + // + // Filling Pusher(s) ... + if (iHasLong) + { + longPusher++; + } + else if (iHasShort) + { + shortPusher++; + } + + // + if (iHasLong && !hasLong) + { + // + hasLong = iHasLong; + + // + // Filling Signal ... + iType = POSITION_TYPE_BUY; + + // + iEntry = GetEntry( + iSymbol, + iType // + ); + + // + CalculateTPSL( + iSL, + iTP, + iType, + iEntry, + iR2R, + iSLProvided, + iTPProvided // + ); + + // + // Fill Signal Here ... + bool isSignalGenerated = mSignallers[i].GenerateMarketSignal( + signal, + iSymbol, + iPeriod, + iType, + iEntry, + iSL, + iTP // + ); + } + else if (iHasShort && !hasShort) + { + // + hasShort = iHasShort; + + // + // Fill Signal Here ... + iType = POSITION_TYPE_SELL; + + // + iEntry = GetEntry( + iSymbol, + iType // + ); + + // + CalculateTPSL( + iSL, + iTP, + iType, + iEntry, + iR2R, + iSLProvided, + iTPProvided // + ); + + // + // Fill Signal Here ... + bool isSignalGenerated = mSignallers[i].GenerateMarketSignal( + signal, + iSymbol, + iPeriod, + iType, + iEntry, + iSL, + iTP // + ); + } + } + } + + // + result = hasLong || hasShort; + + // + return result; + } + + // + // X786 Long ... + bool HasX786LongConditions() + { + // + bool result = false; + + // + X121MCycleConditions conditions; + GetMarketConditions(conditions); + + // + result = + // + (conditions.isSMHKSwitchedToBullish && + (conditions.isTDBullish && + conditions.isCHEBullish && + conditions.isTrendBullish)) + // + || + // + (conditions.isTDSwitchedToBullish && + (conditions.isSMHKBullish && + conditions.isCHEBullish && + conditions.isTrendBullish)) + // + || + // + (conditions.isCHESwitchedToBullish && + (conditions.isTDBullish && + conditions.isSMHKBullish && + conditions.isTrendBullish)) + // + || + // + (conditions.isTrendSwitchedToBullish && + (conditions.isTDBullish && + conditions.isCHEBullish && + conditions.isSMHKBullish)) + // + ; + + // + return result; + } + + // + // X786 Short ... + bool HasX786ShortConditions() + { + // + bool result = false; + + // + X121MCycleConditions conditions; + GetMarketConditions(conditions); + + // + result = + // + (conditions.isSMHKSwitchedToBearish && + (conditions.isTDBearish && + conditions.isCHEBearish && + conditions.isTrendBearish)) + // + || + // + (conditions.isTDSwitchedToBearish && + (conditions.isSMHKBearish && + conditions.isCHEBearish && + conditions.isTrendBearish)) + // + || + // + (conditions.isCHESwitchedToBearish && + (conditions.isTDBearish && + conditions.isSMHKBearish && + conditions.isTrendBearish)) + // + || + // + (conditions.isTrendSwitchedToBearish && + (conditions.isTDBearish && + conditions.isCHEBearish && + conditions.isSMHKBearish)) + // + ; + + // + return result; + } + + // + // X121 Long ... + bool HasX121LongConditions() + { + // + bool result = false; + + // + return result; + } + + // + // X121 Short ... + bool HasX121ShortConditions() + { + // + bool result = false; + + // + return result; + } + + // + + // + // Initial Market Cycle ... + bool Init( + X121MCycleInputs &inputs // Inputs for Initialization + ) + { + // + bool result = false; + + // + // Validate Input ... + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + string symbol = mInputs.cycle.symbol; + ENUM_TIMEFRAMES period = mInputs.cycle.period; + + // + // Init Helpers ... + + // + // XHK ... + result = hk.Init( + symbol, + period, + mInputs.hkInputs + // + ); + if (!result) + { + return result; + } + + // + // XMC ... + result = mc.Init( + symbol, + period, + mInputs.mcInputs + // + ); + if (!result) + { + return result; + } + + // + // XPV ... + result = pv.Init( + symbol, + period, + mInputs.pvInputs + // + ); + if (!result) + { + return result; + } + + // + // XZG ... + result = zg.Init( + symbol, + period, + mInputs.zgInputs + // + ); + if (!result) + { + return result; + } + + // + // XTD ... + result = td.Init( + symbol, + period, + mInputs.tdInputs + // + ); + if (!result) + { + return result; + } + + // + // XMRB ... + result = mrb.Init( + symbol, + period, + mInputs.mrbInputs + // + ); + if (!result) + { + return result; + } + + // + // XSTR ... + result = str.Init( + symbol, + period, + mInputs.strInputs + // + ); + if (!result) + { + return result; + } + + // + // XCHE ... + result = che.Init( + symbol, + period, + mInputs.cheInputs + // + ); + if (!result) + { + return result; + } + + // + // XOSC ... + result = osc.Init( + symbol, + period, + mInputs.oscInputs + // + ); + if (!result) + { + return result; + } + + // + // XICH ... + result = ich.Init( + symbol, + period, + mInputs.ichInputs + // + ); + if (!result) + { + return result; + } + + // + // XDON ... + result = don.Init( + symbol, + period, + mInputs.donInputs + // + ); + if (!result) + { + return result; + } + + // + return result; + } + + // + // Draw Tools ... + // + // Completely Draw Bars ... + void Draw( + long chartID, // Chart ID ... + int subWindow, // Chart Sub Window ... + int &offset // Distance used for Labels ... + ) + { + // + if (mInputs.drawCBar || mInputs.drawPBar) + { + // + DrawOHCL( + chartID, + subWindow, + mInputs.drawLabels, + !mInputs.drawCBar && mInputs.drawPBar, + !mInputs.drawPBar && mInputs.drawCBar, + offset + // + ); + + // + if (mInputs.drawLabels) + { + offset += 3; + } + } + + // + if (mInputs.drawCBarMid || mInputs.drawPBarMid) + { + // + DrawMidLine( + chartID, + subWindow, + mInputs.drawLabels, + !mInputs.drawCBarMid && mInputs.drawPBarMid, + !mInputs.drawPBarMid && mInputs.drawCBarMid, + offset + // + ); + + // + if (mInputs.drawLabels) + { + // + if (mInputs.drawCBarMid) + { + offset++; + } + + // + if (mInputs.drawPBarMid) + { + offset++; + } + } + } + } + + // + // Draw Functions ... + // + // Draw Middle Line of Cycle ... + void DrawOHCL( + long chartID, + int subWindow, + bool drawLabel = false, // Specify Draw Label of Mid Line or not ... + bool drawOnlyPrev = false, // Specify Draw Only Prev Bar of Cycle ... + bool drawOnlyCurrent = false, // Specify Draw Only Current Bar of Cycle ... + int offset = 0 // Distance used for Labels ... + ) + { + // + if (offset < 0) + { + offset = 0; + } + + // + string baseTag = ToString(mInputs.cycle.cycle); + + // + XOHCL cBar = GetBar(0); + XOHCL pBar = GetBar(1); + + // + datetime fromCDate = GetBarTime(0); + datetime fromPDate = GetBarTime(1); + + // + datetime cTime = TimeCurrent(); + + // + // Try to Draw ... + + // + bool canDrawPrev = !drawOnlyCurrent; + bool canDrawCurrent = !drawOnlyPrev; + + // + // Set Cycles Color based on Current Candle ... + + // + bool isCBarBullish = + cBar.IsBullish(); + + // + bool isPBarBullish = + pBar.IsBearish(); + + // + color clrTemoBullishColor = mInputs.cBarDrawSpecs.openStyle.clr; + color clrTemoBearishColor = mInputs.cBarDrawSpecs.closeStyle.clr; + + // + color cBarSelectedColor = isCBarBullish ? clrTemoBullishColor : clrTemoBearishColor; + color pBarSelectedColor = isPBarBullish ? clrTemoBullishColor : clrTemoBearishColor; + + // + mInputs.cBarDrawSpecs.openStyle.clr = cBarSelectedColor; + mInputs.cBarDrawSpecs.openStyle.labelColor = cBarSelectedColor; + + // + mInputs.cBarDrawSpecs.closeStyle.clr = cBarSelectedColor; + mInputs.cBarDrawSpecs.closeStyle.labelColor = cBarSelectedColor; + + // + mInputs.pBarDrawSpecs.openStyle.clr = pBarSelectedColor; + mInputs.pBarDrawSpecs.openStyle.labelColor = pBarSelectedColor; + + // + mInputs.pBarDrawSpecs.closeStyle.clr = pBarSelectedColor; + mInputs.pBarDrawSpecs.closeStyle.labelColor = pBarSelectedColor; + + // + if (canDrawPrev) + { + offset++; + } + + // + // Label ... + if (drawLabel) + { + // + if (canDrawPrev) + { + // + // Draw Prev Bar Lables ... + + // + DrawXOHCLLabel( + chartID, + subWindow, + pBar, + mInputs.pBarDrawSpecs, + "P", + cTime, + offset - 1 + // + ); + + // + offset += 3; + } + + // + if (canDrawCurrent) + { + // + // Draw Current Bar Lables ... + + // + DrawXOHCLLabel( + chartID, + subWindow, + cBar, + mInputs.cBarDrawSpecs, + "C", + cTime, + offset + // + ); + } + } + + // + // Line ... + + // + if (canDrawPrev) + { + // + // Draw Cycle Prev Bar ... + DrawXOHCLContent( + chartID, + subWindow, + pBar, + mInputs.pBarDrawSpecs, + "P", + fromPDate + // + ); + } + + // + if (canDrawCurrent) + { + // + // Draw Cycle Current Bar ... + DrawXOHCLContent( + chartID, + subWindow, + cBar, + mInputs.cBarDrawSpecs, + "C", + fromCDate + // + ); + } + } + + // + // Draw Middle Line of Cycle ... + void DrawMidLine( + long chartID, + int subWindow, + bool drawLabel = false, // Specify Draw Label of Mid Line or not ... + bool drawOnlyPrev = false, // Specify Draw Only Prev Bar of Cycle ... + bool drawOnlyCurrent = false, // Specify Draw Only Current Bar of Cycle ... + int offset = 0 // Distance used for Labels ... + ) + { + // + if (offset < 0) + { + offset = 0; + } + + // + // Calculate Mid Line ... + XOHCL cBar = GetBar(0); + double cMidLine = cBar.GetMid(); + + // + XOHCL pBar = GetBar(1); + double pMidLine = pBar.GetMid(); + + // + string baseTag = ToString(mInputs.cycle.cycle); + + // + string midCTag = baseTag + "|MID|C|"; + string midPTag = baseTag + "|MID|P|"; + + // + string midCLblTag = midCTag + "lbl"; + string midPLblTag = midPTag + "lbl"; + + // + datetime fromCDate = GetBarTime(0); + datetime fromPDate = GetBarTime(1); + + // + datetime cTime = TimeCurrent(); + + // + // Try to Draw ... + + // + bool canDrawPrev = !drawOnlyCurrent; + bool canDrawCurrent = !drawOnlyPrev; + + // + if (canDrawPrev) + { + offset++; + } + + // + // Label ... + if (drawLabel) + { + // + if (canDrawPrev) + { + // + // Draw Prev Candle MidLine Lable ... + DrawLabel( + chartID, + subWindow, + mInputs.pBarMidDrawSpecs, + midPLblTag, + cTime, + pMidLine, + offset // + ); + } + + // + if (canDrawCurrent) + { + // + // Draw Current Candle MidLine Label ... + DrawLabel( + chartID, + subWindow, + mInputs.cBarMidDrawSpecs, + midCLblTag, + cTime, + cMidLine, + offset - 1 // + ); + } + } + + // + // Line ... + + // + if (canDrawPrev) + { + // + // Draw Prev Candle MidLine ... + DrawLine( + chartID, + subWindow, + mInputs.pBarMidDrawSpecs, + midPTag, + fromPDate, + pMidLine // + ); + } + + // + if (canDrawCurrent) + { + // + // Draw Current Candle MidLine ... + DrawLine( + chartID, + subWindow, + mInputs.cBarMidDrawSpecs, + midCTag, + fromCDate, + cMidLine // + ); + } + } + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Props ... + + // + X121MCycleInputs mInputs; + + // + // Signallers ... + + // + XSignallerDescriptor mSignallers[]; + + // + // Count Signallers ... + int CountSignallers() + { + return ArraySize(mSignallers); + } + + // + // Find Signaller Index ... + int FindSignallerIndex(ENUM_XSIGNAL_PROVIDERS signaller) + { + // + int result = -1; + + // + int count = CountSignallers(); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XSignallerDescriptor iSignaller = mSignallers[i]; + + // + if (iSignaller.name == signaller) + { + // + result = i; + break; + } + } + + // + return result; + } + int FindSignallerIndex(string signaller) + { + // + int result = -1; + + // + if (!IsValid(signaller)) + { + return result; + } + + // + ENUM_XSIGNAL_PROVIDERS mSignaller = ToXSignalProvider(signaller); + if (mSignaller == PROVIDER_NONE) + { + return result; + } + + // + result = FindSignallerIndex(mSignaller); + + // + return result; + } + + // + // Tools ... + + // + bool Update(int hostBarIndex = 0) + { + return mInputs.cycle.Update(hostBarIndex); + } + + // + // Draw Functions ... + + // + // Draw OHCL Labels ... + void DrawXOHCLLabel( + long chartID, + int subWindow, + XOHCL &bar, // Specify Cycle XOHCL Model to Draw ... + XOHCLDrawSpecification &specs, // Specify Cycle XOHCL Draw Specifications ... + string baseTag, // Specify a Unique Tag ... + datetime time, // Draw Time ... + int offset = 0 // + ) + { + // + // Open ... + string openTag = mInputs.cycle.prefix + "_" + baseTag + "_O_lbl"; + DrawLabel( + chartID, + subWindow, + specs.openStyle, + openTag, + time, + bar.open, + offset + // + ); + + // + // High ... + string highTag = mInputs.cycle.prefix + "_" + baseTag + "_H_lbl"; + DrawLabel( + chartID, + subWindow, + specs.highStyle, + highTag, + time, + bar.high, + offset + 1 + // + ); + + // + // Close ... + string closeTag = mInputs.cycle.prefix + "_" + baseTag + "_C_lbl"; + DrawLabel( + chartID, + subWindow, + specs.closeStyle, + closeTag, + time, + bar.close, + offset + 2 + // + ); + + // + // Low ... + string lowTag = mInputs.cycle.prefix + "_" + baseTag + "_L_lbl"; + DrawLabel( + chartID, + subWindow, + specs.lowStyle, + lowTag, + time, + bar.low, + offset + 3 + // + ); + } + + // + // Draw XOHCL Content ... + void DrawXOHCLContent( + long chartID, + int subWindow, + XOHCL &bar, // Specify Cycle XOHCL Model to Draw ... + XOHCLDrawSpecification &specs, // Specify Cycle XOHCL Draw Specifications ... + string baseTag, // Specify a Unique Tag ... + datetime time // Draw Time ... + ) + { + // + // Open ... + string openTag = mInputs.cycle.prefix + "_" + baseTag + "_O"; + DrawLine( + chartID, + subWindow, + specs.openStyle, + openTag, + time, + bar.open + // + ); + + // + // High ... + string highTag = mInputs.cycle.prefix + "_" + baseTag + "_H"; + DrawLine( + chartID, + subWindow, + specs.highStyle, + highTag, + time, + bar.high + // + ); + + // + // Close ... + string closeTag = mInputs.cycle.prefix + "_" + baseTag + "_C"; + DrawLine( + chartID, + subWindow, + specs.closeStyle, + closeTag, + time, + bar.close + // + ); + + // + // Low ... + string lowTag = mInputs.cycle.prefix + "_" + baseTag + "_L"; + DrawLine( + chartID, + subWindow, + specs.lowStyle, + lowTag, + time, + bar.low + // + ); + } + + // + // Draw Label Using Specifications ... + void DrawLabel( + long chartID, + int subWindow, + XDrawSpecifications &specs, + string tag, + datetime time, + double price, + int offset = 0 // + ) + { + // + if (offset < 0) + { + offset = 0; + } + + // + int offsetSeconds = PeriodSeconds(mInputs.cycle.hostPeriod) * offset; + + // + string value = specs.label; + + // + DrawText( + chartID, + tag, + subWindow, + time - offsetSeconds, + price, + specs.label, + specs.labelFont, + specs.labelFontSize, + specs.labelColor, + specs.labelAngel, + specs.labelAnchor, + specs.back, + specs.selection, + specs.hidden, + specs.zOrder // + ); + } + + // + // Draw TrendLine Using Specifications ... + void DrawLine( + long chartID, + int subWindow, + XDrawSpecifications &specs, + string tag, + datetime fromDate, + double fromPrice, + datetime toDate = NULL, + double toPrice = 0 // + ) + { + // + if (toPrice <= 0) + { + toPrice = fromPrice; + } + + // + if (toDate == 0 || toDate == NULL) + { + toDate = TimeCurrent(); + } + + // + DrawTrendLine( + chartID, + tag, + subWindow, + fromDate, + fromPrice, + toDate, + toPrice, + specs.clr, + specs.style, + specs.width, + specs.back, + specs.selection, + specs.rayRight, + specs.hidden, + specs.zOrder // + ); + } +}; + +// +// Tools ... + +// +struct X121MarketCycleDescriptor +{ + // + string symbol; // Trading Symbol + ENUM_TIMEFRAMES hostPeriod; // Host Period + ENUM_X_MARKET_CYCLES cycle; // Init Cycle + ENUM_TIMEFRAMES period; // Cycle Period + ENUM_X_PERIOD_METHOD periodMethod; // Cycle Period Method + string prefix; // Prefix + bool useDefaults; // Use Inputs Default Settings ... + + // + X121MCycleInputs inputs; // Inputs + + // + XSCX121Market *market; // Market + + // + X121MCycleConditions conditions; // Market Conditions + + // + // Tools ... + + // + bool Init() + { + // + bool result = false; + + // + result = inputs.Init( + symbol, + hostPeriod, + cycle, + period, + periodMethod, + prefix, + useDefaults // + ); + if (!result) + { + return result; + } + + // + + // + // Instantiate Market ... + market = new XSCX121Market(); + + // + // Initialize Market ... + result = market.Init(inputs); + + // + return result; + } + + // + bool Init( + string mSymbol, // Trading Symbol + ENUM_TIMEFRAMES mHostPeriod, // Host Period + ENUM_X_MARKET_CYCLES mCycle, // Init Cycle + ENUM_TIMEFRAMES mPeriod, // Cycle Period + ENUM_X_PERIOD_METHOD mPeriodMethod, // Cycle Period Method + string mPrefix = "", // Prefix + bool mUseDefaults = true // Use Inputs Default Settings ... + ) + { + // + bool result = false; + + // + result = + // + IsValid(mSymbol) && + IsValid(mHostPeriod) && + IsValid(mPeriodMethod, mPeriod) + // + ; + if (!result) + { + return result; + } + + // + this.cycle = mCycle; + this.symbol = mSymbol; + this.period = mPeriod; + this.prefix = mPrefix; + this.hostPeriod = mHostPeriod; + this.useDefaults = mUseDefaults; + this.periodMethod = mPeriodMethod; + + // + result = this.Init(); + + // + return result; + } +}; + +// +// Custom Draws ... + +// +// Custom Struct Draws ... +bool DrawSupRes( + XOHCLSupRes &item, // Struct item to Draw ... + XDrawSpecifications &supSpecs, // Supports specs ... + XDrawSpecifications &resSpecs, // Resistances specs ... + long chartID = 0, + int subWindow = 0, + string prefix = "SupRes" // +) +{ + // + bool result = false; + + // + result = item.IsValid(); + if (!result) + { + return result; + } + + // + datetime cTime = TimeCurrent(); + datetime pTime = TimeCurrent() - PeriodSeconds(PERIOD_M10); + + // + // Support ... + int supCount = item.CountSupports(); + bool canDrawSups = IsValidSize(supCount) && supSpecs.draw; + if (canDrawSups) + { + // + for (int i = 0; i < supCount; i++) + { + // + double iSup = item.sup[i]; + + // + string supName = prefix + "_" + "Sup_" + ToString(iSup); + + // + DrawTrendLine( + chartID, + supName, + subWindow, + pTime, + iSup, + cTime, + iSup, + supSpecs.clr, + supSpecs.style, + supSpecs.width, + supSpecs.back, + supSpecs.selection, + supSpecs.rayRight, + supSpecs.hidden, + supSpecs.zOrder // + ); + + // + if (IsValid(supSpecs.label)) + { + // + DrawText( + chartID, + supName + "_lbl", + subWindow, + cTime, + iSup, + supSpecs.label, + supSpecs.labelFont, + supSpecs.labelFontSize, + supSpecs.labelColor, + supSpecs.labelAngel, + supSpecs.labelAnchor, + supSpecs.back, + supSpecs.selection, + supSpecs.hidden, + supSpecs.zOrder // + ); + } + } + } + + // + // Resistance ... + int resCount = item.CountResistances(); + bool canDrawRess = IsValidSize(supCount) && supSpecs.draw; + if (canDrawRess) + { + // + for (int i = 0; i < resCount; i++) + { + // + double iRes = item.res[i]; + + // + string resName = prefix + "_" + "Res_" + ToString(iRes); + + // + DrawTrendLine( + chartID, + resName, + subWindow, + pTime, + iRes, + cTime, + iRes, + resSpecs.clr, + resSpecs.style, + resSpecs.width, + resSpecs.back, + resSpecs.selection, + resSpecs.rayRight, + resSpecs.hidden, + resSpecs.zOrder // + ); + + // + if (IsValid(resSpecs.label)) + { + // + DrawText( + chartID, + resName + "_lbl", + subWindow, + cTime, + iRes, + resSpecs.label, + resSpecs.labelFont, + resSpecs.labelFontSize, + resSpecs.labelColor, + resSpecs.labelAngel, + resSpecs.labelAnchor, + resSpecs.back, + resSpecs.selection, + resSpecs.hidden, + resSpecs.zOrder // + ); + } + } + } + + // + result = canDrawSups || canDrawRess; + + // + return result; +} + +// \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xaccount.class.ex5 b/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xaccount.class.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..4ab357d8cca195f65a81bc58a2cd382d0f4c9d6c GIT binary patch literal 5854 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 VvT)#&cz{K!b{s{~lkGLE{s)G27 +#include "../Classes/x-saherelm.base.class.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +// +// a Class for Manage Account ... +class XSCAccount : public XSCBase +{ + // + // Public ... +public: + // + // Constructor ... + void XSCAccount() + { + // + mAccountInfo = new CAccountInfo(); + } + + // + // Deconstructor ... + void ~XSCAccount() + { + } + + // + // START Provided Functions ... + // + + // + // User Account ... + long GetUserAccount() + { + return mAccountInfo.Login(); + } + + // + // Account Leverage ... + long GetLeverage() + { + return mAccountInfo.Leverage(); + } + + // + // Get Trade Expert State ... + bool CanExpertTrade() + { + return mAccountInfo.TradeExpert(); + } + + // + // User Account Trade Mopde (ENUM_ACCOUNT_TRADE_MODE) ... + // -------------------------- + // ACCOUNT_TRADE_MODE_DEMO + // ACCOUNT_TRADE_MODE_CONTEST + // ACCOUNT_TRADE_MODE_REAL + ENUM_ACCOUNT_TRADE_MODE GetTradeMode() + { + return mAccountInfo.TradeMode(); + } + + // + // Get Account Balance ... + double GetBalance() + { + return mAccountInfo.Balance(); + } + + // + // Get the amount of give Credit ... + double GetCredit() + { + return mAccountInfo.Credit(); + } + + // + // Get the amount of current Profit on account ... + double GetProfit() + { + return mAccountInfo.Profit(); + } + + // + // Get the amount of current Equity on account ... + double GetEquity() + { + return mAccountInfo.Equity(); + } + + // + // Get the amount of reserved Margin ... + double GetMargin() + { + return mAccountInfo.Margin(); + } + + // + // Get the amount of free Margin ... + double GetFreeMargin() + { + return mAccountInfo.FreeMargin(); + } + + // + // Get the Level of Margin ... + double GetMarginLevel() + { + return mAccountInfo.MarginLevel(); + } + + // + // Get the Level Of Margin for a Deposit ... + double GetMarginCall() + { + return mAccountInfo.MarginCall(); + } + + // + // Get the Level of Margin for Stop out ... + double GetMarginStopOut() + { + return mAccountInfo.MarginStopOut(); + } + + // + // Get the Client Name ... + string GetName() + { + return mAccountInfo.Name(); + } + + // + // Get the Trade Server Name ... + string GetServerName() + { + return mAccountInfo.Server(); + } + + // + // Get deposit Currency Name ... + string GetCurrency() + { + return mAccountInfo.Currency(); + } + + // + // Get the Company Name that serves an Account ... + string GetCompany() + { + return mAccountInfo.Company(); + } + + // + // Calculate Profits for the current account based on passed parameters ... + double CalculateTradeProfit( + const string symbol, // trading symbol + ENUM_ORDER_TYPE type, // order type + double volume, // volume + double entry, // open price + double exit // close price + ) + { + // + double result = mAccountInfo.OrderProfitCheck( + symbol, + type, + volume, + entry, + exit); + + // + return result; + } + + // + // Calculate amount of margin which required for trade operation ... + double CalculateMarging( + const string symbol, // trading symbol + ENUM_ORDER_TYPE type, // order type + double volume, // volume + double entry // open price + ) + { + // + double result = mAccountInfo.MarginCheck( + symbol, + type, + volume, + entry); + + // + return result; + } + + // + // Calculate amount of free margin left after trade operation ... + double CalculateFreeMarging( + const string symbol, // trading symbol + ENUM_ORDER_TYPE type, // order type + double volume, // volume + double entry // open price + ) + { + // + double result = mAccountInfo.FreeMarginCheck( + symbol, + type, + volume, + entry); + + // + return result; + } + + // + // Calculate the Maximum possible volume of trade operation ... + double CalculateMaxVolume( + const string symbol, // trading symbol + ENUM_ORDER_TYPE type, // order type + double entry, // open price + double percent = 100 // percent of available margin + ) + { + // + double result = mAccountInfo.MaxLotCheck( + symbol, + type, + entry, + percent); + + // + return result; + } + + // + // Calculate Point Value for Given Symbol based on Account ... + double GetPointValue( + string symbol // trading symbol + ) + { + // + double result = 0; + + // + double tickSize = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE); + double tickValue = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE); + double point = SymbolInfoDouble(symbol, SYMBOL_POINT); + + // + double ticksPerPoint = tickSize / point; + + // + result = tickValue / ticksPerPoint; + + // + return result; + } + + // + // Calculate Risk Amount based on account Currency by Providing: + // Points and Volume ... + double CalculateRiskAmount( + string symbol, // trading symbol + double points, // amount of Risk Points + double volume // position Volume + ) + { + // + double result = 0; + + // + double pointValue = GetPointValue(symbol); + + // + result = pointValue * volume * points; + + // + return result; + } + + // + // Calculate Risk Points based on account Currency by Providing: + // Volume and Amount ... + double CalculateRiskPoints( + string symbol, // trading symbol + double volume, // position Volume + double amount // amount of Risk based on Account Currency + ) + { + // + double result = 0; + + // + double pointValue = GetPointValue(symbol); + + // + result = amount / (pointValue * volume); + + // + return result; + } + + // + // Calculate Volume based on account Currency by Providing: + // Amount and Risk Points ... + double CalculateVolume( + string symbol, // trading symbol + double amount, // amount of Risk based on Account Currency + double points // amount of Risk Points + ) + { + // + double result = 0; + + // + points = + points <= 0 + ? 10 + : points; + + // + double pointValue = GetPointValue(symbol); + + // + result = amount / (pointValue * points); + + // + return result; + } + + // + // END Provided Functions ... + // + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Account Info ... + CAccountInfo mAccountInfo; +}; + +// +// START Usefull Functions ... +// + +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xalert.class.ex5 b/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xalert.class.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..4a799cf2aade1eb552d7d6bafd5f85043d7af7f8 GIT binary patch literal 6186 zcmdT>RZtvIvK=(I1`Wl9+mDfIgf7Cyzogv~<<9bX=Gz963rGqf# zjqU#NRtDe-00STZcK`_R0bmdC1keC@09=3L9f0lcSsP&a7q$J%%K@AK&VLalfX?46 z^A~gZd;1^Ef3y8VvFG0jcmRX}oPXWtpU&~O|F>@2f9mG=JD>kjcno+}}V{&){5VG%e~LBWqb zy1aIJTeVMlu@ROe;1^Uhx3k0`RKW9$mv-jf+MlT<#X?JW%fS)%b}itlKR`nE%pjR# z=NZga?0p3j?A#D3?(Nnh7@GT_-JrtvdnhMTx;W3-*^2P6L8MzFyluH z0rO>R5ncutFRO?TL*hG#fjsSiX%MEfjfSmJ9`XfbO{S8_~QGiPr{-xfvF$X?t&E0kmKWDHJ?=)g@6na1FugL>&&_h;KZ`!{Acm11gBwmLV|CEx%@X59X2p413iyycuLePG`Q+T20=@P zT-g`m?wykqS5?i?7Cy$oe zWzbH2DcESqd$SrzZ&H#6kN^}c`y6pYN4F&w~pDXKZoRG ziF?Hpl}FLj@@(o!C?(oN#2SWg=H(N%g`dd`-+e5z-EY%ZjrS%k8uus7no%MK#5+G9 zaeA;x#%@~U?l+w&V>Vu+s;`m2cDyBec0jaCa%Hd1*=1L?oUYqxh}h3bx0n?~d^8Ad zJAG#_U%zjy8~GJq92!v~9ilpR*LFeevM)oGP~8|1W)F+cz%MiDi(Kj^>%vs7QZ6x( zh~q1lTczFZ=vaP?8$8D6bIH?kRb7lDIuYXE35`5`YnH#s?p6q+*NGl`Vz(+kvblzZ z#u*1;?K%(eVn1^FRQe`nWdUxdiL7V$zd%%tE5{lV*MC93+&xi`EYfa6CG83c@qu%Ir35xT}iBE8+veWOZ4x49{%W zPomQNE@m;P-eMC_ZTXd7?lkfhlVmitlL}+)gIaZ-cp92TL_a8BUyMxOMM)C;;*~W7 zkEPbf5V)vfy7cAmj9;A)itaaO89+83WsHa^<-xD+^usATgBS~lsq|iiO1>w58i&06 zoNS<2+A_J=Ncb7LZsFBvm^nbJk&a~2s}rBtdfBA-Lj2phlU4M1z8U*$h98%=|B#(U z%uMZ|D28JwB22!CIa@p}Rs3T~XvYqPWKxp}5vFUOOgpN${A#2aCMGK?slLtng5V81)M9EIXY))kMRQs zciUKldHiP!-;{7pOZR3X8ZeVVGu3D)6DISxC%hDKSRZUM3Q zkFMLtZAksSK8p`6wB6TxrUmXQiQYb6vXIO7@+fPDHyMIB*-0*_NOwC3JPP$^g5C1o zi+YX6d+Ul?74n}o>E4Er)kP%3&i)>;3G|YBL_!7m zVq@PK`Ee(5*Xz~~(rq5-vtERbVZ(S~`jOfvNM#KNQvQ(~-HQSusgK|(&=6i!cWmQt zt+aH4_TE@ej$J3(Ra#?ImUAq=NLxaIHar1oAB;LOg!!Idy#HyY*ZM zv>2SDWk2#H23@G3UxQz`qC$fJpwBL|Yen-z;R&=D(?oY0^x9gmaT={At<$eemw6~N zk=UF_{ ziv)ae({=F?$0Rk)EIN|-L#Q>2RZnRYC!mv6&npQYzD0tYA!g_RMKbj@4wqcm` zu%bgl*+Wk7fOOZ>1kq2F6>*E1sy8+fsCu*A{7s*4)w3tb*&y%HULW0!A*@3xewMt@ zyPw<12%%!jC7&~n#N8ej1y-b2YOV!zT20Y=uc$dTgbSQErL5Rnm7AIR^D8O zD~cbtUxXAS=dsWOTN3+s>xfYo*9YY#Ks~wkU>_>jH#tpr=zeyXNhmFFH4!-K`)4$Z zYU=z$p(Ec>Ho`|{oifEfs*f1I+`YduZH7IHw~il-L7j9-mGl&T8aSR8P);JZc{GcX z_!-=@$r}W*y|bL$94$@nKJhYSLj@Nc?%9A` zubFnKUuPEAtpOc5&)zaB9P~Kqr=-Vch?6B%RRP@lBs3?gt7){;0krw@-L`d6d-Liy=PNp^kL2@7a7krO^rw@F^3gEhd6{UBtU=EoaSB-SVky-F zMI3iAPrB7WPe~86EN@xZx7W?xC@55>V3?f5u_9c66u1E~YQzlyJOk1fJ&om$takZS z+h`4}$JAaq?``cH6wWny6zJaU>Zzu$%QOzJ8N~^C{j^_w&s+RKsoABy?UGoVUUJk- zD5{>~#-Yo^Nm$GYG0n3sAx*MYu|6l0KUig1@L+NRPNCO3@sv&yw)<*-K0aI#}T!XWvW9N zLW6A71Kmbo>_+7|($UbGJ3rNX3_keeX}fOv2`>bjt+FWLNDWX-G9=4dTXgEQ+Z-Je$wLWx+{^Wl+QE9Bkot>qVGZj<~xYp4p5=K%eLavbwI(Q?G!lLiip zbSAJR%;vTgsAuq3yG!$DVtO2`rUMry^}6fC2cX9X_a-!?krG1ySxxG!Y>!1%?A+QXpM!Z+eb*hBgOI z#s>v98FrkwfbwuNUHhJVP3Q7-bsA(?r&T%a4PDp0j<913L4_5iBXrDgIrK|)1OoGj zq~qG3Tt7}mOq6b;&3({%2W5C`WK`yH=ODiX zFyrpC#~`zR`x?6qRJ_fBpV9ldwG6NfGT06Xgv1-~vm zswK~35Dh`VylbXrfCgJ4$=K-dFgoieUh%zp{}gT#?h$9mm?boi9igA(JACx?qPWks z+zs$n3{P`_ob6uT^A&c%DI#UmYFs>$8|D4I99wd7edYYDPaHf2Ro-iVmtifnnF94< z(sHhaT|nH%7$t4X#D|r|j$y)dan10fy_CQWJ4-d%qb^xT>-3YUlp&RU#^^&^*t=3i zMf2ww-7nk4C0sGK3Ai9L4jC(jxwacf4~18V8!0{cxM3dU;9-EUUt6~!`KL>k(((X* zXo~P8%Yo+e)oMcio@Ohd;ScF!n#wT0J?h9!>jgZ9npg@J?-F=w&NcSF)z`+P!sqbf zL+s}tW7^#DF3Jjf`D&vN;U*=Obg`+U4L5u59pGh)y4tcm6D@{75b|_%lPNhjmd95I z3pSco!5=m8l#MqsPCk(LbFw*-nAUyrPTmdg{3Fv{h=`L1B_6bf&OzS;r z(;KPz>sGTLpWs#?Hv#qy$BVTzhg_A(AWr7yjg|c16X1MbgJ$eak4XcM9>%aj>}M2I z>--6$*S1AhkcdIfiWXf_F4gpY5zHB&-uU20Vo`i>6<=i0mMB}{=nkq^jk%;0f$m7Y z9&UyE5S-Zvy{s^^J(-11G35kD^=<2r_5{*2D&;la8gyh?#J?!+$F!`!R>5_7jg(5h z4qZj9o!ptU7!)vNA9?|=vgcKX@;Q7lpUUnXl@G4Y2GJM%{upfp+Th!(w-9ieH%$a{ z&mBC(M0X21vZ6?~EMf`hnvg^aQ2UiNXs z{Dkh)_r%PyR}88d6&r`|wum%}kF78yk^6|-cbo4cKpO^#fv2e0Qtm_yM+a5%S_#Qj zQz;dB89S-k2JG#K)~B9RxXq$NLWv3V_?G37mF_5>%O5LMWtM4|-VE@lySYHVV+)6Z zM@LDu7`bS;zIdE$>-VwoG$(V-krpqDrA=Sc>nF%b0^Q0WQ>u88Xqy zu?D%t-%B1$k_7Z9tKeEK3q5MYS=r^>h~^Hk3h=uBA|1 z<10sJx(8P3HbgcgCS8}TQgK<#tLM1;d%c^2ZX}@7&8}qafs3k^=~yUJEu38O;>%J1Qw(AYeMf{d>e zGfrv}M>cC%Ia08@*r?zr{o-e9DMHr6{hd#M<(|^)(%End89goG#P&S%d}QiPYNV$7 zpi~LQ4VGJX;wVyPmOhE(dt63KYF4It9gcn%*xI~#nn_G!xTdU5`ysa+y5nl> zvGkQ_n$?Q!c?wdf(ZHM7kQyxulh!FE2W?yH5-um)t8C`sP4EwnEGKLi(sw|+#A@6! zZOR{g%!o;&iW(#R!EaYNWfQ;i%>vo@BtW2)k7Syqa$tymCBt(pk8&6PN(ok7wm_Th z!>c_ts&7sp{l|pOckxymnZQNMS1u4Srbh~hKuPp%=ZQ}$^@wL)cyu24M_=>l%c<#= z%tGgO+VKzl79DQ4Zu46Yu*rpPSAhRfy{r&$8Eivd5U*co@V?$3;r)0hf*VSyELU-$ zfr-Pp>T6BJ+I(*XGrgo&9_HVLe$CZxmBZT1X{4YQ;t^CWTy+TA4avPt;R%9z-TtQ^ z+4JLF=&o6J28N`J>tQ6ZG0^D2?n@;F_(}cEkA)3}4qj1>m5a0D--XN;u+l0k^WCjiqNgn+1MON#mgve zw$UMqYbfAEoF-4Gf9WKsAeMy?nF>@^sn*2j>{EKOO=qJWvSS@HcONyBTc|xvolKCb z=_h#Q%O_H`rCHBuC3S9hHvspL1p4TJbTx`_@6!QSUv4|3lW;m?-Ud>2Cgh+eq!hjl zRf!VXov#T@`#h8?U!nu2X^ zS)wpX#Uvj7rp}SY)K0gfv)9dd-PMx!sk?s|SU^wokpX@&rW)vJbWh$o!TH8#aBj4#LMFJi<--J zX_3>16pkD1HA(w`W}Q`BB{}BO!GtS8<`-FL5Vw6Tqf;%NjT{G&Sj0XaZ`hl+-4gl@ zvif%Nhkshh&|OJh1?<56K{||{R%)nJzrrC8^-ZJ!h|6io7rERpFaX;RfJ~6_yW_4> qUxDfjH9WR6RhdI962AP3Sr;h~4e4{~*21v4XyfmCoS1HWvi||kfw$-Y literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xalert.class.mq5 b/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xalert.class.mq5 new file mode 100644 index 0000000..7f15e32 --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xalert.class.mq5 @@ -0,0 +1,1575 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCAlert +// Description: provides all Alerts requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.base.class.mq5" + +// +// Class Definition ... + +class XSCAlert : public XSCBase +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructor ... + XSCAlert( + string prefix = "X-Alert", // Alerts Prefixe + bool enableAlerts = true, // Enable Alerts + bool logAlerts = true, // Log Alerts + bool terminalAlerts = false, // Terminal Alerts + bool mailAlerts = false, // Mail Alerts + bool pushAlerts = false // Push Alerts + ) + { + // + mPrefix = prefix; + mLogAlerts = logAlerts; + mMailAlerts = mailAlerts; + mPushAlerts = pushAlerts; + mEnableAlerts = enableAlerts; + mTerminalAlerts = terminalAlerts; + + // + // Normalize Prefix if Not Provided ... + if (!IsValid(mPrefix)) + { + mPrefix = GetTag(); + } + } + + // + // Deconstructor ... + ~XSCAlert() {} + + // + // Override ... + string GetTag() override + { + return GetSpecificToken(this); + } + + // + // Properties Getter(s) / Setter(s) ... + + // + string GetPrefix() + { + return mPrefix; + } + + // + void SetPrefix(string value) + { + mPrefix = value; + } + + // + bool GetLogAlerts() + { + return mLogAlerts; + } + + // + void SetLogAlerts(bool value) + { + mLogAlerts = value; + } + + // + bool GetEnableAlerts() + { + return mEnableAlerts; + } + + // + void SetEnableAlerts(bool value) + { + mEnableAlerts = value; + } + + // + bool GetPushAlerts() + { + return mPushAlerts; + } + + // + void SetPushAlerts(bool value) + { + mPushAlerts = value; + } + + // + bool GetMailAlerts() + { + return mMailAlerts; + } + + // + void SetMailAlerts(bool value) + { + mMailAlerts = value; + } + + // + bool GetTerminalAlerts() + { + return mTerminalAlerts; + } + + // + void SetTerminalAlerts(bool value) + { + mTerminalAlerts = value; + } + + // + // Tools Funtions ... + + // + // Alerts ... + + // + // Logging an Alert ... + void LogAlert(string message) + { + // + // Validate Args ... + if (!CanLogAlert()) + { + return; + } + + // + Log(message); + } + + // + // Terminal Alert ... + void TerminalAlert(string message) + { + // + // Validate Args ... + if (!CanTerminalAlert()) + { + return; + } + + // + // Prepare Message ... + message = PrepareMessage(message); + + // Send Terminal Alert ... + Alert(message); + } + + // + // Mail Alert ... + void MailAlert(string message) + { + // + // Validate Args ... + if (!CanMailAlert()) + { + return; + } + + // + // Send Mail Alert ... + SendMail(GetPrefix(), message); + } + + // + // Send Push Notification ... + void PushAlert(string message) + { + // + // Validate Args ... + if (!CanPushAlert()) + { + return; + } + + // + // Prepare Message ... + message = PrepareMessage(message); + + // + // Send Push Notification Alert ... + SendNotification(message); + } + + // + // Send an Alert by Handling all Different Specified + // type's of Alert's if they are Enabled ... + void Alert(string message) + { + // + // Handle Log, if Enabled ... + LogAlert(message); + + // + // Handle Mail if Enabled ... + MailAlert(message); + + // + // Handle Push if Enabled ... + PushAlert(message); + + // + // Handle Terminal if Enabled ... + TerminalAlert(message); + } + + // + // Logs ... + + // + // Log a Message ... + void Log(string message) + { + // + if (!CanLog()) + { + return; + } + + // + Print(GetPrefix(), " > ", message); + } + void Log(string tag, string message) + { + // + if (!CanLog()) + { + return; + } + + // + Print(GetPrefix(), "_", tag, " > ", message); + } + void LogEmpty() + { + // + if (!CanLog()) + { + return; + } + + // + Print(" "); + } + + // + // Log Specific Array ... + template + void LogArray( + T &array[], // Array to Log + string label = NULL // Array Label + ) + { + // + if (!CanLog()) + { + return; + } + + // + Print(GetPrefix(), ">", (IsValid(label) ? label : "")); + ArrayPrint(array); + } + + // + // Error ... + + // + // Log an Error ... + void LogError( + int error = -1 // Specific Error, if it's equal to -1, use Last Error ... + ) + { + // + if (!CanLog()) + { + return; + } + + // + if (error <= -1) + { + error = GetLastError(); + } + + // + string errorMsg = GetErrorDescription(error); + + // + Log("Error: " + errorMsg); + } + + // + // Retrieve Specified Error Code Description ... + string GetErrorDescription(int err_code) + { + // + string result = ""; + + // + switch (err_code) + { + // + //--- Constant Description + + // + case ERR_SUCCESS: + result = "The operation completed successfully"; + break; + + // + case ERR_INTERNAL_ERROR: + result = "Unexpected internal error"; + break; + + // + case ERR_WRONG_INTERNAL_PARAMETER: + result = "Wrong parameter in the inner call of the client terminal function"; + break; + + // + case ERR_INVALID_PARAMETER: + result = "Wrong parameter when calling the system function"; + break; + + // + case ERR_NOT_ENOUGH_MEMORY: + result = "Not enough memory to perform the system function"; + break; + + // + case ERR_STRUCT_WITHOBJECTS_ORCLASS: + result = "The structure contains objects of strings and/or dynamic arrays and/or structure of such objects and/or classes"; + break; + + // + case ERR_INVALID_ARRAY: + result = "Array of a wrong type, wrong size, or a damaged object of a dynamic array"; + break; + + // + case ERR_ARRAY_RESIZE_ERROR: + result = "Not enough memory for the relocation of an array, or an attempt to change the size of a static array"; + break; + + // + case ERR_STRING_RESIZE_ERROR: + result = "Not enough memory for the relocation of string"; + break; + + // + case ERR_NOTINITIALIZED_STRING: + result = "Not initialized string"; + break; + + // + case ERR_INVALID_DATETIME: + result = "Invalid date and/or time"; + break; + + // + case ERR_ARRAY_BAD_SIZE: + result = "Requested array size exceeds 2 GB"; + break; + + // + case ERR_INVALID_POINTER: + result = "Wrong pointer"; + break; + + // + case ERR_INVALID_POINTER_TYPE: + result = "Wrong type of pointer"; + break; + + // + case ERR_FUNCTION_NOT_ALLOWED: + result = "System function is not allowed to call"; + break; + + // + //--- Charts + + // + case ERR_CHART_WRONG_ID: + result = "Wrong chart ID"; + break; + + // + case ERR_CHART_NO_REPLY: + result = "Chart does not respond"; + break; + + // + case ERR_CHART_NOT_FOUND: + result = "Chart not found"; + break; + + // + case ERR_CHART_NO_EXPERT: + result = "No Expert Advisor in the chart that could handle the event"; + break; + + // + case ERR_CHART_CANNOT_OPEN: + result = "Chart opening error"; + break; + + // + case ERR_CHART_CANNOT_CHANGE: + result = "Failed to change chart symbol and period"; + break; + + // + case ERR_CHART_CANNOT_CREATE_TIMER: + result = "Failed to create timer"; + break; + + // + case ERR_CHART_WRONG_PROPERTY: + result = "Wrong chart property ID"; + break; + + // + case ERR_CHART_SCREENSHOT_FAILED: + result = "Error creating screenshots"; + break; + + // + case ERR_CHART_NAVIGATE_FAILED: + result = "Error navigating through chart"; + break; + + // + case ERR_CHART_TEMPLATE_FAILED: + result = "Error applying template"; + break; + + // + case ERR_CHART_WINDOW_NOT_FOUND: + result = "Subwindow containing the indicator was not found"; + break; + + // + case ERR_CHART_INDICATOR_CANNOT_ADD: + result = "Error adding an indicator to chart"; + break; + + // + case ERR_CHART_INDICATOR_CANNOT_DEL: + result = "Error deleting an indicator from the chart"; + break; + + // + case ERR_CHART_INDICATOR_NOT_FOUND: + result = "Indicator not found on the specified chart"; + break; + + // + //--- Graphical Objects + case ERR_OBJECT_ERROR: + result = "Error working with a graphical object"; + break; + + // + case ERR_OBJECT_NOT_FOUND: + result = "Graphical object was not found"; + break; + + // + case ERR_OBJECT_WRONG_PROPERTY: + result = "Wrong ID of a graphical object property"; + break; + + // + case ERR_OBJECT_GETDATE_FAILED: + result = "Unable to get date corresponding to the value"; + break; + + // + case ERR_OBJECT_GETVALUE_FAILED: + result = "Unable to get value corresponding to the date"; + break; + + // + //--- MarketInfo + + // + case ERR_MARKET_UNKNOWN_SYMBOL: + result = "Unknown symbol"; + break; + + // + case ERR_MARKET_NOT_SELECTED: + result = "Symbol is not selected in MarketWatch"; + break; + + // + case ERR_MARKET_WRONG_PROPERTY: + result = "Wrong identifier of a symbol property"; + break; + + // + case ERR_MARKET_LASTTIME_UNKNOWN: + result = "Time of the last tick is not known (no ticks)"; + break; + + // + case ERR_MARKET_SELECT_ERROR: + result = "Error adding or deleting a symbol in MarketWatch"; + break; + + // + //--- History Access + + // + case ERR_HISTORY_NOT_FOUND: + result = "Requested history not found"; + break; + + // + case ERR_HISTORY_WRONG_PROPERTY: + result = "Wrong ID of the history property"; + break; + + // + //--- Global_Variables + + // + case ERR_GLOBALVARIABLE_NOT_FOUND: + result = "Global variable of the client terminal is not found"; + break; + + // + case ERR_GLOBALVARIABLE_EXISTS: + result = "Global variable of the client terminal with the same name already exists"; + break; + + // + case ERR_MAIL_SEND_FAILED: + result = "Email sending failed"; + break; + + // + case ERR_PLAY_SOUND_FAILED: + result = "Sound playing failed"; + break; + + // + case ERR_MQL5_WRONG_PROPERTY: + result = "Wrong identifier of the program property"; + break; + + // + case ERR_TERMINAL_WRONG_PROPERTY: + result = "Wrong identifier of the terminal property"; + break; + + // + case ERR_FTP_SEND_FAILED: + result = "File sending via ftp failed"; + break; + + // + case ERR_NOTIFICATION_SEND_FAILED: + result = "Error in sending notification"; + break; + + // + //--- Custom Indicator Buffers + + // + case ERR_BUFFERS_NO_MEMORY: + result = "Not enough memory for the distribution of indicator buffers"; + break; + + // + case ERR_BUFFERS_WRONG_INDEX: + result = "Wrong indicator buffer index"; + break; + + // + //--- Custom Indicator Properties + + // + case ERR_CUSTOM_WRONG_PROPERTY: + result = "Wrong ID of the custom indicator property"; + break; + + // + //--- Account + + // + case ERR_ACCOUNT_WRONG_PROPERTY: + result = "Wrong account property ID"; + break; + + // + case ERR_TRADE_WRONG_PROPERTY: + result = "Wrong trade property ID"; + break; + + // + case ERR_TRADE_DISABLED: + result = "Trading by Expert Advisors prohibited"; + break; + + // + case ERR_TRADE_POSITION_NOT_FOUND: + result = "Position not found"; + break; + + // + case ERR_TRADE_ORDER_NOT_FOUND: + result = "Order not found"; + break; + + // + case ERR_TRADE_DEAL_NOT_FOUND: + result = "Deal not found"; + break; + + // + case ERR_TRADE_SEND_FAILED: + result = "Trade request sending failed"; + break; + + // + //--- Indicators + + // + case ERR_INDICATOR_UNKNOWN_SYMBOL: + result = "Unknown symbol"; + break; + + // + case ERR_INDICATOR_CANNOT_CREATE: + result = "Indicator cannot be created"; + break; + + // + case ERR_INDICATOR_NO_MEMORY: + result = "Not enough memory to add the indicator"; + break; + + // + case ERR_INDICATOR_CANNOT_APPLY: + result = "The indicator cannot be applied to another indicator"; + break; + + // + case ERR_INDICATOR_CANNOT_ADD: + result = "Error applying an indicator to chart"; + break; + + // + case ERR_INDICATOR_DATA_NOT_FOUND: + result = "Requested data not found"; + break; + + // + case ERR_INDICATOR_WRONG_HANDLE: + result = "Wrong indicator handle"; + break; + + // + case ERR_INDICATOR_WRONG_PARAMETERS: + result = "Wrong number of parameters when creating an indicator"; + break; + + // + case ERR_INDICATOR_PARAMETERS_MISSING: + result = "No parameters when creating an indicator"; + break; + + // + case ERR_INDICATOR_CUSTOM_NAME: + result = "The first parameter in the array must be the name of the custom indicator"; + break; + + // + case ERR_INDICATOR_PARAMETER_TYPE: + result = "Invalid parameter type in the array when creating an indicator"; + break; + + // + case ERR_INDICATOR_WRONG_INDEX: + result = "Wrong index of the requested indicator buffer"; + break; + + // + //--- Depth of Market + + // + case ERR_BOOKS_CANNOT_ADD: + result = "Depth Of Market can not be added"; + break; + + // + case ERR_BOOKS_CANNOT_DELETE: + result = "Depth Of Market can not be removed"; + break; + + // + case ERR_BOOKS_CANNOT_GET: + result = "The data from Depth Of Market can not be obtained"; + break; + + // + case ERR_BOOKS_CANNOT_SUBSCRIBE: + result = "Error in subscribing to receive new data from Depth Of Market"; + break; + + // + //--- File Operations + + // + case ERR_TOO_MANY_FILES: + result = "More than 64 files cannot be opened at the same time"; + break; + + // + case ERR_WRONG_FILENAME: + result = "Invalid file name"; + break; + + // + case ERR_TOO_LONG_FILENAME: + result = "Too long file name"; + break; + + // + case ERR_CANNOT_OPEN_FILE: + result = "File opening error"; + break; + + // + case ERR_FILE_CACHEBUFFER_ERROR: + result = "Not enough memory for cache to read"; + break; + + // + case ERR_CANNOT_DELETE_FILE: + result = "File deleting error"; + break; + + // + case ERR_INVALID_FILEHANDLE: + result = "A file with this handle was closed, or was not opening at all"; + break; + + // + case ERR_WRONG_FILEHANDLE: + result = "Wrong file handle"; + break; + + // + case ERR_FILE_NOTTOWRITE: + result = "The file must be opened for writing"; + break; + + // + case ERR_FILE_NOTTOREAD: + result = "The file must be opened for reading"; + break; + + // + case ERR_FILE_NOTBIN: + result = "The file must be opened as a binary one"; + break; + + // + case ERR_FILE_NOTTXT: + result = "The file must be opened as a text"; + break; + + // + case ERR_FILE_NOTTXTORCSV: + result = "The file must be opened as a text or CSV"; + break; + + // + case ERR_FILE_NOTCSV: + result = "The file must be opened as CSV"; + break; + + // + case ERR_FILE_READERROR: + result = "File reading error"; + break; + + // + case ERR_FILE_BINSTRINGSIZE: + result = "String size must be specified, because the file is opened as binary"; + break; + + // + case ERR_INCOMPATIBLE_FILE: + result = "A text file must be for string arrays, for other arrays - binary"; + break; + + // + case ERR_FILE_IS_DIRECTORY: + result = "This is not a file, this is a directory"; + break; + + // + case ERR_FILE_NOT_EXIST: + result = "File does not exist"; + break; + + // + case ERR_FILE_CANNOT_REWRITE: + result = "File can not be rewritten"; + break; + + // + case ERR_WRONG_DIRECTORYNAME: + result = "Wrong directory name"; + break; + + // + case ERR_DIRECTORY_NOT_EXIST: + result = "Directory does not exist"; + break; + + // + case ERR_FILE_ISNOT_DIRECTORY: + result = "This is a file, not a directory"; + break; + + // + case ERR_CANNOT_DELETE_DIRECTORY: + result = "The directory cannot be removed"; + break; + + // + case ERR_CANNOT_CLEAN_DIRECTORY: + result = "Failed to clear the directory (probably one or more files are blocked and removal operation failed)"; + break; + + // + case ERR_FILE_WRITEERROR: + result = "Failed to write a resource to a file"; + break; + + // + //--- String Casting + + // + case ERR_NO_STRING_DATE: + result = "No date in the string"; + break; + + // + case ERR_WRONG_STRING_DATE: + result = "Wrong date in the string"; + break; + + // + case ERR_WRONG_STRING_TIME: + result = "Wrong time in the string"; + break; + + // + case ERR_STRING_TIME_ERROR: + result = "Error converting string to date"; + break; + + // + case ERR_STRING_OUT_OF_MEMORY: + result = "Not enough memory for the string"; + break; + + // + case ERR_STRING_SMALL_LEN: + result = "The string length is less than expected"; + break; + + // + case ERR_STRING_TOO_BIGNUMBER: + result = "Too large number, more than ULONG_MAX"; + break; + + // + case ERR_WRONG_FORMATSTRING: + result = "Invalid format string"; + break; + + // + case ERR_TOO_MANY_FORMATTERS: + result = "Amount of format specifiers more than the parameters"; + break; + + // + case ERR_TOO_MANY_PARAMETERS: + result = "Amount of parameters more than the format specifiers"; + break; + + // + case ERR_WRONG_STRING_PARAMETER: + result = "Damaged parameter of string type"; + break; + + // + case ERR_STRINGPOS_OUTOFRANGE: + result = "Position outside the string"; + break; + + // + case ERR_STRING_ZEROADDED: + result = "0 added to the string end, a useless operation"; + break; + + // + case ERR_STRING_UNKNOWNTYPE: + result = "Unknown data type when converting to a string"; + break; + + // + case ERR_WRONG_STRING_OBJECT: + result = "Damaged string object"; + break; + + // + //--- Operations with Arrays + + // + case ERR_INCOMPATIBLE_ARRAYS: + result = "Copying incompatible arrays. String array can be copied only to a string array, and a numeric array - in numeric array only"; + break; + + // + case ERR_SMALL_ASSERIES_ARRAY: + result = "The receiving array is declared as AS_SERIES, and it is of insufficient size"; + break; + + // + case ERR_SMALL_ARRAY: + result = "Too small array, the starting position is outside the array"; + break; + + // + case ERR_ZEROSIZE_ARRAY: + result = "An array of zero length"; + break; + + // + case ERR_NUMBER_ARRAYS_ONLY: + result = "Must be a numeric array"; + break; + + // + case ERR_ONEDIM_ARRAYS_ONLY: + result = "Must be a one-dimensional array"; + break; + + // + case ERR_SERIES_ARRAY: + result = "Timeseries cannot be used"; + break; + + // + case ERR_DOUBLE_ARRAY_ONLY: + result = "Must be an array of type double"; + break; + + // + case ERR_FLOAT_ARRAY_ONLY: + result = "Must be an array of type float"; + break; + + // + case ERR_LONG_ARRAY_ONLY: + result = "Must be an array of type long"; + break; + + // + case ERR_INT_ARRAY_ONLY: + result = "Must be an array of type int"; + break; + + // + case ERR_SHORT_ARRAY_ONLY: + result = "Must be an array of type short"; + break; + + // + case ERR_CHAR_ARRAY_ONLY: + result = "Must be an array of type char"; + break; + + // + //--- Operations with OpenCL + + // + case ERR_OPENCL_NOT_SUPPORTED: + result = "OpenCL functions are not supported on this computer"; + break; + + // + case ERR_OPENCL_INTERNAL: + result = "Internal error occurred when running OpenCL"; + break; + + // + case ERR_OPENCL_INVALID_HANDLE: + result = "Invalid OpenCL handle"; + break; + + // + case ERR_OPENCL_CONTEXT_CREATE: + result = "Error creating the OpenCL context"; + break; + + // + case ERR_OPENCL_QUEUE_CREATE: + result = "Failed to create a run queue in OpenCL"; + break; + + // + case ERR_OPENCL_PROGRAM_CREATE: + result = "Error occurred when compiling an OpenCL program"; + break; + + // + case ERR_OPENCL_TOO_LONG_KERNEL_NAME: + result = "Too long kernel name (OpenCL kernel)"; + break; + + // + case ERR_OPENCL_KERNEL_CREATE: + result = "Error creating an OpenCL kernel"; + break; + + // + case ERR_OPENCL_SET_KERNEL_PARAMETER: + result = "Error occurred when setting parameters for the OpenCL kernel"; + break; + + // + case ERR_OPENCL_EXECUTE: + result = "OpenCL program runtime error"; + break; + + // + case ERR_OPENCL_WRONG_BUFFER_SIZE: + result = "Invalid size of the OpenCL buffer"; + break; + + // + case ERR_OPENCL_WRONG_BUFFER_OFFSET: + result = "Invalid offset in the OpenCL buffer"; + break; + + // + case ERR_OPENCL_BUFFER_CREATE: + result = "Failed to create and OpenCL buffer"; + break; + + // + //--- User-Defined Errors + default: + result = "UNKNOWN Erro ..."; + break; + } + + // + return result; + } + + // + // Retrieve Specified Error Code Description ... + string GetTradeServerReturnCodeDescription(int return_code) + { + // + string result = ""; + + // + switch (return_code) + { + // + case TRADE_RETCODE_REQUOTE: + result = "Requote"; + break; + + // + case TRADE_RETCODE_REJECT: + result = "Request rejected"; + break; + + // + case TRADE_RETCODE_CANCEL: + result = "Request canceled by trader"; + break; + + // + case TRADE_RETCODE_PLACED: + result = "Order placed"; + break; + + // + case TRADE_RETCODE_DONE: + result = "Request completed"; + break; + + // + case TRADE_RETCODE_DONE_PARTIAL: + result = "Only part of the request was completed"; + break; + + // + case TRADE_RETCODE_ERROR: + result = "Request processing error"; + break; + + // + case TRADE_RETCODE_TIMEOUT: + result = "Request canceled by timeout"; + break; + + // + case TRADE_RETCODE_INVALID: + result = "Invalid request"; + break; + + // + case TRADE_RETCODE_INVALID_VOLUME: + result = "Invalid volume in the request"; + break; + + // + case TRADE_RETCODE_INVALID_PRICE: + result = "Invalid price in the request"; + break; + + // + case TRADE_RETCODE_INVALID_STOPS: + result = "Invalid stops in the request"; + break; + + // + case TRADE_RETCODE_TRADE_DISABLED: + result = "Trade is disabled"; + break; + + // + case TRADE_RETCODE_MARKET_CLOSED: + result = "Market is closed"; + break; + + // + case TRADE_RETCODE_NO_MONEY: + result = "There is not enough money to complete the request"; + break; + + // + case TRADE_RETCODE_PRICE_CHANGED: + result = "Prices changed"; + break; + + // + case TRADE_RETCODE_PRICE_OFF: + result = "There are no quotes to process the request"; + break; + + // + case TRADE_RETCODE_INVALID_EXPIRATION: + result = "Invalid order expiration date in the request"; + break; + + // + case TRADE_RETCODE_ORDER_CHANGED: + result = "Order state changed"; + break; + + // + case TRADE_RETCODE_TOO_MANY_REQUESTS: + result = "Too frequent requests"; + break; + + // + case TRADE_RETCODE_NO_CHANGES: + result = "No changes in request"; + break; + + // + case TRADE_RETCODE_SERVER_DISABLES_AT: + result = "Autotrading disabled by server"; + break; + + // + case TRADE_RETCODE_CLIENT_DISABLES_AT: + result = "Autotrading disabled by client terminal"; + break; + + // + case TRADE_RETCODE_LOCKED: + result = "Request locked for processing"; + break; + + // + case TRADE_RETCODE_FROZEN: + result = "Order or position frozen"; + break; + + // + case TRADE_RETCODE_INVALID_FILL: + result = "Invalid order filling type"; + break; + + // + case TRADE_RETCODE_CONNECTION: + result = "No connection with the trade server"; + break; + + // + case TRADE_RETCODE_ONLY_REAL: + result = "Operation is allowed only for live accounts"; + break; + + // + case TRADE_RETCODE_LIMIT_ORDERS: + result = "The number of pending orders has reached the limit"; + break; + + // + case TRADE_RETCODE_LIMIT_VOLUME: + result = "The volume of orders and positions for the symbol has reached the limit"; + break; + + // + default: + result = "Invalid return code of the trade server"; + break; + } + + // + return result; + } + + // + // Protected ... +protected: + // + // Private ... + + // + bool CanLog() + { + return mLogAlerts; + } + + // + bool CanLogAlert() + { + // + bool result = GetEnableAlerts() && GetLogAlerts(); + + // + return result; + } + + // + bool CanTerminalAlert() + { + // + bool result = GetEnableAlerts() && GetTerminalAlerts(); + + // + return result; + } + + // + bool CanMailAlert() + { + // + bool result = GetEnableAlerts() && GetMailAlerts(); + + // + return result; + } + + // + bool CanPushAlert() + { + // + bool result = GetEnableAlerts() && GetPushAlerts(); + + // + return result; + } + +private: + // + // Props ... + string mPrefix; // Alerts Prefixe + bool mEnableAlerts; // Enable Alerts + bool mLogAlerts; // Log Alerts + bool mTerminalAlerts; // Terminal Alerts + bool mMailAlerts; // Mail Alerts + bool mPushAlerts; // Push Alerts + + // + // Tools ... + + // + // Clear Escape String and + // Attach Alert Prefix to Message ... + string PrepareMessage(string message) + { + // + StringReplace(message, "\n", " | "); + + // + StringConcatenate(message, GetPrefix(), " > ", message); + + // + return message; + } +}; + +// +// a Base Class by Support Alert ... +class XSCBaseAlert : public XSCBase +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructor(s) ... + void XSCBaseAlert() + { + // + // Instance Alert ... + mAlert = new XSCAlert(); + } + + // + // Deconstructors ... + void ~XSCBaseAlert() + { + // + delete mAlert; + } + + // + // Alert Handler Functions ... + + // + // Alert Functions Getter(s) / Setters(s) ... + + // + string GetAlertPrefix() + { + return mAlert.GetPrefix(); + } + + // + void SetAlertPrefix(string value) + { + mAlert.SetPrefix(value); + } + + // + bool GetAlertLogAlerts() + { + return mAlert.GetLogAlerts(); + } + + // + void SetAlertLogAlerts(bool value) + { + mAlert.SetLogAlerts(value); + } + + // + bool GetAlertEnableAlerts() + { + return mAlert.GetEnableAlerts(); + } + + // + void SetAlertEnableAlerts(bool value) + { + mAlert.SetEnableAlerts(value); + } + + // + bool GetAlertPushAlerts() + { + return mAlert.GetPushAlerts(); + } + + // + void SetAlertPushAlerts(bool value) + { + mAlert.SetPushAlerts(value); + } + + // + bool GetAlertMailAlerts() + { + return mAlert.GetMailAlerts(); + } + + // + void SetAlertMailAlerts(bool value) + { + mAlert.SetMailAlerts(value); + } + + // + bool GetAlertTerminalAlerts() + { + return mAlert.GetTerminalAlerts(); + } + + // + void SetAlertTerminalAlerts(bool value) + { + mAlert.SetTerminalAlerts(value); + } + + // + // Alert Actions ... + + // + // Logging an Alert ... + void LogAlert(string message) + { + mAlert.LogAlert(message); + } + + // + // Terminal Alert ... + void TerminalAlert(string message) + { + mAlert.TerminalAlert(message); + } + + // + // Mail Alert ... + void MailAlert(string message) + { + mAlert.MailAlert(message); + } + + // + // Send Push Notification ... + void PushAlert(string message) + { + mAlert.PushAlert(message); + } + + // + // Send an Alert by Handling all Different Specified + // type's of Alert's if they are Enabled ... + void Alert(string message) + { + mAlert.Alert(message); + } + + // + // Logs ... + + // + // Log a Message ... + void Log(string message) + { + mAlert.Log(message); + } + void Log(string tag, string message) + { + mAlert.Log(tag, message); + } + void LogEmpty() + { + mAlert.LogEmpty(); + } + + // + // Log Specific Array ... + template + void LogArray( + T &array[], // Array to Log + string label = NULL // Array Label + ) + { + mAlert.LogArray(array, label); + } + + // + // Error ... + + // + // Log an Error ... + void LogError( + int error = -1 // Specific Error, if it's equal to -1, use Last Error ... + ) + { + mAlert.LogError(error); + } + + // + // Retrieve Specified Error Code Description ... + string GetErrorDescription(int err_code) + { + return mAlert.GetErrorDescription(err_code); + } + + // + // Retrieve Specified Error Code Description ... + string GetTradeServerReturnCodeDescription(int return_code) + { + return mAlert.GetTradeServerReturnCodeDescription(return_code); + } + + // + // Protected ... +protected: + // + // Alert ... + XSCAlert *mAlert; + + // + // Private ... +private: +}; + +// \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xdata-collector.class.ex5 b/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xdata-collector.class.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..9036de9139ba9cb64bba8332af97a4863a9bc873 GIT binary patch literal 6550 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 m_(ZH^sy+D4PeLU*xnPDbIR8%Y8ft41@u;emc +class XSCDataCollector : public XSCBase +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructors ... + void XSCDataCollector( + string path = NULL, // Base Folder for Data Store + string fileName = NULL // File Name for Data Store + ) + { + // + if (!IsValid(path)) + { + path = GetType(); + } + + // + if (!IsValid(fileName)) + { + fileName = GetType() + ".txt"; + } + + // + Path(path); + FileName(fileName); + } + + // + // Deconstructor ... + void ~XSCDataCollector() {} + + // + // Properties ... + + // + bool Path(string value) + { + // + bool result = false; + + // + result = IsValid(value); + if (!result) + { + return result; + } + + // + result = value != mPath; + if (!result) + { + return result; + } + + // + mPath = value; + + // + return result; + } + + // + string Path() + { + return mPath; + } + + // + bool FileName(string value) + { + // + bool result = false; + + // + result = IsValid(value); + if (!result) + { + return result; + } + + // + result = value != mFileName; + if (!result) + { + return result; + } + + // + mFileName = value; + + // + return result; + } + + // + string FileName() + { + return mFileName; + } + + // + // Tools ... + + // + // Clear Exists Collected Data ... + void Clear() + { + // + ResetLastError(); + + // + string dataStorePath = GetStorePath(); + + // + // Check Data Store Exists or not ... + bool isExists = FileIsExist(dataStorePath); + if (!isExists) + { + return; + } + + // + FileDelete(dataStorePath); + } + + // + // Collect All Stored Items ... + int Collect( + T &items[] // Hold Result + ) + { + // + int result = 0; + + // + Clean(items); + + // + // Reading Store Whole Content ... + + // + string storePath = GetStorePath(); + int mFileHandler = FileOpen( + storePath, + FILE_READ | FILE_TXT); + result = mFileHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // Parse Store Content and Read Data ... + while (!FileIsEnding(mFileHandler)) + { + // + // Each Line Represent One Model ... + string content = FileReadString(mFileHandler); + + // + T iItem; + bool isValid = iItem.ParseModel(content); + if (isValid) + { + // + AddRef( + iItem, + items + // + ); + } + } + + // + // Close File ... + FileClose(mFileHandler); + + // + result = ArraySize(items); + + // + return result; + } + + // + // Add Item ... + bool Add( + T &item // Item to Store + ) + { + // + bool result = false; + + // + result = item.IsModelValid(); + if (!result) + { + return result; + } + + // + string content = item.ToModelString(); + result = IsValid(content); + if (!result) + { + return result; + } + + // + string storePath = GetStorePath(); + int mFileHandler = FileOpen( + storePath, + FILE_READ | FILE_WRITE | FILE_TXT); + result = mFileHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + FileSeek(mFileHandler, 0, SEEK_END); + FileWrite(mFileHandler, content); + FileFlush(mFileHandler); + FileClose(mFileHandler); + + // + return result; + } + + // + // Add Item ... + bool Add( + string content // Content + ) + { + // + bool result = false; + + // + result = IsValid(content); + if (!result) + { + return result; + } + + // + string storePath = GetStorePath(); + int mFileHandler = FileOpen( + storePath, + FILE_READ | FILE_WRITE | FILE_TXT); + result = mFileHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + FileSeek(mFileHandler, 0, SEEK_END); + FileWrite(mFileHandler, content); + FileFlush(mFileHandler); + FileClose(mFileHandler); + + // + return result; + } + + // + // Add Items ... + int Add( + T &items[] // Items to Add ... + ) + { + // + int result = 0; + + // + int itemsCount = ArraySize(items); + if (itemsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < itemsCount; i++) + { + // + T iItem = items[i]; + + // + if (!iItem.IsModelValid()) + { + continue; + } + + // + bool isAdded = Add(iItem); + if (isAdded) + { + result++; + } + } + + // + return result; + } + + // + // Remove Item ... + bool Remove( + T &item // Item to Remove + ) + { + // + bool result = false; + + // + result = item.IsModelValid(); + if (!result) + { + return result; + } + + // + T items[]; + int itemsCount = Collect(items); + if (itemsCount <= 0) + { + return result; + } + + // + int itemIndex = item.FindIndex(items); + result = ArrayRemove( + items, + itemIndex, + 1); + if (!result) + { + return result; + } + + // + Clear(); + + // + int itemsAdded = Add(items); + + // + result = itemsAdded == ArraySize(items); + + // + return result; + } + + // + // Protected ... +protected: + // + // Tools ... + + // + // Retrieve Type of Class as String ... + string GetType() + { + // + string mType = (string) typename(T); + + // + string result = mType; + + // + string parts[]; + int partsCount = SplitContent( + parts, + result, + " " + // + ); + if (partsCount <= 0) + { + // + result = mType; + return result; + } + + // + bool hasLastPart = GetLastItem( + result, + parts + // + ); + if (!hasLastPart) + { + // + result = mType; + return result; + } + + // + return result; + } + + // + // Pricate ... +private: + // + // Props ... + + // + string mPath; // Path + string mFileName; // Data Store File Name + + // + // Tools ... + + // + // Generate Full File Path ... + string GetFilePath(string fileName) + { + // + string result = ""; + + // + result = + // + Path() + "\\" + fileName + // + ; + + // + return result; + } + + // + // Retrieve Data Store File Address ... + string GetStorePath() + { + // + string result = NULL; + + // + result = GetFilePath(mFileName); + + // + return result; + } +}; + +// \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xea.class.ex5 b/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xea.class.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..7cb65ed2ba2dca4ff1f3ad85c0dec6b80e6cb25e GIT binary patch literal 10716 zcmdUTQ*U2$ zk7DP46>tJ@0_gsk+kYADzx99XHu*2zwEyb!|F_crxl0TH+JD`q|DTip4{VeA84rWF zrMoyvFubjCtC9s(jewkU9~QYxM?I4nKFFe<0}%@yyE+u|U2huSqLb#YjPpBRM>5mb zN3*&+3VbYuQw*ph@oFw79rDp2)IqDhehy7nyP?FGvdp*bG6v;yql7s-uQf{24dkMf z!y*(gU(oJh&SiPt7O)=#mc7WtY0|IH-JxWCZbi>c9Cyx|q^ITNA*y}o6HPmaK5kZKPZe6; zWsoyhCpc0dD&HC0L%~}VBx5IAS&{<&M$QJRzKx+IxwQS%57*PO98>2oW-HbG`cxq z_eepHCfBwb@9TcMs+RH=<8{2RN+HOh#I9Sgb?TdZcFoWNN4nzffvZ|A?Z{HuS6Wg33JnNu8SfG^;sGGpjZ2d+ZF0Zo#$dV#u*T5kYftL*Oh{#juFV>MX^&jb`F}@PB<%};##d5lJ{8^3q4PCx?|JtY%q>olE zNd4Q6!-JQTLYyK4&nD%2o}U4-JG@wOAMM9&Lbb831W5cd4!xoVu>$5-ev9`YVeDiL zm2|scm;}UpeH+Zi_+p9Fy^~mI@}754F3ZdwwJNjPx&m*>J2_=6nG!2v{)ruf7G_iWNugPuy%bXF!4!;F1-%UXE@&|hSqIK<7<{o? z%LywILK2n8Srliccjs*=29+EWmEd2~P7U8Sl>21o-e!bbX1kRklIHe>vY5%Xmy+Mf z7V5;Cvc{%=d3Dn88`J%VUeFDDlDckx3gHM9bm<)f#gQHO6L%Nt8Ehm0ltCltT~wNL zhmv8mv+}v1$U?J|E!j5OaInz?NGy#YmE{#9dFT!BL=Pi39!88(P0j-P4--e}C4TzN z_X!s8u||<=cufmYyPNFtbUz%VQV~2-?iv>*@w{}#|iVN>Kyz;CQdb*iv$YhlUWByr%Oa_l5-(BZvkAWiY$jq zPAVV|KMSqPhLSZSq%o=-r~$3sOTSqjcLD>ZU_$@AMqY}|aS6jirqC=m^llu4?)N~E zE4T)g202Qlult&cGRt%IGBGOdU`SB#%2_oLOw%9Q&A165Mu3A~B_ktxEIF3ylwR3H zq-AZds_Sj66Jv^F^`3&Z(1n@zR0x7T<1e_TqSeNNQ+4u?d)ZAv;xUpi`Ugm}VBPir zAI%J3TEj0g+)S>z53uE?UGUko!cUy)tryjxxN0PP(jye4@ktHo@_BT-}ulBpN|^EThMGhL@8 zXkcgkMI4YPT2`zrx!wNvGisC9nD35sS-%fQzS5yXY( z9jwB-@m&y>!Cq}_6t<^T(Ze%Ui8f1RkK^O@q;SVPiU0I*5 z43Q;(OD33me}vsFC(7CS>6qyIa&Ovh22~qzoDBTADo%6K=N4OXeke>M)VBJ-dDK@4 zjDbelj-fV)JKLzgj1Se7LtYFAP4obOQIPAD9ctTQJz*_ab_%@gWqFEh>eTb6 zVS5Z6t9xwicz`~QsIY?;t0t7SC{{b7D76cQW*(1xp=8wHZ!5uU+BLpWU3aPFXIj;p ztoZTCXWVbr5w~tVg_XXRr!atn4u7w!HVt{FWHno-m(RUExjdm=EWSmB2Pl<_H__e6 zT;aP!+XsQZ)*gcj{PP@Lm4HSWEq!jN#d%L^m%#Q?D0?1x)bLavG#~w` zr^!7*1!yiQ5u_FFhiN=UfgmR!*cwdlxwa2kX2H8@b@z2A%^`V_lLio`^W)$&aB00` znxJo54ZCRg@LI%GSwKq&S0-?Cgq|amYl0{-?$HQ95w@?x8LYv}S9t0PZxrTgrE8n# zW2nS$FAQxX3tSRK z@=Gg{IZ1TjnakV{BHI!a8tBM2aci0AHnZ`RTHqB@li>=T0?uSuA$( z8u#E{dW(<--8(+6a{dxu#_H#51Tvo_GkYbB+EisP=PIDG=#x)Noq)QQPvG)!ZM#pt z#-QwNkiJdGb;K)z_Xn1hPc`o(+u0hlr@{w2g3K*7X08H_R&zlR6wFxsw z#RfI(9yIh1du|AiZ`)~$VamEtR3Q!um#(DpZ%8pn zQXgKoS<24$I^iAVIFiE9^e~})l*8qK)YkhlX#LFZqUwqOl3HF7gFim%?e?!FIWyQ| zINJ(kAv+kLnE96P!pD^6WCz)`9{XL-sru3JDk>eSr8GfB7LU~1jPgR9r{A+UFx%}G zSGv>u5bW(X_^g77|awv>2HKlFdEM?R!)~?tS03;#d!pDm-LaR(A4f zw6q?+!j%Zr{0`N}fxCG>YLcOc3_xD4;PciM`svj(F(mdxhNI&E$OYt~@D0(X7wZLP zWtC_8n%g!rS2GFS*0dfsT`H4MkUF|qo>OPYazJqkR*)xANJ|Nw(xOfkQ|>^d)rh9)WiT!H;C? zOs@w{RM=9t8h!9}({iK-lhxj}1Snf*h8WX&5t~Vclx4h+?GYV>VDvkSz{B&1m{vgm z;BZ-In(BLNenGu%-TJ{p_nXnRq1>JcSf&%+iHQNqkCUf7fxmg?6;ts4wr(WUr2Raz zk;>4tiiu;pTy!u=MdOUE?t(zMox5Hl(pG?1s+JGNsLk`I|m4rkdCZQem;aIfXhoZ92Dve#F>lZerc(9Si1f3E&}W(VA-Ewj&bpB&t&MUh1(;5Mp#+% zBhW7z`9#}3O-OMNjAC)&Atw)yfR6WfGkIagU*TMp_~Lh^%zUI!SKUw_9=FiA#=hw* zqbxhbn~NkL_7id ziu_Is<|)(n>n{4PBqj%1Nl(ZHo(1QvAqTyUO=Uv~uu7*dL$LBZd3GoRkfEQ!D=X>eL9svl%^UxBw0Sn0Kb7 zsNZs-6?*-Ppufk)EG-F?6g!ZbD{0+f)?kBC?OByFOO-}MOyPH-K7$Fd*dfvyRD+H@ z)iPzjtHUgQw)X^wzhVmqaY;p~^5yi>@?~|tF9=<0iyd`Gk=yF@MeeJXr_I$DQ%V}bMgU{)vVvwe+)6pb( zNOP?DwY_qMPP|ik*X)z1{-Z4LdO&oXkwS70!O3t{RV2V-Y>`6W&VyRMXbn9Z!HDuK-(z)3`=!vW zefA9no0Yovcubqy^%i;}iT#GVeH_>;2iM|Cx?&XnOQDRIuazWUj6!2+U}rNy3$q+k zbl1YCodSPZT4;U$2+A2mu>!h?X@96oTOau^LSQY-8&QbzLz47Lh%8}EZ0AfFVuh0- z=2E_bIm)zzTCw~#q2y|8s6BNdVtZ~bdsPZVn#-WqO4U> zbAC;jKlPK3}`&_o~h^|+84@l6(U zzf=?4SX{)ckm|MF#39pM0#|EJtc<)7zMuLXaJ4A7+19EffnoLq`3m&O3Sd}u11Ay# z8~Se1Rsi!hq3>EM%Vd&aHJ8)47kG4kE!c-zK@DkSdBMAK6(L8n8Uz#|geLHg_C_?( z4%+{oiptiV;ATu1aFdUA<#MSA?cT7N#Ka9FU1^XDTpL#g)u2(-V*oz!i<+B z0VRJ%?d23njC}!GDU>;=eK`;senN@~|CX@Rqj_uhB`EjY_psQt3O8n75sQ5pSDlkI z&|y+tDfL>NJB+Yq_#~d{i`petEUmkL$!ZB1@9;F{Azp>FbJL5P5s*IP3PvglI{4Ku zry9xdSKh!En@TFH!G^_T!MBOdlXgVsuQ9Z!9UCM-?AoAr*;&;+W>)XCAPwUye=I{MW=cQ;R5=2g%*)a zLtH^fUp1PrgqbrjT;EJg5gddwrkc&m1gpy%fS z6E)k@)9^bpzLy%W)MyQ$_UDQ%Fy}}R23UZTmSrTHiGu%|6@1JP{=Ap`N7|JkSJn+B zeVT^}?`G*WSN$&-y`rbod?M#7Kg0Brqod7B588SC{-pE8!RmRwfEYI1jX^cHWAg*K z2U#@@nW2mfyJ3~~;Ig28?va$xPPcu^%>5x#PC-L{l6Yl`R_B3l7|Rq=6*ub=*M>(e z$7Y*p+)tmu-(<5~NA4!7j+HN#G;_8CS=8(=0xTl{E3HIvleBK)*VL8<&ioy;uIf^B zs$Q+-J0~Vn@TUEMG@Rj~6R6z`Rj7Ey4iBMToA;d0t=Z*B*!9 zc>t7*SRq1C`t92E1MVtxW&EK!Eb{bnA|M2QMjno6Y`c2|b{;o#>k^+?W{%(ZE_TDledIvb&lN zd+Ve1CzcGft0#@E4LLBP;6;}QX;|3ihf`mtU`w@g=53CbjZ|)y_8ENZv#y!w z)E`gV41{bC{m6PluXX)dCNec9z7MCiGEKwrlFShVDpUwR`-Vwgh&;b&#qx}DuHd2+ zf1%x_Q~tg?NhN>6&#y{8kYBl$c~EIV$%`H`TDMxF3D5pzyjWA{#+dG?C{%{Qt5k+2 zqb*Z0f@;C*xD;&}5_f-Xgh@$g-NGk72Q zZn-G@9l(UyPI%@Y6KfNv7>t(Nbi#nn<{kzaBjl4hGf~Z^u;fK^C&dmnQcVo`#0kk< z=-rluZu8UQLT{)$iM|abPz~W_1o=V)b~)>zH2!&Bfv^fIsJ!q}L(6CRd8*q?&j7RV6Y;#q^$T38$y^F`sJz50R^Z&{ZKgeS9OpU150Y#f z>eiANh5eT#eIEGD$_cz~4}g4X9ZuVw4QB}ckBxYo6x&Hn+;8A{+BwYrU$dIUGAFdR z+`ho*LxhP|jc@!VZr8uXei!z4Lx}rCr#h)PJA73?Gd)zu;k*BZ(V(E@c;kyspRl-W zG=Cp-l}D48c6#oJ6zP= zhj*pdjg<@Fn*?aVe4z4WWTg4Ws>DX?axiS{2t?AS)x4@84DlV)4ElUfAP*C#_|Un5 zbC=pG^*kdASi=Wbi?6|9<<@@@&PG#@Ki`F_m7OvVao$7P;2?;)y~h74gzu2s9L6r#MxBB_I7jFN>2^ zk3eFt?9Ic)`%FBNmoU|LwMR%VXgPL#r4DCqgJJjCZ&8Z*x*$<7z|CI*whd;Zv(*kW zIiK#~GvUD2ko37)t8E<}j|RaRcrzqg6%}G3;vriFGG$xfK+H4tEKX{ z5XPQf+~kl`pevsBwmSjS(23&uEsI7}&Y4b{FJee0y)P#mWMLW7 z!Y*fDZ${JTMnfr3pp_~C1(y2-0kiA>%EcDmuv(@ad5JB%A2dm-+@kh?GZCqI z9~(ch4PCt`f8i*$X4}sp>K!zi??W=I%R82jDw^nbZ{vO$&8XghfFeR}%*oJ^LP@SL zBltG>aDFU5Mp&5fYWr;C=xh{F$vjG+$`oo<5I$e9Va1lMX;#bY7;eDsz03gfO(%zy z*JP>~#W~UDb2|i~xfAhc+2MYvfp)a@C{+8olxT zxYXH~OHuZ^TQS2$+PwS~oz)5F&!Jo8<@IFcccTn@Y8)f#-1%o1@S~{jp;2Rr3tlP3 zo@8?fQ9q87l_-C@w;`fo5!xSP-aiDU#fh*I=TKgYIa|xU9Zr>b7ojbLsiERJJIeVY z=kGr3N5Y{|UB+jzZS{BfZ7_4LWpOo;I-i|PF*1P0HpaIXyQ%pLJMqRR4K~ovkSUtN zS9B#l6DC{O?wI7psS{vE1{zJ%h#)oaH}T-)9haaBVJRvmSZ3uCdR%Yl1l2&xDd1Ph zU-qGhZue_|t&xr1o>56awR&_RJiJD;tSyH5O;TL9rTlk~@kX25!YV&P+_Z@*a}4n( zw(Nt}^iisw#wLG|>ILrNU5+>S+Y*w`@xL#eJWn-`dvlIEOvq!=Nz_4v80;t*LNITG|dpniAW2Yc4mWU%Vt` zI7qaS^1YAGj<@jB(AZTf=9^KyYq!z%;)k;@3oQ(?q7w44g0F$(+f6wB8rj}tm{0N6 zQO?db+rW%He(>4}gqJJx+DA>#R8$Cm!sJ+BB$h1F2vmc#kAjaFu7?#a=TqiA2ZZ%$ zd!_T+7xj|53{Vn%f8RrcHsRZCcgLlw-4G*G*d)?>l)&gN7f6rUu+LH zc%l~EeF1LKakwnw=JjDUUhFKgUd)i3M3S0cy-P%8p9yk+S_fw21uXJ$8gKH z8@8Q8A@53*m`9~^Q6Y9>HiE=~m01g6Z*YjI zGZ8lUll}^AAGNL?;%wGmDeM#)Dc@Jxf zB+&J@(NPzb$4B;m4=i&lpZ@|DzUHM#__Bit6C`usNU2PjtT$DhE>-yXpg7v3rp8beFB55^g4M;o1H-^!Ly*?C z?)BE}_Won)-a>+Kab~5yKUCn#?hh&AOgbFXCq%5M9!WC;EP{oYUBv<+a>-QOu8J*VaS^d^NIi5GBAERxCP+QZ#>6N7 zDwoE=_IgFUB>I_#^*#Xag>(iW7ign6h=;4*?fQNb($aT1FR1}V^~R$hVuSN$4um&W zDz+^g?3cDBVmY*jBmYjaa!~^xgB(9N!wp!F-b6R6$&&g~O#8uQUU)X_zc;k_S`AD$ zbWkW5Mc$N>=>!Xo2!}1zvf$G_$lBQ_+wn&3KGp7mk{)ZO2M-zfjr*EIpKQn3o~b2* zoZcc`g~Hpx2cy^_P1cRtIaceJGD}L);y~mRJF1Dn_Zls^GKwPLk8 z9l7JTMWp4q+;NQvs!(Pk9r`+dpmN)flp5lycluDOzqhE~M&!QV1|~GgWy|C^+4+uD z6wCuk6oBk%T@Nm*c~w{4sGr>COCX8_Z2)&)<+Kg-c3zJkl(73d_PtU!FT5|ZswyR*=`v)ncYy< zB?w9U0#$}4A8Pl0402Tl8RIf-U=|;UnR{FP4Bc4}r=|Ucxu`Hf;V|!0r%oF};LL3CFf%%=d^oNSZ=r33Z|`3XVnppisX*p-C0%gLch;6qhM-UZwzA z)8u-yDKWhd!@*gNDr|TVz7BFJ;uv zVk-!kjq}zh*2(oEm1dOn_0{~jJ>-+%1L3*n51(?MkUtTC9JQKC!}Q@mQMp)t04^%% zC&_Ig0k8R-p_Uirc+m+{A#oWWCy}_lJH_kTlHVJiJ8#(MtA4WX&CG-8Xi+I!g9e$1 zV@^h9G&5lfj5Wv4_gi{t?#A-bjb+=aSa7cCLc)tyw^q(xcjs6c^Tw?#dD$Kr&As-8 zeRx7XkPlG+)ofP3Yi~S@r@zH408+Pe* zsD^hXTloo+<0%fX_-#G}!#k7Y;2d_rnDe3ex@Bf$mNM^ew+oHk>12 z!3e4$z_+5dN(D$7pcd^#N}Iuj9fY{*yjzwdYqa=baeszBc7#I+S;1z765W#*$nh*| zG{2FyIGt$7UvtMhUuz5r7BR#0lq)Fuyru{bMIw;4n|bE>nxXIJBa4K_Qf@6gFsF`6 zzJoj!dv-6`x-v`yQMNCWqu-vXBtIUR!9k9cpN%Eu=1+f&W%l(MQ?wfo2_XyMFt?*Z z3p0|g<7v=-EHf6ju)S;WUoVYZ5DrMKp-|ZK!sh85wfR$u?-5c;?~zKxdEUT8yC8!L z&-hkZ=4qGz4h**@FQTe62lQ@c$_!5E+c)s{Ng+DICvT~i=U_P4DV`V9^r*62(jvz_)KCx#a{hd4m@TM$a0jOpwbq0D) zm|AJ#ixY1)tjFLM39 z=pI5El5M|5rsME~^Qqvegt6Zsc%r^%2^aO!6Z8YX_%wszVToCo4`Yc|HA6#S$`Yfo zmD)G1FfH$|djxYZuWYy~J{*2YJyA)EJE2Y-XsDXW?_%Z%?XV#|8*h0)v2$6782>bb z5veSYt#JEU(}oj*HdSm(QI22GP-}VYMp^iDy`1u$ECJg?xI#5A>Wq{Fe&ItupZdgovYuvqtN{peL+dNs0br=gbM;LlU%H|R!ZDh zS_`nh{B_uUW12Xp<3~2dwEV|17#uEI4N4s>g|i-DE^5;5(l|W6JnkFMU)a#&EIFJr zy(1fVtI}hh3;|5h@g+)dwt~Uhq4g|9dL@}mLhTwY<1ny(Ez(#BA8Q=USnaWUFlf$| zp%xMlmv*&|ahN4)z2sL0Rh)W;JYzv@ed251UO9Ln0!JkOE4IeDiq{f4RJyYzh++Od zh}Tu5dNkki^}P!^aSt)rd&NC}oK)*!mken|aPxO?Zdb+%ars6BpxIvwv*wb8mT6-` u)PWaWqW_Yz%{~1V;(AFi_#hCuHPGrWo>wf`79$j|; literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xea.class.mq5 b/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xea.class.mq5 new file mode 100644 index 0000000..38136a7 --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xea.class.mq5 @@ -0,0 +1,3906 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCBaseEA +// Description: provides all Base EA requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include +#include "../Classes/x-saherelm.xalert.class.mq5" +#include "../Classes/x-saherelm.xtrade.class.mq5" + +// +// Define On Signal Event Handler Type ... +typedef void (*TOnSignal)(XSignal &signals[]); + +// +// Tokens ... +string XINProfitToken = "INP"; +string XINDrawdownToken = "IND"; +string XProfitsToken = "PFS"; +string XTimesToken = "TMS"; +string XPricessToken = "PCS"; + +// +enum ENUM_X_PROFIT_TRACK_FIELDS +{ + X_PROFIT_TRACK_PROFIT, + X_PROFIT_TRACK_LONGS_PROFIT, + X_PROFIT_TRACK_SHORTS_PROFIT, +}; + +// +// Model Account Profits ... +struct XProfitTrack +{ + // + int longs; // Number of Long ... + int shorts; // Number of Short ... + + // + double profit; // Profit of All ... + double longsProfit; // Profits of Longs ... + double shortsProfit; // Profits of Shorts ... + + // + double profitFrom; // Profit of All ... + double longsProfitFrom; // Profits of Longs ... + double shortsProfitFrom; // Profits of Shorts ... + + // + double volume; // Volume ... + double longsVolume; // Volume of Longs ... + double shortsVolume; // Volume of Shorts ... + + // + datetime time; // Check Time ... + + // + XProfitTrack() + { + Clean(); + } + + // + // Tools ... + + // + // Initialization ... + bool Init(XSCTrade *mTrader) + { + // + bool result = false; + + // + XPosition positions[]; + int positionsCount = mTrader.GetPositions(positions); + result = positionsCount > 0; + if (!result) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + bool isLong = IsLong(iPosition.type); + + // + if (isLong) + { + // + longs++; + longsVolume += iPosition.volume; + longsProfit += iPosition.profit; + } + else + { + // + shorts++; + shortsVolume += iPosition.volume; + shortsProfit += iPosition.profit; + } + + // + profit += iPosition.profit; + volume += iPosition.volume; + } + + // + result = IsValid(); + if (result) + { + time = TimeCurrent(); + } + + // + return result; + } + + // + double SelectField(ENUM_X_PROFIT_TRACK_FIELDS field) + { + // + double result = profit; + + // + switch (field) + { + // + case X_PROFIT_TRACK_LONGS_PROFIT: + result = longsProfit; + break; + + // + case X_PROFIT_TRACK_SHORTS_PROFIT: + result = shortsProfit; + break; + + // + default: + case X_PROFIT_TRACK_PROFIT: + result = profit; + break; + } + + // + return result; + } + + // + // Cleanup ... + void Clean() + { + // + longs = 0; + shorts = 0; + profit = 0; + volume = 0; + profitFrom = 0; + longsVolume = 0; + longsProfit = 0; + shortsVolume = 0; + shortsProfit = 0; + longsProfitFrom = 0; + shortsProfitFrom = 0; + + // + time = NULL; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + (longs > 0 || shorts > 0) + // + && + // + volume > 0 + // + ; + + // + return result; + } + + // +}; + +// +// Track Specific Position ... +struct XPositionTrack +{ + // + ulong ticket; // Position Ticket + string symbol; // Position Symbol + ENUM_POSITION_TYPE type; // Position Type + ENUM_TIMEFRAMES period; // Position Period + + // + double price[]; // Check Price ... + double profit[]; // Check Profit ... + datetime time[]; // Check Time ... + + // + double tp; // Current TP + double sl; // Current SL + double volume; // Current Volume + double entry; // Position Entry + datetime openAt; // Position Open Time + + // + int inProfitCount; // Number of Cross in DrawDown + int inDrawdownCount; // Number of Crossed in Profit + + // + // Constructor ... + XPositionTrack() + { + Clean(); + } + + // + // Tools ... + + // + // Initialization ... + bool Init( + XPosition &position // Source Position + ) + { + // + bool result = false; + + // + Clean(); + + // + result = position.IsValid(); + if (!result) + { + return result; + } + + // + ticket = position.ticket; + symbol = position.symbol; + period = position.period; + type = position.type; + tp = position.tp; + sl = position.sl; + entry = position.entry; + volume = position.volume; + openAt = position.openAt; + + // + datetime cTime = TimeCurrent(); + Add( + cTime, + time // + ); + + // + Add( + position.profit, + profit // + ); + + // + Add( + position.price, + price // + ); + + // + result = IsValid(); + + // + return result; + } + + // + bool Update( + XPosition &position // Source Position + ) + { + // + bool result = false; + + // + // Check Current Model is Valid or not ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // Check Position is a Valid Model ... + result = position.IsValid(); + if (!result) + { + return result; + } + + // + // Check Current Model belongs to Given Position ... + result = + // + entry == position.entry && + openAt == position.openAt && + symbol == position.symbol && + period == position.period && + type == position.type && + ticket == position.ticket + // + ; + if (!result) + { + return result; + } + + // + tp = position.tp; + sl = position.sl; + volume = position.volume; + + // + datetime cTime = TimeCurrent(); + + // + SetArrayStates(false); + + // + Add( + cTime, + time // + ); + + // + Add( + position.profit, + profit // + ); + + // + Add( + position.price, + price // + ); + + // + SetArrayStates(true); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + // Fill In Profit or Drawdown Counters ... + + // + bool isCrossInProfit = IsCrossedInProfit(); + if (isCrossInProfit) + { + inProfitCount++; + } + + // + bool isCrossedInDrawdown = IsCrossedInDrawdown(); + if (isCrossedInDrawdown) + { + inDrawdownCount++; + } + + // + return result; + } + + // + // Cleanup ... + void + Clean() + { + // + ticket = 0; + type = NULL; + symbol = NULL; + period = NULL; + + // + tp = 0; + sl = 0; + volume = 0; + entry = 0; + openAt = NULL; + + // + inProfitCount = 0; + inDrawdownCount = 0; + + // + Clean(price); + Clean(profit); + Clean(time); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + ticket > 0 && + type != NULL && + period != NULL && + volume > 0 && + entry > 0 && + openAt > 0 + // + ; + + // + return result; + } + + // + void SetArrayStates(bool state) + { + // + ArraySetAsSeries(price, state); + ArraySetAsSeries(profit, state); + ArraySetAsSeries(time, state); + } + + // + bool IsCrossedInProfit() + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + result = ArraySize(time) > 1; + if (!result) + { + return result; + } + + // + result = + // + profit[0] > 0 && + profit[1] < 0 + // + ; + + // + return result; + } + + // + bool IsCrossedInDrawdown() + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + result = ArraySize(time) > 1; + if (!result) + { + return result; + } + + // + result = + // + profit[0] < 0 && + profit[1] > 0 + // + ; + + // + return result; + } + + // + // Collector Tools ... + + // + string GetToken() + { + return GetToken(this); + } + + // + bool IsModelValid() + { + return IsValid(); + } + + // + bool IsSameAs(XPositionTrack &track) + { + // + bool result = false; + + // + result = + // + track.IsValid() && + type == track.type && + ticket == track.ticket && + symbol == track.symbol && + period == track.period && + openAt == track.openAt + // + ; + + // + return result; + } + + // + int FindIndex( + const XPositionTrack &values[] // Collection + ) + { + // + return FindIndex( + this, + values + // + ); + } + + // + // Converts a Model to String Representation ... + string ToModelString() + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + // For Modeling a PositionTrack Object ... + // - tp + // - sl + // - type + // - entry + // - ticket + // - symbol + // - period + // - openAt + // - volume + // - inProfitCount + // - inDrawdownCount + // - time[] + // - price[] + // - profit[] + + // + // Ticket ... + string ticketStr = Surround(XIDToken, ticket); + + // + // Symbol ... + string SymbolStr = Surround(XSymbolToken, symbol); + + // + // Type ... + string typeStr = Surround(XTypeToken, type); + + // + // Period ... + int iPeriodInt = (int)period; + string periodStr = Surround(XPeriodToken, iPeriodInt); + + // + // TP ... + string tpStr = Surround(XTPToken, tp); + + // + // SL ... + string slStr = Surround(XSLToken, sl); + + // + // Volume ... + string volumeStr = Surround(XVolumeToken, volume); + + // + // Entry ... + string entryStr = Surround(XEntryToken, entry); + + // + // OpenAt ... + string timeStr = Surround(XTimeToken, openAt); + + // + // InProfitCount ... + string inProfitCountStr = Surround(XINProfitToken, inProfitCount); + + // + // InDrawdownCount ... + string inDrawdownCountStr = Surround(XINDrawdownToken, inDrawdownCount); + + // + // Time(s) ... + string timesContentStr = ToString(time); + string timesStr = Surround(XTimesToken, timesContentStr); + + // + // Price(s) ... + string pricesContentStr = ToString(price); + string pricesStr = Surround(XPricessToken, pricesContentStr); + + // + // Profit(s) ... + string profitsContentStr = ToString(profit); + string profitsStr = Surround(XProfitsToken, profitsContentStr); + + // + string token = GetToken(); + + // + result = + // + token + + "[" + + // + ticketStr + + SymbolStr + + typeStr + + periodStr + + tpStr + + slStr + + volumeStr + + entryStr + + timeStr + + inProfitCountStr + + inDrawdownCountStr + + timesStr + + pricesStr + + profitsStr + + // + "]" + // + ; + + // + return result; + } + + // + // Pres and Fill Model based on it's String Representation ... + bool ParseModel(string value) + { + // + bool result = false; + + // + Clean(); + + // + result = IsValid(value); + if (!result) + { + return result; + } + + // + // For Modeling a PositionTrack Object ... + // - tp + // - sl + // - type + // - entry + // - ticket + // - symbol + // - period + // - openAt + // - volume + // - inProfitCount + // - inDrawdownCount + // - time[] + // - price[] + // - profit[] + + // + // TP ... + tp = ParseDoubleSurrounded(value, XTPToken); + + // + // SL ... + tp = ParseDoubleSurrounded(value, XSLToken); + + // + // Type ... + type = ((ENUM_POSITION_TYPE)ParseIntSurrounded(value, XTypeToken)); + + // + // Entry ... + entry = ParseDoubleSurrounded(value, XEntryToken); + + // + // Ticket ... + ticket = ParseLongSurrounded(value, XIDToken); + + // + // Symbol ... + symbol = ParseStringSurrounded(value, XSymbolToken); + + // + // Period ... + period = ((ENUM_TIMEFRAMES)ParseIntSurrounded(value, XPeriodToken)); + + // + // Open At ... + openAt = ParseTimeSurrounded(value, XTimeToken); + + // + // Volume ... + volume = ParseDoubleSurrounded(value, XVolumeToken); + + // + // InProfitCount ... + inProfitCount = ParseIntSurrounded(value, XINProfitToken); + + // + // InDrawdownCount ... + inDrawdownCount = ParseIntSurrounded(value, XINDrawdownToken); + + // + // Time(s) ... + ParseTimeArraySurrounded( + time, + value, + XTimesToken + // + ); + + // + // Price(s) ... + ParseDoubleArraySurrounded( + price, + value, + XPricessToken + // + ); + + // + // Profit(s) ... + ParseDoubleArraySurrounded( + profit, + value, + XProfitsToken + // + ); + + // + result = IsValid(); + + // + return result; + } +}; + +// +// Type Definitions for XPosition Tracker Events ... +typedef void (*TOnPositionState)(const XPositionTrack &track); + +// +// an Struct for Holding Event Handled Items for Position Tracker ... +struct XPositionTrackerState +{ + // + XPositionTrack inProfits[]; + XPositionTrack inDrawdowns[]; + + // + XPositionTrack onProfits[]; + XPositionTrack onDrawdowns[]; + + // + XPositionTrackerState() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + Clean(inProfits); + Clean(inDrawdowns); + + // + Clean(onProfits); + Clean(onDrawdowns); + } +}; + +// +// Position Tracker Class ... +class XSCPositionTracker +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructor ... + void XSCPositionTracker(bool cleanStore = false) + { + // + XSCDataCollector mBase; + + // + if (cleanStore) + { + mBase.Clear(); + } + } + + // + // Tools ... + + // + // Cleaning Store ... + void Clear() + { + // + XSCDataCollector mBase; + + // + mBase.Clear(); + } + + // + // Collect All Store ... + int Collect(XPositionTrack &result[]) + { + // + int mResult = 0; + + // + XSCDataCollector mBase; + + // + mResult = mBase.Collect(result); + + // + return mResult; + } + + // + // Add Item To Store ... + bool Add(XPositionTrack &item) + { + // + bool result = false; + + // + XSCDataCollector mBase; + + // + result = mBase.Add(item); + + // + return result; + } + + // + // Add Item(s) To Store ... + int Add(XPositionTrack &items[]) + { + // + int result = 0; + + // + XSCDataCollector mBase; + + // + result = mBase.Add(items); + + // + return result; + } + + // + // Remove an Item from Store ... + bool Remove(XPositionTrack &item) + { + // + bool result = false; + + // + XSCDataCollector mBase; + + // + result = mBase.Remove(item); + + // + return result; + } + + // + // Custom Functions ... + + // + // Sync all Content using Specific Trader Class ... + int Sync( + XPositionTrackerState &state, // Hold all Changes State ... + XSCTrade *mTrader // XSCTrade Instance for Synchronize ... + ) + { + // + int result = 0; + + // + XPosition positions[]; + int positionsCount = mTrader.GetPositions(positions); + + // + ulong trackTickets[]; + XPositionTrack trackers[]; + int trackersCount = Collect(trackers); + + // + // Nothing to Do ... + if (positionsCount <= 0 && trackersCount <= 0) + { + return result; + } + + // + // Collect Exists Trackers Ticket's For Managing ... + for (int i = 0; i < trackersCount; i++) + { + // + XPositionTrack iTrack = trackers[i]; + + // + bool isValid = iTrack.IsValid(); + if (isValid) + { + // + AddSpecific( + iTrack.ticket, + trackTickets // + ); + } + } + + // + // Clear Tracker Store for Update Later ... + Clear(); + + // + // Collect All Required to Add/Update Trackers here ... + XPositionTrack syncedTracks[]; + + // + // a Flag for Synchronization Performance ... + bool hasTracker = trackersCount > 0; + + // + // Loop through Position for Managing Trackers ... + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + // if there isn't any Track before ... + if (!hasTracker) + { + // + XPositionTrack iTrack; + bool isInited = iTrack.Init(iPosition); + if (isInited) + { + // + AddRef( + iTrack, + syncedTracks // + ); + + // + FillState( + iTrack, + state // + ); + } + + // + continue; + } + + // + // if there was some tracks ... + + // + // Try to Find Position Ticket in Track Tickets ... + int iTicketIdx = FindIndex( + iPosition.ticket, + trackTickets // + ); + bool isTrackedBefore = iTicketIdx >= 0; + + // + // Add new Track ... + if (!isTrackedBefore) + { + // + XPositionTrack iTrack; + bool isInited = iTrack.Init(iPosition); + if (isInited) + { + // + AddRef( + iTrack, + syncedTracks // + ); + + // + FillState( + iTrack, + state // + ); + } + } + // + // Update Exists Track ... + else + { + // + XPositionTrack iTrack = trackers[iTicketIdx]; + bool isUpdated = iTrack.Update(iPosition); + if (isUpdated) + { + // + AddRef( + iTrack, + syncedTracks // + ); + + // + FillState( + iTrack, + state // + ); + } + } + } + + // + // Check Synced Tracks ... + int syncedTracksCount = ArraySize(syncedTracks); + if (syncedTracksCount <= 0) + { + return result; + } + + // + result = Add(syncedTracks); + + // + return result; + } + + // + // Event Handlers ... + + // + // Add Profit Event Handler ... + void AddOnProfitEventHandler(TOnPositionState handler) + { + // + AddSpecific( + handler, + mOnProfitEventHandlers // + ); + } + + // + // Add Drawdown Event Handler ... + void AddOnDrawdownEventHandler(TOnPositionState handler) + { + // + AddSpecific( + handler, + mOnDrawdownEventHandlers // + ); + } + + // + // Protected ... +protected: + // + // Tools ... + + // + // Event Handlers ... + + // + // OnProfit ... + void NotifyOnProfitEvent(XPositionTrack &track) + { + // + int count = ArraySize(mOnProfitEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + TOnPositionState iHandler = mOnProfitEventHandlers[i]; + iHandler(track); + } + } + + // + // OnDrawdown ... + void NotifyOnDrawdownEvent(XPositionTrack &track) + { + // + int count = ArraySize(mOnDrawdownEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + TOnPositionState iHandler = mOnDrawdownEventHandlers[i]; + iHandler(track); + } + } + + // + // Private ... +private: + // + // Props ... + + // + TOnPositionState mOnProfitEventHandlers[]; + TOnPositionState mOnDrawdownEventHandlers[]; + + // + void FillState( + XPositionTrack &track, + XPositionTrackerState &state // + ) + { + // + // In Profit ... + bool isInProfit = track.profit[0] > 0; + if (isInProfit) + { + // + AddRef( + track, + state.inProfits // + ); + } + + // + // In Drawdown ... + bool isInDrawdown = track.profit[0] < 0; + if (isInDrawdown) + { + // + AddRef( + track, + state.inDrawdowns // + ); + } + + // + // On Profit ... + bool isOnProfit = track.IsCrossedInProfit(); + if (isOnProfit) + { + // + AddRef( + track, + state.onProfits // + ); + } + + // + // On Drawdown ... + bool isOnDrawdown = track.IsCrossedInDrawdown(); + if (isOnDrawdown) + { + // + AddRef( + track, + state.onDrawdowns // + ); + } + } +}; + +// +class XSCPositionHolder +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructor(s) ... + + // + XSCPositionHolder() + { + Clear(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clear() + { + Clean(mItems); + } + + // + bool AddItem(XPosition &item) + { + // + bool result = false; + + // + result = item.IsValid(); + if (!result) + { + return result; + } + + // + result = !HasItem(item); + if (!result) + { + return result; + } + + // + AddRef( + item, + mItems // + ); + + // + return result; + } + + // + int AddItems(XPosition &items[]) + { + // + int result = 0; + + // + int itemsCount = ArraySize(items); + if (itemsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < itemsCount; i++) + { + // + XPosition iItem = items[i]; + + // + bool isAdded = AddItem(iItem); + if (isAdded) + { + result++; + } + } + + // + return result; + } + + // + bool AddOrUpdateItem(XPosition &item) + { + // + bool result = false; + + // + result = item.IsValid(); + if (!result) + { + return result; + } + + // + bool hasItem = HasItem(item); + if (!hasItem) + { + result = AddItem(item); + } + else + { + // + result = RemoveItem(item); + if (result) + { + result = AddItem(item); + } + } + + // + return result; + } + + // + int AddOrUpdateItem(XPosition &items[]) + { + // + int result = 0; + + // + int itemsCount = ArraySize(items); + if (itemsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < itemsCount; i++) + { + // + XPosition iItem = items[i]; + + // + bool isAddOrUpdated = AddOrUpdateItem(iItem); + if (isAddOrUpdated) + { + result++; + } + } + + // + return result; + } + + // + bool HasItem(XPosition &item) + { + // + bool result = false; + + // + int itemIDX = FindItem(item); + result = itemIDX >= 0; + + // + return result; + } + + // + int FindItem(XPosition &item) + { + // + int result = -1; + + // + if (!item.IsValid()) + { + return result; + } + + // + int itemsCount = CountItems(); + if (itemsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < itemsCount; i++) + { + // + XPosition iItem = mItems[i]; + + // + bool isSame = IsItemSameAs(item, iItem); + if (isSame) + { + // + result = i; + break; + } + } + + // + return result; + } + + // + bool GetByIndex( + int index, + XPosition &item // + ) + { + // + bool result = false; + + // + NormalizeIndex( + index, + mItems // + ); + + // + item = mItems[index]; + + // + result = item.IsValid(); + + // + return result; + } + + // + bool RemoveItem(XPosition &item) + { + // + bool result = false; + + // + result = HasItem(item); + if (!result) + { + return result; + } + + // + int itemIDX = FindItem(item); + result = ArrayRemove( + mItems, + itemIDX, + 1 // + ); + + // + return result; + } + + // + int RemoveItems(XPosition &items[]) + { + // + int result = 0; + + // + int itemsCount = ArraySize(items); + if (itemsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < itemsCount; i++) + { + // + XPosition iItem = items[i]; + + // + bool isRemoved = RemoveItem(iItem); + if (isRemoved) + { + result++; + } + } + + // + return result; + } + + // + int CountItems() + { + return ArraySize(mItems); + } + + // + bool IsItemSameAs( + XPosition &source, + XPosition &dest // Compare Source with this ... + ) + { + // + bool result = false; + + // + result = + // + dest.IsValid() && + source.IsValid() && + source.symbol == dest.symbol && + source.period == dest.period && + source.ticket == dest.ticket && + source.openAt == dest.openAt && + source.provider == dest.provider + // + ; + + // + return result; + } + + // + // Custom Functions ... + + // + bool GetMaxInDrawdown( + XPosition &item // Result + ) + { + // + bool result = false; + + // + item.Clean(); + + // + int itemsCount = CountItems(); + result = IsValidSize(itemsCount); + if (!result) + { + return result; + } + + // + int maxIDX = -1; + for (int i = 0; i < itemsCount; i++) + { + // + XPosition iItem = mItems[i]; + + // + bool canSelect = + // + iItem.profit < 0 + // + && + // + ( + // + (maxIDX == -1 && !item.IsValid()) + ? true + : item.profit < iItem.profit + // + ) + // + ; + if (canSelect) + { + // + maxIDX = i; + item = iItem; + } + } + + // + result = maxIDX > -1 && item.IsValid(); + + // + return result; + } + + // + bool GetMaxInProfit( + XPosition &item // Result + ) + { + // + bool result = false; + + // + item.Clean(); + + // + int itemsCount = CountItems(); + result = IsValidSize(itemsCount); + if (!result) + { + return result; + } + + // + int maxIDX = -1; + for (int i = 0; i < itemsCount; i++) + { + // + XPosition iItem = mItems[i]; + + // + bool canSelect = + // + iItem.profit > 0 + // + && + // + ( + // + (maxIDX == -1 && !item.IsValid()) + ? true + : item.profit < iItem.profit + // + ) + // + ; + if (canSelect) + { + // + maxIDX = i; + item = iItem; + } + } + + // + result = maxIDX > -1 && item.IsValid(); + + // + return result; + } + + // + bool GetFarestEntry( + XPosition &item, // Result + string symbol = NULL, + string provider = NULL, + ENUM_TIMEFRAMES period = NULL, + ENUM_POSITION_TYPE type = NULL // + ) + { + // + bool result = false; + + // + item.Clean(); + + // + int itemsCount = CountItems(); + result = IsValidSize(itemsCount); + if (!result) + { + return result; + } + + // + for (int i = 0; i < itemsCount; i++) + { + // + XPosition iItem = mItems[i]; + + // + bool isFiltersPassed = + // + iItem.IsFiltersPassed( + symbol, + provider, + period, + type // + ) + // + ; + + // + if (!isFiltersPassed) + { + continue; + } + + // + // Do Additional Filtering ... + bool isValidEntry = + // + !item.IsValid() + ? true + : item.entry < iItem.entry + // + ; + if (isValidEntry) + { + // + item = iItem; + } + } + + // + result = item.IsValid(); + + // + return result; + } + + // + bool GetNearestEntry( + XPosition &item, // Result + string symbol = NULL, + string provider = NULL, + ENUM_TIMEFRAMES period = NULL, + ENUM_POSITION_TYPE type = NULL // + ) + { + // + bool result = false; + + // + item.Clean(); + + // + int itemsCount = CountItems(); + result = IsValidSize(itemsCount); + if (!result) + { + return result; + } + + // + for (int i = 0; i < itemsCount; i++) + { + // + XPosition iItem = mItems[i]; + + // + bool isFiltersPassed = + // + iItem.IsFiltersPassed( + symbol, + provider, + period, + type // + ) + // + ; + + // + if (!isFiltersPassed) + { + continue; + } + + // + // Do Additional Filtering ... + bool isValidEntry = + // + !item.IsValid() + ? true + : item.entry > iItem.entry + // + ; + if (isValidEntry) + { + // + item = iItem; + } + } + + // + result = item.IsValid(); + + // + return result; + } + + // + bool GetFarestSL( + XPosition &item, // Result + string symbol = NULL, + string provider = NULL, + ENUM_TIMEFRAMES period = NULL, + ENUM_POSITION_TYPE type = NULL // + ) + { + // + bool result = false; + + // + item.Clean(); + + // + int itemsCount = CountItems(); + result = IsValidSize(itemsCount); + if (!result) + { + return result; + } + + // + for (int i = 0; i < itemsCount; i++) + { + // + XPosition iItem = mItems[i]; + + // + bool isFiltersPassed = + // + iItem.IsFiltersPassed( + symbol, + provider, + period, + type // + ) + // + ; + + // + if (!isFiltersPassed) + { + continue; + } + + // + // Do Additional Filtering ... + bool isValidEntry = + // + !item.IsValid() + ? true + : item.sl < iItem.sl + // + ; + if (isValidEntry) + { + // + item = iItem; + } + } + + // + result = item.IsValid(); + + // + return result; + } + + // + bool GetNearestSL( + XPosition &item, // Result + string symbol = NULL, + string provider = NULL, + ENUM_TIMEFRAMES period = NULL, + ENUM_POSITION_TYPE type = NULL // + ) + { + // + bool result = false; + + // + item.Clean(); + + // + int itemsCount = CountItems(); + result = IsValidSize(itemsCount); + if (!result) + { + return result; + } + + // + for (int i = 0; i < itemsCount; i++) + { + // + XPosition iItem = mItems[i]; + + // + bool isFiltersPassed = + // + iItem.IsFiltersPassed( + symbol, + provider, + period, + type // + ) + // + ; + + // + if (!isFiltersPassed) + { + continue; + } + + // + // Do Additional Filtering ... + bool isValidEntry = + // + !item.IsValid() + ? true + : item.sl > iItem.sl + // + ; + if (isValidEntry) + { + // + item = iItem; + } + } + + // + result = item.IsValid(); + + // + return result; + } + + // + bool GetFarestTP( + XPosition &item, // Result + string symbol = NULL, + string provider = NULL, + ENUM_TIMEFRAMES period = NULL, + ENUM_POSITION_TYPE type = NULL // + ) + { + // + bool result = false; + + // + item.Clean(); + + // + int itemsCount = CountItems(); + result = IsValidSize(itemsCount); + if (!result) + { + return result; + } + + // + for (int i = 0; i < itemsCount; i++) + { + // + XPosition iItem = mItems[i]; + + // + bool isFiltersPassed = + // + iItem.IsFiltersPassed( + symbol, + provider, + period, + type // + ) + // + ; + + // + if (!isFiltersPassed) + { + continue; + } + + // + // Do Additional Filtering ... + bool isValidEntry = + // + !item.IsValid() + ? true + : item.tp < iItem.tp + // + ; + if (isValidEntry) + { + // + item = iItem; + } + } + + // + result = item.IsValid(); + + // + return result; + } + + // + bool GetNearestTP( + XPosition &item, // Result + string symbol = NULL, + string provider = NULL, + ENUM_TIMEFRAMES period = NULL, + ENUM_POSITION_TYPE type = NULL // + ) + { + // + bool result = false; + + // + item.Clean(); + + // + int itemsCount = CountItems(); + result = IsValidSize(itemsCount); + if (!result) + { + return result; + } + + // + for (int i = 0; i < itemsCount; i++) + { + // + XPosition iItem = mItems[i]; + + // + bool isFiltersPassed = + // + iItem.IsFiltersPassed( + symbol, + provider, + period, + type // + ) + // + ; + + // + if (!isFiltersPassed) + { + continue; + } + + // + // Do Additional Filtering ... + bool isValidEntry = + // + !item.IsValid() + ? true + : item.tp > iItem.tp + // + ; + if (isValidEntry) + { + // + item = iItem; + } + } + + // + result = item.IsValid(); + + // + return result; + } + + // + // Private ... +private: + // + // Props ... + XPosition mItems[]; +}; + +// +// Class Definition ... + +class XSCBaseEA : public XSCBaseAlert +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructor ... + XSCBaseEA( + // + // XTrade Class Requirements ... + int slippage, // Specify Slippage + ulong magicNumber, // Specify Magic Number + int manageInterval, // Manager Check Intervals Seconds + double maxAllowedSpread, // Max Allowed Spred for Opening Trades + int maxAllowedPositions, // Max Allowed Positions + double maxAllowedDrawdownFactor, // Max Allowed Drawdown Factor + double staticVolume, // Static Volume for Positions + // + // Position Management ... + bool allowLong = true, // Allow Long Trades + bool allowShort = true, // Allow Short Trades + double minProfitPerTrade = 0, // Min Profit Per Trade based On Volume Factor (Hedge) + double minProfitPerVolumeFactor = 0, // Min Volume Factor for Calculating Profit (Hedge) + // + // Event Handlers ... + TOnStopLoss onStopLossTriggered = NULL, // On StopLoass Triggered Event Handler + TOnTakeProfit onTakeProfitTriggered = NULL, // On TakeProfit Triggered Event Handler + TOnDealsChanged onDealsChangedHandler = NULL, // On Deals Changed Event Handler + TOnOrdersChanged onOrdersChangedHandler = NULL, // On Orders Changed Event Handler + TOnPositionsChanged onPositionsChangedHandler = NULL, // On Positions Changed Event Handler + TOnTradeStateChanged onTradeStateChangedHandler = NULL, // On Trade State Changed Event Handler + // + // Log Handler ... + bool enableAlerts = true, // Enable Alerts + bool logAlerts = true, // Log Alerts + bool terminalAlerts = false, // Terminal Alerts + bool mailAlerts = false, // Mail Alerts + bool pushAlerts = false // Push Alerts + ) + { + // + // Instance XSCTrade Class ... + mTrader = new XSCTrade( + slippage, + magicNumber, + manageInterval, + maxAllowedSpread, + maxAllowedPositions, + maxAllowedDrawdownFactor + // + ); + + // + mIsInTestMode = IsRunningOnTestMode(); + + // + // Position Management ... + mAllowLong = allowLong; + mAllowShort = allowShort; + mMinProfitPerTrade = minProfitPerTrade; + mMinProfitPerVolumeFactor = minProfitPerVolumeFactor; + mStaticVolume = staticVolume; + + // + // Set Event Handlers ... + mOnStopLossTriggered = onStopLossTriggered; + mOnTakeProfitTriggered = onTakeProfitTriggered; + mOnDealsChangedHandler = onDealsChangedHandler; + mOnOrdersChangedHandler = onOrdersChangedHandler; + mOnPositionsChangedHandler = onPositionsChangedHandler; + mOnTradeStateChangedHandler = onTradeStateChangedHandler; + + // + // Add Event Listeners to XTrade Class if they Provided ... + if (mOnStopLossTriggered != NULL) + { + mTrader.AddOnStopLossEventHandler(mOnStopLossTriggered); + } + + // + if (mOnTakeProfitTriggered != NULL) + { + mTrader.AddOnTakeProfitEventHandler(mOnTakeProfitTriggered); + } + + // + if (mOnDealsChangedHandler != NULL) + { + mTrader.AddOnDealsChangedEventHandler(mOnDealsChangedHandler); + } + + // + if (mOnOrdersChangedHandler != NULL) + { + mTrader.AddOnOrdersChangedEventHandler(mOnOrdersChangedHandler); + } + + // + if (mOnPositionsChangedHandler != NULL) + { + mTrader.AddOnPositionsChangedEventHandler(mOnPositionsChangedHandler); + } + + // + if (mOnTradeStateChangedHandler != NULL) + { + mTrader.AddOnTradeStateChangedEventHandler(mOnTradeStateChangedHandler); + } + + // + // Instantiate XPositionTracker Class ... + mPositionTracker = new XSCPositionTracker(); + + // + // Do Synchronisation after Instantiate everything ... + XPositionTrackerState state; + mPositionTracker.Sync( + state, + mTrader // + ); + } + + // + // Deconstractor ... + ~XSCBaseEA() + { + // + delete mTrader; + delete mPositionTracker; + } + + // + // Properties Getter(s) / Setter(s) ... + + // + // Retrieve Slippage ... + int GetSlippage() + { + return mTrader.GetSlippage(); + } + + // + // Retrieve Magic Number ... + ulong GetMagicNumber() + { + return mTrader.GetMagicNumber(); + } + + // + // Retrieve Max Allowed Spread for Trading ... + double GetMaxAllowedSpread() + { + return mTrader.GetMaxAllowedSpread(); + } + + // + // Retrieve Max Allowed Same Time Positions Count ... + int GetMaxAllowedPositions() + { + return mTrader.GetMaxAllowedPositions(); + } + + // + // Retrieve Max Allowed Drawdown for Opening new Trades ... + double GetMaxAllowedDrawdownFactor() + { + return mTrader.GetMaxAllowedDrawdownFactor(); + } + + // + double GetStaticVolume() + { + return mStaticVolume; + } + + // + void SetStaticVolume(double value) + { + // + if (value <= 0) + { + value = 0.01; + } + + // + mStaticVolume = value; + } + + // + bool GetAllowLong() + { + return mAllowLong; + } + + // + void SetAllowLong(bool value) + { + mAllowLong = value; + } + + // + bool GetAllowShort() + { + return mAllowShort; + } + + // + void SetAllowShort(bool value) + { + mAllowShort = value; + } + + // + double GetMinProfitPerTrade() + { + return mMinProfitPerTrade; + } + + // + void SetMinProfitPerTrade(double value) + { + // + if (value <= 0) + { + value = 0; + } + + // + if (value == mMinProfitPerTrade) + { + return; + } + + // + mMinProfitPerTrade = value; + } + + // + double GetMinProfitPerVolumeFactor() + { + return mMinProfitPerVolumeFactor; + } + + // + void SetMinProfitPerVolumeFactor(double value) + { + // + if (value <= 0) + { + value = 0; + } + + // + if (value == mMinProfitPerVolumeFactor) + { + return; + } + + // + mMinProfitPerVolumeFactor = value; + } + + // + bool IsHedgeEnable() + { + // + bool result = + // + mMinProfitPerTrade > 0 && + mMinProfitPerVolumeFactor > 0 + // + ; + + // + return result; + } + + // + // Overrides ... + + // + // Customize Token ... + virtual string GetToken() + { + return GetSpecificToken(this); + } + + // + virtual string GetTag() + { + return this.GetToken(); + } + + // + // Virtual Functions ... + + // + // Handle Chart Events ... + virtual void OnChartEvent( + const int id, // event ID + const long &lparam, // long type event parameter + const double &dparam, // double type event parameter + const string &sparam // string type event parameter + ) + { + } + + // + // OnTick Handler ... + virtual void OnTick() + { + // + // Draw ... + Draw(); + + // + // Check Trade Events ... + OnTrade(); + + // + HandleProfitManageMent(); + + // + // First Check For Any Guard Actions ... + // then Handle Guards if Provided ... + XGuard guards[]; + bool hasGuard = CheckForGuard(guards); + if (hasGuard) + { + DoGuards(guards); + } + + // + XSignal signals[]; + + // + // Second Check for Position Management or Equity Management + // Actions like Supports or etc ... + bool isIgnored = HandleStateManagement(signals); + if (isIgnored) + { + return; + } + + // + // Second Check For Signals ... + // then Execute Signals if Provided ... + int signalsCount = RequestForSignal(signals); + if (signalsCount <= 0) + { + return; + } + + // + // Execute Signals ... + HandleSignalsExecution(signals); + } + + // + // Handle StopLoss Event ... + virtual void OnStopLossTriggered(const XDeal &deal) {} + + // + // Handle TakeProfit Event ... + virtual void OnTakeProfitTriggered(const XDeal &deal) {} + + // + // Handle Deals Changed Event ... + virtual void OnDealsChangedHandler(int count) {} + + // + // Handle Order Changed Event ... + virtual void OnOrdersChangedHandler(int count) {} + + // + // Handle Position Changed Event ... + virtual void OnPositionsChangedHandler(int count) {} + + // + // Handle Trade State Changed ... + virtual void OnTradeStateChangedHandler(const XOnTradeHandlerState &state) {} + + // + // Handle On Trade ... + virtual void OnTrade() + { + // + XOnTradeHandlerState state = mTrader.HandleOnTrade(); + + // + if ( + !state.hasNewDeal && + !state.hasNewOrder && + !state.hasNewPosition && + !state.hasNewHistoryOrder) + { + return; + } + + // + // STATE ... + + // + // Notfy Trade State Changed Event ... + OnTradeStateChangedHandler(state); + + // + // DEALS ... + if (state.hasNewDeal) + { + // + // Notfy Deals Changed Event ... + OnDealsChangedHandler(state.newDeals); + + // + // Retrieve Last Deal ... + XDeal deals[]; + mTrader.GetDeals(deals); + int dealsCount = ArraySize(deals); + if (dealsCount > 0) + { + // + XDeal lastDeal = deals[0]; + + // + if (lastDeal.reason == DEAL_REASON_TP) + { + OnTakeProfitTriggered(lastDeal); + } + else if (lastDeal.reason == DEAL_REASON_SL) + { + OnStopLossTriggered(lastDeal); + } + } + } + + // + // ORDERS ... + if (state.hasNewOrder || state.hasNewHistoryOrder) + { + // + // Notfy Orders Changed Event ... + OnOrdersChangedHandler(state.newOrders + state.newHistoryOrders); + } + + // + // POSITIONS ... + if (state.hasNewPosition) + { + // + // Notfy Positions Changed Event ... + OnPositionsChangedHandler(state.newPositions); + } + } + + // + // Retrieve Dept Of Market ... + virtual void OnBookEvent(const string &symbol) + { + // + // TODO: Implement this ... + } + + // + // Draw On Chart if anything is required ... + virtual void Draw() {} + + // + // Check For any Guard Actions ... + virtual bool CheckForGuard(XGuard &guards[]) + { + return false; + } + + // + // When a Guard Notified to Do Support Signal ... + // this Method Calls For Retrieve Support Signal ... + // if it's Provided, Execute it ... + virtual bool RequestForSupport( + XSignal &support, // Holds Support Signal, if Provided + string provider, // Positions Provided by Specific Provider + string symbol, // Trading Symbol + ENUM_POSITION_TYPE type, // Trading Type + ENUM_TIMEFRAMES period // Specified Time Frame + ) + { + return false; + } + + // + // Handle Position(s)/ Order(s) or EQM Supporting Action ... + // if returns false, prevent for process Tick ... + virtual bool HandleStateManagement(XSignal &signals[]) + { + return false; + } + + // + // Regulary Filtered Signals passed to this + // and here we can do Additional Signal Filtering + // for Signal Management such as (Providers and etc) ... + virtual int HandleSignalManagement(XSignal &signals[]) + { + // + int result = ArraySize(signals); + + // + return result; + } + + // + // Here we Have to Check Market based + // on our Strategy for Trading ... + // and if a Good Entry founded ... + // model it as an XSignal struct and passed it to result ... + virtual int RequestForSignal( + XSignal &signals[] // Holds Signals ... + ) + { + return 0; + } + + // + // When Some Errors happens in Executing Signals ... + virtual void ManageUnExecutedSignals( + ENUM_X_SIGNAL_EXECUTION_RESULT &states[], + XSignal &unExecutedSignals[] // + ) + { + } + + // + // Execute Provided Signals ... + virtual void HandleSignalsExecution(XSignal &signals[]) + { + // + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return; + } + + // + // Filter Signals Based on their Types ... + XSignal filteredSignals[]; + + // + // Try to Filter Signals ... + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = signals[i]; + + // + bool isLong = IsLong(iSignal.type); + + // + if ((isLong && !GetAllowLong()) || (!isLong && !GetAllowShort())) + { + continue; + } + + // + AddRef( + iSignal, + filteredSignals // + ); + } + + // + int filteredSignalsCount = ArraySize(filteredSignals); + if (filteredSignalsCount <= 0) + { + return; + } + + // + int managedSignalsCount = HandleSignalManagement(filteredSignals); + if (managedSignalsCount <= 0) + { + return; + } + + // + // Try to Execute Signals ... + XSignal notExecuteds[]; + ENUM_X_SIGNAL_EXECUTION_RESULT reasons[]; + int executedSignalsCount = mTrader.ExecuteSpecifiedSignals( + filteredSignals, + notExecuteds, // Not Executed Signals + reasons + // + ); + + // + string message = NULL; + if (executedSignalsCount == 0) + { + // + message = "(" + ToString(filteredSignalsCount) + ") Signals Execution Failed ..."; + + // + for (int j = 0; j < ArraySize(reasons); j++) + { + // + string iReason = ToString(reasons[j]); + + // + message += "\n" + ToString(j) + ": " + iReason; + } + } + else if (executedSignalsCount < filteredSignalsCount) + { + // + int diff = filteredSignalsCount - executedSignalsCount; + + // + message = "Failed to Execute (" + ToString(diff) + ") Signals ..."; + } + else if (executedSignalsCount == filteredSignalsCount) + { + message = "(" + ToString(executedSignalsCount) + ") Signals Executed Successfully ..."; + } + + // + if (ArraySize(notExecuteds) > 0) + { + // + ManageUnExecutedSignals( + reasons, + notExecuteds // + ); + } + + // + if (IsValid(message)) + { + mAlert.Alert(message); + } + } + + // + virtual void OnGoingToProfit(XProfitTrack &track) {} + virtual void OnLongsGoingToProfit(XProfitTrack &track) {} + virtual void OnShortsGoingToProfit(XProfitTrack &track) {} + + // + virtual void OnGoingToDrawdown(XProfitTrack &track) {} + virtual void OnLongsGoingToDrawdown(XProfitTrack &track) {} + virtual void OnShortsGoingToDrawdown(XProfitTrack &track) {} + + // + virtual void OnPositionGoingInProfit(XPositionTrack &track) {} + virtual void OnPositionGoingToDrawdown(XPositionTrack &track) {} + + // + // Protected ... +protected: + // + // Props ... + + // + // Trade Class Instance ... + XSCTrade *mTrader; + XSCPositionTracker *mPositionTracker; + + // + // Check in Test Mode or not ... + bool mIsInTestMode; + + // + // Tools ... + + // + // Signal Event Listeners ... + void NotifyOnSignalEventHandlers(XSignal &signals[]) + { + // + int listenersCount = ArraySize(mOnSignalEventHandlers); + if (listenersCount <= 0) + { + return; + } + + // + for (int i = 0; i < listenersCount; i++) + { + // + TOnSignal iListener = mOnSignalEventHandlers[i]; + + // + iListener(signals); + } + } + + // + // Position Management ... + + // + // Calculate Required Profit for Hedging ... + double CalculateRequiredProfitForHedge( + XPosition &positions[] // Source + ) + { + // + double result = SpecifiedCalculateRequiredProfitForHedge( + positions, + mMinProfitPerTrade, + mMinProfitPerVolumeFactor // + ); + + // + return result; + } + + // + // Calculate Positions Profit Summary ... + double CalculatePositionsProfit( + XPosition &positions[] // Source + ) + { + // + double result = SpecifiedCalculatePositionsProfit(positions); + + // + return result; + } + + // + // Profit Tracker ... + + // + XProfitTrack mProfitTracks[]; + + // + bool GetProfitTrack( + XProfitTrack &track, + int index = 0 // + ) + { + // + bool result = false; + + // + if (index < 0) + { + index = 0; + } + + // + int tracksCount = CountProfitTracks(); + result = tracksCount > 0 && index < tracksCount; + if (!result) + { + return result; + } + + // + track.Clean(); + + // + track = mProfitTracks[index]; + + // + result = track.IsValid(); + + // + return result; + } + + // + int CountProfitTracks() + { + return ArraySize(mProfitTracks); + } + + // + void AddProfitTrack() + { + // + XProfitTrack track; + bool isValid = track.Init(mTrader); + if (!isValid) + { + return; + } + + // + ArraySetAsSeries(mProfitTracks, false); + + // + AddRef( + track, + mProfitTracks // + ); + + // + ArraySetAsSeries(mProfitTracks, true); + } + + // + // Extract Specified Field Vales of XProfit Track Struct ... + int ExtractProfitTrackField( + double &result[], + ENUM_X_PROFIT_TRACK_FIELDS field, + int start = 0, + int count = 10 // + ) + { + // + Clean(result); + + // + if (start < 0) + { + start = 0; + } + + // + int end = start + count; + + // + int tracksCount = CountProfitTracks(); + if (end > tracksCount) + { + end = tracksCount; + } + + // + for (int i = start; i < end; i++) + { + // + XProfitTrack iTrack; + bool isValid = GetProfitTrack( + iTrack, + i // + ); + + // + if (!isValid) + { + continue; + } + + // + double iValue = iTrack.SelectField(field); + Add( + iValue, + result // + ); + } + + // + int mResult = ArraySize(result); + + // + return mResult; + } + + // + double AverageProfitTrackField( + ENUM_X_PROFIT_TRACK_FIELDS field, + int start = 0, + int count = 10 // + ) + { + // + double result = EMPTY_VALUE; + + // + double items[]; + int itemsCount = ExtractProfitTrackField( + items, + field, + start, + count // + ); + if (itemsCount <= 0) + { + return result; + } + + // + result = GetAverage(items); + + // + return result; + } + + // + bool IsProfitTrackFieldIncreasing( + ENUM_X_PROFIT_TRACK_FIELDS field, + int start = 0, + int count = 10 // + ) + { + // + bool result = false; + + // + double items[]; + int itemsCount = ExtractProfitTrackField( + items, + field, + start, + count // + ); + if (itemsCount <= 0) + { + return result; + } + + // + int from = itemsCount - 1; + int to = 0; + + // + result = IsIncreasing( + from, + to, + items // + ); + + // + return result; + } + + // + bool IsProfitTrackFieldDecreasing( + ENUM_X_PROFIT_TRACK_FIELDS field, + int start = 0, + int count = 10 // + ) + { + // + bool result = false; + + // + double items[]; + int itemsCount = ExtractProfitTrackField( + items, + field, + start, + count // + ); + if (itemsCount <= 0) + { + return result; + } + + // + int from = itemsCount - 1; + int to = 0; + + // + result = IsDecreasing( + from, + to, + items // + ); + + // + return result; + } + + // + void HandleProfitManageMent() + { + // + // Check Tracking Interval ... + + // + static datetime lastProfitTracked = NULL; + datetime cTime = TimeCurrent(); + + // + int profitManagementInterval = PeriodSeconds(PERIOD_M5); + int timeDiff = (int)cTime - (int)lastProfitTracked; + + // + bool canManage = + // + lastProfitTracked == NULL + ? true + : timeDiff >= profitManagementInterval + // + ; + if (!canManage) + { + return; + } + + // + XPosition positions[]; + int positionsCount = mTrader.GetPositions(positions); + if (!IsValidSize(positionsCount)) + { + // + Clean(mProfitTracks); + return; + } + + // + lastProfitTracked = cTime; + + // + // Do Track ... + + // + AddProfitTrack(); + + // + int profitsCount = CountProfitTracks(); + if (profitsCount <= 1) + { + return; + } + + // + XProfitTrack cT; + bool isValid = GetProfitTrack( + cT, + 0 // + ); + if (!isValid) + { + return; + } + + // + XProfitTrack pT; + isValid = GetProfitTrack( + pT, + 1 // + ); + if (!isValid) + { + return; + } + + // + cT.profitFrom = pT.profit; + cT.longsProfitFrom = pT.longsProfit; + cT.shortsProfitFrom = pT.shortsProfit; + + // + bool isGoningToProfit = + // + cT.profit > 0 && + pT.profit <= 0 + // + ; + if (isGoningToProfit) + { + // + OnGoingToProfit(cT); + } + + // + bool isLongsGoningToProfit = + // + cT.longsProfit > 0 && + pT.longsProfit <= 0 + // + ; + if (isLongsGoningToProfit) + { + OnLongsGoingToProfit(cT); + } + + // + bool isShortsGoningToProfit = + // + cT.shortsProfit > 0 && + pT.shortsProfit <= 0 + // + ; + if (isShortsGoningToProfit) + { + OnShortsGoingToProfit(cT); + } + + // + bool isGoningToDrawdown = + // + cT.profit < 0 && + pT.profit >= 0 + // + ; + if (isGoningToDrawdown) + { + OnGoingToDrawdown(cT); + } + + bool isLongsGoningToDrawdown = + // + cT.longsProfit < 0 && + pT.longsProfit >= 0 + // + ; + if (isLongsGoningToDrawdown) + { + OnLongsGoingToDrawdown(cT); + } + + bool isShortsGoningToDrawdown = + // + cT.shortsProfit < 0 && + pT.shortsProfit >= 0 + // + ; + if (isShortsGoningToDrawdown) + { + OnShortsGoingToDrawdown(cT); + } + } + + // + // Synchronize Positions and Position Tracker ... + void SyncPositionTracker() + { + // + // Check Syncing Interval ... + + // + static datetime lastSyncPositionTracker = NULL; + datetime cTime = TimeCurrent(); + + // + int syncInterval = PeriodSeconds(PERIOD_M5); + int lastDiff = (int)cTime - (int)lastSyncPositionTracker; + + // + bool canSync = + // + lastSyncPositionTracker == NULL + ? true + : lastDiff >= syncInterval + // + ; + if (!canSync) + { + return; + } + + // + lastSyncPositionTracker = cTime; + + // + // Do Sync ... + + // + XPositionTrackerState state; + int synced = mPositionTracker.Sync( + state, + mTrader // + ); + if (synced > 0) + { + // + // Check State and Do What we Want ... + int onProfitsCount = ArraySize(state.onProfits); + int onDrawdownCount = ArraySize(state.onDrawdowns); + + // + // Do What we want whe a Position Dropped to Prefit ... + if (onProfitsCount > 0) + { + // + for (int i = 0; i < onProfitsCount; i++) + { + // + XPositionTrack iTrack = state.onProfits[i]; + + // + OnPositionGoingInProfit(iTrack); + } + } + + // + // Do what we want when a Position Dropped to Drawdown ... + if (onDrawdownCount > 0) + { + // + for (int i = 0; i < onDrawdownCount; i++) + { + // + XPositionTrack iTrack = state.onDrawdowns[i]; + + // + OnPositionGoingToDrawdown(iTrack); + } + } + } + } + + // + // Guards ... + + // + // Do All Provided Guards ... + void DoGuards(XGuard &guards[]) + { + // + int guardsCount = ArraySize(guards); + if (guardsCount <= 0) + { + return; + } + + // + for (int i = 0; i < guardsCount; i++) + { + // + XGuard iGuard = guards[i]; + + // + switch (iGuard.action) + { + // + // Hedge In Profit Specified Positions ... + case X_GUARD_ACTION_HEDGE: + HandleGuardHedgeAction( + iGuard.provider, + iGuard.symbol, + iGuard.type, + iGuard.period); + break; + + // + // Trail Stop Loss in Specified Positions ... + case X_GUARD_ACTION_TRAIL_STOP: + HandleGuardTrailingStopAction( + iGuard.provider, + iGuard.symbol, + iGuard.type, + iGuard.period, + iGuard.dblPayLoad); + break; + + // + // Force Close Specified Positions ... + case X_GUARD_ACTION_FORCE_CLOSE: + HandleGuardForceCloseAction( + iGuard.provider, + iGuard.symbol, + iGuard.type, + iGuard.period); + break; + + // + // Generate and Place Support Signals ... + case X_GUARD_ACTION_ADD_SUPPORT_SIGNAL: + HandleGuardAddSupportPositionAction( + iGuard.provider, + iGuard.symbol, + iGuard.type, + iGuard.period); + break; + + // + // Delete All Placed Pending Orders ... + case X_GUARD_ACTION_CANCEL_PENDING_ORDERS: + HandleGuardCancelPendingOrdersAction( + iGuard.provider, + iGuard.symbol, + iGuard.type, + iGuard.period); + break; + } + } + } + + // + // Close All Specified Provider's Positions in Profit Summary ... + void HandleGuardHedgeAction( + string provider, // Positions Provided by Specific Provider + string symbol, // Trading Symbol + ENUM_POSITION_TYPE type, // Trading Type + ENUM_TIMEFRAMES period, // Specified Time Frame + double minProfitForHedging = 1 // Specified Profit for Hedge + ) + { + // + XPosition positions[]; + int positionsCount = mTrader + .GetPositions( + positions, + symbol, + provider, + period, + type + // + ); + if (positionsCount <= 1) + { + return; + } + + // + double profit = CalculatePositionsProfit(positions); + double requiredProfit = CalculateRequiredProfitForHedge(positions); + + // + bool isReadyForHedge = profit >= requiredProfit; + if (!isReadyForHedge) + { + return; + } + + // + string comment = "Guard Hedge " + provider; + int closed = mTrader.Close( + positions, + comment + // + ); + if (closed > 0) + { + // + string message = "Guard Hedge " + provider + "'s Positions on Profit: " + ToString(profit); + + // + mAlert.Alert(message); + } + } + + // + // Close Max In Profit Trade Guard Action ... + void HandleGuardCloseInProfitAction( + string provider, // Positions Provided by Specific Provider + string symbol, // Trading Symbol + ENUM_POSITION_TYPE type, // Trading Type + ENUM_TIMEFRAMES period, // Specified Time Frame + ENUM_X_POSITION_SELECT_METHODS method = NULL // Select Method + ) + { + // + XPosition positions[]; + int positionsCount = mTrader + .GetInProfitPositions( + positions, + symbol, + provider, + period, + type, + method + // + ); + if (positionsCount <= 0) + { + return; + } + + // + string comment = "Close InProfit ..."; + mTrader.Close( + positions, + comment + // + ); + + // + string message = "Guard Close (" + ToString(positionsCount) + ") Postion(s) In Profit ..."; + + // + mAlert.Alert(message); + } + + // + // Close Max In Drawdown Trade Guard Action ... + void HandleGuardCloseInDrawdownAction( + string provider, // Positions Provided by Specific Provider + string symbol, // Trading Symbol + ENUM_POSITION_TYPE type, // Trading Type + ENUM_TIMEFRAMES period, // Specified Time Frame + ENUM_X_POSITION_SELECT_METHODS method = NULL // Select Method + ) + { + // + XPosition positions[]; + int positionsCount = mTrader + .GetInDrawdownPositions( + positions, + symbol, + provider, + period, + type, + method + // + ); + if (positionsCount <= 0) + { + return; + } + + // + string comment = "Close InDrawdown ..."; + mTrader.Close( + positions, + comment + // + ); + + // + string message = "Guard Close (" + ToString(positionsCount) + ") Position(s) In Drawdown ..."; + + // + mAlert.Alert(message); + } + + // + // Force Close Specified Set Of Position ... + void HandleGuardForceCloseAction( + string provider, // Positions Provided by Specific Provider + string symbol, // Trading Symbol + ENUM_POSITION_TYPE type, // Trading Type + ENUM_TIMEFRAMES period, // Specified Time Frame + ulong ticket = 0 // Specific Ticket + ) + { + // + string comment = ""; + + // + // Close All Positions ... + if (ticket == 0) + { + // + XPosition positions[]; + int positionsCount = mTrader.GetPositions( + positions, + symbol, + provider, + period, + type + // + ); + if (positionsCount <= 0) + { + return; + } + + // + comment = provider + " Force Close Guard ..."; + + // + mTrader.Close( + positions, + comment + // + ); + } + // + // Close Specific Position ... + else + { + // + XPosition position; + bool hasPosition = mTrader + .GetPosition( + ticket, + position + // + ); + + // + if (hasPosition) + { + // + comment = provider + "(" + ToString(ticket) + ")" + " Force Close Guard ..."; + + // + mTrader.Close( + ticket, + comment + // + ); + } + } + + // + if (IsValid(comment)) + { + mAlert.Alert(comment); + } + } + + // + // Trailing Specified Set Of Positions Stop Losses ... + void HandleGuardTrailingStopAction( + string provider, // Positions Provided by Specific Provider + string symbol, // Trading Symbol + ENUM_POSITION_TYPE type, // Trading Type + ENUM_TIMEFRAMES period, // Specified Time Frame + double sl // Desired SL Value ... + ) + { + // + if (sl <= 0) + { + return; + } + + // + NormalizePrice( + sl, + symbol + // + ); + + // + XPosition positions[]; + int positionsCount = mTrader + .GetPositions( + positions, + symbol, + provider, + period, + type + // + ); + if (positionsCount <= 0) + { + return; + } + + // + int modified = 0; + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + string comment = PrepareSLTrailTag(iPosition.comment); + + // + if (iPosition.sl == sl) + { + continue; + } + + // + bool isModified = mTrader.Modify( + iPosition.ticket, + sl, + iPosition.tp, + comment); + if (isModified) + { + modified++; + } + } + + // + if (modified > 0) + { + // + string message = "(" + ToString(modified) + ") Position's Stop Trailed Successfully ..."; + + // + mAlert.Alert(message); + } + } + + // + // Add Support Signal for Specified Positions ... + void HandleGuardAddSupportPositionAction( + string provider, // Positions Provided by Specific Provider + string symbol, // Trading Symbol + ENUM_POSITION_TYPE type, // Trading Type + ENUM_TIMEFRAMES period // Specified Time Frame + ) + { + // + XSignal support; + bool hasSupport = RequestForSupport( + support, + provider, + symbol, + type, + period + // + ); + + // + if (!hasSupport || !support.IsValid()) + { + return; + } + + // + // TODO: May be need to add Support Tag to comments ... + + // + ENUM_X_SIGNAL_EXECUTION_RESULT reason = NULL; + bool isExecuted = mTrader.ExecuteSignal( + support, + reason); + + // + string comment = NULL; + if (!isExecuted) + { + comment = "Support Execution Failed doue " + ToString(reason); + } + else + { + comment = "Guard Support Signal Executed Successfully ..."; + } + + // + if (IsValid(comment)) + { + mAlert.Alert(comment); + } + } + + // + // Cancel all Placed Orders ... + void HandleGuardCancelPendingOrdersAction( + string provider, // Positions Provided by Specific Provider + string symbol, // Trading Symbol + ENUM_POSITION_TYPE type, // Trading Type + ENUM_TIMEFRAMES period // Specified Time Frame + ) + { + // + XOrder orders[]; + int ordersCount = mTrader.GetOrders( + orders, + symbol, + provider, + period, + ToOrderType(type), + ORDER_STATE_PLACED, + true // Filter by Magic ... + // + ); + if (ordersCount <= 0) + { + return; + } + + // + int canceledOrdersCount = mTrader.CancelOrders(orders); + + // + if (canceledOrdersCount > 0) + { + // + string message = "Guard Cancel (" + ToString(canceledOrdersCount) + ") Pending Orders ..."; + + // + mAlert.Alert(message); + } + } + + // + // Position Filter ... + + // + int FilterSymbolBasedPositions( + string &symbols[], // Hold Symbols ... + XSCPositionHolder *&holders[] // Holder Class Instances ... + ) + { + // + int result = 0; + + // + XPosition positions[]; + int positionsCount = mTrader.GetPositions( + positions // + ); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + // Create a HashMap for Holding Positions ... + CHashMap symbolMap; + + // + // Loop Through Positions ... + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + bool hasIKey = symbolMap.ContainsKey(iPosition.symbol); + + // + // Empty Class Pointer ... + XSCPositionHolder *mHolder = NULL; + + // + // Add new to Map ... + if (!hasIKey) + { + // + mHolder = new XSCPositionHolder(); + if (symbolMap.TrySetValue(iPosition.symbol, mHolder)) + { + mHolder.AddOrUpdateItem(iPosition); + } + } + // + // Update Exists in Map ... + else + { + // + if (symbolMap.TryGetValue(iPosition.symbol, mHolder)) + { + mHolder.AddOrUpdateItem(iPosition); + } + } + } + + // + // Now we Have a Map which Filled Based on Separate Symbols and InDrawDown Positions ... + int mapCount = symbolMap.Count(); + if (!IsValidSize(mapCount)) + { + return result; + } + + // + result = symbolMap.CopyTo( + symbols, + holders // + ); + + // + return result; + } + + // + // Private ... +private: + // + // Props ... + + // + // Signal Event Listeners ... + TOnSignal mOnSignalEventHandlers[]; + + // + // Position Management ... + bool mAllowLong; // Allow Long Trades + bool mAllowShort; // Allow Short Trades + double mMinProfitPerTrade; // Min Profit Per Trade based On Volume Factor (Hedge) + double mMinProfitPerVolumeFactor; // Min Volume Factor for Calculating Profit (Hedge) + double mStaticVolume; // Static Volume for Positions + + // + // Event Handlers ... + TOnStopLoss mOnStopLossTriggered; + TOnTakeProfit mOnTakeProfitTriggered; + TOnDealsChanged mOnDealsChangedHandler; + TOnOrdersChanged mOnOrdersChangedHandler; + TOnPositionsChanged mOnPositionsChangedHandler; + TOnTradeStateChanged mOnTradeStateChangedHandler; +}; + +// \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xhelper.class.ex5 b/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xhelper.class.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..03c5c351728ed3273ba540fa66f5c079f0ff50f7 GIT binary patch literal 5112 zcmdT>WmFW%G5s@3qf9`}@w>Ykhkw8i-=K1MWzlV*~za8~@7xTLA!j+9ZJs)VLe8J4Cqg z5R;*Q5Z8zA zcoQla+x_D&1ONxP0ek@-07rm5zyW{&umFSspoe${5O}!j04yI++Xr3|-~w=cK%fBK zhZFLE!5&`!gZXc^e<(&gOyCVb3LyC4-v9Kc5B0xw+x}Dc(}(%|cPstRTM`01eb_eW zKa>9tbd3%wuOyk{9l!!7cul^;cpCUgKu0iH*TT}OB5=nVI~no8eFh`=iW&<_B#A-e zE||e4X-XeT_w=Wr-)gWEw~-Nz%I*jWals?EyDknD(d~92(SVQlAs{i1a-v}#E8I`W z9Stz7MrD0I=cu@eAkj{2zH*#L{%|-?DGD9Ko|k#)^UMo~r;6oz6*Y$Q_A&j^kj5Oz zP8YSz8#owxxfZxo5{fb;?->qlZM>5LiKtadseknttiu4~*^&FXM+D;xgw{q#68<@PZWU6YLZcbj;te zz6oG`J(l^Mq@iEG55Jf}j~GUxfG1+qxOw3IymX#5_pK{?AckMbCR4R2as7x~*f`ZX z?TGRxV}3*=>b`8x$!9iO&XVFon|LTr&Pt|f|Z2b6R?p_WMI)F)=={6h|i z`Jl5)iI1bg_aFqNqqqlUeO6^KokDK?0$Y=^gtM>tZLFjS<3cA^bb}{fP8A}Tll#i~ znMpePbwE;-(0+(?-Px5bbWVf6WO3h5HgSj%cLiI%8>3luj7%g4carp$mNu|GK3#2A zo6d(MPdSsZS^Be=jugul5A(AFWq~h)Q-WsLLk;7)S(G7NLp?%{3v6MJi%ZJSy-0PB zki`dBR4ToH>uJ&A{iZqMGL%{0A~Gp<;%G;hzbNul2JMX;R<3sw?uU=HpoQ}$ld?#t(m8=&^~s4I(^K8YL*nc-|fuft?{-PURD(H zo3k>7F_w2b6n?6ELEc-IsmRLcU&k_(8gVd6F{mCbD&kUc2oA2?U$+ubL<(pn(3g`@ z-M2SRr~4sKKKKa&LdITM1bF>EwBT#>HPY^N%BpK2x?~=4Efi?lh(>g(IL5p(cF9<) zYxKr6XdDE7EGxjJJlkE*(oAC*uPXq4hwjQmzqQ44%2zGeqQdG(%1ORtZXw;NFCzK# zY}>U|Pd9FC+wFBPkhVD*?!-VEuIE$l4|y5ybzla9xv>WS2m-#vM3M~~wEmJ6=GW#X zmc9K$h>WIABPK?c^c)ia7pQPpW<=g1nMJKJntSwU(#VPQ>G zoVe|A@5jq7OpMlv6_pWln!c!IdJi&Y4X}`?Uqo(avsndk+t_MTU_aV?wOOnXoXo%> zy5DMZXi1hRgrsP+IbT|?0)}fRdQw%}=fj8B2(+}ZpjTV@W} z))=hn`g#%ixjQPkV3OXl>Z7Khf^i2;R#-M(BP=G5o#5MFLxQoGfEJ^Kx|wy6YqFJ; zpzE49@UYQx!FH?nGuAd7FkJGfRjaT?31g4MzDoX15m8SssHlFIFKACYQDFHX_EuJDw^bO_ZVOS8qL zEH~Hu+NJ)?ztd(B#q`2lDI>;lP)=_&8Ef1hszP;VvBYUFUBq-KKQLgL zYYU=cX$%_A+bCKBiy09cR|&iPEx5Chn=r*-*hh<#oM28$?=RfF&;|Cv!+E8GXM?=# zPpJI+I4IU~{KR0CQ;;l_%n^m7!S?K9Oe}oX)uyoJ;c{=M5OMnMIPz6)F{2}9p+-Ib zZTM$HW_0-tSl=r%?S+uUwxV3B$>H48QVCmi#8<5+`voXL=^^ghwd5~QCyj~Q%zV^z zAJO#37fOx~DBBsD9_Et4B`nLrzT#!yS_UH%xq}7{X*5)ih`O%evLlT_{Dv;4&+VDwxaMfGE)mAD{&qw&fRFxR@>t3klBe|9QOowc^by8TW=G~IT z^9>X8+%8l_%4)o;GHs!@3|zX zq10~PfB@NCm0cb!KS0P5m?fg;}H(GpW zTd$rVc)#tYrH&Ez0e>-}c+i{xMnfiNGb4+&4+NLhagFKL9WS7K zGD-v^5*-fWUomWtcQ?^LTh%#Yf0?a;8s`t+kETuN*LSKHzRA8?k%(=ygFMm4By(rP zQecAmV7p*3wlV6Ny6Nz&h+#{;6fv%VGDt$tQwnpx6HH$X3ox+Cgmm>M?lYI6XyWQ4 zi2*_Q>eDiHd-#p6>XV;##s-pV)3)cLVIE|;L4Eqq|(&%nOUVrj2 z`VzKIuugX%#a@1-C5s(ebVAYXcZMpM6ugwmKPQrVesS}eBqoVR*D?xZEVemlo3-b+ zLn$m)Z?_6~TNL#5oYQwo_cnTYn^!2uRH={S%ZPi{F_)A6MSI7N2ThJC#KAgS+aJSC ztE#$>IKn5H=xVNaUI6tw>u{Ds^@?U9vUtRQq|3F&V(68uIh7W*nUbo_?PTuWQQ+Lp zH{Z#ENybU2v;y`5YRPW+=Hz}NelD`{qkIP#m~rwdqZ20FAkydBxU8`x{idHT)$jIG z8qN52Qx?nI-5QfbW%cc8&OVLjE=$_{I|~3I7w;aN#dvU!dmLakqOmt$ROh-Qe3rMAXLa-F4 zV~YV<`?YDI7A^_{wo0vB1Sv2d}VsROX4N6lh%4*T=%AIoYyt70x+zuEoFqB&7o8n!N5x_hF9mup_# zkj>fIH&O&Di%$+B_^Nw%A%mDm-p9I45fjQGUEb*}dSSM0zpV}PL z48q{~BzcDpKd=g)wpOMxT?nK&5=Pz*>B0x%Fe>byq^e3dwPDgoSUG$$zh(Oj@#bu& z+@hA@W2DavpaDllfgtqiezK{CfB3>Yf_1G~N%1Bi{dj-A*UHTb2$ExW$28uX6=0Z3 zb5<_qyd_8dv|fgnXNfl}iJq4=juA+x53$Yi$rUnO_rM`Z4qJ?mBLhoBM@RU)C7TJp zXYY%+Mj1edp77@zhhB{oESwATSIr5qmDa31UE7txLruPr(4=`>-8!2)2jxc!XY;WHu;;|Mqo!8Mw}*5xYq z18iQ{34Aw3L&&rp@K|K`Qq`H88r1o?LCV0j5LEY@O{7%$Ku4sO55?88lkH!dMqFO& z?!j!uVgI_yCt*9}^?3++$u6`!N#=L4B@H=7=fv&t`EAjoL;Z{`!(hUQYOZ&o!_!_U zIxwF=h^zV3{vJXfzY82LlYTXikAXMW1|T#PKdq2f2-v-`eeZP3H64q?>EYRCm%rS( zLRGG4lao_8C&2D&YgJLIRG44F-*=180ACc-V5s15qBi^ejAwWDoGCfxUA)i2Iw{X%12{R>Os-1Z^xTkFY^1ESVV_N` zWKP?zYQV|v=hYdXs}~t_iU3ALbu~ha5b=jPdg^$oM~(R-QU%3Y((m>iJC`{QnMbsY z=X99i+cBQxYorUQHes}TiP!gUU$tTy5U4&~*9wWYC!O?2O zz2_{dMX{0~fydTUNGC*JO-jzaRJgGt*Tnz;mp51Y&VhWlKbftM6scL@toRwFqlSo;V%(65H} z0gCX&{@if4?E7mM$PtV>n#)aHOzYW1w>-Udy6u;XYxjGstd*#q#f;|-x{b>mF}kx&#=__urBp^nvBoiq@~~RZtvIvK`z#xHAL>n}Oi&G6aXAyd^#W`0uuP z|1)WP` zEpxNS(28qf0NP59{m!#MYafWV>9v5YJ1`$Xfo77v-{1fzvAixKi`#J|%MpUwb}U#6 z=^0)0Kp&B#2yq+={TRtGb+wqT0y>@w7@RIOIgLv zBr=r7QL{QU<1v&laQj$+_QFEU&G#tBDk9R0jC-H^_jBRT0|>Qfc5bo!!X~JEa|SaL z!E2V0c4ic4pi|Y4XlI6FKf=+2gDTZE>OagUruGHwzE8Am0xEy=@g{sxh2j#$1{=fA zSQov>g!|%vQk}d6->A$jPc3th=p5T=eR3mcj7F-@uACR8bP{5O3oQXus_7~={ZjG+ zp)^g=fvGp&$-8z_Aw$;$WCRatTF2pL$o(y4_3P zn|7x)wzf4F98cVjV`OtXD#HDnf8=K)0*6zTi=iWm+W*he&R9Eo@hUPfNAvMr?M678 zKoNKJJX~0_oy1&MfNaF;VGdv{pCncc`!p9x&w4`C4(QsiJ+^v9eHSu5UHmmTi5I(o z3E3Ki#yxmH<3+5qGVXp zD2qOi9RV3Gl_`_S4QtclNWYdOmfW<=YxSq85fj&N3utNKNt|bhab73*SXs zRm?{<{b@7?H{Za#00aAx@BQ8;4lS>#Dny8RW$H(MM+p!Rw14XByKVtLy}}9Vu8Fyb z898&0F-+DFcNlT&KdE{UDwI558R7WOvyUA7lqifqHh;aA;^6i!EY&&p0Co7|9nCpP zM^W0*7CfUxVSys29ubCk>)hUv^(Hm;M)zH^2lGo}Me!FyLz7Zv5w4DFH}<_L+hmir zqUXLA@U57T8@2^T`FGE=o65IfwpgiegzXlM+?*)DOueu>RJ+8ejYXFLPNjW)b}dTK zRuXWtnLoAIXa>Jy)QFfw&?}rEQL&Ois_=7R4!!{`OxVuCNz)nmo^$SUu*FllF6^Az|`# zA1!8@@BO+h+f*d*4clf$j z7Wb+dbfJrE%U0MwHf!7&K--PVBOzLb$=3ExD$b-X#!;6u@xfu;3>edAfJuI4KGx z)-=D|_Ihwy#C>`h!^b1dpu%S^pXunjlS*bXD2AI)lzo9cK8Taf-8$X@eoddW!_onz zy2>(DIvpE1s30Ze_-KQ~3himLVM3}oX}K)W0u`y4%2pgkz4KYfw91|s+hJ~J=L&J6 zG&RY+O{oa_h}sZLZ5^Bu7phBpBP`gKe#d^~9i{$sqLMn6=jjvL)xyoLmCQ+6QV*y5 zD5sVwyR@;{gyv2fchM@K3K7Ci`0@DrJ%McMwSvsqVapc5-VxHrk1wgk%%Gv%ApPb` zmztsTMk^PazXf=u_3lK+`67#xkoxnBWnRoV)bR~%KeN&-aT0mAyDR4X*{$=Ogl6GB zFK%yd-Z+IHPkQRBFGs``u3n#}I&;t55!Z1;C?i$`;6txTf&s9D^O%-E!Ss0Rtt$EG z!zz~C?9&ciDceS_{A&%mTsj|jBI!=Awu+D3>P0qsN7hqouPGua30OLsiM#qkxhF(! zZtUz?^fs}NUDS!+5u|)dz1YvlbSn zHW{q9W+VZnS$tGp5e?1*ANxAia?E{(6RH&1Z5k(77`0|+U&s~!`*@-q^k!I6gBq*m zeK=pmX1Ei!hN|-a>EYVt5E(`FbeTBTt(^X*gw>SvZRLaBc=xi^oOUJG$vD5n$LPmM zo`=N%#!AUeH5aIxC76Ua$V*GH-$hNY{ud`7lS=iA_uXT*JTXVm$FeO5M^zt{J$)92 zB4H^0nz^x?f{HUri$068yfbVjx|*Y;)81XsU)XZHtEUlp#nq+$W_`iItL;$Agoarx zjmTz2@#&cn4M{h)DkSPB93W{3H7CCC6`tjeFV=}(e43(Fr`t>P5%>_t?^md2?3Y8= z*y~#M5ZO<}naMPpS7*jc$#IS>Ba9uyG1E9Is2XI$2rsVuqxrN2Yf!_k=J+{Ctx` z>7k(@C3Se5vLHFyfx4ZPTu0@kt&$myD~>XuqW;cXL6rkG7ePQO{LV{z}R$=)wVv-U(2z#q*O zi=$-2{5eN1AIhuvB49&P9CRNRPtjVEdVjLbZ&od#&br@0P+2sk9BEWy2A_et4_15< zU#eo`m?Gksf1Pe8tm;G*nt46<|KRU9c7e|n!7AzLt7i9nC znJTPzKT#?N)rD+Tq^bNBqm2(go6r*!~uW&yYHWy;;|>qei{s5ZQIj|XcALw1iC;s4T2w4H`T_$ zY?Xxp#L7{nytb5Bmxe5Fc9j>&-WafWa|CXtVnocAD&~B2^|{0qFWh|i<@_Pvf@em` zyPatXfHI!HPAZo+cqi$SKTBnbms|Or(ySBK1~#P;O{TBw3T$f*bd=m+FoT{OAKRYBhj%GIT4jj62xrj0LyV=#G@&d1_{kSdh%4=nHitOLmDSP1y=ve4TA(Pv_9U8}GWPpxt#r_L1B8n)eOJ zzWhL+tq+u-9~I8=nRD3AYo6^}V>gBa=!B+$p8mNkSU=VU2Vh{)Qu5*9VS3D?C&GoS z0BOrVy^K?2vGLkmwKL=DhQIA*m)Dq~3a7WBxl+`o6A5yVU3)`xkGtL^?Ja3KEGY(; zODMsC1U&4FZH7w#bY1bA^$Reaydu2VpcaE1jY~P<0$Spf-?A`6wKns($d)B~%#|-D z+RQWNTb^dZ{tk8|>Ji1alodL5Ue3ev24$+OpgSqA4lCXB?N;Q+jVLX-PQ(hrE%1zH zu(nF^d^;W2Wy39zJEwNW4S(IvSQP=PTxt@=k5x`on51#%o;qrfwM3NGI+s9M^oM=F za8dT`@qBYJ_lQenTp_f{KA7RtQc`Bm-O6wxU)yqAG#e=_Teya_416Dqj=HG6MBmM= z*I8gC&1Gbf2=?PqZQNzTvnmml-cBy$b-h=$5c@FB}Ks-J=!&ZyN6SQ#oXs`ZOJ@V_nBHMH{8- zsU@qXG2bfnRgnu!eanM~5*&pY%enTt2RY zd!yR)^BU0Q+Cqoj{hEEUU@XF^OXk{;>5IHUi$<>!l8nO~0_|#F) zo`_}uE`ej?$tkYqMLmpaU($>V{qOfF=mK82b(P$bd7n<|$-iyAm54&za|PFLuo)QV zgf5uh^N&(?Idl1DV9`HMZ#-o=nqN)&!%!R6cBM^$BhnaSDb(|dNA1_@O5?iOad7=*VlH`y8tG(A-U zmunKUtW8>PH+sHO;9ylA1KpNioNk|-iCAm2hxxM2dT~UuB`=-xC*xhy653#d5WgZI)aL$I(^5G+f0xc3>Kw$f@-mJTU!y=aId} zh4^yQT-kM^H<;?cMw+Nc1ko@~ABB_%22~`s(?os)3Facc##1{1@sPMk)BX|Ly!q&6 zXS@)?d2gXr2)3K`G%d)P;M1l0K&qv5-|XCYD68@+c-yOKatH*m=qJ#_aM2>)E2?dFai&RIef)o0WgZ0tjKCO|K|)T&l%s;Hf?VKIXPpQII7jiFNywiX?P8_)FhTa zLG8ycL08=UYU_h8%g5?YxMEu|3BZ4XGFTW;gT(Xdf$X}$&s|Eg&S%{L2g^(b2|^~g zF1K>9I!U~j4Z%CkScl$cO*{;eeFC4c&lLXB(9k@xu}ADvtP0<_rnB}-_9E5 zz$pFezqLDh!&9CC7q8DD z*s$dh=GypQr&Ufzp$3mRDs(yb&g29B>p*JMi&+kbs>^O7 z@^0(8;j6c&-cSDH`SG7`)KkVW+8uR9sHqL#3BX4q8Q-ZC>WrXFOoNKh4Iy6)ey{_*F2VgX$q!fMf`ZK1-bT98^+V9ItHO#B! nkvHbN6OmT+CtBC(xbT_O@3l)6Kz^>b+E5W8({*hTm$d%@xh)D` literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xhttp.class.mq5 b/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xhttp.class.mq5 new file mode 100644 index 0000000..82adadb --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xhttp.class.mq5 @@ -0,0 +1,373 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCHttp +// Description: provides all HTTP requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Definitions ... + +// +enum X_HTTP_METHOD +{ + X_HTTP_GET, + X_HTTP_POST +}; + +// +// Imports ... + +// +// Includes ... +#include "../Classes/x-saherelm.base.class.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// a Class for Manage Account ... +class XSCHttp : public XSCBase +{ + // + // Public ... +public: + // + // Constructor ... + void XSCHttp() + { + XSCHttp("", 10000); + } + void XSCHttp( + string path, // Base Folder to Store Data + int timeout // base timeout for Requests + ) + { + // + Path(path); + Timeout(timeout); + } + + // + // Deconstructor ... + void ~XSCHttp() + { + } + + // + // Properties Getter(s) / Setter(s) ... + + // + // Path ... + void Path(string value) + { + // + mPath = value; + + // + if (!IsValid(mPath)) + { + mPath = GetTag(); + } + } + + string Path() + { + return mPath; + } + + // + // Timeout ... + void Timeout(int value) + { + mTimeout = value; + } + + // + int Timeout() + { + return mTimeout; + } + + // + // Error ... + int Error() + { + return mError; + } + + // + // Response ... + string Response() + { + return mResponse; + } + + // + // Overrides ... + string GetTag() override + { + return GetSpecificToken(this); + } + + // + // Tools ... + + // + // Send Global Request ... + int SendRequest( + X_HTTP_METHOD method, // Httm Request Method + const string url, // Server Address + const string headers, // Headers providing + const char &payload[], // the Data which needs to Send + char &response[], // Response of request + string responseHeaders, // Response Headers + int timeout = 500 // Timeout for response default is 500 + ) + { + // + int result = -1; + + // + string strMethod = ToString(method); + if (StringLen(strMethod) == 0) + { + return result; + } + + // + // Reset State ... + ResetState(); + + // + result = WebRequest( + strMethod, + url, + headers, + timeout, + payload, + response, + responseHeaders); + + // + if (result < 0) + { + mError = GetLastError(); + } + else + { + mResponse = CharArrayToString(response); + } + + // + return result; + } + + // + // Get Request ... + int GetRequest( + const string url, // Server Address + const string headers, // Headers providing + const char &payload[], // the Data which needs to Send + char &response[], // Response of request + string responseHeaders, // Response Headers + int timeout = 500 // Timeout for response default is 500 + ) + { + // + int result = SendRequest( + X_HTTP_GET, + url, + headers, + payload, + response, + responseHeaders, + timeout); + + // + return result; + } + + // + // Post Request ... + int PostRequest( + const string url, // Server Address + const string headers, // Headers providing + const char &payload[], // the Data which needs to Send + char &response[], // Response of request + string responseHeaders, // Response Headers + int timeout = 500 // Timeout for response default is 500 + ) + { + // + int result = SendRequest( + X_HTTP_POST, + url, + headers, + payload, + response, + responseHeaders, + timeout); + + // + return result; + } + + // + // Handle Download Specific URL Content to Specific Path and File Name ... + bool Download( + string url, // the URL address which going to download + string fileName // Specify Destination file name to Store Response + ) + { + // + bool result = false; + + // + string filePath = GetFilePath(fileName); + string cookie = NULL; + string referer = NULL; + int timeout = Timeout(); + + // + char payload[]; + string headers; + char response[]; + string responseHeaders; + + // + // Send Request ... + int requestResult = GetRequest( + url, + headers, + payload, + response, + responseHeaders, + timeout); + + // + // Define File Handler ... + int mFileHandler = FileOpen( + filePath, + FILE_WRITE | FILE_BIN); + if (mFileHandler == INVALID_HANDLE) + { + // + mError = GetLastError(); + return result; + } + + // + // Write Response to File ... + uint writed = FileWriteArray( + mFileHandler, + response, + 0, + ArraySize(response)); + FileFlush(mFileHandler); + FileClose(mFileHandler); + + // + result = writed > 0; + + // + return result; + } + + // + // END Provided Functions ... + // + + // + // Protected ... +protected: + // + // Destintion Folder Path ... + string mPath; + + // + // WEB Request Timeout Value ... + int mTimeout; + + // + // WEB Request's Response ... + string mResponse; + + // + // Error Value ... + int mError; + + // + // Private ... +private: + // + // Reset Errors State ... + void ResetState() + { + // + // Reset Errors ... + mError = -1; + mResponse = ""; + ResetLastError(); + } + + // + // Generate Full File Path ... + string GetFilePath(string fileName) + { + // + string result = ""; + + // + result = + // + Path() + "\\" + fileName + // + ; + + // + return result; + } +}; + +// +// Tools ... + +// +// Convert enum to String ... +string ToString(X_HTTP_METHOD method) +{ + // + string result = ""; + + // + switch (method) + { + // + case X_HTTP_GET: + result = "GET"; + break; + + // + case X_HTTP_POST: + result = "POST"; + break; + } + + // + return result; +} + +// \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xmd5.class.ex5 b/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xmd5.class.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..91b0e5de3ed84ee20155c27927b0291a88741ccd GIT binary patch literal 4620 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 literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xmd5.class.mq5 b/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xmd5.class.mq5 new file mode 100644 index 0000000..3311aa5 --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xmd5.class.mq5 @@ -0,0 +1,441 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCMD5 +// Description: Provides MD5 Hashing Requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// START Definitions ... +// + +// +static uchar _md5_PADDING[64] = + { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +// +#define _md5_F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define _md5_G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define _md5_H(x, y, z) ((x) ^ (y) ^ (z)) +#define _md5_I(x, y, z) ((y) ^ ((x) | (~z))) +#define _md5_ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) + +// +#define _md5_FF(a, b, c, d, x, s, ac) \ + { \ + (a) += _md5_F((b), (c), (d)) + (x) + (uint)(ac); \ + (a) = _md5_ROTATE_LEFT((a), (s)); \ + (a) += (b); \ + } + +// +#define _md5_GG(a, b, c, d, x, s, ac) \ + { \ + (a) += _md5_G((b), (c), (d)) + (x) + (uint)(ac); \ + (a) = _md5_ROTATE_LEFT((a), (s)); \ + (a) += (b); \ + } + +// +#define _md5_HH(a, b, c, d, x, s, ac) \ + { \ + (a) += _md5_H((b), (c), (d)) + (x) + (uint)(ac); \ + (a) = _md5_ROTATE_LEFT((a), (s)); \ + (a) += (b); \ + } + +// +#define _md5_II(a, b, c, d, x, s, ac) \ + { \ + (a) += _md5_I((b), (c), (d)) + (x) + (uint)(ac); \ + (a) = _md5_ROTATE_LEFT((a), (s)); \ + (a) += (b); \ + } + +// +#define _md5_INIT_STATE_0 0x67452301 +#define _md5_INIT_STATE_1 0xefcdab89 +#define _md5_INIT_STATE_2 0x98badcfe +#define _md5_INIT_STATE_3 0x10325476 + +// +#define _md5_S11 7 +#define _md5_S12 12 +#define _md5_S13 17 +#define _md5_S14 22 + +// +#define _md5_S21 5 +#define _md5_S22 9 +#define _md5_S23 14 +#define _md5_S24 20 + +// +#define _md5_S31 4 +#define _md5_S32 11 +#define _md5_S33 16 +#define _md5_S34 23 + +// +#define _md5_S41 6 +#define _md5_S42 10 +#define _md5_S43 15 +#define _md5_S44 21 + +// +// END Definitions ... +// + +// +// XCMD5 a library for Hashing ... +class XSCMD5 +{ + // + // Public Provides ... +public: + // + // Protected Provides ... + + // + // Constructor ... + XSCMD5(void) {} + + // + // Deconstructor ... + ~XSCMD5(void) {} + + // + // Hash Specified Char Array ... + string Hash( + uchar &mSource[], // Specify Char Array to Hash + int mLength = 0 // Specify Length of Char Array which required to hash + ) + { + // + string result = ""; + + // + int sourceCount = ArraySize(mSource); + + // + // Validate Args ... + if ( + sourceCount <= 0 || + (sourceCount > 0 && mLength > sourceCount)) + { + return result; + } + + // + // Normalize Args ... + if (mLength == 0) + { + mLength = sourceCount; + } + + // + // Init MD5 ... + MD5Init(); + + // + // Update Buffer ... + MD5Update(mSource, mLength); + + // + // Calculate Result ... + result = MD5Final(); + + // + return result; + } + + // + // Hash Specified String ... + string Hash( + string mSource // Specified String + ) + { + // + string result = ""; + + // + // Converts String to Char Array ... + uchar bytes[]; + StringToCharArray( + mSource, + bytes, + 0, + StringLen(mSource)); + + // + result = Hash( + bytes, + ArraySize(bytes)); + + // + return result; + } + +protected: + // + // Private Provides ... +private: + // + uint m_lMD5[4]; + uint m_nCount[2]; + uchar m_lpszBuffer[64]; + + // + // Convert Byte to DWord ... + void ByteToDWord(int &out[], uint &in[], uint len) + { + // + uint i = 0; + uint j = 0; + + // + for (; j < len; i++, j += 4) + { + out[i] = (int)in[j] | (int)in[j + 1] << 8 | (int)in[j + 2] << 16 | (int)in[j + 3] << 24; + } + } + + // + // Convert DWord to Byte ... + void DWordToByte(uchar &out[], int &in[], uint len) + { + // + uint i = 0; + uint j = 0; + + // + for (; j < len; i++, j += 4) + { + // + out[j] = (uchar)(in[i] & 0xff); + out[j + 1] = (uchar)((in[i] >> 8) & 0xff); + out[j + 2] = (uchar)((in[i] >> 16) & 0xff); + out[j + 3] = (uchar)((in[i] >> 24) & 0xff); + } + } + + // + // Init MD5 Array ... + void MD5Init() + { + // + ArrayInitialize(m_lpszBuffer, 64); + + // + m_nCount[0] = m_nCount[1] = 0; + m_lMD5[0] = _md5_INIT_STATE_0; + m_lMD5[1] = _md5_INIT_STATE_1; + m_lMD5[2] = _md5_INIT_STATE_2; + m_lMD5[3] = _md5_INIT_STATE_3; + } + + // + // Update MD5 ... + void MD5Update(uchar &inBuf[], uint inLen) + { + // + int i, ii; + int mdi; + + // + uint in[16]; + int i0 = 0; + + // + mdi = (int)((m_nCount[0] >> 3) & 0x3F); + + // + if ((m_nCount[0] + ((uint)inLen << 3)) < m_nCount[0]) + { + m_nCount[1]++; + } + + // + m_nCount[0] += ((uint)inLen << 3); + m_nCount[1] += ((uint)inLen >> 29); + + // + while ((inLen--) > 0) + { + // + m_lpszBuffer[mdi++] = inBuf[i0++]; + if (mdi == 0x40) + { + // + for (i = 0, ii = 0; i < 16; i++, ii += 4) + { + in[i] = (((uint)m_lpszBuffer[ii + 3]) << 24) | (((uint)m_lpszBuffer[ii + 2]) << 16) | (((uint)m_lpszBuffer[ii + 1]) << 8) | ((uint)m_lpszBuffer[ii]); + } + + // + Transform(m_lMD5, in); + + // + mdi = 0; + } + } + } + + // + // Finalize an MD5 Expression ... + string MD5Final() + { + // + uchar bits[8]; + int nIndex; + uint nPadLen; + const int nMD5Size = 16; + uchar lpszMD5[16]; + string temp; + string out = ""; + int i; + + // + DWordToByte(bits, m_nCount, 8); + nIndex = (int)((m_nCount[0] >> 3) & 0x3f); + nPadLen = (nIndex < 56) ? (56 - nIndex) : (120 - nIndex); + MD5Update(_md5_PADDING, nPadLen); + MD5Update(bits, 8); + DWordToByte(lpszMD5, m_lMD5, nMD5Size); + + // + for (i = 0; i < nMD5Size; i++) + { + // + if (lpszMD5[i] == 0) + { + temp = "00"; + } + else if (lpszMD5[i] <= 15) + { + temp = StringFormat("0%x", lpszMD5[i]); + } + else + { + temp = StringFormat("%x", lpszMD5[i]); + } + + // + out += temp; + } + + // + lpszMD5[0] = '\0'; + + // + return (out); + } + + // + // Transform Buffers ... + void Transform(uint &buf[], uint &in[]) + { + // + uint a = buf[0], b = buf[1], c = buf[2], d = buf[3]; + + // + _md5_FF(a, b, c, d, in[0], _md5_S11, 0xD76AA478); + _md5_FF(d, a, b, c, in[1], _md5_S12, 0xE8C7B756); + _md5_FF(c, d, a, b, in[2], _md5_S13, 0x242070DB); + _md5_FF(b, c, d, a, in[3], _md5_S14, 0xC1BDCEEE); + _md5_FF(a, b, c, d, in[4], _md5_S11, 0xF57C0FAF); + _md5_FF(d, a, b, c, in[5], _md5_S12, 0x4787C62A); + _md5_FF(c, d, a, b, in[6], _md5_S13, 0xA8304613); + _md5_FF(b, c, d, a, in[7], _md5_S14, 0xFD469501); + _md5_FF(a, b, c, d, in[8], _md5_S11, 0x698098D8); + _md5_FF(d, a, b, c, in[9], _md5_S12, 0x8B44F7AF); + _md5_FF(c, d, a, b, in[10], _md5_S13, 0xFFFF5BB1); + _md5_FF(b, c, d, a, in[11], _md5_S14, 0x895CD7BE); + _md5_FF(a, b, c, d, in[12], _md5_S11, 0x6B901122); + _md5_FF(d, a, b, c, in[13], _md5_S12, 0xFD987193); + _md5_FF(c, d, a, b, in[14], _md5_S13, 0xA679438E); + _md5_FF(b, c, d, a, in[15], _md5_S14, 0x49B40821); + + // + _md5_GG(a, b, c, d, in[1], _md5_S21, 0xF61E2562); + _md5_GG(d, a, b, c, in[6], _md5_S22, 0xC040B340); + _md5_GG(c, d, a, b, in[11], _md5_S23, 0x265E5A51); + _md5_GG(b, c, d, a, in[0], _md5_S24, 0xE9B6C7AA); + _md5_GG(a, b, c, d, in[5], _md5_S21, 0xD62F105D); + _md5_GG(d, a, b, c, in[10], _md5_S22, 0x02441453); + _md5_GG(c, d, a, b, in[15], _md5_S23, 0xD8A1E681); + _md5_GG(b, c, d, a, in[4], _md5_S24, 0xE7D3FBC8); + _md5_GG(a, b, c, d, in[9], _md5_S21, 0x21E1CDE6); + _md5_GG(d, a, b, c, in[14], _md5_S22, 0xC33707D6); + _md5_GG(c, d, a, b, in[3], _md5_S23, 0xF4D50D87); + _md5_GG(b, c, d, a, in[8], _md5_S24, 0x455A14ED); + _md5_GG(a, b, c, d, in[13], _md5_S21, 0xA9E3E905); + _md5_GG(d, a, b, c, in[2], _md5_S22, 0xFCEFA3F8); + _md5_GG(c, d, a, b, in[7], _md5_S23, 0x676F02D9); + _md5_GG(b, c, d, a, in[12], _md5_S24, 0x8D2A4C8A); + + // + _md5_HH(a, b, c, d, in[5], _md5_S31, 0xFFFA3942); + _md5_HH(d, a, b, c, in[8], _md5_S32, 0x8771F681); + _md5_HH(c, d, a, b, in[11], _md5_S33, 0x6D9D6122); + _md5_HH(b, c, d, a, in[14], _md5_S34, 0xFDE5380C); + _md5_HH(a, b, c, d, in[1], _md5_S31, 0xA4BEEA44); + _md5_HH(d, a, b, c, in[4], _md5_S32, 0x4BDECFA9); + _md5_HH(c, d, a, b, in[7], _md5_S33, 0xF6BB4B60); + _md5_HH(b, c, d, a, in[10], _md5_S34, 0xBEBFBC70); + _md5_HH(a, b, c, d, in[13], _md5_S31, 0x289B7EC6); + _md5_HH(d, a, b, c, in[0], _md5_S32, 0xEAA127FA); + _md5_HH(c, d, a, b, in[3], _md5_S33, 0xD4EF3085); + _md5_HH(b, c, d, a, in[6], _md5_S34, 0x04881D05); + _md5_HH(a, b, c, d, in[9], _md5_S31, 0xD9D4D039); + _md5_HH(d, a, b, c, in[12], _md5_S32, 0xE6DB99E5); + _md5_HH(c, d, a, b, in[15], _md5_S33, 0x1FA27CF8); + _md5_HH(b, c, d, a, in[2], _md5_S34, 0xC4AC5665); + + // + _md5_II(a, b, c, d, in[0], _md5_S41, 0xF4292244); + _md5_II(d, a, b, c, in[7], _md5_S42, 0x432AFF97); + _md5_II(c, d, a, b, in[14], _md5_S43, 0xAB9423A7); + _md5_II(b, c, d, a, in[5], _md5_S44, 0xFC93A039); + _md5_II(a, b, c, d, in[12], _md5_S41, 0x655B59C3); + _md5_II(d, a, b, c, in[3], _md5_S42, 0x8F0CCC92); + _md5_II(c, d, a, b, in[10], _md5_S43, 0xFFEFF47D); + _md5_II(b, c, d, a, in[1], _md5_S44, 0x85845DD1); + _md5_II(a, b, c, d, in[8], _md5_S41, 0x6FA87E4F); + _md5_II(d, a, b, c, in[15], _md5_S42, 0xFE2CE6E0); + _md5_II(c, d, a, b, in[6], _md5_S43, 0xA3014314); + _md5_II(b, c, d, a, in[13], _md5_S44, 0x4E0811A1); + _md5_II(a, b, c, d, in[4], _md5_S41, 0xF7537E82); + _md5_II(d, a, b, c, in[11], _md5_S42, 0xBD3AF235); + _md5_II(c, d, a, b, in[2], _md5_S43, 0x2AD7D2BB); + _md5_II(b, c, d, a, in[9], _md5_S44, 0xEB86D391); + + // + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; + } +}; diff --git a/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xprovider.class.ex5 b/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xprovider.class.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..05aab821305a24a6c9067a0f2e8e16e4974df3c4 GIT binary patch literal 7658 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 HOZoo-8@)S> literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xtrade.class.mq5 b/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xtrade.class.mq5 new file mode 100644 index 0000000..1554dad --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Classes/x-saherelm.xtrade.class.mq5 @@ -0,0 +1,3682 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCTrade +// Description: provides all Trade requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.base.class.mq5" +#include "../Libraries/x-saherelm.xtrade.lib.mq5" +#include "../Classes/x-saherelm.xaccount.class.mq5" + +// +// Definitions ... + +// +// Overrides ... + +// +// XCTrade Base Class ... +class XSCTradeBase : public CTrade +{ +public: + // + // Modify Specific Position, by Specific Comment ... + bool PositionModify( + const string symbol, // Symbol + const double sl, // Stop Loss + const double tp, // Take Profit + const string comment = "" // Comment For Modify + ) + { + // + // check stopped + if (IsStopped(__FUNCTION__)) + { + return (false); + } + + // + // check position existence + if (!SelectPosition(symbol)) + { + return (false); + } + + // + // clean + ClearStructures(); + + // + // setting request + m_request.action = TRADE_ACTION_SLTP; + m_request.symbol = symbol; + m_request.magic = m_magic; + m_request.sl = sl; + m_request.tp = tp; + m_request.position = PositionGetInteger(POSITION_TICKET); + + // + // Specified Comment ... + if (StringLen(comment) > 0) + { + m_request.comment = comment; + } + + // + // action and return the result + return (OrderSend(m_request, m_result)); + } + bool PositionModify( + const ulong ticket, // Position Ticket + const double sl, // Stop Loss + const double tp, // Take Profit + const string comment = "" // Comment For Modify + ) + { + // + // check stopped + if (IsStopped(__FUNCTION__)) + { + return (false); + } + + // + // check position existence + if (!PositionSelectByTicket(ticket)) + { + return (false); + } + + // + // clean + ClearStructures(); + + // + // setting request + m_request.action = TRADE_ACTION_SLTP; + m_request.position = ticket; + m_request.symbol = PositionGetString(POSITION_SYMBOL); + m_request.magic = m_magic; + m_request.sl = sl; + m_request.tp = tp; + + // + // Specified Comment ... + if (StringLen(comment) > 0) + { + m_request.comment = comment; + } + + // + // action and return the result + return (OrderSend(m_request, m_result)); + } + + // + // Close Specific Position, by Specific Comment ... + bool PositionClose( + const string symbol, // Symbol + const ulong deviation, // Deviation + const string comment = "" // Comment For Close + ) + { + // + bool partial_close = false; + int retry_count = 10; + uint retcode = TRADE_RETCODE_REJECT; + + // + // check stopped + if (IsStopped(__FUNCTION__)) + { + return (false); + } + + // + // clean + ClearStructures(); + + // + // check filling + if (!FillingCheck(symbol)) + { + return (false); + } + + // + do + { + // + // check + if (SelectPosition(symbol)) + { + // + if ((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) + { + // + // prepare request for close BUY position + m_request.type = ORDER_TYPE_SELL; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_BID); + } + else + { + // + // prepare request for close SELL position + m_request.type = ORDER_TYPE_BUY; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_ASK); + } + } + else + { + // + // position not found + m_result.retcode = retcode; + return (false); + } + + // + // setting request + m_request.action = TRADE_ACTION_DEAL; + m_request.symbol = symbol; + m_request.volume = PositionGetDouble(POSITION_VOLUME); + m_request.magic = m_magic; + m_request.deviation = (deviation == ULONG_MAX) ? m_deviation : deviation; + m_request.position = PositionGetInteger(POSITION_TICKET); + + // + // Specify Comment ... + m_request.comment = comment; + + // + // check volume + double max_volume = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX); + if (m_request.volume > max_volume) + { + // + m_request.volume = max_volume; + partial_close = true; + } + else + { + partial_close = false; + } + + // + // hedging? just send order + if (IsHedging()) + { + return (OrderSend(m_request, m_result)); + } + + // + // order send + if (!OrderSend(m_request, m_result)) + { + // + if (--retry_count != 0) + { + continue; + } + + // + if (retcode == TRADE_RETCODE_DONE_PARTIAL) + { + m_result.retcode = retcode; + } + + // + return (false); + } + + // + //--- WARNING. If position volume exceeds the maximum volume allowed for deal, + //--- and when the asynchronous trade mode is on, for safety reasons, position is closed not completely, + //--- but partially. It is decreased by the maximum volume allowed for deal. + if (m_async_mode) + { + break; + } + + // + retcode = TRADE_RETCODE_DONE_PARTIAL; + if (partial_close) + { + Sleep(1000); + } + } while (partial_close); + + // + // succeed + return (true); + } + bool PositionClose( + const ulong ticket, // Position Ticket + const ulong deviation, // Deviation + const string comment = "" // Comment For Close + ) + { + // + // check stopped + if (IsStopped(__FUNCTION__)) + { + return (false); + } + + // + // check position existence + if (!PositionSelectByTicket(ticket)) + { + return (false); + } + + // + string symbol = PositionGetString(POSITION_SYMBOL); + + // + // clean + ClearStructures(); + + // + // check filling + if (!FillingCheck(symbol)) + { + return (false); + } + + // + // check + if ((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) + { + // + // prepare request for close BUY position + m_request.type = ORDER_TYPE_SELL; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_BID); + } + else + { + // + // prepare request for close SELL position + m_request.type = ORDER_TYPE_BUY; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_ASK); + } + + // + // setting request + m_request.action = TRADE_ACTION_DEAL; + m_request.position = ticket; + m_request.symbol = symbol; + m_request.volume = PositionGetDouble(POSITION_VOLUME); + m_request.magic = m_magic; + m_request.deviation = (deviation == ULONG_MAX) ? m_deviation : deviation; + + // + // Specify Comment ... + m_request.comment = comment; + + // + // close position + return (OrderSend(m_request, m_result)); + } + + // + // Partial Close Specific Position, by Specific Comment ... + bool PositionClosePartial( + const string symbol, // Symbol + const double volume, // Partial Closing Volume + const ulong deviation, // Deviation + const string comment = "" // Comment For Close + ) + { + // + uint retcode = TRADE_RETCODE_REJECT; + + // + // check stopped + if (IsStopped(__FUNCTION__)) + { + return (false); + } + + // + // for hedging mode only + if (!IsHedging()) + { + return (false); + } + + // + // clean + ClearStructures(); + + // + // check filling + if (!FillingCheck(symbol)) + { + return (false); + } + + // + // check + if (SelectPosition(symbol)) + { + // + if ((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) + { + // + // prepare request for close BUY position + m_request.type = ORDER_TYPE_SELL; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_BID); + } + else + { + // + // prepare request for close SELL position + m_request.type = ORDER_TYPE_BUY; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_ASK); + } + } + else + { + // + // position not found + m_result.retcode = retcode; + return (false); + } + + // + // check volume + double position_volume = PositionGetDouble(POSITION_VOLUME); + if (position_volume > volume) + { + position_volume = volume; + } + + // + // setting request + m_request.action = TRADE_ACTION_DEAL; + m_request.symbol = symbol; + m_request.volume = position_volume; + m_request.magic = m_magic; + m_request.deviation = (deviation == ULONG_MAX) ? m_deviation : deviation; + m_request.position = PositionGetInteger(POSITION_TICKET); + + // + // Specifieng Comment ... + m_request.comment = comment; + + // + // hedging? just send order + return (OrderSend(m_request, m_result)); + } + bool PositionClosePartial( + const ulong ticket, // Position Ticket + const double volume, // Partial Closing Volume + const ulong deviation, // Deviation + const string comment = "" // Comment For Close + ) + { + // + // check stopped + if (IsStopped(__FUNCTION__)) + { + return (false); + } + + // + // for hedging mode only + if (!IsHedging()) + { + return (false); + } + + // + // check position existence + if (!PositionSelectByTicket(ticket)) + { + return (false); + } + + // + string symbol = PositionGetString(POSITION_SYMBOL); + + // + // clean + ClearStructures(); + + // + // check filling + if (!FillingCheck(symbol)) + { + return (false); + } + + // + // check + if ((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) + { + // + // prepare request for close BUY position + m_request.type = ORDER_TYPE_SELL; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_BID); + } + else + { + // + // prepare request for close SELL position + m_request.type = ORDER_TYPE_BUY; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_ASK); + } + + // + // check volume + double position_volume = PositionGetDouble(POSITION_VOLUME); + if (position_volume > volume) + { + position_volume = volume; + } + + // + // setting request + m_request.action = TRADE_ACTION_DEAL; + m_request.position = ticket; + m_request.symbol = symbol; + m_request.volume = position_volume; + m_request.magic = m_magic; + m_request.deviation = (deviation == ULONG_MAX) ? m_deviation : deviation; + + // + // Specifieng Comment ... + m_request.comment = comment; + + // + // close position + return (OrderSend(m_request, m_result)); + } +}; + +// +// Implementation ... + +// +// a Class For Manage Trades and Handle Trading Actions ... +class XSCTrade : public XSCBase +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructors ... + void XSCTrade( + int slippage, // Specify Slippage + ulong magicNumber, // Specify Magic Number + int manageInterval, // Manager Check Intervals Seconds + double maxAllowedSpread, // Max Allowed Spred for Opening Trades + int maxAllowedPositions, // Max Allowed Positions + double maxAllowedDrawdownFactor // Max Allowed Drawdown Factor + ) + { + // + // Setting Props ... + mSlippage = slippage; + mMagicNumber = magicNumber; + + // + mManageInterval = manageInterval; + + // + mMaxAllowedSpread = maxAllowedSpread; + mMaxAllowedPositions = maxAllowedPositions; + mMaxAllowedDrawdownFactor = maxAllowedDrawdownFactor; + + // + mAccount = new XSCAccount(); + + // + // Instance Base Trader Class ... + mTrader = new XSCTradeBase(); + + // + // Configuring Base Trader Class ... + mTrader.SetAsyncMode(false); + mTrader.SetDeviationInPoints(mSlippage); + mTrader.SetExpertMagicNumber(mMagicNumber); + + // + // Setting Log Level ... + mTrader.LogLevel(LOG_LEVEL_ERRORS); + + // + // OnTrade Context ... + + // + mDaysForRead = 1; + mScanStarted = false; + + // + // Reset On Trade Counter ... + ResetOnTradeContext(); + + // + // Init On Trade Context ... + InitOnTradeContext(); + } + + // + // Deconstructor ... + ~XSCTrade() + { + // + // Remove Pointer ... + delete mTrader; + delete mAccount; + } + + // + // Props ... + + // + // Retrieve Slippage ... + int GetSlippage() + { + return mSlippage; + } + + // + // Retrieve Magic Number ... + ulong GetMagicNumber() + { + return mMagicNumber; + } + + // + int GetManageInterval() + { + return mManageInterval; + } + + // + double GetMaxAllowedSpread() + { + return mMaxAllowedSpread; + } + + // + int GetMaxAllowedPositions() + { + return mMaxAllowedPositions; + } + + // + double GetMaxAllowedDrawdownFactor() + { + return mMaxAllowedDrawdownFactor; + } + + // + // Add Event Listeners ... + + // + // Add New Deals Changed Event Handler ... + void AddOnTradeStateChangedEventHandler(TOnTradeStateChanged handler) + { + // + Add( + handler, + mTradeStateChangedEventHandlers + // + ); + } + + // + // Add New Deals Changed Event Handler ... + void AddOnDealsChangedEventHandler(TOnDealsChanged handler) + { + // + Add( + handler, + mDealsChangedEventHandlers + // + ); + } + + // + // Add New Orders Changed Event Handler ... + void AddOnOrdersChangedEventHandler(TOnOrdersChanged handler) + { + // + Add( + handler, + mOrdersChangedEventHandlers + // + ); + } + + // + // Add New Positions Changed Event Handler ... + void AddOnPositionsChangedEventHandler(TOnPositionsChanged handler) + { + // + Add( + handler, + mPositionsChangedEventHandlers + // + ); + } + + // + // Add New Stop Loss Event Handler ... + void AddOnStopLossEventHandler(TOnStopLoss handler) + { + // + Add( + handler, + mStopLossEventHandlers + // + ); + } + + // + // Add New Stop Loss Event Handler ... + void AddOnTakeProfitEventHandler(TOnTakeProfit handler) + { + // + Add( + handler, + mTakeProfitEventHandlers + // + ); + } + + // + // Functions ... + + // + // Handlers ... + + // + // Process On Trade Requirement ... + // this Only Used when we Have to Proccess OnTrade Event in EA(s) ... + void HandleOnTradeEvent( + XOnTradeHandlerState &result // Hold's Result + ) + { + // + result.Clean(); + + // + if (mScanStarted) + { + // + ProcessOnTradeContext(result); + } + else + { + // + // Init Trade Context ... + InitOnTradeContext(); + + // + return; + } + + // + // Here we Can Check the Start ... + bool isValid = + // + result.IsValid() && + // + !result.hasNewDeal && + !result.hasNewOrder && + !result.hasNewPosition && + !result.hasNewHistoryOrder + // + ; + if (!isValid) + { + return; + } + + // + // State ... + + // + // Notfy Trade State Changed Event ... + NotifyTradeStateChangeEvent(result); + + // + // Deals ... + if (result.hasNewDeal) + { + // + // Notfy Deals Changed Event ... + NotifyDealsChangeEvent(result.newDeals); + + // + // Retrieve Last Deal ... + XDeal deals[]; + int dealsCount = GetDeals(deals); + if (dealsCount > 0) + { + // + XDeal lastDeal = deals[0]; + + // + if (lastDeal.reason == DEAL_REASON_TP) + { + NotifyTakeProfitEvent(lastDeal); + } + else if (lastDeal.reason == DEAL_REASON_SL) + { + NotifyStopLossEvent(lastDeal); + } + } + } + + // + // Orders ... + if (result.hasNewOrder || result.hasNewHistoryOrder) + { + // + // Notfy Orders Changed Event ... + NotifyOrdersChangeEvent(result.newOrders + result.newHistoryOrders); + } + + // + // Positions ... + if (result.hasNewPosition) + { + // + // Notfy Positions Changed Event ... + NotifyPositionsChangeEvent(result.newPositions); + } + } + + // + // This Must be Called Every time OnTrade Event Happening ... + // this Used for Implementing Custom Senarios ... + XOnTradeHandlerState HandleOnTrade() + { + // + // Handle OnTrade Event ... + XOnTradeHandlerState state; + HandleOnTradeEvent(state); + if ( + !state.hasNewDeal && + !state.hasNewOrder && + !state.hasNewPosition && + !state.hasNewHistoryOrder) + { + return state; + } + + // + // State ... + + // + // Notfy Trade State Changed Event ... + NotifyTradeStateChangeEvent(state); + + // + // DEALS ... + if (state.hasNewDeal) + { + // + // Notfy Deals Changed Event ... + NotifyDealsChangeEvent(state.newDeals); + + // + // Retrieve Last Deal ... + XDeal deals[]; + GetDeals(deals); + int dealsCount = ArraySize(deals); + if (dealsCount > 0) + { + // + XDeal lastDeal = deals[0]; + + // + if (lastDeal.reason == DEAL_REASON_TP) + { + NotifyTakeProfitEvent(lastDeal); + } + else if (lastDeal.reason == DEAL_REASON_SL) + { + NotifyStopLossEvent(lastDeal); + } + } + } + + // + // ORDERS ... + if (state.hasNewOrder || state.hasNewHistoryOrder) + { + // + // Notfy Orders Changed Event ... + NotifyOrdersChangeEvent(state.newOrders + state.newHistoryOrders); + } + + // + // POSITIONS ... + if (state.hasNewPosition) + { + // + // Notfy Positions Changed Event ... + NotifyPositionsChangeEvent(state.newPositions); + } + + // + return state; + } + + // + // Trade Actions ... + + // + // Main ... + + // + // Policies ... + + // + // Check Acocunt Balance is Allow new Trades or not ... + bool CheckEquityForTrade() + { + // + bool result = false; + + // + if (mMaxAllowedDrawdownFactor <= 0) + { + // + result = true; + return result; + } + + // + double equity = mAccount.GetEquity(); + double balance = mAccount.GetBalance(); + + // + double selectedBalance = MathMax(equity, balance) - MathMin(equity, balance); + + // + double maxAllowedBalanceDrawDown = GetMaxAllowedEquity(); + + // + result = equity > balance || + (equity <= balance && + selectedBalance <= maxAllowedBalanceDrawDown); + + // + return result; + } + + // + // Check Max Allowed Positions Policy for Trade ... + bool CheckPositionsForTrade() + { + // + bool result = false; + + // + if (mMaxAllowedPositions <= 0) + { + // + result = true; + return result; + } + + // + XPosition positions[]; + int positionsCount = GetPositions(positions); + if (positionsCount <= 0) + { + // + result = true; + return result; + } + + // + result = positionsCount < mMaxAllowedPositions; + + // + return result; + } + + // + // Check Spread is Ok for Executing Specific Signal ... + bool CheckSpreadForSignalExecution(XSignal &mSignal) + { + // + bool result = false; + + // + bool isSpreadCheckEnable = mMaxAllowedSpread > 0; + if (!isSpreadCheckEnable) + { + result = true; + } + else + { + // + // Retrieve Signal Spread ... + double spread = mSignal.GetSpread(); + result = spread <= mMaxAllowedSpread; + } + + // + return result; + } + + // + // Check Account Policy ... + bool CheckAccountPolicy( + XSignal &mSignal, // For Executing Signal + ENUM_X_SIGNAL_EXECUTION_RESULT &state // State Holder + ) + { + // + bool result = false; + + // + // Check Positions For Trade ... + result = CheckPositionsForTrade(); + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_MAX_REACHED; + return result; + } + + // + // Check Equity For Trade ... + result = CheckEquityForTrade(); + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_NO_EQUITY; + return result; + } + + // + // Check Spread for Trade ... + result = CheckSpreadForSignalExecution(mSignal); + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_SPREAD; + return result; + } + + // + return result; + } + + // + // Manage ... + // this must be Call on OnTick for Manage + // Positions ... + // NOTE: Call this Before Checking IsNewBar ... + void Manage() + { + // // + // // All required Position Managements Actions implemented here ... + // datetime tmc = TimeCurrent(); + // bool canManage = !IsValid(mLastManageOn) + // ? true + // : mLastManageOn + mManageInterval >= tmc; + // if (!canManage) + // { + // return; + // } + + // // + // mLastManageOn = tmc; + + // + // - [] Partial Close; + // - [] Risk Free; + // - [] Trail Stop; + // - [] SLS; + // - [] TPS; + + // + // - [] Data Collector; + // - [] Profit Management; + + // + // TODO: Implement them ... + + // + // Implement Signal Collector Inside this Class + // and Manipulate Signals when SL/TP/Partial Close/Trail Stop/Profit/Close/ Modify and etc Happens ... + } + + // + // Execute a Signal ... + bool ExecuteSignal( + XSignal &mSignal, // Signal + ENUM_X_SIGNAL_EXECUTION_RESULT &state, // Result + ENUM_ORDER_TYPE_TIME lifetime = ORDER_TIME_GTC, // Order LifeTime + datetime expiration = NULL, // order expiration time + bool checkPolicies = true // Check Account Policies + ) + { + // + bool result = false; + state = X_SIGNAL_EXECUTION_UNKNOWN; + + // + double currentEntry = GetEntry( + mSignal.symbol, + mSignal.type + // + ); + bool isLong = IsLong(mSignal.type); + + // + if (!mSignal.IsValid()) + { + // + state = X_SIGNAL_EXECUTION_FAILED_INVALID_PARAMS; + return result; + } + + // + // Prepare Signal Comment ... + string mSComment = mSignal.GenerateComment(); + mSignal.comment += mSComment; + + // + // Handle Market Execution ... + if (mSignal.mode == X_ORDER_MODE_MARKET) + { + // + // Do Apply Policies here ... + bool hasPolicy = !checkPolicies + ? true + : CheckAccountPolicy(mSignal, state); + if (!hasPolicy) + { + result = false; + } + else + { + // + if (isLong) + { + // + result = Buy( + mSignal.symbol, + mSignal.period, + mSignal.volume, + mSignal.entry, + mSignal.sl, + mSignal.tp, + mSignal.comment + // + ); + } + else + { + // + result = Sell( + mSignal.symbol, + mSignal.period, + mSignal.volume, + mSignal.entry, + mSignal.sl, + mSignal.tp, + mSignal.comment + // + ); + } + } + } + // + // Handle Stop Execution ... + else if (mSignal.mode == X_ORDER_MODE_STOP) + { + + // + // Check Conditions ... + + // + // Check Price ... + result = isLong + ? mSignal.entry > currentEntry + : mSignal.entry < currentEntry; + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_PRICE_ERROR; + return result; + } + + // + // Execute Order ... + if (isLong) + { + // + result = BuyStop( + mSignal.symbol, + mSignal.period, + mSignal.volume, + mSignal.entry, + mSignal.sl, + mSignal.tp, + lifetime, + expiration, + mSignal.comment + // + ); + } + else + { + // + result = SellStop( + mSignal.symbol, + mSignal.period, + mSignal.volume, + mSignal.entry, + mSignal.sl, + mSignal.tp, + lifetime, + expiration, + mSignal.comment + // + ); + } + } + // + // Handle Limit Execution ... + else if (mSignal.mode == X_ORDER_MODE_LIMIT) + { + // + // Check Conditions ... + + // + // Check Price ... + result = isLong + ? mSignal.entry < currentEntry + : mSignal.entry > currentEntry; + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_PRICE_ERROR; + return result; + } + + // + // Execute Order ... + if (isLong) + { + // + result = BuyLimit( + mSignal.symbol, + mSignal.period, + mSignal.volume, + mSignal.entry, + mSignal.sl, + mSignal.tp, + lifetime, + expiration, + mSignal.comment + // + ); + } + else + { + // + result = SellLimit( + mSignal.symbol, + mSignal.period, + mSignal.volume, + mSignal.entry, + mSignal.sl, + mSignal.tp, + lifetime, + expiration, + mSignal.comment + // + ); + } + } + + // + // Handle Ticket ... + if (result) + { + // + state = X_SIGNAL_EXECUTION_SUCCEED; + + // + ulong ticket; + if (mSignal.mode == X_ORDER_MODE_MARKET) + { + ticket = GetLastOpenPositionTicket(); + } + else + { + ticket = GetLastPlacedOrderTicket(); + } + + // + mSignal.positionId = ticket; + + // + // Handle Store XPositionInfo ... + if (mSignal.mode == X_ORDER_MODE_MARKET) + { + // + // TODO: Implement this ... + } + + // + // Handle Executing Support Signals ... + int supportsCount = ArraySize(mSignal.supports); + if (supportsCount > 0) + { + // + int executed = 0; + for (int i = 0; i < supportsCount; i++) + { + // + XSignal iSupport = mSignal.supports[i]; + + // + int supIndex = i + 1; + string iComment = GenerateSupportTag(ticket); + + // + bool isExecuted = ExecuteSignal( + iSupport, + state, + lifetime, + expiration + // + ); + if (isExecuted) + { + executed++; + } + } + + // + result = executed == supportsCount; + } + } + + // + return result; + } + + // + // Execute a Collection Of Signals ... + int ExecuteSignals( + XSignal &signals[], // Collection of Signal for Execution + ENUM_X_SIGNAL_EXECUTION_RESULT &states[], // Signal Execution Result + ENUM_ORDER_TYPE_TIME lifetime = ORDER_TIME_GTC, // Order LifeTime + datetime expiration = NULL, // order expiration time + bool checkPolicies = true // Check Account Policies + ) + { + // + int result = 0; + + // + Clean(states); + + // + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return result; + } + + // + ArrayResize(states, signalsCount); + ArrayInitialize(states, X_SIGNAL_EXECUTION_UNKNOWN); + for (int i = 0; i < signalsCount; i++) + { + // + bool isExecuted = ExecuteSignal( + signals[i], + states[i], + lifetime, + expiration, + checkPolicies + // + ); + + // + if (isExecuted) + { + result++; + } + } + + // + return result; + } + + // + int ExecuteSpecifiedSignals( + XSignal &signals[], // Collection of Signal for Execution + XSignal ¬Executeds[], // Not Executed Signal + ENUM_X_SIGNAL_EXECUTION_RESULT &states[], // Signal Execution Result + ENUM_ORDER_TYPE_TIME lifetime = ORDER_TIME_GTC, // Order LifeTime + datetime expiration = NULL, // order expiration time + bool checkPolicies = true // Check Account Policies + ) + { + // + int result = 0; + + // + Clean(states); + Clean(notExecuteds); + + // + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return result; + } + + // + ArrayResize(states, signalsCount); + ArrayInitialize(states, X_SIGNAL_EXECUTION_UNKNOWN); + for (int i = 0; i < signalsCount; i++) + { + // + bool isExecuted = ExecuteSignal( + signals[i], + states[i], + lifetime, + expiration + // + ); + + // + if (isExecuted) + { + result++; + } + else + { + // + AddRef( + signals[i], + notExecuteds // + ); + } + } + + // + return result; + } + + // + // Regular Trade Actions ... + + // + // Buy ... + + // + // Force Open a Buy/Long Position ... + bool Buy( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // position volume + double price, // execution price + double sl = 0, // stop loss price + double tp = 0, // take profit price + string comment = NULL // comment + ) + { + // + bool result = false; + + // + ENUM_TIMEFRAMES mPeriod = ExtractPeriod(comment); + if (!IsValid(comment) || + !IsValid(mPeriod)) + { + // + string mPeriodStr = GeneratePeriodTag(period); + + // + comment += mPeriodStr; + } + + // + result = mTrader.Buy( + volume, + symbol, + price, + sl, + tp, + comment + // + ); + + // + return result; + } + + // + // Send BUY LIMIT order ... + bool BuyLimit( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // order volume + double price, // order price + double sl = 0.0, // stop loss price + double tp = 0.0, // take profit price + ENUM_ORDER_TYPE_TIME typeTime = ORDER_TIME_GTC, // order lifetime + datetime expiration = 0, // order expiration time + string comment = NULL // comment + ) + { + // + bool result = false; + + // + ENUM_TIMEFRAMES mPeriod = ExtractPeriod(comment); + if (!IsValid(comment) || + !IsValid(mPeriod)) + { + // + string mPeriodStr = GeneratePeriodTag(period); + + // + comment += mPeriodStr; + } + + // + result = mTrader.BuyLimit( + volume, + price, + symbol, + sl, + tp, + typeTime, + expiration, + comment + // + ); + + // + return result; + } + + // + // Send BUY STOP order ... + bool BuyStop( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // order volume + double price, // order price + double sl = 0.0, // stop loss price + double tp = 0.0, // take profit price + ENUM_ORDER_TYPE_TIME typeTime = ORDER_TIME_GTC, // order lifetime + datetime expiration = 0, // order expiration time + string comment = NULL // comment + ) + { + // + bool result = false; + + // + ENUM_TIMEFRAMES mPeriod = ExtractPeriod(comment); + if (!IsValid(comment) || + !IsValid(mPeriod)) + { + // + string mPeriodStr = GeneratePeriodTag(period); + + // + comment += mPeriodStr; + } + + // + result = mTrader.BuyStop( + volume, + price, + symbol, + sl, + tp, + typeTime, + expiration, + comment + // + ); + + // + return result; + } + + // + // Sell ... + + // + // Force Open a Sell/Short Position ... + bool Sell( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // position volume + double price, // execution price + double sl = 0, // stop loss price + double tp = 0, // take profit price + string comment = NULL // comment + ) + { + // + bool result = false; + + // + ENUM_TIMEFRAMES mPeriod = ExtractPeriod(comment); + if (!IsValid(comment) || + !IsValid(mPeriod)) + { + // + string mPeriodStr = GeneratePeriodTag(period); + + // + comment += mPeriodStr; + } + + // + result = mTrader.Sell( + volume, + symbol, + price, + sl, + tp, + comment + // + ); + + // + return result; + } + + // + // Send SELL LIMIT order ... + bool SellLimit( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // order volume + double price, // order price + double sl = 0.0, // stop loss price + double tp = 0.0, // take profit price + ENUM_ORDER_TYPE_TIME typeTime = ORDER_TIME_GTC, // order lifetime + datetime expiration = 0, // order expiration time + string comment = NULL // comment + ) + { + // + bool result = false; + + // + ENUM_TIMEFRAMES mPeriod = ExtractPeriod(comment); + if (!IsValid(comment) || + !IsValid(mPeriod)) + { + // + string mPeriodStr = GeneratePeriodTag(period); + + // + comment += mPeriodStr; + } + + // + result = mTrader.SellLimit( + volume, + price, + symbol, + sl, + tp, + typeTime, + expiration, + comment + // + ); + + // + return result; + } + + // + // Send SELL STOP order ... + bool SellStop( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // order volume + double price, // order price + double sl = 0.0, // stop loss price + double tp = 0.0, // take profit price + ENUM_ORDER_TYPE_TIME typeTime = ORDER_TIME_GTC, // order lifetime + datetime expiration = 0, // order expiration time + string comment = NULL // comment + ) + { + // + bool result = false; + + // + ENUM_TIMEFRAMES mPeriod = ExtractPeriod(comment); + if (!IsValid(comment) || + !IsValid(mPeriod)) + { + // + string mPeriodStr = GeneratePeriodTag(period); + + // + comment += mPeriodStr; + } + + // + result = mTrader.SellStop( + volume, + price, + symbol, + sl, + tp, + typeTime, + expiration, + comment + // + ); + + // + return result; + } + + // + // Check a Position is Exists Open or not ... + bool IsOpen( + ulong ticket // Specified Position Ticket + ) + { + // + bool result = false; + + // + result = mPositionInfo + .SelectByTicket(ticket); + + // + return result; + } + + // + // Modify Position ... + bool Modify( + const ulong ticket, // position ticket + double sl = 0, // stop loss price + double tp = 0, // take profit + string comment = NULL // comment + ) + { + // + bool result = false; + + // + // Validate Args ... + result = + IsOpen(ticket) && + (tp >= 0 || sl >= 0); + if (!result) + { + return result; + } + + // + // Use Position Comment when there isn't new One ... + if (!IsValid(comment) == 0) + { + // + // if there isn't provided Comment + // Use Position Comment for default ... + comment = "Modify " + GetPositionComment(ticket); + } + + // + result = mTrader.PositionModify( + ticket, + sl, + tp, + comment + // + ); + + // + return result; + } + + // + // Close Position By Ticket ... + bool Close( + ulong ticket, // Position Ticket + string comment = NULL // Close Position By Specific Comment + ) + { + // + bool result = false; + + // + // Check Position Open ... + result = IsOpen(ticket); + if (!result) + { + return result; + } + + // + // Use Default Position Comment if it's Not Provided ... + if (!IsValid(comment)) + { + comment = "Close " + GetPositionComment(ticket); + } + + // + // Close Position By Specific Comment ... + result = mTrader.PositionClose( + ticket, + mSlippage, + comment + // + ); + + // + return result; + } + + // + // Close Specified Positions ... + int Close( + string comment = NULL, // Close Position By Specific Comment + string symbol = NULL, // Trading Symbol + string provider = NULL, // Signal Provider + ENUM_TIMEFRAMES period = NULL, // Trading Period + ENUM_POSITION_TYPE type = NULL, // Long (Buy) or Short (Sell) + bool filterByMagic = true // Get Only Self Open Positions + ) + { + // + int result = 0; + + // + XPosition positions[]; + int positionsCount = GetPositions( + positions, + symbol, + provider, + period, + type, + filterByMagic); + if (positionsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + bool isClosed = Close( + iPosition.ticket, + comment + // + ); + if (isClosed) + { + result++; + } + } + + // + return result; + } + + // + // Close a Collection of Positions ... + int Close( + XPosition &positions[], // Collection of Positions + string comment // Close Comment + ) + { + // + int result = 0; + + // + int positionsCount = ArraySize(positions); + if (positionsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + bool isClosed = Close( + iPosition.ticket, + comment + // + ); + if (isClosed) + { + result++; + } + } + + // + return result; + } + + // + // Close Partial By Ticket ... + bool ClosePartial( + ulong ticket, // Position Ticket + double volume, // Volume Size for Partial Closing + string comment = NULL // Close Position By Specific Comment + ) + { + // + bool result = false; + + // + result = IsOpen(ticket); + if (!result) + { + return result; + } + + // + // Use Default Partial Close Comment ... + if (!IsValid(comment)) + { + // + comment += "PClose " + GetPositionComment(ticket); + } + + // + result = mTrader.PositionClosePartial( + ticket, + volume, + mSlippage, + comment + // + ); + + // + return result; + } + + // + // Cancel Specific Order ... + bool CancelOrder(ulong ticket) + { + return mTrader + .OrderDelete(ticket); + } + + // + // Cancel Specific Orders ... + int CancelOrders( + XOrder &orders[] // Specified Orders ... + ) + { + // + int result = 0; + + // + int ordersCount = ArraySize(orders); + if (ordersCount <= 0) + { + return result; + } + + // + for (int i = 0; i < ordersCount; i++) + { + // + XOrder iOrder = orders[i]; + + // + bool isDeleted = mTrader + .OrderDelete(iOrder.ticket); + if (isDeleted && !result) + { + result++; + } + } + + // + return result; + } + + // + // Extractors ... + + // + // Positions ... + + // + // Calculate Positions Profit ... + double Profit( + string symbol = NULL, // Trading Symbol + string provider = NULL, // Signal Provider + ENUM_TIMEFRAMES period = NULL, // Trading Period + ENUM_POSITION_TYPE type = NULL, // Long (Buy) or Short (Sell) + bool filterByMagic = true // Get Only Self Open Positions + ) + { + // + double result = 0; + + // + // Retrieve Positions ... + XPosition positions[]; + int positionsCount = GetPositions( + positions, + symbol, + provider, + period, + type, + filterByMagic + // + ); + if (positionsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + result += positions[i].profit; + } + + // + return result; + } + + // + // Retrieve Specific Position by Index ... + bool GetPosition( + int index, // Specified Index + XPosition &result // Hold's Result + ) + { + // + return result + .ByIndex(index); + } + + // + // Retrieve Specific Position by Ticket ... + bool GetPosition( + ulong ticket, // Specified Ticket + XPosition &result // Hold's Result + ) + { + // + return result + .ByTicket(ticket); + } + + // + // Retrieve Positions ... + int GetPositions( + XPosition &result[], // Hold's Result + string symbol = NULL, // Trading Symbol + string provider = NULL, // Signal Provider + ENUM_TIMEFRAMES period = NULL, // Trading Period + ENUM_POSITION_TYPE type = NULL, // Long (Buy) or Short (Sell) + bool filterByMagic = true, // Get Only Self Open Positions + bool forceClean = true // Clean Result Array + ) + { + // + int mResult = 0; + + // + int before = ArraySize(result); + + // + if (forceClean) + { + Clean(result); + } + + // + // Count Positions ... + int itemsCount = PositionsTotal(); + if (itemsCount <= 0) + { + return mResult; + } + + // + // Loop Through all Positions ... + for (int i = itemsCount - 1; i >= 0; i--) + { + // + XPosition iItem; + bool isLoaded = iItem.ByIndex(i); + if (!isLoaded) + { + continue; + } + + // + // Now we have to Check Given Filters ... + bool isFiltersPassed = + iItem.IsFiltersPassed( + symbol, + provider, + period, + type, + mMagicNumber, + filterByMagic + // + ); + if (!isFiltersPassed) + { + continue; + } + + // + // Add Filtered Item into Result ... + AddRef( + iItem, + result + // + ); + } + + // + int after = ArraySize(result); + + // + mResult = after - before; + + // + return mResult; + } + + // + // Select In Profit Positions ... + int GetInProfitPositions( + XPosition &result[], // Hold's Result + string symbol = NULL, // Trading Symbol + string provider = NULL, // Signal Provider + ENUM_TIMEFRAMES period = NULL, // Trading Period + ENUM_POSITION_TYPE type = NULL, // Long (Buy) or Short (Sell) + ENUM_X_POSITION_SELECT_METHODS method = NULL, // Selection Method + bool filterByMagic = true, // Get Only Self Open Positions + bool forceClean = true // Clean Result Array + ) + { + // + int mResult = 0; + + // + int before = ArraySize(result); + + // + if (forceClean) + { + Clean(result); + } + + // + XPosition positions[]; + int positionsCount = GetPositions( + positions, + symbol, + provider, + period, + type, + filterByMagic, + forceClean); + if (positionsCount <= 0) + { + return mResult; + } + + // + XPosition min; + XPosition max; + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + if (iPosition.profit <= 0) + { + continue; + } + + // + // Calculate Min and Max ... + + // + // Min ... + if (!min.IsValid() || min.profit <= 0 || min.profit > iPosition.profit) + { + min = iPosition; + } + + // + // Max ... + if (!max.IsValid() || max.profit <= 0 || max.profit < iPosition.profit) + { + max = iPosition; + } + + // + bool isSelectionMethodFilterPassed = + // + (method == NULL || + method == X_POSITION_SELECT_ALL) + ? true + : false; + // + ; + if (!isSelectionMethodFilterPassed) + { + continue; + } + + // + AddRef( + iPosition, + result + // + ); + } + + // + if (min.IsValid() && + (method == X_POSITION_SELECT_MIN || + method == X_POSITION_SELECT_BOTH)) + { + // + AddRef( + min, + result + // + ); + } + + // + if (max.IsValid() && + (method == X_POSITION_SELECT_MAX || + method == X_POSITION_SELECT_BOTH)) + { + // + AddRef( + max, + result + // + ); + } + + // + int after = ArraySize(result); + + // + mResult = after - before; + + // + return mResult; + } + + // + // Select In Drawdown Positions ... + int GetInDrawdownPositions( + XPosition &result[], // Hold's Result + string symbol = NULL, // Trading Symbol + string provider = NULL, // Signal Provider + ENUM_TIMEFRAMES period = NULL, // Trading Period + ENUM_POSITION_TYPE type = NULL, // Long (Buy) or Short (Sell) + ENUM_X_POSITION_SELECT_METHODS method = NULL, // Selection Method + bool filterByMagic = true, // Get Only Self Open Positions + bool forceClean = true // Clean Result Array + ) + { + // + int mResult = 0; + + // + int before = ArraySize(result); + + // + if (forceClean) + { + Clean(result); + } + + // + XPosition positions[]; + int positionsCount = GetPositions( + positions, + symbol, + provider, + period, + type, + filterByMagic, + forceClean); + if (positionsCount <= 0) + { + return mResult; + } + + // + XPosition min; + XPosition max; + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + if (iPosition.profit >= 0) + { + continue; + } + + // + // Calculate Min and Max ... + + // + // Min ... + if (!min.IsValid() || min.profit <= 0 || min.profit > iPosition.profit) + { + min = iPosition; + } + + // + // Max ... + if (!max.IsValid() || max.profit <= 0 || max.profit < iPosition.profit) + { + max = iPosition; + } + + // + bool isSelectionMethodFilterPassed = + // + (method == NULL || + method == X_POSITION_SELECT_ALL) + ? true + : false; + // + ; + if (!isSelectionMethodFilterPassed) + { + continue; + } + + // + AddRef( + iPosition, + result + // + ); + } + + // + if (min.IsValid() && + (method == X_POSITION_SELECT_MIN || + method == X_POSITION_SELECT_BOTH)) + { + // + AddRef( + min, + result + // + ); + } + + // + if (max.IsValid() && + (method == X_POSITION_SELECT_MAX || + method == X_POSITION_SELECT_BOTH)) + { + // + AddRef( + max, + result + // + ); + } + + // + int after = ArraySize(result); + + // + mResult = after - before; + + // + return mResult; + } + + // + // Orders ... + + // + // Retrieve Specific Order by Index ... + bool GetOrder( + int index, // Specified Index + XOrder &result // Hold's Result + ) + { + // + return result + .ByIndex(index); + } + + // + // Retrieve Specific Positions Orders ... + int GetOrders( + ulong ticket, // Positions Ticket + XOrder &result[], // Hold's Result + bool forceClean = true // Clean Result Array + ) + { + // + int mResult = 0; + + // + // Select History by Specified Ticket ... + bool isHistorySelected = HistorySelectByPosition(ticket); + if (!isHistorySelected) + { + return mResult; + } + + // + int ordersCount = HistoryOrdersTotal(); + if (ordersCount <= 0) + { + return mResult; + } + + // + int before = ArraySize(result); + + // + if (forceClean) + { + Clean(result); + } + + // + for (int i = 0; i < ordersCount; i++) + { + // + XOrder iOrder; + bool isLoaded = iOrder.HistoryByIndex(i); + if (!isLoaded) + { + continue; + } + + // + bool isTicketFilterPassed = + // + iOrder.ticket = ticket + // + ; + if (!isTicketFilterPassed) + { + continue; + } + + // + AddRef( + iOrder, + result + // + ); + } + + // + int after = ArraySize(result); + + // + mResult = after - before; + + // + return mResult; + } + + // + // Retrieve All Orders ... + int GetOrders( + XOrder &result[], // Hold's Result + string symbol = NULL, // Trading Symbol + string provider = NULL, // Signal Provider + ENUM_TIMEFRAMES period = NULL, // Trading Period + ENUM_ORDER_TYPE type = NULL, // Long (Buy) or Short (Sell) + ENUM_ORDER_STATE state = NULL, // Order State + bool filterByMagic = true, // Get Only Self Open Positions + bool forceClean = true // Clean Result Array + ) + { + // + int mResult = 0; + + // + int before = ArraySize(result); + + // + if (forceClean) + { + Clean(result); + } + + // + // Count Positions ... + int itemsCount = OrdersTotal(); + if (itemsCount <= 0) + { + return mResult; + } + + // + // Loop Through all Positions ... + for (int i = itemsCount - 1; i >= 0; i--) + { + // + XOrder iItem; + bool isLoaded = iItem.ByIndex(i); + if (!isLoaded) + { + continue; + } + + // + // Now we have to Check Given Filters ... + bool isFiltersPassed = + iItem.IsFiltersPassed( + symbol, + provider, + period, + type, + state, + mMagicNumber, + filterByMagic + // + ); + if (!isFiltersPassed) + { + continue; + } + + // + // Add Filtered Item into Result ... + AddRef( + iItem, + result + // + ); + } + + // + int after = ArraySize(result); + + // + mResult = after - before; + + // + return mResult; + } + + // + // Retrieve Historical Orders ... + int GetOrders( + XOrder &result[], // Hold's Result + string symbol = NULL, // Trading Symbol + string provider = NULL, // Signal Provider + ENUM_TIMEFRAMES period = NULL, // Trading Period + ENUM_ORDER_TYPE type = NULL, // Long (Buy) or Short (Sell) + ENUM_ORDER_STATE state = NULL, // Order State + datetime startDate = NULL, // Specify Start Date + datetime endDate = NULL, // Specify End Date + bool filterByMagic = true, // Get Only Self Open Positions + bool forceClean = true // Clean Result Array + ) + { + // + int mResult = 0; + + // + endDate = NormalizeTime(endDate); + + // + if (!IsValid(startDate)) + { + startDate = endDate - PeriodSeconds(PERIOD_D1); + } + + // + bool isHistorySelected = HistorySelect( + startDate, + endDate); + if (!isHistorySelected) + { + return mResult; + } + + // + int before = ArraySize(result); + + // + if (forceClean) + { + Clean(result); + } + + // + // Count Positions ... + int itemsCount = OrdersTotal(); + if (itemsCount <= 0) + { + return mResult; + } + + // + // Loop Through all Positions ... + for (int i = itemsCount - 1; i >= 0; i--) + { + // + XOrder iItem; + bool isLoaded = iItem.HistoryByIndex(i); + if (!isLoaded) + { + continue; + } + + // + // Now we have to Check Given Filters ... + bool isFiltersPassed = + iItem.IsFiltersPassed( + symbol, + provider, + period, + type, + state, + mMagicNumber, + filterByMagic + // + ); + if (!isFiltersPassed) + { + continue; + } + + // + // Add Filtered Item into Result ... + AddRef( + iItem, + result + // + ); + } + + // + int after = ArraySize(result); + + // + mResult = after - before; + + // + return mResult; + } + + // + // Deals ... + + // + // Retrieve Specific Deal by Index ... + bool GetDeal( + int index, // Specified Index + XDeal &result // Hold's Result + ) + { + // + return result + .ByIndex(index); + } + + // + // Retrieve Specified Deal's History ... + int GetDealsHistory( + XDeal &deal, // Specified Deal + XOrder &history[], // Deals History + bool forceClean = true // Clean Result Array + ) + { + // + int result = 0; + + // + if (!deal.IsValid()) + { + return result; + } + + // + result = GetOrders( + deal.positionId, + history, + forceClean); + + // + return result; + } + + // + // Retrieve All Deals ... + int GetDeals( + XDeal &result[], // Hold's Result + string symbol = NULL, // Trading Symbol + string provider = NULL, // Signal Provider + ENUM_TIMEFRAMES period = NULL, // Trading Period + ENUM_DEAL_TYPE type = NULL, // Deal Type + ENUM_DEAL_ENTRY entry = NULL, // Deal Entry + ENUM_DEAL_REASON reason = NULL, // Deal Reason + datetime startDate = NULL, // Specify Start Date + datetime endDate = NULL, // Specify End Date + bool filterByMagic = true, // Get Only Self Open Positions + bool forceClean = true // Clean Result Array + ) + { + // + int mResult = 0; + + // + endDate = NormalizeTime(endDate); + + // + if (!IsValid(startDate)) + { + startDate = endDate - PeriodSeconds(PERIOD_D1); + } + + // + bool isHistorySelected = HistorySelect( + startDate, + endDate); + if (!isHistorySelected) + { + return mResult; + } + + // + int before = ArraySize(result); + + // + if (forceClean) + { + Clean(result); + } + + // + // Count Positions ... + int itemsCount = HistoryDealsTotal(); + if (itemsCount <= 0) + { + return mResult; + } + + // + // Loop Through all Positions ... + for (int i = itemsCount - 1; i >= 0; i--) + { + // + XDeal iItem; + bool isLoaded = iItem.ByIndex(i); + if (!isLoaded) + { + continue; + } + + // + // Now we have to Check Given Filters ... + bool isFiltersPassed = + iItem.IsFiltersPassed( + symbol, + provider, + period, + type, + entry, + reason, + mMagicNumber, + filterByMagic + // + ); + if (!isFiltersPassed) + { + continue; + } + + // + // Add Filtered Item into Result ... + AddRef( + iItem, + result + // + ); + } + + // + int after = ArraySize(result); + + // + mResult = after - before; + + // + return mResult; + } + + // + // XPosition Pack ... + + // + // Extract specific Positions Pack ... + // in this senario there is no need to Position exists itself ... + bool GetPositionPack( + ulong ticket, // Specified Positions Ticket + string symbol, // Specified Position Symbol + ENUM_TIMEFRAMES period, // Specified Position Period + XPositionPack &pack // Hold Result + ) + { + // + bool result = false; + + // + pack.Clean(); + + // + XPosition position; + bool hasPosition = GetPosition( + ticket, + position + // + ); + if (hasPosition) + { + pack.position = position; + } + + // + XOrder supportOrders[]; + XPosition supportPositions[]; + + // + XOrder orders[]; + GetOrders( + orders, + symbol, // Specified Symbol + NULL, // All Providers + period, // Specified Period + NULL, // All Types + ORDER_STATE_PLACED, // Just UnTriggered Orders + true // Filter by Magic + ); + int ordersCount = ArraySize(orders); + + // + // Select Orders ... + if (ordersCount > 0) + { + // + for (int i = 0; i < ordersCount; i++) + { + // + XOrder iOrder = orders[i]; + + // + // Retrieve Order Supported Ticket ... + ulong parentTicket = ExtractSupportedTicket(iOrder.comment); + if (NotEmpty(parentTicket) && parentTicket == ticket) + { + // + AddRef( + iOrder, + supportOrders + // + ); + } + } + } + + // + int supportOrdersCount = ArraySize(supportOrders); + if (supportOrdersCount > 0) + { + // + pack.supportOrdersCount = supportOrdersCount; + + // + Copy( + supportOrders, + pack.supportOrders); + } + + // + XPosition positions[]; + GetPositions( + positions, + symbol, // Specified Symbol ... + NULL, // All Providers ... + period // Specified Period ... + ); + int positionsCount = ArraySize(positions); + + // + // Select Positions ... + if (positionsCount > 0) + { + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + ulong parentTicket = ExtractSupportedTicket(iPosition.comment); + if (NotEmpty(parentTicket) && parentTicket == ticket) + { + // + AddRef( + iPosition, + supportPositions + // + ); + } + } + } + + // + int supportPositionsCount = ArraySize(supportPositions); + if (supportPositionsCount > 0) + { + // + pack.supportPositionsCount = supportPositionsCount; + + // + Copy( + supportPositions, + pack.supportPositions); + } + + // + result = pack.IsValid(); + + // + return result; + } + + // + // Close Position Pack ... + bool ClosePositionPack( + XPositionPack &pack, // Specified Position Pack + string comment, // Specified Close Comment + bool inProfit = false, // if it's true only close Pack if in profit + double minProfitPerTrade = 0, // Min Profit based On Volume Factor ... + double minProfitPerVolumeFactor = 0 // Min Volume Factor ... + ) + { + // + bool result = false; + + // + ulong ticket = pack.ticket; + + // + XPosition positions[]; + + // + XPosition pPosition; + result = GetPosition( + ticket, + pPosition // + ); + if (result) + { + // + AddRef( + pPosition, + positions // + ); + } + + // + if (pack.supportPositionsCount > 0) + { + // + for (int i = 0; i < pack.supportPositionsCount; i++) + { + // + XPosition iPosition = pack.supportPositions[i]; + + // + AddRef( + iPosition, + positions // + ); + } + } + + // + // Force Close ... + if (!inProfit) + { + // + int closed = Close( + positions, + comment // + ); + + // + int cancelled = 0; + if (pack.supportOrdersCount > 0) + { + cancelled = CancelOrders(pack.supportOrders); + } + + // + result = (closed + cancelled) == (pack.supportPositionsCount + pack.supportOrdersCount + 1); + } + else + { + // + bool canHedge = SpecifiedIsPositionsReadyForHedge( + positions, + minProfitPerTrade, + minProfitPerVolumeFactor // + ); + if (canHedge) + { + // + int closed = Close( + positions, + comment // + ); + + // + int cancelled = 0; + if (pack.supportOrdersCount > 0) + { + cancelled = CancelOrders(pack.supportOrders); + } + + // + result = (closed + cancelled) == (pack.supportPositionsCount + pack.supportOrdersCount + 1); + } + else + { + result = false; + } + } + + // + return result; + } + bool ClosePositionPack( + ulong ticket, // Specified Position Pack + string symbol, // Specified Position Symbol + ENUM_TIMEFRAMES period, // Specified Position Period + string comment, // Specified Close Comment + bool inProfit = false, // if it's true only close Pack if in profit + double minProfitPerTrade = 0, // Min Profit based On Volume Factor ... + double minProfitPerVolumeFactor = 0 // Min Volume Factor ... + ) + { + // + bool result = false; + + // + XPositionPack pack; + result = GetPositionPack( + ticket, + symbol, + period, + pack // + ); + if (!result) + { + return result; + } + + // + result = ClosePositionPack( + pack, + comment, + inProfit, + minProfitPerTrade, + minProfitPerVolumeFactor // + ); + + // + return result; + } + + // + // Close Positions Pack ... + int ClosePositionsPack( + XPosition &positions[], // Positions ... + string comment, // Specified Close Comment + bool inProfit = false, // if it's true only close Pack if in profit + double minProfitPerTrade = 0, // Min Profit based On Volume Factor ... + double minProfitPerVolumeFactor = 0 // Min Volume Factor ... + ) + { + // + int result = 0; + + // + int positionsCount = ArraySize(positions); + if (positionsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + bool isClosed = ClosePositionPack( + iPosition.ticket, + iPosition.symbol, + iPosition.period, + comment, + inProfit, + minProfitPerTrade, + minProfitPerVolumeFactor // + ); + if (isClosed) + { + result++; + } + } + + // + return result; + } + + // + // Protected ... +protected: + // + // Props ... + + // + // Event Listener Notifiers ... + + // + // State ... + void NotifyTradeStateChangeEvent(const XOnTradeHandlerState &state) + { + // + int count = ArraySize(mTradeStateChangedEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + TOnTradeStateChanged iHandler = mTradeStateChangedEventHandlers[i]; + iHandler(state); + } + } + + // + // Deals ... + void NotifyDealsChangeEvent(int changes) + { + // + int count = ArraySize(mDealsChangedEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + TOnDealsChanged iHandler = mDealsChangedEventHandlers[i]; + iHandler(changes); + } + } + + // + // Orders ... + void NotifyOrdersChangeEvent(int changes) + { + // + int count = ArraySize(mOrdersChangedEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + TOnOrdersChanged iHandler = mOrdersChangedEventHandlers[i]; + iHandler(changes); + } + } + + // + // Positions ... + void NotifyPositionsChangeEvent(int changes) + { + // + int count = ArraySize(mPositionsChangedEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + TOnPositionsChanged iHandler = mPositionsChangedEventHandlers[i]; + iHandler(changes); + } + } + + // + // StopLoss ... + void NotifyStopLossEvent(const XDeal &deal) + { + // + int count = ArraySize(mStopLossEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + TOnStopLoss iHandler = mStopLossEventHandlers[i]; + iHandler(deal); + } + } + + // + // Take Profit ... + void NotifyTakeProfitEvent(const XDeal &deal) + { + // + int count = ArraySize(mTakeProfitEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + TOnTakeProfit iHandler = mTakeProfitEventHandlers[i]; + iHandler(deal); + } + } + + // + // Tools ... + + // + // Retrieve Specified Position Comment ... + string GetPositionComment(ulong ticket) + { + // + string result = NULL; + + // + if (!IsOpen(ticket)) + { + return result; + } + + // + XPosition position; + bool isLoaded = position.ByTicket(ticket); + if (!isLoaded) + { + return result; + } + + // + result = position.comment; + + // + return result; + } + + // + // Retrieve Last Open Position Ticket ... + ulong GetLastOpenPositionTicket() + { + // + ulong result = 0; + + int positionsCount = PositionsTotal(); + if (positionsCount <= 0) + { + return result; + } + + // + result = PositionGetTicket(PositionsTotal() - 1); + + // + return result; + } + + // + // Retrieve Last Placed Order Ticket ... + ulong GetLastPlacedOrderTicket() + { + // + ulong result = 0; + + int ordersCount = OrdersTotal(); + if (ordersCount <= 0) + { + return result; + } + + // + if (mOrderInfo.SelectByIndex(ordersCount - 1)) + { + result = mOrderInfo.Ticket(); + } + + // + return result; + } + + // + // Extract Specific Deals Position's Pack ... + // this used when a Position SL or TP triggered and we want to close + // all it's Supported Packs ... + bool GetDealPack( + XDeal &deal, + XPositionPack &pack // + ) + { + // + bool result = false; + + // + ulong ticket = deal.positionId; + ENUM_TIMEFRAMES dealPeriod = GetDealPeriod(deal); + string dealSymbol = deal.symbol; + + // + // So We Have to Get Positions Pack ... + result = GetPositionPack( + ticket, + dealSymbol, + dealPeriod, + pack + // + ); + + // + return result; + } + + // + ENUM_TIMEFRAMES GetDealPeriod(XDeal &deal) + { + // + ENUM_TIMEFRAMES result = NULL; + + // + XOrder orders[]; + int ordersCount = GetDealsHistory( + deal, + orders); + if (!ordersCount) + { + return result; + } + + // + for (int i = 0; i < ordersCount; i++) + { + // + XOrder iOrder = orders[i]; + + // + if (IsValid(iOrder.comment)) + { + // + ENUM_TIMEFRAMES iPeriod = ExtractPeriod(iOrder.comment); + if (IsValid(iPeriod)) + { + result = iPeriod; + break; + } + } + } + + // + return result; + } + + // + double GetMaxAllowedEquity() + { + // + double equity = mAccount.GetEquity(); + double balance = mAccount.GetBalance(); + + // + double balanceForFactor = MathAbs(equity - balance); + if (balanceForFactor <= 0) + { + balanceForFactor = balance; + } + else + { + balanceForFactor = equity; + } + + // + double result = balanceForFactor * mMaxAllowedDrawdownFactor; + + // + return result; + } + + // + // Private ... +private: + // + // Props ... + + // + int mSlippage; // Slippage ... + ulong mMagicNumber; // Magic Number (Unique Identifier) ... + + // + datetime mLastManageOn; // Last Manager Check + int mManageInterval; // Manager Check Intervals Seconds + + // + double mMaxAllowedSpread; // Max Allowed Spred for Opening Trades + int mMaxAllowedPositions; // Max Allowed Same Positions + double mMaxAllowedDrawdownFactor; // Max Allowed Drawdown Factor + + // + XSCAccount *mAccount; // Account Info Provider + XSCTradeBase *mTrader; // Base CTrade Manipulated Instance ... + + // + CDealInfo mDealInfo; // Deals Info ... + COrderInfo mOrderInfo; // Order Info ... + CPositionInfo mPositionInfo; // Positions Info + CHistoryOrderInfo mHistoryOrderInfo; // History Orders Info ... + + // + // Position Info Collector ... + + // + // Tools ... + + // + // OnTrade Event Handlers Section ... + + // + // Props ... + + // + int mDaysForRead; // Reading Dates for Trade History Checker ... + datetime mEndDate; // End Date for Trade history Checking ... + datetime mStartDate; // Start Date for Trade history Checking ... ... + int mOrdersCount; // Number of Active orders ... + int mPositionsCount; // Number of Open positions ... + int mDealsCount; // Number of Deals in the Trade History Checking ... + int mHistoryOrdersCount; // Number of Orders in the Trade History Checking ... + bool mScanStarted; // a Flag of counter relevance ... + + // + // Event Listeners ... + + // + // Deals Changed Event Handlers ... + TOnDealsChanged mDealsChangedEventHandlers[]; + + // + // Orders Changed Event Handlers ... + TOnOrdersChanged mOrdersChangedEventHandlers[]; + + // + // Positions Changed Event Handlers ... + TOnPositionsChanged mPositionsChangedEventHandlers[]; + + // + // Trade State Changed Event Handlers ... + TOnTradeStateChanged mTradeStateChangedEventHandlers[]; + + // + // TPSL ... + TOnStopLoss mStopLossEventHandlers[]; + TOnTakeProfit mTakeProfitEventHandlers[]; + + // + // Reset On Trade Scanner Context ... + void ResetOnTradeContext() + { + // + mEndDate = TimeCurrent(); + mStartDate = mEndDate - (mDaysForRead * PeriodSeconds(PERIOD_D1)); + } + + // + // Initial Context Of Trade Scanner ... + void InitOnTradeContext() + { + // + ResetLastError(); + + // + mOrdersCount = OrdersTotal(); + mPositionsCount = PositionsTotal(); + + // + // load history ... + bool selected = HistorySelect(mStartDate, mEndDate); + if (!selected) + { + return; + } + + // + // get the current value ... + mDealsCount = HistoryDealsTotal(); + mHistoryOrdersCount = HistoryOrdersTotal(); + + // + mScanStarted = true; + } + + // + // Check Statrt Date In Trade History ... + void CheckStartDateInTradeHistory() + { + // + // initial interval, if we were to start working right now .. + datetime currStart = TimeCurrent() - (mDaysForRead * PeriodSeconds(PERIOD_D1)); + + // + // make sure that the start limit of the trade history has not gone + // more than 1 day over the intended date ... + if (currStart - mStartDate > PeriodSeconds(PERIOD_D1)) + { + // + // correct the start date of history to be loaded in the cache ... + mStartDate = currStart; + + // + // now reload the trade history for the updated interval ... + HistorySelect(mStartDate, mEndDate); + + // + // correct the deal and order counters in history for further comparison + mHistoryOrdersCount = HistoryOrdersTotal(); + mDealsCount = HistoryDealsTotal(); + } + } + + // + // Process On Trade Context ... + void ProcessOnTradeContext( + XOnTradeHandlerState &result // Hold's Result + ) + { + // + mEndDate = TimeCurrent(); + + // + ResetLastError(); + + // + // download trading history from the specified interval to the program cache ... + bool selected = HistorySelect(mStartDate, mEndDate); + if (!selected) + { + return; + } + + // + // get the current values ... + int currOrders = OrdersTotal(); + int currPositions = PositionsTotal(); + int currDeals = HistoryDealsTotal(); + int currHistoryOrders = HistoryOrdersTotal(); + + // + // Orders ... + // check if the number of active orders has been changed ... + if (currOrders != mOrdersCount) + { + // + // number of active orders has been changed ... + result.hasNewOrder = true; + result.newOrders = currOrders - mOrdersCount; + + // + // update the value ... + mOrdersCount = currOrders; + } + + // + // Positions ... + // changes in the number of open positions ... + if (currPositions != mPositionsCount) + { + // + // number of open positions has been changed ... + result.hasNewPosition = true; + result.newPositions = currPositions - mPositionsCount; + + // + // update the value ... + mPositionsCount = currPositions; + } + + // + // Deals ... + // changes in the number of deals in the trade history cache ... + if (currDeals != mDealsCount) + { + // + // number of deals in the trade history cache has been changed ... + result.hasNewDeal = true; + result.newDeals = currDeals - mDealsCount; + + // + // update the value ... + mDealsCount = currDeals; + } + + // + // History Orders ... + // changes in the number of history orders in the trade history cache ... + if (currHistoryOrders != mHistoryOrdersCount) + { + // + // number of history orders in the trade history cache has been changed ... + result.hasNewHistoryOrder = true; + result.newHistoryOrders = currHistoryOrders - mHistoryOrdersCount; + + // + // update the value ... + mHistoryOrdersCount = currHistoryOrders; + } + + // + // checking if it is necessary to change the limits of the trade history to be requested in cache ... + CheckStartDateInTradeHistory(); + } +}; + +// \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/14030316/Documents/.gitkeep b/MQLTestWorkspace/BKPS/14030316/Documents/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/MQLTestWorkspace/BKPS/14030316/Documents/JsModules/x-color.tools.js b/MQLTestWorkspace/BKPS/14030316/Documents/JsModules/x-color.tools.js new file mode 100644 index 0000000..c3ac5f9 --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Documents/JsModules/x-color.tools.js @@ -0,0 +1,506 @@ +/** + * XColor Tools Module ... + * a module for handle colorify text contents in node js ... + * + * Maintainer + * + * Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) + */ + +// +//#region Module Imports ... +const XValueTools = require("./x-value.tools"); +//#endregion + +// +//#region Constants ... +/** + * these are available style which can applied to an string ... + */ +const AVAILABLE_STYLES = { + // + Bold: "\x1b[1m", + Dim: "\x1b[2m", + Underlined: "\x1b[4m", + Blink: "\x1b[5m", + ReverseFandB: "\x1b[7m", + Hidden: "\x1b[8m", + // + // Commonly used for reset all Styles ... + Reset: "\x1b[0m" +}; + +/** + * these are available foreground colors which can applied to an string ... + */ +const AVAILABLE_FOREGROUND_COLORS = { + Default: "\x1b[39m", + Black: "\x1b[30m", + Red: "\x1b[31m", + Green: "\x1b[32m", + Yellow: "\x1b[33m", + Blue: "\x1b[34m", + Magenta: "\x1b[35m", + Cyan: "\x1b[36m", + LightGray: "\x1b[37m", + DarkGray: "\x1b[90m", + LightRed: "\x1b[91m", + LightGreen: "\x1b[92m", + LightYellow: "\x1b[93m", + LightBlue: "\x1b[94m", + LightMagenta: "\x1b[95m", + LightCyan: "\x1b[96m", + White: "\x1b[97m", +}; + +/** + * these are available background colors which can applied to an string ... + */ +const AVAILABLE_BACKGROUND_COLORS = { + Default: "\x1b[49m", + Black: "\x1b[40m", + Red: "\x1b[41m", + Green: "\x1b[42m", + Yellow: "\x1b[43m", + Blue: "\x1b[44m", + Magenta: "\x1b[45m", + Cyan: "\x1b[46m", + LightGray: "\x1b[47m", + DarkGray: "\x1b[100m", + LightRed: "\x1b[101m", + LightGreen: "\x1b[102m", + LightYellow: "\x1b[103m", + LightBlue: "\x1b[104m", + LightMagenta: "\x1b[105m", + LightCyan: "\x1b[106m", + White: "\x1b[107m", +}; + +/** + * these are available style names, which exports from module and + * users can use them ... + */ +const STYLE_NAMES = { + Bold: "Bold", + Dim: "Dim", + Underlined: "Underlined", + Blink: "Blink", + ReverseFandB: "ReverseFandB", + Hidden: "Hidden", + Reset: "Reset", +}; + +/** + * these are available color names, which exports from module and + * users can use them ... + */ +const COLOR_NAMES = { + Default: "Default", + Black: "Black", + Red: "Red", + Green: "Green", + Yellow: "Yellow", + Blue: "Blue", + Magenta: "Magenta", + Cyan: "Cyan", + LightGray: "LightGray", + DarkGray: "DarkGray", + LightRed: "LightRed", + LightGreen: "LightGreen", + LightYellow: "LightYellow", + LightBlue: "LightBlue", + LightMagenta: "LightMagenta", + LightCyan: "LightCyan", + White: "White", +}; +//#endregion + +// +//#region Actions ... +/** + * apply specified style and color on a content ... + * + * @param {string} content specified content for styling ... + * @param {string} color specific color name for using to styling ... + * @param {string} style soecufic style name to use ... + * @param {boolean} toForeground apply specified color as foreground ... + * @param {boolean} toBackground apply specified color as background ... + * @returns {string} styled content ... + */ +function apply( + content, + color, + style, + toForeground = true, + toBackground = false +) { + // + let result = content; + + // + // Validate Arg ... + if (!XValueTools.isValidArg(content)) { + return result; + } + + // + // Detect and Validate Style and Apply it ... + let eStyle = AVAILABLE_STYLES[style]; + if (XValueTools.isValidArg(eStyle)) { + result = `${eStyle}${result}${AVAILABLE_STYLES.Reset}`; + } + + // + // Detect and Validate Foreground Color and Apply it ... + let eFColor = AVAILABLE_FOREGROUND_COLORS[color]; + if ( + !!toForeground + && XValueTools.isValidArg(eFColor) + ) { + result = `${eFColor}${result}${AVAILABLE_STYLES.Reset}`; + } + + // + // Detect and Validate Background Color and Apply it ... + let eBColor = AVAILABLE_BACKGROUND_COLORS[color]; + if ( + !!toBackground + && XValueTools.isValidArg(eBColor) + ) { + result = `${eBColor}${result}${AVAILABLE_STYLES.Reset}`; + } + +} + +/** + * apply specific style on a content ... + * + * @param {string} content specific content which going to styled ... + * @param {string} style a member of STYLE_NAMES which specified that which style going to applied to content ... + * @returns {string} styled content ... + */ +function applyStyle(content, style) { + // + // Validate Arg ... + if (!XValueTools.isValidArg(content)) { + return content; + } + + // + let eStyle = AVAILABLE_STYLES[style]; + if (eStyle === undefined) { + return content; + } + + // + return `${eStyle}${content}${AVAILABLE_STYLES.Reset}`; +} + +/** + * apply specific foreground color on a content ... + * + * @param {string} content specific content which going to colorified ... + * @param {string} color a member of COLOR_NAMES which specified that which color going to applied to content ... + * @returns {string} colorified content ... + */ +function applyForegroundColor(content, color) { + // + // Validate Arg ... + if (!XValueTools.isValidArg(content)) { + return content; + } + + // + let eColor = AVAILABLE_FOREGROUND_COLORS[color]; + if (eColor === undefined) { + return content; + } + + // + return `${eColor}${content}${AVAILABLE_STYLES.Reset}`; +} + +/** + * apply specific background color on a content ... + * + * @param {string} content specific content which going to colorified ... + * @param {string} color a member of COLOR_NAMES which specified that which color going to applied to content ... + * @returns {string} colorified content ... + */ +function applyBackgroundColor(content, color) { + // + // Validate Arg ... + if (!XValueTools.isValidArg(content)) { + return content; + } + + // + let eColor = AVAILABLE_BACKGROUND_COLORS[color]; + if (eColor === undefined) { + return content; + } + + // + return `${eColor}${content}${AVAILABLE_STYLES.Reset}`; +} + +/** + * generate style and color applier expression ... + * + * @param {string} color specific color name for using to styling ... + * @param {string} style soecufic style name to use ... + * @param {boolean} reset close applier string by reset styles ... + * @param {boolean} toForeground apply specified color as foreground ... + * @param {boolean} toBackground apply specified color as background ... + * @returns {string} style and color applier string ... + */ +function getApplier( + style = "", + color = "", + reset = false, + toForeground = true, + toBackground = false +) { + // + let result = ""; + + // + // Detect and Validate Style and Apply it ... + let eStyle = AVAILABLE_STYLES[style]; + if (XValueTools.isValidArg(eStyle)) { + result = `${eStyle}`; + } + + // + // Detect and Validate Foreground Color and Apply it ... + let eFColor = AVAILABLE_FOREGROUND_COLORS[color]; + if ( + !!toForeground + && XValueTools.isValidArg(eFColor) + ) { + result = `${eFColor}`; + } + + // + // Detect and Validate Background Color and Apply it ... + let eBColor = AVAILABLE_BACKGROUND_COLORS[color]; + if ( + !!toBackground + && XValueTools.isValidArg(eBColor) + ) { + result = `${eBColor}`; + } + + // + if ( + !!reset && + result.length > 0 + ) { + result = `${result}${AVAILABLE_STYLES.Reset}`; + } + + // + return result; +} + +/** + * generate style applier expression ... + * + * @param {string} style soecufic style name to use ... + * @param {boolean} reset close applier string by reset styles ... + * @returns {string} style applier string ... + */ +function getStyleApplier( + style = "", + reset = false +) { + // + let result = ""; + + // + // Detect and Validate Style and Apply it ... + let eStyle = AVAILABLE_STYLES[style]; + if (XValueTools.isValidArg(eStyle)) { + result = `${eStyle}`; + } + + // + if ( + !!reset && + result.length > 0 + ) { + result = `${result}${AVAILABLE_STYLES.Reset}`; + } + + // + return result; +} + +/** + * generate color applier expression ... + * + * @param {string} color specific color name for using to styling ... + * @param {boolean} reset close applier string by reset styles ... + * @param {boolean} toForeground apply specified color as foreground ... + * @param {boolean} toBackground apply specified color as background ... + * @returns {string} color applier string ... + */ +function getColorApplier( + color = "", + reset = false, + toForeground = true, + toBackground = false +) { + // + let result = ""; + + // + // Detect and Validate Foreground Color and Apply it ... + let eFColor = AVAILABLE_FOREGROUND_COLORS[color]; + if ( + !!toForeground + && XValueTools.isValidArg(eFColor) + ) { + result = `${eFColor}`; + } + + // + // Detect and Validate Background Color and Apply it ... + let eBColor = AVAILABLE_BACKGROUND_COLORS[color]; + if ( + !!toBackground + && XValueTools.isValidArg(eBColor) + ) { + result = `${eBColor}`; + } + + // + if ( + !!reset && + result.length > 0 + ) { + result = `${result}${AVAILABLE_STYLES.Reset}`; + } + + // + return result; +} + +/** + * colorified specific content ... + * + * @param {string} content specified content for styling ... + * @param {string} color specific color name for using to styling ... + * @param {boolean} toForeground apply specified color as foreground ... + * @param {boolean} toBackground apply specified color as background ... + * @returns {string} + */ +function colorifyContent( + content = "", + color = "", + toForeground = true, + toBackground = false +) { + // + let result = content; + + // + if (!XValueTools.isValidArg(content)) { + return result; + } + + // + // Finde Colors ... + + // + // Detect and Validate Foreground Color and Apply it ... + let eFColor = AVAILABLE_FOREGROUND_COLORS[color]; + if ( + !!toForeground + && XValueTools.isValidArg(eFColor) + ) { + result = `${eFColor}${result}`; + } + + // + // Detect and Validate Background Color and Apply it ... + let eBColor = AVAILABLE_BACKGROUND_COLORS[color]; + if ( + !!toBackground + && XValueTools.isValidArg(eBColor) + ) { + result = `${eBColor}${result}`; + } + + // + if ( + result.length > 0 + && ( + XValueTools.isValidArg(eFColor) || + XValueTools.isValidArg(eBColor) + ) + ) { + result = `${result}${AVAILABLE_STYLES.Reset}`; + } + + // + return result; +} + +/** + * apply style on specific content ... + * + * @param {string} content specified content for styling ... + * @param {string} style soecufic style name to use ... + * @returns {string} + */ +function stylifiyContent( + content = "", + style = "", +) { + // + let result = content; + + // + if (!XValueTools.isValidArg(content)) { + return result; + } + + // + // Detect and Validate Style and Apply it ... + let eStyle = AVAILABLE_STYLES[style]; + if (XValueTools.isValidArg(eStyle)) { + result = `${eStyle}${result}`; + } + + // + if ( + result.length > 0 + && XValueTools.isValidArg(eStyle) + ) { + result = `${result}${AVAILABLE_STYLES.Reset}`; + } + + // + return result; +} +//#endregion + +// +//#region Module Exports ... +module.exports = { + // + STYLE_NAMES, + COLOR_NAMES, + // + apply, + applyStyle, + getApplier, + getColorApplier, + getStyleApplier, + colorifyContent, + stylifiyContent, + applyForegroundColor, + applyBackgroundColor, +} +//#endregion \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/14030316/Documents/JsModules/x-file.tools.js b/MQLTestWorkspace/BKPS/14030316/Documents/JsModules/x-file.tools.js new file mode 100644 index 0000000..a1642a4 --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Documents/JsModules/x-file.tools.js @@ -0,0 +1,830 @@ +/** + * XFile Tools Module ... + * a module for handle all file/folder manipulating task in node js ... + * + * Maintainer + * + * Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) + */ + +// +//#region Module Imports ... +const fs = require('fs'); +const os = require('os'); +const Path = require('path'); +const http = require('http'); +const https = require('https'); +const XValueTools = require('./x-value.tools'); +//#endregion + +// +//#region Constants ... +/** + * current os path separators ... + */ +const PathSeparator = Path.sep; + +/** + * current directory ... + */ +const CurrentDir = __dirname; +//#endregion + +// +//#region Actions ... +// +//#region Global ... +/** + * retrieve a path status ... + * + * @param {string} path a path value to check ... + * @returns an stat object ... + */ +function getStatus(path = '') { + // + if (!XValueTools.isValidArg(path)) { + return undefined; + } + + // + return fs.statSync(path); +} + +/** + * retrieve user's Home path ... + * + * @returns {string} a path ... + */ +function getHomePath() { + return os.homedir(); +} +//#endregion + +// +//#region Path ... +/** + * retrieve the base name of specific address path ... + * + * @param {string} path address of file or folder ... + * @returns string ... + */ +function basename(path = '') { + // + if (!XValueTools.isValidArg(path)) { + return ''; + } + + // + const result = Path.basename(path); + return result; +} + +/** + * join several path segments together ... + * + * @param {...string} path path params ... + * @returns a joined paths ... + */ +function joinPath(...path) { + return Path.join(...path); +} + +/** + * resolve a relative path to absolute ... + * + * @param {string[]} path a path value to check ... + * @returns {string} + */ +function resolvePath(...path) { + return Path.resolve(...path); +} +//#endregion + +// +//#region File ... +/** + * determines a path destination is a file or not ... + * + * @param {string} path a path value to check ... + * @returns a boolean value ... + */ +function isFileExists(path = '') { + // + if (!XValueTools.isValidArg(path)) { + return false; + } + + // + try { + const stat = getStatus(path); + if (!stat) { + return false; + } + + // + return stat.isFile(); + } catch { + return false; + } +} + +/** + * remove a file ... + * + * @param {string} path a file path ... + * @returns {Promise} action done or not ... + */ +function removeFile(path = '') { + return new Promise((resolve) => { + // + if (!isFileExists(path)) { + resolve(false); + } + + // + fs.unlink(path, (err) => { + // + if (err) { + resolve(false); + return; + } + + // + resolve(true); + }); + }); +} + +/** + * copy a file to destination path ... + * + * @param {string} source source file path ... + * @param {string} dest dest folder path ... + * @returns {Promise} action done or not ... + */ +function copyFile( + source = '', + dest = '' +) { + return new Promise((resolve) => { + // + if ( + !isFileExists(source) || + !isDirectoryExists(dest) + ) { + resolve(false); + return; + } + + // + const destFilePath = Path.join(dest, Path.basename(source)); + fs.copyFile(source, destFilePath, (err) => { + // + if (err) { + resolve(false); + return; + } + + // + resolve(true); + }); + }); +} + +/** + * reading specified file content ... + * + * @param {string} path a file path ... + * @returns {Promise} file content ... + */ +function readFile(path = '') { + return new Promise((resolve) => { + // + if (!isFileExists(path)) { + resolve(''); + return; + } + + // + fs.readFile(path, 'utf8', (err, content) => { + // + if (err) { + resolve(undefined); + return; + } + + // + resolve(content); + }); + }); +} + +/** + * write content to a file ... + * + * @param {string} path a file path ... + * @param {string} content the content which going to write to the file ... + * @param {bool} overwrite determines file overwrite if exists ... + * @returns {Promise} action done or not ... + */ +function writeFile( + path = '', + content = '', + overwrite = true +) { + return new Promise((resolve) => { + // + if (isFileExists(path) && !overwrite) { + // + resolve(false); + return; + } + + // + // Normalize Content ... + content = XValueTools.isValidArg(content) ? + content : + ''; + + // + fs.writeFile(path, content, (err) => { + // + if (err) { + // + resolve(false); + return; + } + + // + resolve(true); + }); + }); +} + +/** + * create a file ... + * + * @param {string} path file path ... + * @param {string} fileName file name ... + * @returns {Promise} action done or not ... + */ +function createFile( + path = '', + fileName = '' +) { + return new Promise((resolve) => { + // + const filePath = Path.join(path, fileName); + if ( + isFileExists(filePath) || + !XValueTools.isValidArg(path) || + !XValueTools.isValidArg(fileName) + ) { + // + resolve(false); + return; + } + + // + fs.writeFile(filePath, '', (err) => { + // + if (err) { + // + resolve(false); + return; + } + + // + resolve(true); + }); + }); +} + +/** + * remove a file name extension ... + * + * @param {string} name + * @returns {string} name without extension ... + */ +function removeFileExtension(name = '') { + return name.substring(0, name.lastIndexOf('.')) || name; +} + +/** + * retrieve a file extension ... + * + * @param {string} path a path which locate a file ... + * @returns {string} + */ +function getFileExtension(path = '') { + // + let result = ""; + + // + // Validate Arg ... + if ( + !XValueTools.isValidArg(path) + || !isFileExists(path) + ) { + return result; + } + + // + // Retrieve just file name ... + const fileName = basename(path); + result = fileName.replace( + removeFileExtension(fileName), + "" + ); + + // + return result; +} + +/** + * retrieve all files list recursively from specific path ... + * + * @param {string} path a source folder path ... + * @param {string[]} extensions which file extensions need to be listed, live empty for all files ... + * @returns {Promise} + */ +async function getRecursiveFilesList( + path = "", + extensions = [] +) { + // + let result = []; + + // + // Validate Args ... + if ( + !XValueTools.isValidArg(path) + || !isDirectoryExists(path) + ) { + return result; + } + + // + const contents = await getDirectoryContents(path); + for(const item of contents) { + // + const itemPath = joinPath( + path, + item + ); + + // + const isItemFile = isFileExists(itemPath); + if (isItemFile) { + // + const itemFileExtension = getFileExtension(itemPath); + const isFileInSupportedExtensions = + extensions === undefined || extensions.length === 0 + ? true + : extensions.includes(itemFileExtension) + ; + if (isFileInSupportedExtensions) { + result.push(itemPath); + } + } else if (isDirectoryExists(itemPath)) { + // + const itemPathFiles = await getRecursiveFilesList(itemPath, extensions); + result.push(...itemPathFiles); + } + } + + // + return result; +} +//#endregion + +// +//#region Directory ... +/** + * create a directory ... + * + * @param {string} path destination path including dir name ... + * @param {boolean} recursive create directories recursively ... + * @returns action done or not ... + */ +function createDirectory( + path = '', + recursive = true +) { + // + let result = false; + + // + if ( + isDirectoryExists(path) || + !XValueTools.isValidArg(path) + ) { + return false; + } + + // + try { + // + fs.mkdirSync(path, { recursive: recursive }); + result = true; + return result; + } catch { + return false; + } +} + +/** + * remove a directory ... + * + * @param {string} path destination path including dir name ... + * @param {boolean} recursive removes directories recursively ... + * @returns {Promise} action done or not ... + */ +function removeDirectory( + path = '', + recursive = false +) { + return new Promise((resolve) => { + // + if (!isDirectoryExists(path)) { + resolve(false); + return; + } + + // + fs.rm(path, { + recursive + }, (err) => { + // + if (err) { + resolve(false); + return; + } + + // + resolve(true); + }); + }); +} + +/** + * determines a path destination is a directory or not ... + * + * @param {string} path a folder path ... + * @returns represent destnation path is Directory or not ... + */ +function isDirectoryExists(path = '') { + // + if (!XValueTools.isValidArg(path)) { + return false; + } + + // + try { + // + const isExists = fs.existsSync(path); + if (!isExists) { + return false; + } + + // + const stat = getStatus(path); + if (!stat) { + return false; + } + + // + const result = stat.isDirectory(); + return result; + } catch { + return false; + } +} + +/** + * retrieve a directory content ... + * + * @param {string} path a folder path ... + * @returns {Promise} a collection of folder files ... + */ +function getDirectoryContents(path = '') { + return new Promise((resolve) => { + // + if (!isDirectoryExists(path)) { + resolve([]); + return; + } + + // + fs.readdir(path, (err, content) => { + // + if (err) { + resolve([]); + return; + } + + // + resolve(content); + }); + }); +} + +/** + * retrieve a directory files ... + * + * @param {string} path a folder path ... + * @returns {Promise} a collection of folder files ... + */ +function getDirectoryFiles( + path = '', + containsHiddenFiles = false +) { + return new Promise((resolve) => { + // + if (!isDirectoryExists(path)) { + resolve([]); + return; + } + + // + fs.readdir(path, (err, content) => { + // + if (err) { + resolve([]); + return; + } + + // + if (!containsHiddenFiles) { + content = content.filter(c => !c.startsWith('.')); + } + + // + const result = []; + content + .forEach(c => { + // + const cPath = Path.join(path, c); + if (isFileExists(cPath)) { + result.push(c); + } + }); + + // + resolve(result); + }); + }); +} + +/** + * retrieve a directory folders ... + * + * @param {string} path a folder path ... + * @returns {Promise} a collection of folder names ... + */ +function getDirectoryFolders(path = '') { + return new Promise((resolve) => { + // + if (!isDirectoryExists(path)) { + resolve([]); + return; + } + + // + fs.readdir(path, (err, content) => { + // + if (err) { + resolve([]); + return; + } + + // + const result = []; + content.forEach(c => { + // + const cPath = Path.join(path, c); + if (isDirectoryExists(cPath)) { + result.push(c); + } + }); + + // + resolve(result); + }); + }); +} + +/** + * copy a folder with all of it's content to dest ... + * + * @param {string} source source folder path ... + * @param {string} dest dest folder path ... + * @returns {Promise} action done or not ... + */ +async function copyFolder( + source = '', + dest = '' +) { + // + if ( + !isDirectoryExists(source) || + !XValueTools.isValidArg(dest) || + !XValueTools.isValidArg(source) + ) { + return false; + } + + // + const folderName = Path.basename(source); + const destPath = Path.join(dest, folderName); + + // + // Create Dest Path folder if not exists ... + if (!isDirectoryExists(destPath)) { + // + let result = createDirectory(destPath, true); + if (!result) { + return false; + } + } + + // + // Files ... + const files = await getDirectoryFiles(source); + if (files && files.constructor === Array && files.length > 0) { + // + const filesPromises = files.map(file => copyFile(Path.join(source, file), destPath)); + const filesResult = (await Promise.all(filesPromises)).every(r => !!r); + if (!filesResult) { + return false; + } + } + + // + // Folders ... + const folders = await getDirectoryFolders(source); + if (folders && folders.constructor === Array && folders.length > 0) { + // + const folderPromises = folders.map(folder => copyFolder(Path.join(source, folder), destPath)); + const filesResult = (await Promise.all(folderPromises)).every(r => !!r); + if (!filesResult) { + return false; + } + } + + // + return true; +} +//#endregion + +// +//#region Downloader ... +/** + * download a file from specific url and store it ... + * + * @param {string} filepath the file name and path which required to put download file on it ... + * @param {string} url the web url for downloading ... + */ +function download(filepath, url) { + // + // Validate Args ... + if ( + !XValueTools.isValidArg(url) + || !XValueTools.isValidURL(url) + || !XValueTools.isValidArg(filepath) + ) { + return; + } + + // + var file = fs.createWriteStream(filepath); + + // + if (url.startsWith('https:')) { + https.get(url, function (response) { + response.pipe(file); + }); + } else if (url.startsWith('http:')) { + http.get(url, function (response) { + response.pipe(file); + }); + } +} +//#endregion + +// +//#region JSON ... +/** + * read and parse a JSON content from a file ... + * + * @param {string} path source file path ... + * @returns {any} + */ +function readJSON(path = "") { + // + // Validate Args ... + if (!isFileExists(path)) { + return undefined; + } + + // + let result = undefined; + try { + result = require(path); + } catch { + result = undefined; + } + + // + return result; +} + +/** + * write a JSON Object content into a file ... + * + * @param {string} path dest file path ... + * @param {any} content an object which required to write to file ... + * @returns {Promise} + */ +async function writeJSON( + path = "", + content = undefined +) { + // + let result = false; + + // + // Validate Args ... + if (!XValueTools.isValidArg(path)) { + return result; + } + + // + // Normallize Content ... + if (content === undefined) { + content = {}; + } + + // + const contentString = XValueTools.beautifyJSON(content); + + // + result = await writeFile( + path, + contentString, + true + ); + + // + return result; +} +//#endregion +//#endregion + +// +//#region Module Exports ... +module.exports = { + // + CurrentDir, + PathSeparator, + + // + getStatus, + getHomePath, + + // + basename, + joinPath, + resolvePath, + + // + download, + + // + readJSON, + writeJSON, + + // + copyFile, + readFile, + writeFile, + createFile, + removeFile, + isFileExists, + getFileExtension, + removeFileExtension, + getRecursiveFilesList, + + // + copyFolder, + createDirectory, + removeDirectory, + createDirectory, + removeDirectory, + isDirectoryExists, + isDirectoryExists, + getDirectoryFiles, + getDirectoryFolders, + getDirectoryContents, +} +//#endregion \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/14030316/Documents/JsModules/x-shell.tools.js b/MQLTestWorkspace/BKPS/14030316/Documents/JsModules/x-shell.tools.js new file mode 100644 index 0000000..0ee13de --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Documents/JsModules/x-shell.tools.js @@ -0,0 +1,219 @@ +/** + * XShell Tools Module ... + * a module for handling shell actions and retrieve OS Info in node js ... + * + * Maintainer + * + * Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) + */ + +// +//#region Imports ... +const os = require('os'); +const process = require('process'); +const { exec } = require("child_process"); +const XFileTools = require('./x-file.tools'); +//#endregion + +// +//#region Constants ... +// +const OS = { + Aix: 'aix', + Darwin: 'darwin', + FreeBSD: 'freebsd', + Linux: 'linux', + OpenBSD: 'openbsd', + SnOS: 'sunos', + Windows: 'win32' +}; + +// +const isWindows = process.platform === OS.Windows; +//#endregion + +// +//#region Actions ... +// +//#region Pure shell commands ... +/** + * execute a command using NodeJS on shell ... + * + * @param {string} cmd command to execute ... + * @param {string} cwd working directory ... + * + * @returns Promise instance ... + */ +function execute(cmd, cwd) { + return new Promise((resolve, reject) => { + // + if (!cmd || cmd.toString().length === 0 || (cwd && !XFileTools.isDirectoryExists(cwd))) { + reject('invalid args ...'); + return; + } + + // + exec(cmd, { cwd }, (err, result, stdError) => { + // + if (err) { + reject(err); + return; + } + + // + if (stdError) { + // + // reject(stdError); + // return; + } + + // + resolve(result); + }); + }); +}; + +/** + * determines a command exists on host or not ... + * + * @param {string} name specific command name ... + * + * @returns boolean Promise ... + */ +function checkCommandExists(name) { + return new Promise(resolve => { + // + if (!name) { + resolve(false); + return; + } + + // + const cmd = isWindows ? `${name} >nul 2>&1` : `type ${name} >/dev/null 2>&1`; + execute(cmd).then(result => { + resolve(true); + }) + .catch(err => { + resolve(false); + }); + }); +} +//#endregion + +// +//#region required commands state ... +/** + * check al required commands exists or not ... + * + * @returns + */ +async function isRequiredCommandsExists() { + // + let result = false; + + // + // const isTarExists = await isTarCommandExists(); + // const isCatExists = await isCatCommandExists(); + // const isGrepExists = await isGrepCommandExists(); + // const isSedExists = await isSedCommandExists(); + const isNpmExists = await isNpmCommandExists(); + const isNgExists = await isNgCommandExists(); + const isIonicExists = await isIonicCommandExists(); + const isCordovaExists = await isCordovaCommandExists(); + + // + result = isNpmExists + && isNgExists + && isIonicExists + && isCordovaExists + ; + + // + return result; +} + +/** + * retrieve required commands state object ... + * + * @returns + */ +async function getRequiredCommandsStates() { + // + const result = {}; + + // + // const isTarExists = await isTarCommandExists(); + // const isCatExists = await isCatCommandExists(); + // const isGrepExists = await isGrepCommandExists(); + // const isSedExists = await isSedCommandExists(); + const isNpmExists = await isNpmCommandExists(); + const isNgExists = await isNgCommandExists(); + const isIonicExists = await isIonicCommandExists(); + const isCordovaExists = await isCordovaCommandExists(); + + // + result['npm'] = isNpmExists; + result['ng'] = isNgExists; + result['ionic'] = isIonicExists; + result['cordova'] = isCordovaExists; + + // + return result; +} +//#endregion + +// +//#region Commonly used Command Checkers ... +/** + * determines npm command exists or not ... + * + * @returns + */ +function isNpmCommandExists() { + return checkCommandExists('npm'); +} + +/** + * determines ng command exists or not ... + * + * @returns + */ +function isNgCommandExists() { + return checkCommandExists('ng'); +} + +/** + * determines ionic command exists or not ... + * + * @returns + */ +function isIonicCommandExists() { + return checkCommandExists('ionic'); +} + +/** + * determines cordova command exists or not ... + * + * @returns + */ +function isCordovaCommandExists() { + return checkCommandExists('cordova'); +} +//#endregion +//#endregion + +// +//#region Module Exports ... +module.exports = { + // + execute, + checkCommandExists, + isRequiredCommandsExists, + getRequiredCommandsStates, + + // + isNgCommandExists, + isIonicCommandExists, + isCordovaCommandExists, +} +//#endregion \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/14030316/Documents/JsModules/x-type-detector.tools.js b/MQLTestWorkspace/BKPS/14030316/Documents/JsModules/x-type-detector.tools.js new file mode 100644 index 0000000..86ed3d8 --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Documents/JsModules/x-type-detector.tools.js @@ -0,0 +1,268 @@ +/** + * DataType Tools Module ... + * a module for manipulate and detect supported data types in node js ... + * + * Maintainer + * + * Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) + */ + +// +//#region Constants ... +/** + * all supported data types ... + */ +const DataTypes = { + Null: 'null', + Date: 'date', + Array: 'array', + Object: 'object', + String: 'string', + Number: 'number', + Unknown: 'unknown', + Boolean: 'boolean', + Function: 'function', + Undefined: 'undefined', +}; +//#endregion + +// +//#region Actions ... +/** + * detect type of a content ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function getType(value) { + // + const type = typeof value; + + // + let result = DataTypes.Unknown; + let dateIdentifier = '[object Date]'; + let constructor = value && value.constructor ? + value.constructor.toString() : + ''; + + // + switch (type) { + // + case 'undefined': + result = DataTypes.Undefined; + break; + + // + case 'boolean': + result = DataTypes.Boolean; + break; + + // + case 'string': + result = DataTypes.String; + break; + + // + case 'number': + result = DataTypes.Number; + break; + + // + case 'function': + result = DataTypes.Function; + break; + + // + case 'object': + // + // Null ... + if (value === null) { + result = DataTypes.Null; + } else + // + // Array ... + if (Array.isArray(value)) { + result = DataTypes.Array; + } else + // + // Data ... + if ( + value instanceof Date || + isFunction(value.getMonth) || + constructor.includes(dateIdentifier) || + Object.prototype.toString.call(value) === dateIdentifier + ) { + result = DataTypes.Date; + } else + // + // Object ... + { + result = DataTypes.Object; + } + break; + + // + default: + result = DataTypes.Unknown; + break; + } + + // + return result; +} + +/** + * retrieve an object constructor ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function getConstructor(value) { + // + const result = value && value.constructor ? + value.constructor.toString() : + ''; + + // + return result; +} + +/** + * retrieve an object prototype ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function getPrototype(value) { + // + const result = value ? + Object.prototype.toString.call(value) : + ''; + + // + return result; +} + +/** + * check an object is null or not ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function isNull(value) { + return getType(value) === DataTypes.Null; +} + +/** + * check an object is undefined or not ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function isUndefined(value) { + return getType(value) === DataTypes.Undefined; +} + +/** + * check an object is null or undefined or not ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function isNullOrUndefined(value) { + return isNull(value) || isUndefined(value); +} + +/** + * check an object is a date or not ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function isDate(value) { + return getType(value) === DataTypes.Date; +} + +/** + * check an object is number or not ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function isNumber(value) { + return getType(value) === DataTypes.Number; +} + +/** + * check an object is string or not ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function isString(value) { + return getType(value) === DataTypes.String; +} + +/** + * check an object is boolean or not ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function isBoolean(value) { + return getType(value) === DataTypes.Boolean; +} + +/** + * check an object is an Array or not ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function isArray(value) { + return getType(value) === DataTypes.Array; +} + +/** + * check an object is and Object or not ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function isObject(value) { + return getType(value) === DataTypes.Object; +} + +/** + * check an object is a Function or not ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function isFunction(value) { + return getType(value) === DataTypes.Function; +} +//#endregion + +// +//#region Module Exports ... +module.exports = { + // + DataTypes, + + // + getType, + getConstructor, + getPrototype, + isNull, + isUndefined, + isNullOrUndefined, + isDate, + isNumber, + isString, + isBoolean, + isArray, + isObject, + isFunction, +} +//#endregion \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/14030316/Documents/JsModules/x-value.tools.js b/MQLTestWorkspace/BKPS/14030316/Documents/JsModules/x-value.tools.js new file mode 100644 index 0000000..81cfcc4 --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Documents/JsModules/x-value.tools.js @@ -0,0 +1,1528 @@ +/** + * Value Tools Module ... + * a module for Validate args and values ... + * + * Maintainer + * + * Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) + */ + +// +//#region Imports ... +const XTypeTools = require('./x-type-detector.tools'); +//#endregion + +// +//#region Actions ... +/** +* validate a value as an argument ... +* +* @param {string} value the value which going to validate ... +* @returns +*/ +function isValidArg(value) { + // + let result = false; + + // + result = value && + value.length > 0; + + // + return result; +} + +/** + * validate a collection of valuea as an arguments ... + * + * @param {string|string[]} values the value collection which going to checked ... + * @returns + */ +function isValidArgs(values) { + // + // Normalize Values ... + const normalValues = toNormalArray(values); + if (!hasChildArray(normalValues)) { + return false; + } + + // + let result = normalValues.every(nv => isValidArg(nv)); + return result; +} + +/** + * converts content to an array object ... + * + * @param {string|string[]} content the content which required to normalized ... + * @returns {string[]} array object ... + */ +function toNormalArray(content = '') { + // + // Validate Args ... + if (!isValidArg(content)) { + return []; + } + + // + const result = Array.isArray(content) ? + [...content] : + content.includes(',') && + content !== ',' ? + [...content.split(',')] : + [content]; + + // + return result; +} + +/** + * determines value is array and has atleast one child ... + * + * @param {any} value the value which going to checked ... + * @returns {boolean} result of checking ... + */ +function hasChildArray(value) { + // + let result = false; + result = value && + Array.isArray(value) && + value.length > 0; + + // + return result; +} + +/** + * check an string is ends with specified symbol ... + * + * @param {string} symbol specified search symbol ... + * @param {string} value specified search content ... + * @param {boolean} ignoreCase specified search case sensitive or not ... + * @returns + */ +function endsWidth( + symbol = '', + value = '', + ignoreCase = true +) { + // + if (!isValidArg(value)) { + return false; + } + + // + if (!isValidArg(symbol)) { + return true; + } + + // + // TODO: uncomment it if necessary ... + // symbol = symbol.trim(); + + // + let result = false; + const subtractedContent = value.substring(value.length - symbol.length); + result = !!ignoreCase ? + subtractedContent + .toLowerCase() === symbol + .toLowerCase() : + subtractedContent === symbol; + + // + return result; +} + +/** + * surround specified content by provided symbol ... + * + * @param {string} symbol surround string ... + * @param {string} content used content to surrounded by symbol ... + * @returns surrounded content ... + */ +function surroundBy( + symbol = '', + content = '' +) { + // + // Validate Args ... + if (!isValidArg(content)) { + content = ''; + } + + // + if (!isValidArg(symbol)) { + symbol = ''; + } + + // + if (isSurrounded(symbol, content)) { + return content; + } + + // + const result = `${symbol}${content}${symbol}`; + return result; +} + +/** + * convert a parsed sign to clear string ... + * + * @param {string} value a parsed content ... + * @returns clear parsed signs ... + */ +function toStringExpression(value) { + // + let result = ''; + result = value; + + // + if ( + !value || + !isValidArg(value) || + !isSurroundedString(value) + ) { + return result; + } + + // + const startSymbol = value.charAt(0); + const endSymbol = value.charAt(value.length - 1); + + // + if (startSymbol !== endSymbol) { + return result; + } + + // + if ( + startSymbol === "\"" || + startSymbol === "\'" + ) { + result = clearSurround(startSymbol, value); + } + + // + return result; +} + + + +/** + * find and cleare proposed candidates from specified content ... + * + * @param {string|string[]} candidates the proposed string(s) whic going to cleared from content ... + * @param {string} content the destination content which used to find and replace candidates on it ... + * @returns cleared content ... + */ +function clearContent( + candidates, + content +) { + // + // Validate Args ... + if ( + !candidates || + !isValidArg(content) + ) { + return ''; + } + + // + // Normalize candidates ... + const normalCandidates = toNormalArray(candidates) + .filter(c => isValidArg(c)); + if (!hasChildArray(normalCandidates)) { + return content; + } + + // + // define regexp for content ... + const regExpExpression = normalCandidates.join('|'); + const regExp = new RegExp( + regExpExpression, + 'gi' + ); + + // + let result = ''; + result = content.replace(regExp, ''); + + // + return result; +} + +/** + * clear surrounded symbol from content ... + * + * @param {string} symbol specified search symbol ... + * @param {string} content specified content to clear ... + * @returns + */ +function clearSurround( + symbol = '', + content = '' +) { + // + // Validate Args ... + if ( + !isValidArg(content) || + (isValidArg(symbol) && + symbol.length >= content.length - 1) + ) { + return ''; + } + + // + // Validate Surround ... + if (!isSurrounded(symbol, content)) { + return content; + } + + // + if (!isValidArg(symbol)) { + return content; + } + + // + let result = content.substring(symbol.length, content.length - symbol.length); + return result; +} + +/** + * clear object sign ... + * + * @param {string} content + * @returns cleared content ... + */ +function clearObjectSurround(content = '') { + // + // Validate Args ... + if ( + !isValidArg(content) || + !isSurroundedObject(content) + ) { + return content; + } + + // + const endIndex = content.length - ( + endsWidth('}', content) ? + 1 : + endsWidth('},', content) || + endsWidth('};', content) || + endsWidth('}\n', content) ? + 2 : + 0 + ); + + // + const result = content.substring(1, endIndex); + return result; +} + +/** + * clear array sign ... + * + * @param {string} content + * @returns cleared content ... + */ +function clearArraySurround(content = '') { + // + // Validate Args ... + if ( + !isValidArg(content) || + !isSurroundedArray(content) + ) { + return content; + } + + // + const endIndex = content.length - ( + endsWidth(']', content) ? + 1 : + endsWidth('],', content) || + endsWidth('];', content) || + endsWidth(']\n', content) ? + 2 : + 0 + ); + + // + const result = content.substring(1, endIndex); + return result; +} + +/** + * slice a content to individual parts ... + * + * @param {number|number[]} indexes which indexes used to slice ... + * @param {strng} content the content which going to sliced ... + * @returns sliced parts of content ... + */ +function sliceContent(indexes, content) { + // + // Validate Args ... + if ( + !isValidArg(indexes) || + !isValidArg(content) + ) { + return []; + } + + // + // Normalize indexes ... + const normalIndexes = toNormalArray(indexes) + .filter(index => index > -1 && index < content.length); + if (!hasChildArray(normalIndexes)) { + return []; + } + + // + let result = ['']; + result.pop(); + + // + let lastIndex = 0; + for (const index of normalIndexes) { + // + const part = content.substring(lastIndex, index); + if (isValidArg(part)) { + result.push(part.trim()); + } + + // + lastIndex = index + 1; + } + + // + // check remained parts ... + if (lastIndex < content.length) { + // + const part = content.substring(lastIndex); + if (isValidArg(part)) { + result.push(part.trim()); + } + } + + // + return result; +} + + + +/** + * check an string is starts and ends with specified symbol ... + * + * @param {string} symbol specified search symbol ... + * @param {string} content specified search content ... + * @param {boolean} ignoreCase specified search case sensitive or not ... + * @returns + */ +function isSurrounded( + symbol = '', + content = '', + ignoreCase = true +) { + // + // Validate Args ... + if (!isValidArg(content)) { + return false; + } + + // + if (!isValidArg(symbol)) { + return true; + } + + // + symbol = symbol.trim(); + + // + let result = false; + result = (!!ignoreCase ? + content + .toLowerCase() + .startsWith(symbol.toLowerCase()) : + content.startsWith(symbol) + ) && + endsWidth(symbol, content, ignoreCase); + + // + return result; +} + +/** + * determines a content is an string surrounded value or not ... + * + * @param {string} content a content which going to check ... + * @returns + */ +function isSurroundedString(content = '') { + // + // Validate Args ... + if (!isValidArg(content)) { + return false; + } + + // + let result = false; + result = ( + content.startsWith('\'') && + ( + endsWidth('\'', content) || + endsWidth('\',', content) || + endsWidth('\';', content) || + endsWidth('\'\n', content) + ) || + content.startsWith('\"') && + ( + endsWidth('\"', content) || + endsWidth('\",', content) || + endsWidth('\";', content) || + endsWidth('\"\n', content) + ) || + content.startsWith('`') && + ( + endsWidth('\`', content) || + endsWidth('\`,', content) || + endsWidth('\`;', content) || + endsWidth('\`\n', content) + ) + ); + return result; +} + +/** + * check a content is an array content or not ... + * + * @param {string} content + * @returns + */ +function isSurroundedArray(content = '') { + // + // Validate Args ... + if (!isValidArg(content)) { + return false; + } + + // + let result = false; + result = content.startsWith('[') && + ( + endsWidth(']', content) || + endsWidth('],', content) || + endsWidth('];', content) || + endsWidth(']\n', content) + ); + return result; +} + +/** + * check a content is an object content or not ... + * + * @param {string} content + * @returns + */ +function isSurroundedObject(content = '') { + // + // Validate Args ... + if (!isValidArg(content)) { + return false; + } + + // + let result = false; + result = content.startsWith('{') && + ( + endsWidth('}', content) || + endsWidth('},', content) || + endsWidth('};', content) || + endsWidth('}\n', content) + ); + return result; +} + +/** + * check an index model is contains inside anothers or not ... + * + * @param {{ start: number, end: number}} source the source index model to check ... + * @param {...{ start: number, end: number}} dest the collection of index models which going to check ... + * @returns + */ +function isIndexInside(source, ...dest) { + // + let result = false; + + // + // Validate Args ... + if (!source || !dest) { + return result; + } + + // + // Check idx is standard ... + if ( + !source || + !source.end || + !source.start || + source.start > source.end + ) { + return false; + } + + // + // Check types of destinations ... + for (let index of dest) { + // + // Check idx is standard ... + if ( + !index || + !index.end || + !index.start || + index.start > index.end + ) { + return false; + } + } + + // + if (dest.includes(source)) { + dest = dest.filter(d => d !== source); + } + + // + const insideContentIndex = dest.find(dIndex => { + // + const result = source.start >= dIndex.start && + source.start <= dIndex.end && + source.end >= dIndex.start && + source.end <= dIndex.end; + return result; + }); + + // + result = insideContentIndex; + return result; +} + +/** + * check a number exists in + * @param {number} idx the number which going to check ... + * @param {{ start: number, end: number}} index the index model + * @returns + */ +function isInsideIndex(idx = -1, index) { + // + let result = false; + + // + // Validate Args ... + if ( + !index || + !index.hasOwnProperty('end') || + !index.hasOwnProperty('start') + ) { + return result; + } + + // + result = idx > index.start && idx < index.end; + return result; +} + +/** + * determines an object is key/value and type ... + * + * @param {any} content the object which we are going to check ... + * @returns + */ +function isKeyValueType(content) { + // + const result = content && + content.hasOwnProperty('key') && + content.hasOwnProperty('type') && + content.hasOwnProperty('value'); + + // + return result; +} + + + +/** + * find all indexes of token(s) in content ... + * + * @param {string|string[]} tokens the tokens which require to search ... + * @param {string} content the content which using to search ... + * @returns {number[]} all occured indexes ... + */ +function findAllIndexes( + tokens, + content +) { + // + // Validate Args ... + if ( + !isValidArg(tokens) || + !isValidArg(content) + ) { + return []; + } + + // + // normalize tokens ... + const normalTokens = toNormalArray(tokens); + if (!hasChildArray(normalTokens)) { + return []; + } + + // + // Parse contents ... + let match; + const result = []; + const regExp = new RegExp( + normalTokens.join('|'), + 'g' + ); + while ((match = regExp.exec(content)) !== null) { + result.push(match.index); + } + if (!hasChildArray(result)) { + return []; + } + + // + return result; +} + +/** + * find nearest symbol in a content from specified index ... + * + * @param {string|string[]} candidates specifies which symbols to find ... + * @param {string} content te content for seasrch ... + * @param {number} startFromIndex the index of start position ... + * @returns + */ +function findNearest( + candidates, + content = '', + startFromIndex = 0 +) { + // + // Validate Args ... + if ( + !isValidArg(content) || + !isValidArg(candidates) || + !isValidArg(content.trim()) + ) { + return ''; + } + + // + // Normalize Content ... + content = content.trim(); + + // + // Normalize Starts From ... + startFromIndex = startFromIndex < 0 || startFromIndex > content.length - 1 ? 0 : startFromIndex; + + // + // Normalize Symbols ... + const normalCandidates = toNormalArray(candidates); + if (!hasChildArray(normalCandidates)) { + return ''; + } + + // + let nearestIndex = findNearestIndex( + normalCandidates, + content, + startFromIndex + ); + if (nearestIndex < 0) { + return ''; + } + + // + let result = content.substring( + nearestIndex, + nearestIndex + Math.max(...normalCandidates.map(nc => nc.length)) + ).trim(); + return result; +} + +/** + * search candidates in content and find nearest one and return it ... + * + * @param {string|string[]} candidates which candidates required to check ... + * @param {string} content the content which required to search candidates ... + * @param {number} startFromIndex the proposed index to start searching content from on ... + * @returns + */ +function findNearestIndex( + candidates = [''], + content = '', + startFromIndex = 0, + ignoreClosedItems = false +) { + // + // Validate Args ... + if ( + !isValidArg(content) || + !isValidArg(candidates) + ) { + return -1; + } + + // + // Mormalize startFromIndex value ... + startFromIndex = startFromIndex < 0 ? + 0 : + startFromIndex > content.length - 1 ? + content.length - 1 : + startFromIndex; + + // + // Normalize candidates ... + let normalCandidates = toNormalArray(candidates); + + // + if (!!ignoreClosedItems) { + normalCandidates = normalCandidates + .map(c => content.indexOf( + c, + startFromIndex + ) + ).map(c => +c) + .filter(c => +c > -1); + } else { + normalCandidates = findAllIndexesOutOfCloseds(normalCandidates, content) + .filter(c => c >= startFromIndex); + } + if (!hasChildArray(normalCandidates)) { + return -1; + } + + // + let result = -1; + result = Math.min(...normalCandidates); + + // + return result; +} + +/** + * find close index of specific sign in destination content ... + * + * @param {string} openSymbol open of area sign ... + * @param {string} closeSymbol close of area sign ... + * @param {string} content the destination content for parsing ... + * @param {number} startsFrom an start index of content for start parsing ... + * @returns + */ +function findCloseIndex( + openSymbol = '', + closeSymbol = '', + content = '', + startsFrom = -1 +) { + // + // Validate Args ... + if ( + startsFrom < 0 || + !isValidArg(content) || + !isValidArg(openSymbol) || + !isValidArg(closeSymbol) || + openSymbol === closeSymbol || + !content.includes(openSymbol) || + !content.includes(closeSymbol) || + startsFrom > content.length - 1 + ) { + return -1; + } + + // + let result = -1; + + // + let index = startsFrom; + const openSignStack = []; + while (index < content.length) { + // + const openCandidate = content.substring(index, index + openSymbol.length); + const closeCandidate = content.substring(index, index + closeSymbol.length); + + // + if (openCandidate === openSymbol) { + openSignStack.push(index); + } else if (closeCandidate === closeSymbol) { + // + if (openSignStack.length > 0) { + openSignStack.pop(); + } + + // + if (openSignStack.length === 0) { + result = index; + break; + } + } + + // + index++; + } + + // + return result; +} + +/** + * find closed contents of specific sign in destination content ... + * + * @param {string} openSymbol open of area sign ... + * @param {string} closeSymbol close of area sign ... + * @param {string} content the destination content for parsing ... + * @param {number} startsFrom an start index of content for start parsing ... + * @returns + */ +function findClosedContent( + openSymbol = '', + closeSymbol = '', + content = '', + startsFrom = 0, +) { + // + let result = [{ + start: -1, + end: -1, + content: '' + }]; + result.pop(); + + // + // Validate Args ... + if ( + !isValidArg(content) || + !isValidArg(openSymbol) || + !isValidArg(closeSymbol) || + !content.includes(openSymbol) || + !content.includes(closeSymbol) || + openSymbol.length >= content.length || + closeSymbol.length >= content.length + ) { + return result; + } + + // + // Normalize Start From ... + startsFrom = startsFrom < 0 || startsFrom >= content.length ? 0 : startsFrom; + + // + let canContinue = true; + while (!!canContinue) { + // + let openSymbolIndex = content.indexOf(openSymbol, startsFrom); + if (openSymbolIndex < 0) { + // + canContinue = false; + continue; + } + + // + let closeSymbolIndex = findCloseIndex( + openSymbol, + closeSymbol, + content, + openSymbolIndex + ); + if (closeSymbolIndex < 0) { + // + canContinue = false; + continue; + } + if (content.charAt(closeSymbolIndex) !== closeSymbol) { + closeSymbolIndex++; + } + + // + // Prevent ${} string interpolations ... + if ( + openSymbol === '{' && + openSymbolIndex - 1 >= 0 + ) { + // + const prevChar = content.charAt(openSymbolIndex - 1); + if (prevChar === '$') { + continue; + } + } + + // + const item = content + .substring(openSymbolIndex, closeSymbolIndex + 1) + .trim(); + startsFrom = closeSymbolIndex + 1; + result.push({ + start: openSymbolIndex, + end: closeSymbolIndex, + content: item + }); + } + + // + if (!hasChildArray(result)) { + return result; + } + + // + return result; +} + +/** + * extract a collection of closed contents exists in a content ... + * + * @param symbols a collection of open and close contents ... + * @param {string} content a content for searching inside it ... + * @returns a collection of closed content ... + */ +function findClosedContents( + symbols = [ + { + openSymbol: '', + closeSymbol: '' + } + ], + content = '' +) { + // + let result = [{ + start: -1, + end: -1, + content: '' + }]; + result.pop(); + + // + if ( + !isValidArg(content) || + !hasChildArray(symbols) + ) { + return []; + } + + // + symbols.forEach(symbol => { + // + const closedContent = findClosedContent( + symbol.openSymbol, + symbol.closeSymbol, + content + ); + + // + if (hasChildArray(closedContent)) { + result.push( + ...closedContent + ); + } + }); + + // + return result; +} + +/** + * find all string content closed items ... + * + * @param {string} content a content which going to search ... + * @returns a collection of index descriptors ... + */ +function findClosedStrings(content = '') { + // + // Validate Args ... + if (!isValidArg(content)) { + return []; + } + + // + // there are 3 types of strings ... + // ' " and ` + + // + const token1 = '\''; + const token1Stack = [0]; + token1Stack.pop(); + + // + const token2 = '"'; + const token2Stack = [0]; + token2Stack.pop(); + + // + const token3 = '`'; + const token3Stack = [0]; + token3Stack.pop(); + + // + const result = [ + { + start: -1, + end: -1, + content: '' + } + ]; + result.pop(); + + // + for (let i = 0; i < content.length; i++) { + // + const currentChart = content.charAt(i); + + // + //#region Token 1 ... + if (currentChart === token1) { + // + if (!hasChildArray(token1Stack)) { + token1Stack.push(i); + } else { + // + const start = token1Stack.pop(); + const end = i + 1; + const pContent = content.substring(start, end); + result.push({ + start, + end, + content: pContent + }); + } + } + //#endregion + + // + //#region Token 2 ... + if (currentChart === token2) { + // + if (!hasChildArray(token2Stack)) { + token2Stack.push(i); + } else { + // + const start = token2Stack.pop(); + const end = i + 1; + const pContent = content.substring(start, end); + result.push({ + start, + end, + content: pContent + }); + } + } + //#endregion + + // + //#region Token 3 ... + if (currentChart === token3) { + // + if (!hasChildArray(token3Stack)) { + token3Stack.push(i); + } else { + // + const start = token3Stack.pop(); + const end = i + 1; + const pContent = content.substring(start, end); + result.push({ + start, + end, + content: pContent + }); + } + } + //#endregion + } + + // + return result; +} + +/** + * find container indexes from within indexes ... + * + * @param {...{start: number, end: number}} index the collection of indexes to find beiggers inside ... + * @returns + */ +function findContainerIndexes(...index) { + // + let result = [ + { + start: -1, + end: -1, + content: '' + } + ]; + result.pop(); + + // + let concatedIndexes = []; + for (let idx of index) { + // + // Index Childs ... + for (let iix of idx) { + // + // Check idx is standard ... + if ( + !iix || + !iix.end || + !iix.start || + iix.start > iix.end + ) { + continue; + } + + // + // Check index inside another index ... + concatedIndexes.push(iix); + } + } + + // + if (!hasChildArray(concatedIndexes)) { + return result; + } + + // + for (let ccIdx of concatedIndexes) { + // + const isInside = isIndexInside(ccIdx, ...concatedIndexes); + if (isInside) { + continue; + } + + // + if (hasChildArray(result)) { + // + const isInsideResult = isIndexInside(ccIdx, ...result); + if (isInsideResult) { + continue; + } + } + + // + result.push(ccIdx); + } + + // + return result; +} + +/** + * find all tokens indexes inside a content which they are not inside closed items ... + * + * @param {string|string[]} tokens the tokens which require to search ... + * @param {string} content the content which using to search ... + * @returns + */ +function findAllIndexesOutOfCloseds1( + tokens, + content, +) { + // + // Validate Args ... + if (!isValidArg(content)) { + return []; + } + + // + // Extract token Indexes ... + const tokensIndexes = findAllIndexes(tokens, content); + if (!hasChildArray(tokensIndexes)) { + return []; + } + + // + // Extract Closed Objects Indexes ... + const closedArrays = findClosedContent('[', ']', content); + const closedObjects = findClosedContent('{', '}', content); + const closedStrings = findClosedStrings(content); + if ( + !hasChildArray(closedObjects) && + !hasChildArray(closedArrays) && + !hasChildArray(closedStrings) + ) { + return tokensIndexes; + } + + // + // find bigger sloded ... + let containerClosedItems = findContainerIndexes( + closedArrays, + closedObjects, + closedStrings + ).filter(i => !isSurroundedString(i.content)); + + // + let result = [-1]; + result.pop(); + + // + for (let tIdx of tokensIndexes) { + // + let canAdd = true; + for (let ccIndex of containerClosedItems) { + // + canAdd = isInsideIndex(tIdx, ccIndex); + if (canAdd) { + break; + } + } + + // + if (!canAdd) { + result.push(tIdx); + } + } + + // + return result; +} + +/** + * find all tokens indexes inside a content which they are not inside closed items ... + * + * @param {string|string[]} tokens the tokens which require to search ... + * @param {string} content the content which using to search ... + * @returns + */ +function findAllIndexesOutOfCloseds( + tokens, + content, +) { + // + // Define Result ... + let result = [-1]; + result.pop(); + + // + // Validate Args ... + if (!isValidArg(content)) { + return []; + } + + // + // Normalize Tokens ... + const normalizeTokens = toNormalArray(tokens); + if (!hasChildArray(normalizeTokens)) { + return result; + } + + // + // Extract Closed Objects Indexes ... + let openSymbols = [ + '{', + '[', + '\'', + '"', + '`' + ]; + let closeSymbols = [ + '}', + ']', + '\'', + '"', + '`' + ]; + let openStack = []; + let lastOpenSymbol = ''; + let lastClosedIndex = -1; + for (let i = 0; i < content.length; i++) { + // + const prevChar = content.charAt(i - 1) || ''; + const char = content.charAt(i); + const nextChar = content.charAt(i + 1) || ''; + + // + const isToken = normalizeTokens.includes(char); + const isOpenSymbol = openSymbols.includes(char); + const isCloseSymbol = closeSymbols.includes(char); + + // + if (isOpenSymbol && lastOpenSymbol !== char) { + openStack.push(i); + lastOpenSymbol = char === '\'' || char === '"' || char === '`' ? char : lastOpenSymbol; + } else if (isCloseSymbol) { + // + lastOpenSymbol = char === '\'' || char === '"' || char === '`' ? '' : lastOpenSymbol; + let lastPop = openStack.pop(); + if (openStack.length === 0) { + lastClosedIndex = lastPop; + } + } else if (isToken) { + if ( + i > lastClosedIndex && + openStack.length === 0 + ) { + result.push(i); + } + } + } + + // + return result; +} +//#endregion + +// +//#region Validator Actions ... +/** + * check specified value is Valid URL Address or not ... + * + * @param {string} value specified string which required to check + * @returns {boolean} + */ +function isValidURL(value = "") { + // + if (!isValidArg(value)) { + return false; + } + + const pattern = new RegExp( + '^([a-zA-Z]+:\\/\\/)?' + // protocol + '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name + '((\\d{1,3}\\.){3}\\d{1,3}))' + // OR IP (v4) address + '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path + '(\\?[;&a-z\\d%_.~+=-]*)?' + // query string + '(\\#[-a-z\\d_]*)?$', // fragment locator + 'i' + ); + + // + const result = pattern.test(value); + return result; +} + +/** + * check specified value is Valid URL Address or not ... + * + * @param {string} value specified string which required to check + */ +function isValidEmail(value = "") { + // + if (!isValidArg(value)) { + return false; + } + + // + const pattern = /[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}/gim; + + // + const result = pattern.test(value); + return result; +} +//#endregion + +// +//#region Normallizers ... +/** + * normallize an string ... + * + * @param {string} value specified value ... + * @returns {string} + */ +function toNormalString(value = "") { + // + if (!XTypeTools.isString(value)) { + value = ""; + } + + // + const result = value + .trim() + .toLowerCase(); + + // + return result; +} +//#endregion + +// +//#region Beautifiers ... +/** + * converts an object to string based on json and beautify result ... + * + * @param {any} object + * @returns {string} + */ +function beautifyJSON(object = undefined) { + // + // TODO: Complete this ... + let result = ""; + + // + // validate object ... + if (object === undefined) { + return result; + } + + // + // Convert result ... + result = JSON.stringify( + object, + null, + 4 + ); + + // + return result; +} +//#endregion + +// +//#region Module Exports ... +module.exports = { + // + endsWidth, + surroundBy, + isValidArg, + isValidArgs, + toNormalArray, + hasChildArray, + toStringExpression, + + // + sliceContent, + clearContent, + clearSurround, + clearArraySurround, + clearObjectSurround, + + // + isSurrounded, + isIndexInside, + isInsideIndex, + isKeyValueType, + isSurroundedArray, + isSurroundedString, + isSurroundedObject, + + // + findNearest, + findAllIndexes, + findCloseIndex, + findNearestIndex, + findClosedContent, + findClosedStrings, + findClosedContents, + findAllIndexesOutOfCloseds, + + // + // Validator Actions ... + isValidURL, + isValidEmail, + + // + // Normallizers ... + toNormalString, + + // + beautifyJSON, +} +//#endregion \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/14030316/Experts/x-sample.ea.mq5 b/MQLTestWorkspace/BKPS/14030316/Experts/x-sample.ea.mq5 new file mode 100644 index 0000000..3b6ce7d --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Experts/x-sample.ea.mq5 @@ -0,0 +1,1941 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center XSAMPLE MQL5 Expert Advisor +// ------------------------------------------------- +// Name: XSAMPLE +// Description: an Exper Advisor which used RSI and MA +// to Analyse Market ... +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +//////////////////////////////////////////////////////x +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XSAMPLE" +#property strict + +// +#define ShortName "XSAMPLE" + +// +#include "../Libraries/x-saherelm.draw.lib.mq5" +#include "../Helpers/x-saherelm.xcc.helper.mq5" +#include "../Helpers/x-saherelm.xct.helper.mq5" +#include "../Classes/x-saherelm.xtrade.class.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" +#include "../Classes/x-saherelm.xalert.class.mq5" +#include "../Classes/x-saherelm.x121.xmcycle.class.mq5" +#include "../Classes/x-saherelm.x121.xmcycle.class.mq5" + +// +// Inputs ... + +// +input group "Market"; + +// +input group "Short"; +input ENUM_X_PERIOD_METHOD scMethod = X_PERIOD_AUTO; // Method +input ENUM_TIMEFRAMES scPeriod = NULL; // Period + +// +input group "Medium"; +input ENUM_X_PERIOD_METHOD mcMethod = X_PERIOD_AUTO; // Method +input ENUM_TIMEFRAMES mcPeriod = NULL; // Period + +// +input group "Long"; +input ENUM_X_PERIOD_METHOD lcMethod = X_PERIOD_AUTO; // Method +input ENUM_TIMEFRAMES lcPeriod = NULL; // Period + +// +input group "Hind"; +input ENUM_X_PERIOD_METHOD hcMethod = X_PERIOD_AUTO; // Method +input ENUM_TIMEFRAMES hcPeriod = NULL; // Period + +// +long xSampleEAMagicNumber = 78692110; // Magic Number +int xSampleEASlippage = 10; // Slippgae + +// +double xSampleEAVolume = 0.01; + +// +// Vars ... +string xSampleEASymbol; +ENUM_TIMEFRAMES xSampleEAPeriod; + +// +int maxBuys = 1; +int maxSells = 1; +int buyCount = 0; +int sellCount = 0; + +// +double _tp = 0; +double _sl = 0; +double _entry = 0; +ENUM_POSITION_TYPE _type = NULL; + +// +MqlTick xSampleEATick; + +// +XBarTracker xSamplEABarTracker; + +// +// Cycles ... + +// +double bullishBuffer[]; +double bearishBuffer[]; +double nBullishBuffer[]; +double nBearishBuffer[]; + +// +double lastVale = 0; +double lastPeak = 0; +double lastSupport = 0; +double lastResistance = 0; + +// +double xBullishScore = 0; +double xBearishScore = 0; + +// +double normalizeBullishScore = 0; +double normalizeBearishScore = 0; + +// +int xLongVerifications = 0; +int xShortVerifications = 0; +bool isScoreBalanced = false; + +// +int normalizationLength = 15; + +// +datetime lastTradeOn = NULL; + +// +// Indicators ... +XCCInputs ccInputs; +XCTInputs ctInputs; + +// +XZGInputs zgInputs; +XPVInputs pvInputs; +XHKInputs hkInputs; +XMCInputs mcInputs; +XTDInputs tdInputs; +XMRBInputs mrbInputs; +XICHInputs ichInputs; +XCHEInputs cheInputs; +XSTRInputs strInputs; +XDONInputs donInputs; +XOSCInputs oscInputs; + +// +X121MCycleInputs cMarketInputs; // Curent Market Inputs +X121MCycleInputs sMarketInputs; // Short Market Inputs +X121MCycleInputs mMarketInputs; // Medium Market Inputs +X121MCycleInputs lMarketInputs; // Long Market Inputs +X121MCycleInputs hMarketInputs; // Hind Market Inputs + +// +XSCX121Market *cMarket; +XSCX121Market *sMarket; +XSCX121Market *mMarket; +XSCX121Market *lMarket; +XSCX121Market *hMarket; + +// +X121MCycleConditions cConditions; +X121MCycleConditions sConditions; +X121MCycleConditions mConditions; +X121MCycleConditions lConditions; +X121MCycleConditions hConditions; + +// +XSCTrade *mTrader; +XSCAlert *mAlert; + +// +XPivotTracker mPivotTracker; +XSignal mSignals[]; + +// +// Event Handlers ... + +// +// Initialization ... +int OnInit() +{ + // + if (xSampleEASymbol == NULL || StringLen(xSampleEASymbol) <= 0) + { + xSampleEASymbol = _Symbol; + } + + // + if (xSampleEAPeriod == NULL) + { + xSampleEAPeriod = _Period; + } + + // + // Validate Inputs ... + if (!XSampleEAValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + if (!InitialTrader()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initial Cycles ... + if (!InitCycles()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + drawPrefix = ShortName; + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // De Initialize XSampleEA Providers ... + + // + delete mAlert; + delete mTrader; + + // + delete cMarket; + delete sMarket; + delete mMarket; + delete lMarket; + delete hMarket; +} + +// +// On Tick Handler ... +void OnTick() +{ + // + if (!xSamplEABarTracker.IsNewBar()) + { + return; + } + + // + // Reading Tick ... + if (!GetTick( + xSampleEASymbol, + xSampleEATick // + )) + { + return; + } + + // + Analyze(); + + // + Manage(); +} + +// +// Custom Functions ... + +// +// Validate Variables nd Inputs ... +bool XSampleEAValidateInputs() +{ + // + bool result = false; + + // + result = + // + xSampleEASlippage > 0 && + xSampleEAMagicNumber > 0 && + IsValid(scMethod, scPeriod) && + IsValid(mcMethod, mcPeriod) && + IsValid(lcMethod, lcPeriod) && + IsValid(hcMethod, hcPeriod) + // + ; + + // + return result; +} + +// +// Tools ... + +// +// Do Market Analyziation ... +void Analyze() +{ + // + GenerateMarketConditions(); + + // + xBullishScore = 0; + xBearishScore = 0; + CalculateScores( + xBullishScore, + xBearishScore // + ); + + // + normalizeBullishScore = 0; + normalizeBearishScore = 0; + CalculateNormalizedScores( + normalizeBullishScore, + normalizeBearishScore // + ); + + // + xLongVerifications = 0; + xShortVerifications = 0; + CalculateVerifications( + xLongVerifications, + xShortVerifications // + ); + + // + // Detecting Pivots ... + HandlePivotDetection(); + + // + // Check Conditions on Pivots ... + HandleCheckConditions(); + + // + // Execute Signals ... + HandleSignalExecution(); + + // + // SUMMARY ... + + // + string strSuumarry = + "[XTEA]" + "\n" + + "---------------------" + "\n" + + ToString(cMarketInputs.cycle.cycle) + ": " + ToString(cMarket.GetPeriod()) + "\n" + + ToString(sMarketInputs.cycle.cycle) + ": " + ToString(sMarket.GetPeriod()) + "\n" + + ToString(mMarketInputs.cycle.cycle) + ": " + ToString(mMarket.GetPeriod()) + "\n" + + ToString(lMarketInputs.cycle.cycle) + ": " + ToString(lMarket.GetPeriod()) + "\n" + + ToString(hMarketInputs.cycle.cycle) + ": " + ToString(hMarket.GetPeriod()) + "\n" + + "---------------------" + "\n" + + "Scores:" + "\n" + + "---------------------" + "\n" + + "Bullish: " + ToString(xBullishScore) + ", " + ToString(normalizeBullishScore) + ", " + ToString(xLongVerifications) + "\n" + + "Bearish: " + ToString(xBearishScore) + ", " + ToString(normalizeBearishScore) + ", " + ToString(xShortVerifications) + "\n" + + ""; + + // + Comment(strSuumarry); + + // +} + +// +void Manage() +{ + // + XPosition positions[]; + int positionsCount = mTrader.GetPositions( + positions // + ); + if (!IsValidSize(positionsCount)) + { + return; + } + + // + double profit = mTrader.Profit(); + if (profit > 60) + { + // + string comment = "EQM Close ..."; + + // + int closed = mTrader.Close( + positions, + comment // + ); + if (closed > 0) + { + // + string message = "EQM Close (" + ToString(closed) + ") Position in: " + ToString(profit); + + // + mAlert.Alert(message); + + // + int pivotsCount = mPivotTracker.Count(); + if (pivotsCount > 0) + { + // + for (int i = 0; i < pivotsCount; i++) + { + // + double iPivot = mPivotTracker.Get(i); + + // + RemovePivotDraw(iPivot); + + // + lastPeak = 0; + lastVale = 0; + lastSupport = 0; + lastResistance = 0; + } + + // + mPivotTracker.Clean(); + } + } + } +} + +// +// Inbitial Classes ... +bool InitialTrader() +{ + // + bool result = true; + + // + mAlert = new XSCAlert(); + mAlert.SetLogAlerts(true); + mAlert.SetPrefix(ShortName); + mAlert.SetEnableAlerts(true); + mAlert.SetPushAlerts(false); + mAlert.SetMailAlerts(false); + mAlert.SetTerminalAlerts(false); + + // + mTrader = new XSCTrade( + xSampleEASlippage, + xSampleEAMagicNumber, + 0, + 0, + 0, + 0 // + ); + + // + return result; +} + +// +// Initial Market Conditions ... +bool InitCycles() +{ + // + bool result = false; + + // + // Define an Input Object and Configure it ... + // then use same Input for Separate Markets ... + + // + string symbol = _Symbol; + ENUM_TIMEFRAMES period = _Period; + + // + // Set Inputs to Default ... + ccInputs.Default(); + ctInputs.Default(); + zgInputs.Default(); + pvInputs.Default(); + hkInputs.Default(); + mcInputs.Default(); + tdInputs.Default(); + mrbInputs.Default(); + ichInputs.Default(); + cheInputs.Default(); + strInputs.Default(); + donInputs.Default(); + oscInputs.Default(); + + // + cMarketInputs.Default(); + sMarketInputs.Default(); + mMarketInputs.Default(); + lMarketInputs.Default(); + hMarketInputs.Default(); + + // + // XHK ... + hkInputs.drawHikenAshi = false; + hkInputs.drawSmoothedHikenAshi = false; + + // + // XMRB ... + mrbInputs.showFastMa = false; + mrbInputs.showSlowMa = false; + mrbInputs.showRibbon = false; + + // + // XMC ... + mcInputs.showFastMa = false; + mcInputs.showSlowMa = false; + mcInputs.showVerifierMa = false; + + // + // XICH ... + ichInputs.showKumo = false; + ichInputs.showKijunSen = false; + ichInputs.showTenkanSen = false; + ichInputs.showChikouSpan = false; + ichInputs.showSenkouSpanA = false; + ichInputs.showSenkouSpanB = false; + ichInputs.showKijunSenPlus = false; + ichInputs.showKijunSenNegative = false; + + // + // XCHE ... + cheInputs.showLongExit1Line = false; + cheInputs.showShortExit1Line = false; + cheInputs.showLongExit2Line = false; + cheInputs.showShortExit2Line = false; + + // + // XPV ... + pvInputs.showPeaksAndVales = true; + pvInputs.showLevels = false; + pvInputs.showConsolidations = false; + pvInputs.showFibo1Levels = false; + pvInputs.showFibo2Levels = false; + pvInputs.showFibo3Levels = false; + pvInputs.showFibo4Levels = false; + pvInputs.showFibo5Levels = false; + + // + // XZG ... + zgInputs.showZigZag = false; + zgInputs.showPeaksAndVales = false; + + // + // XDON ... + donInputs.showOpen = false; + donInputs.showHigh = false; + donInputs.showClose = false; + donInputs.showLow = false; + + // + // XSTR ... + strInputs.showTrends = false; + strInputs.fillTrends = false; + + // + // Current Cycle ... + + // + ConfigureCurrentCycles(); + + // + cMarketInputs.cycle.symbol = symbol; + cMarketInputs.cycle.period = period; + + // + cMarketInputs.pvInputs = pvInputs; + cMarketInputs.zgInputs = zgInputs; + cMarketInputs.tdInputs = tdInputs; + cMarketInputs.mcInputs = mcInputs; + cMarketInputs.hkInputs = hkInputs; + cMarketInputs.mrbInputs = mrbInputs; + cMarketInputs.strInputs = strInputs; + cMarketInputs.oscInputs = oscInputs; + cMarketInputs.cheInputs = cheInputs; + cMarketInputs.ichInputs = ichInputs; + cMarketInputs.donInputs = donInputs; + + // + result = cMarketInputs.Init( + symbol, + period, + X_MARKET_CYCLE_SHORT, + period, + X_PERIOD_MANUALLY, + "HOST", + false // + ); + if (!result) + { + return result; + } + + // + cMarket = new XSCX121Market(); + result = cMarket.Init(cMarketInputs); + if (!result) + { + return result; + } + + // + // Short Cycle ... + + // + ConfigureShortCycles(); + + // + sMarketInputs.cycle.symbol = symbol; + sMarketInputs.cycle.period = period; + + // + sMarketInputs.pvInputs = pvInputs; + sMarketInputs.zgInputs = zgInputs; + sMarketInputs.tdInputs = tdInputs; + sMarketInputs.mcInputs = mcInputs; + sMarketInputs.hkInputs = hkInputs; + sMarketInputs.mrbInputs = mrbInputs; + sMarketInputs.strInputs = strInputs; + sMarketInputs.oscInputs = oscInputs; + sMarketInputs.cheInputs = cheInputs; + sMarketInputs.ichInputs = ichInputs; + sMarketInputs.donInputs = donInputs; + + // + result = sMarketInputs.Init( + symbol, + period, + X_MARKET_CYCLE_SHORT, + scPeriod, + scMethod, + NULL, + false // + ); + if (!result) + { + return result; + } + + // + sMarket = new XSCX121Market(); + result = sMarket.Init(sMarketInputs); + if (!result) + { + return result; + } + + // + // Medium Cycle ... + + // + ConfigureMediumCycles(); + + // + mMarketInputs.cycle.symbol = symbol; + mMarketInputs.cycle.period = period; + + // + mMarketInputs.pvInputs = pvInputs; + mMarketInputs.zgInputs = zgInputs; + mMarketInputs.tdInputs = tdInputs; + mMarketInputs.mcInputs = mcInputs; + mMarketInputs.hkInputs = hkInputs; + mMarketInputs.mrbInputs = mrbInputs; + mMarketInputs.strInputs = strInputs; + mMarketInputs.oscInputs = oscInputs; + mMarketInputs.cheInputs = cheInputs; + mMarketInputs.ichInputs = ichInputs; + mMarketInputs.donInputs = donInputs; + + // + result = mMarketInputs.Init( + symbol, + period, + X_MARKET_CYCLE_MEDIUM, + mcPeriod, + mcMethod, + NULL, + false // + ); + if (!result) + { + return result; + } + + // + mMarket = new XSCX121Market(); + result = mMarket.Init(mMarketInputs); + if (!result) + { + return result; + } + + // + // Long Cycle ... + + // + ConfigureLongCycles(); + + // + lMarketInputs.cycle.symbol = symbol; + lMarketInputs.cycle.period = period; + + // + lMarketInputs.pvInputs = pvInputs; + lMarketInputs.zgInputs = zgInputs; + lMarketInputs.tdInputs = tdInputs; + lMarketInputs.mcInputs = mcInputs; + lMarketInputs.hkInputs = hkInputs; + lMarketInputs.mrbInputs = mrbInputs; + lMarketInputs.strInputs = strInputs; + lMarketInputs.oscInputs = oscInputs; + lMarketInputs.cheInputs = cheInputs; + lMarketInputs.ichInputs = ichInputs; + lMarketInputs.donInputs = donInputs; + + // + result = lMarketInputs.Init( + symbol, + period, + X_MARKET_CYCLE_LONG, + lcPeriod, + lcMethod, + NULL, + false // + ); + if (!result) + { + return result; + } + + // + lMarket = new XSCX121Market(); + result = lMarket.Init(lMarketInputs); + if (!result) + { + return result; + } + + // + // Hind Cycle ... + + // + ConfigureHindCycles(); + + // + hMarketInputs.cycle.symbol = symbol; + hMarketInputs.cycle.period = period; + + // + hMarketInputs.pvInputs = pvInputs; + hMarketInputs.zgInputs = zgInputs; + hMarketInputs.tdInputs = tdInputs; + hMarketInputs.mcInputs = mcInputs; + hMarketInputs.hkInputs = hkInputs; + hMarketInputs.mrbInputs = mrbInputs; + hMarketInputs.strInputs = strInputs; + hMarketInputs.oscInputs = oscInputs; + hMarketInputs.cheInputs = cheInputs; + hMarketInputs.ichInputs = ichInputs; + hMarketInputs.donInputs = donInputs; + + // + result = hMarketInputs.Init( + symbol, + period, + X_MARKET_CYCLE_HIND, + hcPeriod, + hcMethod, + NULL, + false // + ); + if (!result) + { + return result; + } + + // + hMarket = new XSCX121Market(); + result = hMarket.Init(hMarketInputs); + if (!result) + { + return result; + } + + // + return result; +} + +// +// Generate and Update Market Conditions ... +void GenerateMarketConditions() +{ + // + cConditions.Clear(); + cMarket.GetMarketConditions(cConditions); + + // + sConditions.Clear(); + sMarket.GetMarketConditions(sConditions); + + // + mConditions.Clear(); + mMarket.GetMarketConditions(mConditions); + + // + lConditions.Clear(); + lMarket.GetMarketConditions(lConditions); + + // + hConditions.Clear(); + hMarket.GetMarketConditions(hConditions); +} + +// +// Calculate Markets Score Summary ... +void CalculateScores( + double &mBullishScore, + double &mBearishScore // +) +{ + // + // Current Market ... + + // + double cBullScore = 0; + double cBearScore = 0; + double cScoreMultiplier = 1; + + // + cConditions.GenerateScore( + cBullScore, + cBearScore, + cScoreMultiplier // + ); + + // + // Short Market ... + + // + double sBullScore = 0; + double sBearScore = 0; + double sScoreMultiplier = 1.25; + + // + sConditions.GenerateScore( + sBullScore, + sBearScore, + sScoreMultiplier // + ); + + // + // Medium Market ... + + // + double mBullScore = 0; + double mBearScore = 0; + double mScoreMultiplier = 1.5; + + // + mConditions.GenerateScore( + mBullScore, + mBearScore, + mScoreMultiplier // + ); + + // + // Long Market ... + + // + double lBullScore = 0; + double lBearScore = 0; + double lScoreMultiplier = 2; + + // + lConditions.GenerateScore( + lBullScore, + lBearScore, + lScoreMultiplier // + ); + + // + // Hind Market ... + + // + double hBullScore = 0; + double hBearScore = 0; + double hScoreMultiplier = 2.5; + + // + hConditions.GenerateScore( + hBullScore, + hBearScore, + hScoreMultiplier // + ); + + // + mBullishScore = cBullScore + + sBullScore + + mBullScore + + lBullScore + + hBullScore; + + // + mBearishScore = cBearScore + + sBearScore + + mBearScore + + lBearScore + + hBearScore; + + // + Add( + mBullishScore, + bullishBuffer + // + ); + + // + Add( + mBearishScore, + bearishBuffer + // + ); +} + +// +// Calculate Market Normalized Scores ... +void CalculateNormalizedScores( + double &mBullishScore, + double &mBearishScore // +) +{ + // + CalculateNormalization( + mBullishScore, + mBearishScore + // + ); + + Add( + mBullishScore, + nBullishBuffer // + ); + + Add( + mBearishScore, + nBearishBuffer // + ); +} + +// +// Calculate Normalization Value ... +void CalculateNormalization( + double &normalBullish, + double &normalBearish // +) +{ + // + normalBullish = GetNormalizedValueMethod2( + bullishBuffer, + ArraySize(bullishBuffer), + 1, + -1, + 0 // + ); + + // + normalBearish = GetNormalizedValueMethod2( + bearishBuffer, + ArraySize(bearishBuffer), + 1, + -1, + 0 // + ); +} + +// +// Calculate Market Verifications ... +void CalculateVerifications( + int &longVerifications, + int &shortVerifications // +) +{ + // + // Generate Long ans Short Verifiers ... + + // + // XSTR ... + + // + bool isTrendBullish = + // + hConditions.isTrendBullish && + lConditions.isTrendBullish && + mConditions.isTrendBullish && + sConditions.isTrendBullish && + cConditions.isTrendBullish + // + ; + + // + if (isTrendBullish) + { + longVerifications++; + } + + // + bool isTrendBearish = + // + hConditions.isTrendBearish && + lConditions.isTrendBearish && + mConditions.isTrendBearish && + sConditions.isTrendBearish && + cConditions.isTrendBearish + // + ; + + // + if (isTrendBearish) + { + shortVerifications++; + } + + // + // XTD ... + + // + bool isTDBullish = + // + hConditions.isTDBullish && + lConditions.isTDBullish && + mConditions.isTDBullish && + sConditions.isTDBullish && + cConditions.isTDBullish + // + ; + + // + if (isTDBullish) + { + longVerifications++; + } + + // + bool isTDBearish = + // + hConditions.isTDBearish && + lConditions.isTDBearish && + mConditions.isTDBearish && + sConditions.isTDBearish && + cConditions.isTDBearish + // + ; + + // + if (isTDBearish) + { + shortVerifications++; + } + + // + // XCHE ... + + // + bool isCHEBullish = + // + hConditions.isCHEBullish && + lConditions.isCHEBullish && + mConditions.isCHEBullish && + sConditions.isCHEBullish && + cConditions.isCHEBullish + // + ; + + // + if (isCHEBullish) + { + longVerifications++; + } + + // + bool isCHEBearish = + // + hConditions.isCHEBearish && + lConditions.isCHEBearish && + mConditions.isCHEBearish && + sConditions.isCHEBearish && + cConditions.isCHEBearish + // + ; + + // + if (isCHEBearish) + { + shortVerifications++; + } + + // + // XHK ... + + // + bool isHKBullish = + // + (hConditions.isHKBullish && + lConditions.isHKBullish && + mConditions.isHKBullish && + sConditions.isHKBullish && + cConditions.isHKBullish) + // + || + // + (hConditions.isSMHKBullish && + lConditions.isSMHKBullish && + mConditions.isSMHKBullish && + sConditions.isSMHKBullish && + cConditions.isSMHKBullish) + // + ; + + // + if (isHKBullish) + { + longVerifications++; + } + + // + bool isHKBearish = + // + (hConditions.isHKBearish && + lConditions.isHKBearish && + mConditions.isHKBearish && + sConditions.isHKBearish && + cConditions.isHKBearish) + // + || + // + (hConditions.isSMHKBearish && + lConditions.isSMHKBearish && + mConditions.isSMHKBearish && + sConditions.isSMHKBearish && + cConditions.isSMHKBearish) + // + ; + + // + if (isHKBearish) + { + shortVerifications++; + } + + // + // XMC ... + + // + bool isMCBullish = + // + (hConditions.isMCFastOverSlow && + lConditions.isMCFastOverSlow && + mConditions.isMCFastOverSlow && + sConditions.isMCFastOverSlow && + cConditions.isMCFastOverSlow) + // + || + // + (hConditions.isMCFastOverVerifier && + lConditions.isMCFastOverVerifier && + mConditions.isMCFastOverVerifier && + sConditions.isMCFastOverVerifier && + cConditions.isMCFastOverVerifier) + // + ; + + // + if (isMCBullish) + { + longVerifications++; + } + + // + bool isMCBearish = + // + (hConditions.isMCFastUnderSlow && + lConditions.isMCFastUnderSlow && + mConditions.isMCFastUnderSlow && + sConditions.isMCFastUnderSlow && + cConditions.isMCFastUnderSlow) + // + || + // + (hConditions.isMCFastUnderVerifier && + lConditions.isMCFastUnderVerifier && + mConditions.isMCFastUnderVerifier && + sConditions.isMCFastUnderVerifier && + cConditions.isMCFastUnderVerifier) + // + ; + + // + if (isMCBearish) + { + shortVerifications++; + } + + // + // XMRB ... + + // + bool isMRBBullish = + // + (hConditions.isMRBFastOverSlow && + lConditions.isMRBFastOverSlow && + mConditions.isMRBFastOverSlow && + sConditions.isMRBFastOverSlow && + cConditions.isMRBFastOverSlow) + // + || + // + (hConditions.isMRBFastOverVerifier && + lConditions.isMRBFastOverVerifier && + mConditions.isMRBFastOverVerifier && + sConditions.isMRBFastOverVerifier && + cConditions.isMRBFastOverVerifier) + // + || + // + (hConditions.isMRBSlowOverVerifier && + lConditions.isMRBSlowOverVerifier && + mConditions.isMRBSlowOverVerifier && + sConditions.isMRBSlowOverVerifier && + cConditions.isMRBSlowOverVerifier) + // + ; + + // + if (isMRBBullish) + { + longVerifications++; + } + + // + bool isMRBBearish = + // + (hConditions.isMRBFastUnderSlow && + lConditions.isMRBFastUnderSlow && + mConditions.isMRBFastUnderSlow && + sConditions.isMRBFastUnderSlow && + cConditions.isMRBFastUnderSlow) + // + || + // + (hConditions.isMRBFastUnderVerifier && + lConditions.isMRBFastUnderVerifier && + mConditions.isMRBFastUnderVerifier && + sConditions.isMRBFastUnderVerifier && + cConditions.isMRBFastUnderVerifier) + // + || + // + (hConditions.isMRBSlowUnderVerifier && + lConditions.isMRBSlowUnderVerifier && + mConditions.isMRBSlowUnderVerifier && + sConditions.isMRBSlowUnderVerifier && + cConditions.isMRBSlowUnderVerifier) + // + ; + + // + if (isMRBBearish) + { + shortVerifications++; + } +} + +// +// Detect Probably Pivots ... +void HandlePivotDetection() +{ + // + // Detect Pivots Based On Score Pressures ... + bool hasLastSupportAndResistance = lastSupport > 0 && lastResistance > 0; + isScoreBalanced = MathAbs(xBullishScore - xBearishScore) <= 10; + if (isScoreBalanced && !hasLastSupportAndResistance) + { + // + XOHCL xBar = cConditions.bars[0]; + + // + double high = xBar.FindHighest( + 3, + MODE_HIGH // + ); + + // + double low = xBar.FindLowest( + 3, + MODE_LOW // + ); + + // + lastSupport = low; + lastResistance = high; + + // + mPivotTracker.Add(lastSupport); + mPivotTracker.Add(lastResistance); + } + + // + // Detect Pivots Based on Peaks and Vales ... + + // // + // // Vale ... + // bool hasLastValePivot = false; // lastVale > 0; + // bool hasValePivotCMarket = + // // + // !hasLastValePivot && + // // + // ( + // // + // (cConditions.zigzagPVs[0] == cConditions.pvVales[0] && + // cConditions.zigzagPVs[1] == cConditions.pvVales[1] && + // cConditions.zigzagPVs[2] == cConditions.pvVales[2] && + // cConditions.zigzagPVs[3] == cConditions.pvVales[3]) + // // + // || + // // + // (cConditions.pvVales[0] == cConditions.pvVales[1] && + // cConditions.pvVales[1] == cConditions.pvVales[2] && + // cConditions.pvVales[2] == cConditions.pvVales[3] && + // cConditions.pvVales[3] == cConditions.pvVales[4] && + // cConditions.pvVales[4] == cConditions.pvVales[5]) + // // + // ) + // // + // ; + // if (hasValePivotCMarket) + // { + // // + // lastVale = cConditions.pvVales[0]; + // mPivotTracker.Add(lastVale); + // } + + // // + // // Peak ... + // bool hasLastPeakPivot = false; // lastPeak > 0; + // bool hasPeakPivotCMarket = + // // + // !hasLastPeakPivot && + // // + // ( + // // + // (cConditions.zigzagPVs[0] == cConditions.pvPeaks[0] && + // cConditions.zigzagPVs[1] == cConditions.pvPeaks[1] && + // cConditions.zigzagPVs[2] == cConditions.pvPeaks[2] && + // cConditions.zigzagPVs[3] == cConditions.pvPeaks[3]) + // // + // || + // // + // (cConditions.pvPeaks[0] == cConditions.pvPeaks[1] && + // cConditions.pvPeaks[1] == cConditions.pvPeaks[2] && + // cConditions.pvPeaks[2] == cConditions.pvPeaks[3] && + // cConditions.pvPeaks[3] == cConditions.pvPeaks[4] && + // cConditions.pvPeaks[4] == cConditions.pvPeaks[5]) + // // + // ) + // // + // ; + // if (hasPeakPivotCMarket) + // { + // // + // lastPeak = cConditions.pvPeaks[0]; + // mPivotTracker.Add(lastPeak); + // } + + // + // Handle Draw Pivots ... + HandleDrawPivots(); +} + +// +// Check Conditions arround Pivots +// and Generate Signal based on them ... +// then Execute probabley Signals ... +void HandleCheckConditions() +{ + // + // Here we Can Execute Signals based on Pivots ... + int pivotsCount = mPivotTracker.Count(); + if (!IsValidSize(pivotsCount)) + { + return; + } + + // + // Loop Through Pivots and Check Conditions For Trading ... + for (int i = 0; i < pivotsCount; i++) + { + // + double iPivot = mPivotTracker.Get(i); + + // + HandleGeneratePivotSignal(iPivot); + } +} + +// +// Handle Trade On Pivot ... +void HandleGeneratePivotSignal( + double pivot // +) +{ + // + if (pivot <= 0) + { + return; + } + + // + XOHCL zBar = cConditions.bars[0]; + XOHCL cBar = cConditions.bars[1]; + XOHCL pBar = cConditions.bars[2]; + + // + // Current Bar HIghest and Lowest ... + // double cHigh = cBar.FindHighest( + // 2, + // MODE_HIGH // + // ); + // double cLow = cBar.FindLowest( + // 2, + // MODE_LOW // + // ); + + // + bool isSupportRejected = + // + // (cLow > pivot && + // cHigh > pivot) + // // + // && + // + cBar.HasStrongBody() + // + && + // + cBar.IsSupportRejected(pivot) + // + ; + + // + bool isSupportBreaked = + // + // (cHigh < pivot && + // cLow < pivot) + // // + // && + // + cBar.HasStrongBody() + // + && + // + cBar.IsSupportBreaked(pivot) + // + ; + + // + bool isResistanceRejected = + // + // (cLow < pivot && + // cHigh < pivot) + // // + // && + // + cBar.HasStrongBody() + // + && + // + cBar.IsResistanceRejected(pivot) + // + ; + + // + bool isResistanceBreaked = + // + // (cHigh > pivot && + // cLow > pivot) + // // + // && + // + cBar.HasStrongBody() + // + && + // + cBar.IsResistanceBreaked(pivot) + // + ; + + // + // Check has Signal or not ... + bool hasLong = (isSupportRejected || isResistanceBreaked); + bool hasShort = (isSupportBreaked || isResistanceRejected); + + // + if (hasLong) + { + // + Print("Has Long ..."); + } + else if (hasShort) + { + // + Print("Has Short ..."); + } + + // + // Here we Have Calculate and Get Verifications based on Long or Short Conditions ... + + // + bool longPassed = + // + ( + // + (normalizeBullishScore < 0 && + normalizeBearishScore < 0) + // + ? !isScoreBalanced + : true + // + ) + // + && + // + xLongVerifications >= 2 + // + && + // + xBullishScore > (xBearishScore * 1.2) + // + ; + + bool shortPassed = + // + ( + // + (normalizeBullishScore < 0 && + normalizeBearishScore < 0) + // + ? !isScoreBalanced + : true + // + ) + // + && + // + xShortVerifications >= 3 + // + && + // + xBearishScore > (xBullishScore * 1.2) + // + ; + + // + // Apply Verifications to Conditions ... + + // + hasLong = + !hasLong + ? false + : longPassed; + + // + hasShort = + !hasShort + ? false + : shortPassed; + + // + bool hasSignal = hasLong || hasShort; + if (!hasSignal) + { + return; + } + + // + // Define Global Variables ... + double r2r = 1.5; + double tpPrice = 0; + double slPrice = 0; + + // + // Generate Signal ... + + // + ENUM_POSITION_TYPE mType = + hasLong + ? POSITION_TYPE_BUY + : POSITION_TYPE_SELL; + + // + double mEntry = GetEntry( + xSampleEASymbol, + mType // + ); + + // + // TODO: Fix SL ... + slPrice = + hasLong + ? lastSupport + : lastResistance; + + // + double mSL = 0; + double mTP = 0; + CalculateTPSL( + mSL, + mTP, + mType, + mEntry, + r2r, + slPrice // + ); + + // + XSignal signal; + bool isPrepared = signal.Prepare( + xSampleEASymbol, + "X92", + xSampleEAPeriod, + mType, + X_ORDER_MODE_MARKET, + mEntry, + 0.01, + mSL, + mTP // + ); + + // + if (isPrepared) + { + // + signal.comment = ToString(pivot); + + // + AddRef( + signal, + mSignals // + ); + } +} + +// +// Execute Signals ... +void HandleSignalExecution() +{ + // + int signalsCount = ArraySize(mSignals); + if (!IsValidSize(signalsCount)) + { + return; + } + + // + XSignal tmp[]; + Copy( + mSignals, + tmp // + ); + + // + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = tmp[i]; + double iPivot = (double)iSignal.comment; + iSignal.comment = NULL; + + // + if (!iSignal.IsValid()) + { + continue; + } + + // + // TODO: + // Validate Signal Execution based on lastTradeOn ... + + // + ENUM_X_SIGNAL_EXECUTION_RESULT state; + bool isExecuted = mTrader.ExecuteSignal( + iSignal, + state // + ); + if (isExecuted) + { + // + // Remove Signal from mSignals ... + + // + bool isRemoved = ArrayRemove( + mSignals, + i, + 1 // + ); + + // + if (isRemoved) + { + // + string message = "Signal Executed Successfully ..."; + + // + mAlert.Alert(message); + + // + long chartID = ChartID(); + + // + iSignal.Draw( + chartID // + ); + + // + // Reset Last Values ... + if (iPivot == lastSupport) + { + lastSupport = 0; + } + else if (iPivot == lastResistance) + { + lastResistance = 0; + } + else if (iPivot == lastPeak) + { + lastPeak = 0; + } + else if (iPivot == lastVale) + { + lastVale = 0; + } + + // + // Check Last Trade ON ... + lastTradeOn = + // + TimeCurrent() + // + ; + + // + // Remove Drawn Pivot ... + RemovePivotDraw(iPivot); + + // + // Add Signal Entry Point / TP and SL as Pivots ... + mPivotTracker.Add(iSignal.entry); + mPivotTracker.Add(iSignal.tp); + mPivotTracker.Add(iSignal.sl); + } + } + } +} + +// +void ApplyPreDefineConfigurations() +{ + // + bool isX786 = false; + bool isX121 = false; + + // + if (isX786) + { + } + + // + if (isX121) + { + } +} + +// +void HandleDrawPivots() +{ + // + // return; + bool hasChild = mPivotTracker.HasChild(); + if (!hasChild) + { + return; + } + + // + int pivotsCount = mPivotTracker.Count(); + + // + for (int i = 0; i < pivotsCount; i++) + { + // + XPivot iPivot = mPivotTracker.GetPivot(i); + if (!iPivot.IsValid()) + { + continue; + } + + // + DrawPivot(iPivot); + } +} + +// +void RemovePivotDraw(double pivot) +{ + // + if (pivot <= 0) + { + return; + } + + // + long chartID = ChartID(); + + // + string pPrefix = "P_" + + ToString(pivot); + + // + if (!IsDrawExists(pPrefix)) + { + return; + } + + // + RemoveDraw(pPrefix); +} + +// +void DrawPivot( + XPivot &pivot, + color clrSupport = clrLime, + color clrResistance = clrOrangeRed // +) +{ + // + if (!pivot.IsValid()) + { + return; + } + + // + long chartID = ChartID(); + datetime time1 = iTime( + xSampleEASymbol, + xSampleEAPeriod, + 2 // + ); + datetime time = iTime( + xSampleEASymbol, + xSampleEAPeriod, + 0 // + ); + + // + bool currentPrice = MathMax(xSampleEATick.ask, xSampleEATick.bid); + + // + bool isSupport = currentPrice > pivot.pivot; + + // + color crl = isSupport + ? clrSupport + : clrResistance; + + // + string pPrefix = "P_" + + ToString(pivot.pivot); + + // + // RemoveDraws(pPrefix); + + // + if (IsDrawExists(pPrefix)) + { + return; + } + + // + string name = + // + (isSupport + ? "SUP_" + : "RES_") + + // + pPrefix + // + ; + + // + DrawTrendLine( + chartID, + name, + 0, + time1, + pivot.pivot, + time, + pivot.pivot, + crl, + STYLE_SOLID, + 2, + false, + false, + true // + ); +} + +// +void ConfigureCurrentCycles() {} + +// +void ConfigureShortCycles() {} + +// +void ConfigureMediumCycles() {} + +// +void ConfigureLongCycles() {} + +// +void ConfigureHindCycles() {} + +// \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xama.helper.ex5 b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xama.helper.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..8f9b4af0e67aa620f85986d10c218f240e6db0b3 GIT binary patch literal 5700 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 ZNGD+in#bNnFJoXQw_m>YBMhSa`9Ju2%U%Eg literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xama.helper.mq5 b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xama.helper.mq5 new file mode 100644 index 0000000..227800b --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xama.helper.mq5 @@ -0,0 +1,317 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCXAMAHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.xhelper.class.mq5" + +// +// Definitions ... + +// +enum ENUM_XAMA_BUFFERS +{ + XAMA_MAIN_LINE = 0 +}; + +// +// Input Models ... +struct XAMAInputs +{ + // + // Props ... + // + // Market ... + int length; // Period + int fastEMA; // Fast EMA Period + int slowEMA; // Slow EMA Period + int maShift; // Shift + ENUM_APPLIED_PRICE appliedTo; // Applied To + // + // Presentation ... + bool showLine; // Show Line + + // + // Constructor(s) ... + XAMAInputs() + { + // + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + length = 0; + fastEMA = 0; + slowEMA = 0; + maShift = 0; + showLine = false; + appliedTo = PRICE_CLOSE; + } + + // + // Default ... + void Default() + { + // + length = 18; + fastEMA = 2; + slowEMA = 30; + maShift = 0; + showLine = true; + appliedTo = PRICE_CLOSE; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + length > 0 && + fastEMA > 0 && + slowEMA > 0 && + slowEMA > fastEMA + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(length, length); + + // + return result; + } +}; + +// +// Class ... +class XSCXAMAHelper : public XSCBaseHelper +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructors ... + XSCXAMAHelper() : XSCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XSCXAMAHelper() {} + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + XAMAInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + ArraySetAsSeries(mainBuffer, true); + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.xama", + // + // Inputs ... + // + // Market ... + "", + mInputs.length, // Period + mInputs.fastEMA, // Fast EMA Period + mInputs.slowEMA, // Slow EMA Period + mInputs.maShift, // Shift + mInputs.appliedTo, // Applied To + // + // Presentation ... + "", + mInputs.showLine // Show Line + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + XAMAInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + XAMAInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Buffers ... + + // + double GetMain( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(mainBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return mainBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyMain( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + mainBuffer, + buffer, + forceClean + // + ); + } + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Props ... + XAMAInputs mInputs; // Inputs ... + + // + // Buffers ... + double mainBuffer[]; + + // + // Tools ... + + // + // Calculate Values Until Now ... + void Calculate() + { + // + int totalBars = CountBars(); + + // + // Main Buffer ... + CopyBuffer( + mHandler, + XAMA_MAIN_LINE, + 0, + totalBars, + mainBuffer + // + ); + } +}; + +// +// Tools ... \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xcc.helper.ex5 b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xcc.helper.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..2ffee68ade2671ed807266cf5bb3d6f14a6208bf GIT binary patch literal 6562 zcmdT_Wl$VIvR*t$aQEQu?yd<0&0>K7i@R@dcL)wagS&+w!GpVJaa-ILhhY11_wN2( z)q8)hyLx*1>zS$gx~rxYfr3b`fEQdDWWYaV=U@JRBLLu78^?cz7m4670N@|?pM+gui|UZHo+p+BpPyOw2HREM8LN{r0Z45yB_V`-?cYqjx`>%TcQ@Q@e|K<()CvUF5_4)5+`k%YR3*h?OZJz&} z{C}WtwIg3?TD~Q~qHL@{?avj((i}H)3A}4y%hb>+WR%5M1LUVpJlX;^*6$ZIK+3~w{-VHj!zKiWUM|flN$mIQEM0eV4*y5dm zYN8r#yU-_apu1oICj`99ll))B*93Aq1i63Z6vm1PH~)@*qlx9!D=Z+z&Ged|{>=9k z_vo)5KAzAIdBzLPZO(q1o8cy;`AIngTL2^0cSRFd;? z7q%*_;y&V)xKVQg(5gj|j@4N@;C6IBSjpV6csPi_^n4WKj zyx`XBYr9{mrgK?h7U=d6Ux$RLlV_b<2RY8p`^2GF>gmfEVsV|9f>!Bc2hMl>{187g ztU@E+YXcP*B4amewrtszg_Zl%!Ushl{xD^=D~eH82yTtwz>G2No9s<*#);*TtYJ_F zR+S6+spp_&eQ(`*(p6+Q27a$vMl689gn4#7P{Nmu;yW1g#&cmO^h5$U#zS6BZ zYRC&)E;rXLR~8qmw4izaaqq?h3(6OkpV2HDS&nqekEUXt-NI9OkLO17fXO~g&j08n zU!NI(t{vG;XvuC~Nc(!z%Yyw+a`R8Ld{eSbod#1P*A=_pGhTUnXUw8Z#0Zx-6$EAO z4sy83m8^S#>x>aDL~j|l57&^#RT5o&cYO=0fjtAHKXT7SS}(X4g3~9dB%WP^3E;(m zB~~qj3Qn>dHx_yH>`36so`%k;Y4;yp%#whHsN{i82Tf7BE%CO;&8Z7Z4D~yqkf1bJ zY+|2{ihZvrWt~BzjslUj?241(=UC}S-0vgO5jRTMG5x0FlLi~}06h+131T5S)oy}T zZ8_R{YvQGD{VfZRafjBkx*bLo=90UnHfp~km8kqOXHwC_;P1_hid!d4!`RJ(HnN^w zIw73J4fw-ebPkHmDEksxd)03o7uqFfAJ((vzFx?OFZ{u#%Tv3U!p)G$GhB%+NBtP< zL%CEVpfaLT9tBz|R@=QNv~9F_;|rDb^PH2Kb-YVMA-E+eGif7?eDxKs^00yzw@(-F zD^_0R!y2ahdXZuDTqm2^-(N8SpvO0qD|~kn6D)c~vdrC%@k7&et7`;gl}%*A6QP2v z#%Ly{3c@E9ug%{(P8Q){IJ_r3Qcq+7s8m+@q!Vy)f;TB4GaAb?VduVBG_C6bti1kZ zXtGvK_13*XhnVB|ja=mKLDvc2xB>;at@|lNP}rkd?iaR`>RLBT@gR(GUb4T6Z77J^yxOhtIOL7cxon*+{$iJQTOqW@0v?9 z%qiuIz^`ON{jfCLV{c}s1+0O{Gs3$F5QLMshrf4@|ih!#| z{P#Z`@`M0oFO6B&)1>5hid3^M<}Rast`S{_a?LKe82RFd4DD9}-oH?VtXdDL-_vmq zNxgw-QjV%T%pRe)kA*0oQ$6cKhb~2JLY{D%Nlm0lUEt3wL~(nN(Ak6;a%#7z5*b5- z5-b&@=g-E%Yp02R!q$awzGVdp+57n8U)>jL+0l?PDZE4%F-h#p`b-#=oTmf@k*eHi zZ98L*u^nza>u114oEE_JoM9v>WpERusKopy)9$i~!asuoQA&n5@{D5o^vgW2Z88wa zR}Paug~JDZx7uk?_zGB?op#Up3pknncZiD9v{>`fpJNE300R3(<;Df_0sG``0 z=Ggm=o$|%uyJ)Mg|V4IE>)MMi|#eSnyPluUQ-j z&%MT}&}axyXN^H2?WJYc#_Pp_sICaAC7l}S z<6M9$>`dqGF@(x`B5^z`sd7`f^#E7V`H)WCxCvaN{3*CrNXrBJg}c#aTLWqR2r9t- zg4GCMrOQgZQAhXEH@BLvWfBT-OA^#^<~dv zl2FKkkqX*(^q4K-lc> zw7LBS&k**Vt1Rm2T6wD40Ie2t1cfPuHy4%kxi(vSWHagvA4hLJv* zn%wkiItwSN5y=U`F-c-_{@^O`9opfz`D4->B#Bz$#O3k1ihAoZhE?ewz#b;vV5e3FWqo#4SJ3cT` zzvankb!+kh<^^AtLj4_WkGh6YIq@;q4gg7Lqod#^(i`|ZYp9Fz`peS9D{8Uu&->5> zb!MQH*o2iJJnY%$)ubUyj*Y!>M!zP)oH?FfkBlC6(PfS_9R)~DU5+oV5_2&tJ z|9-#Pabk>{ED^L6_6QG&^M6fNB89 zK5SCipi3A>ka2h{c0va}Qao|9zfr0167XU9=B{wYrik|twA86w)%2tGT@z~3?|{81 zO?h9_ixfJ~H^QE=@vd)HcRD28<|XJ`_P@|?R=;y_S7q^CEQL8s12{f;9MNJ6 zlGytX{wM6mYI>PHIyePjy+BQ-)g#XjH#_n48FP%1$XE3Hl=sMfl~snCoyWeXNpbP8 zmp9=%N_tpSv2@Ud?C{My`$mnIz)mewRq9IO;E?)CdL^zI&0du07<}gZ&Mju&Ds6+Y zVcl>)M>RGd9tC)6FYZaxVM6;{xX{iRH1k{zj@JXv8;y5UNQL3*eMh6I1t_93d7+n` zeAbCkdk**9TcQ@WdH!slJ&3evI`Qu zwy6nL%{~xPmgvAXGUS3cKlM~g?!+@OEwaS6O?bVRP$g#p% zkk!;8lh+iY_~#*`(C!AX>}q1!^r`fdE-M6Mpi?FaH#j4_F> zD!^k-&l9Pc^trDR(m>LlCzxc0!I6=UsFO!T3dDlB$$+I`ngOYW;}hW0M`D!_Xf^Uy!fNL5T~tAod;OJ&Gk znp$O$GV-zZI+5Txf2nwC14nl=0n*)r41;#d9> z?<3Nw{SXX8!i3e2&=W9lZ{F$DtxKX|`sA%YFIQ|B4|$BeW%7z2j>N?LKn}LQ{`y?n zApN7y=5p%x0f*j5^|Na4y@NTnaibn)c83w+#1eI$`Qd^w^+v#2(CPT+5`Z%c0SEFq zqew@0n7TZ#StFFxD6Zo|=rc`S8~Lm;%exO>8o6HMJ=x|b$yAyUd}TDa-0sh0cOwVuR;e#5aUu=s&`(uQR}a7iRJ@+YWM?op}Dq3Jn&aaPBU@?)G9it?q} zRE3BS6gP$RQBk8?WW!LRk1ObD1x)v<&@%jiEj!(IO=`P#Ssv^<)GTTB2NHPFFbt~X z1C?p}iI0Z{>ySk#rD4jMU!Cd0KV~01p>uPUYXy+NgtOLpR6dGS2dckFf0Ip2 zW}8ypfz}aBFyHDua1+R$hB6@rRYevil@(wR9(a$LSEsTF+XQb6ep6#WkebsLwMlE2 z+C?^HRJPSE^a!7tyb@CP@`EH)4$(IF`6yJHMkdk5cjet!uA1&@< z8BN`xDir{!&S2j;UbQLmp_OS{v35MAXF$3 z`p{HxtCu7=q8;7-ZD1yy%IWRpUP|S4$zUcu-eZ-xtaG;fT5>TO17xTc}{Mfy|pSn6Ib=TL0h4E7cnV` z$O8)QJ7wVqf4D)QOV$g6v`flkwW9>jbilhTQ!fes+>;|rYoexnUrrG&@%GxQd9pvI z$;fkUu^+ZQBG2PJ%$cDKZ6K1Y}7v4R@2wOqVt22|BV%sLLBoDUBvjVhWAS2 zaruCb4u|p$O5O3mdoGW_qq9$)avr$zQ^9+KepvRt5*;+%bY#Z9|o8_Rg;=NcbLl$b?Qj(c8 zrKPbO^~~|3YI}i3M741yB=H84x9?b;ZR<}^%@QP&56wf)Us5{y*f5rqQEESa4x@0I z-4RD4p*y-W?GSnFC!^+h=iJ0wh&-FrPO;pzI}vMvx^g`%NF3t+aT!~TDD&JUi_5MJ z90Y4@RKhT%u-5UrY<=Rx&W~+QZt=*;plmd%mWJaD&fZ>5oG=(P?Q6E4mic|GXg z)zwcL*`Tzmc(;!XvvsvwI%c9^PF=~TpuapZkX(_4uy9c}p}nZ3(fJ3e>Q3mJ9O$~i zFwpfn?!VWtVeQA~N^_L*6UlGF0KY~SG2&=Bwr4zok7HMoXxFoG_`6`Lhk^#jZ!58( z*Ej|4#5z5C7x~Ms6-S&t)kyS}eau_|n$&)gB2l5m3riP@3?Xvo%=)Nw9DT%}){xCwVAg?#~WwiMrIVMG#Y>a*l`zs`di6Il(l@dLoI z=3v+A0!B6xTXVsxla*VD8k(l=$B&K;X*L>qfwOk%&6hSIGHdaOZMs|!T1H7x53|sE zL~CJI7Vie}w*fY1H)W?JBjE5a)T=-5kJFnz?F*Pp2c1bFyp+u0#T3b3Pm0pCc?J?y*0^hL22Zn;C%pADrOWttEc;QI9W zJm7id(nMQlFdbW!i?}XhVSpgpZFzd;&-FnXc|j(-RYK*|H3@3stj;!{a!Tc8o$mF5 zHFSZadhQl1%;dmMQsL3|Z88ye&Sr>?oRRxVzip!4~%b!54?cSv0U%a0naRA-H?c;7*X>5P~}dhu{{1yxhIJ ze^>S1-|McPp8k4fs=ofJMgc5@v12*CbNGM9$uEXIDqOeu~#uaeM&-vG^G(e$w>aMD?x z6pU^EaaRuD3UCAX0^R`}0CoU-fG2z5nSvf9rqqw)rP-p1AWN!CJfz5=t+#} zMZFvE%5Nq0U|kFb_h_v<&2f(tU#t4#MwFr_x3Z5+|S z6cYkVE%Zf}ei(9)70gwFnBwm=5?ix`|)9x8Zi8*2G&<`Fmk&=(cWpDPn~~W3JXhK`s@R( zqbcwn>Q5J>l$5prRt82KW$G3YHSfH*CHz+X4Bob0bZY|d3b%|E=`nON_I`T4?-ml= z5Eo1_q#D+uHCtms79SCyc)1rr*jvAT zlypp}%c*V_) zRmB-*&=EQFP0bsFuLAWi9CCrrA`9JI+|p8Riw#Rq>I{s6ZpHO zGiAL{D8zf?GnUcE*wL==<0%z&kbNGGf5%!LP!)wPv2Rj;&xM18_P7ibR~!=9Y(-kU z<5lsp4Jt`ZJg;i#3Nu-~+pkm*y2}8^LeP4ngJ2^{5Msu*gA^`Gl)uz6^BFmQCCo_jOD!QY#+E*+In@e)>WR zbo${gz+d*^`095Bx!E%cqu~nr7)0}rACE9C;p))OR{ShBXN`r-i`U;PgJR@dA2NpQ zWsoDB{KxfM1em?`F9s%LFgv@MZO#I~*R(_o2s-ev&vP#5m7+bRNYX(oAtW=Q^a3N2 zf%KY-cOR-l#n-e&Ic;g>o-=;M8G(`g5(kJ1Tu$l~+yKi(3Z=Ag77m;Ow2>OIK}(_E zPEoqqvfb)4)M3QMg7|Vz?eW|GURp)pUxvmp_)D6{c8`g$*OqdqP`EPUKU2pu;Wnmm zG*H%;jU8`cEg<3g6Bn9lCc6*`K_?ufGk%mZV3`mY<}TT8-k9lj{M9)fB94H&2G7b8 z=N0Ng?fn#Q0tiB<2q%gI6BsBf6!4{?w@TaPTlGk|gwjxKgnm#xme4wNy`-9Wk&or5 zk&&)Q!%oVZ0?-m7P?XhV`#e&}3Y-BreAC98fdINqw#S!#GE`&d@14ndZQR|>-HlG zB9Zn;^BX!;lheE9z}B0*P*uSL6wzA)lzLfmxl>*e${vc~TEqdPX1Q^Se&L?&>O>@P zGo_S3b!_veeda%a(8A`}wgvguvT|$o@k6au9S|1vQXOAPO^OwMYa{C_G}xpv9Qp>I z=V6q4Ql)5Zeg$csTz$U_Vp!oo!7~vk93fvpIbq|GnyFvFuis_oes;gE^dws|Y#2bCEja z{+*f`BS_JubHs6rqnkp%iHIxLT0{&?XiQIjjw-|-|KcgPd5kML>8p==A0@djH>}Xe zQw0z`mx+L>%&@RwRF})waaRrFSuDvxgLXt4^5t97mt&n)2lqzKpMyY%?QWwGM z)eobt?5XFNcdK-teXG=tctrB2*N0|9XHUL+*KK(){0UiLu)yRrk>8}rPOVi>Y7nsC zVY>Y+vrBpu?2N6sz!zP78sk1QNP3%S?YvcKV&)-ydPWUWJKTr8)R?V{VihIt=Rk(b zTEEJ9rq5e0wW%F6TN*RTp}-0Kmh)8;K~Zx^b{@w0%ghnN z{-=3_GY2;;7M;`%v{N#kBlJ2$@(wS`-Ho2(^RYd`eqOak=hW$%-1*DAgkNr$M@k5m zL?T*n2CP~~WRc!PRBaoPfT6`xd!Qk)`5A>f`MivDvI)~Qrx4dg6^s2Hjr=+lqT!gi z)=kx9r*_IkI`+Vb69WF?F_EJYl6`V|Qe_}4kl8!7@zr<4IiRS06*D%{PV)zrXwBN$ z;QO5L;l-2e^;`@QfnNGPfc>ADW-ok=RmsPx6*L{v+0j%i1xy8*ACqznXWNCkD-meP zF%pmX74nHAAzZRICGj^*ru7DCv$(u&iL4&++I66o_-rTEEMl#%pleMA&OCbxD!%K_ z)hmyJuvVmjb^3w8458A@5y^Me=cm~Mf{A^#?wm+Q<2${}$5P=iCEIEOHIK&V>Xx-) zqwWP{bQufo7osL}sGB@1nhYstc$nuMsqb5C;2X9~2N}Y}s+w{5R6|2>@uPe=Z$f%= zO^^xm_UT0j6A!Ve8D-nvkrW8bF;>6TJGtn8q5Jdpr%n!fLcv4iDc1}Jm%KWI!(thq zpZg;7S>=4qaDANnMoG-O0U#yn^jR6bogEDPl%!5iT#*gx!2gHjCe@ImJ3 zi&>az zbwbm+n*4s3ullkXWXnY6yLo}M^us&+H{8CVO-iZIN7F0TbfCiGv{(`0R7am88orbB z#^tB<<`9@QO16w4*Wv&g=D2ER_> zgiGHD)c3GYze2M7piR8yV1(f+d`ioVB=6*QEMirL4rY^?k5c1V2njo;tnVIq9-Zp^00Mg?3u;l50maM9gJ2a?%D^F@ z4n@9t_%;jGY6x02LM$XlT?^(u58FNKhZKDohQ`38h^<4Hx67`8jA|`1K8$fm5g4A| zaiR<4Lfa)fHSP3p(U{qIPC^P4sRY85ROxPDuU*svp@bh(eHR@LKhBsM9m25tRgdaX#e+v?9x^QRXp5SAL{L)hIzyEHD&$MQ<@`mry;RJg21 z#%$vPI#Cg1iD4a=U-1%(5_dv1(B|fq)KQY}3y2U~F=(w{A#9Ig?>-w4sXoxH$0ffW zaxu*;!xoEOp4LmSiBtbFAGqP6qcTE=;gTUqq9WkE6;hHZ{0`aRky0{EIhSW>l)4}D z+y_-pc`HKK4k~OTlcl5kw%SrmIfY8c7H2$+J}h`;qTfLGJ+NUHgu(8B`r_QcqmZ5H z`30qfe4#x?$x*m`sus?AISfxMk|H>y?XsAXI6C*xOj(<#prt5~HK%{s9R<|Cmfn@_ zqB$@2t9Z6DnKeTLWi?RSHy-$CrjSkZh>%?M3KHM!C5-4C-23G2lWkOB(wdOEOihKA-*UV?bVqTliUa`oRozHz73bll&7$Z%GI!C2MpXSs4KSL}x# zr63?mcBH^7iA|~MfgN&GgV+b~V9CR*KjKxrByV;$5%(LYDwYCL%CB>bBrIp-$Dw|u z`uw~U-ll}Xula0!a{W#u*DOC4g*?S~n+d&Dg&lxOj54VJA5#TNEO#W~CoaRKaw~Fc z;SfBB4-8ZTECqhy;Qp7)MY?INZ@18zWH(x#3`H#fq?VW|Zl6ZM7Ec)|QnH*8Z@0JyhlWfP$Qrnk;NL5VzN+!N z$B)cwU9*xbt;abJ%(uDCw<5@AP$*ZVtM~1rByYJ~pAeB(TzZ^A^cYZ|S#XbUKw|{-Lw^LMm4L7lgpZ}3!|i>Fb6hT zxy9%mI~ScP6L7fi4_hmJcg0YXCBW+A=7ZoOPOgk87_#G}+>@vIPNY1{3shZ`FwGZ3 z%6dp8qgOidHh(-jaX0?Do=OX3YMENmIzA-A_b^>h&8bq?(rg~S*Xed6*c?D*$*mgBD7G3SK*X4$%?6^#+NyfWitnL~z%%;`wom6Yz=qMD_SRbam6E8h!I}J;%h zP|Lk|#OMQufAu!Aendw%u@H8onD8+SJ`LywB)v-ict%Q`^v$Z)X%mc;nn1aaX`g)A zZT;$kRFM^a<=PL<{0`tMgS7n+m!4Sl2Fx{{ylw$DP7bG{8-%3P4V z)bL^~*lbh$Gc|4tf5#}k0EK?!sC#QDEoZ=Nod3C zv(If7)$yk0BNvJ7?zyEvIS`!y$1ANBl#T7{o5il3UCTKPW6;wcOI6bXZ z$cXG)i+W$)XwpOi+2*_9k$pB25WEDY9=+c_Ff9Er(;*pk>g4kh;8y}UmZwY#!9AI> zvJ&0Vr#Rx7X<4tRJhiW#L!SQdd5xXRzIR$-2!0=H%xz>I<^lh#W^IQG>^jsoSm zq`s({?5COZ%F2w(S5S(Mh9lU|>^^LiZ9&}k%5!T+wh>^2RZ}sKt>3Q7{k5&5mGHeL zr)Iuxh6R;G%N;0Oyxn4X7qP@v9mSMpyOIFjIv&&sm7fDSF!UlzXm#Er#cSJzacZ}f zRO76|WHyt5=$wM#=uS2ww=n^)SioIY;O^WB!L&wEIx+#nOiBFZpZmV4sUfqYJ4%jT z_S0@QD7R#%1{;>W32;k30L|Mh4n>BN$ay@1qEd}-Rj+<+;A1$!Eoj-Hm z7o=gWvp74`cExmm5O_2xt%pWb{S-(>!6;u7iK1}A`N-RmSDK-8O?j|V{c%))!0??6#9oPA3o4mnsleeZ;sZ+A&!SIyYmsqw4juV z;u8t8=aKPvI|57Xe5`udF5Th9cbWqkEO?$oxRiEe&HNFIW7Mw=%naH?0z_Z`=(m6cEt7bu!Y-2;APzIs z)sEQNv_y)ZLeAf<%lM32`{IvDCj(A-vFA(W`m#iX#gEyT8 0 && + loopback < length && + multiplier1 > 0 && + multiplier2 > multiplier1 + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(length, loopback); + + // + return result; + } +}; + +// +// Class ... +class XSCXCHEHelper : public XSCBaseHelper +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructors ... + XSCXCHEHelper() : XSCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XSCXCHEHelper() {} + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + XCHEInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + ArraySetAsSeries(longExit1Buffer, true); + ArraySetAsSeries(longExit2Buffer, true); + ArraySetAsSeries(shortExit1Buffer, true); + ArraySetAsSeries(shortExit2Buffer, true); + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.xche", + // + // Inputs ... + // + // Market ... + "", + mInputs.length, + mInputs.loopback, + mInputs.multiplier1, + mInputs.multiplier2, + // + // Calculations ... + "", + mInputs.upAppliedTo, + mInputs.downAppliedTo, + // + // Presentation ... + "", + mInputs.showLongExit1Line, // Show 1st Long Exit, + mInputs.showShortExit1Line, // Show 1st Short Exit, + mInputs.showLongExit2Line, // Show 2st Long Exit, + mInputs.showShortExit2Line // Show 2st Short Exit + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + XCHEInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + XCHEInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs); + } + + // + // Buffers ... + + // + double GetLongExit1( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + return longExit1Buffer[barIndex]; + } + + // + // Copy Required Long Exits 1 ... + int CopyLongExit1( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + longExit1Buffer, + buffer, + forceClean + // + ); + } + + // + double GetLongExit2( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + return longExit2Buffer[barIndex]; + } + + // + // Copy Required Long Exits 2 ... + int CopyLongExit2( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + longExit2Buffer, + buffer, + forceClean + // + ); + } + + // + double GetShortExit1( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + return shortExit1Buffer[barIndex]; + } + + // + // Copy Required Short Exits 1 ... + int CopyShortExit1( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + shortExit1Buffer, + buffer, + forceClean + // + ); + } + + // + double GetShortExit2( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + return shortExit2Buffer[barIndex]; + } + + // + // Copy Required Short Exits 2 ... + int CopyShortExit2( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + shortExit2Buffer, + buffer, + forceClean + // + ); + } + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Props ... + XCHEInputs mInputs; // Inputs ... + + // + // Buffers ... + // + double longExit1Buffer[]; + double longExit2Buffer[]; + double shortExit1Buffer[]; + double shortExit2Buffer[]; + + // + // Tools ... + + // + // Calculate Values Until Now ... + void Calculate() + { + // + int totalBars = CountBars(); + int calculatedBars = CountCalculatedBars(); + + // + // Long Exit 1 ... + CopyBuffer( + mHandler, + X_CHE_LONG_EXIT_1_LINE, + 0, + totalBars, + longExit1Buffer + // + ); + + // + // Long Exit 2 ... + CopyBuffer( + mHandler, + X_CHE_LONG_EXIT_2_LINE, + 0, + totalBars, + longExit2Buffer + // + ); + + // + // Short Exit 1 ... + CopyBuffer( + mHandler, + X_CHE_SHORT_EXIT_1_LINE, + 0, + totalBars, + shortExit1Buffer + // + ); + + // + // Short Exit 2 ... + CopyBuffer( + mHandler, + X_CHE_SHORT_EXIT_2_LINE, + 0, + totalBars, + shortExit2Buffer + // + ); + } +}; + +// +// Tools ... diff --git a/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xct.helper.ex5 b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xct.helper.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..164ee98c9f7881cd59e59b35facc07699c1d5f5e GIT binary patch literal 6130 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 literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xct.helper.mq5 b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xct.helper.mq5 new file mode 100644 index 0000000..a7e8769 --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xct.helper.mq5 @@ -0,0 +1,220 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCXCTHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.xhelper.class.mq5" + +// +// Definitions ... + +// +// Input Models ... +struct XCTInputs +{ + // + // Props ... + + // + color clr; // Text Color + ENUM_BASE_CORNER corner; // Text Position + + // + // Presentation ... + bool showCandleTime; // Show Candle Time + + // + // Constructor(s) ... + XCTInputs() + { + // + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + clr = CLR_NONE; + corner = CORNER_RIGHT_LOWER; + + // + // Presentation ... + showCandleTime = false; + } + + // + // Default ... + void Default() + { + // + clr = clrYellow; + corner = CORNER_RIGHT_LOWER; + + // + // Presentation ... + showCandleTime = false; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + true + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(0, 0); + + // + return result; + } +}; + +// +// Class ... +class XSCXCTHelper : public XSCBaseHelper +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructors ... + XSCXCTHelper() : XSCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XSCXCTHelper() {} + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + XCTInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.xct", + // + // Inputs ... + mInputs.clr, // Text Color + mInputs.corner, // Text Position + // + // Presentation ... + "", + mInputs.showCandleTime // Show Candle Time + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + XCTInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + XCTInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Props ... + XCTInputs mInputs; // Inputs ... +}; + +// +// Tools ... \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xdon.helper.ex5 b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xdon.helper.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..98842cf50267b822af384c4488925fe9063737c1 GIT binary patch literal 6374 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 XfMJ2n%__@$Pjo>+Ff6+*OsW3?fg}(L literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xdon.helper.mq5 b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xdon.helper.mq5 new file mode 100644 index 0000000..3e7355d --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xdon.helper.mq5 @@ -0,0 +1,1075 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCXDONHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.xhelper.class.mq5" + +// +// Definitions ... + +// +enum ENUM_XDON_BUFFERS +{ + // + // Open ... + XDON_UPPER_O_LINE = 0, + XDON_LOWER_O_LINE = 1, + // + // Close ... + XDON_UPPER_C_LINE = 2, + XDON_LOWER_C_LINE = 3, + // + // High ... + XDON_UPPER_H_LINE = 4, + XDON_LOWER_H_LINE = 5, + // + // Low ... + XDON_UPPER_L_LINE = 6, + XDON_LOWER_L_LINE = 7, +}; + +// +// Input Models ... +struct XDONInputs +{ + // + // Props ... + + // + // Market ... + int length; // Market Length + double offset; // Offset + + // + // Presentation ... + bool showOpen; // Show Open + bool showHigh; // Show High + bool showClose; // Show Close + bool showLow; // Show Low + + // + // Constructor(s) ... + XDONInputs() + { + // + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + // Market ... + length = 0; + offset = 0; + + // + // Presentation ... + showOpen = false; + showHigh = false; + showClose = false; + showLow = false; + } + + // + // Default ... + void Default() + { + // + // Market ... + length = 52; + offset = 0; + + // + // Presentation ... + showOpen = true; + showHigh = true; + showClose = true; + showLow = true; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + length >= 5 && + offset >= 0 + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(0, length); + + // + return result; + } +}; + +// +// Class ... +class XSCXDONHelper : public XSCBaseHelper +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructors ... + XSCXDONHelper() : XSCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XSCXDONHelper() {} + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + XDONInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + ArraySetAsSeries(upperOBuffer, true); + ArraySetAsSeries(lowerOBuffer, true); + ArraySetAsSeries(upperCBuffer, true); + ArraySetAsSeries(lowerCBuffer, true); + ArraySetAsSeries(upperHBuffer, true); + ArraySetAsSeries(lowerHBuffer, true); + ArraySetAsSeries(upperLBuffer, true); + ArraySetAsSeries(lowerLBuffer, true); + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.xdon", + // + // Inputs ... + // + // Market ... + "", + mInputs.length, // Market Length + mInputs.offset, // Offset + // + // Presentation ... + "", + mInputs.showOpen, // Show Open + mInputs.showHigh, // Show High + mInputs.showClose, // Show Close + mInputs.showLow // Show Low + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + XDONInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + XDONInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Buffers ... + + // + // Open ... + + // + // Upper ... + + // + double GetUpperO( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(upperOBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return upperOBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyUpperO( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + upperOBuffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameUpperO( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + upperOBuffer, + verifier, + barIndex // + ); + } + + // + // Lower ... + + // + double GetLowerO( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(lowerOBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return lowerOBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyLowerO( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + lowerOBuffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameLowerO( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + lowerOBuffer, + verifier, + barIndex // + ); + } + + // + // Close ... + + // + // Upper ... + + // + double GetUpperC( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(upperCBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return upperCBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyUpperC( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + upperCBuffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameUpperC( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + upperCBuffer, + verifier, + barIndex // + ); + } + + // + // Lower ... + + // + double GetLowerC( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(lowerCBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return lowerCBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyLowerC( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + lowerCBuffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameLowerC( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + lowerCBuffer, + verifier, + barIndex // + ); + } + + // + // High ... + + // + // Upper ... + + // + double GetUpperH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(upperHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return upperHBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyUpperH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + upperHBuffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameUpperH( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + upperHBuffer, + verifier, + barIndex // + ); + } + + // + // Lower ... + + // + double GetLowerH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(lowerHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return lowerHBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyLowerH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + lowerHBuffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameLowerH( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + lowerHBuffer, + verifier, + barIndex // + ); + } + + // + // Low ... + + // + // Upper ... + + // + double GetUpperL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(upperLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return upperLBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyUpperL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + upperLBuffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameUpperL( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + upperLBuffer, + verifier, + barIndex // + ); + } + + // + // Lower ... + + // + double GetLowerL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(lowerLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return lowerLBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyLowerL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + lowerLBuffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameLowerL( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + lowerLBuffer, + verifier, + barIndex // + ); + } + + // + void GetUppers( + double &result[], + int barIndex = 0 // + ) + { + // + Clean(result); + + // + double uo = GetUpperO(barIndex); + double uc = GetUpperC(barIndex); + double uh = GetUpperH(barIndex); + double ul = GetUpperL(barIndex); + + // + Add(uo, result); + Add(uc, result); + Add(uh, result); + Add(ul, result); + } + double GetMinUpper( + int barIndex = 0 // + ) + { + // + double values[]; + GetUppers(values); + + // + double result = GetMin(values); + + // + return result; + } + double GetMaxUpper( + int barIndex = 0 // + ) + { + // + double values[]; + GetUppers(values); + + // + double result = GetMax(values); + + // + return result; + } + + // + void GetLowers( + double &result[], + int barIndex = 0 // + ) + { + // + Clean(result); + + // + double lo = GetLowerO(barIndex); + double lc = GetLowerC(barIndex); + double lh = GetLowerH(barIndex); + double ll = GetLowerL(barIndex); + + // + Add(lo, result); + Add(lc, result); + Add(lh, result); + Add(ll, result); + } + double GetMinLower( + int barIndex = 0 // + ) + { + // + double values[]; + GetLowers(values); + + // + double result = GetMin(values); + + // + return result; + } + double GetMaxLower( + int barIndex = 0 // + ) + { + // + double values[]; + GetLowers(values); + + // + double result = GetMin(values); + + // + return result; + } + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Props ... + XDONInputs mInputs; // Inputs ... + + // + // Buffers ... + double upperOBuffer[]; + double lowerOBuffer[]; + double upperCBuffer[]; + double lowerCBuffer[]; + double upperHBuffer[]; + double lowerHBuffer[]; + double upperLBuffer[]; + double lowerLBuffer[]; + + // + // Tools ... + + // + // Calculate Values Until Now ... + void Calculate() + { + // + int totalBars = CountBars(); + + // + // Open ... + + // + // Upper Buffer ... + CopyBuffer( + mHandler, + XDON_UPPER_O_LINE, + 0, + totalBars, + upperOBuffer + // + ); + + // + // Lower Buffer ... + CopyBuffer( + mHandler, + XDON_LOWER_O_LINE, + 0, + totalBars, + lowerOBuffer + // + ); + + // + // Close ... + + // + // Upper Buffer ... + CopyBuffer( + mHandler, + XDON_UPPER_C_LINE, + 0, + totalBars, + upperCBuffer + // + ); + + // + // Lower Buffer ... + CopyBuffer( + mHandler, + XDON_LOWER_C_LINE, + 0, + totalBars, + lowerCBuffer + // + ); + + // + // High ... + + // + // Upper Buffer ... + CopyBuffer( + mHandler, + XDON_UPPER_H_LINE, + 0, + totalBars, + upperHBuffer + // + ); + + // + // Lower Buffer ... + CopyBuffer( + mHandler, + XDON_LOWER_H_LINE, + 0, + totalBars, + lowerHBuffer + // + ); + + // + // Low ... + + // + // Upper Buffer ... + CopyBuffer( + mHandler, + XDON_UPPER_L_LINE, + 0, + totalBars, + upperLBuffer + // + ); + + // + // Lower Buffer ... + CopyBuffer( + mHandler, + XDON_LOWER_L_LINE, + 0, + totalBars, + lowerLBuffer + // + ); + } +}; + +// +// Tools ... \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xhk.helper.ex5 b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xhk.helper.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..336cdab83925888e70933f992035c665214a53d0 GIT binary patch literal 6010 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 YgZo3f3WaIP;h*vRHrziQwN 2 + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(0, smoothingLength); + + // + return result; + } +}; + +// +// Class ... +class XSCXHKHelper : public XSCBaseHelper +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructors ... + XSCXHKHelper() : XSCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XSCXHKHelper() {} + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + XHKInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + ArraySetAsSeries(openBuffer, true); + ArraySetAsSeries(highBuffer, true); + ArraySetAsSeries(lowBuffer, true); + ArraySetAsSeries(closeBuffer, true); + ArraySetAsSeries(smOpenBuffer, true); + ArraySetAsSeries(smHighBuffer, true); + ArraySetAsSeries(smLowBuffer, true); + ArraySetAsSeries(smCloseBuffer, true); + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.xhk", + // + // Inputs ... + // + // Market ... + "", + mInputs.smoothingLength, // Smoothing Length + // + // Presentation ... + "", + mInputs.drawHikenAshi, // Draw Hiken Ashi + mInputs.drawSmoothedHikenAshi // Draw Smoothed Hiken Ashi + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + XHKInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + XHKInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Buffers ... + + // + double GetOpen( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(openBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return openBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyOpen( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + openBuffer, + buffer, + forceClean + // + ); + } + + // + double GetHigh( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(highBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return highBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyHigh( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + highBuffer, + buffer, + forceClean + // + ); + } + + // + double GetLow( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(lowBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return lowBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyLow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + lowBuffer, + buffer, + forceClean + // + ); + } + + // + double GetClose( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(closeBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return closeBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyClose( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + closeBuffer, + buffer, + forceClean + // + ); + } + + // + // Smoothed ... + + // + double GetSMOpen( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(smOpenBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return smOpenBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopySMOpen( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + smOpenBuffer, + buffer, + forceClean + // + ); + } + + // + double GetSMHigh( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(smHighBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return smHighBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopySMHigh( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + smHighBuffer, + buffer, + forceClean + // + ); + } + + // + double GetSMLow( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(smLowBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return smLowBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopySMLow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + smLowBuffer, + buffer, + forceClean + // + ); + } + + // + double GetSMClose( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(smCloseBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return smCloseBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopySMClose( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + smCloseBuffer, + buffer, + forceClean + // + ); + } + + // + // XOHCL ... + + // + // Retrieve Hiken Ashi Info as XOHCL model ... + bool AsOHCL( + XOHCL &bar, // Holds Result + int barIndex // Bar Index + ) + { + // + bool result = false; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(openBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + double open = GetOpen(barIndex); + double high = GetHigh(barIndex); + double close = GetClose(barIndex); + double low = GetLow(barIndex); + + // + result = bar.Init( + mSymbol, + mPeriod, + open, + high, + close, + low, + barIndex + // + ); + + // + return result; + } + + // + // Copy Required Items ... + int CopyAsOHCL( + int start, // Start + int count, // Number of Items for read + XOHCL &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + int result = 0; + + // + // Update Calculations ... + Calculate(); + + // + if (forceClean) + { + Clean(buffer); + } + + // + int before = ArraySize(buffer); + + // + if (start < 0) + { + start = 0; + } + + // + if (start >= ArraySize(openBuffer)) + { + start = ArraySize(openBuffer) - 1; + } + + // + bool asSeriesBuffer = ArrayGetAsSeries(buffer); + ArraySetAsSeries(buffer, true); + + // + for (int i = start; i < start + count; i++) + { + // + XOHCL iBar; + bool isInit = AsOHCL(iBar, i); + + // + if (isInit) + { + // + AddRef( + iBar, + buffer + // + ); + } + } + + // + ArraySetAsSeries(buffer, asSeriesBuffer); + + // + int after = ArraySize(buffer); + + // + result = after - before; + + // + return result; + } + + // + // Retrieve Smoothed Hiken Ashi Info as XOHCL model ... + bool SMAsOHCL( + XOHCL &bar, // Holds Result + int barIndex // Bar Index + ) + { + // + bool result = false; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(openBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + double open = GetSMOpen(barIndex); + double high = GetSMHigh(barIndex); + double close = GetSMClose(barIndex); + double low = GetSMLow(barIndex); + + // + result = bar.Init( + mSymbol, + mPeriod, + open, + high, + close, + low, + barIndex + // + ); + + // + return result; + } + + // + // Copy Required Items ... + int CopySMAsOHCL( + int start, // Start + int count, // Number of Items for read + XOHCL &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + int result = 0; + + // + // Update Calculations ... + Calculate(); + + // + if (forceClean) + { + Clean(buffer); + } + + // + int before = ArraySize(buffer); + + // + if (start < 0) + { + start = 0; + } + + // + if (start >= ArraySize(openBuffer)) + { + start = ArraySize(openBuffer) - 1; + } + + // + bool asSeriesBuffer = ArrayGetAsSeries(buffer); + ArraySetAsSeries(buffer, true); + + // + for (int i = start; i < start + count; i++) + { + // + XOHCL iBar; + bool isInit = SMAsOHCL(iBar, i); + + // + if (isInit) + { + // + AddRef( + iBar, + buffer + // + ); + } + } + + // + ArraySetAsSeries(buffer, asSeriesBuffer); + + // + int after = ArraySize(buffer); + + // + result = after - before; + + // + return result; + } + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Props ... + XHKInputs mInputs; // Inputs ... + + // + // Buffers ... + double openBuffer[]; + double highBuffer[]; + double lowBuffer[]; + double closeBuffer[]; + double smOpenBuffer[]; + double smHighBuffer[]; + double smLowBuffer[]; + double smCloseBuffer[]; + + // + // Tools ... + + // + // Calculate Values Until Now ... + void Calculate() + { + // + int totalBars = CountBars(); + + // + // Open Buffer ... + CopyBuffer( + mHandler, + XHK_OPEN_LINE, + 0, + totalBars, + openBuffer + // + ); + + // + // High Buffer ... + CopyBuffer( + mHandler, + XHK_HIGHLINE, + 0, + totalBars, + highBuffer + // + ); + + // + // Low Buffer ... + CopyBuffer( + mHandler, + XHK_LOW_LINE, + 0, + totalBars, + lowBuffer + // + ); + + // + // Close Buffer ... + CopyBuffer( + mHandler, + XHK_CLOSE_LINE, + 0, + totalBars, + closeBuffer + // + ); + + // + // Smoothed ... + + // + // Open Buffer ... + CopyBuffer( + mHandler, + XHK_SM_OPEN_LINE, + 0, + totalBars, + smOpenBuffer + // + ); + + // + // High Buffer ... + CopyBuffer( + mHandler, + XHK_SM_HIGHLINE, + 0, + totalBars, + smHighBuffer + // + ); + + // + // Low Buffer ... + CopyBuffer( + mHandler, + XHK_SM_LOW_LINE, + 0, + totalBars, + smLowBuffer + // + ); + + // + // Close Buffer ... + CopyBuffer( + mHandler, + XHK_SM_CLOSE_LINE, + 0, + totalBars, + smCloseBuffer + // + ); + } +}; + +// +// Tools ... \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xhull.helper.ex5 b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xhull.helper.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..8c1af1177726eab2e6db7bbac9ff5dfa79049962 GIT binary patch literal 5986 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 literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xhull.helper.mq5 b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xhull.helper.mq5 new file mode 100644 index 0000000..900f629 --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xhull.helper.mq5 @@ -0,0 +1,399 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCXHULLHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.xhelper.class.mq5" + +// +// Definitions ... + +// +enum ENUM_XHULLC_BUFFERS +{ + XHULLC_UP_LINE = 0, + XHULLC_DOWN_LINE = 2, +}; + +// +// Input Models ... +struct XHULLInputs +{ + // + // Props ... + // + // Market ... + int length; // Length + double divisor; // Divisor (Speed) + + // + // Calculation ... + ENUM_APPLIED_PRICE upAppliedTo; // Up Zone Applied to + ENUM_APPLIED_PRICE downAppliedTo; // Down Zone Applied to + + // + // Presentation ... + bool showUpZone; // Show Up Zone + bool showDownZone; // Show Down Zone + + // + // Constructor(s) ... + XHULLInputs() + { + // + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + // Market ... + length = 0; + divisor = 0; + + // + // Calculation ... + upAppliedTo = PRICE_HIGH; + downAppliedTo = PRICE_LOW; + + // + // Presentation ... + showUpZone = false; + showDownZone = false; + } + + // + // Default ... + void Default() + { + // + // Market ... + length = 72; + divisor = 2.0; + + // + // Calculation ... + upAppliedTo = PRICE_HIGH; + downAppliedTo = PRICE_LOW; + + // + // Presentation ... + showUpZone = true; + showDownZone = true; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + length >= 9 && + divisor >= 0.5 + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(0, length); + + // + return result; + } +}; + +// +// Class ... +class XSCXHULLHelper : public XSCBaseHelper +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructors ... + XSCXHULLHelper() : XSCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XSCXHULLHelper() {} + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + XHULLInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + // ArraySetAsSeries(mainBuffer, true); + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.xhull", + // + // Inputs ... + // + // Market ... + "", + mInputs.length, // Length + mInputs.divisor, // Divisor (Speed) + // + // Calculation ... + "", + mInputs.upAppliedTo, // Up Zone Applied to + mInputs.downAppliedTo, // Down Zone Applied to + // + // Presentation ... + "", + mInputs.showUpZone, // Show Up Zone + mInputs.showDownZone // Show Down Zone + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + XHULLInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + XHULLInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Buffers ... + + // + double GetUp( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(upBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return upBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyUp( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + upBuffer, + buffer, + forceClean + // + ); + } + + // + double GetDown( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(downBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return downBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyDown( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + downBuffer, + buffer, + forceClean + // + ); + } + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Props ... + XHULLInputs mInputs; // Inputs ... + + // + // Buffers ... + double upBuffer[]; + double downBuffer[]; + + // + // Tools ... + + // + // Calculate Values Until Now ... + void Calculate() + { + // + int totalBars = CountBars(); + + // + // Up Buffer ... + CopyBuffer( + mHandler, + XHULLC_UP_LINE, + 0, + totalBars, + upBuffer + // + ); + + // + // Down Buffer ... + CopyBuffer( + mHandler, + XHULLC_DOWN_LINE, + 0, + totalBars, + downBuffer + // + ); + } +}; + +// +// Tools ... \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xich.helper.ex5 b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xich.helper.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..48d8fafdfbbbd40a2c033435f0c48998e586e7f9 GIT binary patch literal 5740 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 Q7qZw(Sxfb}jWTWdA9Sb)>i_@% literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xich.helper.mq5 b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xich.helper.mq5 new file mode 100644 index 0000000..3a1dcf9 --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xich.helper.mq5 @@ -0,0 +1,827 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCXICHHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +#include "../Classes/x-saherelm.xhelper.class.mq5" + +// +// Definitions ... +// +// Ichimoku Lines Calculator Mode ... +enum ENUM_XICH_CALCULATION_MODE +{ + // + X_XICH_HH_LL_MODE = 1, // Highest High and Lowest Low + X_XICH_HO_LC_MODE = 2, // Highest Open and Lowest Close +}; + +// +enum ENUM_XICH_BUFFERS +{ + X_ICH_TEANKANSEN_LINE = 0, + X_ICH_KIJUNSEN_LINE = 1, + X_ICH_CHIKOUSPAN_LINE = 4, + X_ICH_SENKOUSPANA_LINE = 5, + X_ICH_SENKOUSPANB_LINE = 6, +}; + +// +// Input Models ... +struct XICHInputs +{ + // + // Props ... + + // + // Market ... + // + // Tenkan Sen ... + int tenkanSenLength; // Length + ENUM_XICH_CALCULATION_MODE tenkanSenMode; // Calculation Mode + + // + // Kijun Sen ... + int kijunSenLength; // Length + ENUM_XICH_CALCULATION_MODE kijunSenMode; // Calculation Mode + + // + // Senkou Span B ... + int senkouSpanBLength; // Length + ENUM_XICH_CALCULATION_MODE senkouSpanBMode; // Calculation Mode + + // + // Chikou Span ... + ENUM_APPLIED_PRICE chikuoSpanAppliedTo; // Price Type + + // + // Presentation ... + bool showTenkanSen; // Show Tenkan Sen + bool showKijunSen; // Show Kijun Sen + bool showKijunSenPlus; // Show Kijun Sen + + bool showKijunSenNegative; // Show Kijun Sen - + bool showChikouSpan; // Show Chikou Span + bool showSenkouSpanA; // Show Senkou Span A + bool showSenkouSpanB; // Show Senkou Span B + bool showKumo; // Show Kumo + bool shiftKumo; // Shift Kumo to Future + + // + // Constructor(s) ... + XICHInputs() + { + // + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + kijunSenLength = 0; + tenkanSenLength = 0; + senkouSpanBLength = 0; + + // + kijunSenMode = X_XICH_HH_LL_MODE; + tenkanSenMode = X_XICH_HH_LL_MODE; + senkouSpanBMode = X_XICH_HH_LL_MODE; + + // + chikuoSpanAppliedTo = PRICE_CLOSE; + + // + showTenkanSen = false; + showKijunSen = false; + showKijunSenPlus = false; + showKijunSenNegative = false; + showChikouSpan = false; + showSenkouSpanA = false; + showSenkouSpanB = false; + showKumo = false; + shiftKumo = true; + } + + // + // Default ... + void Default() + { + // + kijunSenLength = 26; + tenkanSenLength = 9; + senkouSpanBLength = 52; + + // + kijunSenMode = X_XICH_HH_LL_MODE; + tenkanSenMode = X_XICH_HH_LL_MODE; + senkouSpanBMode = X_XICH_HH_LL_MODE; + + // + chikuoSpanAppliedTo = PRICE_CLOSE; + + // + showTenkanSen = true; + showKijunSen = true; + showKijunSenPlus = false; + showKijunSenNegative = false; + showChikouSpan = true; + showSenkouSpanA = true; + showSenkouSpanB = true; + showKumo = true; + shiftKumo = true; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + tenkanSenLength > 2 && + kijunSenLength > tenkanSenLength && + senkouSpanBLength > kijunSenLength + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(result, tenkanSenLength); + result = MathMax(result, kijunSenLength); + result = MathMax(result, senkouSpanBLength); + + // + return result; + } +}; + +// +// Class ... +class XSCXICHHelper : public XSCBaseHelper +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructors ... + XSCXICHHelper() : XSCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XSCXICHHelper() {} + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + XICHInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + ArraySetAsSeries(tenkanSenBuffer, true); + ArraySetAsSeries(kijunSenBuffer, true); + ArraySetAsSeries(chikouSpanBuffer, true); + ArraySetAsSeries(senkouSpanABuffer, true); + ArraySetAsSeries(senkouSpanBBuffer, true); + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.xich", + // + // Inputs ... + // + // TenkanSen ... + "", + mInputs.tenkanSenLength, + mInputs.tenkanSenMode, + // + // KijunSen ... + "", + mInputs.kijunSenLength, + mInputs.kijunSenMode, + // + // SenkouSpan B ... + "", + mInputs.senkouSpanBLength, + mInputs.senkouSpanBMode, + // + // ChikouSpan ... + "", + mInputs.chikuoSpanAppliedTo, + // + // Presentation ... + "", + mInputs.showTenkanSen, // Show Tenkan Sen + mInputs.showKijunSen, // Show Kijun Sen + mInputs.showKijunSenPlus, // Show Kijun Sen + + mInputs.showKijunSenNegative, // Show Kijun Sen - + mInputs.showChikouSpan, // Show Chikou Span + mInputs.showSenkouSpanA, // Show Senkou Span A + mInputs.showSenkouSpanB, // Show Senkou Span B + mInputs.showKumo, // Show Kumo + mInputs.shiftKumo // Shift Kumo to Future + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + XICHInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + XICHInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs); + } + + // + // Buffers ... + + // + // TenkanSen ... + + // + double GetTenkanSen( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + return tenkanSenBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyTenkanSen( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + tenkanSenBuffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameTenkanSen( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + tenkanSenBuffer, + verifier, + barIndex // + ); + } + + // + // KijunSen ... + + // + double GetKijunSen( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + return kijunSenBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyKijunSen( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + kijunSenBuffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameKijunSen( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + kijunSenBuffer, + verifier, + barIndex // + ); + } + + // + // ChikouSpan ... + + // + double GetChikouSpan( + int barIndex // Bar Index + ) + { + // + barIndex -= mInputs.kijunSenLength; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (barIndex > ArraySize(chikouSpanBuffer)) + { + barIndex = ArraySize(chikouSpanBuffer) - 1; + } + + // + Calculate(); + + // + return chikouSpanBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyChikouSpan( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start - mInputs.kijunSenLength, + count, + chikouSpanBuffer, + buffer, + forceClean + // + ); + } + + // + // SenkouSpanA ... + + // + double GetSenkouSpanA( + int barIndex // Bar Index + ) + { + // + barIndex += mInputs.kijunSenLength; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (barIndex > ArraySize(senkouSpanABuffer)) + { + barIndex = ArraySize(senkouSpanABuffer) - 1; + } + + // + Calculate(); + + // + return senkouSpanABuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopySenkouSpanA( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start + mInputs.kijunSenLength, + count, + senkouSpanABuffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameSenkouSpanA( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + senkouSpanABuffer, + verifier, + barIndex // + ); + } + + // + // SenkouSpanB ... + + // + double GetSenkouSpanB( + int barIndex // Bar Index + ) + { + // + barIndex += mInputs.kijunSenLength; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (barIndex > ArraySize(senkouSpanBBuffer)) + { + barIndex = ArraySize(senkouSpanBBuffer) - 1; + } + + // + Calculate(); + + // + return senkouSpanBBuffer[barIndex + mInputs.kijunSenLength]; + } + + // + // Copy Required Items ... + int CopySenkouSpanB( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start + mInputs.kijunSenLength, + count, + senkouSpanBBuffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameSenkouSpanB( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + senkouSpanBBuffer, + verifier, + barIndex // + ); + } + + // + // Future SenkouSpanA ... + + // + double GetFutureSenkouSpanA( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + return senkouSpanABuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyFutureSenkouSpanA( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + senkouSpanABuffer, + buffer, + forceClean + // + ); + } + + // + // SenkouSpanB ... + + // + double GetFutureSenkouSpanB( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + return senkouSpanBBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyFutureSenkouSpanB( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + senkouSpanBBuffer, + buffer, + forceClean + // + ); + } + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Props ... + XICHInputs mInputs; // Inputs ... + + // + // Buffers ... + double tenkanSenBuffer[]; + double kijunSenBuffer[]; + double chikouSpanBuffer[]; + double senkouSpanABuffer[]; + double senkouSpanBBuffer[]; + + // + // Tools ... + + // + // Calculate Values Until Now ... + void Calculate() + { + // + int totalBars = CountBars(); + int calculatedBars = CountCalculatedBars(); + + // + // TenkanSen ... + CopyBuffer( + mHandler, + X_ICH_TEANKANSEN_LINE, + 0, + totalBars, + tenkanSenBuffer + // + ); + + // + // KijunSen ... + CopyBuffer( + mHandler, + X_ICH_KIJUNSEN_LINE, + 0, + totalBars, + kijunSenBuffer + // + ); + + // + // ChikouSpan ... + CopyBuffer( + mHandler, + X_ICH_CHIKOUSPAN_LINE, + 0, + totalBars, + chikouSpanBuffer + // + ); + + // + // SenkouSpan A ... + CopyBuffer( + mHandler, + X_ICH_SENKOUSPANA_LINE, + 0, + totalBars, + senkouSpanABuffer + // + ); + + // + // SenkouSpan B ... + CopyBuffer( + mHandler, + X_ICH_SENKOUSPANB_LINE, + 0, + totalBars, + senkouSpanBBuffer + // + ); + } +}; + +// +// Tools ... diff --git a/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xmc.helper.ex5 b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xmc.helper.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..76d54e89d3f918c878bd5c7b0b5eac59ef380f89 GIT binary patch literal 5906 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 literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xmc.helper.mq5 b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xmc.helper.mq5 new file mode 100644 index 0000000..af386a3 --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xmc.helper.mq5 @@ -0,0 +1,496 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCXMCHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +#include "../Classes/x-saherelm.xhelper.class.mq5" + +// +// Definitions ... + +// +enum ENUM_XMC_BUFFERS +{ + X_MC_FAST_LINE = 0, + X_MC_SLOW_LINE = 1, + X_MC_VERIFIER_LINE = 2, +}; + +// +// Input Models ... +struct XMCInputs +{ + // + // Props ... + + // + // Market ... + + // + // Fast ... + int fastLength; // Length + int fastShift; // Shift + ENUM_MA_METHOD fastMethod; // Method + ENUM_APPLIED_PRICE fastAppliedTo; // Applied To + + // + // Slow ... + int slowLength; // Length + int slowShift; // Shift + ENUM_MA_METHOD slowMethod; // Method + ENUM_APPLIED_PRICE slowAppliedTo; // Applied To + + // + // Verifier ... + int verifierLength; // Length + int verifierShift; // Shift + ENUM_MA_METHOD verifierMethod; // Method + ENUM_APPLIED_PRICE verifierAppliedTo; // Applied To + + // + // Presentation ... + bool showFastMa; // Show Fast + bool showSlowMa; // Show Slow + bool showVerifierMa; // Show Verifier + + // + // Constructor(s) ... + XMCInputs() + { + // + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + fastLength = 0; + fastShift = 0; + fastMethod = 0; + fastAppliedTo = PRICE_CLOSE; + + // + slowLength = 0; + slowShift = 0; + slowMethod = 0; + slowAppliedTo = PRICE_CLOSE; + + // + verifierLength = 0; + verifierShift = 0; + verifierMethod = 0; + verifierAppliedTo = PRICE_CLOSE; + + // + showFastMa = false; + showSlowMa = false; + showVerifierMa = false; + } + + // + // Default ... + void Default() + { + // + fastLength = 9; + fastShift = 0; + fastMethod = MODE_EMA; + fastAppliedTo = PRICE_CLOSE; + + // + slowLength = 18; + slowShift = 0; + slowMethod = MODE_EMA; + slowAppliedTo = PRICE_CLOSE; + + // + verifierLength = 200; + verifierShift = 0; + verifierMethod = MODE_EMA; + verifierAppliedTo = PRICE_CLOSE; + + // + showFastMa = true; + showSlowMa = true; + showVerifierMa = true; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + fastLength > 1 && + slowLength > fastLength && + verifierLength > slowLength + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(fastLength, slowLength); + result = MathMax(result, verifierLength); + + // + return result; + } +}; + +// +// Class ... +class XSCXMCHelper : public XSCBaseHelper +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructors ... + XSCXMCHelper() : XSCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XSCXMCHelper() {} + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + XMCInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + ArraySetAsSeries(fastBuffer, true); + ArraySetAsSeries(slowBuffer, true); + ArraySetAsSeries(verifierBuffer, true); + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.xmc", + // + // Inputs ... + // + // Fast ... + "", + mInputs.fastLength, + mInputs.fastShift, + mInputs.fastMethod, + mInputs.fastAppliedTo, + // + // Slow ... + "", + mInputs.slowLength, + mInputs.slowShift, + mInputs.slowMethod, + mInputs.slowAppliedTo, + // + // Verifier ... + "", + mInputs.verifierLength, + mInputs.verifierShift, + mInputs.verifierMethod, + mInputs.verifierAppliedTo, + // + // Presentation ... + "", + mInputs.showFastMa, // Show Fast, + mInputs.showSlowMa, // Show Slow, + mInputs.showVerifierMa // Show Verifier + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + XMCInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + XMCInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs); + } + + // + // Buffers ... + + // + // Fast ... + + // + double GetFast( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + return fastBuffer[barIndex]; + } + + // + // Copy Required Buffer ... + int CopyFast( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + fastBuffer, + buffer, + forceClean + // + ); + } + + // + // Slow ... + + // + double GetSlow( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + return slowBuffer[barIndex]; + } + + // + // Copy Required Buffer ... + int CopySlow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + slowBuffer, + buffer, + forceClean + // + ); + } + + // + // Verifier ... + + // + double GetVerifier( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + return verifierBuffer[barIndex]; + } + + // + // Copy Required Buffer ... + int CopyVerifier( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + verifierBuffer, + buffer, + forceClean + // + ); + } + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Props ... + XMCInputs mInputs; // Inputs ... + + // + // Buffers ... + // + double fastBuffer[]; + double slowBuffer[]; + double verifierBuffer[]; + + // + // Tools ... + + // + // Calculate Values Until Now ... + void Calculate() + { + // + int totalBars = CountBars(); + + // + // Fast ... + CopyBuffer( + mHandler, + X_MC_FAST_LINE, + 0, + totalBars, + fastBuffer + // + ); + + // + // Slow ... + CopyBuffer( + mHandler, + X_MC_SLOW_LINE, + 0, + totalBars, + slowBuffer + // + ); + + // + // Verifier ... + CopyBuffer( + mHandler, + X_MC_VERIFIER_LINE, + 0, + totalBars, + verifierBuffer + // + ); + } +}; + +// +// Tools ... diff --git a/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xmrb.helper.ex5 b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xmrb.helper.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..fa0de345e4d3f5ea98a8865dff610cfaed147045 GIT binary patch literal 6378 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 Z%62G|K_ACtZru6fK8r{{a>5Mze*ng~APoQj literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xmrb.helper.mq5 b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xmrb.helper.mq5 new file mode 100644 index 0000000..78addb8 --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xmrb.helper.mq5 @@ -0,0 +1,1411 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCXMRBHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.xhelper.class.mq5" + +// +// Definitions ... + +// +enum ENUM_XMRB_BUFFERS +{ + // + // Ribbon ... + XMRB_FAST_LINE = 0, + XMRB_SLOW_LINE = 1, + // + // Ribbon 1 ... + XMRB_R1_FAST_LINE = 2, + XMRB_R1_SLOW_LINE = 3, + // + // Ribbon 2 ... + XMRB_R2_FAST_LINE = 4, + XMRB_R2_SLOW_LINE = 5, + // + // Ribbon 3 ... + XMRB_R3_FAST_LINE = 6, + XMRB_R3_SLOW_LINE = 7, + // + // Ribbon 4 ... + XMRB_R4_FAST_LINE = 8, + XMRB_R4_SLOW_LINE = 9, + // + // Ribbon 5 ... + XMRB_R5_FAST_LINE = 10, + XMRB_R5_SLOW_LINE = 11, + // + // Ribbon 5 ... + XMRB_R6_FAST_LINE = 12, + XMRB_R6_SLOW_LINE = 13, +}; + +// +// Input Models ... +struct XMRBInputs +{ + // + // Props ... + + // + // Ribbon 1 ... + int fast1Length; // Fast + int slow1Length; // Slow + ENUM_APPLIED_PRICE r1AppliedTo; // AppliedTo + + // + // Ribbon 2 ... + int fast2Length; // Fast + int slow2Length; // Slow + ENUM_APPLIED_PRICE r2AppliedTo; // AppliedTo + + // + // Ribbon 3 ... + int fast3Length; // Fast + int slow3Length; // Slow + ENUM_APPLIED_PRICE r3AppliedTo; // AppliedTo + + // + // Ribbon 4 ... + int fast4Length; // Fast + int slow4Length; // Slow + ENUM_APPLIED_PRICE r4AppliedTo; // AppliedTo + + // + // Ribbon 5 ... + int fast5Length; // Fast + int slow5Length; // Slow + ENUM_APPLIED_PRICE r5AppliedTo; // AppliedTo + + // + // Ribbon 6 ... + int fast6Length; // Fast + int slow6Length; // Slow + ENUM_APPLIED_PRICE r6AppliedTo; // AppliedTo + + // + // Calculation ... + ENUM_MA_METHOD ribbonMode; // Mode + + // + // Presentation ... + bool showFastMa; // Show Fast + bool showSlowMa; // Show Slow + bool showRibbon; // Show Ribbon + + // + // Constructor(s) ... + XMRBInputs() + { + // + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + // Ribbon 1 ... + fast1Length = 0; // Fast + slow1Length = 0; // Slow + r1AppliedTo = PRICE_HIGH; // AppliedTo + + // + // Ribbon 2 ... + fast2Length = 0; // Fast + slow2Length = 0; // Slow + r2AppliedTo = PRICE_OPEN; // AppliedTo + + // + // Ribbon 3 ... + fast3Length = 0; // Fast + slow3Length = 0; // Slow + r3AppliedTo = PRICE_CLOSE; // AppliedTo + + // + // Ribbon 4 ... + fast4Length = 0; // Fast + slow4Length = 0; // Slow + r4AppliedTo = PRICE_MEDIAN; // AppliedTo + + // + // Ribbon 5 ... + fast5Length = 0; // Fast + slow5Length = 0; // Slow + r5AppliedTo = PRICE_TYPICAL; // AppliedTo + + // + // Ribbon 6 ... + fast6Length = 0; // Fast + slow6Length = 0; // Slow + r6AppliedTo = PRICE_LOW; // AppliedTo + + // + // Calculation ... + ribbonMode = MODE_EMA; // Mode + + // + // Presentation ... + showFastMa = false; // Show Fast + showSlowMa = false; // Show Slow + showRibbon = false; // Show Ribbon + } + + // + // Default ... + void Default() + { + // + // Ribbon 1 ... + fast1Length = 20; // Fast + slow1Length = 50; // Slow + r1AppliedTo = PRICE_HIGH; // AppliedTo + + // + // Ribbon 2 ... + fast2Length = 20; // Fast + slow2Length = 50; // Slow + r2AppliedTo = PRICE_OPEN; // AppliedTo + + // + // Ribbon 3 ... + fast3Length = 20; // Fast + slow3Length = 50; // Slow + r3AppliedTo = PRICE_CLOSE; // AppliedTo + + // + // Ribbon 4 ... + fast4Length = 20; // Fast + slow4Length = 50; // Slow + r4AppliedTo = PRICE_MEDIAN; // AppliedTo + + // + // Ribbon 5 ... + fast5Length = 20; // Fast + slow5Length = 50; // Slow + r5AppliedTo = PRICE_TYPICAL; // AppliedTo + + // + // Ribbon 6 ... + fast6Length = 20; // Fast + slow6Length = 50; // Slow + r6AppliedTo = PRICE_LOW; // AppliedTo + + // + // Calculation ... + ribbonMode = MODE_EMA; // Mode + + // + // Presentation ... + showFastMa = true; // Show Fast + showSlowMa = true; // Show Slow + showRibbon = false; // Show Ribbon + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + (fast1Length > 2 && + fast2Length > 2 && + fast3Length > 2 && + fast4Length > 2 && + fast5Length > 2 && + fast6Length > 2 && + slow1Length > fast1Length && + slow2Length > fast2Length && + slow3Length > fast3Length && + slow4Length > fast4Length && + slow5Length > fast5Length && + slow6Length > fast6Length + // + ) + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(fast1Length, fast2Length); + result = MathMax(result, fast3Length); + result = MathMax(result, fast4Length); + result = MathMax(result, fast5Length); + result = MathMax(result, fast6Length); + + // + result = MathMax(result, slow1Length); + result = MathMax(result, slow2Length); + result = MathMax(result, slow3Length); + result = MathMax(result, slow4Length); + result = MathMax(result, slow5Length); + result = MathMax(result, slow6Length); + + // + return result; + } +}; + +// +// Class ... +class XSCXMRBHelper : public XSCBaseHelper +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructors ... + XSCXMRBHelper() : XSCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XSCXMRBHelper() {} + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + XMRBInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + ArraySetAsSeries(fastBuffer, true); + ArraySetAsSeries(slowBuffer, true); + ArraySetAsSeries(r1FastBuffer, true); + ArraySetAsSeries(r1SlowBuffer, true); + ArraySetAsSeries(r2FastBuffer, true); + ArraySetAsSeries(r2SlowBuffer, true); + ArraySetAsSeries(r3FastBuffer, true); + ArraySetAsSeries(r3SlowBuffer, true); + ArraySetAsSeries(r4FastBuffer, true); + ArraySetAsSeries(r4SlowBuffer, true); + ArraySetAsSeries(r5FastBuffer, true); + ArraySetAsSeries(r5SlowBuffer, true); + ArraySetAsSeries(r6FastBuffer, true); + ArraySetAsSeries(r6SlowBuffer, true); + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.xmrb", + // + // Inputs ... + // + // Ribbon 1 ... + "", + mInputs.fast1Length, // Fast + mInputs.slow1Length, // Slow + mInputs.r1AppliedTo, // AppliedTo + // + // Ribbon 2 ... + "", + mInputs.fast2Length, // Fast + mInputs.slow2Length, // Slow + mInputs.r2AppliedTo, // AppliedTo + // + // Ribbon 3 ... + "", + mInputs.fast3Length, // Fast + mInputs.slow3Length, // Slow + mInputs.r3AppliedTo, // AppliedTo + // + // Ribbon 4 ... + "", + mInputs.fast4Length, // Fast + mInputs.slow4Length, // Slow + mInputs.r4AppliedTo, // AppliedTo + // + // Ribbon 5 ... + "", + mInputs.fast5Length, // Fast + mInputs.slow5Length, // Slow + mInputs.r5AppliedTo, // AppliedTo + // + // Ribbon 6 ... + "", + mInputs.fast6Length, // Fast + mInputs.slow6Length, // Slow + mInputs.r6AppliedTo, // AppliedTo + // + // Calculation ... + "", + mInputs.ribbonMode, // Mode + // + // Presentation ... + "", + mInputs.showFastMa, // Show Fast + mInputs.showSlowMa, // Show Slow + mInputs.showRibbon // Show Ribbon + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + XMRBInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + XMRBInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Buffers ... + + // + // Fast ... + + // + double GetFast( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(fastBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fastBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyFast( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + fastBuffer, + buffer, + forceClean + // + ); + } + + // + // Slow ... + + // + double GetSlow( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(slowBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return slowBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopySlow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + slowBuffer, + buffer, + forceClean + // + ); + } + + // + // Ribbon 1 ... + + // + // Fast ... + + // + double GetR1Fast( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(r1FastBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return r1FastBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyR1Fast( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + r1FastBuffer, + buffer, + forceClean + // + ); + } + + // + // Slow ... + + // + double GetR1Slow( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(r1SlowBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return r1SlowBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyR1Slow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + r1SlowBuffer, + buffer, + forceClean + // + ); + } + + // + // Ribbon 2 ... + + // + // Fast ... + + // + double GetR2Fast( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(r2FastBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return r2FastBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyR2Fast( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + r2FastBuffer, + buffer, + forceClean + // + ); + } + + // + // Slow ... + + // + double GetR2Slow( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(r2SlowBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return r2SlowBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyR2Slow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + r2SlowBuffer, + buffer, + forceClean + // + ); + } + + // + // Ribbon 3 ... + + // + // Fast ... + + // + double GetR3Fast( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(r3FastBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return r3FastBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyR3Fast( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + r3FastBuffer, + buffer, + forceClean + // + ); + } + + // + // Slow ... + + // + double GetR3Slow( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(r3SlowBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return r3SlowBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyR3Slow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + r3SlowBuffer, + buffer, + forceClean + // + ); + } + + // + // Ribbon 4 ... + + // + // Fast ... + + // + double GetR4Fast( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(r4FastBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return r4FastBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyR4Fast( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + r4FastBuffer, + buffer, + forceClean + // + ); + } + + // + // Slow ... + + // + double GetR4Slow( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(r4SlowBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return r4SlowBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyR4Slow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + r4SlowBuffer, + buffer, + forceClean + // + ); + } + + // + // Ribbon 5 ... + + // + // Fast ... + + // + double GetR5Fast( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(r5FastBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return r5FastBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyR5Fast( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + r5FastBuffer, + buffer, + forceClean + // + ); + } + + // + // Slow ... + + // + double GetR5Slow( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(r5SlowBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return r5SlowBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyR5Slow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + r5SlowBuffer, + buffer, + forceClean + // + ); + } + + // + // Ribbon 6 ... + + // + // Fast ... + + // + double GetR6Fast( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(r6FastBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return r6FastBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyR6Fast( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + r6FastBuffer, + buffer, + forceClean + // + ); + } + + // + // Slow ... + + // + double GetR6Slow( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(r6SlowBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return r6SlowBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyR6Slow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + r6SlowBuffer, + buffer, + forceClean + // + ); + } + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Props ... + XMRBInputs mInputs; // Inputs ... + + // + // Buffers ... + double fastBuffer[]; + double slowBuffer[]; + double r1FastBuffer[]; + double r1SlowBuffer[]; + double r2FastBuffer[]; + double r2SlowBuffer[]; + double r3FastBuffer[]; + double r3SlowBuffer[]; + double r4FastBuffer[]; + double r4SlowBuffer[]; + double r5FastBuffer[]; + double r5SlowBuffer[]; + double r6FastBuffer[]; + double r6SlowBuffer[]; + + // + // Tools ... + + // + // Calculate Values Until Now ... + void Calculate() + { + // + int totalBars = CountBars(); + + // + // Fast Buffer ... + CopyBuffer( + mHandler, + XMRB_FAST_LINE, + 0, + totalBars, + fastBuffer + // + ); + + // + // Slow Buffer ... + CopyBuffer( + mHandler, + XMRB_SLOW_LINE, + 0, + totalBars, + slowBuffer + // + ); + + // + // Ribbon 1 ... + + // + // Fast Buffer ... + CopyBuffer( + mHandler, + XMRB_R1_FAST_LINE, + 0, + totalBars, + r1FastBuffer + // + ); + + // + // Slow Buffer ... + CopyBuffer( + mHandler, + XMRB_R1_SLOW_LINE, + 0, + totalBars, + r1SlowBuffer + // + ); + + // + // Ribbon 2 ... + + // + // Fast Buffer ... + CopyBuffer( + mHandler, + XMRB_R2_FAST_LINE, + 0, + totalBars, + r2FastBuffer + // + ); + + // + // Slow Buffer ... + CopyBuffer( + mHandler, + XMRB_R2_SLOW_LINE, + 0, + totalBars, + r2SlowBuffer + // + ); + + // + // Ribbon 3 ... + + // + // Fast Buffer ... + CopyBuffer( + mHandler, + XMRB_R3_FAST_LINE, + 0, + totalBars, + r3FastBuffer + // + ); + + // + // Slow Buffer ... + CopyBuffer( + mHandler, + XMRB_R3_SLOW_LINE, + 0, + totalBars, + r3SlowBuffer + // + ); + + // + // Ribbon 4 ... + + // + // Fast Buffer ... + CopyBuffer( + mHandler, + XMRB_R4_FAST_LINE, + 0, + totalBars, + r4FastBuffer + // + ); + + // + // Slow Buffer ... + CopyBuffer( + mHandler, + XMRB_R4_SLOW_LINE, + 0, + totalBars, + r4SlowBuffer + // + ); + + // + // Ribbon 5 ... + + // + // Fast Buffer ... + CopyBuffer( + mHandler, + XMRB_R5_FAST_LINE, + 0, + totalBars, + r5FastBuffer + // + ); + + // + // Slow Buffer ... + CopyBuffer( + mHandler, + XMRB_R5_SLOW_LINE, + 0, + totalBars, + r5SlowBuffer + // + ); + + // + // Ribbon 6 ... + + // + // Fast Buffer ... + CopyBuffer( + mHandler, + XMRB_R6_FAST_LINE, + 0, + totalBars, + r6FastBuffer + // + ); + + // + // Slow Buffer ... + CopyBuffer( + mHandler, + XMRB_R6_SLOW_LINE, + 0, + totalBars, + r6SlowBuffer + // + ); + } +}; + +// +// Tools ... \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xosc.helper.ex5 b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xosc.helper.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..24d74f335548ac9caddd95205199e00b0a3606a6 GIT binary patch literal 5542 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 YlZOKv=}_Nkf_l_e9L-zRH= 2 && + rviLength >= 2 && + bullpLength >= 2 && + bearpLength >= 2 && + rsiLength >= 2 && + cciLength >= 2 && + momentumLength >= 2 && + sarStep > 0 && + sarStep < sarMaximum && + macdFastLength >= 2 && + macdSlowLength > macdFastLength && + macdSignaLength >= 2 && + stochKLength >= 2 && + stochDLength >= 2 && + stochSlowing >= 2 && + stddevLength >= 2 && + stddevShift >= 0 + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(atrLength, rviLength); + result = MathMax(result, bullpLength); + result = MathMax(result, bearpLength); + result = MathMax(result, rsiLength); + result = MathMax(result, cciLength); + result = MathMax(result, momentumLength); + result = MathMax(result, macdFastLength); + result = MathMax(result, macdSlowLength); + result = MathMax(result, macdSignaLength); + result = MathMax(result, stochKLength); + result = MathMax(result, stochDLength); + result = MathMax(result, stochSlowing); + result = MathMax(result, stddevLength); + + // + return result; + } +}; + +// +// Class ... +class XSCXOSCHelper : public XSCBaseHelper +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructors ... + XSCXOSCHelper() : XSCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XSCXOSCHelper() {} + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + XOSCInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + ArraySetAsSeries(atrBuffer, true); + ArraySetAsSeries(rviMainBuffer, true); + ArraySetAsSeries(rviSignalBuffer, true); + ArraySetAsSeries(bullPBuffer, true); + ArraySetAsSeries(bearPBuffer, true); + ArraySetAsSeries(volumeBuffer, true); + ArraySetAsSeries(rsiBuffer, true); + ArraySetAsSeries(cciBuffer, true); + ArraySetAsSeries(momentumBuffer, true); + ArraySetAsSeries(sarBuffer, true); + ArraySetAsSeries(macdMainBuffer, true); + ArraySetAsSeries(macdSignalBuffer, true); + ArraySetAsSeries(stochMainBuffer, true); + ArraySetAsSeries(stochSignalBuffer, true); + ArraySetAsSeries(stddevBuffer, true); + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.xosc", + // + // Inputs ... + // + // ATR ... + "", + mInputs.atrLength, + // + // RVI ... + "", + mInputs.rviLength, + // + // Bulls Power ... + "", + mInputs.bullpLength, + // + // Bears Power ... + "", + mInputs.bearpLength, + // + // Voluem ... + "", + mInputs.volumeAppliedTo, + // + // RSI ... + "", + mInputs.rsiLength, + mInputs.rsiAppliedTo, + // + // CCI ... + "", + mInputs.cciLength, + mInputs.cciAppliedTo, + // + // STDDev ... + "", + mInputs.stddevLength, + mInputs.stddevShift, + mInputs.stddevMethod, + mInputs.stddevAppliedTo, + // + // Momentum ... + "", + mInputs.momentumLength, + mInputs.momentumAppliedTo, + // + // SAR ... + "", + mInputs.sarStep, + mInputs.sarMaximum, + // + // MACD ... + "", + mInputs.macdFastLength, + mInputs.macdSlowLength, + mInputs.macdSignaLength, + mInputs.macdAppliedTo, + // + // Stochastic ... + "", + mInputs.stochKLength, + mInputs.stochDLength, + mInputs.stochSlowing, + mInputs.stochMaMethod, + mInputs.stochMode + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + XOSCInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + XOSCInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs); + } + + // + // Buffers ... + + // + // ATR ... + + // + double GetATR( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + return atrBuffer[barIndex]; + } + + // + // Copy Required Buffer ... + int CopyATR( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + atrBuffer, + buffer, + forceClean + // + ); + } + + // + // RVI ... + + // + double GetRVI( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + return rviMainBuffer[barIndex]; + } + + // + // Copy Required Buffer ... + int CopyRVI( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + rviMainBuffer, + buffer, + forceClean + // + ); + } + + // + double GetRVISignal( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + return rviSignalBuffer[barIndex]; + } + + // + // Copy Required Buffer ... + int CopyRVISignal( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + rviSignalBuffer, + buffer, + forceClean + // + ); + } + + // + // BULLP ... + + // + double GetBullPower( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + return bullPBuffer[barIndex]; + } + + // + // Copy Required Buffer ... + int CopyBullPower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + bullPBuffer, + buffer, + forceClean + // + ); + } + + // + // BEARP ... + + // + double GetBearPower( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + return bearPBuffer[barIndex]; + } + + // + // Copy Required Buffer ... + int CopyBearPower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + bearPBuffer, + buffer, + forceClean + // + ); + } + + // + // VOLUME ... + + // + double GetVolume( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + return volumeBuffer[barIndex]; + } + + // + // Copy Required Buffer ... + int CopyVolume( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + volumeBuffer, + buffer, + forceClean + // + ); + } + + // + // RSI ... + + // + double GetRSI( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + return rsiBuffer[barIndex]; + } + + // + // Copy Required Buffer ... + int CopyRSI( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + rsiBuffer, + buffer, + forceClean + // + ); + } + + // + // CCI ... + + // + double GetCCI( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + return cciBuffer[barIndex]; + } + + // + // Copy Required Buffer ... + int CopyCCI( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + cciBuffer, + buffer, + forceClean + // + ); + } + + // + // MOMENTUM ... + + // + double GetMomentum( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + return momentumBuffer[barIndex]; + } + + // + // Copy Required Buffer ... + int CopyMomentum( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + momentumBuffer, + buffer, + forceClean + // + ); + } + + // + // SAR ... + + // + double GetSAR( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + return sarBuffer[barIndex]; + } + + // + // Copy Required Buffer ... + int CopySAR( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + sarBuffer, + buffer, + forceClean + // + ); + } + + // + // STDDEV ... + + // + double GetSTDDEV( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + return stddevBuffer[barIndex]; + } + + // + // Copy Required Buffer ... + int CopySTDDEV( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + stddevBuffer, + buffer, + forceClean + // + ); + } + + // + // MACD ... + + // + double GetMACD( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + return macdMainBuffer[barIndex]; + } + + // + // Copy Required Buffer ... + int CopyMACD( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + macdMainBuffer, + buffer, + forceClean + // + ); + } + + // + double GetMACDSignal( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + return macdSignalBuffer[barIndex]; + } + + // + // Copy Required Buffer ... + int CopyMACDSignal( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + macdSignalBuffer, + buffer, + forceClean + // + ); + } + + // + // STOCH ... + + // + double GetSTOCH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + return stochMainBuffer[barIndex]; + } + + // + // Copy Required Buffer ... + int CopySTOCH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + stochMainBuffer, + buffer, + forceClean + // + ); + } + + // + double GetSTOCHSignal( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + return stochSignalBuffer[barIndex]; + } + + // + // Copy Required Buffer ... + int CopySTOCHSignal( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + stochSignalBuffer, + buffer, + forceClean + // + ); + } + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Props ... + XOSCInputs mInputs; // Inputs ... + + // + // Buffers ... + double atrBuffer[]; + double rviMainBuffer[]; + double rviSignalBuffer[]; + double bullPBuffer[]; + double bearPBuffer[]; + double volumeBuffer[]; + double rsiBuffer[]; + double cciBuffer[]; + double momentumBuffer[]; + double sarBuffer[]; + double macdMainBuffer[]; + double macdSignalBuffer[]; + double stochMainBuffer[]; + double stochSignalBuffer[]; + double stddevBuffer[]; + + // + // Tools ... + + // + // Calculate Values Until Now ... + void Calculate() + { + // + int totalBars = CountBars(); + int calculatedBars = CountCalculatedBars(); + + // + // ATR ... + CopyBuffer( + mHandler, + X_OSC_ATR_LINE, + 0, + totalBars, + atrBuffer + // + ); + + // + // BULLP ... + CopyBuffer( + mHandler, + X_OSC_BULL_POWER_LINE, + 0, + totalBars, + bullPBuffer + // + ); + + // + // BEARP ... + CopyBuffer( + mHandler, + X_OSC_BEAR_POWER_LINE, + 0, + totalBars, + bearPBuffer + // + ); + + // + // VOLUME ... + CopyBuffer( + mHandler, + X_OSC_VOLUME_LINE, + 0, + totalBars, + volumeBuffer + // + ); + + // + // RSI ... + CopyBuffer( + mHandler, + X_OSC_RSI_LINE, + 0, + totalBars, + rsiBuffer + // + ); + + // + // CCI ... + CopyBuffer( + mHandler, + X_OSC_CCI_LINE, + 0, + totalBars, + cciBuffer + // + ); + + // + // MOMENTUM ... + CopyBuffer( + mHandler, + X_OSC_MOMENTUM_LINE, + 0, + totalBars, + momentumBuffer + // + ); + + // + // SAR ... + CopyBuffer( + mHandler, + X_OSC_SAR_LINE, + 0, + totalBars, + sarBuffer + // + ); + + // + // STDDEV ... + CopyBuffer( + mHandler, + X_OSC_STDDEV_LINE, + 0, + totalBars, + stddevBuffer + // + ); + + // + // RVI ... + + // + // RVI Main ... + CopyBuffer( + mHandler, + X_OSC_RVI_MAIN_LINE, + 0, + totalBars, + rviMainBuffer + // + ); + + // + // RVI Signal ... + CopyBuffer( + mHandler, + X_OSC_RVI_SIGNAL_LINE, + 0, + totalBars, + rviSignalBuffer + // + ); + + // + // MACD ... + + // + // MACD Main ... + CopyBuffer( + mHandler, + X_OSC_MACD_MAIN_LINE, + 0, + totalBars, + macdMainBuffer + // + ); + + // + // MACD Signal ... + CopyBuffer( + mHandler, + X_OSC_MACD_SIGNAL_LINE, + 0, + totalBars, + macdSignalBuffer + // + ); + + // + // STOCH ... + + // + // STOCH Main ... + CopyBuffer( + mHandler, + X_OSC_STOCH_MAIN_LINE, + 0, + totalBars, + stochMainBuffer + // + ); + + // + // STOCH Signal ... + CopyBuffer( + mHandler, + X_OSC_STOCH_SIGNAL_LINE, + 0, + totalBars, + stochSignalBuffer + // + ); + } +}; + +// +// Tools ... diff --git a/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xpv.helper.ex5 b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xpv.helper.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..599abd081c6fc6c79bc02599c23b419249a2e391 GIT binary patch literal 5714 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 literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xpv.helper.mq5 b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xpv.helper.mq5 new file mode 100644 index 0000000..b78b183 --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xpv.helper.mq5 @@ -0,0 +1,1870 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCXPVHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.xhelper.class.mq5" + +// +// Definitions ... + +// +enum ENUM_XPV_BUFFERS +{ + // + // Peaks and Vales ... + XPV_PEAKS_LINE = 0, + XPV_VALES_LINE = 1, + // + // Support and Resistances ... + XPV_RESISTANCE_LINE = 2, + XPV_SUPPORT_LINE = 4, + // + // Fibonacci ... + XPV_FIB_1_LINE = 6, + XPV_FIB_2_LINE = 8, + XPV_FIB_3_LINE = 10, + XPV_FIB_4_LINE = 12, + XPV_FIB_5_LINE = 14, + // + // Short ... + XPV_SC_HH_LINE = 16, + XPV_SC_LL_LINE = 18, + // + // Medium ... + XPV_MC_HH_LINE = 20, + XPV_MC_LL_LINE = 22, + // + // Long ... + XPV_LC_HH_LINE = 24, + XPV_LC_LL_LINE = 26, + // + // Hind ... + XPV_HC_HH_LINE = 28, + XPV_HC_LL_LINE = 30, +}; + +// +// Input Models ... +struct XPVInputs +{ + // + // Props ... + + // + // Makret Cycles ... + + // + // Short ... + ENUM_X_PERIOD_METHOD scMethod; // How to Find Period + ENUM_TIMEFRAMES scPeriod; // Time Period + + // + // Medium ... + ENUM_X_PERIOD_METHOD mcMethod; // How to Find Period + ENUM_TIMEFRAMES mcPeriod; // Time Period + + // + // Long ... + ENUM_X_PERIOD_METHOD lcMethod; // How to Find Period + ENUM_TIMEFRAMES lcPeriod; // Time Period + + // + // Hind ... + ENUM_X_PERIOD_METHOD hcMethod; // How to Find Period + ENUM_TIMEFRAMES hcPeriod; // Time Period + + // + // Fibonacci ... + double fiboLevel1; // Fibio 1st Level + double fiboLevel2; // Fibio 2st Level + double fiboLevel3; // Fibio 3rd Level + double fiboLevel4; // Fibio 4th Level + double fiboLevel5; // Fibio 5th Level + + // + // Boundary Detection Modes ... + ENUM_SERIESMODE hhMode; // Highest High Calculation Method + ENUM_SERIESMODE llMode; // Lowest Low Calculation Method + + // + // Presentation ... + bool showPeaksAndVales; // Show Peaks and Vales + bool showLevels; // Show Levels + bool showConsolidations; // Show Consolidations + bool showFibo1Levels; // Show Fibo 1st Level + bool showFibo2Levels; // Show Fibo 2nd Level + bool showFibo3Levels; // Show Fibo 3rd Level + bool showFibo4Levels; // Show Fibo 4th Level + bool showFibo5Levels; // Show Fibo 5th Level + + // + // Constructor(s) ... + XPVInputs() + { + // + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + // Makret Cycles ... + + // + // Short ... + scMethod = X_PERIOD_NOTHING; + scPeriod = NULL; + + // + // Medium ... + mcMethod = X_PERIOD_NOTHING; + mcPeriod = NULL; + + // + // Long ... + lcMethod = X_PERIOD_NOTHING; + lcPeriod = NULL; + + // + // Hind ... + hcMethod = X_PERIOD_NOTHING; + hcPeriod = NULL; + + // + // Fibonacci ... + fiboLevel1 = 0; + fiboLevel2 = 0; + fiboLevel3 = 0; + fiboLevel4 = 0; + fiboLevel5 = 0; + + // + // Boundary Detection Modes ... + hhMode = MODE_HIGH; + llMode = MODE_LOW; + + // + // Presentation ... + showPeaksAndVales = false; + showLevels = false; + showConsolidations = false; + showFibo1Levels = false; + showFibo2Levels = false; + showFibo3Levels = false; + showFibo4Levels = false; + showFibo5Levels = false; + } + + // + // Default ... + void Default() + { + // + // Makret Cycles ... + + // + // Short ... + scMethod = X_PERIOD_AUTO; + scPeriod = NULL; + + // + // Medium ... + mcMethod = X_PERIOD_AUTO; + mcPeriod = NULL; + + // + // Long ... + lcMethod = X_PERIOD_AUTO; + lcPeriod = NULL; + + // + // Hind ... + hcMethod = X_PERIOD_AUTO; + hcPeriod = NULL; + + // + // Fibonacci ... + fiboLevel1 = 0.236; + fiboLevel2 = 0.382; + fiboLevel3 = 0.5; + fiboLevel4 = 0.618; + fiboLevel5 = 0.764; + + // + // Boundary Detection Modes ... + hhMode = MODE_HIGH; + llMode = MODE_LOW; + + // + // Presentation ... + showPeaksAndVales = true; + showLevels = false; + showConsolidations = false; + showFibo1Levels = true; + showFibo2Levels = true; + showFibo3Levels = true; + showFibo4Levels = true; + showFibo5Levels = true; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsValid(scMethod, scPeriod) && + IsValid(mcMethod, mcPeriod) && + IsValid(lcMethod, lcPeriod) && + IsValid(hcMethod, hcPeriod) + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(result, 0); + + // + return result; + } +}; + +// +// Class ... +class XSCXPVHelper : public XSCBaseHelper +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructors ... + XSCXPVHelper() : XSCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XSCXPVHelper() {} + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + XPVInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + ArraySetAsSeries(peaksBuffer, true); + ArraySetAsSeries(valesBuffer, true); + ArraySetAsSeries(resistanceBuffer, true); + ArraySetAsSeries(supportBuffer, true); + ArraySetAsSeries(fib1Buffer, true); + ArraySetAsSeries(fib2Buffer, true); + ArraySetAsSeries(fib3Buffer, true); + ArraySetAsSeries(fib4Buffer, true); + ArraySetAsSeries(fib5Buffer, true); + ArraySetAsSeries(scHHBuffer, true); + ArraySetAsSeries(scLLBuffer, true); + ArraySetAsSeries(mcHHBuffer, true); + ArraySetAsSeries(mcLLBuffer, true); + ArraySetAsSeries(lcHHBuffer, true); + ArraySetAsSeries(lcLLBuffer, true); + ArraySetAsSeries(hcHHBuffer, true); + ArraySetAsSeries(hcLLBuffer, true); + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.xpv", + // + // Inputs ... + // + // Makret Cycles ... + "", + // + // Short ... + "", + mInputs.scMethod, // How to Find Period + mInputs.scPeriod, // Time Period + // + // Medium ... + "", + mInputs.mcMethod, // How to Find Period + mInputs.mcPeriod, // Time Period + // + // Long ... + "", + mInputs.lcMethod, // How to Find Period + mInputs.lcPeriod, // Time Period + // + // Hind ... + "", + mInputs.hcMethod, // How to Find Period + mInputs.hcPeriod, // Time Period + // + // Fibonacci ... + "", + mInputs.fiboLevel1, // Fibio 1st Level + mInputs.fiboLevel2, // Fibio 2st Level + mInputs.fiboLevel3, // Fibio 3rd Level + mInputs.fiboLevel4, // Fibio 4th Level + mInputs.fiboLevel5, // Fibio 5th Level + // + // Boundary Detection Modes ... + "", + mInputs.hhMode, // Highest High Calculation Method + mInputs.llMode, // Lowest Low Calculation Method + // + // Presentation ... + "", + mInputs.showPeaksAndVales, // Show Peaks and Vales + mInputs.showLevels, // Show Levels + mInputs.showConsolidations, // Show Consolidations + mInputs.showFibo1Levels, // Show Fibo 1st Level + mInputs.showFibo2Levels, // Show Fibo 2nd Level + mInputs.showFibo3Levels, // Show Fibo 3rd Level + mInputs.showFibo4Levels, // Show Fibo 4th Level + mInputs.showFibo5Levels // Show Fibo 5th Level + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + XPVInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + XPVInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Buffers ... + + // + // Peaks ... + + // + double GetPeak( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(peaksBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return peaksBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyPeak( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + peaksBuffer, + buffer, + forceClean + // + ); + } + + // + bool IsSamePeak( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + peaksBuffer, + verifier, + barIndex // + ); + } + + // + // Vales ... + + // + double GetVale( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(valesBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return valesBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyVale( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + valesBuffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameVale( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + valesBuffer, + verifier, + barIndex // + ); + } + + // + // Resistance ... + + // + double GetResistance( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(resistanceBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return resistanceBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyResistance( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + resistanceBuffer, + buffer, + forceClean + // + ); + } + + // + // Support ... + + // + double GetSupport( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(supportBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return supportBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopySupport( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + supportBuffer, + buffer, + forceClean + // + ); + } + + // + // Fibonacci ... + + // + // Level 1 ... + + // + double GetFib1( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(fib1Buffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fib1Buffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyFib1( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + fib1Buffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameFib1( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + fib1Buffer, + verifier, + barIndex // + ); + } + + // + // Level 2 ... + + // + double GetFib2( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(fib2Buffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fib2Buffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyFib2( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + fib2Buffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameFib2( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + fib2Buffer, + verifier, + barIndex // + ); + } + + // + // Level 3 ... + + // + double GetFib3( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(fib3Buffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fib3Buffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyFib3( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + fib3Buffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameFib3( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + fib3Buffer, + verifier, + barIndex // + ); + } + + // + // Level 4 ... + + // + double GetFib4( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(fib4Buffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fib4Buffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyFib4( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + fib4Buffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameFib4( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + fib4Buffer, + verifier, + barIndex // + ); + } + + // + // Level 5 ... + + // + double GetFib5( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(fib5Buffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fib5Buffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyFib5( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + fib5Buffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameFib5( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + fib5Buffer, + verifier, + barIndex // + ); + } + + // + // Cycles ... + + // + // Short ... + + // + // HH ... + + // + double GetSCHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(scHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return scHHBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopySCHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + scHHBuffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameSCHH( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + scHHBuffer, + verifier, + barIndex // + ); + } + + // + // LL ... + + // + double GetSCLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(scLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return scLLBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopySCLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + scLLBuffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameSCLL( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + scLLBuffer, + verifier, + barIndex // + ); + } + + // + // Medium ... + + // + // HH ... + + // + double GetMCHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(mcHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return mcHHBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyMCHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + mcHHBuffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameMCHH( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + mcHHBuffer, + verifier, + barIndex // + ); + } + + // + // LL ... + + // + double GetMCLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(mcLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return mcLLBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyMCLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + mcLLBuffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameMCLL( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + mcLLBuffer, + verifier, + barIndex // + ); + } + + // + // Long ... + + // + // HH ... + + // + double GetLCHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(lcHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return lcHHBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyLCHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + lcHHBuffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameLCHH( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + lcHHBuffer, + verifier, + barIndex // + ); + } + + // + // LL ... + + // + double GetLCLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(lcLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return lcLLBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyLCLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + lcLLBuffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameLCLL( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + lcLLBuffer, + verifier, + barIndex // + ); + } + + // + // Hind ... + + // + // HH ... + + // + double GetHCHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(hcHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hcHHBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyHCHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + hcHHBuffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameHCHH( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + hcHHBuffer, + verifier, + barIndex // + ); + } + + // + // LL ... + + // + double GetHCLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(hcLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hcLLBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyHCLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + hcLLBuffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameHCLL( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + hcLLBuffer, + verifier, + barIndex // + ); + } + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Props ... + XPVInputs mInputs; // Inputs ... + + // + // Buffers ... + double peaksBuffer[]; + double valesBuffer[]; + double resistanceBuffer[]; + double supportBuffer[]; + double fib1Buffer[]; + double fib2Buffer[]; + double fib3Buffer[]; + double fib4Buffer[]; + double fib5Buffer[]; + double scHHBuffer[]; + double scLLBuffer[]; + double mcHHBuffer[]; + double mcLLBuffer[]; + double lcHHBuffer[]; + double lcLLBuffer[]; + double hcHHBuffer[]; + double hcLLBuffer[]; + + // + // Tools ... + + // + // Calculate Values Until Now ... + void Calculate() + { + // + int totalBars = CountBars(); + + // + // Peaks and Vales ... + + // + // Peaks Buffer ... + CopyBuffer( + mHandler, + XPV_PEAKS_LINE, + 0, + totalBars, + peaksBuffer + // + ); + + // + // Vales Buffer ... + CopyBuffer( + mHandler, + XPV_VALES_LINE, + 0, + totalBars, + valesBuffer + // + ); + + // + // Support and Resistances ... + + // + // Resistances Buffer ... + CopyBuffer( + mHandler, + XPV_RESISTANCE_LINE, + 0, + totalBars, + resistanceBuffer + // + ); + + // + // Supports Buffer ... + CopyBuffer( + mHandler, + XPV_SUPPORT_LINE, + 0, + totalBars, + supportBuffer + // + ); + + // + // Fibonacci ... + + // + // Level 1 Buffer ... + CopyBuffer( + mHandler, + XPV_FIB_1_LINE, + 0, + totalBars, + fib1Buffer + // + ); + + // + // Level 2 Buffer ... + CopyBuffer( + mHandler, + XPV_FIB_2_LINE, + 0, + totalBars, + fib2Buffer + // + ); + + // + // Level 3 Buffer ... + CopyBuffer( + mHandler, + XPV_FIB_3_LINE, + 0, + totalBars, + fib3Buffer + // + ); + + // + // Level 4 Buffer ... + CopyBuffer( + mHandler, + XPV_FIB_4_LINE, + 0, + totalBars, + fib4Buffer + // + ); + + // + // Level 5 Buffer ... + CopyBuffer( + mHandler, + XPV_FIB_5_LINE, + 0, + totalBars, + fib5Buffer + // + ); + + // + // Cycles ... + + // + // Short ... + + // + // HH ... + CopyBuffer( + mHandler, + XPV_SC_HH_LINE, + 0, + totalBars, + scHHBuffer + // + ); + + // + // LL ... + CopyBuffer( + mHandler, + XPV_SC_LL_LINE, + 0, + totalBars, + scLLBuffer + // + ); + + // + // Medium ... + + // + // HH ... + CopyBuffer( + mHandler, + XPV_MC_HH_LINE, + 0, + totalBars, + mcHHBuffer + // + ); + + // + // LL ... + CopyBuffer( + mHandler, + XPV_MC_LL_LINE, + 0, + totalBars, + mcLLBuffer + // + ); + + // + // Long ... + + // + // HH ... + CopyBuffer( + mHandler, + XPV_LC_HH_LINE, + 0, + totalBars, + lcHHBuffer + // + ); + + // + // LL ... + CopyBuffer( + mHandler, + XPV_LC_LL_LINE, + 0, + totalBars, + lcLLBuffer + // + ); + + // + // Hind ... + + // + // HH ... + CopyBuffer( + mHandler, + XPV_HC_HH_LINE, + 0, + totalBars, + hcHHBuffer + // + ); + + // + // LL ... + CopyBuffer( + mHandler, + XPV_HC_LL_LINE, + 0, + totalBars, + hcLLBuffer + // + ); + } +}; + +// +// Tools ... \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xsslc.helper.ex5 b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xsslc.helper.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..7714bbaa49bd080c9b7ee36d52c7bef7db4cf03f GIT binary patch literal 5652 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 a8@sYyJQAkxDG14Idhab(mp`f#O#Tmo7p2nx literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xsslc.helper.mq5 b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xsslc.helper.mq5 new file mode 100644 index 0000000..6198876 --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xsslc.helper.mq5 @@ -0,0 +1,408 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCXSSLCHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.xhelper.class.mq5" + +// +// Definitions ... + +// +enum ENUM_XSSLC_BUFFERS +{ + XSSLC_UP_LINE = 0, + XSSLC_DOWN_LINE = 1, +}; + +// +// Input Models ... +struct XSSLCInputs +{ + // + // Props ... + + // + // Market ... + int length; // Length + + // + // Calculation ... + ENUM_MA_METHOD method; // Method + ENUM_APPLIED_PRICE upAppliedTo; // Up Applied To + ENUM_APPLIED_PRICE downAppliedTo; // Down Applied To + + // + // Presentation ... + bool showUp; // Show Up + bool showDown; // Show Down + + // + // Constructor(s) ... + XSSLCInputs() + { + // + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + // Market ... + length = 0; + + // + // Calculation ... + method = MODE_SMA; + upAppliedTo = PRICE_HIGH; + downAppliedTo = PRICE_LOW; + + // + // Presentation ... + showUp = false; + showDown = false; + } + + // + // Default ... + void Default() + { + // + // Market ... + length = 36; + + // + // Calculation ... + method = MODE_SMA; + upAppliedTo = PRICE_HIGH; + downAppliedTo = PRICE_LOW; + + // + // Presentation ... + showUp = true; + showDown = true; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + false + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(0, 0); + + // + return result; + } +}; + +// +// Class ... +class XSCXSSLCHelper : public XSCBaseHelper +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructors ... + XSCXSSLCHelper() : XSCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XSCXSSLCHelper() {} + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + XSSLCInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + ArraySetAsSeries(upBuffer, true); + ArraySetAsSeries(downBuffer, true); + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.xsslc", + // + // Inputs ... + // + // Market ... + "", + mInputs.length, // Length + // + // Calculation ... + "", + mInputs.method, // Method + mInputs.upAppliedTo, // Up Applied To + mInputs.downAppliedTo, // Down Applied To + // + // Presentation ... + "", + mInputs.showUp, // Show Up + mInputs.showDown // Show Down + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + XSSLCInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + XSSLCInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Buffers ... + + // + // Up ... + + // + double GetUp( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(upBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return upBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyUp( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + upBuffer, + buffer, + forceClean + // + ); + } + + // + // Down ... + + // + double GetDown( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(downBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return downBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyDown( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + downBuffer, + buffer, + forceClean + // + ); + } + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Props ... + XSSLCInputs mInputs; // Inputs ... + + // + // Buffers ... + double upBuffer[]; + double downBuffer[]; + + // + // Tools ... + + // + // Calculate Values Until Now ... + void Calculate() + { + // + int totalBars = CountBars(); + + // + // Up ... + CopyBuffer( + mHandler, + XSSLC_UP_LINE, + 0, + totalBars, + upBuffer + // + ); + + // + // Down ... + CopyBuffer( + mHandler, + XSSLC_DOWN_LINE, + 0, + totalBars, + downBuffer + // + ); + } +}; + +// +// Tools ... \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xstr.helper.ex5 b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xstr.helper.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..d331aeb4d48bf4514574ef5adda52fbd00a39e6b GIT binary patch literal 5368 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%0A{!RTs%9+Qq2z=K5x|)T9&R=yAyL~h$R(2_ zeZ%c??hmp%`4Av|h3MzELSaImHVFAFP6xs3oTy#>H6ck#Qsd0XoqdL{Hz&}Tr2Dfk zdlM+2Jo2|^ugEmdxC8!|qv|5(5GqRHuhp5DrNd#Sc4usIN2OZRanJDalDMXAfz?kq zytF_V=5`7eJ}7Pxw(PiDN?Mv~%5x9+Q7$&t>r+LB`uKQxH=(lXTcJvlY2@eS+`MN@ zJo?fbiR6x=Nhfitr`@^se+#vS@d{o}E`*AYv90E>O=eQ23CT$snj*se>TX;H`4h;n z#l1=BBtJb?{*hJE(3LikIW{cq(w8T`|!$GR^o3fKm3< zzKnYc4soLKA9kL212C7=-%$=^Yw-3^`maF^v2|<=JVYITGdinrC{dxOuB~HJi-|P- znkDPgakSV&3%KTiUyZ+up*2qAb2!+}$@P4w$fp)JELvSCrMlZmhcRoo>7*3+#arf% z$5vXMK$9cQXsnTBAm3`U)V_Us@XHu(v5Ie*g`Q7By@|>=lN1jP8BzuY&+F|fd?hUW zN;6aaoJWnI9#GbNU(V)Ux$hMnBZ@+vG^uBMnuCLuE<;oW)nSp}6mpt*DdD4ql0ixb zz@d(QEc5wT!(|+JZmL*4tZ$^XTh21z9U|=r(*Dy{^rdyCZejchVbo|kmnheDu}ojE J0Q&p${{iH8N74WQ literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xstr.helper.mq5 b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xstr.helper.mq5 new file mode 100644 index 0000000..009f3ba --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xstr.helper.mq5 @@ -0,0 +1,421 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCXSTRHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +#include "../Classes/x-saherelm.xhelper.class.mq5" + +// +// Definitions ... + +// +enum ENUM_XSTR_BUFFERS +{ + X_STR_TREND_LINE = 0, + X_STR_STATE_LINE = 5, +}; + +// +enum ENUM_XSTR_TREND_STATES +{ + X_STR_BULLISH = 1, // Bullish + X_STR_BEARISH = -1, // Bearish +}; + +// +// Input Models ... +struct XSTRInputs +{ + // + // Props ... + + // + // Market ... + int length; // Length + double multiplier; // Multiplier + ENUM_APPLIED_PRICE appliedTo; // Applied To + + // + // Presentation ... + bool showTrends; // Show Trends + bool fillTrends; // Fill Trends + + // + // Constructor(s) ... + XSTRInputs() + { + // + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + length = 0; + multiplier = 0; + appliedTo = PRICE_CLOSE; + // + showTrends = false; + fillTrends = false; + } + + // + // Default ... + void Default() + { + // + length = 14; + multiplier = 3.5; + appliedTo = PRICE_MEDIAN; + // + showTrends = true; + fillTrends = false; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + length > 0 && + multiplier > 0 + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = length; + + // + return result; + } +}; + +// +// Class ... +class XSCXSTRHelper : public XSCBaseHelper +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructors ... + XSCXSTRHelper() : XSCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XSCXSTRHelper() {} + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + XSTRInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + ArraySetAsSeries(trendBuffer, true); + ArraySetAsSeries(stateBuffer, true); + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.xstr", + // + // Inputs ... + // + // ATR ... + "", + mInputs.length, // Length + mInputs.multiplier, // Multiplier + mInputs.appliedTo, // Applied To + // + // Presentation ... + "", + mInputs.showTrends, // Show Trends + mInputs.fillTrends // Fill Trends + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + XSTRInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + XSTRInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs); + } + + // + // Buffers ... + + // + // Trend ... + + // + double GetTrend( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + return trendBuffer[barIndex]; + } + + // + // Copy Required Buffer ... + int CopyTrend( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + trendBuffer, + buffer, + forceClean + // + ); + } + + // + // State ... + + // + ENUM_XSTR_TREND_STATES GetState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + return (ENUM_XSTR_TREND_STATES)((int)stateBuffer[barIndex]); + } + + // + // Copy Required Buffer ... + int CopyState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + stateBuffer, + buffer, + forceClean + // + ); + } + + // + // Tools ... + + // + ENUM_XSTR_TREND_STATES ToState(double state) + { + return (ENUM_XSTR_TREND_STATES)((int)state); + } + + // + bool IsBullish(double state) + { + // + bool result = false; + + // + result = + // + ToState(state) == X_STR_BULLISH; + // + ; + + // + return result; + } + + // + bool IsBearish(double state) + { + // + bool result = false; + + // + result = + // + ToState(state) == X_STR_BEARISH; + // + ; + + // + return result; + } + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Props ... + XSTRInputs mInputs; // Inputs ... + + // + // Buffers ... + double trendBuffer[]; + double stateBuffer[]; + + // + // Tools ... + + // + // Calculate Values Until Now ... + void Calculate() + { + // + int totalBars = CountBars(); + int calculatedBars = CountCalculatedBars(); + + // + // Trend ... + CopyBuffer( + mHandler, + X_STR_TREND_LINE, + 0, + totalBars, + trendBuffer + // + ); + + // + // State ... + CopyBuffer( + mHandler, + X_STR_STATE_LINE, + 0, + totalBars, + stateBuffer + // + ); + } +}; + +// +// Tools ... diff --git a/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xtd.helper.ex5 b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xtd.helper.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..e0cfd1ea99656165cbd0af906104d46ebd3966d7 GIT binary patch literal 5978 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 literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xtd.helper.mq5 b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xtd.helper.mq5 new file mode 100644 index 0000000..488e7d6 --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xtd.helper.mq5 @@ -0,0 +1,458 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCXTDHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.xhelper.class.mq5" + +// +// Definitions ... + +// +enum ENUM_XTD_BUFFERS +{ + XTD_BULLISH_LINE = 0, + XTD_BEARISH_LINE = 1, + XTD_SIGNAL_LINE = 2, +}; + +// +// Input Models ... +struct XTDInputs +{ + // + // Props ... + // + int length; // Market Length + bool drawCrosses; // Draw Cross Arrows + + // + // Bullish ... + uchar bullishArrowCode; // Cross Over Arrow Code + color bullishArrowColor; // Cross Over Arrow Color + + // + // Bearish ... + uchar bearishArrowCode; // Cross Under Arrow Code + color bearishArrowColor; // Cross Under Arrow Color + + // + // Constructor(s) ... + XTDInputs() + { + // + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + length = 0; + drawCrosses = false; + + // + // Bullish ... + bullishArrowCode = 228; + bullishArrowColor = CLR_NONE; + + // + // Bearish ... + bearishArrowCode = 230; + bearishArrowColor = CLR_NONE; + } + + // + // Default ... + void Default() + { + // + length = 14; + drawCrosses = false; + + // + // Bullish ... + bullishArrowCode = 228; + bullishArrowColor = CLR_NONE; + + // + // Bearish ... + bearishArrowCode = 230; + bearishArrowColor = CLR_NONE; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + length >= 2 + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(result, length); + + // + return result; + } +}; + +// +// Class ... +class XSCXTDHelper : public XSCBaseHelper +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructors ... + XSCXTDHelper() : XSCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XSCXTDHelper() {} + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + XTDInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + ArraySetAsSeries(bullishBuffer, true); + ArraySetAsSeries(bearishBuffer, true); + ArraySetAsSeries(signalBuffer, true); + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.xtd", + // + // Inputs ... + // + mInputs.length, // Market Length + mInputs.drawCrosses, // Draw Cross Arrows + // + // Bullish ... + mInputs.bullishArrowCode, // Cross Over Arrow Code + mInputs.bullishArrowColor, // Cross Over Arrow Color + // + // Bearish ... + mInputs.bearishArrowCode, // Cross Under Arrow Code + mInputs.bearishArrowColor // Cross Under Arrow Color + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + XTDInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + XTDInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Buffers ... + + // + double GetBullish( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(bullishBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return bullishBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyBullish( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + bullishBuffer, + buffer, + forceClean + // + ); + } + + // + double GetBearish( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(bearishBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return bearishBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyBearish( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + bearishBuffer, + buffer, + forceClean + // + ); + } + + // + double GetSignal( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(signalBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return signalBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopySignal( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + signalBuffer, + buffer, + forceClean + // + ); + } + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Props ... + XTDInputs mInputs; // Inputs ... + + // + // Buffers ... + double bullishBuffer[]; + double bearishBuffer[]; + double signalBuffer[]; + + // + // Tools ... + + // + // Calculate Values Until Now ... + void Calculate() + { + // + int totalBars = CountBars(); + + // + // Bullish ... + CopyBuffer( + mHandler, + XTD_BULLISH_LINE, + 0, + totalBars, + bullishBuffer + // + ); + + // + // Bearish ... + CopyBuffer( + mHandler, + XTD_BEARISH_LINE, + 0, + totalBars, + bearishBuffer + // + ); + + // + // Signal ... + CopyBuffer( + mHandler, + XTD_SIGNAL_LINE, + 0, + totalBars, + signalBuffer + // + ); + } +}; + +// +// Tools ... \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xtm.helper.ex5 b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xtm.helper.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..e907fd440f411d8c8c0aa998e9a02f67e8be93a0 GIT binary patch literal 5424 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 N`Hl{z;GWD~_CHu(Srq^P literal 0 HcmV?d00001 diff --git a/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xtm.helper.mq5 b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xtm.helper.mq5 new file mode 100644 index 0000000..a55a04b --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xtm.helper.mq5 @@ -0,0 +1,310 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCXTMHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.xhelper.class.mq5" + +// +// Definitions ... + +// +enum ENUM_XTM_BUFFERS +{ + XTM_MAIN_LINE = 0 +}; + +// +// Input Models ... +struct XTMInputs +{ + // + // Props ... + // + // Market ... + int maPeriod; // Period + int maShift; // Shift + ENUM_MA_METHOD maMethod; // Method + ENUM_APPLIED_PRICE maAppliedTo; // Applied To + // + // Presentation ... + bool showLine; // Show Line + + // + // Constructor(s) ... + XTMInputs() + { + // + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + maShift = 0; + maPeriod = 0; + showLine = false; + maMethod = MODE_SMA; + maAppliedTo = PRICE_CLOSE; + } + + // + // Default ... + void Default() + { + // + maShift = 0; + maPeriod = 14; + showLine = true; + maMethod = MODE_SMA; + maAppliedTo = PRICE_CLOSE; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + maPeriod >= 2 + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(result, maPeriod); + + // + return result; + } +}; + +// +// Class ... +class XSCXTMHelper : public XSCBaseHelper +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructors ... + XSCXTMHelper() : XSCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XSCXTMHelper() {} + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + XTMInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + ArraySetAsSeries(mainBuffer, true); + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.xtm", + // + // Inputs ... + // + // Market ... + "", + mInputs.maPeriod, // Period + mInputs.maShift, // Shift + mInputs.maMethod, // Method + mInputs.maAppliedTo, // Applied To + // + // Presentation ... + "", + mInputs.showLine // Show Line + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + XTMInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + XTMInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Buffers ... + + // + double GetMain( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(mainBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return mainBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyMain( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + mainBuffer, + buffer, + forceClean + // + ); + } + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Props ... + XTMInputs mInputs; // Inputs ... + + // + // Buffers ... + double mainBuffer[]; + + // + // Tools ... + + // + // Calculate Values Until Now ... + void Calculate() + { + // + int totalBars = CountBars(); + + // + // Main Buffer ... + CopyBuffer( + mHandler, + XTM_MAIN_LINE, + 0, + totalBars, + mainBuffer + // + ); + } +}; + +// +// Tools ... \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xzg.helper.ex5 b/MQLTestWorkspace/BKPS/14030316/Helpers/x-saherelm.xzg.helper.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..de57867595493626111bb568fdb881b962a402dc GIT binary patch literal 5796 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 0 && + deviation > 0 && + backStep > 0 + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(backStep, depth); + + // + return result; + } +}; + +// +// Class ... +class XSCXZGHelper : public XSCBaseHelper +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructors ... + XSCXZGHelper() : XSCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XSCXZGHelper() {} + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + XZGInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + ArraySetAsSeries(mainBuffer, true); + ArraySetAsSeries(PeaksAndValesBuffer, true); + ArraySetAsSeries(highsBuffer, true); + ArraySetAsSeries(lowsBuffer, true); + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.xzg", + // + // Inputs ... + // + // Market ... + "", + mInputs.depth, // Depth + mInputs.deviation, // Deviation + mInputs.backStep, // Back Step + mInputs.mode, // Mode + // + // Presentation ... + "", + mInputs.showZigZag, // Show ZigZag + mInputs.showPeaksAndVales // Show Peaks and Vales + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + XZGInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + XZGInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Buffers ... + + // + double GetMain( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(mainBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return mainBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyMain( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + mainBuffer, + buffer, + forceClean + // + ); + } + + // + double GetPeaksAndVales( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(PeaksAndValesBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return PeaksAndValesBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyPeaksAndVales( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + PeaksAndValesBuffer, + buffer, + forceClean + // + ); + } + + // + double GetHigh( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(highsBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return highsBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyHigh( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + highsBuffer, + buffer, + forceClean + // + ); + } + + // + double GetLow( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(lowsBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return lowsBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyLow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + lowsBuffer, + buffer, + forceClean + // + ); + } + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Props ... + XZGInputs mInputs; // Inputs ... + + // + // Buffers ... + double mainBuffer[]; + double PeaksAndValesBuffer[]; + double highsBuffer[]; + double lowsBuffer[]; + + // + // Tools ... + + // + // Calculate Values Until Now ... + void Calculate() + { + // + int totalBars = CountBars(); + + // + // Main Buffer ... + CopyBuffer( + mHandler, + XZG_MAIN_LINE, + 0, + totalBars, + mainBuffer + // + ); + + // + // Peaks and Vales Buffer ... + CopyBuffer( + mHandler, + XZG_PEAKSANDVALES_LINE, + 0, + totalBars, + PeaksAndValesBuffer + // + ); + + // + // Highs Buffer ... + CopyBuffer( + mHandler, + XZG_HIGHS_LINE, + 0, + totalBars, + highsBuffer + // + ); + + // + // Lows Buffer ... + CopyBuffer( + mHandler, + XZG_LOWS_LINE, + 0, + totalBars, + lowsBuffer + // + ); + } +}; + +// +// Tools ... \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xama.mq5 b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xama.mq5 new file mode 100644 index 0000000..714a25d --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xama.mq5 @@ -0,0 +1,348 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XAMA Indicator +// --------------------------------------------- +// Name: XAMA +// Description: Trend Magic Indicator ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XAMA Indicator" +#property strict + +// +// Constants ... + +#define ShortName "XAMA" + +// +// Indicator States ... +enum ENUM_X_XAMA_STATES +{ + X_XAMA_BULLISH = 1, + X_XAMA_BEARISH = -1, + X_XAMA_NEUTURAL = 0, +}; + +// +// Inputs ... + +// +// Market ... +input group "Market"; +input int length = 18; // Period +input int fastEMA = 2; // Fast EMA Period +input int slowEMA = 30; // Slow EMA Period +input int maShift = 0; // Shift +input ENUM_APPLIED_PRICE appliedTo = PRICE_CLOSE; // Applied To + +// +// Presentation ... +input group "Presentation"; +input bool showLine = true; // Show Line + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Buffers ... +// +#property indicator_chart_window + +// +#property indicator_buffers 3 +#property indicator_plots 1 + +// +// maBuffer ... +#define maBufferIndex 0 +#define maColorBufferIndex 1 +#define stateBufferIndex 2 + +double maBuffer[]; +double maColorBuffer[]; +double stateBuffer[]; + +#property indicator_label1 "XAMA" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 clrLime, clrGray, clrRed, CLR_NONE +#property indicator_style1 STYLE_SOLID +#property indicator_width1 1 +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +int maHandler = INVALID_HANDLE; +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initializing MA Handler ... + maHandler = iAMA( + _Symbol, + _Period, + length, + fastEMA, + slowEMA, + maShift, + appliedTo); + if (maHandler == INVALID_HANDLE) + { + // + return INIT_FAILED; + } + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Here we can handle De Initialization Reasons ... + IndicatorRelease(maHandler); +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + int maxLength = MathMax(fastEMA, slowEMA); + maxLength = MathMax(maxLength, length); + + // + // Check Calculated Bars ... + int maCalculatedBars = BarsCalculated(maHandler); + if (maCalculatedBars < maxLength) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + int copiedMas = CopyBuffer(maHandler, 0, 0, limit, maBuffer); + if (copiedMas <= 0) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + // Do Buffers Calculation ... + CalculateBuffers(i); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + // Validate Args ... + if (length >= 2) + { + result = true; + } + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + string maBufferLabel = "XAMA " + "(" + (string)length + ")"; + + // + // Ma Buffer ... + ArraySetAsSeries(maBuffer, true); + SetIndexBuffer(maBufferIndex, maBuffer, INDICATOR_DATA); + PlotIndexSetString(maBufferIndex, PLOT_LABEL, maBufferLabel); + + // + // Ma Color Buffer ... + ArraySetAsSeries(maColorBuffer, true); + SetIndexBuffer(maColorBufferIndex, maColorBuffer, INDICATOR_COLOR_INDEX); + + // + // State Buffer ... + ArraySetAsSeries(stateBuffer, true); + SetIndexBuffer(stateBufferIndex, stateBuffer, INDICATOR_CALCULATIONS); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + string indicatorShortName = ""; + StringConcatenate(indicatorShortName, ShortName, " ", "(", length, ")"); + + // + IndicatorSetString(INDICATOR_SHORTNAME, indicatorShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers(int bar_index) +{ + // + // Requirements ... + XOHCL candle; + candle.Init( + _Symbol, + _Period, + bar_index); + + // + double maValue = maBuffer[bar_index]; + + // + double lineColorIndex = + maValue < candle.low ? 0 : maValue > candle.high ? 2 + : 1; + + // + // Define State Value ... + // lineColorIndex == 0 => Bullish => 1; + // lineColorIndex == 1 => Neutural => 0; + // lineColorIndex == 2 => Bearish => -1; + double stateValue = + lineColorIndex == 0 ? X_XAMA_BULLISH : lineColorIndex == 2 ? X_XAMA_BEARISH + : X_XAMA_NEUTURAL; + + // + // Set Ma Buffer Color Index ... + maColorBuffer[bar_index] = showLine ? lineColorIndex : 3; + + // + // Set State Buffer Value ... + stateBuffer[bar_index] = stateValue; +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xcc.mq5 b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xcc.mq5 new file mode 100644 index 0000000..2e11f1c --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xcc.mq5 @@ -0,0 +1,458 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Candle Styles +// --------------------------------------------------- +// Name: XCC +// Description: Candle Styles ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XCC Indicator" +#property strict + +// +// START Constants ... +// + +// +// Indicator Short Name ... +#define ShortName "XCC" + +// +// Holds an SnapShot of Charts Configuration ... +struct XChartStyle +{ + // + // chart's ID ... + long chartId; + // + // chart's mode ... + ENUM_CHART_MODE mode; + // + // show bid line ... + bool showBidLine; + // + // show ask line ... + bool showAskLine; + // + // show grids on chart ... + bool showGrid; + // + // show volumes ... + bool showVolumes; + // + // Displaying trade levels in the chart (levels of open positions, Stop Loss, Take Profit and pending orders) ... + bool showTradeLevels; + // + // chart autoscroll ... + bool autoScroll; + // + // chart quick navigation state ... + bool quickNavigation; + // + // chart's foreground color ... + color foreGroundColor; + // + // chart's background color ... + color backGroundColor; + // + // Up Color ... + color upColor; + // + // Down Color ... + color downColor; + // + // Bullish color ... + color bullishColor; + // + // Bearish color ... + color bearishColor; + // + // grid color ... + color gridColor; + // + // bid line color ... + color bidLineColor; + // + // ask line color ... + color askLineColor; + // + // line mode and doji candlestick color ... + color lineColor; + // + // Color of stop order levels (Stop Loss and Take Profit) ... + color stopColor; + // + // volumes color ... + color volumesColor; +}; + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input group "Chart Style"; +input ENUM_CHART_MODE mode = CHART_CANDLES; // Mode +input color upColor = clrLime; // Up Color +input color downColor = clrRed; // Down Color +input color lineColor = clrLime; // Line mode and Doji candlestick Color +input color bearishColor = clrRed; // Bullish Color +input color bullishColor = clrLime; // Bearish Color +input color volumesColor = clrGreen; // Volumes Color + +// +input group "Presentation"; +input bool showCandles = true; // Show Candles + +// +// END Inputs ... +// + +// +// START Includes and Imports ... +// + +// +// Includes Draw Library ... +#include "../Libraries/x-saherelm.draw.lib.mq5" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes and Imports ... +// + +// +// START Buffers ... +// + +// +#property indicator_chart_window + +// +#property indicator_buffers 0 +#property indicator_plots 0 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int maxLength; + +// +XChartStyle chartStyle; +XChartStyle clearStyle; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + drawPrefix = ShortName; + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Apply Chart Style ... + ApplyCustomChartStyle(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed +} + +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[] + // +) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + CalculateBuffers(i); + } + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = true; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index // Selected Bar Index +) +{ +} + +// +// Apply Custom Chart Style ... +void ApplyCustomChartStyle() +{ + // + // Read Current Chart Config and Store it ... + ReadChartStyle(); + + // + // After Reading Current Chart Style ... + // we have to Save Configs and Change Styles ... + clearStyle = chartStyle; + + // + clearStyle.upColor = CLR_NONE; + clearStyle.downColor = CLR_NONE; + clearStyle.lineColor = CLR_NONE; + clearStyle.bullishColor = CLR_NONE; + clearStyle.bearishColor = CLR_NONE; + + // + // Decide to Show or not Candles based on User Input ... + if (showCandles) + { + SetChartStyle(chartStyle); + } + else + { + SetChartStyle(clearStyle); + } +} + +// +// Read Previous Chart Style ... +void ReadChartStyle() +{ + // + // Retrieve Current Chart ID ... + long chartId = ChartID(); + chartStyle.chartId = chartId; + + // + // Retrieve Chart Mode ... + chartStyle.mode = (ENUM_CHART_MODE)ChartGetInteger(chartId, CHART_MODE); + + // + chartStyle.showBidLine = (bool)ChartGetInteger(chartId, CHART_SHOW_BID_LINE); + chartStyle.showAskLine = (bool)ChartGetInteger(chartId, CHART_SHOW_ASK_LINE); + chartStyle.showGrid = (bool)ChartGetInteger(chartId, CHART_SHOW_GRID); + chartStyle.showVolumes = (bool)ChartGetInteger(chartId, CHART_SHOW_VOLUMES); + chartStyle.showTradeLevels = (bool)ChartGetInteger(chartId, CHART_SHOW_TRADE_LEVELS); + chartStyle.autoScroll = (bool)ChartGetInteger(chartId, CHART_AUTOSCROLL); + chartStyle.quickNavigation = (bool)ChartGetInteger(chartId, CHART_QUICK_NAVIGATION); + + // + chartStyle.foreGroundColor = (color)ChartGetInteger(chartId, CHART_COLOR_FOREGROUND); + chartStyle.backGroundColor = (color)ChartGetInteger(chartId, CHART_COLOR_BACKGROUND); + chartStyle.upColor = (color)ChartGetInteger(chartId, CHART_COLOR_CHART_UP); + chartStyle.downColor = (color)ChartGetInteger(chartId, CHART_COLOR_CHART_DOWN); + chartStyle.bullishColor = (color)ChartGetInteger(chartId, CHART_COLOR_CANDLE_BULL); + chartStyle.bearishColor = (color)ChartGetInteger(chartId, CHART_COLOR_CANDLE_BEAR); + chartStyle.gridColor = (color)ChartGetInteger(chartId, CHART_COLOR_GRID); + chartStyle.bidLineColor = (color)ChartGetInteger(chartId, CHART_COLOR_BID); + chartStyle.askLineColor = (color)ChartGetInteger(chartId, CHART_COLOR_ASK); + chartStyle.stopColor = (color)ChartGetInteger(chartId, CHART_COLOR_STOP_LEVEL); + chartStyle.lineColor = (color)ChartGetInteger(chartId, CHART_COLOR_CHART_LINE); + chartStyle.volumesColor = (color)ChartGetInteger(chartId, CHART_COLOR_VOLUME); + + // + chartStyle.mode = mode; + chartStyle.upColor = upColor; + chartStyle.downColor = downColor; + chartStyle.lineColor = lineColor; + chartStyle.bearishColor = bearishColor; + chartStyle.bullishColor = bullishColor; + chartStyle.volumesColor = volumesColor; +} + +// +// Set Chart Style ... +void SetChartStyle( + XChartStyle &mChartStyle // Chart Style to Apply +) +{ + // + ApplyChartStyle( + mChartStyle.chartId, + mChartStyle.mode, + mChartStyle.showBidLine, + mChartStyle.showAskLine, + mChartStyle.showGrid, + mChartStyle.showVolumes, + mChartStyle.showTradeLevels, + mChartStyle.autoScroll, + mChartStyle.quickNavigation, + mChartStyle.foreGroundColor, + mChartStyle.backGroundColor, + mChartStyle.upColor, + mChartStyle.downColor, + mChartStyle.bullishColor, + mChartStyle.bearishColor, + mChartStyle.gridColor, + mChartStyle.bidLineColor, + mChartStyle.askLineColor, + mChartStyle.lineColor, + mChartStyle.stopColor, + mChartStyle.volumesColor); +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xche.mq5 b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xche.mq5 new file mode 100644 index 0000000..f47d363 --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xche.mq5 @@ -0,0 +1,631 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// --------------------------------------------- +// Name: XCHE +// Description: Chandelier Exit Indicator ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XCHE Indicator" +#property strict + +// +// START Constants ... +// + +// +#define ShortName "XCHE" + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input group "Market"; +input int length = 35; // Length +input int loopback = 26; // Loopback +input double multiplier1 = 3.0; // 1st Multiplier +input double multiplier2 = 3.5; // 2nd Multiplier + +// +input group "Calculation"; +input ENUM_APPLIED_PRICE upAppliedTo = PRICE_HIGH; // Up Zone Applied to +input ENUM_APPLIED_PRICE downAppliedTo = PRICE_LOW; // Down Zone Applied to + +// +input group "Presentation"; +input bool showLongExit1Line = true; // Show 1st Long Exit +input bool showShortExit1Line = true; // Show 1st Short Exit +input bool showLongExit2Line = true; // Show 2st Long Exit +input bool showShortExit2Line = true; // Show 2st Short Exit + +// +// END Inputs ... +// + +// +// START Includes and Imports ... +// + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes and Imports ... +// + +// +// START Buffers ... +// + +// +#property indicator_chart_window + +// +#property indicator_buffers 8 +#property indicator_plots 8 + +// +// Long Exit 1 ... +#define longExit1BufferIndex 0 +double longExit1Buffer[]; + +// +#property indicator_label1 "XCHE LE 1" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrLime +#property indicator_style1 STYLE_DOT + +// +// Short Exit 1 ... +#define shortExit1BufferIndex 1 +double shortExit1Buffer[]; + +// +#property indicator_label2 "XCHE SE 1" +#property indicator_type2 DRAW_LINE +#property indicator_style2 STYLE_DOT +#property indicator_color2 clrRed + +// +// Long Exit 2 ... +#define longExit2BufferIndex 2 +double longExit2Buffer[]; + +// +#property indicator_label3 "XCHE LE 2" +#property indicator_type3 DRAW_LINE +#property indicator_style2 STYLE_DOT +#property indicator_color3 clrAqua + +// +// Short Exit 2 ... +#define shortExit2BufferIndex 3 +double shortExit2Buffer[]; + +// +#property indicator_label4 "XCHE SE 2" +#property indicator_type4 DRAW_LINE +#property indicator_style2 STYLE_DOT +#property indicator_color4 clrMagenta + +// +// START Arrows ... + +// +// Long Exit 1 Start ... +#define longExit1StartBufferIndex 4 +double longExit1StartBuffer[]; + +// +#property indicator_label5 "XCHE LES 1" +#property indicator_type5 DRAW_ARROW +#property indicator_color5 clrLime + +// +// Short Exit 1 Start ... +#define shortExit1StartBufferIndex 5 +double shortExit1StartBuffer[]; + +// +#property indicator_label6 "XCHE SES 1" +#property indicator_type6 DRAW_ARROW +#property indicator_color6 clrRed + +// +// Long Exit 2 Start ... +#define longExit2StartBufferIndex 6 +double longExit2StartBuffer[]; + +// +#property indicator_label7 "XCHE LES 2" +#property indicator_type7 DRAW_ARROW +#property indicator_color7 clrAqua + +// +// Short Exit 2 Start ... +#define shortExit2StartBufferIndex 7 +double shortExit2StartBuffer[]; + +// +#property indicator_label8 "XCHE SES 2" +#property indicator_type8 DRAW_ARROW +#property indicator_color8 clrMagenta + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int maxLength; + +// +// Working Array ... +double work[][6]; +#define hi1Idx 0 +#define lo1Idx 1 +#define hi2Idx 2 +#define lo2Idx 3 +#define trend1Idx 4 +#define trend2Idx 5 + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart mPeriod is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed +} + +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + if (Bars(_Symbol, _Period) < rates_total) + { + return (prev_calculated); + } + + // + if (ArrayRange(work, 0) != rates_total) + { + ArrayResize(work, rates_total); + } + + // + // this counts Available Bars ... + int limit; + + // + limit = prev_calculated - 1; + if (limit < 0) + { + limit = 0; + } + + // + // Main Loop ... + for (int i = limit; i < rates_total && !IsStopped(); i++) + { + CalculateBuffers( + i, + prev_calculated, + rates_total, + // + open, + high, + low, + close); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = true; + + // + result = + length >= 9 && + loopback >= 0; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(length, loopback); + + // + return result; +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + uint arrowCode = 159; + + // + // LEVEL 1 ... + + // + // Long Exit 1 ... + + // + // Draw Type ... + ENUM_DRAW_TYPE longExit1DrawType = showLongExit1Line ? DRAW_LINE : DRAW_NONE; + ENUM_DRAW_TYPE longExit1StartDrawType = showLongExit1Line ? DRAW_ARROW : DRAW_NONE; + + // + // Buffer ... + SetIndexBuffer(longExit1BufferIndex, longExit1Buffer, INDICATOR_DATA); + PlotIndexSetInteger(longExit1BufferIndex, PLOT_SHOW_DATA, showLongExit1Line); + PlotIndexSetInteger(longExit1BufferIndex, PLOT_DRAW_TYPE, longExit1DrawType); + + // + // Start Buffer ... + SetIndexBuffer(longExit1StartBufferIndex, longExit1StartBuffer, INDICATOR_DATA); + PlotIndexSetInteger(longExit1StartBufferIndex, PLOT_ARROW, arrowCode); + PlotIndexSetInteger(longExit1StartBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(longExit1StartBufferIndex, PLOT_DRAW_TYPE, longExit1StartDrawType); + + // + // Short Exit 1 ... + + // + // Draw Type ... + ENUM_DRAW_TYPE shortExit1DrawType = showShortExit1Line ? DRAW_LINE : DRAW_NONE; + ENUM_DRAW_TYPE shortExit1StartDrawType = showShortExit1Line ? DRAW_ARROW : DRAW_NONE; + + // + // Buffer ... + SetIndexBuffer(shortExit1BufferIndex, shortExit1Buffer, INDICATOR_DATA); + PlotIndexSetInteger(shortExit1BufferIndex, PLOT_SHOW_DATA, showShortExit1Line); + PlotIndexSetInteger(shortExit1BufferIndex, PLOT_DRAW_TYPE, shortExit1DrawType); + + // + // Start Buffer ... + SetIndexBuffer(shortExit1StartBufferIndex, shortExit1StartBuffer, INDICATOR_DATA); + PlotIndexSetInteger(shortExit1StartBufferIndex, PLOT_ARROW, arrowCode); + PlotIndexSetInteger(shortExit1StartBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(shortExit1StartBufferIndex, PLOT_DRAW_TYPE, shortExit1StartDrawType); + + // + // LEVEL 2 ... + + // + // Long Exit 2 ... + + // + // Draw Type ... + ENUM_DRAW_TYPE longExit2DrawType = showLongExit2Line ? DRAW_LINE : DRAW_NONE; + ENUM_DRAW_TYPE longExit2StartDrawType = showLongExit2Line ? DRAW_ARROW : DRAW_NONE; + + // + // Buffer ... + SetIndexBuffer(longExit2BufferIndex, longExit2Buffer, INDICATOR_DATA); + PlotIndexSetInteger(longExit2BufferIndex, PLOT_SHOW_DATA, showLongExit2Line); + PlotIndexSetInteger(longExit2BufferIndex, PLOT_DRAW_TYPE, longExit2DrawType); + + // + // Start Buffer ... + SetIndexBuffer(longExit2StartBufferIndex, longExit2StartBuffer, INDICATOR_DATA); + PlotIndexSetInteger(longExit2StartBufferIndex, PLOT_ARROW, arrowCode); + PlotIndexSetInteger(longExit2StartBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(longExit2StartBufferIndex, PLOT_DRAW_TYPE, longExit2StartDrawType); + + // + // Short Exit 2 ... + + // + // Draw Type ... + ENUM_DRAW_TYPE shortExit2DrawType = showShortExit2Line ? DRAW_LINE : DRAW_NONE; + ENUM_DRAW_TYPE shortExit2StartDrawType = showShortExit2Line ? DRAW_ARROW : DRAW_NONE; + + // + // Buffer ... + SetIndexBuffer(shortExit2BufferIndex, shortExit2Buffer, INDICATOR_DATA); + PlotIndexSetInteger(shortExit2BufferIndex, PLOT_SHOW_DATA, showShortExit2Line); + PlotIndexSetInteger(shortExit2BufferIndex, PLOT_DRAW_TYPE, shortExit2DrawType); + + // + // Start Buffer ... + SetIndexBuffer(shortExit2StartBufferIndex, shortExit2StartBuffer, INDICATOR_DATA); + PlotIndexSetInteger(shortExit2StartBufferIndex, PLOT_ARROW, arrowCode); + PlotIndexSetInteger(shortExit2StartBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(shortExit2StartBufferIndex, PLOT_DRAW_TYPE, shortExit2StartDrawType); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index, // Selected Bar Index + int prevCalculated, // Previous Calculated + int ratesTotal, // Total Rates + const double &open[], // Rates Open ... + const double &high[], // Rates High ... + const double &low[], // Rates Low ... + const double &close[] // Rates Close ... +) +{ + // + // Cleanup Buffers ... + longExit1Buffer[bar_index] = longExit1StartBuffer[bar_index] = shortExit1Buffer[bar_index] = shortExit1StartBuffer[bar_index] = EMPTY_VALUE; + longExit2Buffer[bar_index] = longExit2StartBuffer[bar_index] = shortExit2Buffer[bar_index] = shortExit2StartBuffer[bar_index] = EMPTY_VALUE; + + // + int start = MathMax(bar_index - loopback, 0); + + // + // Calculate ATR Value ... + double atrValue = 0; + for (int k = 1; k <= length && (bar_index - k - 1) >= 0; k++) + { + // + atrValue += MathMax(high[bar_index - k], close[MathMax(bar_index - k - 1, 0)]) - + MathMin(low[bar_index - k], close[MathMax(bar_index - k - 1, 0)]); + } + atrValue /= (double)length; + + // + // Retrieve Highest High and Lowest Lows ... + double loopbackMax = high[ArrayMaximum(high, start, loopback)]; + double loopbackMin = low[ArrayMinimum(low, start, loopback)]; + + // + // Fill Multi Dimesional Working Array ... + work[bar_index][hi1Idx] = loopbackMax - multiplier1 * atrValue; + work[bar_index][lo1Idx] = loopbackMin + multiplier1 * atrValue; + work[bar_index][hi2Idx] = loopbackMax - multiplier2 * atrValue; + work[bar_index][lo2Idx] = loopbackMin + multiplier2 * atrValue; + work[bar_index][trend1Idx] = (bar_index > 0) ? work[bar_index - 1][trend1Idx] : 0; + work[bar_index][trend2Idx] = (bar_index > 0) ? work[bar_index - 1][trend2Idx] : 0; + + // + if (bar_index > 0) + { + // + // Calculate Trends ... + if (close[bar_index] > work[bar_index - 1][lo1Idx]) + { + work[bar_index][trend1Idx] = 1; + } + + // + if (close[bar_index] < work[bar_index - 1][hi1Idx]) + { + work[bar_index][trend1Idx] = -1; + } + + // + if (close[bar_index] > work[bar_index - 1][lo2Idx]) + { + work[bar_index][trend2Idx] = 1; + } + + // + if (close[bar_index] < work[bar_index - 1][hi2Idx]) + { + work[bar_index][trend2Idx] = -1; + } + + // + // Calculate Exit Values ... + + // + // Exit 1 ... + + // + // Long ... + if (multiplier1 > 0 && work[bar_index][trend1Idx] == 1) + { + // + if (work[bar_index][hi1Idx] < work[bar_index - 1][hi1Idx]) + { + work[bar_index][hi1Idx] = work[bar_index - 1][hi1Idx]; + } + + // + longExit1Buffer[bar_index] = work[bar_index][hi1Idx]; + + // + if (longExit1Buffer[bar_index - 1] == EMPTY_VALUE) + { + longExit1StartBuffer[bar_index] = longExit1Buffer[bar_index]; + } + } + + // + // Short ... + if (multiplier1 > 0 && work[bar_index][trend1Idx] == -1) + { + // + if (work[bar_index][lo1Idx] > work[bar_index - 1][lo1Idx]) + { + work[bar_index][lo1Idx] = work[bar_index - 1][lo1Idx]; + } + + // + shortExit1Buffer[bar_index] = work[bar_index][lo1Idx]; + + // + if (shortExit1Buffer[bar_index - 1] == EMPTY_VALUE) + { + shortExit1StartBuffer[bar_index] = shortExit1Buffer[bar_index]; + } + } + + // + // Exit 2 ... + + // + // Long ... + if (multiplier2 > 0 && work[bar_index][trend2Idx] == 1) + { + if (work[bar_index][hi2Idx] < work[bar_index - 1][hi2Idx]) + { + work[bar_index][hi2Idx] = work[bar_index - 1][hi2Idx]; + } + + // + longExit2Buffer[bar_index] = work[bar_index][hi2Idx]; + + // + if (longExit2Buffer[bar_index - 1] == EMPTY_VALUE) + { + longExit2StartBuffer[bar_index] = longExit2Buffer[bar_index]; + } + } + + // + // Short ... + if (multiplier2 > 0 && work[bar_index][trend2Idx] == -1) + { + // + if (work[bar_index][lo2Idx] > work[bar_index - 1][lo2Idx]) + { + work[bar_index][lo2Idx] = work[bar_index - 1][lo2Idx]; + } + + // + shortExit2Buffer[bar_index] = work[bar_index][lo2Idx]; + + // + if (shortExit2Buffer[bar_index - 1] == EMPTY_VALUE) + { + shortExit2StartBuffer[bar_index] = shortExit2Buffer[bar_index]; + } + } + } +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xcss.mq5 b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xcss.mq5 new file mode 100644 index 0000000..3f69620 --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xcss.mq5 @@ -0,0 +1,666 @@ +/////////////////////////////////////////////////////// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------- +// Name: XCSS +// Description: XCycle Section Score ... +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XCSS Indicator" +#property strict + +// +// IMPORT ... +#include "../Helpers/x-saherelm.xcc.helper.mq5" +#include "../Helpers/x-saherelm.xct.helper.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" +#include "../Classes/x-saherelm.x121.xmcycle.class.mq5" + +// +#define ShortName "XCSS" + +// +// INPUTS ... + +// +input group "Market"; + +// +input group "Short"; +input ENUM_X_PERIOD_METHOD scMethod = X_PERIOD_AUTO; // Method +input ENUM_TIMEFRAMES scPeriod = NULL; // Period + +// +input group "Medium"; +input ENUM_X_PERIOD_METHOD mcMethod = X_PERIOD_AUTO; // Method +input ENUM_TIMEFRAMES mcPeriod = NULL; // Period + +// +input group "Long"; +input ENUM_X_PERIOD_METHOD lcMethod = X_PERIOD_AUTO; // Method +input ENUM_TIMEFRAMES lcPeriod = NULL; // Period + +// +input group "Hind"; +input ENUM_X_PERIOD_METHOD hcMethod = X_PERIOD_AUTO; // Method +input ENUM_TIMEFRAMES hcPeriod = NULL; // Period + +// +// BUFFERS ... + +// +#property indicator_separate_window + +// +#property indicator_buffers 2 +#property indicator_plots 2 + +// +#define bullishBufferIndex 0 +double bullishBuffer[]; + +// +#property indicator_label1 "Bullish" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrLime +#property indicator_width1 2 + +// +#define bearishBufferIndex 1 +double bearishBuffer[]; + +// +#property indicator_label2 "Bearish" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrRed +#property indicator_width2 2 + +// +// VARIABLE ... + +// +// Indicators ... +XCCInputs ccInputs; +XCTInputs ctInputs; + +// +XZGInputs zgInputs; +XPVInputs pvInputs; +XHKInputs hkInputs; +XMCInputs mcInputs; +XTDInputs tdInputs; +XMRBInputs mrbInputs; +XICHInputs ichInputs; +XCHEInputs cheInputs; +XSTRInputs strInputs; +XDONInputs donInputs; +XOSCInputs oscInputs; + +// +X121MCycleInputs cMarketInputs; // Curent Market Inputs +X121MCycleInputs sMarketInputs; // Short Market Inputs +X121MCycleInputs mMarketInputs; // Medium Market Inputs +X121MCycleInputs lMarketInputs; // Long Market Inputs +X121MCycleInputs hMarketInputs; // Hind Market Inputs + +// +XSCX121Market *cMarket; +XSCX121Market *sMarket; +XSCX121Market *mMarket; +XSCX121Market *lMarket; +XSCX121Market *hMarket; + +// +// EVENT Handlers ... + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initial Cycles ... + if (!InitCycles()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed +} + +// +// Calculating what we want ... +int OnCalculate( + const int rates_total, // Total Bars on Chart ... + const int prev_calculated, // Total Calculated Bars on Charts ... + const datetime &time[], // History of Open Time ... + const double &open[], // History of Open Price ... + const double &high[], // History of High Price ... + const double &low[], // History of Low Price ... + const double &close[], // History of Close Price ... + const long &tick_volume[], // History of Tick Volumes on Bar ... + const long &volume[], // History of Trade Volumes ... + const int &spread[] // History of Spread Price ... +) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Main Loop ... + for (int i = 0; i > limit && !IsStopped(); i++) + { + CalculateBuffers(i); + } + + // + return rates_total; +} + +// +// CUSTOM Functions ... + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + result = + // + IsValid(scMethod, scPeriod) && + IsValid(mcMethod, mcPeriod) && + IsValid(lcMethod, lcPeriod) && + IsValid(hcMethod, hcPeriod) + // + ; + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // Bullish ... + ArraySetAsSeries(bullishBuffer, true); + SetIndexBuffer(bullishBufferIndex, bullishBuffer, INDICATOR_DATA); + PlotIndexSetDouble(bullishBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + + // + // Bearish ... + ArraySetAsSeries(bearishBuffer, true); + SetIndexBuffer(bearishBufferIndex, bearishBuffer, INDICATOR_DATA); + PlotIndexSetDouble(bearishBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +void CalculateBuffers( + int barIndex // +) +{ + // + // int totalBars = iBars(_Symbol, _Period); + // Print("BarIndex: ", barIndex, ", totalBars: ", totalBars); + // bool canGo = MathAbs(totalBars - barIndex) > 100; + // if (!canGo) + // { + // return; + // } + + // + // Current Market ... + + // + double cBullScore = 0; + double cBearScore = 0; + + // + X121MCycleConditions cConditions; + cMarket.GetMarketConditions(cConditions); + + // + cConditions.GenerateScore( + cBullScore, + cBearScore // + ); + + // + // Short Market ... + + // + double sBullScore = 0; + double sBearScore = 0; + + // + X121MCycleConditions sConditions; + sMarket.GetMarketConditions(sConditions); + + // + sConditions.GenerateScore( + sBullScore, + sBearScore // + ); + + // + // Medium Market ... + + // + double mBullScore = 0; + double mBearScore = 0; + + // + X121MCycleConditions mConditions; + mMarket.GetMarketConditions(mConditions); + + // + mConditions.GenerateScore( + mBullScore, + mBearScore // + ); + + // + // Long Market ... + + // + double lBullScore = 0; + double lBearScore = 0; + + // + X121MCycleConditions lConditions; + lMarket.GetMarketConditions(lConditions); + + // + lConditions.GenerateScore( + lBullScore, + lBearScore // + ); + + // + // Hind Market ... + + // + double hBullScore = 0; + double hBearScore = 0; + + // + X121MCycleConditions hConditions; + hMarket.GetMarketConditions(hConditions); + + // + hConditions.GenerateScore( + hBullScore, + hBearScore // + ); + + // + double bullishScore = cBullScore + + sBullScore + + mBullScore + + lBullScore + + hBullScore; + bullishBuffer[barIndex] = bullishScore; + + // + double bearishScore = cBearScore + + sBearScore + + mBearScore + + lBearScore + + hBearScore; + bearishBuffer[barIndex] = bearishScore; +} + +// +bool InitCycles() +{ + // + bool result = false; + + // + // Define an Input Object and Configure it ... + // then use same Input for Separate Markets ... + + // + string symbol = _Symbol; + ENUM_TIMEFRAMES period = _Period; + + // + // Set Inputs to Default ... + ccInputs.Default(); + ctInputs.Default(); + zgInputs.Default(); + pvInputs.Default(); + hkInputs.Default(); + mcInputs.Default(); + tdInputs.Default(); + mrbInputs.Default(); + ichInputs.Default(); + cheInputs.Default(); + strInputs.Default(); + donInputs.Default(); + oscInputs.Default(); + + // + cMarketInputs.Default(); + sMarketInputs.Default(); + mMarketInputs.Default(); + lMarketInputs.Default(); + hMarketInputs.Default(); + + // + // Current Cycle ... + + // + ConfigureCurrentCycles(); + + // + cMarketInputs.cycle.symbol = symbol; + cMarketInputs.cycle.period = period; + + // + cMarketInputs.pvInputs = pvInputs; + cMarketInputs.zgInputs = zgInputs; + cMarketInputs.tdInputs = tdInputs; + cMarketInputs.mcInputs = mcInputs; + cMarketInputs.hkInputs = hkInputs; + cMarketInputs.mrbInputs = mrbInputs; + cMarketInputs.strInputs = strInputs; + cMarketInputs.oscInputs = oscInputs; + cMarketInputs.cheInputs = cheInputs; + cMarketInputs.ichInputs = ichInputs; + cMarketInputs.donInputs = donInputs; + + // + result = cMarketInputs.Init( + symbol, + period, + X_MARKET_CYCLE_SHORT, + period, + X_PERIOD_MANUALLY, + "HOST", + false // + ); + if (!result) + { + return result; + } + + // + cMarket = new XSCX121Market(); + result = cMarket.Init(cMarketInputs); + if (!result) + { + return result; + } + + // + // Short Cycle ... + + // + ConfigureShortCycles(); + + // + sMarketInputs.cycle.symbol = symbol; + sMarketInputs.cycle.period = period; + + // + sMarketInputs.pvInputs = pvInputs; + sMarketInputs.zgInputs = zgInputs; + sMarketInputs.tdInputs = tdInputs; + sMarketInputs.mcInputs = mcInputs; + sMarketInputs.hkInputs = hkInputs; + sMarketInputs.mrbInputs = mrbInputs; + sMarketInputs.strInputs = strInputs; + sMarketInputs.oscInputs = oscInputs; + sMarketInputs.cheInputs = cheInputs; + sMarketInputs.ichInputs = ichInputs; + sMarketInputs.donInputs = donInputs; + + // + result = sMarketInputs.Init( + symbol, + period, + X_MARKET_CYCLE_SHORT, + scPeriod, + scMethod, + NULL, + false // + ); + if (!result) + { + return result; + } + + // + sMarket = new XSCX121Market(); + result = sMarket.Init(sMarketInputs); + if (!result) + { + return result; + } + + // + // Medium Cycle ... + + // + ConfigureMediumCycles(); + + // + mMarketInputs.cycle.symbol = symbol; + mMarketInputs.cycle.period = period; + + // + mMarketInputs.pvInputs = pvInputs; + mMarketInputs.zgInputs = zgInputs; + mMarketInputs.tdInputs = tdInputs; + mMarketInputs.mcInputs = mcInputs; + mMarketInputs.hkInputs = hkInputs; + mMarketInputs.mrbInputs = mrbInputs; + mMarketInputs.strInputs = strInputs; + mMarketInputs.oscInputs = oscInputs; + mMarketInputs.cheInputs = cheInputs; + mMarketInputs.ichInputs = ichInputs; + mMarketInputs.donInputs = donInputs; + + // + result = mMarketInputs.Init( + symbol, + period, + X_MARKET_CYCLE_MEDIUM, + mcPeriod, + mcMethod, + NULL, + false // + ); + if (!result) + { + return result; + } + + // + mMarket = new XSCX121Market(); + result = mMarket.Init(mMarketInputs); + if (!result) + { + return result; + } + + // + // Long Cycle ... + + // + ConfigureLongCycles(); + + // + lMarketInputs.cycle.symbol = symbol; + lMarketInputs.cycle.period = period; + + // + lMarketInputs.pvInputs = pvInputs; + lMarketInputs.zgInputs = zgInputs; + lMarketInputs.tdInputs = tdInputs; + lMarketInputs.mcInputs = mcInputs; + lMarketInputs.hkInputs = hkInputs; + lMarketInputs.mrbInputs = mrbInputs; + lMarketInputs.strInputs = strInputs; + lMarketInputs.oscInputs = oscInputs; + lMarketInputs.cheInputs = cheInputs; + lMarketInputs.ichInputs = ichInputs; + lMarketInputs.donInputs = donInputs; + + // + result = lMarketInputs.Init( + symbol, + period, + X_MARKET_CYCLE_MEDIUM, + lcPeriod, + lcMethod, + NULL, + false // + ); + if (!result) + { + return result; + } + + // + lMarket = new XSCX121Market(); + result = lMarket.Init(lMarketInputs); + if (!result) + { + return result; + } + + // + // Hind Cycle ... + + // + ConfigureHindCycles(); + + // + hMarketInputs.cycle.symbol = symbol; + hMarketInputs.cycle.period = period; + + // + hMarketInputs.pvInputs = pvInputs; + hMarketInputs.zgInputs = zgInputs; + hMarketInputs.tdInputs = tdInputs; + hMarketInputs.mcInputs = mcInputs; + hMarketInputs.hkInputs = hkInputs; + hMarketInputs.mrbInputs = mrbInputs; + hMarketInputs.strInputs = strInputs; + hMarketInputs.oscInputs = oscInputs; + hMarketInputs.cheInputs = cheInputs; + hMarketInputs.ichInputs = ichInputs; + hMarketInputs.donInputs = donInputs; + + // + result = hMarketInputs.Init( + symbol, + period, + X_MARKET_CYCLE_MEDIUM, + hcPeriod, + hcMethod, + NULL, + false // + ); + if (!result) + { + return result; + } + + // + hMarket = new XSCX121Market(); + result = hMarket.Init(hMarketInputs); + if (!result) + { + return result; + } + + // + return result; +} + +// +void ConfigureCurrentCycles() {} + +// +void ConfigureShortCycles() {} + +// +void ConfigureMediumCycles() {} + +// +void ConfigureLongCycles() {} + +// +void ConfigureHindCycles() {} + +// \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xct.mq5 b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xct.mq5 new file mode 100644 index 0000000..25b3b07 --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xct.mq5 @@ -0,0 +1,261 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// --------------------------------------------- +// Name: XCT +// Description: Trend Magic Indicator ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XCT Indicator" +#property strict + +// +// START Constants ... +// + +// +#define ShortName "XCT" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input color clr = clrYellow; // Text Color +input ENUM_BASE_CORNER corner = CORNER_RIGHT_LOWER; // Text Position + +// +input group "Presentation"; +input bool showCandleTime = true; // Show Candle Time + +// +// END Inputs ... +// + +// +// START Buffers ... +// + +// +#property indicator_chart_window + +// +#property indicator_buffers 0 +#property indicator_plots 0 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (showCandleTime) + { + CreateIndicatorObject(); + } + else + { + ObjectDelete(0, ShortName); + } + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + ulong chID = FindChartID( + _Symbol, + _Period + // + ); + + // + // Delete Object ... + ObjectDelete(chID, ShortName); + + // + Comment(""); +} + +// +// Calculating what we want ... +int OnCalculate( + const int rates_total, // Total Bars on Chart ... + const int prev_calculated, // Total Calculated Bars on Charts ... + const datetime &time[], // History of Open Time ... + const double &open[], // History of Open Price ... + const double &high[], // History of High Price ... + const double &low[], // History of Low Price ... + const double &close[], // History of Close Price ... + const long &tick_volume[], // History of Tick Volumes on Bar ... + const long &volume[], // History of Trade Volumes ... + const int &spread[] // History of Spread Price ... +) +{ + // + ArraySetAsSeries(time, true); + + // + if (!showCandleTime) + { + return rates_total; + } + + // + ulong chID = FindChartID( + _Symbol, + _Period + // + ); + + // + XBarRemainsTime barRemains; + barRemains.Init( + _Symbol, + _Period + // + ); + + // + string msg = barRemains + .ToString( + "", + "", + "", + "", + "", + ":", + true + // + ); + + // + long mSpread = SymbolInfoInteger(Symbol(), SYMBOL_SPREAD); + + // + string _sp = ""; + if (mSpread < 10) + _sp = ".."; + else if (mSpread < 100) + _sp = "."; + + // + string objText = "Spread: " + IntegerToString(mSpread) + _sp + " Next Bar in: " + msg; + + // + ObjectSetInteger(chID, ShortName, OBJPROP_COLOR, clr); + ObjectSetString(chID, ShortName, OBJPROP_TEXT, objText); + ObjectSetInteger(chID, ShortName, OBJPROP_FONTSIZE, 10); + ObjectSetString(chID, ShortName, OBJPROP_FONT, "Courier"); + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +void CreateIndicatorObject() +{ + // + if (!showCandleTime) + { + return; + } + + // + ObjectCreate(0, ShortName, OBJ_LABEL, 0, 0, 0); + ObjectSetInteger(0, ShortName, OBJPROP_CORNER, corner); + ObjectSetInteger(0, ShortName, OBJPROP_XDISTANCE, 10); + ObjectSetInteger(0, ShortName, OBJPROP_YDISTANCE, 2); + + // + ENUM_ANCHOR_POINT Anchor = ANCHOR_LEFT_UPPER; + switch (corner) + { + case CORNER_LEFT_UPPER: + Anchor = ANCHOR_LEFT_UPPER; + break; + case CORNER_RIGHT_UPPER: + Anchor = ANCHOR_RIGHT_UPPER; + break; + case CORNER_LEFT_LOWER: + Anchor = ANCHOR_LEFT_LOWER; + break; + case CORNER_RIGHT_LOWER: + Anchor = ANCHOR_RIGHT_LOWER; + break; + } + + // + ObjectSetInteger(0, ShortName, OBJPROP_ANCHOR, Anchor); +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xdon.mq5 b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xdon.mq5 new file mode 100644 index 0000000..c96e2bf --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xdon.mq5 @@ -0,0 +1,366 @@ +/////////////////////////////////////////////////////// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------- +// Name: XDON +// Description: DONCHAIN Channel ... +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XDON Indicator" +#property strict + +// +#define ShortName "XDON" + +// +// INPUT ... + +// +input group "Market"; +input int length = 52; // Market Length +input double offset = 0; // Offset + +// +input group "Presentation"; +input bool showOpen = true; // Show Open +input bool showHigh = true; // Show High +input bool showClose = true; // Show Close +input bool showLow = true; // Show Low + +// +// BUFFERS ... + +// +#property indicator_chart_window + +// +#property indicator_buffers 8 +#property indicator_plots 8 + +// +#define upperOBufferIndex 0 +double upperOBuffer[]; + +// +#property indicator_label1 "XDON OU" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrCornflowerBlue +#property indicator_width1 2 + +// +#define lowerOBufferIndex 1 +double lowerOBuffer[]; + +// +#property indicator_label2 "XDON OL" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrCornflowerBlue +#property indicator_width2 2 + +// +#define upperCBufferIndex 2 +double upperCBuffer[]; + +// +#property indicator_label3 "XDON CU" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrCoral +#property indicator_width3 2 + +// +#define lowerCBufferIndex 3 +double lowerCBuffer[]; + +// +#property indicator_label4 "XDON CL" +#property indicator_type4 DRAW_LINE +#property indicator_color4 clrCoral +#property indicator_width4 2 + +// +#define upperHBufferIndex 4 +double upperHBuffer[]; + +// +#property indicator_label5 "XDON HU" +#property indicator_type5 DRAW_LINE +#property indicator_color5 clrAquamarine +#property indicator_width5 2 + +// +#define lowerHBufferIndex 5 +double lowerHBuffer[]; + +// +#property indicator_label6 "XDON HL" +#property indicator_type6 DRAW_LINE +#property indicator_color6 clrAquamarine +#property indicator_width6 2 + +// +#define upperLBufferIndex 6 +double upperLBuffer[]; + +// +#property indicator_label7 "XDON LU" +#property indicator_type7 DRAW_LINE +#property indicator_color7 clrDarkOrchid +#property indicator_width7 2 + +// +#define lowerLBufferIndex 7 +double lowerLBuffer[]; + +// +#property indicator_label8 "XDON LL" +#property indicator_type8 DRAW_LINE +#property indicator_color8 clrDarkOrchid +#property indicator_width8 2 + +// +// EVENT Handlers ... + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed +} + +// +// Calculating what we want ... +int OnCalculate( + const int rates_total, // Total Bars on Chart ... + const int prev_calculated, // Total Calculated Bars on Charts ... + const datetime &time[], // History of Open Time ... + const double &open[], // History of Open Price ... + const double &high[], // History of High Price ... + const double &low[], // History of Low Price ... + const double &close[], // History of Close Price ... + const long &tick_volume[], // History of Tick Volumes on Bar ... + const long &volume[], // History of Trade Volumes ... + const int &spread[] // History of Spread Price ... +) +{ + // + if (rates_total < length - 1) + { + return prev_calculated; + } + + // + int start = prev_calculated == 0 + ? length + : prev_calculated - 1; + + // + // Main Loop ... + for (int barIndex = start; barIndex < rates_total; barIndex++) + { + // + // OPEN ... + + // + double upperOValue = open[ArrayMaximum(open, barIndex - length + 1, length)]; + double lowerOValue = open[ArrayMinimum(open, barIndex - length + 1, length)]; + + // + double oDelta = MathAbs(upperOValue - lowerOValue); + double oOffsetValue = oDelta * (offset) * 0.01; + + // + upperOBuffer[barIndex] = upperOValue - oOffsetValue; + lowerOBuffer[barIndex] = lowerOValue + oOffsetValue; + + // + // CLOSE ... + + // + double upperCValue = close[ArrayMaximum(close, barIndex - length + 1, length)]; + double lowerCValue = close[ArrayMinimum(close, barIndex - length + 1, length)]; + + // + double cDelta = MathAbs(upperCValue - lowerCValue); + double cOffsetValue = cDelta * (offset) * 0.01; + + // + upperCBuffer[barIndex] = upperCValue - cOffsetValue; + lowerCBuffer[barIndex] = lowerCValue + cOffsetValue; + + // + // HIGH ... + + // + double upperHValue = high[ArrayMaximum(high, barIndex - length + 1, length)]; + double lowerHValue = high[ArrayMinimum(high, barIndex - length + 1, length)]; + + // + double hDelta = MathAbs(upperHValue - lowerHValue); + double hOffsetValue = hDelta * (offset) * 0.01; + + // + upperHBuffer[barIndex] = upperHValue - hOffsetValue; + lowerHBuffer[barIndex] = lowerHValue + hOffsetValue; + + // + // LOW ... + + // + double upperLValue = low[ArrayMaximum(low, barIndex - length + 1, length)]; + double lowerLValue = low[ArrayMinimum(low, barIndex - length + 1, length)]; + + // + double lDelta = MathAbs(upperLValue - lowerLValue); + double lOffsetValue = lDelta * (offset) * 0.01; + + // + upperLBuffer[barIndex] = upperLValue - lOffsetValue; + lowerLBuffer[barIndex] = lowerLValue + lOffsetValue; + } + + // + return rates_total; +} + +// +// CUSTOM Functions ... + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + result = length >= 7; + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // Open ... + ENUM_DRAW_TYPE openDrawType = showOpen ? DRAW_LINE : DRAW_NONE; + + // + // UPPER ... + SetIndexBuffer(upperOBufferIndex, upperOBuffer, INDICATOR_DATA); + PlotIndexSetInteger(upperOBufferIndex, PLOT_SHOW_DATA, showOpen); + PlotIndexSetDouble(upperOBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(upperOBufferIndex, PLOT_DRAW_TYPE, openDrawType); + + // + // LOWER ... + SetIndexBuffer(lowerOBufferIndex, lowerOBuffer, INDICATOR_DATA); + PlotIndexSetInteger(lowerOBufferIndex, PLOT_SHOW_DATA, showOpen); + PlotIndexSetDouble(lowerOBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(lowerOBufferIndex, PLOT_DRAW_TYPE, openDrawType); + + // + // Close ... + ENUM_DRAW_TYPE closeDrawType = showClose ? DRAW_LINE : DRAW_NONE; + + // + // UPPER ... + SetIndexBuffer(upperCBufferIndex, upperCBuffer, INDICATOR_DATA); + PlotIndexSetInteger(upperCBufferIndex, PLOT_SHOW_DATA, showClose); + PlotIndexSetDouble(upperCBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(upperCBufferIndex, PLOT_DRAW_TYPE, closeDrawType); + + // + // LOWER ... + SetIndexBuffer(lowerCBufferIndex, lowerCBuffer, INDICATOR_DATA); + PlotIndexSetInteger(lowerCBufferIndex, PLOT_SHOW_DATA, showClose); + PlotIndexSetDouble(lowerCBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(lowerCBufferIndex, PLOT_DRAW_TYPE, closeDrawType); + + // + // High ... + ENUM_DRAW_TYPE highDrawType = showHigh ? DRAW_LINE : DRAW_NONE; + + // + // UPPER ... + SetIndexBuffer(upperHBufferIndex, upperHBuffer, INDICATOR_DATA); + PlotIndexSetInteger(upperHBufferIndex, PLOT_SHOW_DATA, showHigh); + PlotIndexSetDouble(upperHBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(upperHBufferIndex, PLOT_DRAW_TYPE, highDrawType); + + // + // LOWER ... + SetIndexBuffer(lowerHBufferIndex, lowerHBuffer, INDICATOR_DATA); + PlotIndexSetInteger(lowerHBufferIndex, PLOT_SHOW_DATA, showHigh); + PlotIndexSetDouble(lowerHBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(lowerHBufferIndex, PLOT_DRAW_TYPE, highDrawType); + + // + // Low ... + ENUM_DRAW_TYPE lowDrawType = showLow ? DRAW_LINE : DRAW_NONE; + + // + // UPPER ... + SetIndexBuffer(upperLBufferIndex, upperLBuffer, INDICATOR_DATA); + PlotIndexSetInteger(upperLBufferIndex, PLOT_SHOW_DATA, showLow); + PlotIndexSetDouble(upperLBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(upperLBufferIndex, PLOT_DRAW_TYPE, lowDrawType); + + // + // LOWER ... + SetIndexBuffer(lowerLBufferIndex, lowerLBuffer, INDICATOR_DATA); + PlotIndexSetInteger(lowerLBufferIndex, PLOT_SHOW_DATA, showLow); + PlotIndexSetDouble(lowerLBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(lowerLBufferIndex, PLOT_DRAW_TYPE, lowDrawType); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} diff --git a/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xhk.mq5 b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xhk.mq5 new file mode 100644 index 0000000..37cf4b5 --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xhk.mq5 @@ -0,0 +1,479 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// -------------------------------------------- +// Name: XHK +// Description: Hiken Ashi ... +// Market Analysor ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XHK Indicator" +#property strict + +// +// Constants ... + +// +// Indicator Short Name ... +#define ShortName "XHK" + +// +// Imports ... +#include +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +input group "Market"; +input int smoothingLength = 17; // Smoothing Length +// +input group "Presentation"; +input bool drawHikenAshi = true; // Draw Hiken Ashi +input bool drawSmoothedHikenAshi = true; // Draw Smoothed Hiken Ashi + +// +// Buffers ... + +// +#property indicator_chart_window + +// +#property indicator_buffers 10 +#property indicator_plots 10 + +// +// Buffers ... + +// +// Open ... +#define openBufferIndex 0 +double openBuffer[]; + +// +// High ... +#define highBufferIndex 1 +double highBuffer[]; + +// +// Low ... +#define lowBufferIndex 2 +double lowBuffer[]; + +// +// Close ... +#define closeBufferIndex 3 +double closeBuffer[]; + +// +// Candle Color ... +#define candleColorBufferIndex 4 +double candleColorBuffer[]; + +// +#define candlesBufferIndex 0 + +// +#property indicator_label1 "XHK Open;XHK High;XHK Low;XHK Close" +#property indicator_type1 DRAW_COLOR_CANDLES +#property indicator_color1 CLR_NONE, clrAqua, clrMagenta + +// +// SM Open ... +#define openSMBufferIndex 5 +double openSMBuffer[]; + +// +// SM High ... +#define highSMBufferIndex 6 +double highSMBuffer[]; + +// +// SM Low ... +#define lowSMBufferIndex 7 +double lowSMBuffer[]; + +// +// SM Close ... +#define closeSMBufferIndex 8 +double closeSMBuffer[]; + +// +// SM Candle Color ... +#define candleColorSMBufferIndex 9 +double candleColorSMBuffer[]; + +// +#define candlesSMBufferIndex 1 + +// +#property indicator_label2 "XSMHK Open;XSMHK High;XSMHK Low;XSMHK Close" +#property indicator_type2 DRAW_COLOR_CANDLES +#property indicator_color2 CLR_NONE, clrDarkGreen, clrDarkRed + +// +// Variables, Properties and etc ... + +// +int maxLength; + +// +double mHideColorIDX = 0; + +// +// Event Handlers ... + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed +} + +// +// Calculating what we want ... +int OnCalculate( + const int rates_total, // Total Bars on Chart ... + const int prev_calculated, // Total Calculated Bars on Charts ... + const datetime &time[], // History of Open Time ... + const double &open[], // History of Open Price ... + const double &high[], // History of High Price ... + const double &low[], // History of Low Price ... + const double &close[], // History of Close Price ... + const long &tick_volume[], // History of Tick Volumes on Bar ... + const long &volume[], // History of Trade Volumes ... + const int &spread[] // History of Spread Price ... +) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + CalculateBuffers(i, prev_calculated, rates_total, open, high, close, low); + } + + // + CalculateSM(rates_total, prev_calculated); + + // + return rates_total; +} + +// +// Functions ... + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = true; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // Candles Color ... + ArraySetAsSeries(candleColorBuffer, true); + SetIndexBuffer(candleColorBufferIndex, candleColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Set EMPTY_VALUE on Candles Buffer ... + PlotIndexSetDouble(candlesBufferIndex, PLOT_EMPTY_VALUE, 0.0); + + // + PlotIndexSetInteger(candlesBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(candleColorBufferIndex, PLOT_SHOW_DATA, false); + + // + // Open ... + ArraySetAsSeries(openBuffer, true); + PlotIndexSetInteger(openBufferIndex, PLOT_SHOW_DATA, false); + SetIndexBuffer(openBufferIndex, openBuffer, INDICATOR_DATA); + + // + // High ... + ArraySetAsSeries(highBuffer, true); + SetIndexBuffer(highBufferIndex, highBuffer, INDICATOR_DATA); + PlotIndexSetInteger(highBufferIndex, PLOT_SHOW_DATA, false); + + // + // Close ... + ArraySetAsSeries(closeBuffer, true); + SetIndexBuffer(closeBufferIndex, closeBuffer, INDICATOR_DATA); + PlotIndexSetInteger(closeBufferIndex, PLOT_SHOW_DATA, false); + + // + // Low ... + ArraySetAsSeries(lowBuffer, true); + SetIndexBuffer(lowBufferIndex, lowBuffer, INDICATOR_DATA); + PlotIndexSetInteger(lowBufferIndex, PLOT_SHOW_DATA, false); + + // + // Candles Color ... + ArraySetAsSeries(candleColorSMBuffer, true); + SetIndexBuffer(candleColorSMBufferIndex, candleColorSMBuffer, INDICATOR_COLOR_INDEX); + + // + // Set EMPTY_VALUE on Candles Buffer ... + PlotIndexSetDouble(candlesSMBufferIndex, PLOT_EMPTY_VALUE, 0.0); + + // + PlotIndexSetInteger(candlesSMBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(candleColorSMBufferIndex, PLOT_SHOW_DATA, false); + + // + // Open ... + ArraySetAsSeries(openSMBuffer, true); + PlotIndexSetInteger(openSMBufferIndex, PLOT_SHOW_DATA, false); + SetIndexBuffer(openSMBufferIndex, openSMBuffer, INDICATOR_DATA); + + // + // High ... + ArraySetAsSeries(highSMBuffer, true); + SetIndexBuffer(highSMBufferIndex, highSMBuffer, INDICATOR_DATA); + PlotIndexSetInteger(highSMBufferIndex, PLOT_SHOW_DATA, false); + + // + // Close ... + ArraySetAsSeries(closeSMBuffer, true); + SetIndexBuffer(closeSMBufferIndex, closeSMBuffer, INDICATOR_DATA); + PlotIndexSetInteger(closeSMBufferIndex, PLOT_SHOW_DATA, false); + + // + // Low ... + ArraySetAsSeries(lowSMBuffer, true); + SetIndexBuffer(lowSMBufferIndex, lowSMBuffer, INDICATOR_DATA); + PlotIndexSetInteger(lowSMBufferIndex, PLOT_SHOW_DATA, false); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[] // +) +{ + // + double mPrevHKOpenValue; + double mPrevHKCloseValue; + + // + if (ArraySize(open) <= bar_index + 1) + { + // + mPrevHKOpenValue = 0; + mPrevHKCloseValue = 0; + } + else + { + // + mPrevHKOpenValue = openBuffer[bar_index + 1]; + mPrevHKCloseValue = closeBuffer[bar_index + 1]; + } + + // + double mHKOpenValue = (mPrevHKOpenValue + mPrevHKCloseValue) / 2; + double mHKCloseValue = (open[bar_index] + high[bar_index] + close[bar_index] + low[bar_index]) / 4; + double mHKHighValue = MathMax(high[bar_index], MathMax(mHKOpenValue, mHKCloseValue)); + double mHKLowValue = MathMin(low[bar_index], MathMin(mHKOpenValue, mHKCloseValue)); + + // + openBuffer[bar_index] = mHKOpenValue; + highBuffer[bar_index] = mHKHighValue; + lowBuffer[bar_index] = mHKLowValue; + closeBuffer[bar_index] = mHKCloseValue; + + // + bool isBearish = + // + openBuffer[bar_index] > closeBuffer[bar_index] + // + ; + + // + candleColorBuffer[bar_index] = !drawHikenAshi + ? mHideColorIDX + : isBearish + ? 2 + : 1; +} + +// +// Calculate Smoothed HikenAshi ... +void CalculateSM( + int ratesTotal, // Total Bars + int prevCalculated // Calculated Bars +) +{ + // + // Open ... + int calculatedSMHKOpens = ExponentialMAOnBuffer( + ratesTotal, + prevCalculated, + 0, + smoothingLength, + openBuffer, + openSMBuffer); + + // + // High ... + int calculatedSMHKHighs = ExponentialMAOnBuffer( + ratesTotal, + prevCalculated, + 0, + smoothingLength, + highBuffer, + highSMBuffer); + + // + // Low ... + int calculatedSMHKLows = ExponentialMAOnBuffer( + ratesTotal, + prevCalculated, + 0, + smoothingLength, + lowBuffer, + lowSMBuffer); + + // + // Close ... + int calculatedSMHKCloses = ExponentialMAOnBuffer( + ratesTotal, + prevCalculated, + 0, + smoothingLength, + closeBuffer, + closeSMBuffer); + + // + // Find Calculated Items for Colors ... + int mNumberOfItems = MathMin(calculatedSMHKOpens, calculatedSMHKHighs); + mNumberOfItems = MathMin(mNumberOfItems, calculatedSMHKLows); + mNumberOfItems = MathMin(mNumberOfItems, calculatedSMHKCloses); + + // + // Create a Loop for Color of Candles ... + for (int i = 0; i < mNumberOfItems; i++) + { + // + bool isBearish = + // + openSMBuffer[i] > closeSMBuffer[i] + // + ; + + // + if (drawSmoothedHikenAshi) + { + // + candleColorSMBuffer[i] = isBearish + ? 2 + : 1; + } + else + { + // + candleColorSMBuffer[i] = mHideColorIDX; + } + } +} diff --git a/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xhull.mq5 b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xhull.mq5 new file mode 100644 index 0000000..ffc1792 --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xhull.mq5 @@ -0,0 +1,583 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// --------------------------------------------- +// Name: XHULL +// Description: Hull Trend Indicator ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XHULL Indicator" +#property strict + +// +// START Constants ... +// + +// +#define ShortName "XHULL" + +// +struct XHullData +{ + // + double value; + double value3; + + // + double wsum1; + double wsum2; + double wsum3; + + // + double lsum1; + double lsum2; + double lsum3; +}; + +// +// END Constants ... +// + +// +// START Includes and Imports ... +// + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes and Imports ... +// + +// +// START XSCHULL Class Definition ... +// + +// +// a Class For Hull Calculations ... +class XSCHull +{ + // +public: + // + // Constructor ... + XSCHull() : mFullPeriod(1), mHalfPeriod(1), mSqrtPeriod(1), mArraySize(-1) + { + // + // These are a way above to assign Private variables at Construct time ... + } + + // + // Deconstructor ... + ~XSCHull() + { + ArrayFree(mData); + } + + // + // Initial Hull ... + bool Init( + int mPeriod, + double mDivisor) + { + // + bool result = false; + + // + mFullPeriod = (int)(mPeriod > 1 ? mPeriod : 1); + mHalfPeriod = (int)(mFullPeriod > 1 ? mFullPeriod / (mDivisor > 1 ? mDivisor : 1) : 1); + mSqrtPeriod = (int)MathSqrt(mFullPeriod); + + // + mArraySize = -1; + mWeight1 = mWeight2 = mWeight3 = 1; + + // + result = true; + + // + return result; + } + + // + // CalCulate Specific Value ... + double Calculate( + double value, + int i, + int bars) + { + // + double result = 0; + + // + if (mArraySize < bars) + { + // + mArraySize = ArrayResize(mData, bars + 500); + if (mArraySize < bars) + return result; + } + + // + mData[i].value = value; + if (i > mFullPeriod) + { + // + mData[i].wsum1 = mData[i - 1].wsum1 + value * mHalfPeriod - mData[i - 1].lsum1; + mData[i].lsum1 = mData[i - 1].lsum1 + value - mData[i - mHalfPeriod].value; + mData[i].wsum2 = mData[i - 1].wsum2 + value * mFullPeriod - mData[i - 1].lsum2; + mData[i].lsum2 = mData[i - 1].lsum2 + value - mData[i - mFullPeriod].value; + } + else + { + // + mData[i].wsum1 = mData[i].wsum2 = + mData[i].lsum1 = mData[i].lsum2 = mWeight1 = mWeight2 = 0; + for (int k = 0, w1 = mHalfPeriod, w2 = mFullPeriod; w2 > 0 && i >= k; k++, w1--, w2--) + { + // + if (w1 > 0) + { + // + mData[i].wsum1 += mData[i - k].value * w1; + mData[i].lsum1 += mData[i - k].value; + mWeight1 += w1; + } + + // + mData[i].wsum2 += mData[i - k].value * w2; + mData[i].lsum2 += mData[i - k].value; + mWeight2 += w2; + } + } + + // + mData[i].value3 = 2.0 * mData[i].wsum1 / mWeight1 - mData[i].wsum2 / mWeight2; + + // + if (i > mSqrtPeriod) + { + // + mData[i].wsum3 = mData[i - 1].wsum3 + mData[i].value3 * mSqrtPeriod - mData[i - 1].lsum3; + mData[i].lsum3 = mData[i - 1].lsum3 + mData[i].value3 - mData[i - mSqrtPeriod].value3; + } + else + { + // + mData[i].wsum3 = + mData[i].lsum3 = mWeight3 = 0; + + // + for (int k = 0, w3 = mSqrtPeriod; w3 > 0 && i >= k; k++, w3--) + { + // + mData[i].wsum3 += mData[i - k].value3 * w3; + mData[i].lsum3 += mData[i - k].value3; + mWeight3 += w3; + } + } + + // + result = mData[i].wsum3 / mWeight3; + + // + return result; + } + + // + // Protected ... +protected: + // + // Private ... +private: + // + int mFullPeriod; + int mHalfPeriod; + int mSqrtPeriod; + int mArraySize; + double mWeight1; + double mWeight2; + double mWeight3; + + // + XHullData mData[]; +}; + +// +// END XSCHULL Class Definition ... +// + +// +// START Inputs ... +// + +// +input group "Market"; +input int length = 72; // Length +input double divisor = 2.0; // Divisor (Speed) + +// +input group "Calculation"; +input ENUM_APPLIED_PRICE upAppliedTo = PRICE_HIGH; // Up Zone Applied to +input ENUM_APPLIED_PRICE downAppliedTo = PRICE_LOW; // Down Zone Applied to + +// +input group "Presentation"; +input bool showUpZone = true; // Show Up Zone +input bool showDownZone = true; // Show Down Zone + +// +// END Inputs ... +// + +// +// START Buffers ... +// + +// +#property indicator_chart_window + +// +#property indicator_buffers 4 +#property indicator_plots 4 + +// +// UP Zone ... + +// +#define upZoneBufferIndex 0 +#define upZoneColorBufferIndex 1 + +// +double upZoneBuffer[]; +double upZoneColorBuffer[]; + +// +#property indicator_label1 "XHULL Up" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 clrLightGray, clrAqua, clrMagenta +#property indicator_width1 1 + +// +// DOWN Zone ... + +// +#define downZoneBufferIndex 2 +#define downZoneColorBufferIndex 3 + +// +double downZoneBuffer[]; +double downZoneColorBuffer[]; + +// +#property indicator_label2 "XHULL Down" +#property indicator_type2 DRAW_COLOR_LINE +#property indicator_color2 clrLightGray, clrAqua, clrMagenta +#property indicator_width2 1 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int maxLength; + +// +XSCHull *mUpZHull; +XSCHull *mDownZHull; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Make an Instance of Hull Class ... + + // + mUpZHull = new XSCHull(); + mUpZHull.Init( + length, + divisor); + + // + mDownZHull = new XSCHull(); + mDownZHull.Init( + length, + divisor); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart mPeriod is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + delete mUpZHull; + delete mDownZHull; +} + +// +// Calculating what we want ... +int OnCalculate( + const int rates_total, // Total Bars on Chart ... + const int prev_calculated, // Total Calculated Bars on Charts ... + const datetime &time[], // History of Open Time ... + const double &open[], // History of Open Price ... + const double &high[], // History of High Price ... + const double &low[], // History of Low Price ... + const double &close[], // History of Close Price ... + const long &tick_volume[], // History of Tick Volumes on Bar ... + const long &volume[], // History of Trade Volumes ... + const int &spread[] // History of Spread Price ... +) +{ + // + // this counts Available Bars ... + int limit; + + // + limit = prev_calculated - 1; + if (limit < 0) + { + limit = 0; + } + + // + // Main Loop ... + for (int i = limit; i < rates_total && !IsStopped(); i++) + { + // + double upPrice = getPrice( + upAppliedTo, + open, high, low, close, i); + + // + double downPrice = getPrice( + downAppliedTo, + open, high, low, close, i); + + // + CalculateBuffers( + i, + rates_total, + upPrice, + downPrice); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = true; + + // + result = + length >= 9 && + divisor >= 0.5; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = length; + + // + return result; +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // UP Zone ... + + // + // Draw Type ... + ENUM_DRAW_TYPE upZoneDrawType = showUpZone ? DRAW_COLOR_LINE : DRAW_NONE; + + // + // Buffer ... + SetIndexBuffer(upZoneBufferIndex, upZoneBuffer, INDICATOR_DATA); + PlotIndexSetInteger(upZoneBufferIndex, PLOT_SHOW_DATA, showUpZone); + PlotIndexSetInteger(upZoneBufferIndex, PLOT_DRAW_TYPE, upZoneDrawType); + + // + // Color Buffer ... + SetIndexBuffer(upZoneColorBufferIndex, upZoneColorBuffer, INDICATOR_COLOR_INDEX); + + // + // DOWN Zone ... + + // + // Draw Type ... + ENUM_DRAW_TYPE downZoneDrawType = showDownZone ? DRAW_COLOR_LINE : DRAW_NONE; + + // + // Buffer ... + SetIndexBuffer(downZoneBufferIndex, downZoneBuffer, INDICATOR_DATA); + PlotIndexSetInteger(downZoneBufferIndex - 1, PLOT_SHOW_DATA, showDownZone); + PlotIndexSetInteger(downZoneBufferIndex - 1, PLOT_DRAW_TYPE, downZoneDrawType); + + // + // Color Buffer ... + SetIndexBuffer(downZoneColorBufferIndex, downZoneColorBuffer, INDICATOR_COLOR_INDEX); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index, // Selected Bar Index + int ratesTotal, // Total Rates + double upPrice, // Up Price ... + double downPrice // Down Price ... +) +{ + // + double upValue = mUpZHull.Calculate( + upPrice, + bar_index, + ratesTotal); + upZoneBuffer[bar_index] = upValue; + double upColorIDX = (bar_index > 0) + ? (upZoneBuffer[bar_index] > upZoneBuffer[bar_index - 1]) + ? 1 + : (upZoneBuffer[bar_index] < upZoneBuffer[bar_index - 1]) + ? 2 + : upZoneColorBuffer[bar_index - 1] + : 0; + upZoneColorBuffer[bar_index] = upColorIDX; + + // + double downValue = mDownZHull.Calculate( + downPrice, + bar_index, + ratesTotal); + downZoneBuffer[bar_index] = downValue; + double downColorIDX = (bar_index > 0) + ? (downZoneBuffer[bar_index] > downZoneBuffer[bar_index - 1]) + ? 1 + : (downZoneBuffer[bar_index] < downZoneBuffer[bar_index - 1]) + ? 2 + : downZoneColorBuffer[bar_index - 1] + : 0; + downZoneColorBuffer[bar_index] = downColorIDX; +} + +// +// END Functions ... +// + +// +// TEMPLATE Function ... + +template +double getPrice(ENUM_APPLIED_PRICE tprice, T &open[], T &high[], T &low[], T &close[], int i) +{ + switch (tprice) + { + case PRICE_CLOSE: + return (close[i]); + case PRICE_OPEN: + return (open[i]); + case PRICE_HIGH: + return (high[i]); + case PRICE_LOW: + return (low[i]); + case PRICE_MEDIAN: + return ((high[i] + low[i]) / 2.0); + case PRICE_TYPICAL: + return ((high[i] + low[i] + close[i]) / 3.0); + case PRICE_WEIGHTED: + return ((high[i] + low[i] + close[i] + close[i]) / 4.0); + } + return (0); +} diff --git a/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xich.mq5 b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xich.mq5 new file mode 100644 index 0000000..00bf6fb --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xich.mq5 @@ -0,0 +1,846 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XICH +// Description: Ichimoku Kinko Hyo ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XICH Indicator" +#property strict + +// +// START Constants ... +// + +// +// Indicator Short Name ... +#define ShortName "XICH" + +// +// Ichimoku Golden Numbers ... +enum ENUM_X_ICHIMOKU_GOLDEN_NUMBERS +{ + X_ICH_BASE = 9, + X_ICH_GOLDEN = 17, + X_ICH_CYCLE = 26, + X_ICH_PERIOD = 35, + X_ICH_STAR = 45, + X_ICH_MED = 52, + X_ICH_LONG = 63, + X_ICH_FULL = 72 +}; + +// +// Ichimoku Lines Calculator Mode ... +enum ENUM_X_ICHIMOKU_CALCULATION_MODE +{ + // + X_XICH_HH_LL_MODE = 1, // Highest High and Lowest Low + X_XICH_HO_LC_MODE = 2, // Highest Open and Lowest Close +}; + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +// ICHIMOKU Kinko Hyo ... + +// +// TENKANSEN ... +input group "Tenkan Sen"; +input int tenkanSenLength = 9; // Length +input ENUM_X_ICHIMOKU_CALCULATION_MODE tenkanSenMode = X_XICH_HH_LL_MODE; // Calculation Mode + +// +// KIJUNSEN ... +input group "Kijun Sen"; +input int kijunSenLength = 26; // Length +input ENUM_X_ICHIMOKU_CALCULATION_MODE kijunSenMode = X_XICH_HH_LL_MODE; // Calculation Mode + +// +// SENKOUSPANB ... +input group "Senkou Span B"; +input int senkouSpanBLength = 52; // Length +input ENUM_X_ICHIMOKU_CALCULATION_MODE senkouSpanBMode = X_XICH_HH_LL_MODE; // Calculation Mode + +// +// CHIKOUSPAN ... +input group "Chikou Span"; +input ENUM_APPLIED_PRICE chikuoSpanAppliedTo = PRICE_CLOSE; // Price Type + +// +input group "Presentation"; +input bool showTenkanSen = true; // Show Tenkan Sen +input bool showKijunSen = true; // Show Kijun Sen +input bool showKijunSenPlus = false; // Show Kijun Sen + +input bool showKijunSenNegative = false; // Show Kijun Sen - +input bool showChikouSpan = true; // Show Chikou Span +input bool showSenkouSpanA = true; // Show Senkou Span A +input bool showSenkouSpanB = true; // Show Senkou Span B +input bool showKumo = true; // Show Kumo +input bool shiftKumo = true; // Shift Kumo to Future + +// +// END Inputs ... +// + +// +// START Includes and Imports ... +// + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes and Imports ... +// + +// +// START Buffers ... +// +#property indicator_chart_window + +// +#property indicator_buffers 15 +#property indicator_plots 8 + +// +// PLOTTED Buffers ... + +// +// ICHIMOKU ... + +// +// TENKANSEN ... + +// +#define tenkanSenBufferIndex 0 +double tenkanSenBuffer[]; + +// +#property indicator_label1 "XICH TK" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrBrown +#property indicator_style1 STYLE_SOLID +#property indicator_width1 1 + +// +// KIJUNSEN ... + +// +#define kijunSenBufferIndex 1 +double kijunSenBuffer[]; + +// +#property indicator_label2 "XICH KJ" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrDodgerBlue +#property indicator_style2 STYLE_SOLID +#property indicator_width2 1 + +// +#define kijunSenPlusBufferIndex 2 +double kijunSenPlusBuffer[]; + +// +#property indicator_label3 "XICH KJ+" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrMediumTurquoise +#property indicator_style3 STYLE_DOT +#property indicator_width3 1 + +// +#define kijunSenNegativeBufferIndex 3 +double kijunSenNegativeBuffer[]; + +// +#property indicator_label4 "XICH KJ-" +#property indicator_type4 DRAW_LINE +#property indicator_color4 clrDarkSeaGreen +#property indicator_style4 STYLE_DOT +#property indicator_width4 1 + +// +// CHIKOUSPAN ... + +// +#define chikouSpanBufferIndex 4 +double chikouSpanBuffer[]; + +// +#property indicator_label5 "XICH CS" +#property indicator_type5 DRAW_LINE +#property indicator_color5 clrDarkGreen +#property indicator_style5 STYLE_SOLID +#property indicator_width5 1 + +// +#define senkouABufferIndex 5 +double senkouABuffer[]; + +// +#property indicator_label6 "XICH SSA" +#property indicator_type6 DRAW_LINE +#property indicator_color6 clrLightGray +#property indicator_style6 STYLE_DASHDOTDOT +#property indicator_width6 1 + +// +#define senkouBBufferIndex 6 +double senkouBBuffer[]; + +// +#property indicator_label7 "XICH SSB" +#property indicator_type7 DRAW_LINE +#property indicator_color7 clrLightGray +#property indicator_style7 STYLE_DASHDOTDOT +#property indicator_width7 1 + +// +// KUMO ... + +// +// SENKOUSPANA ... + +// +#define senkouSpanABufferIndex 7 +double senkouSpanABuffer[]; + +// +// SENKOUSPANB ... + +// +#define senkouSpanBBufferIndex 8 +double senkouSpanBBuffer[]; + +// +// KUMOCLOUD ... + +// +#define kumoBufferIndex 7 + +// +#property indicator_label8 "XICH Kumo" +#property indicator_type8 DRAW_FILLING +#property indicator_color8 clrAqua, clrMagenta +#property indicator_style8 STYLE_SOLID +#property indicator_width8 1 + +// +// DATA Buffers ... + +// +#define dTenkanBufferIndex 9 +double dTenkanBuffer[]; + +// +#define dKijunBufferIndex 10 +double dKijunBuffer[]; + +// +#define dChikouBufferIndex 11 +double dChikouBuffer[]; + +// +#define dSSABufferIndex 12 +double dSSABuffer[]; + +// +#define dSSBBufferIndex 13 +double dSSBBuffer[]; + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int maxLength; +int mHandler; + +// +ENUM_SERIESMODE mTenkanSenTopMode = NULL; +ENUM_SERIESMODE mTenkanSenBottomMode = NULL; + +// +ENUM_SERIESMODE mKijunSenTopMode = NULL; +ENUM_SERIESMODE mKijunSenBottomMode = NULL; + +// +ENUM_SERIESMODE mSenkouSpanBTopMode = NULL; +ENUM_SERIESMODE mSenkouSpanBBottomMode = NULL; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Init Handler ... + mHandler = iIchimoku( + _Symbol, + _Period, + tenkanSenLength, + kijunSenLength, + senkouSpanBLength); + if (mHandler == INVALID_HANDLE) + { + return INIT_FAILED; + } + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + IndicatorRelease(mHandler); +} + +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + // Check Calculated Bars ... + int ichCalculatedBars = BarsCalculated(mHandler); + if (ichCalculatedBars < maxLength) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + int copiedTenkans = CopyBuffer(mHandler, TENKANSEN_LINE, 0, limit, dTenkanBuffer); + int copiedKijuns = CopyBuffer(mHandler, KIJUNSEN_LINE, 0, limit, dKijunBuffer); + int copiedChikous = CopyBuffer(mHandler, CHIKOUSPAN_LINE, 0, limit, dChikouBuffer); + int copiedSSAs = CopyBuffer(mHandler, SENKOUSPANA_LINE, 0, limit, dSSABuffer); + int copiedSSBs = CopyBuffer(mHandler, SENKOUSPANB_LINE, 0, limit, dSSBBuffer); + if ( + copiedSSAs < 0 || + copiedSSBs < 0 || + copiedKijuns < 0 || + copiedTenkans < 0 || + copiedChikous < 0) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + CalculateBuffers(i); + } + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = + // + (tenkanSenLength > 2 && + kijunSenLength > tenkanSenLength && + senkouSpanBLength > kijunSenLength) + // + ; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + // Ichimoku ... + result = MathMax(result, tenkanSenLength); + result = MathMax(result, kijunSenLength); + result = MathMax(result, senkouSpanBLength); + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // ICHIMOKU ... + + // + // TENKANSEN ... + + // + ENUM_DRAW_TYPE tenkanSenDrawType = showTenkanSen ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(tenkanSenBuffer, true); + SetIndexBuffer(tenkanSenBufferIndex, tenkanSenBuffer, INDICATOR_DATA); + PlotIndexSetInteger(tenkanSenBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(tenkanSenBufferIndex, PLOT_SHOW_DATA, showTenkanSen); + PlotIndexSetInteger(tenkanSenBufferIndex, PLOT_DRAW_TYPE, tenkanSenDrawType); + + // + // KIJUNSEN ... + + // + ENUM_DRAW_TYPE kijunSenDrawType = showKijunSen ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(kijunSenBuffer, true); + SetIndexBuffer(kijunSenBufferIndex, kijunSenBuffer, INDICATOR_DATA); + PlotIndexSetInteger(kijunSenBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(kijunSenBufferIndex, PLOT_SHOW_DATA, showKijunSen); + PlotIndexSetInteger(kijunSenBufferIndex, PLOT_DRAW_TYPE, kijunSenDrawType); + + // + // KIJUNSEN Plus ... + + // + ENUM_DRAW_TYPE kijunSenPlusDrawType = showKijunSenPlus ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(kijunSenPlusBuffer, true); + SetIndexBuffer(kijunSenPlusBufferIndex, kijunSenPlusBuffer, INDICATOR_DATA); + PlotIndexSetInteger(kijunSenPlusBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(kijunSenPlusBufferIndex, PLOT_SHIFT, kijunSenLength); + PlotIndexSetInteger(kijunSenPlusBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(kijunSenPlusBufferIndex, PLOT_DRAW_TYPE, kijunSenPlusDrawType); + + // + // KIJUNSEN Negative ... + + // + ENUM_DRAW_TYPE kijunSenNegativeDrawType = showKijunSenNegative ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(kijunSenNegativeBuffer, true); + SetIndexBuffer(kijunSenNegativeBufferIndex, kijunSenNegativeBuffer, INDICATOR_DATA); + PlotIndexSetInteger(kijunSenNegativeBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(kijunSenNegativeBufferIndex, PLOT_SHIFT, -kijunSenLength); + PlotIndexSetInteger(kijunSenNegativeBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(kijunSenNegativeBufferIndex, PLOT_DRAW_TYPE, kijunSenNegativeDrawType); + + // + // CHIKOUSPAN ... + + // + ENUM_DRAW_TYPE chikouSpanDrawType = showChikouSpan ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(chikouSpanBuffer, true); + SetIndexBuffer(chikouSpanBufferIndex, chikouSpanBuffer, INDICATOR_DATA); + PlotIndexSetInteger(chikouSpanBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(chikouSpanBufferIndex, PLOT_SHIFT, -kijunSenLength); + PlotIndexSetInteger(chikouSpanBufferIndex, PLOT_SHOW_DATA, showChikouSpan); + PlotIndexSetInteger(chikouSpanBufferIndex, PLOT_DRAW_TYPE, chikouSpanDrawType); + + // + // SENKOUSPAN A and B ... + int shiftSize = shiftKumo ? kijunSenLength : 0; + + // + // SENKOUSPANA ... + ENUM_DRAW_TYPE senkouSpanADrawType = showSenkouSpanA ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(senkouABuffer, true); + SetIndexBuffer(senkouABufferIndex, senkouABuffer, INDICATOR_DATA); + PlotIndexSetInteger(senkouABufferIndex, PLOT_SHIFT, shiftSize); + PlotIndexSetInteger(senkouABufferIndex, PLOT_SHOW_DATA, showSenkouSpanA); + PlotIndexSetInteger(senkouABufferIndex, PLOT_DRAW_TYPE, senkouSpanADrawType); + + // + // SENKOUSPANB ... + ENUM_DRAW_TYPE senkouSpanBDrawType = showSenkouSpanB ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(senkouBBuffer, true); + SetIndexBuffer(senkouBBufferIndex, senkouBBuffer, INDICATOR_DATA); + PlotIndexSetInteger(senkouBBufferIndex, PLOT_SHIFT, shiftSize); + PlotIndexSetInteger(senkouBBufferIndex, PLOT_SHOW_DATA, showSenkouSpanB); + PlotIndexSetInteger(senkouBBufferIndex, PLOT_DRAW_TYPE, senkouSpanBDrawType); + + // + // KUMO ... + + // + // SENKOUSPANA ... + ArraySetAsSeries(senkouSpanABuffer, true); + SetIndexBuffer(senkouSpanABufferIndex, senkouSpanABuffer, INDICATOR_DATA); + PlotIndexSetInteger(senkouSpanABufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + // SENKOUSPANB ... + ArraySetAsSeries(senkouSpanBBuffer, true); + SetIndexBuffer(senkouSpanBBufferIndex, senkouSpanBBuffer, INDICATOR_DATA); + PlotIndexSetInteger(senkouSpanBBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + // KUMO ... + + // + ENUM_DRAW_TYPE kumoDrawType = showKumo ? DRAW_FILLING : DRAW_NONE; + + // + PlotIndexSetInteger(kumoBufferIndex, PLOT_SHIFT, shiftSize); + PlotIndexSetInteger(kumoBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(kumoBufferIndex, PLOT_DRAW_TYPE, kumoDrawType); + + // + // DATA Buffers ... + + // + // D Tenkan ... + ArraySetAsSeries(dTenkanBuffer, true); + SetIndexBuffer(dTenkanBufferIndex, dTenkanBuffer, INDICATOR_CALCULATIONS); + + // + // D Kijun ... + ArraySetAsSeries(dKijunBuffer, true); + SetIndexBuffer(dKijunBufferIndex, dKijunBuffer, INDICATOR_CALCULATIONS); + + // + // D Chikou ... + ArraySetAsSeries(dChikouBuffer, true); + SetIndexBuffer(dChikouBufferIndex, dChikouBuffer, INDICATOR_CALCULATIONS); + + // + // D SSA ... + ArraySetAsSeries(dSSABuffer, true); + SetIndexBuffer(dSSABufferIndex, dSSABuffer, INDICATOR_CALCULATIONS); + + // + // D SSB ... + ArraySetAsSeries(dSSBBuffer, true); + SetIndexBuffer(dSSBBufferIndex, dSSBBuffer, INDICATOR_CALCULATIONS); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index // Selected Bar Index +) +{ + // + // ICHIMOKU ... + + // + double topValue; + double bottomValue; + + // + // TENKANSEN ... + + // + // Extract Tenkan Sen Top/Bottom Calculation Mode based on User Input ... + if (mTenkanSenTopMode == NULL || mTenkanSenBottomMode == NULL) + { + // + switch (tenkanSenMode) + { + // + case X_XICH_HH_LL_MODE: + // + mTenkanSenTopMode = MODE_HIGH; + mTenkanSenBottomMode = MODE_LOW; + break; + + // + case X_XICH_HO_LC_MODE: + // + mTenkanSenTopMode = MODE_OPEN; + mTenkanSenBottomMode = MODE_CLOSE; + break; + } + } + + // + XOHCL bar; + bar.Init( + _Symbol, + _Period, + bar_index + // + ); + + // + // Calculate Top ... + topValue = bar + .FindHighest( + tenkanSenLength, + mTenkanSenTopMode + // + ); + + // + // Calculate Bottom ... + bottomValue = bar + .FindLowest( + tenkanSenLength, + mTenkanSenBottomMode + // + ); + + // + double tenkanSenValue = (topValue + bottomValue) / 2; + tenkanSenBuffer[bar_index] = tenkanSenValue; + + // + // KIJUNSEN ... + + // + // Extract Kijun Sen Top/Bottom Calculation Mode based on User Input ... + if (mKijunSenTopMode == NULL || mKijunSenBottomMode == NULL) + { + // + switch (kijunSenMode) + { + // + case X_XICH_HH_LL_MODE: + // + mKijunSenTopMode = MODE_HIGH; + mKijunSenBottomMode = MODE_LOW; + break; + + // + case X_XICH_HO_LC_MODE: + // + mKijunSenTopMode = MODE_OPEN; + mKijunSenBottomMode = MODE_CLOSE; + break; + } + } + + // + // Calculate Top ... + topValue = bar + .FindHighest( + kijunSenLength, + mKijunSenTopMode + // + ); + + // + // Calculate Bottom ... + bottomValue = bar + .FindLowest( + kijunSenLength, + mKijunSenBottomMode + // + ); + + // + double kijunSenValue = (topValue + bottomValue) / 2; + kijunSenBuffer[bar_index] = kijunSenValue; + + // + kijunSenPlusBuffer[bar_index] = kijunSenValue; + kijunSenNegativeBuffer[bar_index] = kijunSenValue; + + // + // CHIKOUSPAN ... + double chikouSpanValue = bar + .GetPrice(chikuoSpanAppliedTo); + + // + chikouSpanBuffer[bar_index] = chikouSpanValue; + + // + // KUMO ... + + // + // SENKOUSPANA ... + double senkouSpanAValue = (tenkanSenValue + kijunSenValue) / 2; + senkouABuffer[bar_index] = senkouSpanAValue; + senkouSpanABuffer[bar_index] = senkouSpanAValue; + + // + // SENKOUSPANB ... + + // + // Extract Senkou Span B Top/Bottom Calculation Mode based on User Input ... + if (mSenkouSpanBTopMode == NULL || mSenkouSpanBBottomMode == NULL) + { + // + switch (senkouSpanBMode) + { + // + case X_XICH_HH_LL_MODE: + // + mSenkouSpanBTopMode = MODE_HIGH; + mSenkouSpanBBottomMode = MODE_LOW; + break; + + // + case X_XICH_HO_LC_MODE: + // + mSenkouSpanBTopMode = MODE_OPEN; + mSenkouSpanBBottomMode = MODE_CLOSE; + break; + } + } + + // + // Calculate Top ... + topValue = bar + .FindHighest( + senkouSpanBLength, + mSenkouSpanBTopMode + // + ); + + // + // Calculate Bottom ... + bottomValue = bar + .FindLowest( + senkouSpanBLength, + mSenkouSpanBBottomMode + // + ); + + // + double senkouSpanBValue = (topValue + bottomValue) / 2; + senkouBBuffer[bar_index] = senkouSpanBValue; + senkouSpanBBuffer[bar_index] = senkouSpanBValue; +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xmc.mq5 b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xmc.mq5 new file mode 100644 index 0000000..f7fe43b --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xmc.mq5 @@ -0,0 +1,446 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XMC MA Cross Indicator +// --------------------------------------------------- +// Name: XMC +// Description: Moving Average Crosses +// Market Analysor ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XMC Indicator" +#property strict + +// +// START Constants ... +// + +// +// Indicator Short Name ... +#define ShortName "XMC" + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input group "Fast"; +input int fastMaLength = 9; // Length +input int fastMaShift = 0; // Shift +input ENUM_MA_METHOD fastMaMethod = MODE_EMA; // Method +input ENUM_APPLIED_PRICE fastMaAppliedTo = PRICE_CLOSE; // Applied To + +// +input group "Slow"; +input int slowMaLength = 18; // Length +input int slowMaShift = 0; // Shift +input ENUM_MA_METHOD slowMaMethod = MODE_EMA; // Method +input ENUM_APPLIED_PRICE slowMaAppliedTo = PRICE_CLOSE; // Applied To + +// +input group "Verifier"; +input int verifierMaLength = 50; // Length +input int verifierMaShift = 0; // Shift +input ENUM_MA_METHOD verifierMaMethod = MODE_EMA; // Method +input ENUM_APPLIED_PRICE verifierMaAppliedTo = PRICE_CLOSE; // Applied To + +// +input group "Presentation"; +input bool showFastMa = true; // Show Fast +input bool showSlowMa = true; // Show Slow +input bool showVerifierMa = true; // Show Verifier + +// +// END Inputs ... +// + +// +// START Includes and Imports ... +// + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes and Imports ... +// + +// +// START Buffers ... +// +#property indicator_chart_window + +// +#property indicator_buffers 3 +#property indicator_plots 3 + +// +// PLOTTED Buffers ... + +// +// MA ... + +// +// FAST ... +#define fastMaBufferIndex 0 +double fastMaBuffer[]; + +// +#property indicator_label1 "XMC MA F" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrYellow +#property indicator_style1 STYLE_SOLID +#property indicator_width1 1 + +// +// SLOW ... +#define slowMaBufferIndex 1 +double slowMaBuffer[]; + +// +#property indicator_label2 "XMC MA S" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrDarkOrange +#property indicator_style2 STYLE_SOLID +#property indicator_width2 1 + +// +// VERIFIER ... +#define verifierMaBufferIndex 2 +double verifierMaBuffer[]; + +// +#property indicator_label3 "XMC MA V" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrDarkBlue +#property indicator_style3 STYLE_SOLID +#property indicator_width3 2 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int maxLength; + +// +int fastMaHandler = INVALID_HANDLE; +int slowMaHandler = INVALID_HANDLE; +int verifierMaHandler = INVALID_HANDLE; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // MA Initialization ... + + // + // FAST ... + fastMaHandler = iMA( + _Symbol, + _Period, + fastMaLength, + fastMaShift, + fastMaMethod, + fastMaAppliedTo); + if (fastMaHandler == INVALID_HANDLE) + { + return INIT_FAILED; + } + + // + // SLOW ... + slowMaHandler = iMA( + _Symbol, + _Period, + slowMaLength, + slowMaShift, + slowMaMethod, + slowMaAppliedTo); + if (slowMaHandler == INVALID_HANDLE) + { + return INIT_FAILED; + } + + // + // VERIFIER ... + verifierMaHandler = iMA( + _Symbol, + _Period, + verifierMaLength, + verifierMaShift, + verifierMaMethod, + verifierMaAppliedTo); + if (verifierMaHandler == INVALID_HANDLE) + { + return INIT_FAILED; + } + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Here we can handle De Initialization Reasons ... + IndicatorRelease(fastMaHandler); + IndicatorRelease(slowMaHandler); + IndicatorRelease(verifierMaHandler); +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + // Check Calculated Bars ... + int fastMaCalculatedBars = BarsCalculated(fastMaHandler); + int slowMaCalculatedBars = BarsCalculated(slowMaHandler); + int verifierMaCalculatedBars = BarsCalculated(verifierMaHandler); + if (fastMaCalculatedBars < maxLength || + slowMaCalculatedBars < maxLength || + verifierMaCalculatedBars < maxLength) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + int copiedFastMas = CopyBuffer(fastMaHandler, 0, 0, limit, fastMaBuffer); + int copiedSlowMas = CopyBuffer(slowMaHandler, 0, 0, limit, slowMaBuffer); + int copiedVerifierMas = CopyBuffer(verifierMaHandler, 0, 0, limit, verifierMaBuffer); + if (copiedFastMas <= 0 || + copiedSlowMas <= 0 || + copiedVerifierMas <= 0) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + CalculateBuffers(i); + } + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = + // + // Validate Ma ... + (fastMaLength > 2 && + slowMaLength > fastMaLength && + verifierMaLength > slowMaLength) + // + ; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + // Ma ... + result = MathMax(result, fastMaLength); + result = MathMax(result, slowMaLength); + result = MathMax(result, verifierMaLength); + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // MA ... + + // + // FAST ... + ENUM_DRAW_TYPE fastMaDrawType = showFastMa ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(fastMaBuffer, true); + SetIndexBuffer(fastMaBufferIndex, fastMaBuffer, INDICATOR_DATA); + PlotIndexSetInteger(fastMaBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fastMaBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(fastMaBufferIndex, PLOT_DRAW_TYPE, fastMaDrawType); + + // + // SLOW ... + ENUM_DRAW_TYPE slowMaDrawType = showSlowMa ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(slowMaBuffer, true); + SetIndexBuffer(slowMaBufferIndex, slowMaBuffer, INDICATOR_DATA); + PlotIndexSetInteger(slowMaBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(slowMaBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(slowMaBufferIndex, PLOT_DRAW_TYPE, slowMaDrawType); + + // + // VERIFIER ... + ENUM_DRAW_TYPE verifierMaDrawType = showVerifierMa ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(verifierMaBuffer, true); + SetIndexBuffer(verifierMaBufferIndex, verifierMaBuffer, INDICATOR_DATA); + PlotIndexSetInteger(verifierMaBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(verifierMaBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(verifierMaBufferIndex, PLOT_DRAW_TYPE, verifierMaDrawType); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + string indicatorShortName = ""; + StringConcatenate(indicatorShortName, ShortName, ""); + + // + IndicatorSetString(INDICATOR_SHORTNAME, indicatorShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index // Selected Bar Index +) +{ +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xmrb.mq5 b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xmrb.mq5 new file mode 100644 index 0000000..5ff1d82 --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xmrb.mq5 @@ -0,0 +1,855 @@ +////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// -------------------------------------- +// Name: XMRB +// Description: Moving Average Ribbon +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XMRB Indicator" +#property strict + +// +// START Constants ... +// + +// +// Indicator Short Name ... +#define ShortName "XMRB" + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input group "Ribbon 1"; +input int fast1Length = 20; // Fast +input int slow1Length = 50; // Slow +input ENUM_APPLIED_PRICE r1AppliedTo = PRICE_HIGH; // Applied To + +// +input group "Ribbon 2"; +input int fast2Length = 20; // Fast +input int slow2Length = 50; // Slow +input ENUM_APPLIED_PRICE r2AppliedTo = PRICE_OPEN; // Applied To + +// +input group "Ribbon 3"; +input int fast3Length = 20; // Fast +input int slow3Length = 50; // Slow +input ENUM_APPLIED_PRICE r3AppliedTo = PRICE_CLOSE; // Applied To + +// +input group "Ribbon 4"; +input int fast4Length = 20; // Fast +input int slow4Length = 50; // Slow +input ENUM_APPLIED_PRICE r4AppliedTo = PRICE_MEDIAN; // Applied To + +// +input group "Ribbon 5"; +input int fast5Length = 20; // Fast +input int slow5Length = 50; // Slow +input ENUM_APPLIED_PRICE r5AppliedTo = PRICE_TYPICAL; // Applied To + +// +input group "Ribbon 6"; +input int fast6Length = 20; // Fast +input int slow6Length = 50; // Slow +input ENUM_APPLIED_PRICE r6AppliedTo = PRICE_LOW; // Applied To + +// +input group "Calculation"; +input ENUM_MA_METHOD ribbonMode = MODE_EMA; // Mode + +// +input group "Presentation"; +input bool showFastMa = true; // Show Fast +input bool showSlowMa = true; // Show Slow +input bool showRibbon = false; // Show Ribbon + +// +// END Inputs ... +// + +// +// START Includes and Imports ... +// + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes and Imports ... +// + +// +// START Buffers ... +// +#property indicator_chart_window + +// +#property indicator_buffers 14 +#property indicator_plots 14 + +// +// PLOTTED Buffers ... + +// +// MA ... + +// +// FAST ... +#define fastMaBufferIndex 0 +double fastMaBuffer[]; + +// +#property indicator_label1 "XMRB F" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrLime +#property indicator_style1 STYLE_SOLID +#property indicator_width1 1 + +// +// SLOW ... +#define slowMaBufferIndex 1 +double slowMaBuffer[]; + +// +#property indicator_label2 "XMRB S" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrRed +#property indicator_style2 STYLE_SOLID +#property indicator_width2 1 + +// +// DATA Buffers ... + +// +// FAST ... + +// +#define fast1BufferIndex 2 +double fast1Buffer[]; + +// +#property indicator_label3 "XMRB 1 F" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrAquamarine +#property indicator_style3 STYLE_DOT +#property indicator_width3 1 + +// +#define fast2BufferIndex 3 +double fast2Buffer[]; + +// +#property indicator_label4 "XMRB 2 F" +#property indicator_type4 DRAW_LINE +#property indicator_color4 clrAquamarine +#property indicator_style4 STYLE_DOT +#property indicator_width4 1 + +// +#define fast3BufferIndex 4 +double fast3Buffer[]; + +// +#property indicator_label5 "XMRB 3 F" +#property indicator_type5 DRAW_LINE +#property indicator_color5 clrAquamarine +#property indicator_style5 STYLE_DOT +#property indicator_width5 1 + +// +#define fast4BufferIndex 5 +double fast4Buffer[]; + +// +#property indicator_label6 "XMRB 4 F" +#property indicator_type6 DRAW_LINE +#property indicator_color6 clrAquamarine +#property indicator_style6 STYLE_DOT +#property indicator_width6 1 + +// +#define fast5BufferIndex 6 +double fast5Buffer[]; + +// +#property indicator_label7 "XMRB 5 F" +#property indicator_type7 DRAW_LINE +#property indicator_color7 clrAquamarine +#property indicator_style7 STYLE_DOT +#property indicator_width7 1 + +// +#define fast6BufferIndex 7 +double fast6Buffer[]; + +// +#property indicator_label8 "XMRB 6 F" +#property indicator_type8 DRAW_LINE +#property indicator_color8 clrAquamarine +#property indicator_style8 STYLE_DOT +#property indicator_width8 1 + +// +// SLOW ... + +// +#define slow1BufferIndex 8 +double slow1Buffer[]; + +// +#property indicator_label9 "XMRB 1 S" +#property indicator_type9 DRAW_LINE +#property indicator_color9 clrPlum +#property indicator_style9 STYLE_DOT +#property indicator_width9 1 + +// +#define slow2BufferIndex 9 +double slow2Buffer[]; + +// +#property indicator_label10 "XMRB 2 S" +#property indicator_type10 DRAW_LINE +#property indicator_color10 clrPlum +#property indicator_style10 STYLE_DOT +#property indicator_width10 1 + +// +#define slow3BufferIndex 10 +double slow3Buffer[]; + +// +#property indicator_label11 "XMRB 3 S" +#property indicator_type11 DRAW_LINE +#property indicator_color11 clrPlum +#property indicator_style11 STYLE_DOT +#property indicator_width11 1 + +// +#define slow4BufferIndex 11 +double slow4Buffer[]; + +// +#property indicator_label12 "XMRB 4 S" +#property indicator_type12 DRAW_LINE +#property indicator_color12 clrPlum +#property indicator_style12 STYLE_DOT +#property indicator_width12 1 + +// +#define slow5BufferIndex 12 +double slow5Buffer[]; + +// +#property indicator_label13 "XMRB 5 S" +#property indicator_type13 DRAW_LINE +#property indicator_color13 clrPlum +#property indicator_style13 STYLE_DOT +#property indicator_width13 1 + +// +#define slow6BufferIndex 13 +double slow6Buffer[]; + +// +#property indicator_label14 "XMRB 6 S" +#property indicator_type14 DRAW_LINE +#property indicator_color14 clrPlum +#property indicator_style14 STYLE_DOT +#property indicator_width14 1 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int maxLength; + +// +int fast1MaHandler = INVALID_HANDLE; +int fast2MaHandler = INVALID_HANDLE; +int fast3MaHandler = INVALID_HANDLE; +int fast4MaHandler = INVALID_HANDLE; +int fast5MaHandler = INVALID_HANDLE; +int fast6MaHandler = INVALID_HANDLE; + +// +int slow1MaHandler = INVALID_HANDLE; +int slow2MaHandler = INVALID_HANDLE; +int slow3MaHandler = INVALID_HANDLE; +int slow4MaHandler = INVALID_HANDLE; +int slow5MaHandler = INVALID_HANDLE; +int slow6MaHandler = INVALID_HANDLE; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Initialize MAs ... + if (!InitializeMas()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Here we can handle De Initialization Reasons ... + + // + IndicatorRelease(fast1MaHandler); + IndicatorRelease(fast2MaHandler); + IndicatorRelease(fast3MaHandler); + IndicatorRelease(fast4MaHandler); + IndicatorRelease(fast5MaHandler); + IndicatorRelease(fast6MaHandler); + + // + IndicatorRelease(slow1MaHandler); + IndicatorRelease(slow2MaHandler); + IndicatorRelease(slow3MaHandler); + IndicatorRelease(slow4MaHandler); + IndicatorRelease(slow5MaHandler); + IndicatorRelease(slow6MaHandler); +} + +// +// Calculating what we want ... +int OnCalculate( + const int rates_total, // Total Bars on Chart ... + const int prev_calculated, // Total Calculated Bars on Charts ... + const datetime &time[], // History of Open Time ... + const double &open[], // History of Open Price ... + const double &high[], // History of High Price ... + const double &low[], // History of Low Price ... + const double &close[], // History of Close Price ... + const long &tick_volume[], // History of Tick Volumes on Bar ... + const long &volume[], // History of Trade Volumes ... + const int &spread[] // History of Spread Price ... +) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + // Check Calculated Bars ... + // + int fast1MaCalculatedBars = BarsCalculated(fast1MaHandler); + int fast2MaCalculatedBars = BarsCalculated(fast2MaHandler); + int fast3MaCalculatedBars = BarsCalculated(fast3MaHandler); + int fast4MaCalculatedBars = BarsCalculated(fast4MaHandler); + int fast5MaCalculatedBars = BarsCalculated(fast5MaHandler); + int fast6MaCalculatedBars = BarsCalculated(fast6MaHandler); + // + int slow1MaCalculatedBars = BarsCalculated(slow1MaHandler); + int slow2MaCalculatedBars = BarsCalculated(slow2MaHandler); + int slow3MaCalculatedBars = BarsCalculated(slow3MaHandler); + int slow4MaCalculatedBars = BarsCalculated(slow4MaHandler); + int slow5MaCalculatedBars = BarsCalculated(slow5MaHandler); + int slow6MaCalculatedBars = BarsCalculated(slow6MaHandler); + if ( + fast1MaCalculatedBars < maxLength || + fast2MaCalculatedBars < maxLength || + fast3MaCalculatedBars < maxLength || + fast4MaCalculatedBars < maxLength || + fast5MaCalculatedBars < maxLength || + fast6MaCalculatedBars < maxLength || + slow1MaCalculatedBars < maxLength || + slow2MaCalculatedBars < maxLength || + slow3MaCalculatedBars < maxLength || + slow4MaCalculatedBars < maxLength || + slow5MaCalculatedBars < maxLength || + slow6MaCalculatedBars < maxLength // + ) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + // + int copiedFast1Mas = CopyBuffer(fast1MaHandler, 0, 0, limit, fast1Buffer); + int copiedFast2Mas = CopyBuffer(fast2MaHandler, 0, 0, limit, fast2Buffer); + int copiedFast3Mas = CopyBuffer(fast3MaHandler, 0, 0, limit, fast3Buffer); + int copiedFast4Mas = CopyBuffer(fast4MaHandler, 0, 0, limit, fast4Buffer); + int copiedFast5Mas = CopyBuffer(fast5MaHandler, 0, 0, limit, fast5Buffer); + int copiedFast6Mas = CopyBuffer(fast6MaHandler, 0, 0, limit, fast6Buffer); + // + int copiedSlow1Mas = CopyBuffer(slow1MaHandler, 0, 0, limit, slow1Buffer); + int copiedSlow2Mas = CopyBuffer(slow2MaHandler, 0, 0, limit, slow2Buffer); + int copiedSlow3Mas = CopyBuffer(slow3MaHandler, 0, 0, limit, slow3Buffer); + int copiedSlow4Mas = CopyBuffer(slow4MaHandler, 0, 0, limit, slow4Buffer); + int copiedSlow5Mas = CopyBuffer(slow5MaHandler, 0, 0, limit, slow5Buffer); + int copiedSlow6Mas = CopyBuffer(slow6MaHandler, 0, 0, limit, slow6Buffer); + if ( + copiedFast1Mas <= 0 || + copiedFast2Mas <= 0 || + copiedFast3Mas <= 0 || + copiedFast4Mas <= 0 || + copiedFast5Mas <= 0 || + copiedFast6Mas <= 0 || + copiedSlow1Mas <= 0 || + copiedSlow2Mas <= 0 || + copiedSlow3Mas <= 0 || + copiedSlow4Mas <= 0 || + copiedSlow5Mas <= 0 || + copiedSlow6Mas <= 0 // + ) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + CalculateBuffers(i); + } + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = + // + (fast1Length > 2 && + fast2Length > 2 && + fast3Length > 2 && + fast4Length > 2 && + fast5Length > 2 && + fast6Length > 2 && + slow1Length > fast1Length && + slow2Length > fast2Length && + slow3Length > fast3Length && + slow4Length > fast4Length && + slow5Length > fast5Length && + slow6Length > fast6Length + // + ) + // + ; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + // Ma ... + + // + result = MathMax(fast1Length, fast2Length); + result = MathMax(result, fast3Length); + result = MathMax(result, fast4Length); + result = MathMax(result, fast5Length); + result = MathMax(result, fast6Length); + + // + result = MathMax(result, slow1Length); + result = MathMax(result, slow2Length); + result = MathMax(result, slow3Length); + result = MathMax(result, slow4Length); + result = MathMax(result, slow5Length); + result = MathMax(result, slow6Length); + + // + return result; +} + +// +// Initialize Ma Handlers ... +bool InitializeMas() +{ + // + bool result = false; + + // + fast1MaHandler = iMA( + _Symbol, + _Period, + fast1Length, + 0, + ribbonMode, + r1AppliedTo); + fast2MaHandler = iMA( + _Symbol, + _Period, + fast2Length, + 0, + ribbonMode, + r2AppliedTo); + fast3MaHandler = iMA( + _Symbol, + _Period, + fast3Length, + 0, + ribbonMode, + r3AppliedTo); + fast4MaHandler = iMA( + _Symbol, + _Period, + fast4Length, + 0, + ribbonMode, + r4AppliedTo); + fast5MaHandler = iMA( + _Symbol, + _Period, + fast5Length, + 0, + ribbonMode, + r5AppliedTo); + fast6MaHandler = iMA( + _Symbol, + _Period, + fast6Length, + 0, + ribbonMode, + r6AppliedTo); + + // + slow1MaHandler = iMA( + _Symbol, + _Period, + slow1Length, + 0, + ribbonMode, + r1AppliedTo); + slow2MaHandler = iMA( + _Symbol, + _Period, + slow2Length, + 0, + ribbonMode, + r2AppliedTo); + slow3MaHandler = iMA( + _Symbol, + _Period, + slow3Length, + 0, + ribbonMode, + r3AppliedTo); + slow4MaHandler = iMA( + _Symbol, + _Period, + slow4Length, + 0, + ribbonMode, + r4AppliedTo); + slow5MaHandler = iMA( + _Symbol, + _Period, + slow5Length, + 0, + ribbonMode, + r5AppliedTo); + slow6MaHandler = iMA( + _Symbol, + _Period, + slow6Length, + 0, + ribbonMode, + r6AppliedTo); + + // + result = + fast1MaHandler != INVALID_HANDLE && + fast2MaHandler != INVALID_HANDLE && + fast3MaHandler != INVALID_HANDLE && + fast4MaHandler != INVALID_HANDLE && + fast5MaHandler != INVALID_HANDLE && + fast6MaHandler != INVALID_HANDLE && + slow1MaHandler != INVALID_HANDLE && + slow2MaHandler != INVALID_HANDLE && + slow3MaHandler != INVALID_HANDLE && + slow4MaHandler != INVALID_HANDLE && + slow5MaHandler != INVALID_HANDLE && + slow6MaHandler != INVALID_HANDLE; + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // FAST ... + ENUM_DRAW_TYPE fastDrawType = showFastMa ? DRAW_LINE : DRAW_NONE; + + ArraySetAsSeries(fastMaBuffer, true); + SetIndexBuffer(fastMaBufferIndex, fastMaBuffer, INDICATOR_DATA); + PlotIndexSetInteger(fastMaBufferIndex, PLOT_SHOW_DATA, showFastMa); + PlotIndexSetInteger(fastMaBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fastMaBufferIndex, PLOT_DRAW_TYPE, fastDrawType); + + // + // SLOW ... + ENUM_DRAW_TYPE slowDrawType = showSlowMa ? DRAW_LINE : DRAW_NONE; + + ArraySetAsSeries(slowMaBuffer, true); + SetIndexBuffer(slowMaBufferIndex, slowMaBuffer, INDICATOR_DATA); + PlotIndexSetInteger(slowMaBufferIndex, PLOT_SHOW_DATA, showSlowMa); + PlotIndexSetInteger(slowMaBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(slowMaBufferIndex, PLOT_DRAW_TYPE, slowDrawType); + + // + // DATA ... + ENUM_DRAW_TYPE ribbonDrawType = showRibbon ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(fast1Buffer, true); + SetIndexBuffer(fast1BufferIndex, fast1Buffer, INDICATOR_DATA); + PlotIndexSetInteger(fast1BufferIndex, PLOT_SHOW_DATA, showRibbon); + PlotIndexSetInteger(fast1BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fast1BufferIndex, PLOT_DRAW_TYPE, ribbonDrawType); + + // + ArraySetAsSeries(fast2Buffer, true); + SetIndexBuffer(fast2BufferIndex, fast2Buffer, INDICATOR_DATA); + PlotIndexSetInteger(fast2BufferIndex, PLOT_SHOW_DATA, showRibbon); + PlotIndexSetInteger(fast2BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fast2BufferIndex, PLOT_DRAW_TYPE, ribbonDrawType); + + // + ArraySetAsSeries(fast3Buffer, true); + SetIndexBuffer(fast3BufferIndex, fast3Buffer, INDICATOR_DATA); + PlotIndexSetInteger(fast3BufferIndex, PLOT_SHOW_DATA, showRibbon); + PlotIndexSetInteger(fast3BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fast3BufferIndex, PLOT_DRAW_TYPE, ribbonDrawType); + + // + ArraySetAsSeries(fast4Buffer, true); + SetIndexBuffer(fast4BufferIndex, fast4Buffer, INDICATOR_DATA); + PlotIndexSetInteger(fast4BufferIndex, PLOT_SHOW_DATA, showRibbon); + PlotIndexSetInteger(fast4BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fast4BufferIndex, PLOT_DRAW_TYPE, ribbonDrawType); + + // + ArraySetAsSeries(fast5Buffer, true); + SetIndexBuffer(fast5BufferIndex, fast5Buffer, INDICATOR_DATA); + PlotIndexSetInteger(fast5BufferIndex, PLOT_SHOW_DATA, showRibbon); + PlotIndexSetInteger(fast5BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fast5BufferIndex, PLOT_DRAW_TYPE, ribbonDrawType); + + // + ArraySetAsSeries(fast6Buffer, true); + SetIndexBuffer(fast6BufferIndex, fast6Buffer, INDICATOR_DATA); + PlotIndexSetInteger(fast6BufferIndex, PLOT_SHOW_DATA, showRibbon); + PlotIndexSetInteger(fast6BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fast6BufferIndex, PLOT_DRAW_TYPE, ribbonDrawType); + + // + ArraySetAsSeries(slow1Buffer, true); + SetIndexBuffer(slow1BufferIndex, slow1Buffer, INDICATOR_DATA); + PlotIndexSetInteger(slow1BufferIndex, PLOT_SHOW_DATA, showRibbon); + PlotIndexSetInteger(slow1BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(slow1BufferIndex, PLOT_DRAW_TYPE, ribbonDrawType); + + // + ArraySetAsSeries(slow2Buffer, true); + SetIndexBuffer(slow2BufferIndex, slow2Buffer, INDICATOR_DATA); + PlotIndexSetInteger(slow2BufferIndex, PLOT_SHOW_DATA, showRibbon); + PlotIndexSetInteger(slow2BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(slow2BufferIndex, PLOT_DRAW_TYPE, ribbonDrawType); + + // + ArraySetAsSeries(slow3Buffer, true); + SetIndexBuffer(slow3BufferIndex, slow3Buffer, INDICATOR_DATA); + PlotIndexSetInteger(slow3BufferIndex, PLOT_SHOW_DATA, showRibbon); + PlotIndexSetInteger(slow3BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(slow3BufferIndex, PLOT_DRAW_TYPE, ribbonDrawType); + + // + ArraySetAsSeries(slow4Buffer, true); + SetIndexBuffer(slow4BufferIndex, slow4Buffer, INDICATOR_DATA); + PlotIndexSetInteger(slow4BufferIndex, PLOT_SHOW_DATA, showRibbon); + PlotIndexSetInteger(slow4BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(slow4BufferIndex, PLOT_DRAW_TYPE, ribbonDrawType); + + // + ArraySetAsSeries(slow5Buffer, true); + SetIndexBuffer(slow5BufferIndex, slow5Buffer, INDICATOR_DATA); + PlotIndexSetInteger(slow5BufferIndex, PLOT_SHOW_DATA, showRibbon); + PlotIndexSetInteger(slow5BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(slow5BufferIndex, PLOT_DRAW_TYPE, ribbonDrawType); + + // + ArraySetAsSeries(slow6Buffer, true); + SetIndexBuffer(slow6BufferIndex, slow6Buffer, INDICATOR_DATA); + PlotIndexSetInteger(slow6BufferIndex, PLOT_SHOW_DATA, showRibbon); + PlotIndexSetInteger(slow6BufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(slow6BufferIndex, PLOT_DRAW_TYPE, ribbonDrawType); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index // Selected Bar Index +) +{ + // + // Retireve Values ... + + // + double fast1Value = fast1Buffer[bar_index]; + double fast2Value = fast2Buffer[bar_index]; + double fast3Value = fast3Buffer[bar_index]; + double fast4Value = fast4Buffer[bar_index]; + double fast5Value = fast5Buffer[bar_index]; + double fast6Value = fast6Buffer[bar_index]; + + // + double fasts[] = { + fast1Value, + fast2Value, + fast3Value, + fast4Value, + fast5Value, + fast6Value}; + + // + double slow1Value = slow1Buffer[bar_index]; + double slow2Value = slow2Buffer[bar_index]; + double slow3Value = slow3Buffer[bar_index]; + double slow4Value = slow4Buffer[bar_index]; + double slow5Value = slow5Buffer[bar_index]; + double slow6Value = slow6Buffer[bar_index]; + + // + double slows[] = { + slow1Value, + slow2Value, + slow3Value, + slow4Value, + slow5Value, + slow6Value}; + + // + double fastValue = GetAverage(fasts); + fastMaBuffer[bar_index] = fastValue; + + // + double slowValue = GetAverage(slows); + slowMaBuffer[bar_index] = slowValue; +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xosc.mq5 b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xosc.mq5 new file mode 100644 index 0000000..ecf3a27 --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xosc.mq5 @@ -0,0 +1,721 @@ +////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// --------------------------------------------- +// Name: XOSC +// Description: provides some oscillator values +// as empty Indicator ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121_XAMA Indicator" +#property strict + +// +// START Constants ... +// + +#define ShortName "XOSC" + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +// ATR ... +input group "ATR"; +input int atrLength = 14; // Length + +// +// RVI ... +// The buffer numbers are the following: 0 - MAIN_LINE, 1 - SIGNAL_LINE. +input group "RVI"; +input int rviLength = 10; // Length + +// +// BULLPOWER ... +input group "Bulls Power"; +input int bullpLength = 13; // Length + +// +// BEARPOWER ... +input group "Bears Power"; +input int bearpLength = 13; // Length + +// +// VOLUME ... +input group "Volumes"; +input ENUM_APPLIED_VOLUME volumeAppliedTo = VOLUME_TICK; // Applied To + +// +// RSI ... +input group "RSI"; +input int rsiLength = 14; // Length +input ENUM_APPLIED_PRICE rsiAppliedTo = PRICE_CLOSE; // Applied To + +// +// CCI ... +input group "CCI"; +input int cciLength = 14; // Length +input ENUM_APPLIED_PRICE cciAppliedTo = PRICE_TYPICAL; // Applied To + +// +// STDDEV ... +input group "Standard Deviation"; +input int stddevLength = 20; // Length +input int stddevShift = 0; // Shift +input ENUM_MA_METHOD stddevMethod = MODE_SMA; // Mode +input ENUM_APPLIED_PRICE stddevAppliedTo = PRICE_CLOSE; // AppliedTo + +// +// MOMENTUM ... +input group "Momentum"; +input int momentumLength = 14; // Length +input ENUM_APPLIED_PRICE momentumAppliedTo = PRICE_CLOSE; // Applied To + +// +// SAR ... +input group "SAR"; +input double sarStep = 0.02; // Step +input double sarMaximum = 0.2; // Maximum + +// +// MACD ... +// The buffer numbers are the following: 0 - MAIN_LINE, 1 - SIGNAL_LINE. +input group "MACD"; +input int macdFastLength = 12; // Fast Length +input int macdSlowLength = 26; // Slow Length +input int macdSignaLength = 9; // Signal Length +input ENUM_APPLIED_PRICE macdAppliedTo = PRICE_CLOSE; // Applied To + +// +// STOCHASTIC ... +// The buffer numbers: 0 - MAIN_LINE, 1 - SIGNAL_LINE. +input group "Stochastic"; +input int stochKLength = 5; // K Length +input int stochDLength = 3; // D Length +input int stochSlowing = 3; // Slowing +input ENUM_MA_METHOD stochMaMethod = MODE_SMA; // Ma Method +input ENUM_STO_PRICE stochMode = STO_LOWHIGH; // Calculation Mode + +// +// END Inputs ... +// + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Buffers ... +// + +// +#property indicator_chart_window + +// +#property indicator_buffers 15 +#property indicator_plots 0 + +// +// ATR ... +#define atrBufferIndex 0 +double atrBuffer[]; + +// +// RVI ... +#define rviMainBufferIndex 1 +#define rviSignalBufferIndex 2 +double rviMainBuffer[]; +double rviSignalBuffer[]; + +// +// BULLPOWER ... +#define bullPBufferIndex 3 +double bullPBuffer[]; + +// +// BEARPOWER ... +#define bearPBufferIndex 4 +double bearPBuffer[]; + +// +// VOLUME ... +#define volumeBufferIndex 5 +double volumeBuffer[]; + +// +// RSI ... +#define rsiBufferIndex 6 +double rsiBuffer[]; + +// +// CCI ... +#define cciBufferIndex 7 +double cciBuffer[]; + +// +// MOMENTUM ... +#define momentumBufferIndex 8 +double momentumBuffer[]; + +// +// SAR ... +#define sarBufferIndex 9 +double sarBuffer[]; + +// +// MACD ... +#define macdMainBufferIndex 10 +#define macdSignalBufferIndex 11 +double macdMainBuffer[]; +double macdSignalBuffer[]; + +// +// STOCHASTIC ... +#define stochMainBufferIndex 12 +#define stochSignalBufferIndex 13 +double stochMainBuffer[]; +double stochSignalBuffer[]; + +// +// STANDARDDEVIATION ... +#define stddevBufferIndex 14 +double stddevBuffer[]; + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int maxLength; + +// +int atrHandler = INVALID_HANDLE; +int rviHandler = INVALID_HANDLE; +int bullPHandler = INVALID_HANDLE; +int bearPHandler = INVALID_HANDLE; +int volumeHandler = INVALID_HANDLE; +int rsiHandler = INVALID_HANDLE; +int cciHandler = INVALID_HANDLE; +int momentumHandler = INVALID_HANDLE; +int sarHandler = INVALID_HANDLE; +int macdHandler = INVALID_HANDLE; +int stochHandler = INVALID_HANDLE; +int stddevHandler = INVALID_HANDLE; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Initializing Handlers ... + + // + // ATR ... + atrHandler = iATR( + _Symbol, + _Period, + atrLength); + + // + // RVI ... + rviHandler = iRVI( + _Symbol, + _Period, + rviLength); + + // + // BULLSPOWER ... + bullPHandler = iBullsPower( + _Symbol, + _Period, + bullpLength); + + // + // BEARSPOWER ... + bearPHandler = iBearsPower( + _Symbol, + _Period, + bullpLength); + + // + // VOLUMES ... + volumeHandler = iVolumes( + _Symbol, + _Period, + volumeAppliedTo); + + // + // RSI ... + rsiHandler = iRSI( + _Symbol, + _Period, + rsiLength, + rsiAppliedTo); + + // + // CCI ... + cciHandler = iCCI( + _Symbol, + _Period, + cciLength, + cciAppliedTo); + + // + // MOMENTUM ... + momentumHandler = iMomentum( + _Symbol, + _Period, + momentumLength, + momentumAppliedTo); + + // + // SAR ... + sarHandler = iSAR( + _Symbol, + _Period, + sarStep, + sarMaximum); + + // + // MACD ... + macdHandler = iMACD( + _Symbol, + _Period, + macdFastLength, + macdSlowLength, + macdSignaLength, + macdAppliedTo); + + // + // STOCHASTIC ... + stochHandler = iStochastic( + _Symbol, + _Period, + stochKLength, + stochDLength, + stochSlowing, + stochMaMethod, + stochMode); + + // + // STANDARDDEVIATION ... + stddevHandler = iStdDev( + _Symbol, + _Period, + stddevLength, + stddevShift, + stddevMethod, + stddevAppliedTo); + + // + bool isAllHandlersInit = + // + atrHandler != INVALID_HANDLE && + rviHandler != INVALID_HANDLE && + bullPHandler != INVALID_HANDLE && + bearPHandler != INVALID_HANDLE && + volumeHandler != INVALID_HANDLE && + rsiHandler != INVALID_HANDLE && + cciHandler != INVALID_HANDLE && + momentumHandler != INVALID_HANDLE && + sarHandler != INVALID_HANDLE && + macdHandler != INVALID_HANDLE && + stochHandler != INVALID_HANDLE && + stddevHandler != INVALID_HANDLE + // + ; + if (!isAllHandlersInit) + { + return INIT_FAILED; + } + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Here we can handle De Initialization Reasons ... + IndicatorRelease(atrHandler); + IndicatorRelease(rviHandler); + IndicatorRelease(bullPHandler); + IndicatorRelease(bearPHandler); + IndicatorRelease(volumeHandler); + IndicatorRelease(rsiHandler); + IndicatorRelease(cciHandler); + IndicatorRelease(momentumHandler); + IndicatorRelease(sarHandler); + IndicatorRelease(macdHandler); + IndicatorRelease(stochHandler); + IndicatorRelease(stddevHandler); +} + +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + // Check Calculated Bars ... + int atrCalculatedBars = BarsCalculated(atrHandler); + int rviCalculatedBars = BarsCalculated(rviHandler); + int bullPCalculatedBars = BarsCalculated(bullPHandler); + int bearPCalculatedBars = BarsCalculated(bearPHandler); + int volumeCalculatedBars = BarsCalculated(volumeHandler); + int rsiCalculatedBars = BarsCalculated(rsiHandler); + int cciCalculatedBars = BarsCalculated(cciHandler); + int momentumCalculatedBars = BarsCalculated(momentumHandler); + int sarCalculatedBars = BarsCalculated(sarHandler); + int macdCalculatedBars = BarsCalculated(macdHandler); + int stochCalculatedBars = BarsCalculated(stochHandler); + int stddevCalculatedBars = BarsCalculated(stddevHandler); + + // + bool isCalculatedBarsPassed = + // + atrCalculatedBars >= maxLength && + rviCalculatedBars >= maxLength && + bullPCalculatedBars >= maxLength && + bearPCalculatedBars >= maxLength && + volumeCalculatedBars >= maxLength && + rsiCalculatedBars >= maxLength && + cciCalculatedBars >= maxLength && + momentumCalculatedBars >= maxLength && + sarCalculatedBars >= maxLength && + macdCalculatedBars >= maxLength && + stochCalculatedBars >= maxLength && + stddevCalculatedBars >= maxLength + // + ; + if (!isCalculatedBarsPassed) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + int atrCopiedItems = CopyBuffer(atrHandler, 0, 0, limit, atrBuffer); + int rviMainCopiedItems = CopyBuffer(rviHandler, MAIN_LINE, 0, limit, rviMainBuffer); + int rviSignalCopiedItems = CopyBuffer(rviHandler, SIGNAL_LINE, 0, limit, rviSignalBuffer); + int bullPCopiedItems = CopyBuffer(bullPHandler, 0, 0, limit, bullPBuffer); + int bearPCopiedItems = CopyBuffer(bearPHandler, 0, 0, limit, bearPBuffer); + int volumeCopiedItems = CopyBuffer(volumeHandler, 0, 0, limit, volumeBuffer); + int rsiCopiedItems = CopyBuffer(rsiHandler, 0, 0, limit, rsiBuffer); + int cciCopiedItems = CopyBuffer(cciHandler, 0, 0, limit, cciBuffer); + int momentumCopiedItems = CopyBuffer(momentumHandler, 0, 0, limit, momentumBuffer); + int sarCopiedItems = CopyBuffer(sarHandler, 0, 0, limit, sarBuffer); + int macdMainCopiedItems = CopyBuffer(macdHandler, MAIN_LINE, 0, limit, macdMainBuffer); + int macdSignalCopiedItems = CopyBuffer(macdHandler, SIGNAL_LINE, 0, limit, macdSignalBuffer); + int stochMainCopiedItems = CopyBuffer(stochHandler, MAIN_LINE, 0, limit, stochMainBuffer); + int stocSignalhCopiedItems = CopyBuffer(stochHandler, SIGNAL_LINE, 0, limit, stochSignalBuffer); + int stddevCopiedItems = CopyBuffer(stddevHandler, 0, 0, limit, stddevBuffer); + + // + bool isCopiedBarsPassed = + // + atrCopiedItems > 0 && + rviMainCopiedItems > 0 && + rviSignalCopiedItems > 0 && + bullPCopiedItems > 0 && + bearPCopiedItems > 0 && + volumeCopiedItems > 0 && + rsiCopiedItems > 0 && + cciCopiedItems > 0 && + momentumCopiedItems > 0 && + sarCopiedItems > 0 && + macdMainCopiedItems > 0 && + macdSignalCopiedItems > 0 && + stochMainCopiedItems > 0 && + stocSignalhCopiedItems > 0 && + stddevCopiedItems > 0 + // + ; + if (!isCopiedBarsPassed) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + // Do Buffers Calculation ... + // HERE We Do Not anything ... + } + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + // Validate Args ... + result = + // + atrLength >= 2 && + rviLength >= 2 && + bullpLength >= 2 && + bearpLength >= 2 && + rsiLength >= 2 && + cciLength >= 2 && + momentumLength >= 2 && + sarStep > 0 && + sarStep < sarMaximum && + macdFastLength >= 2 && + macdSlowLength > macdFastLength && + macdSignaLength >= 2 && + stochKLength >= 2 && + stochDLength >= 2 && + stochSlowing >= 2 && + stddevLength >= 2 && + stddevShift >= 0 + // + ; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(atrLength, rviLength); + result = MathMax(result, bullpLength); + result = MathMax(result, bearpLength); + result = MathMax(result, rsiLength); + result = MathMax(result, cciLength); + result = MathMax(result, momentumLength); + result = MathMax(result, macdFastLength); + result = MathMax(result, macdSlowLength); + result = MathMax(result, macdSignaLength); + result = MathMax(result, stochKLength); + result = MathMax(result, stochDLength); + result = MathMax(result, stochSlowing); + result = MathMax(result, stddevLength); + + // + return result; +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // DATA Buffers ... + + // + // ATR ... + ArraySetAsSeries(atrBuffer, true); + SetIndexBuffer(atrBufferIndex, atrBuffer, INDICATOR_CALCULATIONS); + + // + // RVI ... + + // + // Main ... + ArraySetAsSeries(rviMainBuffer, true); + SetIndexBuffer(rviMainBufferIndex, rviMainBuffer, INDICATOR_CALCULATIONS); + + // + // Signal ... + ArraySetAsSeries(rviSignalBuffer, true); + SetIndexBuffer(rviSignalBufferIndex, rviSignalBuffer, INDICATOR_CALCULATIONS); + + // + // BULLPOWER ... + ArraySetAsSeries(bullPBuffer, true); + SetIndexBuffer(bullPBufferIndex, bullPBuffer, INDICATOR_CALCULATIONS); + + // + // BEARPOWER ... + ArraySetAsSeries(bearPBuffer, true); + SetIndexBuffer(bearPBufferIndex, bearPBuffer, INDICATOR_CALCULATIONS); + + // + // VOLUME ... + ArraySetAsSeries(volumeBuffer, true); + SetIndexBuffer(volumeBufferIndex, volumeBuffer, INDICATOR_CALCULATIONS); + + // + // RSI ... + ArraySetAsSeries(rsiBuffer, true); + SetIndexBuffer(rsiBufferIndex, rsiBuffer, INDICATOR_CALCULATIONS); + + // + // CCI ... + ArraySetAsSeries(cciBuffer, true); + SetIndexBuffer(cciBufferIndex, cciBuffer, INDICATOR_CALCULATIONS); + + // + // MOMENTUM ... + ArraySetAsSeries(momentumBuffer, true); + SetIndexBuffer(momentumBufferIndex, momentumBuffer, INDICATOR_CALCULATIONS); + + // + // SAR ... + ArraySetAsSeries(sarBuffer, true); + SetIndexBuffer(sarBufferIndex, sarBuffer, INDICATOR_CALCULATIONS); + + // + // STANDARDDEVIATION ... + ArraySetAsSeries(stddevBuffer, true); + SetIndexBuffer(stddevBufferIndex, stddevBuffer, INDICATOR_CALCULATIONS); + + // + // MACD ... + + // + // Main ... + ArraySetAsSeries(macdMainBuffer, true); + SetIndexBuffer(macdMainBufferIndex, macdMainBuffer, INDICATOR_CALCULATIONS); + + // + // Signal ... + ArraySetAsSeries(macdSignalBuffer, true); + SetIndexBuffer(macdSignalBufferIndex, macdSignalBuffer, INDICATOR_CALCULATIONS); +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xpv.mq5 b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xpv.mq5 new file mode 100644 index 0000000..d724dd2 --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xpv.mq5 @@ -0,0 +1,1211 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XPV +// Description: Peaks and Vales ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XPV Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "XPV" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +input group "Makret Cycles"; + +// +input group "Short"; +input ENUM_X_PERIOD_METHOD scMethod = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES scPeriod = NULL; // Time Period + +// +input group "Medium"; +input ENUM_X_PERIOD_METHOD mcMethod = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES mcPeriod = NULL; // Time Period + +// +input group "Long"; +input ENUM_X_PERIOD_METHOD lcMethod = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES lcPeriod = NULL; // Time Period + +// +input group "Hind"; +input ENUM_X_PERIOD_METHOD hcMethod = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES hcPeriod = NULL; // Time Period + +// +input group "Fibonacci"; +input double fiboLevel1 = 0.236; // Fibio 1st Level +input double fiboLevel2 = 0.382; // Fibio 2st Level +input double fiboLevel3 = 0.5; // Fibio 3rd Level +input double fiboLevel4 = 0.618; // Fibio 4th Level +input double fiboLevel5 = 0.764; // Fibio 5th Level + +// +input group "Boundary Detection Modes"; +input ENUM_SERIESMODE hhMode = MODE_HIGH; // Highest High Calculation Method +input ENUM_SERIESMODE llMode = MODE_LOW; // Lowest Low Calculation Method + +// +input group "Presentation"; +input bool showPeaksAndVales = true; // Show Peaks and Vales +input bool showLevels = false; // Show Levels +input bool showConsolidations = false; // Show Consolidations +input bool showFibo1Levels = false; // Show Fibo 1st Level +input bool showFibo2Levels = false; // Show Fibo 2nd Level +input bool showFibo3Levels = false; // Show Fibo 3rd Level +input bool showFibo4Levels = false; // Show Fibo 4th Level +input bool showFibo5Levels = false; // Show Fibo 5th Level + +// +// Buffers ... + +// +#property indicator_chart_window + +// +#property indicator_buffers 32 +#property indicator_plots 32 + +// +// PEAKS ... + +// +#define peaksBufferIndex 0 +double peaksBuffer[]; + +// +#property indicator_label1 "XPV PEAKS" +#property indicator_type1 DRAW_ARROW +#property indicator_color1 clrAqua +#property indicator_width1 1 + +// +// VALES ... + +// +#define valesBufferIndex 1 +double valesBuffer[]; + +// +#property indicator_label2 "XPV VALES" +#property indicator_type2 DRAW_ARROW +#property indicator_color2 clrMagenta +#property indicator_width2 1 + +// +#define rBufferIndex 2 +double rBuffer[]; + +// +#define rColorBufferIndex 3 +double rColorBuffer[]; + +// +#property indicator_label3 "XPV R" +#property indicator_type3 DRAW_COLOR_LINE +#property indicator_color3 CLR_NONE, clrAqua +#property indicator_style3 STYLE_DOT +#property indicator_width3 1 + +// +#define sBufferIndex 4 +#define sBufferPlotIndex 3 +double sBuffer[]; + +// +#define sColorBufferIndex 5 +double sColorBuffer[]; + +// +#property indicator_label4 "XPV S" +#property indicator_type4 DRAW_COLOR_LINE +#property indicator_color4 CLR_NONE, clrMagenta +#property indicator_style4 STYLE_DOT +#property indicator_width4 1 + +// +// FIBBO Level 1 ... + +// +#define fl1BufferIndex 6 +#define fl1BufferPlotIndex 4 +double fl1Buffer[]; + +// +#define fl1ColorBufferIndex 7 +double fl1ColorBuffer[]; + +// +#property indicator_label5 "XPV FL1" +#property indicator_type5 DRAW_COLOR_LINE +#property indicator_color5 CLR_NONE, clrGold +#property indicator_style5 STYLE_DASHDOTDOT +#property indicator_width5 1 + +// +// FIBBO Level 2 ... + +// +#define fl2BufferIndex 8 +#define fl2BufferPlotIndex 5 +double fl2Buffer[]; + +// +#define fl2ColorBufferIndex 9 +double fl2ColorBuffer[]; + +// +#property indicator_label6 "XPV FL2" +#property indicator_type6 DRAW_COLOR_LINE +#property indicator_color6 CLR_NONE, clrGold +#property indicator_style6 STYLE_DASHDOTDOT +#property indicator_width6 1 + +// +// FIBBO Level 3 ... + +// +#define fl3BufferIndex 10 +#define fl3BufferPlotIndex 6 +double fl3Buffer[]; + +// +#define fl3ColorBufferIndex 11 +double fl3ColorBuffer[]; + +// +#property indicator_label7 "XPV FL3" +#property indicator_type7 DRAW_COLOR_LINE +#property indicator_color7 CLR_NONE, clrGold +#property indicator_style7 STYLE_DASHDOTDOT +#property indicator_width7 1 + +// +// FIBBO Level 4 ... + +// +#define fl4BufferIndex 12 +#define fl4BufferPlotIndex 7 +double fl4Buffer[]; + +// +#define fl4ColorBufferIndex 13 +double fl4ColorBuffer[]; + +// +#property indicator_label8 "XPV FL4" +#property indicator_type8 DRAW_COLOR_LINE +#property indicator_color8 CLR_NONE, clrGold +#property indicator_style8 STYLE_DASHDOTDOT +#property indicator_width8 1 + +// +// FIBBO Level 5 ... + +// +#define fl5BufferIndex 14 +#define fl5BufferPlotIndex 8 +double fl5Buffer[]; + +// +#define fl5ColorBufferIndex 15 +double fl5ColorBuffer[]; + +// +#property indicator_label9 "XPV FL5" +#property indicator_type9 DRAW_COLOR_LINE +#property indicator_color9 CLR_NONE, clrGold +#property indicator_style9 STYLE_DASHDOTDOT +#property indicator_width9 1 + +// +// LEVELS ... + +// +#define scHHBufferIndex 16 +#define scHHBufferPlotIndex 9 +double scHHBuffer[]; + +// +#define scHHColorBufferIndex 17 +double scHHColorBuffer[]; + +// +#property indicator_label10 "XPV SHH" +#property indicator_type10 DRAW_COLOR_LINE +#property indicator_color10 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style10 STYLE_DOT +#property indicator_width10 1 + +#define scLLBufferIndex 18 +#define scLLBufferPlotIndex 10 +double scLLBuffer[]; + +// +#define scLLColorBufferIndex 19 +double scLLColorBuffer[]; + +// +#property indicator_label11 "XPV SLL" +#property indicator_type11 DRAW_COLOR_LINE +#property indicator_color11 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style11 STYLE_DOT +#property indicator_width11 1 + +// +#define mcHHBufferIndex 20 +#define mcHHBufferPlotIndex 11 +double mcHHBuffer[]; + +// +#define mcHHColorBufferIndex 21 +double mcHHColorBuffer[]; + +// +#property indicator_label12 "XPV MHH" +#property indicator_type12 DRAW_COLOR_LINE +#property indicator_color12 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style12 STYLE_DOT +#property indicator_width12 1 + +// +#define mcLLBufferIndex 22 +#define mcLLBufferPlotIndex 12 +double mcLLBuffer[]; + +// +#define mcLLColorBufferIndex 23 +double mcLLColorBuffer[]; + +// +#property indicator_label13 "XPV MLL" +#property indicator_type13 DRAW_COLOR_LINE +#property indicator_color13 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style13 STYLE_DOT +#property indicator_width13 1 + +// +#define lcHHBufferIndex 24 +#define lcHHBufferPlotIndex 13 +double lcHHBuffer[]; + +// +#define lcHHColorBufferIndex 25 +double lcHHColorBuffer[]; + +// +#property indicator_label14 "XPV LHH" +#property indicator_type14 DRAW_COLOR_LINE +#property indicator_color14 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style14 STYLE_DOT +#property indicator_width14 1 + +// +#define lcLLBufferIndex 26 +#define lcLLBufferPlotIndex 14 +double lcLLBuffer[]; + +// +#define lcLLColorBufferIndex 27 +double lcLLColorBuffer[]; + +// +#property indicator_label15 "XPV LLL" +#property indicator_type15 DRAW_COLOR_LINE +#property indicator_color15 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style15 STYLE_DOT +#property indicator_width15 1 + +// +#define hcHHBufferIndex 28 +#define hcHHBufferPlotIndex 15 +double hcHHBuffer[]; + +// +#define hcHHColorBufferIndex 29 +double hcHHColorBuffer[]; + +// +#property indicator_label16 "XPV HHH" +#property indicator_type16 DRAW_COLOR_LINE +#property indicator_color16 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style16 STYLE_DOT +#property indicator_width16 1 + +// +#define hcLLBufferIndex 30 +#define hcLLBufferPlotIndex 16 +double hcLLBuffer[]; + +// +#define hcLLColorBufferIndex 31 +double hcLLColorBuffer[]; + +// +#property indicator_label17 "XPV HLL" +#property indicator_type17 DRAW_COLOR_LINE +#property indicator_color17 CLR_NONE, clrLightGray, clrAqua, clrMagenta +#property indicator_style17 STYLE_DOT +#property indicator_width17 1 + +// +// Variables, Properties and etc ... + +// +int maxLength; + +// +double mHideColorIDX = 0; + +// +XMarketCycle sc; +double mLastSCHH = 0; +double mLastSCLL = 0; + +// +XMarketCycle mc; +double mLastMCHH = 0; +double mLastMCLL = 0; + +// +XMarketCycle lc; +double mLastLCHH = 0; +double mLastLCLL = 0; + +// +XMarketCycle hc; +double mLastHCHH = 0; +double mLastHCLL = 0; + +// +double lastPeak = 0; +double lastVale = 0; + +// +// Event Handlers ... + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + if (!InitMarketCycles()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed +} + +// +// Calculating what we want ... +int OnCalculate( + const int rates_total, // Total Bars on Chart ... + const int prev_calculated, // Total Calculated Bars on Charts ... + const datetime &time[], // History of Open Time ... + const double &open[], // History of Open Price ... + const double &high[], // History of High Price ... + const double &low[], // History of Low Price ... + const double &close[], // History of Close Price ... + const long &tick_volume[], // History of Tick Volumes on Bar ... + const long &volume[], // History of Trade Volumes ... + const int &spread[] // History of Spread Price ... + // +) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + CalculateBuffers(i); + } + + // + return rates_total; +} + +// +// Functions ... + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = + // + IsValid(scMethod, scPeriod) && + IsValid(mcMethod, mcPeriod) && + IsValid(lcMethod, lcPeriod) && + IsValid(hcMethod, hcPeriod) + // + ; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(sc.length, mc.length); + result = MathMax(result, lc.length); + result = MathMax(result, hc.length); + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // PEAKS and VALES ... + ENUM_DRAW_TYPE pvDrawType = showPeaksAndVales ? DRAW_ARROW : DRAW_NONE; + + // + // PEAKS ... + ArraySetAsSeries(peaksBuffer, true); + SetIndexBuffer(peaksBufferIndex, peaksBuffer, INDICATOR_DATA); + PlotIndexSetInteger(peaksBufferIndex, PLOT_ARROW, 225); + PlotIndexSetDouble(peaksBufferIndex, PLOT_EMPTY_VALUE, 0); + + // + PlotIndexSetInteger(peaksBufferIndex, PLOT_SHOW_DATA, showPeaksAndVales); + PlotIndexSetInteger(peaksBufferIndex, PLOT_DRAW_TYPE, pvDrawType); + + // + // VALES ... + ArraySetAsSeries(valesBuffer, true); + SetIndexBuffer(valesBufferIndex, valesBuffer, INDICATOR_DATA); + PlotIndexSetInteger(valesBufferIndex, PLOT_ARROW, 225); + PlotIndexSetDouble(valesBufferIndex, PLOT_EMPTY_VALUE, 0); + + // + PlotIndexSetInteger(valesBufferIndex, PLOT_SHOW_DATA, showPeaksAndVales); + PlotIndexSetInteger(valesBufferIndex, PLOT_DRAW_TYPE, pvDrawType); + + // + // SUPPORT and RESISTANCE ... + // + + // + // RESISTANCE ... + ArraySetAsSeries(rBuffer, true); + SetIndexBuffer(rBufferIndex, rBuffer, INDICATOR_DATA); + PlotIndexSetInteger(rBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(rBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + // RESISTANCE Color ... + ArraySetAsSeries(rColorBuffer, true); + SetIndexBuffer(rColorBufferIndex, rColorBuffer, INDICATOR_COLOR_INDEX); + + // + // SUPPORT ... + ArraySetAsSeries(sBuffer, true); + SetIndexBuffer(sBufferIndex, sBuffer, INDICATOR_DATA); + PlotIndexSetInteger(sBufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(sBufferPlotIndex, PLOT_SHOW_DATA, false); + + // + // SUPPORT Color ... + ArraySetAsSeries(sColorBuffer, true); + SetIndexBuffer(sColorBufferIndex, sColorBuffer, INDICATOR_COLOR_INDEX); + + // + // FIBBO Levels ... + + // + // LEVEL 1 ... + + // + // Buffer ... + ArraySetAsSeries(fl1Buffer, true); + SetIndexBuffer(fl1BufferIndex, fl1Buffer, INDICATOR_DATA); + PlotIndexSetInteger(fl1BufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fl1BufferPlotIndex, PLOT_SHOW_DATA, showFibo1Levels); + + // + // Color ... + ArraySetAsSeries(fl1ColorBuffer, true); + SetIndexBuffer(fl1ColorBufferIndex, fl1ColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LEVEL 2 ... + + // + // Buffer ... + ArraySetAsSeries(fl2Buffer, true); + SetIndexBuffer(fl2BufferIndex, fl2Buffer, INDICATOR_DATA); + PlotIndexSetInteger(fl2BufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fl2BufferPlotIndex, PLOT_SHOW_DATA, showFibo2Levels); + + // + // Color ... + ArraySetAsSeries(fl2ColorBuffer, true); + SetIndexBuffer(fl2ColorBufferIndex, fl2ColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LEVEL 3 ... + + // + // Buffer ... + ArraySetAsSeries(fl3Buffer, true); + SetIndexBuffer(fl3BufferIndex, fl3Buffer, INDICATOR_DATA); + PlotIndexSetInteger(fl3BufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fl3BufferPlotIndex, PLOT_SHOW_DATA, showFibo3Levels); + + // + // Color ... + ArraySetAsSeries(fl3ColorBuffer, true); + SetIndexBuffer(fl3ColorBufferIndex, fl3ColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LEVEL 4 ... + + // + // Buffer ... + ArraySetAsSeries(fl4Buffer, true); + SetIndexBuffer(fl4BufferIndex, fl4Buffer, INDICATOR_DATA); + PlotIndexSetInteger(fl4BufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fl4BufferPlotIndex, PLOT_SHOW_DATA, showFibo4Levels); + + // + // Color ... + ArraySetAsSeries(fl4ColorBuffer, true); + SetIndexBuffer(fl4ColorBufferIndex, fl4ColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LEVEL 5 ... + + // + // Buffer ... + ArraySetAsSeries(fl5Buffer, true); + SetIndexBuffer(fl5BufferIndex, fl5Buffer, INDICATOR_DATA); + PlotIndexSetInteger(fl5BufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(fl5BufferPlotIndex, PLOT_SHOW_DATA, showFibo5Levels); + + // + // Color ... + ArraySetAsSeries(fl5ColorBuffer, true); + SetIndexBuffer(fl5ColorBufferIndex, fl5ColorBuffer, INDICATOR_COLOR_INDEX); + + // + // SHORT Buffers ... + + // + // HIGH ... + ArraySetAsSeries(scHHBuffer, true); + SetIndexBuffer(scHHBufferIndex, scHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(scHHBufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(scHHBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + + // + ArraySetAsSeries(scHHColorBuffer, true); + SetIndexBuffer(scHHColorBufferIndex, scHHColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LOW ... + ArraySetAsSeries(scLLBuffer, true); + SetIndexBuffer(scLLBufferIndex, scLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(scLLBufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(scLLBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + + // + ArraySetAsSeries(scLLColorBuffer, true); + SetIndexBuffer(scLLColorBufferIndex, scLLColorBuffer, INDICATOR_COLOR_INDEX); + + // + // MEDIUM Buffer ... + + // + // HIGH ... + ArraySetAsSeries(mcHHBuffer, true); + SetIndexBuffer(mcHHBufferIndex, mcHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(mcHHBufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(mcHHBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + + // + ArraySetAsSeries(mcHHColorBuffer, true); + SetIndexBuffer(mcHHColorBufferIndex, mcHHColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LOW ... + ArraySetAsSeries(mcLLBuffer, true); + SetIndexBuffer(mcLLBufferIndex, mcLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(mcLLBufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(mcLLBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + + // + ArraySetAsSeries(mcLLColorBuffer, true); + SetIndexBuffer(mcLLColorBufferIndex, mcLLColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LONG Buffer ... + + // + // HIGH ... + ArraySetAsSeries(lcHHBuffer, true); + SetIndexBuffer(lcHHBufferIndex, lcHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(lcHHBufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(lcHHBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + + // + ArraySetAsSeries(lcHHColorBuffer, true); + SetIndexBuffer(lcHHColorBufferIndex, lcHHColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LOW ... + ArraySetAsSeries(lcLLBuffer, true); + SetIndexBuffer(lcLLBufferIndex, lcLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(lcLLBufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(lcLLBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + + // + ArraySetAsSeries(lcLLColorBuffer, true); + SetIndexBuffer(lcLLColorBufferIndex, lcLLColorBuffer, INDICATOR_COLOR_INDEX); + + // + // HIND Buffer ... + + // + // HIGH ... + ArraySetAsSeries(hcHHBuffer, true); + SetIndexBuffer(hcHHBufferIndex, hcHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(hcHHBufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(hcHHBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + + // + ArraySetAsSeries(hcHHColorBuffer, true); + SetIndexBuffer(hcHHColorBufferIndex, hcHHColorBuffer, INDICATOR_COLOR_INDEX); + + // + // LOW ... + ArraySetAsSeries(hcLLBuffer, true); + SetIndexBuffer(hcLLBufferIndex, hcLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(hcLLBufferPlotIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(hcLLBufferPlotIndex, PLOT_SHOW_DATA, showLevels); + + // + ArraySetAsSeries(hcLLColorBuffer, true); + SetIndexBuffer(hcLLColorBufferIndex, hcLLColorBuffer, INDICATOR_COLOR_INDEX); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index // Selected Bar Index +) +{ + // + // Calculate Cycles ... + CalculateCycles(bar_index); + + // + // Calculate Peaks and Vales ... + CalculatePeaksAndVales(bar_index); + + // + // Calculate Fibonnaci ... + CalculateFibonacci(bar_index); +} + +// +// Custom ... + +// +// Initial Market Cycles ... +bool InitMarketCycles() +{ + // + bool result = false; + + // + // Short ... + result = sc.Init( + _Symbol, + _Period, + X_MARKET_CYCLE_SHORT, + scMethod, + scPeriod + // + ); + if (!result) + { + return result; + } + + // + // Medium ... + result = mc.Init( + _Symbol, + _Period, + X_MARKET_CYCLE_MEDIUM, + mcMethod, + mcPeriod + // + ); + if (!result) + { + return result; + } + + // + // Long ... + result = lc.Init( + _Symbol, + _Period, + X_MARKET_CYCLE_LONG, + lcMethod, + lcPeriod + // + ); + if (!result) + { + return result; + } + + // + // Hind ... + result = hc.Init( + _Symbol, + _Period, + X_MARKET_CYCLE_HIND, + hcMethod, + hcPeriod + // + ); + + // + return result; +} + +// +// Calculate Specified Cycles HH and LL ... +void CalculateCycle( + int barIndex, + XMarketCycle &cycle, + double &lastHH, + double &hhBuffer[], + double &hhColorBuffer[], + double &lastLL, + double &llBuffer[], + double &llColorBuffer[] // +) +{ + // + cycle.Update(barIndex); + + // + XOHCL bar; + bar.Init( + _Symbol, + _Period, + barIndex + // + ); + + // + double hhValue = bar.FindHighest( + cycle.length, + hhMode + // + ); + hhBuffer[barIndex] = hhValue; + + // + double hhColorIDX = + !showLevels + ? mHideColorIDX + : (hhValue == lastHH) + ? !showConsolidations + ? mHideColorIDX + : 1 + : hhValue > lastHH + ? 2 + : hhValue < lastHH + ? 3 + : mHideColorIDX; + hhColorBuffer[barIndex] = hhColorIDX; + + // + lastHH = hhValue; + + // + double llValue = bar.FindLowest( + cycle.length, + llMode + // + ); + llBuffer[barIndex] = llValue; + + // + double llColorIDX = + !showLevels + ? mHideColorIDX + : (llValue == lastLL) + ? !showConsolidations + ? mHideColorIDX + : 1 + : llValue > lastLL + ? 2 + : llValue < lastLL + ? 3 + : mHideColorIDX; + llColorBuffer[barIndex] = llColorIDX; + + // + lastLL = llValue; +} + +// +// Calculate Cycles Up and Down Boundaries ... +void CalculateCycles( + int barIndex // Bar Index +) +{ + // + // Short ... + CalculateCycle( + barIndex, + sc, + // + mLastSCHH, + scHHBuffer, + scHHColorBuffer, + // + mLastSCLL, + scLLBuffer, + scLLColorBuffer + // + ); + + // + // Medium ... + CalculateCycle( + barIndex, + mc, + // + mLastMCHH, + mcHHBuffer, + mcHHColorBuffer, + // + mLastMCLL, + mcLLBuffer, + mcLLColorBuffer + // + ); + + // + // Long ... + CalculateCycle( + barIndex, + lc, + // + mLastLCHH, + lcHHBuffer, + lcHHColorBuffer, + // + mLastLCLL, + lcLLBuffer, + lcLLColorBuffer + // + ); + + // + // Hind ... + CalculateCycle( + barIndex, + hc, + // + mLastHCHH, + hcHHBuffer, + hcHHColorBuffer, + // + mLastHCLL, + hcLLBuffer, + hcLLColorBuffer + // + ); +} + +// +// Calculate Peaks and Values ... +void CalculatePeaksAndVales( + int barIndex // Bar Index +) +{ + // + // Retrieve Requirements ... + + // + // Short ... + double scHHValue = scHHBuffer[barIndex]; + double scLLValue = scLLBuffer[barIndex]; + + // + // Medium ... + double mcHHValue = mcHHBuffer[barIndex]; + double mcLLValue = mcLLBuffer[barIndex]; + + // + // Long ... + double lcHHValue = lcHHBuffer[barIndex]; + double lcLLValue = lcLLBuffer[barIndex]; + + // + // Hind ... + double hcHHValue = hcHHBuffer[barIndex]; + double hcLLValue = hcLLBuffer[barIndex]; + + // + double rColorIDX = mHideColorIDX; + double sColorIDX = mHideColorIDX; + + // + // RESISTANCE ... + double rValue = (scHHValue + mcHHValue + lcHHValue + hcHHValue) / 4; + + // + // PEAKS ... + bool isPeak = rValue == hcHHValue && + hcHHValue == lcHHValue && + lcHHValue == mcHHValue && + mcHHValue == scHHValue; + + // + if (isPeak && lastPeak != rValue) + { + // + rColorIDX = 1; + lastPeak = rValue; + } + + // + // SUPPORT ... + double sValue = (scLLValue + mcLLValue + lcLLValue + hcLLValue) / 4; + + // + // VALES ... + bool isVale = sValue == hcLLValue && + hcLLValue == lcLLValue && + lcLLValue == mcLLValue && + mcLLValue == scLLValue; + + // + if (isVale && lastVale != sValue) + { + // + sColorIDX = 1; + + // + lastVale = sValue; + } + + // + rBuffer[barIndex] = rValue; + sBuffer[barIndex] = sValue; + peaksBuffer[barIndex] = lastPeak; + valesBuffer[barIndex] = lastVale; + + // + if (showPeaksAndVales) + { + // + rColorBuffer[barIndex] = rColorIDX; + sColorBuffer[barIndex] = sColorIDX; + } + else + { + // + rColorBuffer[barIndex] = mHideColorIDX; + sColorBuffer[barIndex] = mHideColorIDX; + } +} + +// +// Calculate Fibonacci Level 1 ... +void CalculateFibonacci( + int barIndex // Bar Index +) +{ + // + // Select Requirements ... + double upPrice = peaksBuffer[barIndex]; + double downPrice = valesBuffer[barIndex]; + + // + // Level 1 ... + double fibLevel1Value = GetFibonacciLevel( + upPrice, + downPrice, + fiboLevel1, + 1); + // + // Level 2 ... + double fibLevel2Value = GetFibonacciLevel( + upPrice, + downPrice, + fiboLevel2, + 1); + + // + // Level 3 ... + double fibLevel3Value = GetFibonacciLevel( + upPrice, + downPrice, + fiboLevel3, + 1); + + // + // Level 4 ... + double fibLevel4Value = GetFibonacciLevel( + upPrice, + downPrice, + fiboLevel4, + 1); + + // + // Level 5 ... + double fibLevel5Value = GetFibonacciLevel( + upPrice, + downPrice, + fiboLevel5, + 1); + + // + fl1Buffer[barIndex] = fibLevel1Value; + fl2Buffer[barIndex] = fibLevel2Value; + fl3Buffer[barIndex] = fibLevel3Value; + fl4Buffer[barIndex] = fibLevel4Value; + fl5Buffer[barIndex] = fibLevel5Value; + + // + double fl1ColorIdx = showFibo1Levels ? 1 : mHideColorIDX; + double fl2ColorIdx = showFibo2Levels ? 1 : mHideColorIDX; + double fl3ColorIdx = showFibo3Levels ? 1 : mHideColorIDX; + double fl4ColorIdx = showFibo4Levels ? 1 : mHideColorIDX; + double fl5ColorIdx = showFibo5Levels ? 1 : mHideColorIDX; + + // + fl1ColorBuffer[barIndex] = fl1ColorIdx; + fl2ColorBuffer[barIndex] = fl2ColorIdx; + fl3ColorBuffer[barIndex] = fl3ColorIdx; + fl4ColorBuffer[barIndex] = fl4ColorIdx; + fl5ColorBuffer[barIndex] = fl5ColorIdx; +} + +// \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xsslc.mq5 b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xsslc.mq5 new file mode 100644 index 0000000..620cb24 --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xsslc.mq5 @@ -0,0 +1,440 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ---------------------------------------------------- +// Name: XSSLC +// Description: SSL Channel Indicator +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XSSLC Indicator" +#property strict + +// +// START Constants ... +// + +// +// Indicator Short Name ... +#define ShortName "XSSLC" + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input group "Market"; +input int length = 36; // Length + +// +input group "Calculation"; +input ENUM_MA_METHOD method = MODE_SMA; // Method +input ENUM_APPLIED_PRICE upAppliedTo = PRICE_HIGH; // Up Applied To +input ENUM_APPLIED_PRICE downAppliedTo = PRICE_LOW; // Down Applied To + +// +input group "Presentation"; +input bool showUp = true; // Show Up +input bool showDown = true; // Show Down + +// +// END Inputs ... +// + +// +// START Includes and Imports ... +// + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes and Imports ... +// + +// +// START Buffers ... +// +#property indicator_chart_window + +// +#property indicator_buffers 5 +#property indicator_plots 2 + +// +// PLOTTED Buffers ... + +// +#define upBufferIndex 0 +double upBuffer[]; + +// +#property indicator_label1 "XSSLC Up" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrLime +#property indicator_style1 STYLE_SOLID +#property indicator_width1 1 + +// +#define downBufferIndex 1 +double downBuffer[]; + +// +#property indicator_label2 "XSSLC Down" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrRed +#property indicator_style2 STYLE_SOLID +#property indicator_width2 1 + +// +// DATA Buffers ... + +// +#define upMaBufferIndex 2 +double upMaBuffer[]; + +// +#define downMaBufferIndex 3 +double downMaBuffer[]; + +// +#define kpiBufferIndex 4 +double kpiBuffer[]; + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int maxLength; + +// +int upHandler = INVALID_HANDLE; +int downHandler = INVALID_HANDLE; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Initialize Requierd Handlers ... + upHandler = iMA( + _Symbol, + _Period, + length, + 0, + method, + upAppliedTo); + downHandler = iMA( + _Symbol, + _Period, + length, + 0, + method, + downAppliedTo); + if (upHandler == INVALID_HANDLE || downHandler == INVALID_HANDLE) + { + // + string msg = "Error in Initilizing Indicator ..."; + Print(msg); + + // + return INIT_FAILED; + } + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Release Indicators ... + IndicatorRelease(upHandler); + IndicatorRelease(downHandler); +} + +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + // Check Calculated Bars ... + int upCalculatedBars = BarsCalculated(upHandler); + int downCalculatedBars = BarsCalculated(downHandler); + if (upCalculatedBars < maxLength || + downCalculatedBars < maxLength) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + int copiedUps = CopyBuffer(upHandler, 0, 0, limit, upMaBuffer); + int copiedDowns = CopyBuffer(downHandler, 0, 0, limit, downMaBuffer); + if (copiedUps <= 0 || + copiedDowns <= 0) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + CalculateBuffers(i, limit, rates_total, prev_calculated, close); + } + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = + // + (length > 2) + // + ; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(result, length); + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // UP ... + + // + ENUM_DRAW_TYPE upDrawType = showUp ? DRAW_LINE : DRAW_NONE; + + ArraySetAsSeries(upBuffer, true); + SetIndexBuffer(upBufferIndex, upBuffer, INDICATOR_DATA); + PlotIndexSetInteger(upBufferIndex, PLOT_SHOW_DATA, showUp); + PlotIndexSetInteger(upBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(upBufferIndex, PLOT_DRAW_TYPE, upDrawType); + + // + // DOWN ... + + // + ENUM_DRAW_TYPE downDrawType = showDown ? DRAW_LINE : DRAW_NONE; + + ArraySetAsSeries(downBuffer, true); + SetIndexBuffer(downBufferIndex, downBuffer, INDICATOR_DATA); + PlotIndexSetInteger(downBufferIndex, PLOT_SHOW_DATA, showDown); + PlotIndexSetInteger(downBufferIndex, PLOT_DRAW_BEGIN, maxLength); + PlotIndexSetInteger(downBufferIndex, PLOT_DRAW_TYPE, downDrawType); + + // + // DATA Buffers ... + + // + // UP MA ... + ArraySetAsSeries(upMaBuffer, true); + SetIndexBuffer(upMaBufferIndex, upMaBuffer, INDICATOR_CALCULATIONS); + + // + // DOWN MA ... + ArraySetAsSeries(downMaBuffer, true); + SetIndexBuffer(downMaBufferIndex, downMaBuffer, INDICATOR_CALCULATIONS); + + // + // KPI ... + ArraySetAsSeries(kpiBuffer, true); + SetIndexBuffer(kpiBufferIndex, kpiBuffer, INDICATOR_CALCULATIONS); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index, // Selected Bar Index + int limit, + int ratesTotal, + int prevCalculated, + const double &close[]) +{ + // + double upMaValue = upMaBuffer[bar_index]; + double downMaValue = downMaBuffer[bar_index]; + + // + double closeValue = close[bar_index]; + + // + double kpiValue; + if (closeValue > upMaValue) + { + kpiValue = 1; + } + else if (closeValue < downMaValue) + { + kpiValue = -1; + } + else + { + kpiValue = kpiBuffer[bar_index + 1]; + } + + // + kpiBuffer[bar_index] = kpiValue; + + // + double upValue = kpiValue < 0 ? downMaValue : upMaValue; + upBuffer[bar_index] = upValue; + + // + double downValue = kpiValue < 0 ? upMaValue : downMaValue; + downBuffer[bar_index] = downValue; +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xstr.mq5 b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xstr.mq5 new file mode 100644 index 0000000..90e6eeb --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xstr.mq5 @@ -0,0 +1,580 @@ +////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// --------------------------------------------- +// Name: XSTR +// Description: Super Trend Indicator ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121_XAMA Indicator" +#property strict + +// +// START Constants ... +// + +#define ShortName "XSTR" + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +// Market ... +input group "ATR"; +input int atrLength = 14; // Length +input double atrMultiplier = 3.0; // Multiplier +input ENUM_APPLIED_PRICE atrAppliedTo = PRICE_MEDIAN; // Applied To + +// +// Presentation ... +input group "Presentation"; +input bool showTrends = true; // Show Trends +input bool fillTrends = true; // Fill Trends + +// +// END Inputs ... +// + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Buffers ... +// + +// +#property indicator_chart_window + +// +#property indicator_buffers 9 +#property indicator_plots 2 + +// +#define fillUpBufferIndex 0 +double fillUpBuffer[]; + +#define fillDownBufferIndex 1 +double fillDownBuffer[]; + +// +#define fillingPlotBufferIndex 0 + +// +#property indicator_label1 "XSTR Filling" +#property indicator_type1 DRAW_FILLING +#property indicator_color1 clrBisque, clrPaleGreen + +// +#define mainBufferIndex 2 +#define mainPlotBufferIndex 1 +double mainBuffer[]; + +// +#define mainColorBufferIndex 3 +double mainColorBuffer[]; + +// +#property indicator_label2 "XSTR" +#property indicator_type2 DRAW_COLOR_LINE +#property indicator_color2 CLR_NONE, clrGreen, clrDarkRed +#property indicator_style2 STYLE_DOT + +// +// DATA Buffers ... + +// +#define atrBufferIndex 4 +double atrBuffer[]; + +// +#define trendBufferIndex 5 +double trendBuffer[]; + +// +#define upBufferIndex 6 +double upBuffer[]; + +// +#define downBufferIndex 7 +double downBuffer[]; + +// +#define priceBufferIndex 8 +double priceBuffer[]; + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int maxLength; + +// +int atrHandler = INVALID_HANDLE; + +// +int changeOfTrend; +int startBearishTrend; +int startBullishTrend; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + atrHandler = iATR( + _Symbol, + _Period, + atrLength); + if (atrHandler == INVALID_HANDLE) + { + return INIT_FAILED; + } + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Here we can handle De Initialization Reasons ... + IndicatorRelease(atrHandler); +} + +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + int numOfRequiredAtrs; + if (prev_calculated > rates_total || prev_calculated < 0) + { + numOfRequiredAtrs = rates_total; + } + else + { + // + numOfRequiredAtrs = rates_total - prev_calculated; + if (prev_calculated > 0) + { + numOfRequiredAtrs++; + } + } + + // + // Checking for stop ... + if (IsStopped()) + { + return 0; + } + + // + // Check Number of items Copy or not ... + int copiedATRs = CopyBuffer(atrHandler, 0, 0, numOfRequiredAtrs, atrBuffer); + if (copiedATRs <= 0) + { + return 0; + } + + // + int limit; + + // + // checking for the limit start of calculation of an indicator ... + if (prev_calculated > rates_total || prev_calculated <= 0) + { + // + // starting index for calculation of all bars ... + limit = maxLength; + } + else + { + // + // starting number for calculation of new bars + limit = prev_calculated - 1; + } + + // + // Main Loop ... + for (int i = limit; i < rates_total && !IsStopped(); i++) + { + // + // Calculated Price ... + double price = getPrice( + atrAppliedTo, + open, + high, + low, + close, + i); + // price = (high[i] + low[i]) / 2; + priceBuffer[i] = price; + + // + double atr = atrBuffer[i]; + + // + // Up ... + upBuffer[i] = price + (atrMultiplier * atr); + + // + // Down ... + downBuffer[i] = price - (atrMultiplier * atr); + + // + if (close[i] > upBuffer[i - 1]) + { + // + trendBuffer[i] = 1; + if (trendBuffer[i - 1] == -1) + { + changeOfTrend = 1; + } + } + else if (close[i] < downBuffer[i - 1]) + { + // + trendBuffer[i] = -1; + if (trendBuffer[i - 1] == 1) + { + changeOfTrend = 1; + } + } + else if (trendBuffer[i - 1] == 1) + { + // + trendBuffer[i] = 1; + changeOfTrend = 0; + } + else if (trendBuffer[i - 1] == -1) + { + // + trendBuffer[i] = -1; + changeOfTrend = 0; + } + + // + // Down Trend Starting ... + if (trendBuffer[i] < 0 && trendBuffer[i - 1] > 0) + { + startBearishTrend = 1; + } + else + { + startBearishTrend = 0; + } + + // + // Up Trend Starting ... + if (trendBuffer[i] > 0 && trendBuffer[i - 1] < 0) + { + startBullishTrend = 1; + } + else + { + startBullishTrend = 0; + } + + // + if (trendBuffer[i] > 0 && downBuffer[i] < downBuffer[i - 1]) + { + downBuffer[i] = downBuffer[i - 1]; + } + + // + if (trendBuffer[i] < 0 && upBuffer[i] > upBuffer[i - 1]) + { + upBuffer[i] = upBuffer[i - 1]; + } + + // + if (startBearishTrend == 1) + { + upBuffer[i] = priceBuffer[i] + (atrMultiplier * atr); + } + + // + if (startBullishTrend == 1) + { + downBuffer[i] = priceBuffer[i] - (atrMultiplier * atr); + } + + // + // Draw the indicator ... + + // + double colorIDX = 0; + mainColorBuffer[i] = colorIDX; + + // + if (trendBuffer[i] == 1) + { + // + mainBuffer[i] = downBuffer[i]; + if (changeOfTrend == 1) + { + mainBuffer[i - 1] = mainBuffer[i - 2]; + changeOfTrend = 0; + } + + // + colorIDX = 1; + } + else if (trendBuffer[i] == -1) + { + // + mainBuffer[i] = upBuffer[i]; + if (changeOfTrend == 1) + { + // + mainBuffer[i - 1] = mainBuffer[i - 2]; + changeOfTrend = 0; + } + + // + colorIDX = 2; + } + + // + if (showTrends) + { + mainColorBuffer[i] = colorIDX; + } + + // + // Filling ... + if (fillTrends) + { + // + fillUpBuffer[i] = mainBuffer[i]; + fillDownBuffer[i] = close[i]; + } + else + { + // + fillUpBuffer[i] = EMPTY_VALUE; + fillDownBuffer[i] = EMPTY_VALUE; + } + } + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + // Validate Args ... + result = + // + atrLength >= 2 + // + ; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = atrLength; + + // + return result; +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // PLOT Buffers ... + + // + // FILLINGS ... + SetIndexBuffer(fillUpBufferIndex, fillUpBuffer, INDICATOR_DATA); + SetIndexBuffer(fillDownBufferIndex, fillDownBuffer, INDICATOR_DATA); + PlotIndexSetInteger(fillingPlotBufferIndex, PLOT_SHOW_DATA, false); + + // + // MAIN ... + SetIndexBuffer(mainBufferIndex, mainBuffer, INDICATOR_DATA); + PlotIndexSetInteger(mainPlotBufferIndex, PLOT_SHOW_DATA, showTrends); + SetIndexBuffer(mainColorBufferIndex, mainColorBuffer, INDICATOR_COLOR_INDEX); + + // + // DATA Buffers ... + + // + // ATR ... + SetIndexBuffer(atrBufferIndex, atrBuffer, INDICATOR_CALCULATIONS); + + // + // TREND ... + SetIndexBuffer(trendBufferIndex, trendBuffer, INDICATOR_CALCULATIONS); + + // + // UP ... + SetIndexBuffer(upBufferIndex, upBuffer, INDICATOR_CALCULATIONS); + + // + // DOWN ... + SetIndexBuffer(downBufferIndex, downBuffer, INDICATOR_CALCULATIONS); + + // + // PRICE ... + SetIndexBuffer(priceBufferIndex, priceBuffer, INDICATOR_CALCULATIONS); +} + +// +// END Functions ... +// + +// +// TEMPLATE Function ... + +template +double getPrice(ENUM_APPLIED_PRICE tprice, T &open[], T &high[], T &low[], T &close[], int i) +{ + switch (tprice) + { + case PRICE_CLOSE: + return (close[i]); + case PRICE_OPEN: + return (open[i]); + case PRICE_HIGH: + return (high[i]); + case PRICE_LOW: + return (low[i]); + case PRICE_MEDIAN: + return ((high[i] + low[i]) / 2.0); + case PRICE_TYPICAL: + return ((high[i] + low[i] + close[i]) / 3.0); + case PRICE_WEIGHTED: + return ((high[i] + low[i] + close[i] + close[i]) / 4.0); + } + return (0); +} diff --git a/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xtd.mq5 b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xtd.mq5 new file mode 100644 index 0000000..ca79695 --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xtd.mq5 @@ -0,0 +1,457 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Trend Detector Oscillator +// -------------------------------------------------- +// Name: XTD +// Description: trend detecting in both sides ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XTD Oscillator" +#property strict + +// +// START Constants ... +// +#define ShortName "XTD" + +// +// XTD Oscillator States ... +enum ENUM_X_XTD_STATES +{ + X_XTD_BULLISH_CROSSED_OVER_BEARISH = 2, + X_XTD_BULLISH_OVER_BEARISH = 1, + X_XTD_NEUTURAL = 0, + X_XTD_BULLISH_UNDER_BEARISH = -1, + X_XTD_BULLISH_CROSSED_UNDER_BEARISH = -2 +}; +// +// END Constants ... +// + +// +// START Inputs ... +// +input int length = 14; // Market Length +input bool drawCrosses = true; // Draw Cross Arrows + +// +// Bullish ... +input uchar bullishArrowCode = 228; // Cross Over Arrow Code +input color bullishArrowColor = clrAqua; // Cross Over Arrow Color + +// +// Bearish ... +input uchar bearishArrowCode = 230; // Cross Under Arrow Code +input color bearishArrowColor = clrMagenta; // Cross Under Arrow Color +// +// END Inputs ... +// + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5"; + +// +// Includes Draw Library ... +#include "../Libraries/x-saherelm.draw.lib.mq5"; + +// +// START Buffers ... +// +// #property indicator_separate_window +#property indicator_chart_window + +// +#property indicator_buffers 3 +// #property indicator_plots 3 +#property indicator_plots 0 + +// +#define bullishBufferIndex 0 +#define bearishBufferIndex 1 +#define signalBufferIndex 2 + +// +double bullishBuffer[]; +double bearishBuffer[]; +double signalBuffer[]; + +// +// #property indicator_label1 "XBullPower" +// #property indicator_type1 DRAW_LINE +// #property indicator_color1 clrLime +// #property indicator_style1 STYLE_SOLID +// #property indicator_width1 1 + +// +// #property indicator_label2 "XBearPower" +// #property indicator_type2 DRAW_LINE +// #property indicator_color2 clrRed +// #property indicator_style2 STYLE_SOLID +// #property indicator_width2 1 + +// +// #property indicator_label3 "XSignal" +// #property indicator_type3 DRAW_LINE +// #property indicator_color3 clrGold +// #property indicator_style3 STYLE_DOT +// #property indicator_width3 1 +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +// +int xtdBullishCandleCount = 0; +int xtdBearishCandleCount = 0; +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + drawPrefix = ShortName; + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Here we can handle De Initialization Reasons ... +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + int maxLength = MathMax(0, length); + + // + limit = prev_calculated < maxLength ? rates_total - (maxLength + 1) : rates_total - prev_calculated; + + // + // Main Loop ... + for (int i = limit; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers(i, close); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + // Validate Args ... + if (length >= 5) + { + result = true; + } + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // Bullish Buffer ... + string bullishBufferLabel = ShortName + "BullPow " + "(" + (string)length + ")"; + ArraySetAsSeries(bullishBuffer, true); + SetIndexBuffer(bullishBufferIndex, bullishBuffer, INDICATOR_CALCULATIONS); + // SetIndexBuffer(bullishBufferIndex, bullishBuffer, INDICATOR_DATA); + // PlotIndexSetInteger(bullishBufferIndex, PLOT_DRAW_BEGIN, length); + // PlotIndexSetString(bullishBufferIndex, PLOT_LABEL, bullishBufferLabel); + + // + // Bearish Buffer ... + string bearishBufferLabel = ShortName + "BearPow " + "(" + (string)length + ")"; + ArraySetAsSeries(bearishBuffer, true); + SetIndexBuffer(bearishBufferIndex, bearishBuffer, INDICATOR_CALCULATIONS); + // SetIndexBuffer(bearishBufferIndex, bearishBuffer, INDICATOR_DATA); + // PlotIndexSetInteger(bearishBufferIndex, PLOT_DRAW_BEGIN, length); + // PlotIndexSetString(bearishBufferIndex, PLOT_LABEL, bearishBufferLabel); + + // + // Signal Buffer ... + string signalBufferLabel = ShortName + "Signal " + "(" + (string)length + ")"; + ArraySetAsSeries(signalBuffer, true); + SetIndexBuffer(signalBufferIndex, signalBuffer, INDICATOR_CALCULATIONS); + // SetIndexBuffer(signalBufferIndex, signalBuffer, INDICATOR_DATA); + // PlotIndexSetInteger(signalBufferIndex, PLOT_DRAW_BEGIN, length); + // PlotIndexSetString(signalBufferIndex, PLOT_LABEL, signalBufferLabel); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + string indicatorShortName = ""; + StringConcatenate(indicatorShortName, ShortName, " ", "( ", length, " )"); + + // + IndicatorSetString(INDICATOR_SHORTNAME, indicatorShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index, + const double &close[]) +{ + // + // Reset Global Counters ... + xtdBullishCandleCount = 0; + xtdBearishCandleCount = 0; + + // + // Loop through Closes ... + for (int i = bar_index; i <= bar_index + length; i++) + { + for (int j = i + 1; j <= bar_index + length; j++) + { + // + if (close[i] > close[j]) + { + xtdBullishCandleCount++; + } + + // + if (close[i] < close[j]) + { + xtdBearishCandleCount++; + } + } + } + + // + // Bullish Power Buffer ... + bullishBuffer[bar_index] = MathAbs(xtdBullishCandleCount); + + // + // Bearish Power Buffer ... + bearishBuffer[bar_index] = MathAbs(xtdBearishCandleCount); + + // + // Signal Buffer ... + signalBuffer[bar_index] = bullishBuffer[bar_index] - bearishBuffer[bar_index]; + + // + // Check and Draw Crosses if it's Specified ... + if (drawCrosses) + { + DrawCrosses(bar_index); + } +} + +// +// +double GetState( + int bar_index // Specified Bar Index +) +{ + // + // Check Cross Points ... + // bullishCrossedOverBearish = 2; + // bullishOverBearish = 1; + // bullishCrossedUnderBearish = -2; + // bullishUnderBearish = -1; + // OtherWise = 0; + bool isBullishCrossedOverBearish = IsCrossedOver( + bullishBuffer, + bearishBuffer, + bar_index); + bool isBullishCrossedUnderBearish = IsCrossedUnder( + bullishBuffer, + bearishBuffer, + bar_index); + bool isBullishOverBearish = IsOver( + bullishBuffer, + bearishBuffer, + bar_index); + bool isBullishUnderBearish = IsUnder( + bullishBuffer, + bearishBuffer, + bar_index); + + // + double result = X_XTD_NEUTURAL; + if (isBullishCrossedOverBearish) + { + result = X_XTD_BULLISH_CROSSED_OVER_BEARISH; + } + else if (isBullishCrossedUnderBearish) + { + result = X_XTD_BULLISH_CROSSED_UNDER_BEARISH; + } + else if (isBullishOverBearish) + { + result = X_XTD_BULLISH_OVER_BEARISH; + } + else if (isBullishUnderBearish) + { + result = X_XTD_BULLISH_UNDER_BEARISH; + } + else + { + result = X_XTD_NEUTURAL; + } + + // + return result; +} + +// +// Draw Crosses ... +void DrawCrosses( + int bar_index // the bars which required to draw cross arrow on it ... +) +{ + // + double stateValue = GetState(bar_index); + + // + bool isOver = stateValue == 2; + double low = iLow(_Symbol, _Period, bar_index); + double high = iHigh(_Symbol, _Period, bar_index); + + // + double price = isOver ? low : high; + datetime time = iTime(_Symbol, _Period, bar_index); + ENUM_ARROW_ANCHOR anchor = isOver ? ANCHOR_TOP : ANCHOR_BOTTOM; + uchar arrowCode = isOver ? bullishArrowCode : bearishArrowCode; + color arrowColor = isOver ? bullishArrowColor : bearishArrowColor; + string crossName = "Trend " + (isOver ? "Up" : "Down") + "_" + (string)time + "_" + (string)price; + + // + DrawArrow( + 0, + crossName, + 0, + time, + price, + arrowCode, + anchor, + arrowColor); +} +// +// END Functions ... +// diff --git a/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xtd.osc.mq5 b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xtd.osc.mq5 new file mode 100644 index 0000000..4f40f3c --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xtd.osc.mq5 @@ -0,0 +1,457 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Trend Detector Oscillator +// -------------------------------------------------- +// Name: XTD +// Description: trend detecting in both sides ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XTD Oscillator" +#property strict + +// +// START Constants ... +// +#define ShortName "XTD" + +// +// XTD Oscillator States ... +enum ENUM_X_XTD_STATES +{ + X_XTD_BULLISH_CROSSED_OVER_BEARISH = 2, + X_XTD_BULLISH_OVER_BEARISH = 1, + X_XTD_NEUTURAL = 0, + X_XTD_BULLISH_UNDER_BEARISH = -1, + X_XTD_BULLISH_CROSSED_UNDER_BEARISH = -2 +}; +// +// END Constants ... +// + +// +// START Inputs ... +// +input int length = 14; // Market Length +input bool drawCrosses = true; // Draw Cross Arrows + +// +// Bullish ... +input uchar bullishArrowCode = 228; // Cross Over Arrow Code +input color bullishArrowColor = clrAqua; // Cross Over Arrow Color + +// +// Bearish ... +input uchar bearishArrowCode = 230; // Cross Under Arrow Code +input color bearishArrowColor = clrMagenta; // Cross Under Arrow Color +// +// END Inputs ... +// + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5"; + +// +// Includes Draw Library ... +#include "../Libraries/x-saherelm.draw.lib.mq5"; + +// +// START Buffers ... +// +#property indicator_separate_window +// #property indicator_chart_window + +// +#property indicator_buffers 3 +#property indicator_plots 2 +// #property indicator_plots 0 + +// +#define bullishBufferIndex 0 +#define bearishBufferIndex 1 +#define signalBufferIndex 2 + +// +double bullishBuffer[]; +double bearishBuffer[]; +double signalBuffer[]; + +// +#property indicator_label1 "XBullPower" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrLime +#property indicator_style1 STYLE_SOLID +#property indicator_width1 1 + +// +#property indicator_label2 "XBearPower" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrRed +#property indicator_style2 STYLE_SOLID +#property indicator_width2 1 + +// +// #property indicator_label3 "XSignal" +// #property indicator_type3 DRAW_LINE +// #property indicator_color3 clrGold +// #property indicator_style3 STYLE_DOT +// #property indicator_width3 1 +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +// +int xtdBullishCandleCount = 0; +int xtdBearishCandleCount = 0; +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + drawPrefix = ShortName; + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Here we can handle De Initialization Reasons ... +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + int maxLength = MathMax(0, length); + + // + limit = prev_calculated < maxLength ? rates_total - (maxLength + 1) : rates_total - prev_calculated; + + // + // Main Loop ... + for (int i = limit; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers(i, close); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + // Validate Args ... + if (length >= 5) + { + result = true; + } + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // Bullish Buffer ... + string bullishBufferLabel = ShortName + "BullPow " + "(" + (string)length + ")"; + ArraySetAsSeries(bullishBuffer, true); + // SetIndexBuffer(bullishBufferIndex, bullishBuffer, INDICATOR_CALCULATIONS); + SetIndexBuffer(bullishBufferIndex, bullishBuffer, INDICATOR_DATA); + PlotIndexSetInteger(bullishBufferIndex, PLOT_DRAW_BEGIN, length); + PlotIndexSetString(bullishBufferIndex, PLOT_LABEL, bullishBufferLabel); + + // + // Bearish Buffer ... + string bearishBufferLabel = ShortName + "BearPow " + "(" + (string)length + ")"; + ArraySetAsSeries(bearishBuffer, true); + // SetIndexBuffer(bearishBufferIndex, bearishBuffer, INDICATOR_CALCULATIONS); + SetIndexBuffer(bearishBufferIndex, bearishBuffer, INDICATOR_DATA); + PlotIndexSetInteger(bearishBufferIndex, PLOT_DRAW_BEGIN, length); + PlotIndexSetString(bearishBufferIndex, PLOT_LABEL, bearishBufferLabel); + + // + // Signal Buffer ... + string signalBufferLabel = ShortName + "Signal " + "(" + (string)length + ")"; + ArraySetAsSeries(signalBuffer, true); + SetIndexBuffer(signalBufferIndex, signalBuffer, INDICATOR_CALCULATIONS); + // SetIndexBuffer(signalBufferIndex, signalBuffer, INDICATOR_DATA); + // PlotIndexSetInteger(signalBufferIndex, PLOT_DRAW_BEGIN, length); + // PlotIndexSetString(signalBufferIndex, PLOT_LABEL, signalBufferLabel); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + string indicatorShortName = ""; + StringConcatenate(indicatorShortName, ShortName, " ", "( ", length, " )"); + + // + IndicatorSetString(INDICATOR_SHORTNAME, indicatorShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index, + const double &close[]) +{ + // + // Reset Global Counters ... + xtdBullishCandleCount = 0; + xtdBearishCandleCount = 0; + + // + // Loop through Closes ... + for (int i = bar_index; i <= bar_index + length; i++) + { + for (int j = i + 1; j <= bar_index + length; j++) + { + // + if (close[i] > close[j]) + { + xtdBullishCandleCount++; + } + + // + if (close[i] < close[j]) + { + xtdBearishCandleCount++; + } + } + } + + // + // Bullish Power Buffer ... + bullishBuffer[bar_index] = MathAbs(xtdBullishCandleCount); + + // + // Bearish Power Buffer ... + bearishBuffer[bar_index] = MathAbs(xtdBearishCandleCount); + + // + // Signal Buffer ... + signalBuffer[bar_index] = bullishBuffer[bar_index] - bearishBuffer[bar_index]; + + // + // Check and Draw Crosses if it's Specified ... + if (drawCrosses) + { + DrawCrosses(bar_index); + } +} + +// +// +double GetState( + int bar_index // Specified Bar Index +) +{ + // + // Check Cross Points ... + // bullishCrossedOverBearish = 2; + // bullishOverBearish = 1; + // bullishCrossedUnderBearish = -2; + // bullishUnderBearish = -1; + // OtherWise = 0; + bool isBullishCrossedOverBearish = IsCrossedOver( + bullishBuffer, + bearishBuffer, + bar_index); + bool isBullishCrossedUnderBearish = IsCrossedUnder( + bullishBuffer, + bearishBuffer, + bar_index); + bool isBullishOverBearish = IsOver( + bullishBuffer, + bearishBuffer, + bar_index); + bool isBullishUnderBearish = IsUnder( + bullishBuffer, + bearishBuffer, + bar_index); + + // + double result = X_XTD_NEUTURAL; + if (isBullishCrossedOverBearish) + { + result = X_XTD_BULLISH_CROSSED_OVER_BEARISH; + } + else if (isBullishCrossedUnderBearish) + { + result = X_XTD_BULLISH_CROSSED_UNDER_BEARISH; + } + else if (isBullishOverBearish) + { + result = X_XTD_BULLISH_OVER_BEARISH; + } + else if (isBullishUnderBearish) + { + result = X_XTD_BULLISH_UNDER_BEARISH; + } + else + { + result = X_XTD_NEUTURAL; + } + + // + return result; +} + +// +// Draw Crosses ... +void DrawCrosses( + int bar_index // the bars which required to draw cross arrow on it ... +) +{ + // + double stateValue = GetState(bar_index); + + // + bool isOver = stateValue == 2; + double low = iLow(_Symbol, _Period, bar_index); + double high = iHigh(_Symbol, _Period, bar_index); + + // + double price = isOver ? low : high; + datetime time = iTime(_Symbol, _Period, bar_index); + ENUM_ARROW_ANCHOR anchor = isOver ? ANCHOR_TOP : ANCHOR_BOTTOM; + uchar arrowCode = isOver ? bullishArrowCode : bearishArrowCode; + color arrowColor = isOver ? bullishArrowColor : bearishArrowColor; + string crossName = "Trend " + (isOver ? "Up" : "Down") + "_" + (string)time + "_" + (string)price; + + // + DrawArrow( + 0, + crossName, + 0, + time, + price, + arrowCode, + anchor, + arrowColor); +} +// +// END Functions ... +// diff --git a/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xtm.mq5 b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xtm.mq5 new file mode 100644 index 0000000..2ee52d1 --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xtm.mq5 @@ -0,0 +1,351 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Candle Indicator +// --------------------------------------------- +// Name: XTM +// Description: Trend Magic Indicator ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XTM Indicator" +#property strict + +// +// START Constants ... +// +#define ShortName "XTM" + +// +// XTM Indicator States ... +enum ENUM_X_XTM_STATES +{ + X_XTM_BULLISH = 1, + X_XTM_BEARISH = -1, + X_XTM_NEUTURAL = 0, +}; +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input group "Market"; +input int maPeriod = 14; // Period +input int maShift = 0; // Shift +input ENUM_MA_METHOD maMethod = MODE_SMA; // Method +input ENUM_APPLIED_PRICE maAppliedTo = PRICE_CLOSE; // Applied To + +// +input group "Presentation"; +input bool showLine = true; // Show Line + +// +// END Inputs ... +// + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Buffers ... +// +#property indicator_chart_window + +// +#property indicator_buffers 3 +#property indicator_plots 1 + +// +// maBuffer ... +#define maBufferIndex 0 +#define maColorBufferIndex 1 +#define stateBufferIndex 2 + +double maBuffer[]; +double maColorBuffer[]; +double stateBuffer[]; + +#property indicator_label1 "XTM" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 clrLime, clrGray, clrRed, CLR_NONE +#property indicator_style1 STYLE_SOLID +#property indicator_width1 1 +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +int maHandler = INVALID_HANDLE; +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initializing MA Handler ... + maHandler = iMA( + _Symbol, + _Period, + maPeriod, + maShift, + maMethod, + maAppliedTo); + if (maHandler == INVALID_HANDLE) + { + return INIT_FAILED; + } + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Here we can handle De Initialization Reasons ... +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + int maxLength = MathMax(0, maPeriod); + + // + // Check Calculated Bars ... + int maCalculatedBars = BarsCalculated(maHandler); + if (maCalculatedBars < maxLength) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + int copiedMas = CopyBuffer(maHandler, 0, 0, limit, maBuffer); + if (copiedMas <= 0) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + // Do Buffers Calculation ... + CalculateBuffers(i); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + // Validate Args ... + if (maPeriod >= 2) + { + result = true; + } + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + string maBufferLabel = "XTM " + "(" + (string)maPeriod + ")"; + + // + // Ma Buffer ... + ArraySetAsSeries(maBuffer, true); + SetIndexBuffer(maBufferIndex, maBuffer, INDICATOR_DATA); + PlotIndexSetString(maBufferIndex, PLOT_LABEL, maBufferLabel); + + // + // Ma Color Buffer ... + ArraySetAsSeries(maColorBuffer, true); + SetIndexBuffer(maColorBufferIndex, maColorBuffer, INDICATOR_COLOR_INDEX); + + // + // State Buffer ... + ArraySetAsSeries(stateBuffer, true); + SetIndexBuffer(stateBufferIndex, stateBuffer, INDICATOR_CALCULATIONS); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + string indicatorShortName = ""; + StringConcatenate(indicatorShortName, ShortName, " ", "(", maPeriod, ")"); + + // + IndicatorSetString(INDICATOR_SHORTNAME, indicatorShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers(int bar_index) +{ + // + // Requirements ... + XOHCL candle; + candle.Init( + _Symbol, + _Period, + bar_index + // + ); + + // + double maValue = maBuffer[bar_index]; + + // + double lineColorIndex = + maValue < candle.low ? 0 : maValue > candle.high ? 2 + : 1; + + // + // Define State Value ... + // lineColorIndex == 0 => Bullish => 1; + // lineColorIndex == 1 => Neutural => 0; + // lineColorIndex == 2 => Bearish => -1; + double stateValue = + lineColorIndex == 0 ? X_XTM_BULLISH : lineColorIndex == 2 ? X_XTM_BEARISH + : X_XTM_NEUTURAL; + + // + // Set Ma Buffer Color Index ... + maColorBuffer[bar_index] = showLine ? lineColorIndex : 3; + + // + // Set State Buffer Value ... + stateBuffer[bar_index] = stateValue; +} + +// +// END Functions ... +// diff --git a/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xzg.mq5 b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xzg.mq5 new file mode 100644 index 0000000..0abb368 --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Indicators/x-saherelm.xzg.mq5 @@ -0,0 +1,750 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// --------------------------------------------- +// Name: XZG +// Description: Zogzag Implementation ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XZG Indicator" +#property strict + +// +#define ShortName "XZG" + +// +// DEFINITIONS ... +enum ENUM_X_ZG_SEARCH_MODE +{ + X_ZG_SEARCH_EXTREMUM = 0, // searching for the first extremum + X_ZG_SEARCH_PEAK = 1, // searching for the next ZigZag peak + X_ZG_SEARCH_VALE = -1 // searching for the next ZigZag vale +}; + +// +// How to Calculate Up and Down Price ... +enum ENUM_X_ZG_PRICE_MODE +{ + // + X_ZG_PRICE_HIGH_LOW_MODE = 1, + X_ZG_PRICE_OPEN_CLOSE_MODE = 2, +}; + +// +// INPUT ... + +// +input group "Market"; +input int depth = 12; // Depth +input int deviation = 5; // Deviation +input int backStep = 3; // Back Step +input ENUM_X_ZG_PRICE_MODE mode = X_ZG_PRICE_HIGH_LOW_MODE; // Mode + +// +input group "Presentation"; +input bool showZigZag = true; // Show ZigZag +input bool showPeaksAndVales = true; // Show Peaks and Vales + +// +// BUFFERS ... + +// +#property indicator_chart_window + +// +#property indicator_buffers 6 +#property indicator_plots 4 + +// +// ZigZag ... + +// +#define mainBufferIndex 0 +#define mainBufferPlotIndex 0 +double mainBuffer[]; + +#define mainColorBufferIndex 1 +double mainColorBuffer[]; + +// +#property indicator_label1 "XZG Main" +#property indicator_type1 DRAW_COLOR_SECTION +#property indicator_color1 CLR_NONE, clrRoyalBlue, clrSaddleBrown +#property indicator_width1 2 + +// +// Highs ... + +// +// ZigZag Pointer or Line Indicator ... +#define arrowBufferIndex 2 +#define arrowBufferPlotIndex 1 +double arrowBuffer[]; + +// +#define arrowColorBufferIndex 3 +double arrowColorBuffer[]; + +// +#property indicator_label2 "XZG PV" +#property indicator_type2 DRAW_COLOR_ARROW +#property indicator_color2 CLR_NONE, clrAqua, clrMagenta +#property indicator_width2 1 + +// +#define highsBufferIndex 4 +double highsBuffer[]; + +// +// Lows ... + +// +#define lowsBufferIndex 5 +double lowsBuffer[]; + +// +// VARIABLES ... + +// +int mRecalc = 3; // Number of last extremes for recalculation + +// +// EVENT Handlers ... + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // logTag = ShortName; + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed +} + +// +// Calculating what we want ... +int OnCalculate( + const int rates_total, // Total Bars on Chart ... + const int prev_calculated, // Total Calculated Bars on Charts ... + const datetime &time[], // History of Open Time ... + const double &open[], // History of Open Price ... + const double &high[], // History of High Price ... + const double &low[], // History of Low Price ... + const double &close[], // History of Close Price ... + const long &tick_volume[], // History of Tick Volumes on Bar ... + const long &volume[], // History of Trade Volumes ... + const int &spread[] // History of Spread Price ... +) +{ + // + double mZGHigh[]; + double mZGLow[]; + if (mode == X_ZG_PRICE_OPEN_CLOSE_MODE) + { + // + ArrayCopy( + mZGHigh, + open + // + ); + + // + ArrayCopy( + mZGLow, + close + // + ); + } + else + { + // + ArrayCopy( + mZGHigh, + high + // + ); + + // + ArrayCopy( + mZGLow, + low + // + ); + } + + // + int zigZagResult = CalcukateZigZag( + prev_calculated, + rates_total, + mZGHigh, + mZGLow + // + ); + + // + if (zigZagResult != rates_total) + { + return zigZagResult; + } + + // + return rates_total; +} + +// +// CUSTOM Functions ... + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + result = + // + depth > 0 && + deviation > 0 && + backStep > 0 + // + ; + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // Main ... + + // + SetIndexBuffer(mainBufferIndex, mainBuffer, INDICATOR_DATA); + SetIndexBuffer(mainColorBufferIndex, mainColorBuffer, INDICATOR_COLOR_INDEX); + + // + PlotIndexSetInteger(mainBufferPlotIndex, PLOT_SHOW_DATA, showZigZag); + PlotIndexSetInteger(mainBufferPlotIndex, PLOT_DRAW_BEGIN, 0); + PlotIndexSetDouble(mainBufferPlotIndex, PLOT_EMPTY_VALUE, 0); + + // + // Arrow ... + + // + SetIndexBuffer(arrowBufferIndex, arrowBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(arrowBufferPlotIndex, PLOT_SHOW_DATA, showPeaksAndVales); + PlotIndexSetInteger(arrowBufferPlotIndex, PLOT_DRAW_BEGIN, 0); + PlotIndexSetInteger(arrowBufferPlotIndex, PLOT_ARROW, 159); + PlotIndexSetInteger(arrowBufferPlotIndex, PLOT_ARROW_SHIFT, 0); + PlotIndexSetDouble(arrowBufferPlotIndex, PLOT_EMPTY_VALUE, 0); + + // + // Arrow Color ... + SetIndexBuffer(arrowColorBufferIndex, arrowColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Highs ... + SetIndexBuffer(highsBufferIndex, highsBuffer, INDICATOR_CALCULATIONS); + + // + // Lows ... + SetIndexBuffer(lowsBufferIndex, lowsBuffer, INDICATOR_CALCULATIONS); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Calculating Zig Zag ... +int CalcukateZigZag( + const int prev_calculated, + const int rates_total, + double &high[], + double &low[] + // +) +{ + // + if (rates_total < 100) + { + return 0; + } + + // + // Define Variables ... + int i = 0; + + // + int start = 0; + int extreme_counter = 0; + int extreme_search = X_ZG_SEARCH_EXTREMUM; + int shift = 0; + int back = 0; + int last_high_pos = 0; + int last_low_pos = 0; + + // + double val = 0; + double res = 0; + double curlow = 0; + double curhigh = 0; + double last_high = 0; + double last_low = 0; + + // + double colorIDX = 0; + double lastZigZagValue = 0; + + // + // Initializing ... + if (prev_calculated == 0) + { + // + ArrayInitialize(mainBuffer, 0); + ArrayInitialize(highsBuffer, 0); + ArrayInitialize(lowsBuffer, 0); + + // + start = depth; + } + + // + // Already Calculated Before ... + if (prev_calculated > 0) + { + // + i = rates_total - 1; + + // + // Searching for the third X_ZG_SEARCH_EXTREMUM from the last UnComplete Bar ... + while (extreme_counter < mRecalc && i > rates_total - 100) + { + // + res = mainBuffer[i]; + if (res != 0) + { + extreme_counter++; + } + + // + i--; + } + + // + i++; + start = i; + + // + // What type of X_ZG_SEARCH_EXTREMUM we Search for ... + if (lowsBuffer[i] != 0) + { + // + curlow = lowsBuffer[i]; + extreme_search = X_ZG_SEARCH_PEAK; + } + else + { + // + curhigh = highsBuffer[i]; + extreme_search = X_ZG_SEARCH_VALE; + } + + // + // Clear Values ... + for (i = start + 1; i < rates_total && !IsStopped(); i++) + { + // + mainBuffer[i] = 0; + lowsBuffer[i] = 0; + highsBuffer[i] = 0; + } + } + + // + // Search for High and Low Extremes ... + for (shift = start; shift < rates_total && !IsStopped(); shift++) + { + // + // Low ... + val = low[Lowest(low, depth, shift)]; + if (val == last_low) + { + val = 0; + } + else + { + // + last_low = val; + + // + if ((low[shift] - val) > deviation * _Point) + { + val = 0; + } + else + { + // + for (back = 1; back <= backStep; back++) + { + // + res = lowsBuffer[shift - back]; + if ((res != 0) && (res > val)) + { + lowsBuffer[shift - back] = 0; + } + } + } + } + + // + if (low[shift] == val) + { + lowsBuffer[shift] = val; + } + else + { + lowsBuffer[shift] = 0; + } + + // + // High ... + val = high[Highest(high, depth, shift)]; + if (val == last_high) + { + val = 0; + } + else + { + // + last_high = val; + + // + if ((val - high[shift]) > deviation * _Point) + { + val = 0; + } + else + { + // + for (back = 1; back <= backStep; back++) + { + // + res = highsBuffer[shift - back]; + if ((res != 0) && (res < val)) + { + highsBuffer[shift - back] = 0; + } + } + } + } + + // + if (high[shift] == val) + { + highsBuffer[shift] = val; + } + else + { + highsBuffer[shift] = 0; + } + } + + // + // Set Last Value ... + if (extreme_search == 0) // Undefined Values ... + { + // + last_low = 0; + last_high = 0; + } + else + { + // + last_low = curlow; + last_high = curhigh; + } + + // + // Final Selection of Extreme Points for ZigZag ... + for (shift = start; shift < rates_total && !IsStopped(); shift++) + { + // + res = 0; + + // + switch (extreme_search) + { + // + case X_ZG_SEARCH_EXTREMUM: + // + if (last_low == 0 && last_high == 0) + { + // + if (highsBuffer[shift] != 0) + { + // + last_high_pos = shift; + last_high = high[shift]; + + // + extreme_search = X_ZG_SEARCH_VALE; + + // + mainBuffer[shift] = last_high; + + // + res = 1; + } + + // + if (lowsBuffer[shift] != 0) + { + // + last_low_pos = shift; + last_low = low[shift]; + + // + extreme_search = X_ZG_SEARCH_PEAK; + + // + mainBuffer[shift] = last_low; + + // + res = 1; + } + } + break; + + // + case X_ZG_SEARCH_PEAK: + // + if (lowsBuffer[shift] != 0 && lowsBuffer[shift] < last_low && highsBuffer[shift] == 0) + { + // + mainBuffer[last_low_pos] = 0; + + // + last_low_pos = shift; + last_low = lowsBuffer[shift]; + + // + mainBuffer[shift] = last_low; + + // + res = 1; + } + + // + if (highsBuffer[shift] != 0 && lowsBuffer[shift] == 0) + { + // + last_high_pos = shift; + last_high = highsBuffer[shift]; + + // + mainBuffer[shift] = last_high; + + // + extreme_search = X_ZG_SEARCH_VALE; + + // + res = 1; + } + break; + + // + case X_ZG_SEARCH_VALE: + // + if (highsBuffer[shift] != 0 && highsBuffer[shift] > last_high && lowsBuffer[shift] == 0) + { + // + mainBuffer[last_high_pos] = 0; + + // + last_high_pos = shift; + last_high = highsBuffer[shift]; + + // + mainBuffer[shift] = last_high; + } + + // + if (lowsBuffer[shift] != 0 && highsBuffer[shift] == 0) + { + // + last_low_pos = shift; + last_low = lowsBuffer[shift]; + + // + mainBuffer[shift] = last_low; + + // + extreme_search = X_ZG_SEARCH_PEAK; + } + break; + } + + // + double iZigZagForColor = lastZigZagValue; + double iZigZag = mainBuffer[shift]; + if (iZigZag == 0 && lastZigZagValue != 0) + { + arrowBuffer[shift] = lastZigZagValue; + } + else if (iZigZag != 0) + { + // + lastZigZagValue = iZigZag; + arrowBuffer[shift] = lastZigZagValue; + } + + // + colorIDX = + lastZigZagValue > iZigZagForColor + ? 1 + : lastZigZagValue < iZigZagForColor + ? 2 + : colorIDX; + + // + mainColorBuffer[shift] = showZigZag ? colorIDX : 0; + arrowColorBuffer[shift] = showPeaksAndVales ? colorIDX : 0; + } + + // + return rates_total; +} + +// +// TOOLS ... + +// +// Search for the index of the highest bar ... +int Highest( + const double &mArray[], + const int mDepth, + const int mStart // +) +{ + // + int result = 0; + + // + if (mStart < 0) + { + return result; + } + + // + double max = mArray[mStart]; + result = mStart; + + // + // Start searching ... + for (int i = mStart - 1; i > mStart - mDepth && i >= 0; i--) + { + // + if (mArray[i] > max) + { + // + result = i; + max = mArray[i]; + } + } + + // + // Return index of the highest bar + return result; +} + +// +// Search for the index of the lowest bar ... +int Lowest( + const double &mArray[], + const int mDepth, + const int mStart // +) +{ + // + int result = 0; + + // + if (mStart < 0) + { + return result; + } + + // + double min = mArray[mStart]; + result = mStart; + + // + // Start searching ... + for (int i = mStart - 1; i > mStart - mDepth && i >= 0; i--) + { + // + if (mArray[i] < min) + { + // + result = i; + min = mArray[i]; + } + } + + // + // Return index of the lowest bar + return result; +} diff --git a/MQLTestWorkspace/BKPS/14030316/Libraries/x-saherelm.common.lib.mq5 b/MQLTestWorkspace/BKPS/14030316/Libraries/x-saherelm.common.lib.mq5 new file mode 100644 index 0000000..b01c0b8 --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Libraries/x-saherelm.common.lib.mq5 @@ -0,0 +1,8270 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Common Library +// -------------------------------------- +// Name: XCommonLib +// Description: provide all commonly used functions ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.xmd5.class.mq5" + +// +// Models ... + +// +// Specified Price Type ... +enum ENUM_X_PRICE +{ + X_PRICE_HIGH, + X_PRICE_OPEN, + X_PRICE_CLOSE, + X_PRICE_LOW +}; + +// +// Swing Types Enum ... +enum ENUM_X_SWING_TYPE +{ + X_NO_SWING = 0, + X_SWING_HIGH = 1, + X_SWING_LOW = -1, +}; + +// +// XPERIOD Calculation Method ... +enum ENUM_X_PERIOD_METHOD +{ + // + X_PERIOD_NOTHING, // Nothing + X_PERIOD_AUTO, // Auto Select + X_PERIOD_MANUALLY // Manually +}; + +// +// Available Market Cycles ... +enum ENUM_X_MARKET_CYCLES +{ + // + X_MARKET_CYCLE_UNKNOWN, // Unknown Cycle + X_MARKET_CYCLE_SHORT, // Short Cycle + X_MARKET_CYCLE_MEDIUM, // Medium Cycle + X_MARKET_CYCLE_LONG, // Long Cycle + X_MARKET_CYCLE_HIND, // Hind Cycle +}; + +// +// Structs ... + +// +// Model a Bar Remains Time ... +struct XBarRemainsTime +{ + // + int days; + int hours; + int minutes; + int seconds; + + // + // Constructor ... + XBarRemainsTime() + { + Clean(); + } + + // + // Always Calculate Current 0 Bar Timing ... + bool Init( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL // Trading Period + ) + { + // + bool result = false; + + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + int minuteSecoonds = 60; + int hourSeconds = minuteSecoonds * 60; + int daySeconds = 24 * hourSeconds; + + // + int periodSeconds = PeriodSeconds( + mPeriod); + datetime startTime = GetBarTime( + mSymbol, + mPeriod, + 0 + // + ); + + // + int secondsDiff = (int)startTime + periodSeconds - (int)TimeCurrent(); + + // + int mWorkingSecondsDiff = secondsDiff; + if (mWorkingSecondsDiff > daySeconds) + { + // + days = mWorkingSecondsDiff / daySeconds; + mWorkingSecondsDiff -= days * daySeconds; + } + if (mWorkingSecondsDiff > hourSeconds) + { + // + hours = mWorkingSecondsDiff / hourSeconds; + mWorkingSecondsDiff -= hours * hourSeconds; + } + if (mWorkingSecondsDiff > minuteSecoonds) + { + // + minutes = mWorkingSecondsDiff / minuteSecoonds; + mWorkingSecondsDiff -= minutes * minuteSecoonds; + } + seconds = mWorkingSecondsDiff; + + // + result = true; + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + days = 0; + hours = 0; + minutes = 0; + seconds = 0; + } + + // + // To String Representation ... + string ToString( + string dayId = "d", + string hourId = "h", + string minuteId = "m", + string secondId = "s", + string idSeparator = ": ", + string separator = ", ", + bool ignoreZeroValues = true + // + ) + { + // + string result = ""; + + // + // Days ... + if (!ignoreZeroValues || days > 0) + { + result += dayId + idSeparator + (string)days + separator; + } + + // + // Hours ... + if (!ignoreZeroValues || hours > 0) + { + // + string strHour = ToString(hours); + if (StringLen(strHour) == 1) + { + strHour = "0" + strHour; + } + + // + result += hourId + idSeparator + strHour + separator; + } + + // + // Minutes ... + if (!ignoreZeroValues || minutes > 0) + { + // + string strMinute = ToString(minutes); + if (StringLen(strMinute) == 1) + { + strMinute = "0" + strMinute; + } + + // + result += minuteId + idSeparator + strMinute + separator; + } + + // + // Seconds ... + if (!ignoreZeroValues || seconds > 0) + { + // + string strSec = ToString(seconds); + if (StringLen(strSec) == 1) + { + strSec = "0" + strSec; + } + + // + result += secondId + idSeparator + strSec; + } + + // + return result; + } +}; + +// +// Describe an Specific Candle ... +struct XOHCL +{ + // + // Props ... + + // + double high; + double open; + double close; + double low; + + // + string symbol; + datetime time; + ENUM_TIMEFRAMES period; + + // + // Constructor ... + XOHCL() + { + Clean(); + } + + // + // Init a Bar ... + // Using Bar Index ... + bool Init( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Period + int barIndex = 0 // Bar Index + ) + { + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + symbol = mSymbol; + period = mPeriod; + + // + time = iTime( + mSymbol, + mPeriod, + barIndex + // + ); + + // + open = iOpen( + mSymbol, + mPeriod, + barIndex + // + ); + + // + close = iClose( + mSymbol, + mPeriod, + barIndex + // + ); + + // + high = iHigh( + mSymbol, + mPeriod, + barIndex); + + // + low = iLow( + mSymbol, + mPeriod, + barIndex + // + ); + + // + bool result = IsValid(); + + // + return result; + } + + // + // Init a Bar ... + // Using Bar Time ... + bool Init( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Period + datetime mTime = NULL // Bar Time + ) + { + // + mTime = NormalizeTime(mTime); + + // + int barIndex = iBarShift( + mSymbol, + mPeriod, + mTime, + false // + ); + + // + bool result = Init( + mSymbol, + mPeriod, + barIndex + // + ); + + // + return result; + } + + // + bool Init( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Period + double mOpen = 0, // Open + double mHigh = 0, // High + double mClose = 0, // Close + double mLow = 0, // Low + int barIndex = 0 // Bar Index + ) + { + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + symbol = mSymbol; + period = mPeriod; + + // + time = iTime( + mSymbol, + mPeriod, + barIndex + // + ); + + // + open = mOpen; + high = mHigh; + close = mClose; + low = mLow; + + // + return IsValid(); + } + + // + bool Init( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Period + double mOpen = 0, // Open + double mHigh = 0, // High + double mClose = 0, // Close + double mLow = 0, // Low + datetime mTime = NULL // Bar Time + ) + { + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + symbol = mSymbol; + period = mPeriod; + + // + int barIndex = iBarShift( + symbol, + period, + mTime); + + // + time = iTime( + mSymbol, + mPeriod, + barIndex + // + ); + + // + open = mOpen; + high = mHigh; + close = mClose; + low = mLow; + + // + return IsValid(); + } + + // + // Tools ... + + // + void Clean() + { + // + high = 0; + open = 0; + close = 0; + low = 0; + + // + time = NULL; + symbol = NULL; + period = NULL; + } + + // + // Validate Bar ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + high > 0 && + open > 0 && + close > 0 && + low > 0 + // + ; + + // + return result; + } + + // + // Calculate X_PRICE Specified Type ... + double GetPrice(ENUM_X_PRICE mPType) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + switch (mPType) + { + // + case X_PRICE_OPEN: + result = open; + break; + // + case X_PRICE_HIGH: + result = high; + break; + // + case X_PRICE_CLOSE: + result = close; + break; + // + case X_PRICE_LOW: + result = low; + break; + } + + // + return result; + } + + // + // Retrieve Price base On Series Mode ... + double GetPrice(ENUM_SERIESMODE mMode) + { + // + ENUM_X_PRICE mXMode = ToPrice(mMode); + + // + return GetPrice(mXMode); + } + + // + // Calculate Applied Price ... + double GetPrice( + ENUM_APPLIED_PRICE mAppliedTo // Select Application Method + ) + { + // + double result = 0; + + // + // Calculate Applied Price ... + switch (mAppliedTo) + { + // + case PRICE_CLOSE: + result = close; + break; + + // + case PRICE_OPEN: + result = open; + break; + + // + case PRICE_HIGH: + result = high; + break; + + // + case PRICE_LOW: + result = low; + break; + + // + case PRICE_MEDIAN: + result = (high + low) / 2; + break; + + // + case PRICE_TYPICAL: + result = (high + low + close) / 3; + break; + + // + case PRICE_WEIGHTED: + result = (high + low + close + close) / 4; + break; + } + + // + return result; + } + + // + // Calculate Bar Mid Line ... + double GetMid() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = (high + low) / 2; + + // + return result; + } + + // + // Calculate up Price ... + double GetUp() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = MathMax(open, close); + + // + return result; + } + + // + // Calculate Down Price ... + double GetDown() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = MathMin(open, close); + + // + return result; + } + + // + // Calculate Bar Body ... + double GetBody() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetUp() - GetDown(); + + // + return result; + } + + // + // Calculate Bar Range ... + double GetRange() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = high - low; + + // + return result; + } + + // + // Calculate Bar Shadows ... + double GetShadows() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetRange() - GetBody(); + + // + return result; + } + + // + // Calculate Bar High Shadow ... + double GetHighShadow() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = + // + high - GetUp() + // + ; + + // + return result; + } + + // + // Calculate Bar Low Shadow ... + double GetLowShadow() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = + // + GetDown() - low; + // + ; + + // + return result; + } + + // + // Check Bar is Bullish ... + bool IsBullish() + { + // + bool result = false; + + // + if (!IsValid()) + { + return result; + } + + // + result = open < close; + + // + return result; + } + + // + // Check Bar is Bearish ... + bool IsBearish() + { + // + bool result = false; + + // + if (!IsValid()) + { + return result; + } + + // + result = open > close; + + // + return result; + } + + // + // Find Next Bar Time ... + datetime NextAt() + { + // + datetime result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + int prSeconds = PeriodSeconds(period); + + // + result = time + prSeconds; + + // + return result; + } + + // + // Find Prev Bar Time ... + datetime BeforeOn() + { + // + datetime result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + int prSeconds = PeriodSeconds(period); + + // + result = time - prSeconds; + + // + return result; + } + + // + // Find Current Bar Index on Chart ... + int Index() + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + result = iBarShift( + symbol, + period, + time + // + ); + + // + return result; + } + + // + bool GetPreviousBar(XOHCL &bar) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int idx = Index(); + + // + result = bar.Init( + this.symbol, + this.period, + idx + 1 // + ); + + // + return result; + } + + // + // Check Bar has Strong Body or Not ... + bool HasStrongBody() + { + // + bool result = false; + + // + if (!IsValid()) + { + return result; + } + + // + double body = GetBody(); + double shadow = GetShadows(); + + // + result = body > shadow * 1.5; + + // + return result; + } + + // + // Bar Must Open Below Prce + // and Close Above it ... + bool IsBreakUp( + double price // a Price to Check Breake + ) + { + // + bool result = false; + + // + result = HasStrongBody(); + if (!result || price <= 0) + { + return result; + } + + // + // Select required Prices ... + + // + result = + // + close > price && + open < price; + + // + return result; + } + + // + // Bar Must Open Above Prce + // and Close Below it ... + bool IsBreakDown( + double price // a Price to Check Breake + ) + { + // + bool result = false; + + // + result = HasStrongBody(); + if (!result || price <= 0) + { + return result; + } + + // + // Select required Prices ... + + // + result = + // + open > price && + close < price; + + // + return result; + } + + // + bool IsBreakOut( + double price, // a Price to Check Breake + bool useHighLow = true // if true using High and Low price for Breakeouts, if not use Open Close + ) + { + // + bool result = false; + + // + result = HasStrongBody(); + if (!result || price <= 0) + { + return result; + } + + // + // Select required Prices ... + + // + double selectedUp = + useHighLow + ? high + : GetUp(); + double selectedDown = + useHighLow + ? low + : GetDown(); + + // + result = + // + selectedUp > price && + selectedDown < price; + + // + return result; + } + + // + // Check a Support Line Rejected or not ... + bool IsSupportRejected( + double price // Support Price + ) + { + // + bool result = false; + + // + // this is zBar ... + // so we are try to Recieve CBar ... + XOHCL cBar; + result = this.GetPreviousBar(cBar); + if (!result) + { + return result; + } + + // + // Now we are going to Recieve PBar ... + XOHCL pBar; + result = cBar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // We Have this (0) Bar, cBar (1) and pBar (2) ... + + // + // pBar Down Shadow must break Price Line ... + // cBar and zBar Close must be Above Price Line ... + // also zBar Open must be Above Price Line ... + result = + // + pBar.high > price && + pBar.low < price && + cBar.close > price && + this.close > price && + this.open > price + // + ; + + // + return result; + } + + // + // Check a Support Line Breaked or not ... + bool IsSupportBreaked( + double price // Support Price + ) + { + // + bool result = false; + + // + // this is zBar ... + // so we are try to Recieve CBar ... + XOHCL cBar; + result = this.GetPreviousBar(cBar); + if (!result) + { + return result; + } + + // + // Now we are going to Recieve PBar ... + XOHCL pBar; + result = cBar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // We Have this (0) Bar, cBar (1) and pBar (2) ... + + // + // pBar Down Shadow must break Price Line ... + // cBar and zBar Close must be Below Price Line ... + // also zBar Open must be Below Price Line ... + result = + // + pBar.high > price && + pBar.low < price && + cBar.close < price && + this.close < price && + this.open < price + // + ; + + // + return result; + } + + // + // Check a Resistance Line Rejected or not ... + bool IsResistanceRejected( + double price // Resistance Price + ) + { + // + bool result = false; + + // + // this is zBar ... + // so we are try to Recieve CBar ... + XOHCL cBar; + result = this.GetPreviousBar(cBar); + if (!result) + { + return result; + } + + // + // Now we are going to Recieve PBar ... + XOHCL pBar; + result = cBar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // We Have this (0) Bar, cBar (1) and pBar (2) ... + + // + // pBar Up Shadow must break Price Line ... + // cBar and zBar Close must be Under Price Line ... + // also zBar Open must be Under Price Line ... + result = + // + pBar.high > price && + pBar.low < price && + cBar.close < price && + this.close < price && + this.open < price + // + ; + + // + return result; + } + + // + // Check a Resistance Line Breaked or not ... + bool IsResistanceBreaked( + double price // Support Price + ) + { + // + bool result = false; + + // + // this is zBar ... + // so we are try to Recieve CBar ... + XOHCL cBar; + result = this.GetPreviousBar(cBar); + if (!result) + { + return result; + } + + // + // Now we are going to Recieve PBar ... + XOHCL pBar; + result = cBar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // We Have this (0) Bar, cBar (1) and pBar (2) ... + + // + // pBar Up Shadow must break Price Line ... + // cBar and zBar Close must be Over Price Line ... + // also zBar Open must be Pver Price Line ... + result = + // + pBar.low < price && + pBar.high > price && + cBar.close > price && + this.close > price && + this.open > price + // + ; + + // + return result; + } + + // + // Check Bar is Inside Previus Bar ... + bool IsInsideBar( + double threshold = 5 // Points Distance between Up and Down + ) + { + // + bool result = false; + + // + if (threshold < 0) + { + threshold = 0; + } + + // + XOHCL pBar; + result = GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + double offset = PointToPrice(threshold, this.symbol); + + // + result = + // + pBar.high > this.high && + pBar.low < this.low && + MathAbs(pBar.low - this.low) > offset && + MathAbs(pBar.high - this.high) > offset + // + ; + + // + return result; + } + + // + // Check Bar has Strongest Body in a Range ... + bool HasStrongestBody( + int mLoopback = 3 // loopback candles to compare it ... + ) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + double body = GetBody(); + XOHCL prev = this; + for (int i = 0; i < mLoopback; i++) + { + // + bool isValid = prev.GetPreviousBar(prev); + if (!isValid) + { + // + result = false; + break; + } + + // + result = + // + result && + body > prev.GetBody() + // + ; + if (!result) + { + break; + } + } + + // + return result; + } + + // + // Check Bar has Weakest Body in a Range ... + bool HasWeakestBody( + int mLoopback = 3 // loopback candles to compare it ... + ) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + double body = GetBody(); + XOHCL prev = this; + for (int i = 0; i < mLoopback; i++) + { + // + bool isValid = prev.GetPreviousBar(prev); + if (!isValid) + { + // + result = false; + break; + } + + // + result = + // + result && + body < prev.GetBody() + // + ; + if (!result) + { + break; + } + } + + // + return result; + } + + // + // Determines Swings based On this Bar ... + // Calculates Based on atleast 3 Bars Prev ... + ENUM_X_SWING_TYPE GetSwingType() + { + // + ENUM_X_SWING_TYPE result = X_NO_SWING; + + // + // Find Current Index of Bar ... + int barIndex = Index(); + if (barIndex <= -1) + { + return result; + } + + // + // First we have to Retrieve atleast 3 Bars before this bar ... + XOHCL bars[]; + int barsCount = GetBars( + bars, + symbol, + period, + barIndex + 1, + 3 + // + ); + if (barsCount < 3) + { + return result; + } + + // + // Check Swing Start Candle has Strong Body ... + bool isStrongBodyCandle = bars[2].HasStrongBody(); + if (!isStrongBodyCandle) + { + return result; + } + + // + // Check Swing Low Conditions ... + bool isSwingLowOrderBlock = + bars[2].low < bars[1].low && + bars[1].low < bars[0].low && + bars[2].low < bars[0].low; + if (isSwingLowOrderBlock) + { + result = X_SWING_LOW; + } + + // + // Check Swing High Conditions ... + bool isSwingHighOrderBlock = + bars[2].high > bars[1].high && + bars[1].high > bars[0].high && + bars[2].high > bars[0].high; + if (isSwingHighOrderBlock) + { + result = X_SWING_HIGH; + } + + // + return result; + } + + // + // Find Swings (Highs nd Lows) ... + int FindSwing( + ENUM_X_SWING_TYPE swing, // Swing Based On Price mode ... + int mLength // Loopback ... + ) + { + // + int result = -1; + + // + if (!IsValid() || + !IsValid(swing)) + { + return result; + } + + // + int current = Index(); + int founded = FindNextSwing( + swing, + (mLength * 2) + 1, + current - mLength + // + ); + + // + while (founded != current) + { + // + current = FindNextSwing( + swing, + mLength, + current + 1 + // + ); + + // + founded = FindNextSwing( + swing, + (mLength * 2) + 1, + current - mLength + // + ); + } + + // + result = current; + + // + return result; + } + + // + // Find Next Swing ... + int FindNextSwing( + ENUM_X_SWING_TYPE swing, // Swing Based On Price mode ... + int from, // from Bar Index + int mLength // Loopback ... + ) + { + // + int result = -1; + + // + if (!IsValid() || + !IsValid(swing)) + { + return result; + } + + // + if (from < 0) + { + mLength += from; + from = 0; + } + + // + ENUM_SERIESMODE mMode = swing == X_SWING_HIGH + ? MODE_HIGH + : MODE_LOW; + + // + result = swing == X_SWING_HIGH + ? iHighest( + symbol, + period, + mMode, + mLength, + from) + : iLowest( + symbol, + period, + mMode, + mLength, + from); + + // + return result; + } + + // + // Find Lowest Bar Index ... + int FindHighestIndex( + int mLength, // Loopback ... + ENUM_SERIESMODE mMode // Calculation mode + ) + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + if (mLength < 2) + { + mLength = 2; + } + + // + result = iHighest( + symbol, + period, + mMode, + mLength, + Index()); + + // + return result; + } + + // + // Find Lowest ... + double FindHighest( + int mLength, // Loopback ... + ENUM_SERIESMODE mMode // Calculation mode + ) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + int idx = FindHighestIndex( + mLength, + mMode); + if (idx <= -1) + { + return result; + } + + // + XOHCL iH; + result = iH.Init( + symbol, + period, + idx + // + ); + if (!result) + { + return result; + } + + // + result = iH.GetPrice(mMode); + + // + return result; + } + + // + // Find Lowest Bar Index ... + int FindLowestIndex( + int mLength, // Loopback ... + ENUM_SERIESMODE mMode // Calculation mode + ) + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + if (mLength < 2) + { + mLength = 2; + } + + // + result = iLowest( + symbol, + period, + mMode, + mLength, + Index()); + + // + return result; + } + + // + // Find Lowest ... + double FindLowest( + int mLength, // Loopback ... + ENUM_SERIESMODE mMode // Calculation mode + ) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + int idx = FindLowestIndex( + mLength, + mMode); + if (idx <= -1) + { + return result; + } + + // + XOHCL iL; + result = iL.Init( + symbol, + period, + idx + // + ); + if (!result) + { + return result; + } + + // + result = iL.GetPrice(mMode); + + // + return result; + } + + // + // Candlestic Tools ... + + // + bool IsDoji() + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = IsValid() && Index() > 0; + if (!result) + { + return result; + } + + // + result = open == close; + + // + return result; + } + + // + // Convert to String Representation ... + string ToString() + { + // + string result = ""; + + // + result = GetTypeName(this) + + "(O(" + ToString(open) + "),H(" + ToString(high) + "),C(" + ToString(close) + "),L(" + ToString(low) + "))"; + + // + return result; + } +}; + +// +struct XPivot +{ + // + double pivot; // Pivot Price ... + int breaks; // Number of Breaks ... + int rejects; // Number of Rejects ... + + // + void XPivot() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + pivot = 0; + breaks = 0; + rejects = 0; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = pivot > 0; + + // + return result; + } +}; + +// +struct XPivotTracker +{ + // + XPivot pivots[]; + + // + // Constructor ... + void XPivotTracker() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + Clean(pivots); + } + + // + int Count() + { + return ArraySize(pivots); + } + + // + double Get(int index) + { + // + double result = 0; + + // + NormalizeIndex(index, pivots); + + // + XPivot iPivot = pivots[index]; + + // + result = iPivot.pivot; + + // + return result; + } + + // + XPivot GetPivot(int index) + { + // + XPivot result; + + // + NormalizeIndex(index, pivots); + + // + result = pivots[index]; + + // + return result; + } + + // + bool Add(double mPivot) + { + // + bool result = false; + + // + result = mPivot > 0 && !Has(mPivot); + if (!result) + { + return result; + } + + // + XPivot pivot; + pivot.pivot = mPivot; + + // + AddRef( + pivot, + pivots // + ); + + // + result = true; + + // + return result; + } + + // + int Adds(double &mPivots[]) + { + // + int result = 0; + + // + int pivotsCount = ArraySize(mPivots); + if (!IsValidSize(pivotsCount)) + { + return result; + } + + // + for (int i = 0; i < pivotsCount; i++) + { + // + double iPivot = mPivots[i]; + + // + bool isAdded = Add(iPivot); + if (isAdded) + { + result++; + } + } + + // + return result; + } + + // + int FindIndex(double mPivot) + { + // + int result = -1; + + // + if (mPivot <= 0) + { + return result; + } + + // + int count = Count(); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XPivot iPivot = pivots[i]; + + // + if (iPivot.pivot == mPivot) + { + // + result = i; + break; + } + } + + // + return result; + } + + // + double Has(double mPivot) + { + // + bool result = false; + + // + int pivotIDX = FindIndex(mPivot); + result = pivotIDX >= 0; + + // + return result; + } + + // + int Reject(double mPivot) + { + // + int result = 0; + + // + int pivotIDX = FindIndex(mPivot); + if (pivotIDX < 0) + { + return result; + } + + // + pivots[pivotIDX].rejects++; + + // + result = pivots[pivotIDX].rejects; + + // + return result; + } + + // + int Break(double mPivot) + { + // + int result = 0; + + // + int pivotIDX = FindIndex(mPivot); + if (pivotIDX < 0) + { + return result; + } + + // + pivots[pivotIDX].breaks++; + + // + result = pivots[pivotIDX].breaks; + + // + return result; + } + + // + bool Remove(double mPivot) + { + // + bool result = false; + + // + int pivotIDX = FindIndex(mPivot); + result = pivotIDX >= 0; + if (!result) + { + return result; + } + + // + result = ArrayRemove( + pivots, + pivotIDX, + 1 // + ); + + // + return result; + } + + // + bool HasChild() + { + // + bool result = false; + + // + int count = Count(); + result = IsValidSize(count); + + // + return result; + } +}; + +// +// Model Support and Resistance +// for Specific Bar ... +struct XOHCLSupRes +{ + // + // Props ... + + // + /// Resistances ... + double res[]; + + // + // Supports ... + double sup[]; + + // + // Constructor ... + XOHCLSupRes() + { + Clean(); + } + + // + // Init ... + bool Init( + double price, // Price ... + const double &pivots[], // Provided Pivot Points ... + int count = 3, // Number of Requireds ... + double step = 0 // Distance between each item with it's Last Side ... + ) + { + // + bool result = false; + + // + Clean(); + + // + if (price <= 0) + { + return result; + } + + // + int pivotsCount = ArraySize(pivots); + if (pivotsCount <= 0) + { + return result; + } + + // + if (count <= 0 || + count > pivotsCount - 1) + { + return result; + } + + // + double lastR = 0; + double tmpR[]; + + // + double lastS = 0; + double tmpS[]; + + // + // Extract Supports ... + // which prices is under low of candle ... + // + // Extract Resistance ... + // which prices is over high of candle ... + for (int i = 0; i < pivotsCount; i++) + { + // + double iFlat = pivots[i]; + + // + if (iFlat > price) + { + // + bool canAdd = + step <= 0 + ? true + : lastR == 0 || MathAbs(iFlat - lastR) >= step; + if (canAdd) + { + // + Add( + iFlat, + tmpR); + + // + lastR = iFlat; + } + } + else if (iFlat < price) + { + // + bool canAdd = + step <= 0 + ? true + : lastS == 0 || MathAbs(iFlat - lastS) >= step; + if (canAdd) + { + // + Add( + iFlat, + tmpS); + + // + lastS = iFlat; + } + } + } + + // + // Sorting Founded Resistance and Supports ... + + // + // Since Resistance Levels must be Increasing ... + ArraySort(tmpR); + + // + // Since Support Levels must be Decreasing ... + ArraySort(tmpS); + ArrayReverse(tmpS); + + // + // Fill Resistance ... + int tmpRCount = ArraySize(tmpR); + if (tmpRCount > 0) + { + // + if (tmpRCount < count) + { + // + ArrayCopy( + res, + tmpR); + } + else + { + // + ArrayCopy( + res, + tmpR, + 0, + 0, + count); + } + } + + // + // Fill Supports ... + int tmpSCount = ArraySize(tmpS); + if (tmpSCount > 0) + { + // + if (tmpSCount < count) + { + // + ArrayCopy( + sup, + tmpS); + } + else + { + // + ArrayCopy( + sup, + tmpS, + 0, + 0, + count); + } + } + + // + result = IsValid(); + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + Clean(sup); + Clean(res); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + CountSupports() > 0 || + CountResistances() > 0 + // + ; + + // + return result; + } + + // + int CountSupports() + { + return ArraySize(sup); + } + + // + int CountResistances() + { + return ArraySize(res); + } +}; + +// +// Tracking Times ... +struct XTimeTracker +{ + // + // Props ... + int xMonth; + int xDayOfWeek; + int xForWeekDay; + int xDay; + int xHour; + + // + // Constructor ... + XTimeTracker() + { + Clean(); + } + + // + // Tools ... + + // + void Clean() + { + // + xDay = -1; + xHour = -1; + xMonth = -1; + xDayOfWeek = -1; + xForWeekDay = -1; + } + + // + // Detecting New Houre ... + bool IsNewHour() + { + // + bool result = false; + + // + // Retrieve Current Time as Struct ... + MqlDateTime timeStruct = GetCurrentTime(); + + // + // Check Houre ... + result = timeStruct.hour != xHour; + if (result) + { + xHour = timeStruct.hour; + } + + // + return result; + } + + // + // Detecting New Day ... + bool IsNewDay() + { + // + bool result = false; + + // + // Retrieve Current Time as Struct ... + MqlDateTime timeStruct = GetCurrentTime(); + + // + // Check Houre ... + result = timeStruct.day_of_year != xDay; + if (result) + { + xDay = timeStruct.day_of_year; + } + + // + return result; + } + + // + // Detecting New Week ... + bool IsNewWeek() + { + // + bool result = false; + + // + // Retrieve Current Time as Struct ... + MqlDateTime timeStruct = GetCurrentTime(); + + // + // Check Week ... + // Since Week Starts From Monday in Forex World ... + // we Calculate Start of Week by 1-Monday ... + result = + xDayOfWeek == -1 && + xForWeekDay == -1 + ? true + : timeStruct.day_of_week == 1 && + timeStruct.day_of_year > xForWeekDay; + + // + xForWeekDay = timeStruct.day_of_year; + xDayOfWeek = timeStruct.day_of_week; + + // + return result; + } + + // + // Detecting End Of Week ... + bool IsWeekEnd() + { + // + bool result = false; + + // + // Retrieve Current Time as Struct ... + MqlDateTime timeStruct = GetCurrentTime(); + + // + // Check WeekEnd ... + // Since Week Starts From Monday in Forex World ... + // we Calculate End of Week by 5-Friday ... + result = + xDayOfWeek != -1 && + timeStruct.day_of_week == 5 && + timeStruct.hour == 23 && + timeStruct.min == 59 && + timeStruct.sec == 59; + + // + return result; + } + + // + // Detecting New Month ... + bool IsNewMonth() + { + // + bool result = false; + + // + // Retrieve Current Time as Struct ... + MqlDateTime timeStruct = GetCurrentTime(); + + // + // Check Houre ... + result = timeStruct.mon != xMonth; + if (result) + { + xMonth = timeStruct.mon; + } + + // + return result; + } +}; + +// +// Tracking Bars on Specified Environment ... +struct XBarTracker +{ + // + string symbol; // Tracking Symbol + ENUM_TIMEFRAMES period; // Tracking Time Frame + + // + int lastTrackedBar; // Last Tracked Bar ... + + // + // Constructor ... + XBarTracker() + { + Clean(); + } + + // + // Initializer ... + bool Init( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL // Trading Period + ) + { + // + bool result = false; + + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + this.symbol = mSymbol; + this.period = mPeriod; + + // + this.lastTrackedBar = 0; + + // + result = true; + + // + return result; + } + + // + // Retrieve all Bars ... + int CountBars() + { + // + return Bars( + symbol, + period + // + ); + } + + // + // Check if it's New Bar ... + bool IsNewBar() + { + // + bool result = false; + + // + int currentBars = CountBars(); + + // + result = currentBars > lastTrackedBar; + if (result) + { + lastTrackedBar = currentBars; + } + + // + return result; + } + + // + // Tools ... + void Clean() + { + // + symbol = NormalizeSymbol(NULL); + period = NormalizePeriod(NULL); + } +}; + +// +// Track Value Changes ... +template +struct XValueTracker +{ + // + // Definitions ... + + // + // Model a Value Change ... + struct XValueChange + { + // + // Props ... + datetime at; // Change Time + T from; // Before Change Value + T to; // After Change Value + + // + // Constructor ... + XValueChange() + { + Clean(); + } + + // + // Cleanup ... + void Clean() + { + // + at = NULL; + from = NULL; + to = NULL; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = IsValid(at); + if (!result) + { + return result; + } + + // + result = NotEmpty(from) && + NotEmpty(to); + + // + return result; + } + }; + + // + // Props ... + XValueChange changes[]; // Hold Changes + + // + // Constructor ... + XValueTracker() + { + Clean(); + } + + // + // Track a Change Happens Or Not ... + bool Track( + const T &source[] // Data Source for Track Changes + ) + { + // + bool result = false; + + // + if (ArraySize(source) <= 1) + { + return result; + } + + // + datetime time = TimeCurrent(); + + // + double from = source[1]; + double to = source[0]; + + // + result = to != from; + if (result) + { + return result; + } + + // + XValueChange lastChange; + bool hasLastChange = + GetLastItem( + lastChange, + changes + // + ); + result = + !hasLastChange + ? true + : lastChange.at < time && + lastChange.to != to && + lastChange.from != from; + if (!result) + { + return result; + } + + // + lastChange.Clean(); + + // + lastChange.to = to; + lastChange.at = time; + lastChange.from = from; + + // + AddRef( + lastChange, + changes + // + ); + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + Clean(changes); + } +}; + +// +// Model a Market Cycle ... +struct XMarketCycle +{ + // + // Props ... + + // + string prefix; // Prefix Trag ... + + // + string symbol; // Market Symbol ... + + // + ENUM_TIMEFRAMES period; // Period of Cycle ... + ENUM_X_PERIOD_METHOD method; // Period Selection Method ... + ENUM_X_MARKET_CYCLES cycle; // Cycles of MArket ... + + // + int length; // Number Of Candles per Current Time Frame ... + ENUM_TIMEFRAMES hostPeriod; // Current Time Frame ... + + // + datetime lastStart; // Last Candle Bar Time ... + + // + XBarTracker barTracker; // Bar Tracker ... + XBarRemainsTime remains; // Current Bar Remains Model ... + + // + // Constructor ... + XMarketCycle() + { + Clean(); + } + + // + // Init Cycle ... + bool Init( + string mSymbol, // Trading Symbol + ENUM_TIMEFRAMES mHostPeriod, // Host Period + ENUM_X_MARKET_CYCLES mCycle, // Init Cycle + string mPrefix = "" // Prefix + ) + { + // + bool result = false; + + // + mSymbol = NormalizeSymbol(mSymbol); + mHostPeriod = NormalizePeriod(mHostPeriod); + + // + result = IsValid(mCycle); + if (!result) + { + return result; + } + + // + this.cycle = mCycle; + + // + // Set Automatically Prefix ... + if (StringLen(mPrefix) == 0) + { + this.prefix = ToString(cycle); + } + + // + result = IsValid( + method, + period // + ); + if (!result) + { + return result; + } + + // + this.symbol = mSymbol; + this.hostPeriod = mHostPeriod; + + // + // Find Cycle Period ... + if (method == X_PERIOD_AUTO) + { + // + // Select Period ... + this.period = GetCyclePeriod( + this.cycle, + this.hostPeriod); + } + + // + // Set Prefix if Provided ... + if (StringLen(mPrefix) > 0) + { + this.prefix = mPrefix; + } + + // + // Calculate Required Info ... + + // + // Length ... + this.length = PeriodSeconds(this.period) / PeriodSeconds(this.hostPeriod); + + // + // Update Additional Data ... + result = this.Update(0); + + // + return result; + } + + // + bool Init( + string mSymbol, // Trading Symbol + ENUM_TIMEFRAMES mHostPeriod, // Host Period + ENUM_X_MARKET_CYCLES mCycle, // Init Cycle + ENUM_X_PERIOD_METHOD mMethod, // Period Selection Method + ENUM_TIMEFRAMES mPeriod, // Provided Period + string mPrefix = "" // Prefix + ) + { + // + this.period = mPeriod; + this.method = mMethod; + + // + return Init( + mSymbol, + mHostPeriod, + mCycle, + mPrefix + // + ); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + length = 0; + lastStart = 0; + + // + cycle = NULL; + prefix = NULL; + symbol = NULL; + period = NULL; + method = NULL; + hostPeriod = NULL; + + // + remains.Clean(); + barTracker.Clean(); + } + + // + // Check Structure Valid ... + bool IsValid() + { + // + bool result = false; + + // + result = IsValid( + method, + period); + if (!result) + { + return result; + } + + // + result = + // + length > 0 && + symbol != NULL && + period != NULL && + method != NULL && + hostPeriod != NULL && + method != X_PERIOD_NOTHING + // + ; + + // + return result; + } + + // + // Update Market Cycle Additional Info ... + bool Update(int hostBarIndex) + { + // + bool result = false; + + // + result = this.IsValid(); + if (!result) + { + return result; + } + + // + // Init Remains ... + result = remains.Init( + this.symbol, + this.period); + if (!result) + { + return result; + } + + // + // Init Bar Tracker ... + result = barTracker.Init( + this.symbol, + this.period); + if (!result) + { + return result; + } + + // + return result; + } + + // + // Count Bars ... + int CountBars() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = barTracker.CountBars(); + + // + return result; + } + + // + // Check New Bar ... + bool IsNewBar() + { + // + bool result = false; + + // + if (!IsValid()) + { + return result; + } + + // + result = barTracker.IsNewBar(); + + // + return result; + } + + // + // Retrieve Current Bar Index based on Host Period bar Index ... + int GetBarIndex(int barIndex) + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + if (barIndex < 0) + { + return result; + } + + // + int totalBars = CountBars(); + if (barIndex >= totalBars) + { + // + result = totalBars - 1; + return result; + } + + // + datetime hostBarTime = iTime( + this.symbol, + this.hostPeriod, + barIndex + // + ); + + // + result = iBarShift( + this.symbol, + this.period, + hostBarTime + // + ); + + // + return result; + } + + // + // Retrieve Current Cycles Specific Bar ... + XOHCL GetBar(int barIndex) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int totalBars = CountBars(); + if (barIndex >= totalBars) + { + barIndex = totalBars - 1; + } + + // + XOHCL result; + result.Init( + this.symbol, + this.period, + barIndex + // + ); + + // + return result; + } + + // + // Extract Specific Range of Bars ... + // using Start Bar Index ... + int GetBars( + XOHCL &result[], // Hold Result + int from = 0, // Start Bar Index + int count = 1, // Number of Bars + bool forceClean = true // Clean Result Array + ) + { + // + int mResult = 0; + + // + if (from < 0) + { + from = 0; + } + + // + int total = Bars( + symbol, + period); + if (from > total - 2) + { + from = total - 2; + } + + // + if (count < 0) + { + count = 1; + } + + // + int start = from; + int end = start + count; + if (end > total - 1) + { + end = total - 1; + } + + // + if (forceClean) + { + Clean(result); + } + + // + int beforeSize = ArraySize(result); + + // + for (int i = start; i < end; i++) + { + // + XOHCL iBar; + bool isValid = iBar.Init( + symbol, + period, + i + // + ); + + // + if (isValid) + { + // + AddRef( + iBar, + result + // + ); + } + } + + // + int afterSize = ArraySize(result); + + // + mResult = afterSize - beforeSize; + + // + return mResult; + } + + // + // Extract Specific Range of Bars ... + // using Start Bar Time ... + int GetBars( + XOHCL &result[], // Hold Result + datetime from = NULL, // Start Bar Time + int count = 1, // Number of Bars + bool forceClean = true // Clean Result Array + ) + { + // + from = NormalizeTime(from); + + // + int barIndex = iBarShift( + symbol, + period, + from, + false + // + ); + + // + return GetBars( + result, + symbol, + period, + barIndex, + count, + forceClean + // + ); + } + + // + // Retrieve Bar Time ... + datetime GetBarTime(int barIndex) + { + // + datetime result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int totalBars = CountBars(); + if (barIndex >= totalBars) + { + barIndex = totalBars - 1; + } + + // + result = iTime( + this.symbol, + this.period, + barIndex + // + ); + + // + return result; + } + + // + // Find Chart ID ... + ulong GetChartID() + { + // + ulong result = 0; + + // + long firstChart = ChartFirst(); + result = firstChart; + + // + while (result >= 0) + { + // + string chSymbol = ChartSymbol(result); + ENUM_TIMEFRAMES chPeriod = ChartPeriod(result); + + // + bool isOwnChart = + // + symbol == chSymbol && + period == chPeriod + // + ; + if (isOwnChart) + { + break; + } + + // + result = ChartNext(result); + if (result < 0) + { + break; + } + } + + // + return result; + } + + // + // Create and String Representation for Unique Taging ... + string ToString() + { + // + string result = ""; + + // + if (!IsValid()) + { + return result; + } + + // + result = + GetTypeName(this) + "(" + + "PRFX(" + this.prefix + ")" + + "SMBL(" + this.symbol + ")" + + "CYC(" + ToString(this.cycle) + ")" + + "PRD(" + ToString(this.period) + ")" + + "PRDHST(" + ToString(this.hostPeriod) + ")" + + "MTH(" + EnumToString(this.method) + ")" + + ")"; + + // + return result; + } + + // + // Here we Produce a Summary brief of + // state of Cycle ... + string GenerateSummary() + { + // + string result = ""; + + // + bool hasPrefix = + StringLen(this.prefix) > 0 && + this.prefix != ToString(this.cycle); + result += (hasPrefix ? this.prefix + "[" : "") + + ToString(this.cycle) + + (hasPrefix ? "]" : "") + "\n"; + + // + result += " - PR: " + ToString(this.period) + "\n"; + + // + XOHCL cBar = GetBar(0); + + // + result += " - State: " + (cBar.IsBullish() ? "Bullish" : cBar.IsBearish() ? "Bearish" + : "Neutural"); + + // + return result; + } +}; + +// +// Styling Buffers ... + +// +struct XBufferPlotStyle +{ + // + int width; // Width + color clr; // Color + uchar arrow; // Arrow Code + ENUM_DRAW_TYPE type; // Type + ENUM_LINE_STYLE style; // Style + + // + // Constructor ... + XBufferPlotStyle() + { + Default(); + } + + // + // Tools ... + + // + // Default ... + void Default() + { + // + width = 1; + arrow = 0; + clr = CLR_NONE; + type = DRAW_NONE; + style = STYLE_SOLID; + } +}; + +// +// Register a Buffer as Indexed Buffer ... +void SetIndexBuffer( + int &index, // the Index refrence for Buffer + double &buffer[], // Buffer to Set + XBufferPlotStyle &style, // Style to Apply to Buffer + double &colorBuffer[], // Color Buffer + string label = NULL, // Buffer Label + bool showData = true, // Show Data on Data Window + double empty = -1, // Set 0 or EMPTY_VALUE used for setting Empty Value + int drawBegin = -1 // if Set More Than -1 applied +) +{ + // + // Set Buffer Index ... + SetIndexBuffer(index, buffer, INDICATOR_DATA); + + // + // Show Date ... + PlotIndexSetInteger(index, PLOT_SHOW_DATA, showData); + + // + // Set Buffer Label ... + if (IsValid(label)) + { + PlotIndexSetString(index, PLOT_LABEL, label); + } + + // + if (empty == 0 || empty == EMPTY_VALUE) + { + PlotIndexSetDouble(index, PLOT_EMPTY_VALUE, empty); + } + + // + if (drawBegin > -1) + { + PlotIndexSetInteger(index, PLOT_DRAW_BEGIN, drawBegin); + } + + // + if (style.type == DRAW_ARROW) + { + PlotIndexSetInteger(index, PLOT_ARROW, style.arrow); + } + + // + PlotIndexSetInteger(index, PLOT_LINE_STYLE, style.style); + PlotIndexSetInteger(index, PLOT_LINE_WIDTH, style.width); + + // + string drawTypeStr = EnumToString(style.type); + bool hasColorBuffer = Contains("COLOR", drawTypeStr); + + // + if (!hasColorBuffer) + { + PlotIndexSetInteger(index, PLOT_LINE_COLOR, style.clr); + } + else + { + // + // Since Color Buffers must add as next Index of it's own Buffer + // here before applied Color Buffer increase index ... + index++; + + // + SetIndexBuffer(index, colorBuffer, INDICATOR_COLOR_INDEX); + } + + // + // Increase Index for Next Buffer ... + index++; +} + +// +void SetIndexCandleBuffers( + int &index, // the Index refrence for Buffer + string openLabel, // Open Label + double &open[], // Open Buffer + string highLabel, // High Label + double &high[], // High Buffer + string lowLabel, // Low Label + double &low[], // Low Buffer + string closeLabel, // Close Label + double &close[], // Close Buffer + bool showData = true, // Show Data on Data Window + double empty = -1, // Set 0 or EMPTY_VALUE used for setting Empty Value + int drawBegin = -1 // if Set More Than -1 applied +) +{ + // + bool hasLabel = + // + IsValid(openLabel) && + IsValid(highLabel) && + IsValid(lowLabel) && + IsValid(closeLabel) + // + ; + + // + string label = + !hasLabel + ? NULL + : openLabel + ";" + highLabel + ";" + lowLabel + ";" + closeLabel; + + // + // Set Buffer Index ... + SetIndexBuffer(index, open, INDICATOR_DATA); + + // + // Set Draw Candles Type ... + PlotIndexSetInteger(index, PLOT_LINE_STYLE, DRAW_CANDLES); + + // + // Show Date ... + PlotIndexSetInteger(index, PLOT_SHOW_DATA, showData); + + // + // Set Buffer Label ... + if (IsValid(label)) + { + PlotIndexSetString(index, PLOT_LABEL, label); + } + + // + if (empty == 0 || empty == EMPTY_VALUE) + { + PlotIndexSetDouble(index, PLOT_EMPTY_VALUE, empty); + } + + // + if (drawBegin > -1) + { + PlotIndexSetInteger(index, PLOT_DRAW_BEGIN, drawBegin); + } + + // + index++; + + // + // Set Buffer Index ... + SetIndexBuffer(index, high, INDICATOR_DATA); + index++; + + // + // Set Buffer Index ... + SetIndexBuffer(index, low, INDICATOR_DATA); + index++; + + // + // Set Buffer Index ... + SetIndexBuffer(index, close, INDICATOR_DATA); + index++; +} + +// +void SetIndexCandleBuffers( + int &index, // the Index refrence for Buffer + string openLabel, // Open Label + double &open[], // Open Buffer + string highLabel, // High Label + double &high[], // High Buffer + string lowLabel, // Low Label + double &low[], // Low Buffer + string closeLabel, // Close Label + double &close[], // Close Buffer + double &colorBuffer[], // Candle Color Buffer + bool showData = true, // Show Data on Data Window + double empty = -1, // Set 0 or EMPTY_VALUE used for setting Empty Value + int drawBegin = -1 // if Set More Than -1 applied +) +{ + // + SetIndexCandleBuffers( + index, + openLabel, + open, + highLabel, + high, + lowLabel, + low, + closeLabel, + close, + showData, + empty, + drawBegin // + ); + + // + int mFirstIndex = index - 4; + + // + // Set Draw Candles Type ... + PlotIndexSetInteger(mFirstIndex, PLOT_LINE_STYLE, DRAW_COLOR_CANDLES); + + // + // Set Color Buffer ... + SetIndexBuffer(index, colorBuffer, INDICATOR_COLOR_INDEX); + + // + index++; +} + +// +// Functions ... + +// +// Validators ... + +// +// Validate an String has length and not NULL ... +bool IsValid(string value) +{ + // + bool result = false; + + // + result = + // + value != NULL && + StringLen(value) > 0 + // + ; + + // + return result; +} +bool IsSpecifiedValid(string value) +{ + return IsValid(value); +} + +// +// Validate a Date ... +bool IsValid(datetime value) +{ + // + bool result = false; + + // + result = NotEmpty(value) && value != NULL; + + // + return result; +} + +// +// Validate a Period Param ... +bool IsValid(ENUM_TIMEFRAMES value) +{ + // + bool result = false; + + // + result = + // + value != NULL + // + ; + + // + return result; +} +bool IsSpecifiedValid(ENUM_TIMEFRAMES value) +{ + // + return IsValid(value); +} + +// +// Validate Specified Cycle ... +bool IsValid(ENUM_X_MARKET_CYCLES value) +{ + // + bool result = false; + + // + result = + // + value != NULL && + value != X_MARKET_CYCLE_UNKNOWN + // + ; + + // + return result; +} + +// +// Validate Specific Period Mode ... +bool IsValid( + ENUM_X_PERIOD_METHOD mMethod, // Period Select Method + ENUM_TIMEFRAMES mPeriod // Selected Period +) +{ + // + bool result = false; + + // + result = + // + mMethod == X_PERIOD_NOTHING + ? false + : mMethod == X_PERIOD_MANUALLY + ? mPeriod != NULL + : mMethod == X_PERIOD_AUTO + ? true + : false + // + ; + + // + return result; +} + +// +bool IsSpecifiedValid( + ENUM_X_PERIOD_METHOD mMethod, // Period Select Method + ENUM_TIMEFRAMES mPeriod // Selected Period +) +{ + return IsValid(mMethod, + mPeriod // + ); +} + +// +// Validate Swing Mode ... +bool IsValid(ENUM_X_SWING_TYPE value) +{ + // + bool result = false; + + // + result = + // + value == X_SWING_HIGH || + value == X_SWING_LOW + // + ; + + // + return result; +} + +// +// As IS ... + +// +// Determine a Position type is Long or not ... +bool IsLong(ENUM_POSITION_TYPE type) +{ + // + bool result = type == POSITION_TYPE_BUY; + + // + return result; +} +bool IsLong(ENUM_ORDER_TYPE type) +{ + // + bool result = type == ORDER_TYPE_BUY; + + // + return result; +} + +// +// Determine a Position type is Short or not ... +bool IsShort(ENUM_POSITION_TYPE type) +{ + // + bool result = type == POSITION_TYPE_SELL; + + // + return result; +} +bool IsShort(ENUM_ORDER_TYPE type) +{ + // + bool result = type == ORDER_TYPE_SELL; + + // + return result; +} + +// +// Retrieve Opposit Direction Type ... +ENUM_POSITION_TYPE GetOpposit(ENUM_POSITION_TYPE type) +{ + // + ENUM_POSITION_TYPE result = NULL; + + // + bool isLong = IsLong(type); + result = isLong + ? POSITION_TYPE_SELL + : POSITION_TYPE_BUY; + + // + return result; +} +ENUM_ORDER_TYPE GetOpposit(ENUM_ORDER_TYPE type) +{ + // + ENUM_ORDER_TYPE result = NULL; + + // + bool isLong = IsLong(type); + result = isLong + ? ORDER_TYPE_SELL + : ORDER_TYPE_BUY; + + // + return result; +} + +// +// Check Expert Running in Testing Mode or not ... +bool IsRunningOnTestMode() +{ + // + bool result = false; + + // + // check programm mode ... + result = MQL5InfoInteger(MQL5_TESTING); + + // + return result; +} + +// +// Find Chart ID ... +long FindChartID( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL // Trading Period +) +{ + // + long result = ChartFirst(); + long first = result; + + // + while (result > 0) + { + // + string chSymbol = ChartSymbol(result); + ENUM_TIMEFRAMES chPeriod = ChartPeriod(result); + + // + bool isOwn = + // + chSymbol == mSymbol && + chPeriod == mPeriod + // + ; + if (isOwn) + { + break; + } + + // + result = ChartNext(result); + } + + // + return result; +} + +// +// Normalizers ... + +// +// Check a Symbol provided or not ... +// if not use Default ... +string NormalizeSymbol(string value) +{ + // + string result = value; + + // + if (!IsValid(result)) + { + result = _Symbol; + } + + // + return result; +} + +// +// Check a Datetime provided or not ... +// if not use Current ... +datetime NormalizeTime(datetime value) +{ + // + datetime result = value; + + // + if (!IsValid(result)) + { + result = TimeCurrent(); + } + + // + return result; +} + +// +// Check a Period provided or not ... +// if not use Default ... +ENUM_TIMEFRAMES NormalizePeriod(ENUM_TIMEFRAMES value) +{ + // + ENUM_TIMEFRAMES result = value; + + // + if (!IsValid(value)) + { + result = _Period; + } + + // + return result; +} + +// +// Normalize Cycle ... +ENUM_X_MARKET_CYCLES NormalizeCycle(ENUM_X_MARKET_CYCLES value) +{ + // + ENUM_X_MARKET_CYCLES result = value; + + // + if (!IsValid(result)) + { + result = X_MARKET_CYCLE_SHORT; + } + + // + return value; +} + +// +// Validate a Buffer Size for Looping or etc ... +bool IsValidSize(int size) +{ + // + bool result = size > 0; + + // + return result; +} + +// +// Normalize Index Based On Specified Buffer ... +template +void NormalizeIndex( + int &index, + T &buffer[] // +) +{ + // + int bufferSize = ArraySize(buffer); + + // + if (bufferSize <= 0) + { + index = 0; + } + + // + if (index <= 0) + { + index = 0; + } + + // + if (index > bufferSize - 1) + { + index = bufferSize - 1; + } +} + +// +// Normalize Start and Count based on Specified Buffer ... +template +void NormalizeCount( + int &start, + int &count, + T &buffer[] // +) +{ + // + // Validate Buffer Size ... + int bufferSize = ArraySize(buffer); + if (!IsValidSize(bufferSize)) + { + return; + } + + // + // Normalization Start ... + NormalizeIndex( + start, + buffer // + ); + + // + if (count < start) + { + count = (start - count); + } + + // + // Normalization Count ... + + // + if (count < 0) + { + count = start; + } + + // + if (count > bufferSize) + { + count = bufferSize; + } +} + +// +// Normalize a give Volume ... +double NormalizeVolume( + double mVolume, // desired volume to normalize + string mSymbol = NULL, // Trading Symbol + int mLength = 2 // Length of Digits +) +{ + // + double result = mVolume; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + // Normalize Digits ... + int digits = GetDigits(mSymbol); + + // + mLength = + mLength == 0 || mLength > digits + ? digits + : MathMin(mLength, digits); + + // + // Normalize Volume ... + result = NormalizeDouble(result, mLength); + + // + double maxAvailableVolume = SymbolInfoDouble(mSymbol, SYMBOL_VOLUME_MAX); + double minAvailableVolume = SymbolInfoDouble(mSymbol, SYMBOL_VOLUME_MIN); + + // + // Validate Result ... + if (result > maxAvailableVolume) + { + result = maxAvailableVolume; + } + else if (result < minAvailableVolume) + { + result = minAvailableVolume; + } + + // + return result; +} + +// +// Normallize Price ... +double NormalizePrice( + double mPrice, // desired Price for normalization + string mSymbol = NULL // Trading Symbol +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double tickSize = 0; + result = SymbolInfoDouble(mSymbol, SYMBOL_TRADE_TICK_SIZE, tickSize); + + // + int digits = GetDigits(mSymbol); + result = NormalizeDouble(MathRound(mPrice / tickSize) * tickSize, digits); + + // + return result; +} + +// +// Prices ... + +// +// Retrieve Ask Price ... +double GetAsk( + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double result = SymbolInfoDouble(mSymbol, SYMBOL_ASK); + + // + return result; +} + +// +// Retrieve Bid Price ... +double GetBid( + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double result = SymbolInfoDouble(mSymbol, SYMBOL_BID); + + // + return result; +} + +// +// Retrieve Spread Price ... +double GetSpread( + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double ask = GetAsk(mSymbol); + double bid = GetBid(mSymbol); + + // + double result = MathAbs(ask - bid); + + // + return result; +} + +// +// Retrieve Point Value ... +double GetPoints( + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double result = SymbolInfoDouble(mSymbol, SYMBOL_POINT); + + // + return result; +} + +// +// Retrieve Point Digits ... +int GetDigits( + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + int result = (int)SymbolInfoInteger(mSymbol, SYMBOL_DIGITS); + + // + return result; +} + +// +// Retrieve Entry Price ... +double GetEntry( + string mSymbol = NULL, // Trading Symbol + ENUM_POSITION_TYPE type = POSITION_TYPE_BUY // Get entry price for Which direction trade ... +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + result = + IsLong(type) + ? GetAsk(mSymbol) + : GetBid(mSymbol); + result = NormalizePrice(result, mSymbol); + + // + return result; +} + +// +// Retrieve Exit Price ... +double GetExit( + string mSymbol = NULL, // Trading Symbol + ENUM_POSITION_TYPE type = POSITION_TYPE_BUY // Get entry price for Which direction trade ... +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + result = + IsLong(type) + ? GetBid(mSymbol) + : GetAsk(mSymbol); + result = NormalizePrice(result, mSymbol); + + // + return result; +} + +// +// Get 1 Pip in Price Value ... +double GetPipPrice( + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double symbolPoint = GetPoints(mSymbol); + int symbolDigits = GetDigits(mSymbol); + + // + double result = symbolPoint; + if (symbolDigits == 3 || symbolDigits == 5) + { + result *= 10; + } + + // + return result; +} + +// +// Converts Pips To Price ... +double PipsToPrice( + double mPips, // pips amount + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + int digits = GetDigits(mSymbol); + double pipValue = GetPipPrice(mSymbol); + double result = mPips * pipValue; + + // + result = NormalizePrice(result, mSymbol); + + // + return result; +} + +// +// Converts Price to Pips ... +double PriceToPips( + double mPrice, // the price amount which required to calculate + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + mPrice = NormalizePrice(mPrice, mSymbol); + + // + int digits = GetDigits(mSymbol); + double pipPrice = GetPipPrice(mSymbol); + + // + double result = mPrice / pipPrice; + + // + result = NormalizeDouble(result, digits); + + // + return result; +} + +// +// Convert Price to Point ... +double PriceToPoint( + double price, // the price amount which required to calculate + string mSymbol = NULL // Trading Symbol +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + price = NormalizePrice(price, mSymbol); + + // + double point = GetPoints(mSymbol); + result = price / point; + + // + return result; +} + +// +// Converts Point to Price ... +double PointToPrice( + double points, // Points Amount + string mSymbol = NULL // Trading Symbol +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double point = GetPoints(mSymbol); + result = points * point; + + // + result = NormalizePrice(result, mSymbol); + + // + return result; +} + +// +// Converts Series Mode to XPRICE ... +ENUM_X_PRICE ToPrice( + ENUM_SERIESMODE mMode // Specified Series Mode ... +) +{ + // + ENUM_X_PRICE result = X_PRICE_CLOSE; + + // + switch (mMode) + { + // + // High ... + case MODE_HIGH: + result = X_PRICE_HIGH; + break; + + // + // Open ... + case MODE_OPEN: + result = X_PRICE_OPEN; + break; + + // + // Low ... + case MODE_LOW: + result = X_PRICE_LOW; + break; + + // + // Close ... + // Default ... + case MODE_CLOSE: + default: + result = X_PRICE_CLOSE; + break; + } + + // + return result; +} + +// +// Retrieve Applied Price ... +template +double GetAppliedPrice( + ENUM_APPLIED_PRICE tprice, // Type of Price Selection + T &open[], // Open Prices + T &high[], // High Preices + T &low[], // Low Prices + T &close[], // Close Prices + int i // Bar Index +) +{ + switch (tprice) + { + case PRICE_CLOSE: + return (close[i]); + case PRICE_OPEN: + return (open[i]); + case PRICE_HIGH: + return (high[i]); + case PRICE_LOW: + return (low[i]); + case PRICE_MEDIAN: + return ((high[i] + low[i]) / 2.0); + case PRICE_TYPICAL: + return ((high[i] + low[i] + close[i]) / 3.0); + case PRICE_WEIGHTED: + return ((high[i] + low[i] + close[i] + close[i]) / 4.0); + } + return (0); +} + +// +// Calculate TP/SL for Specified Type of Positions ... +void CalculateTPSL( + double &mSL, // Hold SL + double &mTP, // Hold TP + ENUM_POSITION_TYPE mType, // Position Type Long (Buy) / Short (Sell) + double mEntry, // Entry Price + double mR2R = 1, // Provided Risk To Reward Ratio + double slPrice = 0, // Provided SL Price + double tpPrice = 0 // Provided TP Price +) +{ + // + // if Both TP and SL Provided, ignore R2R and Calculate direct ... + // if SL provided, Calculate TP based on Provided R2R ... + // if TP provided, Calculate SL based on Provided R2R ... + // default R2R is set to 1 ... + + // + mSL = 0; + mTP = 0; + + // + bool isLong = IsLong(mType); + + // + // Set Default R2R ... + if (mR2R < 1) + { + mR2R = 1; + } + + // + if (mEntry <= 0 || + (tpPrice <= 0 && slPrice <= 0)) + { + return; + } + + // + double risk = 0; + double reward = 0; + + // + bool canCalculateBasedOnSL = slPrice > 0 && + (isLong + ? slPrice < mEntry + : slPrice > mEntry); + + // + bool canCalculateBasedOnTP = tpPrice > 0 && + (isLong + ? tpPrice > mEntry + : tpPrice < mEntry); + + // + if (canCalculateBasedOnSL && !canCalculateBasedOnTP) + { + // + risk = MathAbs(mEntry - slPrice); + reward = risk * mR2R; + } + else if (!canCalculateBasedOnSL && canCalculateBasedOnTP) + { + // + reward = MathAbs(mEntry - tpPrice); + risk = reward / mR2R; + } + else if (!canCalculateBasedOnSL && !canCalculateBasedOnTP) + { + // + bool canSetTPPrice = isLong + ? tpPrice > mEntry + : tpPrice < mEntry; + if (canSetTPPrice) + { + mTP = tpPrice; + } + + // + bool canSetSLPrice = isLong + ? slPrice < mEntry + : slPrice > mEntry; + if (canSetSLPrice) + { + mSL = slPrice; + } + + // + return; + } + + // + mTP = isLong + ? mEntry + reward + : mEntry - reward; + + // + mSL = isLong + ? mEntry - reward + : mEntry + reward; +} + +// +bool GetTick( + string mSymbol, + MqlTick &tick // +) +{ + return SymbolInfoTick(mSymbol, tick); +} + +// +// Symbols ... + +// +// Retrieve Available Symbols ... +int GetAllSymbols( + string &symbols[], // Hold Result + bool onlyInWatchList = false, // Specified Retrieve only Symbols which in Watch List + bool forceClean = true // Force To Clean Result Array +) +{ + // + int result = 0; + + // + if (forceClean) + { + Clean(symbols); + } + + // + int beforeSize = ArraySize(symbols); + + // + int symbolsCount = SymbolsTotal(onlyInWatchList); + if (symbolsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < symbolsCount; i++) + { + // + string iSymbol = SymbolName( + i, + onlyInWatchList + // + ); + if (!IsValid(iSymbol)) + { + continue; + } + + // + Add( + iSymbol, + symbols + // + ); + } + + // + int afterSize = ArraySize(symbols); + + // + result = afterSize - beforeSize; + + // + return result; +} + +// +// This is a Global Way to Filter Symbols +// you can pass Specific string as Query or a List String for Filtering ... +int FilterSymbols( + string query, // Which Query to Search Symbol + string &symbols[], // Hold Result + bool onlyInWatchList = false, // Specified Retrieve only Symbols which in Watch List + bool forceClean = true, // Force To Clean Result Array + bool ignoreCase = true, // Ignore Case + string querySeparator = "," // If Provided means query is a COllection of Queries and need to be Splitted +) +{ + // + int result = 0; + + // + if (forceClean) + { + Clean(symbols); + } + + // + if (!IsValid(query)) + { + return result; + } + + // + // Check Query is an String array or not ... + string mQueries[]; + int queriesCount = 0; + if (IsValid(querySeparator) && Contains(querySeparator, query, true)) + { + // + queriesCount = SplitContent( + mQueries, + query, + querySeparator + // + ); + } + + // + int beforeSize = ArraySize(symbols); + + // + string allSymbols[]; + int allSymbolsCount = GetAllSymbols( + allSymbols, + onlyInWatchList, + forceClean); + if (allSymbolsCount <= 0) + { + return result; + } + + // + // Loop Through all Symbols ... + for (int i = 0; i < allSymbolsCount; i++) + { + // + string iSymbol = allSymbols[i]; + + // + bool isFilterPassed = false; + if (queriesCount == 0) + { + // + isFilterPassed = Contains( + query, + iSymbol, + ignoreCase + // + ); + } + else if (queriesCount > 0) + { + // + isFilterPassed = Contains( + mQueries, + iSymbol, + ignoreCase + // + ); + } + + // + if (isFilterPassed) + { + // + Add( + iSymbol, + symbols + // + ); + } + } + + // + int afterSize = ArraySize(symbols); + + // + result = afterSize - beforeSize; + + // + return result; +} + +// +int FilterUSDSymbols( + string &symbols[], // Hold Result + bool onlyInWatchList = false, // Specified Retrieve only Symbols which in Watch List + bool forceClean = true, // Force To Clean Result Array + bool ignoreCase = true, // Ignore Case + string querySeparator = "," // If Provided means query is a COllection of Queries and need to be Splitted +) +{ + // + return FilterSymbols( + "USD", + symbols, + onlyInWatchList, + forceClean, + ignoreCase, + querySeparator + // + ); +} + +// +// Time / Date ... + +// +// Representation of Time Struct ... +// struct MqlDateTime +// { +// int year; // Year +// int mon; // Month +// int day; // Day +// int hour; // Hour +// int min; // Minutes +// int sec; // Seconds +// int day_of_week; // Day of week (0-Sunday, 1-Monday, ... ,6-Saturday) +// int day_of_year; // Day number of the year (January 1st is assigned the number value of zero) +// }; + +// +// Converts Time to Seconds ... +ulong TimeToSeconds( + datetime time // Specify time to Convert ... +) +{ + // + ulong result = (ulong)time; + + // + return result; +} +ulong TimeToSeconds( + MqlDateTime &time // Specify time to Convert ... +) +{ + // + datetime dTime = StructToTime(time); + + // + ulong result = TimeToSeconds(dTime); + + // + return result; +} + +// +// Converts Seconds To Time ... +datetime SecondsToTime( + ulong seconds // Specify Seconds to Convert ... +) +{ + // + datetime result = (datetime)seconds; + + // + return result; +} +MqlDateTime SecondsToStruct( + ulong seconds // Specify Seconds to Convert ... +) +{ + // + datetime dTime = SecondsToTime(seconds); + + // + MqlDateTime result = {}; + TimeToStruct( + dTime, + result); + + // + return result; +} + +// +// Converts Time to MilliSeconds ... +ulong TimeToMilliSeconds( + datetime time // Specify time to Convert ... +) +{ + // + ulong result = TimeToSeconds(time) * 1000; + + // + return result; +} +ulong TimeToMilliSeconds( + MqlDateTime &time // Specify time to Convert ... +) +{ + // + datetime dTime = StructToTime(time); + + // + ulong result = TimeToMilliSeconds(dTime); + + // + return result; +} + +// +// Converts MillisSeconds to Time ... +datetime MilliSecondsToTiem( + ulong milliSeconds // Specify MilliSeconds to Convert ... +) +{ + // + ulong seconds = milliSeconds / 1000; + + // + datetime result = SecondsToTime(seconds); + + // + return result; +} +MqlDateTime MilliSecondsToStruct( + ulong milliSeconds // Specify MilliSeconds to Convert ... +) +{ + // + datetime dTime = MilliSecondsToTiem(milliSeconds); + + // + MqlDateTime result = {}; + TimeToStruct( + dTime, + result); + + // + return result; +} + +// +// Retrieve DateTime Structure ... +MqlDateTime GetCurrentTime() +{ + // + MqlDateTime result = {}; + + // + TimeCurrent(result); + + // + return result; +} + +// +// Retrieve Current Time as Seconds ... +ulong GetCurrentTimeAsSeconds() +{ + // + datetime time = TimeCurrent(); + + // + ulong result = TimeToSeconds(time); + + // + return result; +} + +// +// Retrieve Current Time as MilliSeconds ... +ulong GetCurrentTimeAsMilliSeconds() +{ + // + datetime time = TimeCurrent(); + + // + ulong result = TimeToMilliSeconds(time); + + // + return result; +} + +// +// Bar Times ... + +// +// Retrieve Specified Bar Time ... +datetime GetBarTime( + string mSymbol = "", // Specify Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Specify TimeFrame + int barIndex = 0 // Specify Bar Index +) +{ + // + // Validate and Normalize Args ... + + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + // Retrieve Bar Time ... + datetime result = iTime( + mSymbol, + mPeriod, + barIndex); + + // + return result; +} + +// +// Retrieve Specified Bar Time ... +ulong GetBarTimeAsSeconds( + string mSymbol = "", // Specify Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Specify TimeFrame + int barIndex = 0 // Specify Bar Index +) +{ + // + // Retrieve Bar Time ... + datetime time = GetBarTime( + mSymbol, + mPeriod, + barIndex); + + // + ulong result = TimeToSeconds(time); + + // + return result; +} + +// +// Retrieve Specified Bar Time ... +ulong GetBarTimeAsMilliSeconds( + string mSymbol = "", // Specify Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Specify TimeFrame + int barIndex = 0 // Specify Bar Index +) +{ + // + // Retrieve Bar Time ... + datetime time = GetBarTime( + mSymbol, + mPeriod, + barIndex); + + // + ulong result = TimeToMilliSeconds(time); + + // + return result; +} + +// +// Retrieve a Bar Time Structure ... +MqlDateTime GetBarTimeStruct( + string mSymbol = "", // Specify Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Specify TimeFrame + int barIndex = 0 // Specify Bar Index +) +{ + // + MqlDateTime result = {}; + + // + // Retrieve Bar Time ... + datetime barTime = GetBarTime( + mSymbol, + mPeriod, + barIndex); + + // + // Convert to Structure ... + TimeToStruct(barTime, result); + + // + return result; +} + +// +// Other Tools ... + +// +template +bool IsSame( + T &buffer[], // Search Buffer + int count = 5, // Number of Searchs + int start = 0 // Start ... +) +{ + // + bool result = false; + + // + int bufferSize = ArraySize(buffer); + result = bufferSize > 0; + if (!result) + { + return result; + } + + // + // Validate Count ... + result = start + count < bufferSize; + if (!result) + { + return result; + } + + // + T iTem = buffer[start]; + for (int i = start; i < start + count; i++) + { + // + if (iTem != buffer[i]) + { + result = false; + break; + } + + // + if (!result) + { + result = true; + } + } + + // + return result; +} + +// +// Check first Cross Over second at index ... +bool IsCrossedOver( + const double &first[], // the buffer which check crossing over second buffer + const double &second[], // first buffer checks based on this buffer + const int index = 0 // check crosses in specific index +) +{ + // + bool result = false; + + // + // Validate Args ... + if (ArraySize(first) < index + 1 || ArraySize(second) < index + 1) + { + return result; + } + + // + result = first[index] > second[index] && + !(first[index + 1] > second[index + 1]); + + // + return result; +} + +// +// Check first is Over second at index ... +bool IsOver( + const double &first[], // the buffer which check over second buffer + const double &second[], // first buffer checks based on this buffer + const int index = 0 // check crosses in specific index +) +{ + // + bool result = false; + + // + // Validate Args ... + if (ArraySize(first) < index + 1 || ArraySize(second) < index + 1) + { + return result; + } + + // + result = first[index] > second[index] && + first[index + 1] > second[index + 1]; + + // + return result; +} + +// +// Check first Cross Under second at index ... +bool IsCrossedUnder( + const double &first[], // the buffer which check crossing under second buffer + const double &second[], // first buffer checks based on this buffer + const int index = 0 // check crosses in specific index +) +{ + // + bool result = false; + + // + // Validate Args ... + if (ArraySize(first) < index + 1 || ArraySize(second) < index + 1) + { + return result; + } + + // + result = first[index] < second[index] && + !(first[index + 1] < second[index + 1]); + + // + return result; +} + +// +// Check first is Under second at index ... +bool IsUnder( + const double &first[], // the buffer which check under second buffer + const double &second[], // first buffer checks based on this buffer + const int index = 0 // check crosses in specific index +) +{ + // + bool result = false; + + // + // Validate Args ... + if (ArraySize(first) < index + 1 || ArraySize(second) < index + 1) + { + return result; + } + + // + result = first[index] < second[index] && + first[index + 1] < second[index + 1]; + + // + return result; +} + +// +// Check if a Value Increasing in Loopback ... +bool IsIncreasing( + const int from, // Last Time Index + const int to, // Fisrs Tima Index + const double &buffer[] // the Buffer which required to search +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + from <= to || + ArraySize(buffer) < from + 1) + { + return result; + } + + // + // Loop through Items ... + double toValue = buffer[to]; + double fromValue = buffer[from]; + result = toValue > fromValue; + for (int i = to + 1; i <= from - 1; i++) + { + // + double iValue = buffer[i]; + bool isPassed = toValue >= iValue; + + // + bool isIIncreasing = IsIncreasing( + from, + i, + buffer); + + // + // Check Result ... + result = result && isPassed && isIIncreasing; + if (!result) + { + break; + } + } + + // + return result; +} + +// +// Check if a Value Decreasing in Loopback ... +bool IsDecreasing( + const int from, // Last Time Index + const int to, // Fisr Tima Index + const double &buffer[] // the Buffer which required to search +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + from <= to || + ArraySize(buffer) < from + 1) + { + return result; + } + + // + // Loop through Items ... + double toValue = buffer[to]; + double fromValue = buffer[from]; + result = toValue < fromValue; + for (int i = to + 1; i <= from - 1; i++) + { + // + double iValue = buffer[i]; + bool isPassed = toValue <= iValue; + + // + bool isIDecreasing = IsDecreasing( + from, + i, + buffer); + + // + // Check Result ... + result = result && isPassed && isIDecreasing; + if (!result) + { + break; + } + } + + // + return result; +} + +// +bool IsTrendingUp( + const double &buffer1[], // First Buffer + const double &buffer2[] // Seccend Buffer +) +{ + // + bool result = false; + + // + int buffer1Count = ArraySize(buffer1); + int buffer2Count = ArraySize(buffer2); + if (buffer1Count <= 0 || buffer2Count <= 0) + { + return result; + } + + // + int count = MathMin(buffer1Count, buffer2Count); + if (count <= 1) + { + return result; + } + + // + int upCounts = 0; + int downCounts = 0; + double value = MathAbs(buffer1[0] - buffer2[0]); + for (int i = 1; i < count; i++) + { + // + double iValue = MathAbs(buffer1[i] - buffer2[i]); + + // + if (value > iValue) + { + upCounts++; + } + + // + if (value < iValue) + { + downCounts++; + } + } + + // + result = upCounts > 1 && upCounts > downCounts; + + // + return result; +} + +// +bool IsTrendingDown( + const double &buffer1[], // First Buffer + const double &buffer2[] // Seccend Buffer +) +{ + // + bool result = false; + + // + int buffer1Count = ArraySize(buffer1); + int buffer2Count = ArraySize(buffer2); + if (buffer1Count <= 0 || buffer2Count <= 0) + { + return result; + } + + // + int count = MathMin(buffer1Count, buffer2Count); + if (count <= 1) + { + return result; + } + + // + int upCounts = 0; + int downCounts = 0; + double value = MathAbs(buffer1[0] - buffer2[0]); + for (int i = 1; i < count; i++) + { + // + double iValue = MathAbs(buffer1[i] - buffer2[i]); + + // + if (value > iValue) + { + upCounts++; + } + + // + if (value < iValue) + { + downCounts++; + } + } + + // + result = downCounts > 1 && downCounts > upCounts; + + // + return result; +} + +// +// Calculate Slope of Specified Buffer at Specified Index ... +double GetSlope( + const double &buffer[], // Buffer + int from, // In Past Index ... + int to // In Past Index ... +) +{ + // + double result = 0; + + // + if (from > ArraySize(buffer) || to > ArraySize(buffer)) + { + return result; + } + + // + double toValue = buffer[to]; + double fromValue = buffer[from]; + double deltaValue = toValue - fromValue; + double deltaTime = from - to; + + // + result = deltaValue / deltaTime; + + // + return result; +} + +// +// Calculate Fib Level ... +double GetFibonacciLevel( + double upPrice, // Upper Bound + double downPrice, // Downer Bound + double level, // Level Multiplier Factor + int direction // From Down to Up < 0, other wise Vice Versa + // +) +{ + // + double ling = upPrice - downPrice; + double pLevel = (ling / 100) * (level * 100); + + // + double result = direction > 0 ? upPrice - pLevel : downPrice + pLevel; + + // + return result; +} + +// +// Method 1 +// Normalize between 1 and 0 ... +template +double GetNormalizedValueMethod1( + T &buffer[], // Array which required to Normalize + int mLength, // Length of Normalization + int mStart = 0, // start index + int digits = 5 // Normalization Digits +) +{ + // + double result = 0; + + // + if (digits <= 5) + { + digits = 5; + } + + // + int bufferSize = ArraySize(buffer); + if (!IsValidSize(bufferSize)) + { + return result; + } + + // + // Normalize Count ... + NormalizeCount( + mStart, + mLength, + buffer // + ); + + // + T max = 0; + T min = 0; + + // + if (bufferSize != mLength) + { + // + T tmp[]; + Copy( + mStart, + mLength, + buffer, + tmp // + ); + + // + max = GetMax(tmp); + min = GetMin(tmp); + } + + // + if (bufferSize == mLength) + { + // + max = GetMax(buffer); + min = GetMin(buffer); + } + + // + T iValue = buffer[mStart]; + + // + double minMaxDiff = (max - min); + if (minMaxDiff <= 0) + { + return result; + } + + // + result = (iValue - min) / minMaxDiff; + + // + result = NormalizeDouble(result, digits); + + // + return result; +} + +// +// Method 2 +// Normalize Between Specified Upper and Lower ... +template +double GetNormalizedValueMethod2( + T &buffer[], // Array which required to Normalize + int mLength, // Length of Normalization + int mUpper, // Specified Upper Value + int mLower, // Specified Lower Value + int mStart = 0, // start index + int digits = 5 // Normalization Digits +) +{ + // + double result = 0; + + // + if (digits <= 5) + { + digits = 5; + } + + // + int bufferSize = ArraySize(buffer); + if (!IsValidSize(bufferSize)) + { + return result; + } + + // + // Normalize Count ... + NormalizeCount( + mStart, + mLength, + buffer // + ); + + // + T max = 0; + T min = 0; + + // + if (bufferSize != mLength) + { + // + T tmp[]; + Copy( + mStart, + mLength, + buffer, + tmp // + ); + + // + max = GetMax(tmp); + min = GetMin(tmp); + } + + // + if (bufferSize == mLength) + { + // + max = GetMax(buffer); + min = GetMin(buffer); + } + + // + T iValue = buffer[mStart]; + + // + double minMaxDiff = (max - min); + double boundaryDiff = (mUpper - mLower); + if (minMaxDiff <= 0 || boundaryDiff <= 0) + { + return result; + } + + // + result = boundaryDiff / (minMaxDiff * (iValue - max) + max); + + // + result = NormalizeDouble(result, digits); + + // + return result; +} + +// +// Templates ... + +// +// Retrieve Specific Object Types Name ... +template +string GetTypeName(const T &t) +{ + return typename(T); +} + +// +template +string GetToken(T &item) +{ + // + string mType = GetTypeName(item); + + // + string result = mType; + + // + string parts[]; + int partsCount = SplitContent( + parts, + result, + " " + // + ); + if (partsCount <= 0) + { + // + result = mType; + return result; + } + + // + bool hasLastPart = GetLastItem( + result, + parts + // + ); + if (!hasLastPart) + { + // + result = mType; + return result; + } + + // + return result; +} + +// +// Same as Get Token for Use in Classes ... +template +string GetSpecificToken(T &item) +{ + // + string mType = GetTypeName(item); + + // + string result = mType; + + // + string parts[]; + int partsCount = SplitContent( + parts, + result, + " " + // + ); + if (partsCount <= 0) + { + // + result = mType; + return result; + } + + // + bool hasLastPart = GetLastItem( + result, + parts + // + ); + if (!hasLastPart) + { + // + result = mType; + return result; + } + + // + return result; +} + +// +// Generate Unique Tags ... +template +string GenerateTag(T &model) +{ + // + string result = ""; + + // + string tag = model.ToString(); + if (StringLen(tag) == 0) + { + return result; + } + + // + static XSCMD5 md5; + + // + result = md5.Hash(tag); + + // + return result; +} + +// +// Hash Specified Content ... +template +string ToMD5(T content) +{ + // + string result = ""; + + // + string strContent = ToString(content); + if (StringLen(strContent) == 0) + { + return result; + } + + // + static XSCMD5 md5; + + // + result = md5.Hash(strContent); + + // + return result; +} + +// +// Check a Value Not Empty ... +template +bool NotEmpty(T value) +{ + return value != EMPTY_VALUE; +} + +// +// Add Specified Item to Array ... +template +int Add( + T item, // item want to add + T &buffer[] // Destination buffer +) +{ + // + int result = 0; + + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; + + // + result = ArraySize(buffer); + + // + return result; +} +template +int AddSpecific( + T item, // item want to add + T &buffer[] // Destination buffer +) +{ + // + return Add( + item, + buffer // + ); +} +template +int AddRef( + T &item, // item want to add + T &buffer[] // Destination buffer +) +{ + // + int result = 0; + + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; + + // + result = ArraySize(buffer); + + // + return result; +} + +// +// Remove Specified Item from an Array ... +template +bool Remove( + T item, + T &buffer[]) +{ + // + bool result = false; + + // + int itemIndex = FindIndex( + item, + buffer); + if (itemIndex < 0) + { + return result; + } + + // + result = ArrayRemove( + buffer, + itemIndex, + 1); + + // + return result; +} + +// +// Clean Specified Array ... +template +void Clean(T &buffer[]) +{ + // + ArrayFree(buffer); + ArrayResize(buffer, 0); +} + +// +// Copy Whole Content of Source to Dest array ... +template +void Copy( + T &source[], // Source Buffer ... + T &dest[], // Dest Buffer ... + bool cleanDest = true // Force Clen Dest Buffer ... +) +{ + // + if (cleanDest) + { + Clean(dest); + } + + // + int sourceCount = ArraySize(source); + if (sourceCount <= 0) + { + return; + } + + // + for (int i = 0; i < sourceCount; i++) + { + // + T iSource = source[i]; + + // + AddRef( + iSource, + dest); + } +} + +// +// Copy Items from a Buffer ... +template +int Copy( + int start, // Start + int count, // Number of Items for read + T &source[], // Source Buffer + T &dest[], // Dest Buffer + bool forceClean = true // Force To Clean buffer +) +{ + // + int result = 0; + + // + if (forceClean) + { + Clean(dest); + } + + // + if (start < 0) + { + start = 0; + } + + // + if (start >= ArraySize(source)) + { + start = ArraySize(source) - 1; + } + + // + if (count == 0) + { + count = ArraySize(source) - 1 - start; + } + + // + if (start + count > ArraySize(source)) + { + return result; + } + + // + int beforeSize = ArraySize(dest); + + // + bool asSeriesDest = ArrayGetAsSeries(dest); + bool asSeriesSource = ArrayGetAsSeries(source); + + // + ArraySetAsSeries(dest, true); + ArraySetAsSeries(source, true); + + // + ArrayCopy( + dest, + source, + 0, + start, + count + // + ); + + // + int afterSize = ArraySize(dest); + + // + result = afterSize - beforeSize; + + // + ArraySetAsSeries(dest, asSeriesDest); + ArraySetAsSeries(source, asSeriesSource); + + // + return result; +} + +// +// Copy Items from a Buffer ... +template +int CopyRef( + int start, // Start + int count, // Number of Items for read + T &source[], // Source Buffer + T &dest[], // Dest Buffer + bool forceClean = true // Force To Clean buffer +) +{ + // + int result = 0; + + // + if (forceClean) + { + Clean(dest); + } + + // + if (start < 0) + { + start = 0; + } + + // + if (start >= ArraySize(source)) + { + start = ArraySize(source) - 1; + } + + // + int beforeSize = ArraySize(dest); + + // + bool asSeriesDest = ArrayGetAsSeries(dest); + bool asSeriesSource = ArrayGetAsSeries(source); + + // + ArraySetAsSeries(dest, true); + ArraySetAsSeries(source, true); + + // + for (int i = start; i < start + count; i++) + { + // + AddRef( + source[i], + dest + // + ); + } + + // + int afterSize = ArraySize(dest); + + // + result = afterSize - beforeSize; + + // + ArraySetAsSeries(dest, asSeriesDest); + ArraySetAsSeries(source, asSeriesSource); + + // + return result; +} + +// +// Retrive Last Item of Specified Buffer ... +template +bool GetLastItem( + T &item, // Holds Result + T &buffer[] // Specified Buffer +) +{ + // + bool result = false; + + // + int bufferSize = ArraySize(buffer); + if (bufferSize <= 0) + { + return result; + } + + // + item = buffer[bufferSize - 1]; + + // + result = true; + return result; +} + +// +// Search Array For Specific Item ... +template +int FindIndex( + T item, // What is Search ... + T &buffer[] // Search in ... +) +{ + // + int result = -1; + + // + int count = ArraySize(buffer); + if (count <= 0) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + T iT = buffer[i]; + + // + if (iT == item) + { + // + result = i; + break; + } + } + + // + return result; +} + +// +// Check an Array Contains Specified Value ... +template +bool Contains( + T item, // What is Search ... + T &buffer[] // Search in ... +) +{ + // + bool result = false; + + // + int idx = FindIndex( + item, + buffer); + result = idx > -1; + + // + return result; +} + +// +// Calculate a Buffer's Average ... +template +double GetAverage( + T &buffer[], // the Buffer which required to search + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + // + double result = 0; + + // + T tmp[]; + int tmpCount = Copy( + start, + count, + buffer, + tmp + // + ); + if (tmpCount <= 0) + { + return result; + } + + // + // Calculate Summary ... + for (int i = 0; i < tmpCount; i++) + { + result += buffer[i]; + } + + // + // Calculate Average ... + result = result / tmpCount; + + // + return result; +} + +// +// Get Max of Specific Loopback of a Buffer ... +template +double GetMax( + T &buffer[], // the Buffer which required to search + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + // + double result = 0; + + // + if (count <= 0) + { + count = ArraySize(buffer); + } + + // + T tmp[]; + int tmpCount = Copy( + start, + count, + buffer, + tmp + // + ); + if (tmpCount <= 0) + { + return result; + } + + // + // Loop Through LoopBack ... + for (int i = 0; i < tmpCount; i++) + { + // + double iValue = tmp[i]; + + // + result = + // + result == 0 || result < iValue + // + ? iValue + // + : result + // + ; + } + + // + return result; +} + +// +// Get Min of Specific Loopback of a Buffer ... +template +double GetMin( + T &buffer[], // the Buffer which required to search + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + // + double result = 0; + + // + if (count <= 0) + { + count = ArraySize(buffer); + } + + // + T tmp[]; + int tmpCount = Copy( + start, + count, + buffer, + tmp + // + ); + if (tmpCount <= 0) + { + return result; + } + + // + // Loop Through LoopBack ... + for (int i = 0; i < tmpCount; i++) + { + // + double iValue = tmp[i]; + + // + result = + // + result == 0 || result > iValue + // + ? iValue + // + : result + // + ; + } + + // + return result; +} + +// +// Find a Value less than Specified ... +template +T FindLesserThan( + T value, // Specified Value ... + const T &source[], // Source ... + bool isDescend = false // Find Biggest Lesser Value ... +) +{ + // + T result = -1; + + // + int itemsCount = ArraySize(source); + if (itemsCount <= 0) + { + return result; + } + + // + // Make a Copy of source ... + T tmp[]; + + // + ArrayResize( + tmp, + ArraySize(source)); + + // + ArrayCopy( + tmp, + source); + + // + // Sort Temp Buffer ... + ArraySort(tmp); + if (isDescend) + { + ArrayReverse(tmp); + } + + // + int tmpCount = ArraySize(tmp); + for (int i = 0; i < tmpCount; i++) + { + // + T iValue = tmp[i]; + + // + if (iValue < value) + { + // + result = iValue; + break; + } + } + + // + return result; +} + +// +// Find a Value less than Specified ... +template +T FindBiggerThan( + T value, // Specified Value ... + const T &source[], // Source ... + bool isDescend = false // Find Smallest Bigger Value ... +) +{ + // + T result = -1; + + // + int itemsCount = ArraySize(source); + if (itemsCount <= 0) + { + return result; + } + + // + // Make a Copy of source ... + T tmp[]; + + // + ArrayResize( + tmp, + ArraySize(source)); + + // + ArrayCopy( + tmp, + source); + + // + // Sort Temp Buffer ... + ArraySort(tmp); + if (!isDescend) + { + ArrayReverse(tmp); + } + + // + int tmpCount = ArraySize(tmp); + for (int i = 0; i < tmpCount; i++) + { + // + T iValue = tmp[i]; + + // + if (iValue > value) + { + // + result = iValue; + break; + } + } + + // + return result; +} + +// +// Find Same Values in Array ... +template +void FindSames( + T &result[], // Holds Result ... + T &source[], // Source ... + int verifications = 3 // Number of Consequence Repeat ... +) +{ + // + Clean(result); + + // + // TenkanSen Flats ... + int sourceCount = ArraySize(source); + if (sourceCount > verifications) + { + // + T mLast = 0; + int mVerified = 0; + for (int i = 0; i < sourceCount; i++) + { + // + T iVal = source[i]; + if (mLast == 0) + { + mLast = iVal; + } + else if (mLast == iVal) + { + mVerified++; + } + else + { + mLast = iVal; + mVerified = 0; + } + + // + if (iVal == mLast && mVerified >= verifications) + { + // + Add( + iVal, + result); + + // + mLast = 0; + mVerified = 0; + } + } + } +} + +// +// Add an Item to a Buffer if not Exists ... +void AddIfNotExists( + double value, + double &values[], + double smoothingPoint = 3) +{ + // + double smoothingValue = smoothingPoint * GetPoints(_Symbol); + + // + int valuesCount = ArraySize(values); + if (valuesCount <= 0) + { + // + Add(value, + values); + } + else + { + // + bool isExists = false; + for (int i = 0; i < valuesCount; i++) + { + // + double iVal = values[i]; + + // + double diff = MathAbs(iVal - value); + + // + if (iVal == value || diff < smoothingValue) + { + // + isExists = true; + break; + } + } + + // + if (!isExists) + { + // + Add(value, + values); + } + } +} + +// +// Add a Buffers Child to another Buffer +// if it's not Contains them ... +void AddsIfNotExists( + double &source[], + double &dest[], + double smoothingPoint = 3) +{ + // + double smoothingValue = smoothingPoint * GetPoints(_Symbol); + + // + int sourceCount = ArraySize(source); + if (sourceCount <= 0) + { + return; + } + + // + for (int i = 0; i < sourceCount; i++) + { + // + double iSource = source[i]; + + // + AddIfNotExists( + iSource, + dest, + smoothingPoint); + } +} + +// +// Bar XOHCL ... + +// +// Extract Specific Range of Bars ... +// using Start Bar Index ... +int GetBars( + XOHCL &result[], // Hold Result + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Time Frame + int from = 0, // Start Bar Index + int count = 1, // Number of Bars + bool forceClean = true // Clean Result Array +) +{ + // + int mResult = 0; + + // + if (from < 0) + { + from = 0; + } + + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + int total = Bars( + mSymbol, + mPeriod); + if (from > total - 2) + { + from = total - 2; + } + + // + if (count < 0) + { + count = 1; + } + + // + int start = from; + int end = start + count; + if (end > total - 1) + { + end = total - 1; + } + + // + if (forceClean) + { + Clean(result); + } + + // + int beforeSize = ArraySize(result); + + // + for (int i = start; i < end; i++) + { + // + XOHCL iBar; + bool isValid = iBar.Init( + mSymbol, + mPeriod, + i + // + ); + + // + if (isValid) + { + // + AddRef( + iBar, + result + // + ); + } + } + + // + int afterSize = ArraySize(result); + + // + mResult = afterSize - beforeSize; + + // + return mResult; +} + +// +// Extract Specific Range of Bars ... +// using Start Bar Time ... +int GetBars( + XOHCL &result[], // Hold Result + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Time Frame + datetime from = NULL, // Start Bar Time + int count = 1, // Number of Bars + bool forceClean = true // Clean Result Array +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + from = NormalizeTime(from); + + // + int barIndex = iBarShift( + mSymbol, + mPeriod, + from, + false + // + ); + + // + return GetBars( + result, + mSymbol, + mPeriod, + barIndex, + count, + forceClean + // + ); +} + +// +// String ... + +// +// Search a Content Contains Specific String or not ... +bool Contains( + string mQuery, // Search String + string mContent, // Search Content + bool ignoreCase = true // Ignore Case +) +{ + // + bool result = false; + + // + // Validate Query ... + result = IsValid(mQuery); + if (!result) + { + return result; + } + + // + // Validate Content ... + result = IsValid(mContent); + if (!result) + { + return result; + } + + // + // Normalize Inputs ... + string query = mQuery; + string content = mContent; + if (ignoreCase) + { + // + StringToLower(query); + StringToLower(content); + } + + // + int queryIdx = StringFind( + content, + query); + + // + result = queryIdx >= 0; + + // + return result; +} + +// +bool Contains( + string &mQueries[], // Search Strings + string mContent, // Search Content + bool ignoreCase = true // Ignore Case +) +{ + // + bool result = false; + + // + // Validate Queries ... + int queriesCount = ArraySize(mQueries); + result = queriesCount > 0; + if (!result) + { + return result; + } + + // + // Validate Content ... + result = IsValid(mContent); + if (!result) + { + return result; + } + + // + int containsCount = 0; + for (int i = 0; i < queriesCount; i++) + { + // + bool isContains = Contains( + mQueries[i], + mContent, + ignoreCase); + + // + if (!isContains) + { + // + result = false; + break; + } + + // + containsCount++; + } + + // + result = containsCount == queriesCount; + + // + return result; +} + +// +// Convert From String ... +template +T FromString(string value) +{ + // + T result = NULL; + + // + if (!IsValid(value)) + { + return result; + } + + // + result = (T)value; + + // + return result; +} + +// +// Converts an item to String ... +template +string ToString(T value) +{ + return (string)value; +} + +// +// Used In Report or Summary Generators ... +string ToString( + string prefix, // Title + bool value, // Value + bool ignoreFalseConditions = true, // Ignore False Conditions + string lineSeparator = "\n", // Line Separator + string prefixSeparator = ":" // Title Separator +) +{ + // + string result = NULL; + + // + result = (value || !ignoreFalseConditions) + ? prefix + + prefixSeparator + " " + + ToString(value) + + lineSeparator + : ""; + + // + return result; +} + +// +string SetLabel( + string mLabel, // Provided Label ... + string value, // Source Value ... + string separator = "\n", // Line Separator + bool addTopEmptyLine = true // Add Empty Line On top +) +{ + // + string result = value; + + // + if (StringLen(mLabel) <= 0) + { + return result; + } + + // + result = (StringLen(value) > 0) + ? (addTopEmptyLine ? separator : "") + + mLabel + + separator + + "-----------------------------" + + separator + + value + : value; + + // + return result; +} + +// +// Converts a Buffer to String Representation ... +template +string ToString( + const T &buffer[], // Specified Buffer + string separator = ",", // Specified Separator + bool addIndex = false, // Specified Add Items Indexes or Not + string indexLabel = "i:", // Specified Index Label + string indexSeparator = ">" // Specified Index Separator +) +{ + // + string result = ""; + + // + int bufferSize = ArraySize(buffer); + if (bufferSize <= 0) + { + return result; + } + + // + for (int i = 0; i < bufferSize; i++) + { + // + if (addIndex) + { + // + if (StringLen(indexLabel) > 0) + { + result += indexLabel + " "; + } + + // + result += (string)i + " "; + + // + if (StringLen(indexSeparator) > 0) + { + result += indexSeparator + " "; + } + } + + // + string iItemString = (string)buffer[i]; + + // + result += iItemString; + + // + if (i < bufferSize - 1) + { + result += separator; + } + } + + // + return result; +} + +// +// Converts String to boolean ... +bool ToBoolean(string value) +{ + // + bool result = false; + + // + if (StringLen(value) <= 0) + { + return result; + } + + // + StringToLower(value); + result = value == "true"; + + // + return result; +} + +// +// Split an String Representation of an Array ... +int SplitContent( + string &result[], // Hold Result ... + string content, // Source ... + string separator = ",", // Separator ... + bool forceCleanResult = true // Clean Result ... +) +{ + // + int mResult = 0; + + // + if (forceCleanResult) + { + Clean(result); + } + + // + int before = ArraySize(result); + + // + if (separator == NULL || StringLen(separator) == 0) + { + separator = ","; + } + + // + if (StringLen(content) == 0) + { + return mResult; + } + + // + StringSplit( + content, + StringGetCharacter( + separator, + 0), + result); + + // + int after = ArraySize(result); + + // + mResult = after - before; + + // + return mResult; +} + +// +// Extract Data from String ... +string ExtractString( + const string source, // Source String used for Extracting + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + string result = ""; + + // + // Validate String ... + if ( + StringLen(source) == 0 || + StringLen(endString) == 0 || + StringLen(startString) == 0) + { + return result; + } + + // + // Find Start String Position ... + int sPos = StringFind( + source, + startString); + if (sPos < 0) + { + return result; + } + + // + // Find End String Position after Start String ... + int searchEndFromPos = sPos + StringLen(startString); + int ePos = StringFind( + source, + endString, + searchEndFromPos); + if (ePos < 0) + { + return result; + } + + // + // Extract Data from Source ... + int dLength = ePos - searchEndFromPos; + result = StringSubstr( + source, + searchEndFromPos, + dLength); + + // + return result; +} + +// +// Extract an Array of Contents ... +int ExtractStrings( + string &result[], // Hold Result + const string source, // Source String used for Extracting + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + int mResult = 0; + + // + Clean(result); + + // + // Validate Args ... + int sourceLength = StringLen(source); + int startLength = StringLen(startString); + int endLength = StringLen(endString); + + // + int minRequiredLength = startLength + endLength; + + // + if ( + endLength <= 0 || + startLength <= 0 || + sourceLength <= 0 || + sourceLength < minRequiredLength) + { + return mResult; + } + + // + // Make a Copy of Source for Manipulating ... + string workStr = source; + + // + // Define a Loop ... + while (StringLen(workStr) > minRequiredLength) + { + // + // Find Item ... + string item = ExtractString( + workStr, + startString, + endString); + + // + // Breakout when couldn't find anymore item ... + int itemLength = StringLen(item); + if (itemLength <= 0) + { + break; + } + + // + // Prepare Item Source String for Replacing in Work String ... + string itemSource = startString + item + endString; + + // + // Add Item to Result Array ... + Add( + item, + result); + + // + // Replace Item Soure in Work String ... + StringReplace( + workStr, + itemSource, + ""); + } + + // + // Calculate Size of Array ... + mResult = ArraySize(result); + + // + return mResult; +} + +// +string ExtractSurrounded( + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + return ExtractString( + surrounded, + mToken + startString, + endString + // + ); +} + +// +int ParseIntSurrounded( + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + int result = NULL; + + // + string strContent = ExtractSurrounded( + surrounded, + mToken, + startString, + endString + // + ); + if (!IsValid(strContent)) + { + return result; + } + + // + result = (int)strContent; + + // + return result; +} +long ParseLongSurrounded( + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + long result = NULL; + + // + string strContent = ExtractSurrounded( + surrounded, + mToken, + startString, + endString + // + ); + if (!IsValid(strContent)) + { + return result; + } + + // + result = (long)strContent; + + // + return result; +} +string ParseStringSurrounded( + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + string result = NULL; + + // + string strContent = ExtractSurrounded( + surrounded, + mToken, + startString, + endString + // + ); + if (!IsValid(strContent)) + { + return result; + } + + // + result = (string)strContent; + + // + return result; +} +double ParseDoubleSurrounded( + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + double result = NULL; + + // + string strContent = ExtractSurrounded( + surrounded, + mToken, + startString, + endString + // + ); + if (!IsValid(strContent)) + { + return result; + } + + // + result = (double)strContent; + + // + return result; +} +datetime ParseTimeSurrounded( + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + datetime result = NULL; + + // + string strContent = ExtractSurrounded( + surrounded, + mToken, + startString, + endString + // + ); + if (!IsValid(strContent)) + { + return result; + } + + // + result = (datetime)strContent; + + // + return result; +} + +// +int ParseIntArraySurrounded( + int &result[], // Holds Result + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + string separator = ",", // Separator ... + const string startString = "(", // Expression Start String must be Unique + const string endString = ")", // Where to End Extraction, usually a Sign + bool forceClean = true // Clean Result ... +) +{ + // + int count = 0; + + // + if (forceClean) + { + Clean(result); + } + + // + int before = ArraySize(result); + + // + string contentStr = ParseStringSurrounded(surrounded, mToken); + if (!IsValid(contentStr)) + { + return count; + } + + // + string tmps[]; + int tmpsCount = SplitContent( + tmps, + contentStr + // + ); + if (tmpsCount <= 0) + { + return count; + } + + // + for (int i = 0; i < tmpsCount; i++) + { + // + string iTMP = tmps[i]; + if (!IsValid(iTMP)) + { + continue; + } + + // + int iValue = (int)iTMP; + + // + Add( + iValue, + result + // + ); + } + + // + int after = ArraySize(result); + + // + count = after - before; + + // + return count; +} +int ParseLongArraySurrounded( + long &result[], // Holds Result + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + string separator = ",", // Separator ... + const string startString = "(", // Expression Start String must be Unique + const string endString = ")", // Where to End Extraction, usually a Sign + bool forceClean = true // Clean Result ... +) +{ + // + int count = 0; + + // + if (forceClean) + { + Clean(result); + } + + // + int before = ArraySize(result); + + // + string contentStr = ParseStringSurrounded(surrounded, mToken); + if (!IsValid(contentStr)) + { + return count; + } + + // + string tmps[]; + int tmpsCount = SplitContent( + tmps, + contentStr + // + ); + if (tmpsCount <= 0) + { + return count; + } + + // + for (int i = 0; i < tmpsCount; i++) + { + // + string iTMP = tmps[i]; + if (!IsValid(iTMP)) + { + continue; + } + + // + long iValue = (long)iTMP; + + // + Add( + iValue, + result + // + ); + } + + // + int after = ArraySize(result); + + // + count = after - before; + + // + return count; +} +int ParseDoubleArraySurrounded( + double &result[], // Holds Result + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + string separator = ",", // Separator ... + const string startString = "(", // Expression Start String must be Unique + const string endString = ")", // Where to End Extraction, usually a Sign + bool forceClean = true // Clean Result ... +) +{ + // + int count = 0; + + // + if (forceClean) + { + Clean(result); + } + + // + int before = ArraySize(result); + + // + string contentStr = ParseStringSurrounded(surrounded, mToken); + if (!IsValid(contentStr)) + { + return count; + } + + // + string tmps[]; + int tmpsCount = SplitContent( + tmps, + contentStr + // + ); + if (tmpsCount <= 0) + { + return count; + } + + // + for (int i = 0; i < tmpsCount; i++) + { + // + string iTMP = tmps[i]; + if (!IsValid(iTMP)) + { + continue; + } + + // + double iValue = (double)iTMP; + + // + Add( + iValue, + result + // + ); + } + + // + int after = ArraySize(result); + + // + count = after - before; + + // + return count; +} +int ParseTimeArraySurrounded( + datetime &result[], // Holds Result + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + string separator = ",", // Separator ... + const string startString = "(", // Expression Start String must be Unique + const string endString = ")", // Where to End Extraction, usually a Sign + bool forceClean = true // Clean Result ... +) +{ + // + int count = 0; + + // + if (forceClean) + { + Clean(result); + } + + // + int before = ArraySize(result); + + // + string contentStr = ParseStringSurrounded(surrounded, mToken); + if (!IsValid(contentStr)) + { + return count; + } + + // + string tmps[]; + int tmpsCount = SplitContent( + tmps, + contentStr + // + ); + if (tmpsCount <= 0) + { + return count; + } + + // + for (int i = 0; i < tmpsCount; i++) + { + // + string iTMP = tmps[i]; + if (!IsValid(iTMP)) + { + continue; + } + + // + datetime iValue = (datetime)iTMP; + + // + Add( + iValue, + result + // + ); + } + + // + int after = ArraySize(result); + + // + count = after - before; + + // + return count; +} + +// +// Surround an String by Specific Token ... +template +string Surround( + string mToken, // an String which used to Tokenize + T &value, // a Value for Tokenize it + string startString = "(", // Token Start Content + string endString = ")" // Token End Content +) +{ + // + string result = NULL; + + // + string strValue = ToString(value); + if (!IsValid(strValue)) + { + return result; + } + + // + result = + // + (IsValid(mToken) + ? mToken + : "") + + // + startString + + strValue + + endString + // + ; + + // + return result; +} + +// +template +string SurroundArray( + string mToken, + T &value[], + string startString = "(", // Token Start Content + string endString = ")" // Token End Content +) +{ + // + string result = NULL; + + // + string valueStr = ToString(value); + if (!IsValid(valueStr)) + { + return result; + } + + // + result = Surround( + mToken, + valueStr, + startString, + endString + // + ); + + // + return result; +} + +// +// Periods / Cycles ... + +// +// Converts an String to TimeFrame ... +ENUM_TIMEFRAMES ToPeriod(string value) +{ + // + if (StringLen(value) == 0) + { + return _Period; + } + + // + StringTrimLeft(value); + StringTrimRight(value); + + // + ENUM_TIMEFRAMES result = _Period; + + // + if (value == "M1") + { + result = PERIOD_M1; + } + else if (value == "M2") + { + result = PERIOD_M2; + } + else if (value == "M3") + { + result = PERIOD_M3; + } + else if (value == "M4") + { + result = PERIOD_M4; + } + else if (value == "M5") + { + result = PERIOD_M5; + } + else if (value == "M6") + { + result = PERIOD_M6; + } + else if (value == "M10") + { + result = PERIOD_M10; + } + else if (value == "M12") + { + result = PERIOD_M12; + } + else if (value == "M15") + { + result = PERIOD_M15; + } + else if (value == "M20") + { + result = PERIOD_M20; + } + else if (value == "M30") + { + result = PERIOD_M30; + } + else if (value == "H1") + { + result = PERIOD_H1; + } + else if (value == "H2") + { + result = PERIOD_H2; + } + else if (value == "H3") + { + result = PERIOD_H3; + } + else if (value == "H4") + { + result = PERIOD_H4; + } + else if (value == "H6") + { + result = PERIOD_H6; + } + else if (value == "H8") + { + result = PERIOD_H8; + } + else if (value == "H12") + { + result = PERIOD_H12; + } + else if (value == "D1") + { + result = PERIOD_D1; + } + else if (value == "W1") + { + result = PERIOD_W1; + } + else if (value == "MN1") + { + result = PERIOD_MN1; + } + + // + return result; +} + +// +// Converts Period to String ... +string ToString(ENUM_TIMEFRAMES mPeriod) +{ + // + string result = ""; + + // + string mPStr = EnumToString(mPeriod); + + string mPStrParts[]; + int partsCount = StringSplit( + mPStr, + StringGetCharacter("_", 0), + mPStrParts); + if (partsCount <= 0) + { + return result; + } + + // + result = mPStrParts[1]; + + // + return result; +} + +// +// Retrieve All Available Period as an Array ...s +int GetAllAvailablePeriods( + ENUM_TIMEFRAMES &result[] // Holds Result ... +) +{ + // + Clean(result); + + // + Add( + PERIOD_M1, + result + // + ); + + // + Add( + PERIOD_M2, + result + // + ); + + // + Add( + PERIOD_M3, + result + // + ); + + // + Add( + PERIOD_M4, + result + // + ); + + // + Add( + PERIOD_M5, + result + // + ); + + // + Add( + PERIOD_M6, + result + // + ); + + // + Add( + PERIOD_M10, + result + // + ); + + // + Add( + PERIOD_M12, + result + // + ); + + // + Add( + PERIOD_M15, + result + // + ); + + // + Add( + PERIOD_M20, + result + // + ); + + // + Add( + PERIOD_M30, + result + // + ); + + // + Add( + PERIOD_H1, + result + // + ); + + // + Add( + PERIOD_H2, + result + // + ); + + // + Add( + PERIOD_H3, + result + // + ); + + // + Add( + PERIOD_H4, + result + // + ); + + // + Add( + PERIOD_H6, + result + // + ); + + // + Add( + PERIOD_H8, + result + // + ); + + // + Add( + PERIOD_H12, + result + // + ); + + // + Add( + PERIOD_D1, + result + // + ); + + // + Add( + PERIOD_W1, + result + // + ); + + // + Add( + PERIOD_MN1, + result + // + ); + + // + int mResult = ArraySize(result); + + // + return mResult; +} + +// +// Get Specific Time Frame Start Candle Time ... +datetime GetPeriodStartTime( + string mSymbol = NULL, // Specified Symbol ... + ENUM_TIMEFRAMES mPeriod = NULL, // Specified Period ... + datetime mTime = NULL // Specified Bar Time of Host Period ... +) +{ + // + // Normalize Arg ... + mTime = NormalizeTime(mTime); + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + int barIndex = iBarShift( + mSymbol, + mPeriod, + mTime, + false + // + ); + + // + datetime result = GetBarTime( + mSymbol, + mPeriod, + barIndex + // + ); + + // + return result; +} + +// +// Converts an String to it's related Market Cycle ... +ENUM_X_MARKET_CYCLES ToCycle(string value) +{ + // + ENUM_X_MARKET_CYCLES result = X_MARKET_CYCLE_UNKNOWN; + + // + ENUM_X_MARKET_CYCLES cycles[]; + int count = GetAllMarketCycles(cycles); + for (int i = 0; i < count; i++) + { + // + ENUM_X_MARKET_CYCLES iCycle = cycles[i]; + string iStr = ToString(iCycle); + + // + if (value == iStr) + { + // + result = iCycle; + break; + } + } + + // + return result; +} + +// +// Converts a Cycle to it's String Representation ... +string ToString(ENUM_X_MARKET_CYCLES cycle) +{ + // + string result = ""; + + // + string mPStr = EnumToString(cycle); + + string mPStrParts[]; + int partsCount = StringSplit( + mPStr, + StringGetCharacter("_", 0), + mPStrParts); + if (partsCount <= 0) + { + return result; + } + + // + result = mPStrParts[3]; + + // + return result; +} + +// +// Retrieve all Available Cycles ... +int GetAllMarketCycles(ENUM_X_MARKET_CYCLES &result[]) +{ + // + int mResult = 0; + + // + Clean(result); + + // + ENUM_X_MARKET_CYCLES tmp[] = { + X_MARKET_CYCLE_UNKNOWN, + X_MARKET_CYCLE_SHORT, + X_MARKET_CYCLE_MEDIUM, + X_MARKET_CYCLE_LONG, + X_MARKET_CYCLE_HIND}; + + // + Copy( + tmp, + result); + + // + Clean(tmp); + + // + mResult = ArraySize(result); + + // + return mResult; +} + +// +// Retrieve Nearest Period base on Given Period ... +ENUM_TIMEFRAMES GetNearestPeriod(ENUM_TIMEFRAMES mPeriod) +{ + // + ENUM_TIMEFRAMES result = _Period; + + // + mPeriod = NormalizePeriod(mPeriod); + + // + switch (mPeriod) + { + // + case PERIOD_M1: + case PERIOD_M2: + result = PERIOD_M4; + break; + + // + case PERIOD_M3: + case PERIOD_M4: + result = PERIOD_M6; + break; + + // + case PERIOD_M5: + case PERIOD_M6: + case PERIOD_M10: + case PERIOD_M12: + result = PERIOD_M15; + break; + + // + case PERIOD_M15: + case PERIOD_M20: + result = PERIOD_M30; + break; + + // + case PERIOD_H1: + case PERIOD_H2: + case PERIOD_H3: + result = PERIOD_H4; + break; + + // + case PERIOD_H6: + case PERIOD_H8: + result = PERIOD_H12; + break; + + // + case PERIOD_H12: + result = PERIOD_D1; + break; + + // + case PERIOD_D1: + result = PERIOD_W1; + break; + + // + default: + result = PERIOD_MN1; + break; + } + + // + return result; +} + +// +// Retrieve Mediest Period base on Given Period ... +ENUM_TIMEFRAMES GetMediestPeriod(ENUM_TIMEFRAMES mPeriod) +{ + // + ENUM_TIMEFRAMES result = _Period; + + // + mPeriod = NormalizePeriod(mPeriod); + + // + switch (mPeriod) + { + // + case PERIOD_M1: + case PERIOD_M2: + result = PERIOD_M15; + break; + + // + case PERIOD_M3: + case PERIOD_M4: + result = PERIOD_M30; + break; + + // + case PERIOD_M5: + case PERIOD_M6: + case PERIOD_M10: + case PERIOD_M12: + result = PERIOD_H1; + break; + + // + case PERIOD_M15: + case PERIOD_M20: + result = PERIOD_H2; + break; + + // + case PERIOD_H1: + case PERIOD_H2: + case PERIOD_H3: + result = PERIOD_H8; + break; + + // + case PERIOD_H6: + case PERIOD_H8: + result = PERIOD_D1; + break; + + // + case PERIOD_H12: + result = PERIOD_W1; + break; + + // + case PERIOD_D1: + result = PERIOD_MN1; + break; + + // + default: + result = PERIOD_MN1; + break; + } + + // + return result; +} + +// +// Retrieve Longest Period base on Given Period ... +ENUM_TIMEFRAMES GetLongestPeriod(ENUM_TIMEFRAMES mPeriod) +{ + // + ENUM_TIMEFRAMES result = _Period; + + // + mPeriod = NormalizePeriod(mPeriod); + + // + switch (mPeriod) + { + // + case PERIOD_M1: + case PERIOD_M2: + result = PERIOD_M30; + break; + + // + case PERIOD_M3: + case PERIOD_M4: + result = PERIOD_H1; + break; + + // + case PERIOD_M5: + case PERIOD_M6: + case PERIOD_M10: + case PERIOD_M12: + result = PERIOD_H2; + break; + + // + case PERIOD_M15: + case PERIOD_M20: + result = PERIOD_H4; + break; + + // + case PERIOD_H1: + case PERIOD_H2: + case PERIOD_H3: + result = PERIOD_H12; + break; + + // + case PERIOD_H6: + case PERIOD_H8: + result = PERIOD_W1; + break; + + // + case PERIOD_H12: + result = PERIOD_MN1; + break; + + // + case PERIOD_D1: + result = PERIOD_MN1; + break; + + // + default: + result = PERIOD_MN1; + break; + } + + // + return result; +} + +// +// Retrieve Hindmost Period base on Given Period ... +ENUM_TIMEFRAMES GetHindMostPeriod(ENUM_TIMEFRAMES mPeriod) +{ + // + ENUM_TIMEFRAMES result = _Period; + + // + mPeriod = NormalizePeriod(mPeriod); + + // + switch (mPeriod) + { + // + case PERIOD_M1: + case PERIOD_M2: + result = PERIOD_H1; + break; + + // + case PERIOD_M3: + case PERIOD_M4: + result = PERIOD_H2; + break; + + // + case PERIOD_M5: + case PERIOD_M6: + case PERIOD_M10: + case PERIOD_M12: + result = PERIOD_H4; + break; + + // + case PERIOD_M15: + case PERIOD_M20: + result = PERIOD_H8; + break; + + // + case PERIOD_H1: + case PERIOD_H2: + case PERIOD_H3: + result = PERIOD_D1; + break; + + // + case PERIOD_H6: + case PERIOD_H8: + result = PERIOD_MN1; + break; + + // + case PERIOD_H12: + result = PERIOD_MN1; + break; + + // + case PERIOD_D1: + result = PERIOD_MN1; + break; + + // + default: + result = PERIOD_MN1; + break; + } + + // + return result; +} + +// +// Retrieve Specified Cycles Period related to Host Period ... +ENUM_TIMEFRAMES GetCyclePeriod( + ENUM_X_MARKET_CYCLES mCycle = NULL, // Specified Cycle + ENUM_TIMEFRAMES mPeriod = NULL // Host Period +) +{ + // + ENUM_TIMEFRAMES result = NULL; + + // + mPeriod = NormalizePeriod(mPeriod); + mCycle = NormalizeCycle(mCycle); + + // + switch (mCycle) + { + // + // Short ... + case X_MARKET_CYCLE_SHORT: + result = GetNearestPeriod(mPeriod); + break; + + // + // Medium ... + case X_MARKET_CYCLE_MEDIUM: + result = GetMediestPeriod(mPeriod); + break; + + // + // Long ... + case X_MARKET_CYCLE_LONG: + result = GetLongestPeriod(mPeriod); + break; + + // + // Hind ... + case X_MARKET_CYCLE_HIND: + result = GetHindMostPeriod(mPeriod); + break; + } + + // + return result; +} \ No newline at end of file diff --git a/MQLTestWorkspace/BKPS/14030316/Libraries/x-saherelm.draw.lib.mq5 b/MQLTestWorkspace/BKPS/14030316/Libraries/x-saherelm.draw.lib.mq5 new file mode 100644 index 0000000..2bdaf10 --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Libraries/x-saherelm.draw.lib.mq5 @@ -0,0 +1,2443 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Draw Library +// -------------------------------------- +// Name: XDraw +// Description: provides Draw abilities ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Global Definitions: Variables, Properties and etc ... + +// +// Retrieve Chart Size in Pixel ... +struct XSize +{ + long width; + long height; + + // + int x; + int y; + int w; + int h; + + // + int wStep; + int hStep; +}; + +// +// Define a Draw Specifications ... +struct XDrawSpecifications +{ + // + // Props ... + + // + bool draw; // Draw or Not ... + + // + int width; // Draw Witdth ... + color clr; // Draw Color ... + ENUM_LINE_STYLE style; // Draw Style ... + + // + bool back; // in the background + bool fill; // fill object if supported + bool selection; // highlight to move + bool rayRight; // line's continuation to the right + bool hidden; // hidden in the object list + long zOrder; // priority for mouse click + + // + string label; // Label ... + color labelColor; // Label Color ... + double labelAngel; // Label Angle ... + string labelFont; // Label Font ... + int labelFontSize; // Label Font Size ... + ENUM_ANCHOR_POINT labelAnchor; // Label Anchor Point ... + + // + // Constructor ... + XDrawSpecifications() + { + Clean(); + } + + // + // Operator ... + void operator=(const XDrawSpecifications &value) + { + // + clr = value.clr; + draw = value.draw; + width = value.width; + style = value.style; + + // + back = value.back; + hidden = value.hidden; + zOrder = value.zOrder; + rayRight = value.rayRight; + selection = value.selection; + + // + fill = value.fill; + + // + label = value.label; + labelColor = value.labelColor; + labelAngel = value.labelAngel; + labelFont = value.labelFont; + labelFontSize = value.labelFontSize; + labelAnchor = value.labelAnchor; + } + + // + // Functions ... + + // + void Clean() + { + // + draw = false; + width = 1; + clr = CLR_NONE; + style = STYLE_SOLID; + + // + back = false; + hidden = false; + rayRight = false; + selection = false; + fill = false; + + // + zOrder = 0; + + // + label = ""; + labelColor = CLR_NONE; + labelAngel = 0; + labelFont = "Arial"; + labelFontSize = 20; + labelAnchor = ANCHOR_LEFT_UPPER; + } + + // + void Label( + string mLabel = "", // Label ... + color mLabelColor = CLR_NONE, // Label Color ... + string mLabelFont = "Arial", // Label Font ... + int mLabelFontSize = 20, // Label Font Size ... + ENUM_ANCHOR_POINT mLabelAnchor = ANCHOR_LEFT_UPPER, // Label Anchor Point ... + double mLabelAngel = 0 // Label Angle ... + ) + { + // + label = mLabel; + labelFont = mLabelFont; + labelColor = mLabelColor; + labelAngel = mLabelAngel; + labelAnchor = mLabelAnchor; + labelFontSize = mLabelFontSize; + } +}; + +// +// Candle Draw Specifications ... +struct XOHCLDrawSpecification +{ + // + // Props ... + XDrawSpecifications openStyle; + XDrawSpecifications highStyle; + XDrawSpecifications closeStyle; + XDrawSpecifications lowStyle; + + // + // Constructors ... + XOHCLDrawSpecification() + { + Clean(); + } + + // + // Operators ... + void operator=(const XOHCLDrawSpecification &value) + { + // + lowStyle = value.lowStyle; + openStyle = value.openStyle; + highStyle = value.highStyle; + closeStyle = value.closeStyle; + } + + // + // Functions ... + + // + void Clean() + { + // + lowStyle.Clean(); + openStyle.Clean(); + highStyle.Clean(); + closeStyle.Clean(); + } + + // + void Default() + { + // + // Open ... + openStyle.width = 1; + openStyle.draw = true; + openStyle.clr = clrLime; + openStyle.style = STYLE_SOLID; + openStyle.Label( + "O", + openStyle.clr); + + // + // High ... + highStyle.width = 1; + highStyle.draw = true; + highStyle.clr = clrAqua; + highStyle.style = STYLE_SOLID; + highStyle.Label( + "H", + highStyle.clr); + + // + // Close ... + closeStyle.width = 1; + closeStyle.draw = true; + closeStyle.clr = clrRed; + closeStyle.style = STYLE_SOLID; + closeStyle.Label( + "C", + closeStyle.clr); + + // + // Low ... + lowStyle.width = 1; + lowStyle.draw = true; + lowStyle.clr = clrMagenta; + lowStyle.style = STYLE_SOLID; + lowStyle.Label( + "L", + lowStyle.clr); + } + + // + void Width(int value) + { + // + lowStyle.width = value; + openStyle.width = value; + highStyle.width = value; + closeStyle.width = value; + } + + // + void Style(ENUM_LINE_STYLE value) + { + // + lowStyle.style = value; + openStyle.style = value; + highStyle.style = value; + closeStyle.style = value; + } + + // + void Color(color value) + { + // + lowStyle.clr = value; + openStyle.clr = value; + highStyle.clr = value; + closeStyle.clr = value; + } + + // + void RayRight(bool value) + { + // + lowStyle.rayRight = value; + openStyle.rayRight = value; + highStyle.rayRight = value; + closeStyle.rayRight = value; + } + + // + void Draw(bool value) + { + // + lowStyle.draw = value; + openStyle.draw = value; + highStyle.draw = value; + closeStyle.draw = value; + } + + // + void Back(bool value) + { + // + lowStyle.back = value; + openStyle.back = value; + highStyle.back = value; + closeStyle.back = value; + } + + // + void Fill(bool value) + { + // + lowStyle.fill = value; + openStyle.fill = value; + highStyle.fill = value; + closeStyle.fill = value; + } + + // + void Label(string value) + { + // + lowStyle.Label(value); + openStyle.Label(value); + highStyle.Label(value); + closeStyle.Label(value); + } + + // + void SetLabelPrefix(string value) + { + // + lowStyle.label = value + " " + lowStyle.label; + openStyle.label = value + " " + openStyle.label; + highStyle.label = value + " " + highStyle.label; + closeStyle.label = value + " " + closeStyle.label; + } +}; + +// +string drawPrefix = "X-OBJ"; + +// +// Common Draw Functions ... + +// +// remove drawn objects ... +void RemoveDraws( + string tag = NULL, + long chartId = -1, + int subWindow = -1 // +) +{ + // + // Normalize Args ... + // + if (tag == NULL) + { + tag = drawPrefix; + } + + // + if (chartId == -1) + { + chartId = 0; + } + + // + if (subWindow == -1) + { + subWindow = 0; + } + + // + for (int iObj = ObjectsTotal(chartId, subWindow) - 1; iObj >= 0; iObj--) + { + // + string on = ObjectName(chartId, iObj, subWindow); + if (StringFind(on, tag) >= 0) + { + ObjectDelete(chartId, on); + } + } + + // + // Redraw Chart ... + ChartRedraw(); +} + +// +bool RemoveDraw( + string name, + long chartId = -1, + int subWindow = -1 // +) +{ + // + bool result = false; + + // + if (chartId == -1) + { + chartId = 0; + } + + // + if (subWindow == -1) + { + subWindow = 0; + } + + // + string objName = ""; + for (int iObj = ObjectsTotal(chartId, subWindow) - 1; iObj >= 0; iObj--) + { + // + string on = ObjectName(chartId, iObj, subWindow); + if (StringFind(on, name) >= 0) + { + // + objName = on; + break; + } + } + + // + if (StringLen(objName) > 0) + { + result = ObjectDelete(chartId, objName); + } + + // + return result; +} + +// +// Deselect All Draws ... +void DeselectAllDraws() +{ + // + int objs = ObjectsTotal(ChartID(), 0); + for (int o = 0; o < objs; o++) + { + ObjectSetInteger(ChartID(), ObjectName(ChartID(), o, 0), OBJPROP_SELECTED, false); + } + + // + ChartRedraw(); +} + +// +// Check Object Exists ... +bool IsDrawExists( + string name, + long chartId = -1, + int subWindow = -1 // +) +{ + // + bool result = false; + + // + if (chartId == -1) + { + chartId = 0; + } + + // + if (subWindow == -1) + { + subWindow = 0; + } + + // + for (int iObj = ObjectsTotal(chartId, subWindow) - 1; iObj >= 0; iObj--) + { + // + string on = ObjectName(chartId, iObj, subWindow); + result = StringFind(on, name) >= 0; + if (result) + { + break; + } + } + + // + return result; +} + +// +// Regular Draws ... + +// +// Arrow Functions ... + +// +// Draw an Arrow Object on Chart ... +bool DrawArrow( + const long chartID = 0, // chart's ID + const string name = "Arrow", // arrow name + const int subWindow = 0, // subwindow index + datetime time = 0, // anchor point time + double price = 0, // anchor point price + const uchar arrowCode = 252, // arrow code + const ENUM_ARROW_ANCHOR anchor = ANCHOR_BOTTOM, // anchor point position + const color clr = clrAqua, // arrow color + const ENUM_LINE_STYLE style = STYLE_SOLID, // border line style + const int width = 3, // arrow size + const bool back = false, // in the background + const bool selection = false, // highlight to move + const bool hidden = false, // hidden in the object list + const long zOrder = 0 // Order Object ... +) +{ + // + bool result = false; + + // + // set anchor point coordinates if they are not set ... + ChangeArrowEmptyPoint(time, price); + + // + // reset the error value ... + ResetLastError(); + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // create an arrow ... + result = ObjectCreate(chartID, objName, OBJ_ARROW, subWindow, time, price); + if (!result) + { + return result; + } + + // + // set the arrow code ... + ObjectSetInteger(chartID, objName, OBJPROP_ARROWCODE, arrowCode); + + // + // set anchor type ... + ObjectSetInteger(chartID, objName, OBJPROP_ANCHOR, anchor); + + // + // set the arrow color ... + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // set the border line style ... + ObjectSetInteger(chartID, objName, OBJPROP_STYLE, style); + + // + // set the arrow's size ... + ObjectSetInteger(chartID, objName, OBJPROP_WIDTH, width); + + // + // display in the foreground false or background true ... + ObjectSetInteger(chartID, objName, OBJPROP_BACK, back); + + // + // enable true or disable false the mode of moving the arrow by mouse + // when creating a graphical object using ObjectCreate function, the object cannot be + // highlighted and moved by default. Inside this method, selection parameter + // is false by default, if you want making it possible to highlight and move the object + // change it to true ... + ObjectSetInteger(chartID, objName, OBJPROP_SELECTABLE, true); + ObjectSetInteger(chartID, objName, OBJPROP_SELECTED, selection); + + // + // hide true or display false graphical object name in the object list ... + ObjectSetInteger(chartID, objName, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart ... + ObjectSetInteger(chartID, objName, OBJPROP_ZORDER, zOrder); + + // + // successful execution ... + return result; +} + +// +// Move the anchor point of Arrow ... +bool MoveArrow( + const long chartID = 0, // chart's ID + const string name = "Arrow", // object name + datetime time = 0, // anchor point time coordinate + double price = 0 // anchor point price coordinate +) +{ + // + bool result = false; + + // + // if point position is not set, move it to the current bar having Bid price ... + if (!time) + { + time = TimeCurrent(); + } + + // + if (!price) + { + price = SymbolInfoDouble(_Symbol, SYMBOL_BID); + } + + // + // move the anchor point ... + result = ObjectMove(chartID, name, 0, time, price); + + // + return result; +} + +// +// Delete an arrow ... +bool DeleteArrow( + const long chartID = 0, // chart's ID + const string name = "Arrow" // arrow name +) +{ + // + bool result = false; + + // + // delete an arrow ... + result = !ObjectDelete(chartID, name); + + // + return result; +} + +// +// Change the arrow code ... +bool ArrowCodeChange( + const long chartID = 0, // chart's ID + const string name = "Arrow", // object name + const uchar code = 252 // arrow code +) +{ + // + bool result = false; + + // + // change the arrow code ... + result = ObjectSetInteger(chartID, name, OBJPROP_ARROWCODE, code); + + // + return result; +} + +// +// Change anchor type ... +bool ArrowAnchorChange( + const long chartID = 0, // chart's ID + const string name = "Arrow", // object name + const ENUM_ARROW_ANCHOR anchor = ANCHOR_TOP // anchor type +) +{ + // + bool result = false; + + // + // change anchor type ... + result = !ObjectSetInteger(chartID, name, OBJPROP_ANCHOR, anchor); + + // + return result; +} + +// +// Check anchor point values and set default values +// for empty ones ... +void ChangeArrowEmptyPoint( + datetime &time, + double &price // +) +{ + // + // if the point's time is not set, it will be on the current bar ... + if (!time) + { + time = TimeCurrent(); + } + + // + // if the point's price is not set, it will have Bid value ... + if (!price) + { + price = SymbolInfoDouble(_Symbol, SYMBOL_BID); + } +} + +// +// Horizontal Line Functions ... + +// +// Create, Draw the horizontal line ... +bool DrawHorizontalLine( + const long chartID = 0, // chart's ID + const string name = "HLine", // line name + const int subWindow = 0, // subwindow index + double price = 0, // line price + const color clr = clrRed, // line color + const ENUM_LINE_STYLE style = STYLE_SOLID, // line style + const int width = 1, // line width + const bool back = false, // in the background + const bool selection = false, // highlight to move + const bool hidden = false, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + bool result = false; + + // + // if the price is not set, set it at the current Bid price level ... + if (!price) + { + price = SymbolInfoDouble(Symbol(), SYMBOL_BID); + } + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // create a horizontal line ... + result = ObjectCreate(chartID, objName, OBJ_HLINE, subWindow, 0, price); + if (!result) + { + return result; + } + + // + // set line color ... + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // set line display style ... + ObjectSetInteger(chartID, objName, OBJPROP_STYLE, style); + + // + // set line width ... + ObjectSetInteger(chartID, objName, OBJPROP_WIDTH, width); + + // + // display in the foreground false or background true ... + ObjectSetInteger(chartID, objName, OBJPROP_BACK, back); + + // + // enable true or disable false the mode of moving the line by mouse + // when creating a graphical object using ObjectCreate function, the object cannot be + // highlighted and moved by default. Inside this method, selection parameter + // is true by default making it possible to highlight and move the object + ObjectSetInteger(chartID, objName, OBJPROP_SELECTABLE, selection); + ObjectSetInteger(chartID, objName, OBJPROP_SELECTED, selection); + + // + // hide true or display false graphical object name in the object list ... + ObjectSetInteger(chartID, objName, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart ... + ObjectSetInteger(chartID, objName, OBJPROP_ZORDER, zOrder); + + // + // successful execution ... + return result; +} + +// +// Move horizontal line ... +bool MoveHorizontalLine( + const long chartID = 0, // chart's ID + const string name = "HLine", // line name + double price = 0 // line price +) +{ + // + bool result = false; + + // + // if the line price is not set, move it to the current Bid price level ... + if (!price) + { + price = SymbolInfoDouble(Symbol(), SYMBOL_BID); + } + + // + // move a horizontal line ... + result = ObjectMove(chartID, name, 0, 0, price); + + // + return result; +} + +// +// Delete a horizontal line ... +bool DeleteHorizontalLine( + const long chartID = 0, // chart's ID + const string name = "HLine" // line name +) +{ + // + bool result = false; + + // + // delete a horizontal line ... + result = ObjectDelete(chartID, name); + + // + return result; +} + +// +// Vertical Line Functions ... + +// +// Create the vertical line ... +bool DrawVerticalLine( + const long chartID = 0, // chart's ID + const string name = "VLine", // line name + const int subWindow = 0, // subwindow index + datetime time = 0, // line time + const color clr = clrRed, // line color + const ENUM_LINE_STYLE style = STYLE_SOLID, // line style + const int width = 1, // line width + const bool back = false, // in the background + const bool selection = false, // highlight to move + const bool hidden = false, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + bool result = false; + + // + // if the line time is not set, draw it via the last bar ... + if (!time) + { + time = TimeCurrent(); + } + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // create a vertical line ... + result = ObjectCreate(chartID, objName, OBJ_VLINE, subWindow, time, 0); + if (!result) + { + return result; + } + + // + // set line color ... + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // set line display style ... + ObjectSetInteger(chartID, objName, OBJPROP_STYLE, style); + + // + // set line width ... + ObjectSetInteger(chartID, objName, OBJPROP_WIDTH, width); + + // + // display in the foreground false or background true ... + ObjectSetInteger(chartID, objName, OBJPROP_BACK, back); + + // + // enable true or disable false the mode of moving the line by mouse + // when creating a graphical object using ObjectCreate function, the object cannot be + // highlighted and moved by default. Inside this method, selection parameter + // is true by default making it possible to highlight and move the object ... + ObjectSetInteger(chartID, objName, OBJPROP_SELECTABLE, true); + ObjectSetInteger(chartID, objName, OBJPROP_SELECTED, selection); + + // + // hide true or display false graphical object name in the object list ... + ObjectSetInteger(chartID, objName, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart + ObjectSetInteger(chartID, objName, OBJPROP_ZORDER, zOrder); + + // + // successful execution ... + return result; +} + +// +// Move the vertical line ... +bool MoveVerticalLine( + const long chartID = 0, // chart's ID + const string name = "VLine", // line name + datetime time = 0 // line time +) +{ + // + bool result = false; + + // + // if line time is not set, move the line to the last bar ... + if (!time) + { + time = TimeCurrent(); + } + + // + // move the vertical line ... + result = ObjectMove(chartID, name, 0, time, 0); + + // + return result; +} + +// +// Delete the vertical line ... +bool DeleteVerticalLine( + const long chartID = 0, // chart's ID + const string name = "VLine" // line name +) +{ + // + bool result = false; + + // + // delete the vertical line ... + result = ObjectDelete(chartID, name); + + // + return result; +} + +// +// Rectangle Functions ... + +// +// Create rectangle by the given coordinates ... +bool DrawRectangle( + const long chartID = 0, // chart's ID + const string name = "Rectangle", // rectangle name + const int subWindow = 0, // subwindow index + datetime time1 = 0, // first point time + double price1 = 0, // first point price + datetime time2 = 0, // second point time + double price2 = 0, // second point price + const color clr = clrRed, // rectangle color + const ENUM_LINE_STYLE style = STYLE_SOLID, // style of rectangle lines + const int width = 1, // width of rectangle lines + const bool fill = false, // filling rectangle with color + const bool back = false, // in the background + const bool selection = true, // highlight to move + const bool hidden = true, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + bool result = false; + + // + // Set anchor points' coordinates if they are not set ... + ChangeRectangleEmptyPoints(time1, price1, time2, price2); + + // + // Create a rectangle by the given coordinates ... + result = ObjectCreate(chartID, name, OBJ_RECTANGLE, subWindow, time1, price1, time2, price2); + if (!result) + { + return result; + } + + // + // Set rectangle color ... + ObjectSetInteger(chartID, name, OBJPROP_COLOR, clr); + + // + // Set the style of rectangle lines + ObjectSetInteger(chartID, name, OBJPROP_STYLE, style); + + // + // Set width of the rectangle lines ... + ObjectSetInteger(chartID, name, OBJPROP_WIDTH, width); + + // + // Enable (true) or disable (false) the mode of filling the rectangle ... + ObjectSetInteger(chartID, name, OBJPROP_FILL, fill); + + // + // Display in the foreground (false) or background (true) ... + ObjectSetInteger(chartID, name, OBJPROP_BACK, back); + + // + // Enable (true) or disable (false) the mode of highlighting the rectangle for moving + // when creating a graphical object using ObjectCreate function, the object cannot be + // highlighted and moved by default. Inside this method, selection parameter + // is true by default making it possible to highlight and move the object + ObjectSetInteger(chartID, name, OBJPROP_SELECTABLE, selection); + + // + ObjectSetInteger(chartID, name, OBJPROP_SELECTED, selection); + + // + // Hide (true) or display (false) graphical object name in the object list ... + ObjectSetInteger(chartID, name, OBJPROP_HIDDEN, hidden); + + // + // Set the priority for receiving the event of a mouse click in the chart ... + ObjectSetInteger(chartID, name, OBJPROP_ZORDER, zOrder); + + // + // Successful execution + return result; +} + +// +// Move the rectangle anchor point ...s +bool RectanglePointChange( + const long chartID = 0, // chart's ID + const string name = "Rectangle", // rectangle name + const int pointIndex = 0, // anchor point index + datetime time = 0, // anchor point time coordinate + double price = 0 // anchor point price coordinate +) +{ + // + bool result = false; + + // + // if point position is not set, move it to the current bar having Bid price ... + if (!time) + { + time = TimeCurrent(); + } + + // + if (!price) + { + price = SymbolInfoDouble(Symbol(), SYMBOL_BID); + } + + // + // Move the anchor point ... + result = ObjectMove(chartID, name, pointIndex, time, price); + + // + return result; +} + +// +// Delete the rectangle ... +bool DeleteRectangle( + const long chartID = 0, // chart's ID + const string name = "Rectangle" // rectangle name +) +{ + // + bool result = false; + + // + result = ObjectDelete(chartID, name); + + // + return result; +} + +// +// Check the values of rectangle's anchor points and set default +// values for empty ones +void ChangeRectangleEmptyPoints( + datetime &time1, double &price1, + datetime &time2, double &price2 // +) +{ + // + // if the first point's time is not set, it will be on the current bar ... + if (!time1) + { + time1 = TimeCurrent(); + } + + // + // if the first point's price is not set, it will have Bid value ... + if (!price1) + { + price1 = SymbolInfoDouble(Symbol(), SYMBOL_BID); + } + + // + // if the second point's time is not set, it is located 9 bars left from the second one ... + if (!time2) + { + // + // array for receiving the open time of the last 10 bars ... + datetime temp[10]; + CopyTime(Symbol(), Period(), time1, 10, temp); + + // + // set the second point 9 bars left from the first one ... + time2 = temp[0]; + } + + // + // if the second point's price is not set, move it 300 points lower than the first one ... + if (!price2) + { + price2 = price1 - 300 * SymbolInfoDouble(Symbol(), SYMBOL_POINT); + } +} + +// +// RectangleLabel Functions ... + +// +// Create Rectangle Label Object ... +bool DrawRectangleLabel( + const long chartID = 0, // chart's ID + const string name = "RectLabel", // label name + const int subWindow = 0, // subwindow index + const int x = 0, // X coordinate + const int y = 0, // Y coordinate + const int width = 50, // width + const int height = 18, // height + const color bgColor = clrWhiteSmoke, // background color + const ENUM_BORDER_TYPE border = BORDER_SUNKEN, // border type + const ENUM_BASE_CORNER corner = CORNER_LEFT_UPPER, // chart corner for anchoring + const color clr = clrRed, // flat border color (Flat) + const ENUM_LINE_STYLE style = STYLE_SOLID, // flat border style + const int lineWidth = 1, // flat border width + const bool back = false, // in the background + const bool selection = false, // highlight to move + const bool hidden = false, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + bool result = false; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // create a rectangle label + result = ObjectCreate(chartID, objName, OBJ_RECTANGLE_LABEL, subWindow, 0, 0); + if (!result) + { + return result; + } + + // + // set label coordinates ... + ObjectSetInteger(chartID, objName, OBJPROP_XDISTANCE, x); + ObjectSetInteger(chartID, objName, OBJPROP_YDISTANCE, y); + + // + // set label size ... + ObjectSetInteger(chartID, objName, OBJPROP_XSIZE, width); + ObjectSetInteger(chartID, objName, OBJPROP_YSIZE, height); + + // + // set background color ... + ObjectSetInteger(chartID, objName, OBJPROP_BGCOLOR, bgColor); + + // + // set border type ... + ObjectSetInteger(chartID, objName, OBJPROP_BORDER_TYPE, border); + + // + // set the chart's corner, relative to which point coordinates are defined ... + ObjectSetInteger(chartID, objName, OBJPROP_CORNER, corner); + + // + // set flat border color (in Flat mode) ... + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // set flat border line style ... + ObjectSetInteger(chartID, objName, OBJPROP_STYLE, style); + + // + // set flat border width ... + ObjectSetInteger(chartID, objName, OBJPROP_WIDTH, lineWidth); + + // + // display in the foreground false or background true ... + ObjectSetInteger(chartID, objName, OBJPROP_BACK, back); + + // + // enable true or disable false the mode of moving the label by mouse ... + ObjectSetInteger(chartID, objName, OBJPROP_SELECTABLE, selection); + ObjectSetInteger(chartID, objName, OBJPROP_SELECTED, selection); + + // + // hide true or display false graphical object name in the object list ... + ObjectSetInteger(chartID, objName, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart ... + ObjectSetInteger(chartID, objName, OBJPROP_ZORDER, zOrder); + + // + // successful execution ... + return result; +} + +// +// Move Rectangle Label .. +bool MoveRectangleLabel( + const long chartID = 0, // chart's ID + const string name = "RectLabel", // label name + const int x = 0, // X coordinate + const int y = 0 // Y coordinate +) +{ + // + bool result = false; + + // + // move the rectangle label ... + result = ObjectSetInteger(chartID, name, OBJPROP_XDISTANCE, x); + if (!result) + { + return result; + } + + // + result = ObjectSetInteger(chartID, name, OBJPROP_YDISTANCE, y); + + // + return result; +} + +// +// Delete the rectangle label ... +bool DeleteRectangleLabel( + const long chartID = 0, // chart's ID + const string name = "RectLabel" // label name +) +{ + // + bool result = false; + + // + // delete the label ... + result = ObjectDelete(chartID, name); + + // + return result; +} + +// +// Change Rectangle Label Size ... +bool ChangeSizeRectangleLabel( + const long chartID = 0, // chart's ID + const string name = "RectLabel", // label name + const int width = 50, // label width + const int height = 18 // label height +) +{ + // + bool result = false; + + // + // change label size ... + result = ObjectSetInteger(chartID, name, OBJPROP_XSIZE, width); + if (!result) + { + return result; + } + + // + result = ObjectSetInteger(chartID, name, OBJPROP_YSIZE, height); + + // + return result; +} + +// +// Change rectangle label border type ... +bool RectLabelChangeBorderType( + const long chartID = 0, // chart's ID + const string name = "RectLabel", // label name + const ENUM_BORDER_TYPE border = BORDER_SUNKEN // border type +) +{ + // + bool result = false; + + // + // change border type ... + result = ObjectSetInteger(chartID, name, OBJPROP_BORDER_TYPE, border); + + // + return result; +} + +// +// TrendLine Funcions ... + +// +// Create a trend line by the given coordinates ... +bool DrawTrendLine( + const long chartID = 0, // chart's ID + const string name = "TrendLine", // line name + const int subWindow = 0, // subwindow index + datetime time1 = 0, // first point time + double price1 = 0, // first point price + datetime time2 = 0, // second point time + double price2 = 0, // second point price + const color clr = clrYellow, // line color + const ENUM_LINE_STYLE style = STYLE_SOLID, // line style + const int width = 1, // line width + const bool back = false, // in the background + const bool selection = false, // highlight to move + const bool rayRight = false, // line's continuation to the right + const bool hidden = false, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + bool result = false; + + // + // set anchor points' coordinates if they are not set ... + ChangeTrendLineEmptyPoints( + time1, + price1, + time2, + price2); + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // create a trend line by the given coordinates ... + result = ObjectCreate(chartID, objName, OBJ_TREND, subWindow, time1, price1, time2, price2); + if (!result) + { + return result; + } + + // + // set line color ... + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // set line display style ... + ObjectSetInteger(chartID, objName, OBJPROP_STYLE, style); + + // + // set line width ... + ObjectSetInteger(chartID, objName, OBJPROP_WIDTH, width); + + // + // display in the foreground false or background true ... + ObjectSetInteger(chartID, objName, OBJPROP_BACK, back); + + // + // enable true or disable false the mode of moving the line by mouse + // when creating a graphical object using ObjectCreate function, the object cannot be + // highlighted and moved by default. Inside this method, selection parameter + // is true by default making it possible to highlight and move the object ... + ObjectSetInteger(chartID, objName, OBJPROP_SELECTABLE, true); + ObjectSetInteger(chartID, objName, OBJPROP_SELECTED, selection); + + // + // enable true or disable false the mode of continuation of the line's display to the right ... + ObjectSetInteger(chartID, objName, OBJPROP_RAY_RIGHT, rayRight); + + // + // hide true or display false graphical object name in the object list ... + ObjectSetInteger(chartID, objName, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart ... + ObjectSetInteger(chartID, objName, OBJPROP_ZORDER, zOrder); + + // + // successful execution ... + return result; +} + +// +// Move trend line anchor point ... | +bool ChangeTrendLinePoint( + const long chartID = 0, // chart's ID + const string name = "TrendLine", // line name + const int pointindex = 0, // anchor point index + datetime time = 0, // anchor point time coordinate + double price = 0 // anchor point price coordinate +) +{ + // + bool result = false; + + // + // if point position is not set, move it to the current bar having Bid price ... + if (!time) + { + time = TimeCurrent(); + } + + // + if (!price) + { + price = SymbolInfoDouble(Symbol(), SYMBOL_BID); + } + + // + // move trend line's anchor point ... + result = ObjectMove(chartID, name, pointindex, time, price); + + // + return result; +} + +// +// The function deletes the trend line from the chart ... +bool DeleteTrendLine( + const long chartID = 0, // chart's ID + const string name = "TrendLine" // line name +) +{ + // + bool result = false; + + // + // delete a trend line ... + result = ObjectDelete(chartID, name); + + // + return result; +} + +// +// Check the values of trend line's anchor points and set default ... +// values for empty ones ... +void ChangeTrendLineEmptyPoints( + datetime &time1, + double &price1, + datetime &time2, + double &price2 // +) +{ + // + // if the first point's time is not set, it will be on the current bar ... + if (!time1) + { + time1 = TimeCurrent(); + } + + // + // if the first point's price is not set, it will have Bid value ... + if (!price1) + { + price1 = SymbolInfoDouble(Symbol(), SYMBOL_BID); + } + + // + // if the second point's time is not set, it is located 9 bars left from the second one ... + if (!time2) + { + // + // array for receiving the open time of the last 10 bars ... + datetime temp[10]; + CopyTime(Symbol(), Period(), time1, 10, temp); + + // + // set the second point 9 bars left from the first one ... + time2 = temp[0]; + } + + // + // if the second point's price is not set, it is equal to the first point's one ... + if (!price2) + { + price2 = price1; + } +} + +// +// Text Functions ... + +// +// Create and Draw a Text Object ... +bool DrawText( + const long chartID = 0, // chart's ID + const string name = "Text", // object name + const int subWindow = 0, // subwindow index + datetime time = 0, // anchor point time + double price = 0, // anchor point price + const string text = "Text", // the text itself + const string font = "Arial", // font + const int fontSize = 10, // font size + const color clr = clrRed, // color + const double angle = 0.0, // text slope + const ENUM_ANCHOR_POINT anchor = ANCHOR_CENTER, // anchor type + const bool back = false, // in the background + const bool selection = false, // highlight to move + const bool hidden = true, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + bool result = false; + + // + // set anchor point coordinates if they are not set ... + ChangeTextEmptyPoint(time, price); + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // + // create Text object + result = ObjectCreate(chartID, objName, OBJ_TEXT, subWindow, time, price); + if (!result) + { + return result; + } + + // + // set the text ... + ObjectSetString(chartID, objName, OBJPROP_TEXT, text); + + // + // set text font ... + ObjectSetString(chartID, objName, OBJPROP_FONT, font); + + // + // set font size ... + ObjectSetInteger(chartID, objName, OBJPROP_FONTSIZE, fontSize); + + // + // set the slope angle of the text ... + ObjectSetDouble(chartID, objName, OBJPROP_ANGLE, angle); + + // + // set anchor type ... + ObjectSetInteger(chartID, objName, OBJPROP_ANCHOR, anchor); + + // + // set color ... + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // display in the foreground false or background true ... + ObjectSetInteger(chartID, objName, OBJPROP_BACK, back); + + // + // enable true or disable false the mode of moving the object by mouse ... + ObjectSetInteger(chartID, objName, OBJPROP_SELECTABLE, true); + ObjectSetInteger(chartID, objName, OBJPROP_SELECTED, selection); + + // + // hide true or display false graphical object name in the object list ... + ObjectSetInteger(chartID, objName, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart ... + ObjectSetInteger(chartID, objName, OBJPROP_ZORDER, zOrder); + + // + // successful execution ... + return result; +} + +// +// Move the anchor point ... +bool MoveText( + const long chartID = 0, // chart's ID + const string name = "Text", // object name + datetime time = 0, // anchor point time coordinate + double price = 0 // anchor point price coordinate +) +{ + // + bool result = false; + + // + // + // if point position is not set, move it to the current bar having Bid price + if (!time) + { + time = TimeCurrent(); + } + + // + if (!price) + { + price = SymbolInfoDouble(_Symbol, SYMBOL_BID); + } + + // + // move the anchor point ... + result = ObjectMove(chartID, name, 0, time, price); + + // + return result; +} + +// +// Change the object text ... +bool ChangeText( + const long chartID = 0, // chart's ID + const string name = "Text", // object name + const string text = "Text" // text +) +{ + // + bool result = false; + + // + // change object text ... + result = ObjectSetString(chartID, name, OBJPROP_TEXT, text); + + // + return result; +} + +// +// Delete Text object ... +bool DeleteText( + const long chartID = 0, // chart's ID + const string name = "Text" // object name +) +{ + // + bool result = false; + + // + // delete the object ... + result = ObjectDelete(chartID, name); + + // + return result; +} + +// +// Check anchor point values and set default values +// for empty ones ... +void ChangeTextEmptyPoint( + datetime &time, + double &price // +) +{ + // + // if the point's time is not set, it will be on the current bar ... + if (!time) + { + time = TimeCurrent(); + } + + // + // if the point's price is not set, it will have Bid value ... + if (!price) + { + price = SymbolInfoDouble(_Symbol, SYMBOL_BID); + } +} + +// +// Fibonacchi Functions ... + +// +// Create Fibonacci Retracement by the given coordinates ... +bool DrawFibonacci( + const long chartID = 0, // chart's ID + const string name = "Fibonacci", // object name + const int subWindow = 0, // subwindow index + datetime time1 = 0, // first point time + double price1 = 0, // first point price + datetime time2 = 0, // second point time + double price2 = 0, // second point price + const color clr = clrRed, // object color + const ENUM_LINE_STYLE style = STYLE_SOLID, // object line style + const int width = 1, // object line width + const bool back = false, // in the background + const bool selection = true, // highlight to move + const bool rayRight = false, // object's continuation to the right + const bool hidden = true, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + bool result = false; + + // + // set anchor points' coordinates if they are not set ... + ChangeFibonacciEmptyPoints(time1, price1, time2, price2); + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // Create Fibonacci Retracement by the given coordinates ... + result = ObjectCreate(chartID, objName, OBJ_FIBO, subWindow, time1, price1, time2, price2); + if (!result) + { + return result; + } + + // + // set color ... + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // set line style ... + ObjectSetInteger(chartID, objName, OBJPROP_STYLE, style); + + // + // set line width ... + ObjectSetInteger(chartID, objName, OBJPROP_WIDTH, width); + + // + // display in the foreground false or background true ... + ObjectSetInteger(chartID, objName, OBJPROP_BACK, back); + + // + // enable true or disable false the mode of highlighting the channel for moving + // when creating a graphical object using ObjectCreate function, the object cannot be + // highlighted and moved by default. Inside this method, selection parameter + // is true by default making it possible to highlight and move the object ... + ObjectSetInteger(chartID, objName, OBJPROP_SELECTABLE, true); + ObjectSetInteger(chartID, objName, OBJPROP_SELECTED, selection); + + // + // enable true or disable false the mode of continuation of the object's display to the right ... + ObjectSetInteger(chartID, objName, OBJPROP_RAY_RIGHT, rayRight); + + // + // hide true or display false graphical object name in the object list ... + ObjectSetInteger(chartID, objName, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart ... + ObjectSetInteger(chartID, objName, OBJPROP_ZORDER, zOrder); + + // + // successful execution ... + return result; +} + +// +// Create Fibonacci Retracement by the given coordinates ... +bool DrawCustomFibonacci( + // + int levels, // number of level lines + double &values[], // values of level lines + color &colors[], // color of level lines + ENUM_LINE_STYLE &styles[], // style of level lines + int &widths[], // width of level lines + string &descriptions[], // level Descriptions + // + const long chartID = 0, // chart's ID + const string name = "Fibonacci", // object name + const int subWindow = 0, // subwindow index + datetime time1 = 0, // first point time + double price1 = 0, // first point price + datetime time2 = 0, // second point time + double price2 = 0, // second point price + const color clr = clrAqua, // object color + const ENUM_LINE_STYLE style = STYLE_DOT, // object line style + const int width = 1, // object line width + const bool back = false, // in the background + const bool selection = true, // highlight to move + const bool rayRight = false, // object's continuation to the right + const bool hidden = true, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + bool result = false; + + // + // set anchor points' coordinates if they are not set ... + ChangeFibonacciEmptyPoints(time1, price1, time2, price2); + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // Create Fibonacci Retracement by the given coordinates ... + result = ObjectCreate(chartID, name, OBJ_FIBO, subWindow, time1, price1, time2, price2); + if (!result) + { + return result; + } + + // + // set color ... + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // set line style ... + ObjectSetInteger(chartID, objName, OBJPROP_STYLE, style); + + // + // set line width ... + ObjectSetInteger(chartID, objName, OBJPROP_WIDTH, width); + + // + // display in the foreground false or background true ... + ObjectSetInteger(chartID, objName, OBJPROP_BACK, back); + + // + // enable true or disable false the mode of highlighting the channel for moving + // when creating a graphical object using ObjectCreate function, the object cannot be + // highlighted and moved by default. Inside this method, selection parameter + // is true by default making it possible to highlight and move the object ... + ObjectSetInteger(chartID, objName, OBJPROP_SELECTABLE, true); + ObjectSetInteger(chartID, objName, OBJPROP_SELECTED, selection); + + // + // enable true or disable false the mode of continuation of the object's display to the right ... + ObjectSetInteger(chartID, objName, OBJPROP_RAY_RIGHT, rayRight); + + // + // hide true or display false graphical object name in the object list ... + ObjectSetInteger(chartID, objName, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart ... + ObjectSetInteger(chartID, objName, OBJPROP_ZORDER, zOrder); + + // + // Change Levels Of Fibonacci ... + result = FibonacciLevelsSet( + levels, + values, + colors, + styles, + widths, + descriptions, + chartID, + objName); + + // + // successful execution ... + return result; +} + +// +// Set number of levels and their parameters ... +bool FibonacciLevelsSet( + int levels, // number of level lines + double &values[], // values of level lines + color &colors[], // color of level lines + ENUM_LINE_STYLE &styles[], // style of level lines + int &widths[], // width of level lines + string &descriptions[], // level Descriptions + const long chartID = 0, // chart's ID + const string name = "Fibonacci" // object name +) +{ + // + bool result = false; + + // + // check array sizes ... + result = levels == ArraySize(colors) && + levels == ArraySize(styles) && + levels == ArraySize(widths) && + levels == ArraySize(widths); + if (!result) + { + return result; + } + + // + // set the number of levels ... + ObjectSetInteger(chartID, name, OBJPROP_LEVELS, levels); + + // + // set the properties of levels in the loop ... + for (int i = 0; i < levels; i++) + { + // + // level value ... + ObjectSetDouble(chartID, name, OBJPROP_LEVELVALUE, i, values[i]); + + // + // level color ... + ObjectSetInteger(chartID, name, OBJPROP_LEVELCOLOR, i, colors[i]); + + // + // level style ... + ObjectSetInteger(chartID, name, OBJPROP_LEVELSTYLE, i, styles[i]); + + // + // level width ... + ObjectSetInteger(chartID, name, OBJPROP_LEVELWIDTH, i, widths[i]); + + // + // level description ... + // ObjectSetString(chartID, name, OBJPROP_LEVELTEXT, i, DoubleToString(100 * values[i], 1)); + ObjectSetString(chartID, name, OBJPROP_LEVELTEXT, i, descriptions[i]); + } + + // + // successful execution ... + return result; +} + +// +// Move Fibonacci Retracement anchor point ... +bool FibonacciPointChange( + const long chartID = 0, // chart's ID + const string name = "Fibonacci", // object name + const int pointIndex = 0, // anchor point index + datetime time = 0, // anchor point time coordinate + double price = 0 // anchor point price coordinate +) +{ + // + bool result = false; + + // + // if point position is not set, move it to the current bar having Bid price ... + if (!time) + { + time = TimeCurrent(); + } + + // + if (!price) + { + price = SymbolInfoDouble(_Symbol, SYMBOL_BID); + } + + // + // move the anchor point ... + result = ObjectMove(chartID, name, pointIndex, time, price); + + // + return result; +} + +// +// Delete Fibonacci Retracement ... +bool DeleteFibonachi( + const long chartID = 0, // chart's ID + const string name = "Fibonacci" // object name +) +{ + // + bool result = false; + + // + // delete the object ... + result = ObjectDelete(chartID, name); + + // + return result; +} + +// +// Check the values of Fibonacci Retracement anchor points and set +// default values for empty ones ... +void ChangeFibonacciEmptyPoints( + datetime &time1, + double &price1, + datetime &time2, + double &price2 // +) +{ + // + // if the second point's time is not set, it will be on the current bar ... + if (!time2) + { + time2 = TimeCurrent(); + } + + // + // if the second point's price is not set, it will have Bid value ... + if (!price2) + { + price2 = SymbolInfoDouble(_Symbol, SYMBOL_BID); + } + + // + // if the first point's time is not set, it is located 9 bars left from the second one ... + if (!time1) + { + // + // array for receiving the open time of the last 10 bars ... + datetime temp[10]; + CopyTime(Symbol(), Period(), time2, 10, temp); + + // + // set the first point 9 bars left from the second one ... + time1 = temp[0]; + } + + // + // if the first point's price is not set, move it 200 points below the second one ... + if (!price1) + { + price1 = price2 - 200 * SymbolInfoDouble(_Symbol, SYMBOL_POINT); + } +} + +// +// Event Functions ... + +// +// Create an Event ... +bool EventCreate( + const long chartID = 0, // chart's ID + const string name = "Event", // object name + const int subWindow = 0, // subwindow index + const string text = "Content", // event text + datetime time = 0, // anchor point time + const color clr = clrRed, // color + const int width = 1, // point width when highlighted + const bool back = false, // in the background + const bool selection = false, // highlight to move + const bool hidden = true, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + bool result = false; + + // + if (!time) + { + time = TimeCurrent(); + } + + // + result = ObjectCreate(chartID, name, OBJ_EVENT, subWindow, time, 0); + if (!result) + { + return result; + } + + // + // set event text + ObjectSetString(chartID, name, OBJPROP_TEXT, text); + + // + // set color + ObjectSetInteger(chartID, name, OBJPROP_COLOR, clr); + + // + // set anchor point width if the object is highlighted + ObjectSetInteger(chartID, name, OBJPROP_WIDTH, width); + + // + // display in the foreground false or background true + ObjectSetInteger(chartID, name, OBJPROP_BACK, back); + + // + // enable true or disable false the mode of moving event by mouse + ObjectSetInteger(chartID, name, OBJPROP_SELECTABLE, selection); + ObjectSetInteger(chartID, name, OBJPROP_SELECTED, selection); + + // + // hide true or display false graphical object name in the object list + ObjectSetInteger(chartID, name, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart + ObjectSetInteger(chartID, name, OBJPROP_ZORDER, zOrder); + + // + // successful execution + return result; +} + +// +// Change Event object text +bool EventTextChange( + const long chartID = 0, // chart's ID + const string name = "Event", // event name + const string text = "Content" // text +) +{ + // + bool result = false; + + // + // change object text + result = ObjectSetString(chartID, name, OBJPROP_TEXT, text); + + // + return result; +} + +// +// Move Event object +bool EventMove( + const long chartID = 0, // chart's ID + const string name = "Event", // event name + datetime time = 0 // time +) +{ + // + bool result = false; + + // + // if time is not set, move event to the last bar + if (!time) + { + time = TimeCurrent(); + } + + // + // move the object + result = ObjectMove(chartID, name, 0, time, 0); + + // + return result; +} + +// +// Delete Event object +bool EventDelete( + const long chartID = 0, // chart's ID + const string name = "Event" // event name +) +{ + // + bool result = false; + + // + // delete the object + result = ObjectDelete(chartID, name); + + // + return result; +} + +// +// Button Functions ... + +// +// Create the button ... +bool ButtonCreate( + const long chartID = 0, // chart's ID + const string name = "Button", // button name + const int subWindow = 0, // subwindow index + const int x = 0, // X coordinate + const int y = 0, // Y coordinate + const int width = 50, // button width + const int height = 15, // button height + const ENUM_BASE_CORNER corner = CORNER_LEFT_UPPER, // chart corner for anchoring + const string text = "Button", // text + const string font = "Arial", // font + const int fontSize = 8, // font size + const color clr = clrBlack, // text color + const color bgColor = clrLightGray, // background color + const color borderColor = clrNONE, // border color + const bool state = false, // pressed/released + const bool back = false, // in the background + const bool selection = false, // highlight to move + const bool hidden = true, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + bool result = false; + + // + // create the button + result = ObjectCreate(chartID, name, OBJ_BUTTON, subWindow, 0, 0); + if (!result) + { + return result; + } + + // + // set button coordinates + ObjectSetInteger(chartID, name, OBJPROP_XDISTANCE, x); + ObjectSetInteger(chartID, name, OBJPROP_YDISTANCE, y); + + // + // set button size + ObjectSetInteger(chartID, name, OBJPROP_XSIZE, width); + ObjectSetInteger(chartID, name, OBJPROP_YSIZE, height); + + // + // set the chart's corner, relative to which point coordinates are defined + ObjectSetInteger(chartID, name, OBJPROP_CORNER, corner); + + // + // set the text + ObjectSetString(chartID, name, OBJPROP_TEXT, text); + + // + // set text font + ObjectSetString(chartID, name, OBJPROP_FONT, font); + + // + // set font size + ObjectSetInteger(chartID, name, OBJPROP_FONTSIZE, fontSize); + + // + // set text color + ObjectSetInteger(chartID, name, OBJPROP_COLOR, clr); + + // + // set background color + ObjectSetInteger(chartID, name, OBJPROP_BGCOLOR, bgColor); + + // + // set border color + ObjectSetInteger(chartID, name, OBJPROP_BORDER_COLOR, borderColor); + + // + // display in the foreground false or background true + ObjectSetInteger(chartID, name, OBJPROP_BACK, back); + + // + // set button state + ObjectSetInteger(chartID, name, OBJPROP_STATE, state); + + // + // enable true or disable false the mode of moving the button by mouse + ObjectSetInteger(chartID, name, OBJPROP_SELECTABLE, selection); + ObjectSetInteger(chartID, name, OBJPROP_SELECTED, selection); + + // + // hide true or display false graphical object name in the object list + ObjectSetInteger(chartID, name, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart + ObjectSetInteger(chartID, name, OBJPROP_ZORDER, zOrder); + + // + return result; +} + +// +// Move the button ... +bool ButtonMove( + const long chartID = 0, // chart's ID + const string name = "Button", // button name + const int x = 0, // X coordinate + const int y = 0 // Y coordinate +) +{ + // + bool result = false; + + // + // move the button + + // + result = ObjectSetInteger(chartID, name, OBJPROP_XDISTANCE, x); + if (!result) + { + return result; + } + + // + result = ObjectSetInteger(chartID, name, OBJPROP_YDISTANCE, y); + + // + return result; +} + +// +// Change button size ... +bool ButtonChangeSize( + const long chartID = 0, // chart's ID + const string name = "Button", // button name + const int width = 50, // button width + const int height = 18 // button height +) +{ + // + bool result = false; + + // + // change the button size + + // + result = ObjectSetInteger(chartID, name, OBJPROP_XSIZE, width); + if (!result) + { + return result; + } + + // + result = ObjectSetInteger(chartID, name, OBJPROP_YSIZE, height); + + // + return result; +} + +// +// Change corner of the chart for binding the button ... +bool ButtonChangeCorner( + const long chartID = 0, // chart's ID + const string name = "Button", // button name + const ENUM_BASE_CORNER corner = CORNER_LEFT_UPPER // chart corner for anchoring +) +{ + // + bool result = false; + + // + // change anchor corner + result = ObjectSetInteger(chartID, name, OBJPROP_CORNER, corner); + + // + return result; +} + +// +// Change button text ... +bool ButtonTextChange( + const long chartID = 0, // chart's ID + const string name = "Button", // button name + const string text = "Text" // text +) +{ + // + bool result = false; + + // + // change object text + result = ObjectSetString(chartID, name, OBJPROP_TEXT, text); + + // + return result; +} + +// +// Delete the button ... +bool ButtonDelete( + const long chartID = 0, // chart's ID + const string name = "Button" // button name +) +{ + // + bool result = false; + + // + // delete the button + result = ObjectDelete(chartID, name); + + // + return result; +} + +// +// Chart Style Drawers ... + +// +// Apply Styles On Chart ... +void ApplyChartStyle( + long mChartId = -1, // chart's ID + ENUM_CHART_MODE mMode = CHART_CANDLES, // chart's mMode + bool mShowBidLine = true, // show bid line + bool mShowAskLine = true, // show ask line + bool mShowGrid = false, // show grids on chart + bool mShowVolumes = false, // show volumes + bool mShowTradeLevels = true, // Displaying trade levels in the chart (levels of open positions, Stop Loss, Take Profit and pending orders) + bool mAutoScroll = true, // chart autoscroll + bool mQuickNavigation = true, // chart quick navigation state + color mForeGroundColor = clrWhite, // chart's foreground color + color mBackGroundColor = clrBlack, // chart's background color + color mUpColor = clrGreen, // Up Color + color mDownColor = clrRed, // Down Color + color mBullishColor = clrGreen, // Bullish color + color mBearishColor = clrRed, // Bearish color + color mGridColor = clrGray, // grid color + color mBidLineColor = clrGray, // bid line color + color mAskLineColor = clrRed, // ask line color + color mLineColor = clrLime, // line mMode and doji candlestick color + color mStopColor = clrGold, // Color of stop order levels (Stop Loss and Take Profit) + color mVolumesColor = clrGreen // volumes color +) +{ + // + // Validate Args ... + if (mChartId == -1) + { + mChartId = 0; + } + + // + ChartSetInteger(mChartId, CHART_MODE, mMode); + ChartSetInteger(mChartId, CHART_SHOW_BID_LINE, mShowBidLine); + ChartSetInteger(mChartId, CHART_SHOW_ASK_LINE, mShowAskLine); + ChartSetInteger(mChartId, CHART_SHOW_GRID, mShowGrid); + ChartSetInteger(mChartId, CHART_SHOW_VOLUMES, mShowVolumes); + ChartSetInteger(mChartId, CHART_SHOW_TRADE_LEVELS, mShowTradeLevels); + ChartSetInteger(mChartId, CHART_AUTOSCROLL, mAutoScroll); + ChartSetInteger(mChartId, CHART_QUICK_NAVIGATION, mQuickNavigation); + ChartSetInteger(mChartId, CHART_COLOR_FOREGROUND, mForeGroundColor); + ChartSetInteger(mChartId, CHART_COLOR_BACKGROUND, mBackGroundColor); + ChartSetInteger(mChartId, CHART_COLOR_CHART_UP, mUpColor); + ChartSetInteger(mChartId, CHART_COLOR_CHART_DOWN, mDownColor); + ChartSetInteger(mChartId, CHART_COLOR_CANDLE_BULL, mBullishColor); + ChartSetInteger(mChartId, CHART_COLOR_CANDLE_BEAR, mBearishColor); + ChartSetInteger(mChartId, CHART_COLOR_GRID, mGridColor); + ChartSetInteger(mChartId, CHART_COLOR_BID, mBidLineColor); + ChartSetInteger(mChartId, CHART_COLOR_ASK, mAskLineColor); + ChartSetInteger(mChartId, CHART_COLOR_STOP_LEVEL, mStopColor); + ChartSetInteger(mChartId, CHART_COLOR_CHART_LINE, mLineColor); + ChartSetInteger(mChartId, CHART_COLOR_VOLUME, mVolumesColor); +} + +// +// Tools ... + +// +// Retrieve Chart Size ... +bool GetChartSize( + XSize &result, // Holds Result ... + long chartID = 0 // Specified Chart ID ... +) +{ + // + bool mResult = false; + + // + mResult = ChartGetInteger(0, CHART_WIDTH_IN_PIXELS, 0, result.width); + if (!mResult) + { + return mResult; + } + + // + mResult = ChartGetInteger(0, CHART_HEIGHT_IN_PIXELS, 0, result.height); + + // + return mResult; +} diff --git a/MQLTestWorkspace/BKPS/14030316/Libraries/x-saherelm.xtrade.lib.mq5 b/MQLTestWorkspace/BKPS/14030316/Libraries/x-saherelm.xtrade.lib.mq5 new file mode 100644 index 0000000..0ed7568 --- /dev/null +++ b/MQLTestWorkspace/BKPS/14030316/Libraries/x-saherelm.xtrade.lib.mq5 @@ -0,0 +1,4260 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Seriallize Library +// --------------------------------------- +// Name: XTradeLib +// Description: All models related to Trade ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include +#include "../Libraries/x-saherelm.draw.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" +#include "../Classes/x-saherelm.xdata-collector.class.mq5" + +// +// Definitions ... + +// +// a List of Used Tokens ... + +// +// Common ... +string XIDToken = "ID"; +string XTicketToken = "TK"; +string XModeToken = "MD"; +string XTypeToken = "TY"; +string XPeriodToken = "PR"; +string XProviderToken = "PRV"; +string XProfitToken = "PF"; + +// +string XTPToken = "TP"; +string XSLToken = "SL"; +string XTimeToken = "TM"; +string XEntryToken = "EN"; +string XVolumeToken = "VL"; +string XSymbolToken = "SMBL"; + +// +string XSupportToken = "SP"; +string XEQMSupportToken = "EQM"; + +// +string XSLTrailToken = "SLT"; + +// +string XActionToken = "A"; + +// +// Available Order Modes ... +enum ENUM_X_ORDER_MODES +{ + X_ORDER_MODE_NOTHING, // Nothing + X_ORDER_MODE_MARKET, // Market Order + X_ORDER_MODE_STOP, // Pending Stop Order + X_ORDER_MODE_LIMIT, // Pending Limit Order + X_ORDER_MODE_STOP_LIMIT, // Pending Stop Limit Order +}; + +// +// Select Positions Type ... +enum ENUM_X_POSITION_SELECT_METHODS +{ + X_POSITION_SELECT_NONE, // None + X_POSITION_SELECT_MAX, // Max + X_POSITION_SELECT_MIN, // Min + X_POSITION_SELECT_BOTH, // Min and Max + X_POSITION_SELECT_ALL, // All +}; + +// +// Signal Execution Result ... +// note that some of them must be handles in +// EA's ... +enum ENUM_X_SIGNAL_EXECUTION_RESULT +{ + // + X_SIGNAL_EXECUTION_UNKNOWN, // Unknown + X_SIGNAL_EXECUTION_SUCCEED, // Succed + X_SIGNAL_EXECUTION_FAILED_SPREAD, // Spread more than Max Allowed + X_SIGNAL_EXECUTION_FAILED_NO_EQUITY, // No Equity for Trade + X_SIGNAL_EXECUTION_FAILED_PRICE_ERROR, // Price Error + X_SIGNAL_EXECUTION_FAILED_MAX_REACHED, // Max Allowed Positions Reached + X_SIGNAL_EXECUTION_FAILED_INVALID_PARAMS, // Invalid Params +}; + +// +// Available Guard Action ... +enum ENUM_X_GUARD_ACTIONS +{ + X_GUARD_ACTION_NOTHING, // Nothing + X_GUARD_ACTION_HEDGE, // Hedge + X_GUARD_PARTIAL_CLOSE, // Partial Close + X_GUARD_ACTION_TRAIL_STOP, // Trail StopLoss + X_GUARD_ACTION_FORCE_CLOSE, // Force Close + X_GUARD_ACTION_ADD_SUPPORT_SIGNAL, // Add Support Signal + X_GUARD_ACTION_CANCEL_PENDING_ORDERS, // Cancel Pending Orders +}; + +// +// Structs ... + +// +// Model an Open Position ... +struct XPosition +{ + // + // Props ... + + // + // Magic Number ... + ulong magic; + + // + // Ticket ID ... + ulong ticket; + + // + // Tradinng Symbol ... + string symbol; + + // + // Trading Period ... + ENUM_TIMEFRAMES period; + + // + // Position Type ... + ENUM_POSITION_TYPE type; + + // + // Take Profit ... + double tp; + + // + // Stop Loss ... + double sl; + + // + // Position Current Profit ... + double profit; + + // + // Position Open Price ... + double entry; + + // + // Current Symbol Price ... + double price; + + // + // Position Swap ... + double swap; + + // + // Position Commission ... + double commission; + + // + // Volume ... + double volume; + + // + // Position Open Time ... + datetime openAt; + + // + // Sifnal Provider ... + string provider; + + // + // Position Comment ... + string comment; + + // + // Constructor ... + XPosition() + { + Clean(); + } + + // + // Initializers ... + + bool ByIndex(int index) + { + // + bool result = false; + + // + static CPositionInfo mPositionInfo; + + // + result = mPositionInfo.SelectByIndex(index); + if (!result) + { + return result; + } + + // + ulong mTicket = mPositionInfo.Ticket(); + + // + result = ByTicket(mTicket); + + // + return result; + } + + bool ByTicket(ulong mTicket) + { + // + bool result = false; + + // + static CPositionInfo mPositionInfo; + + // + result = mPositionInfo.SelectByTicket(mTicket); + if (!result) + { + return result; + } + + // + swap = mPositionInfo.Swap(); + magic = mPositionInfo.Magic(); + openAt = mPositionInfo.Time(); + sl = mPositionInfo.StopLoss(); + ticket = mPositionInfo.Ticket(); + symbol = mPositionInfo.Symbol(); + tp = mPositionInfo.TakeProfit(); + profit = mPositionInfo.Profit(); + volume = mPositionInfo.Volume(); + comment = mPositionInfo.Comment(); + entry = mPositionInfo.PriceOpen(); + type = mPositionInfo.PositionType(); + price = mPositionInfo.PriceCurrent(); + commission = mPositionInfo.Commission(); + + // + period = ExtractPeriod(comment); + provider = ExtractProvider(comment); + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + magic = 0; + ticket = 0; + tp = 0; + sl = 0; + swap = 0; + entry = 0; + price = 0; + profit = 0; + volume = 0; + openAt = 0; + commission = 0; + + // + type = NULL; + period = NULL; + + // + symbol = NULL; + comment = NULL; + provider = NULL; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsValid(symbol) && + NotEmpty(ticket) + // + ; + + // + return result; + } + + // + // Retrieve Entry Price ... + double GetEntry() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetEntry( + symbol, + type + // + ); + + // + return result; + } + + // + // Retrieve Exit ... + double GetExit() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetExit( + symbol, + type + // + ); + + // + return result; + } + + // + // Get Spread by Point ... + double GetSpread() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = PriceToPoint(GetSpread(symbol)); + + // + return result; + } + + // + // Find Risk ... + double GetRisk() + { + // + double result = 0; + + // + if (!IsValid()) + { + return 0; + } + + // + result = MathAbs(entry - sl); + + // + return result; + } + + // + // Find Reward ... + double GetReward() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = MathAbs(tp - entry); + + // + return result; + } + + // + // Find Risk Reward Ratio ... + double GetRiskRewardRatio() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetReward() / GetRisk(); + + // + return result; + } + + // + // Calculate Age ... + int GetAge( + ENUM_TIMEFRAMES mPeriod // Calculate Age based on this period + ) + { + return GetAge(this, mPeriod); + } + + // + // Check this instance is Same os Given instance or not ... + bool IsSameAs( + const XPosition &value // instance for Compare + ) + { + // + bool result = false; + + // + result = + // + type == value.type && + magic == value.magic && + entry == value.entry && + ticket == value.ticket && + volume == value.volume && + symbol == value.symbol && + provider == value.provider + // + ; + + // + return result; + } + + // + // Find index in a Collection ... + int FindIndex( + const XPosition &values[] // Collection to Find + ) + { + // + return FindIndex( + this, + values + // + ); + } + + // + // Check Items Passed Specific Filters or not ... + bool IsFiltersPassed( + string mSymbol = NULL, // Trading Symbol + string mProvider = NULL, // Signal Provider + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Timeframe + ENUM_POSITION_TYPE mType = NULL, // Long (Buy), Short (Sell) + ulong mMagic = NULL, // Magic Number + bool mFilterByMagic = true // Get Only Self Open Positions + ) + { + // + bool result = false; + + // + result = + // + // Magic Filter ... + IsMagicFilterPassed( + mMagic, + mFilterByMagic, + this + // + ) + // + && + // + // Symbol Filter ... + IsSymbolFilterPassed( + mSymbol, + this + // + ) + // + && + // + // Provider Filter ... + IsProviderFilterPassed( + mProvider, + this + // + ) + // + && + // + // Period Filter ... + IsPeriodFilterPassed( + mPeriod, + this + // + ) + // + && + // + // Type Filter ... + IsTypeFilterPassed( + mType, + this + // + ) + // + ; + + // + return result; + } +}; + +// +// Model a Signal ... +struct XSignal +{ + // + // Props ... + + // + ulong positionId; // if Executed this filled ... + + // + datetime time; // Issue Time ... + + // + double tp; // Take Profit ... + double sl; // Stop Loss ... + double entry; // Exntry or Execution Price ... + double volume; // Position Volume ... + + // + string symbol; // Trading Symbol ... + string comment; // Comment ... + string provider; // Signaller ... + + // + ENUM_TIMEFRAMES period; // Trading TimeFrame ... + ENUM_POSITION_TYPE type; // Long (Buy) or Short (Sell) ... + ENUM_X_ORDER_MODES mode; // Execution Mode ... + + // + XSignal supports[]; // a Collecion of Support Signals ... + + // + // Constructor ... + XSignal() + { + Clean(); + } + + // + bool Prepare( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + ENUM_POSITION_TYPE mType, // Long (Buy) or Short (Sell) + ENUM_X_ORDER_MODES mMode, // Execution Mode + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + bool result = false; + + // + result = + // + IsValid(mMode) && + IsValid(mSymbol) && + IsValid(mPeriod) && + NotEmpty(mEntry) && + NotEmpty(mVolume) && + IsValid(mProvider) + // + ; + if (!result) + { + return result; + } + + // + if (mTP < 0) + { + mTP = 0; + } + + // + if (mSL < 0) + { + mSL = 0; + } + + // + type = mType; + mode = mMode; + symbol = mSymbol; + period = mPeriod; + provider = mProvider; + + // + // Normalization Values ... + sl = NormalizePrice(mSL, mSymbol); + tp = NormalizePrice(mTP, mSymbol); + mEntry = NormalizePrice(mEntry, mSymbol); + mVolume = NormalizeVolume(mVolume, mSymbol); + + // + entry = mEntry; + volume = mVolume; + + // + result = Normalize(); + + // + return result; + } + + // + bool PrepareLong( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + ENUM_X_ORDER_MODES mMode, // Execution Mode + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + return Prepare( + mSymbol, + mProvider, + mPeriod, + POSITION_TYPE_BUY, + mMode, + mEntry, + mVolume, + mSL, + mTP + // + ); + } + + // + bool PrepareShort( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + ENUM_X_ORDER_MODES mMode, // Execution Mode + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + return Prepare( + mSymbol, + mProvider, + mPeriod, + POSITION_TYPE_SELL, + mMode, + mEntry, + mVolume, + mSL, + mTP + // + ); + } + + // + // Market Mode ... + + // + bool PrepareMarketLong( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + return PrepareLong( + mSymbol, + mProvider, + mPeriod, + X_ORDER_MODE_MARKET, + mEntry, + mVolume, + mSL, + mTP + // + ); + } + + // + bool PrepareMarketShort( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + return PrepareShort( + mSymbol, + mProvider, + mPeriod, + X_ORDER_MODE_MARKET, + mEntry, + mVolume, + mSL, + mTP + // + ); + } + + // + // Stop Mode ... + + // + bool PrepareStopLong( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + return PrepareLong( + mSymbol, + mProvider, + mPeriod, + X_ORDER_MODE_STOP, + mEntry, + mVolume, + mSL, + mTP + // + ); + } + + // + bool PrepareStopShort( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + return PrepareShort( + mSymbol, + mProvider, + mPeriod, + X_ORDER_MODE_STOP, + mEntry, + mVolume, + mSL, + mTP + // + ); + } + + // + // Limit Mode ... + + // + bool PrepareLimitLong( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + return PrepareLong( + mSymbol, + mProvider, + mPeriod, + X_ORDER_MODE_LIMIT, + mEntry, + mVolume, + mSL, + mTP + // + ); + } + + // + bool PrepareLimitShort( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + return PrepareShort( + mSymbol, + mProvider, + mPeriod, + X_ORDER_MODE_LIMIT, + mEntry, + mVolume, + mSL, + mTP + // + ); + } + + // + // Generate Opposit Direction ... + bool GenerateOpposit( + XSignal &mSignal // Oppsoit Signal + ) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + ENUM_POSITION_TYPE mType = GetOpposit(this.type); + double mEntry = GetExit(this.symbol, mType); + + // + bool isLong = IsLong(mType); + + // + // Calculate Risk Reward Ratio ... + double risk = GetRisk(); + double reward = GetReward(); + + // + double mSL = isLong + ? mEntry - risk + : mEntry + risk; + + // + double mTP = isLong + ? mEntry + reward + : mEntry - reward; + + // + result = mSignal.Prepare( + this.symbol, + this.provider, + this.period, + mType, + this.mode, + mEntry, + this.volume, + mSL, + mTP // + ); + + // + return result; + } + + // + // Prepare Opposit Signal based On a Position ... + bool PrepareOpposit( + XPosition &source // Source Data + ) + { + // + bool result = false; + + // + ENUM_POSITION_TYPE mType = GetOpposit(source.type); + double mEntry = GetEntry(source.symbol, mType); + + // + bool isLong = IsLong(mType); + + // + double risk = source.GetRisk(); + double reward = source.GetReward(); + + // + double mSL = isLong + ? mEntry - risk + : mEntry + risk; + + // + double mTP = isLong + ? mEntry + reward + : mEntry - reward; + + // + return Prepare( + source.symbol, + source.provider, + source.period, + mType, + X_ORDER_MODE_MARKET, + mEntry, + source.volume, + mSL, + mTP // + ); + + // + result = IsValid(); + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + entry = 0; + volume = 0; + positionId = 0; + + // + time = NULL; + type = NULL; + mode = NULL; + symbol = NULL; + period = NULL; + comment = NULL; + provider = NULL; + + // + Clean(supports); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsValid(period) && + IsValid(symbol) && + NotEmpty(volume) && + NotEmpty(entry) + // + ; + + // + if (!result) + { + return result; + } + + // + return result; + } + + // + // DO All Calculations and Normalizations ... + bool Normalize() + { + // + bool result = false; + + // + // Normalizations ... + symbol = NormalizeSymbol(symbol); + period = NormalizePeriod(period); + + // + time = NormalizeTime(time); + + // + sl = NormalizePrice(sl, symbol); + tp = NormalizePrice(tp, symbol); + entry = NormalizePrice(entry, symbol); + volume = NormalizeVolume(volume, symbol); + + // + result = IsValid(); + + // + return result; + } + + // + // Check Signal Executed or not ... + bool IsExecuted() + { + // + bool result = false; + + // + result = + // + IsValid() && + NotEmpty(positionId) + // + ; + + // + return result; + } + + // + // Generate Comment for Signal ... + string GenerateComment() + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + if (IsValid(provider)) + { + // + // Generate Provider Tag ... + result += GenerateProviderTag(provider); + } + + // + if (IsValid(period)) + { + // + // Generate Period Tag ... + result += GeneratePeriodTag(period); + } + + // + return result; + } + + // + int GetAge() + { + // + return GetAge( + this, + this.period // + ); + } + + // + // Retrieve Entry Price ... + double GetEntry() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetEntry( + symbol, + type + // + ); + + // + return result; + } + + // + // Retrieve Exit ... + double GetExit() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetExit( + symbol, + type + // + ); + + // + return result; + } + + // + // Get Spread by Point ... + double GetSpread() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = PriceToPoint(GetSpread(symbol)); + + // + return result; + } + + // + // Find Risk ... + double GetRisk() + { + // + double result = 0; + + // + if (!IsValid()) + { + return 0; + } + + // + result = MathAbs(entry - sl); + + // + return result; + } + + // + // Find Reward ... + double GetReward() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = MathAbs(tp - entry); + + // + return result; + } + + // + // Find Risk Reward Ratio ... + double GetRiskRewardRatio() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetReward() / GetRisk(); + + // + return result; + } + + // + // Data Collecotr ... + + // + // Check this instance is Same os Given instance or not ... + bool IsSameAs( + const XSignal &value // instance for Compare + ) + { + // + bool result = false; + + // + result = + // + type == value.type && + mode == value.mode && + entry == value.entry && + period == value.period && + symbol == value.symbol && + provider == value.provider && + positionId == value.positionId + // + ; + + // + return result; + } + + // + // Find index in a Collection ... + int FindIndex( + const XSignal &values[] // Collection to Find + ) + { + // + return FindIndex( + this, + values + // + ); + } + + // + // Check Items Passed Specific Filters or not ... + bool IsFiltersPassed( + string mSymbol = NULL, // Trading Symbol + string mProvider = NULL, // Signal Provider + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Timeframe + ENUM_POSITION_TYPE mType = NULL, // Long (Buy), Short (Sell) + ENUM_X_ORDER_MODES mMode = NULL // Execution Mode + ) + { + // + bool result = false; + + // + result = + // + // Symbol Filter ... + IsSymbolFilterPassed( + mSymbol, + this + // + ) + // + && + // + // Provider Filter ... + IsProviderFilterPassed( + mProvider, + this + // + ) + // + && + // + // Period Filter ... + IsPeriodFilterPassed( + mPeriod, + this + // + ) + // + && + // + // Type Filter ... + IsTypeFilterPassed( + mType, + this + // + ) + // + && + // + // Mode Filter ... + IsModeFilterPassed( + mMode, + this + // + ) + // + ; + + // + return result; + } + + // + string GetToken() + { + return GetToken(this); + } + + // + bool IsModelValid() + { + return IsValid(); + } + + // + // To String Representation ... + string ToModelString() + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + // For Modeling a Signal we Only Used: + // - Period; + // - Provider; + // - Type; + // - Mode; + // - Symbol; + // - PositionID; + // - Entry; + // - Volume; + // - TPS; + // - SLS; + // - Issue Time; + + // + int iPeriodInt = (int)period; + + // + string tpsStr = Surround(XTPToken, tp); + string slsStr = Surround(XSLToken, sl); + string typeStr = Surround(XTypeToken, type); + string modeStr = Surround(XModeToken, mode); + string timeStr = Surround(XTimeToken, time); + string entryStr = Surround(XEntryToken, entry); + string SymbolStr = Surround(XSymbolToken, symbol); + string volumeStr = Surround(XVolumeToken, volume); + string positionIdStr = Surround(XIDToken, positionId); + string periodStr = Surround(XPeriodToken, iPeriodInt); + string providerStr = Surround(XProviderToken, provider); + + // + result = + // + GetToken() + + "[" + + // + periodStr + + providerStr + + typeStr + + modeStr + + SymbolStr + + positionIdStr + + entryStr + + volumeStr + + tpsStr + + slsStr + + timeStr + + // + "]" + // + ; + + // + return result; + } + + // + // Parse String Model and Fill Available + // Items ... + bool ParseModel(string value) + { + // + bool result = false; + + // + Clean(); + + // + if (!IsValid(value)) + { + return false; + } + + // + // For Modeling a Signal we Only Used: + // - Period; + // - Provider; + // - Type; + // - Mode; + // - Symbol; + // - PositionID; + // - Entry; + // - Volume; + // - TP; + // - SL; + // - Issue Time; + + // + tp = ParseDoubleSurrounded(value, XTPToken); + sl = ParseDoubleSurrounded(value, XSLToken); + positionId = ParseLongSurrounded(value, XIDToken); + entry = ParseDoubleSurrounded(value, XEntryToken); + volume = ParseDoubleSurrounded(value, XVolumeToken); + + // + time = ParseTimeSurrounded(value, XTimeToken); + symbol = ParseStringSurrounded(value, XSymbolToken); + provider = ParseStringSurrounded(value, XProviderToken); + type = ((ENUM_POSITION_TYPE)ParseIntSurrounded(value, XTypeToken)); + mode = ((ENUM_X_ORDER_MODES)ParseIntSurrounded(value, XModeToken)); + period = ((ENUM_TIMEFRAMES)ParseIntSurrounded(value, XPeriodToken)); + + // + // Validate ... + result = IsValid(); + ; + + // + return result; + } + + // + // Draw Signal on Chart ... + bool Draw( + long chartID, + int subWindow = 0, + string prefix = NULL, + color entryColor = clrGold, + color bullishColor = clrSpringGreen, + color bearishColor = clrTomato // + ) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + bool isLong = IsLong(this.type); + + // + prefix = + // + (!IsValid(prefix) ? "" : prefix) + + this.symbol + "_" + + ToString(this.period) + "_" + + this.provider + // + ; + + // + int age = this.GetAge(); + + // + // Retrieve Time ... + datetime time0 = iTime( + this.symbol, + this.period, + age // + ); + + // + // Retrieve 3 Time ... + datetime time3 = iTime( + this.symbol, + this.period, + age + 3 // + ); + + // + color posColor = isLong + ? bullishColor + : bearishColor; + color tpColor = bullishColor; + color slColor = bearishColor; + + // + ENUM_LINE_STYLE vLineStyle = STYLE_DOT; + ENUM_LINE_STYLE tpLineStyle = STYLE_SOLID; + ENUM_LINE_STYLE slLineStyle = STYLE_SOLID; + ENUM_LINE_STYLE entryLineStyle = STYLE_SOLID; + + // + int lineWidth = 2; + + // + // Vertical Line ... + string vlName = prefix + "_" + (string)time; + + // + result = DrawVerticalLine( + chartID, + vlName, + subWindow, + time0, + posColor, + vLineStyle, + lineWidth // + ); + if (!result) + { + return result; + } + + // + // TP ... + double profit = (MathAbs(this.tp - this.entry)) * this.volume; + string tpName = prefix + "_TP_" + (string)profit; + + // + result = DrawTrendLine( + chartID, + tpName, + subWindow, + time3, + this.tp, + time0, + this.tp, + tpColor, + tpLineStyle, + lineWidth // + ); + if (!result) + { + return result; + } + + // + // SL ... + double lost = (MathAbs(this.sl - this.entry)) * this.volume; + string slName = prefix + "_SL_" + (string)lost; + + // + result = DrawTrendLine( + chartID, + slName, + subWindow, + time3, + this.sl, + time0, + this.sl, + slColor, + slLineStyle, + lineWidth // + ); + if (!result) + { + return result; + } + + // + // ENTRY ... + string entryName = prefix + "_ENTRY_" + (string)lost; + + // + result = DrawTrendLine( + chartID, + entryName, + subWindow, + time3, + this.entry, + time, + this.entry, + entryColor, + entryLineStyle, + lineWidth // + ); + + // + return result; + } +}; + +// +// Model an Order ... +struct XOrder +{ + // + // Time of order placement ... + datetime setupAt; + + // + // Time of order expiration ... + datetime expiredAt; + + // + // Time of order execution or cancellation ... + datetime executedAt; + + // + // Order type ... + ENUM_ORDER_TYPE type; + + // + // Order state ... + ENUM_ORDER_STATE state; + + // + // Type of execution by remainder ... + ENUM_ORDER_TYPE_FILLING filling; + + // + // Order lifetime ... + ENUM_ORDER_TYPE_TIME lifetime; + + // + // Order ticket ... + ulong ticket; + + // + // Magic Number ... + long magic; + + // + // Position id, that is placed on order, + // when it is executed. Each executed order invokes a + // deal, that opens new or changes existing + // position. Id of that position is placed on + // executed order in this moment. + long positionId; + + // + // Initial volume on order placement ... + double initialVolume; + + // + // Unfilled volume ... + double currentVolume; + + // + // Price, specified in the order ... + double openPrice; + + // + // Current price by order symbol ... + double currentPrice; + + // + // Price of placing Limit order when StopLimit order is triggered ... + double stopLimitPrice; + + // + // Take Profit level ... + double tp; + + // + // Stop Loss level ... + double sl; + + // + // Trading Symbol ... + string symbol; + + // + // Signal Provider ... + string provider; + + // + // Order Comment ... + string comment; + + // + ENUM_TIMEFRAMES period; + + // + // Constructor ... + XOrder() + { + Clean(); + } + + // + // Initializers ... + bool ByIndex( + int index // Fill By Index ... + ) + { + // + bool result = false; + + // + int ordersCount = OrdersTotal(); + if (ordersCount <= 0) + { + return result; + } + + // + static COrderInfo mOrderInfo; + + // + result = mOrderInfo.SelectByIndex(index); + if (!result) + { + return result; + } + + // + // Reading Order Info ... + magic = mOrderInfo.Magic(); + sl = mOrderInfo.StopLoss(); + tp = mOrderInfo.TakeProfit(); + ticket = mOrderInfo.Ticket(); + openPrice = mOrderInfo.PriceOpen(); + positionId = mOrderInfo.PositionId(); + currentPrice = mOrderInfo.PriceCurrent(); + initialVolume = mOrderInfo.VolumeInitial(); + currentVolume = mOrderInfo.VolumeCurrent(); + stopLimitPrice = mOrderInfo.PriceStopLimit(); + + // + symbol = mOrderInfo.Symbol(); + comment = mOrderInfo.Comment(); + + // + state = mOrderInfo.State(); + type = mOrderInfo.OrderType(); + lifetime = mOrderInfo.TypeTime(); + filling = mOrderInfo.TypeFilling(); + + // + setupAt = mOrderInfo.TimeSetup(); + executedAt = mOrderInfo.TimeDone(); + expiredAt = mOrderInfo.TimeExpiration(); + + // + period = ExtractPeriod(comment); + provider = ExtractProvider(comment); + + // + result = IsValid(); + + // + return result; + } + + // + // Retrieve Specific History Order ... + bool HistoryByIndex( + int index // Fill By Index ... + ) + { + // + bool result = false; + + // + int ordersCount = HistoryOrdersTotal(); + if (ordersCount <= 0) + { + return result; + } + + // + static CHistoryOrderInfo mOrderInfo; + + // + result = mOrderInfo.SelectByIndex(index); + if (!result) + { + return result; + } + + // + // Reading Order Info ... + magic = mOrderInfo.Magic(); + sl = mOrderInfo.StopLoss(); + tp = mOrderInfo.TakeProfit(); + ticket = mOrderInfo.Ticket(); + openPrice = mOrderInfo.PriceOpen(); + positionId = mOrderInfo.PositionId(); + currentPrice = mOrderInfo.PriceCurrent(); + initialVolume = mOrderInfo.VolumeInitial(); + currentVolume = mOrderInfo.VolumeCurrent(); + stopLimitPrice = mOrderInfo.PriceStopLimit(); + + // + symbol = mOrderInfo.Symbol(); + comment = mOrderInfo.Comment(); + + // + state = mOrderInfo.State(); + type = mOrderInfo.OrderType(); + lifetime = mOrderInfo.TypeTime(); + filling = mOrderInfo.TypeFilling(); + + // + setupAt = mOrderInfo.TimeSetup(); + executedAt = mOrderInfo.TimeDone(); + expiredAt = mOrderInfo.TimeExpiration(); + + // + period = ExtractPeriod(comment); + provider = ExtractProvider(comment); + + // + result = IsValid(); + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + tp = 0; + sl = 0; + magic = 0; + ticket = 0; + positionId = 0; + openPrice = 0; + currentPrice = 0; + initialVolume = 0; + currentVolume = 0; + stopLimitPrice = 0; + + // + setupAt = NULL; + expiredAt = NULL; + executedAt = NULL; + + // + symbol = NULL; + comment = NULL; + provider = NULL; + + // + type = NULL; + state = NULL; + period = NULL; + filling = NULL; + lifetime = NULL; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsValid(symbol) && + NotEmpty(ticket) && + NotEmpty(positionId) + // + ; + + // + return result; + } + + // + // Calculate Age ... + int GetAge( + ENUM_TIMEFRAMES mPeriod // Calculate Age based on this period + ) + { + return GetAge(this, mPeriod); + } + + // + // Check this instance is Same os Given instance or not ... + bool IsSameAs( + const XOrder &value // instance for Compare + ) + { + // + bool result = false; + + // + result = + // + type == value.type && + state == value.state && + magic == value.magic && + ticket == value.ticket && + symbol == value.symbol && + provider == value.provider && + positionId == value.positionId + // + ; + + // + return result; + } + + // + // Find index in a Collection ... + int FindIndex( + const XOrder &values[] // Collection to Find + ) + { + // + return FindIndex( + this, + values + // + ); + } + + // + // Check Items Passed Specific Filters or not ... + bool IsFiltersPassed( + string mSymbol = NULL, // Trading Symbol + string mProvider = NULL, // Signal Provider + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Timeframe + ENUM_ORDER_TYPE mType = NULL, // Long (Buy), Short (Sell) + ENUM_ORDER_STATE mState = NULL, // Order State + ulong mMagic = NULL, // Magic Number + bool mFilterByMagic = true // Get Only Self Open Positions + ) + { + // + bool result = false; + + // + result = + // + // Magic Filter ... + IsMagicFilterPassed( + mMagic, + mFilterByMagic, + this + // + ) + // + && + // + // Symbol Filter ... + IsSymbolFilterPassed( + mSymbol, + this + // + ) + // + && + // + // Provider Filter ... + IsProviderFilterPassed( + mProvider, + this + // + ) + // + && + // + // Period Filter ... + IsPeriodFilterPassed( + mPeriod, + this + // + ) + // + && + // + // Type Filter ... + IsTypeFilterPassed( + mType, + this + // + ) + // + && + // + // State Filter ... + IsStateFilterPassed( + mState, + this + // + ) + // + ; + + // + return result; + } +}; + +// +// Model a Deal ... +struct XDeal +{ + // + // the ID of the Expert Advisor, that executed the deal ... + ulong magic; + + // + // the ID of position, in which the deal was involved ... + ulong positionId; + + // + // Ticket ... + ulong ticket; + + // + // the name of the deal symbol ... + string symbol; + + // + // order by which the deal is executed ... + ulong order; + + // + // the time of deal execution ... + datetime time; + + // + // Deal price ... + double price; + + // + // the financial result of the deal (in deposit currency) ... + double profit; + + // + // the amount of swap when position is closed ... + double swap; + + // + // the amount of commission of the deal ... + double commission; + + // + // the volume of deal ... + double volume; + + // + // the deal comment ... + string comment; + + // + string provider; + + // + ENUM_TIMEFRAMES period; + + // + // the deal type ... + // ------------------------------------------------------------------ + // DEAL_TYPE_BUY => Buy ... + // DEAL_TYPE_SELL => Sell ... + // DEAL_TYPE_BUY_CANCELED => Canceled buy deal ... + // There can be a situation when a previously executed buy deal is canceled. In this case, + // the type of the previously executed deal (DEAL_TYPE_BUY) is changed to DEAL_TYPE_BUY_CANCELED, + // and its profit/loss is zeroized. Previously obtained profit/loss is charged/withdrawn using a separated balance operation ... + // + // DEAL_TYPE_SELL_CANCELED => Canceled sell deal ... + // There can be a situation when a previously executed sell deal is canceled. In this case, + // the type of the previously executed deal (DEAL_TYPE_SELL) is changed to DEAL_TYPE_SELL_CANCELED, + // and its profit/loss is zeroized. Previously obtained profit/loss is charged/withdrawn using a separated balance operation + // + // DEAL_TYPE_BALANCE => Balance ... + // DEAL_TYPE_CREDIT => Credit ... + // DEAL_TYPE_CHARGE => Additional charge ... + // DEAL_TYPE_CORRECTION => Correction ... + // DEAL_TAX => Tax charges ... + // DEAL_TYPE_BONUS => Bonus ... + // DEAL_TYPE_INTEREST => Interest rate ... + // DEAL_DIVIDEND => Dividend operations... + // DEAL_DIVIDEND_FRANKED => Franked (non-taxable) dividend operations ... + // DEAL_TYPE_COMMISSION => Additional commission ... + // DEAL_TYPE_COMMISSION_DAILY => Daily commission ... + // DEAL_TYPE_COMMISSION_MONTHLY => Monthly commission ... + // DEAL_TYPE_COMMISSION_AGENT_DAILY => Daily agent commission ... + // DEAL_TYPE_COMMISSION_AGENT_MONTHLY => Monthly agent commission + ENUM_DEAL_TYPE type; + + // + // the deal direction ... + // ---------------------------------- + // DEAL_ENTRY_IN => Entry in ... + // DEAL_ENTRY_OUT => Entry out ... + // DEAL_ENTRY_INOUT => Reverse ... + // DEAL_ENTRY_OUT_BY => Close a position by an opposite one ... + ENUM_DEAL_ENTRY entry; + + // + // deal reson ... + // --------------------- + // DEAL_REASON_SL => The deal was executed as a result of Stop Loss activation ... + // DEAL_REASON_TP => The deal was executed as a result of Take Profit activation ... + // DEAL_REASON_SO => The deal was executed as a result of the Stop Out event ... + // DEAL_REASON_WEB => The deal was executed as a result of activation of an order placed from the web platform ... + // DEAL_REASON_SPLIT => The deal was executed after the split (price reduction) of an instrument, which had an open position during split announcement ... + // DEAL_REASON_CLIENT => The deal was executed as a result of activation of an order placed from a desktop terminal ... + // DEAL_REASON_MOBILE => The deal was executed as a result of activation of an order placed from a mobile application ... + // DEAL_REASON_EXPERT => The deal was executed as a result of activation of an order placed from an MQL5 program, i.e. an Expert Advisor or a script ... + // DEAL_REASON_VMARGIN => The deal was executed after charging the variation margin ... + // DEAL_REASON_ROLLOVER => The deal was executed due to a rollover ... + ENUM_DEAL_REASON reason; + + // + // Constructor ... + XDeal() + { + Clean(); + } + + // + // Initializers ... + bool ByIndex( + int index // Deal Index + ) + { + // + bool result = false; + + // + int dealsCount = HistoryDealsTotal(); + result = dealsCount > 0; + if (!result) + { + return result; + } + + // + static CDealInfo mDealInfo; + + // + result = mDealInfo.SelectByIndex(index); + if (!result) + { + // + return result; + } + + // + // Reading Order Info ... + swap = mDealInfo.Swap(); + magic = mDealInfo.Magic(); + order = mDealInfo.Order(); + ticket = mDealInfo.Ticket(); + time = mDealInfo.Time(); + price = mDealInfo.Price(); + symbol = mDealInfo.Symbol(); + profit = mDealInfo.Profit(); + volume = mDealInfo.Volume(); + comment = mDealInfo.Comment(); + positionId = mDealInfo.PositionId(); + entry = mDealInfo.Entry(); + commission = mDealInfo.Commission(); + type = mDealInfo.DealType(); + reason = (ENUM_DEAL_REASON)HistoryDealGetInteger( + ticket, + DEAL_REASON); + + // + period = ExtractPeriod(comment); + provider = ExtractProvider(comment); + + // + result = IsValid(); + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + magic = 0; + positionId = 0; + ticket = 0; + order = 0; + time = 0; + price = 0; + profit = 0; + swap = 0; + commission = 0; + volume = 0; + + // + symbol = NULL; + comment = NULL; + provider = NULL; + + // + type = NULL; + entry = NULL; + period = NULL; + reason = NULL; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsValid(symbol) && + NotEmpty(ticket) && + NotEmpty(positionId) + // + ; + + // + return result; + } + + // + // Calculate Age ... + int GetAge( + ENUM_TIMEFRAMES mPeriod // Calculate Age based on this period + ) + { + return GetAge(this, mPeriod); + } + + // + // Check this instance is Same os Given instance or not ... + bool IsSameAs( + const XDeal &value // instance for Compare + ) + { + // + bool result = false; + + // + result = + // + type == value.type && + magic == value.magic && + entry == value.entry && + reason == value.reason && + ticket == value.ticket && + volume == value.volume && + symbol == value.symbol && + provider == value.provider && + positionId == value.positionId + // + ; + + // + return result; + } + + // + // Find index in a Collection ... + int FindIndex( + const XDeal &values[] // Collection to Find + ) + { + // + return FindIndex( + this, + values + // + ); + } + + // + // Check Items Passed Specific Filters or not ... + bool IsFiltersPassed( + string mSymbol = NULL, // Trading Symbol + string mProvider = NULL, // Signal Provider + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Timeframe + ENUM_DEAL_TYPE mType = NULL, // Deal Type + ENUM_DEAL_ENTRY mEntry = NULL, // Deal Entry + ENUM_DEAL_REASON mReason = NULL, // Deal Reason + ulong mMagic = NULL, // Magic Number + bool mFilterByMagic = true // Get Only Self Open Positions + ) + { + // + bool result = false; + + // + result = + // + // Magic Filter ... + IsMagicFilterPassed( + mMagic, + mFilterByMagic, + this + // + ) + // + && + // + // Symbol Filter ... + IsSymbolFilterPassed( + mSymbol, + this + // + ) + // + && + // + // Provider Filter ... + IsProviderFilterPassed( + mProvider, + this + // + ) + // + && + // + // Period Filter ... + IsPeriodFilterPassed( + mPeriod, + this + // + ) + // + && + // + // Type Filter ... + IsTypeFilterPassed( + mType, + this + // + ) + // + && + // + // Entry Filter ... + IsEntryFilterPassed( + mEntry, + this + // + ) + // + && + // + // Reason Filter ... + IsReasonFilterPassed( + mReason, + this + // + ) + // + ; + + // + return result; + } +}; + +// +// Model OnTrade Event Handler Result on XCTrade Class ... +struct XOnTradeHandlerState +{ + // + bool hasNewDeal; + int newDeals; + + // + bool hasNewOrder; + int newOrders; + + // + bool hasNewPosition; + int newPositions; + + // + bool hasNewHistoryOrder; + int newHistoryOrders; + + // + // Constructor ... + XOnTradeHandlerState() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + hasNewDeal = false; + hasNewOrder = false; + hasNewPosition = false; + hasNewHistoryOrder = false; + + // + newDeals = 0; + newOrders = 0; + newPositions = 0; + newHistoryOrders = 0; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + ( + // + hasNewDeal + ? newDeals > 0 + : true + // + ) + // + && + // + ( + // + hasNewOrder + ? newOrders > 0 + : true + // + ) + // + && + // + ( + // + hasNewPosition + ? newPositions > 0 + : true + // + ) + // + && + // + ( + // + hasNewHistoryOrder + ? newHistoryOrders > 0 + : true + // + ) + // + ; + + // + return result; + } +}; + +// +// Model Guard Info ... +struct XGuard +{ + // + string symbol; // Trading Symbol ... + string provider; // Signal Provider ... + ENUM_TIMEFRAMES period; // Trading Timeframe ... + ENUM_POSITION_TYPE type; // Position Type ... + ENUM_X_GUARD_ACTIONS action; // Which Action to Do ... + + // + double dblPayLoad; + string strPayload; + + // + // Constructor ... + XGuard() + { + Clean(); + } + + // + // Initialize ... + + // + // Global Initializer ... + bool Init( + string mSymbol, // Trading Symbol ... + ENUM_TIMEFRAMES mPeriod, // Trading Timeframe ... + ENUM_X_GUARD_ACTIONS mAction, // Which Action to Do ... + ENUM_POSITION_TYPE mType = NULL, // Position Type ... + string mProvider = NULL, // Signal Provider ... + double mDblPayLoad = NULL, + string mStrPayload = NULL // + ) + { + // + type = mType; + symbol = mSymbol; + period = mPeriod; + action = mAction; + provider = mProvider; + dblPayLoad = mDblPayLoad; + strPayload = mStrPayload; + + // + bool result = IsValid(); + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + symbol = NULL; + provider = NULL; + period = NULL; + action = X_GUARD_ACTION_NOTHING; + + // + strPayload = NULL; + dblPayLoad = EMPTY_VALUE; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + action != X_GUARD_ACTION_NOTHING + // + ; + + // + return result; + } +}; + +// +// Model a Position with all of it's Supports ... +struct XPositionPack +{ + // + ulong ticket; // Main Position's Ticket + + // + XPosition position; // Main Position (if Exists) + + // + int supportOrdersCount; // Supported Orders (Untriggered) + int supportPositionsCount; // Supported Positions + + // + XOrder supportOrders[]; // Supported Orders (Untriggered) + XPosition supportPositions[]; // Supported Positions + + // + // Constructor ... + XPositionPack() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + ticket = 0; + + // + position.Clean(); + + // + supportOrdersCount = 0; + supportPositionsCount = 0; + + // + Clean(supportOrders); + Clean(supportPositions); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + NotEmpty(ticket) && + ( + // + supportOrdersCount > 0 + ? ArraySize(supportOrders) == supportOrdersCount + : true + // + ) + // + && + // + ( + // + supportPositionsCount > 0 + ? ArraySize(supportPositions) == supportPositionsCount + : true + // + ) + // + ; + + // + return result; + } +}; + +// +// Check Position SL Trails Structure ... +struct XTrail +{ + // + ulong ticket; // Position Ticket ... + ENUM_POSITION_TYPE type; // Type ... + datetime time; // Trail Time ... + double before; // SL Value Before Trailing ... + double after; // SL Value After Trailing ... + int level; // Number of Trails SL ... + double profit; // Profit in SL Time ... + + // + // Constructor ... + XTrail() + { + Clean(); + } + + // + // Tools ... + + // + bool Init( + ulong mTicket, // Ticket + ENUM_POSITION_TYPE mType, // Type + double mProfit, // Profit + double mBefore, // Before + double mAfter // After + ) + { + // + Clean(); + + // + type = mType; + after = mAfter; + ticket = mTicket; + before = mBefore; + profit = mProfit; + + // + level++; + + // + time = TimeCurrent(); + + // + return IsValid(); + } + + // + bool Update( + double mSl, // new SL ... + double mProfit // Profit + ) + { + // + bool result = false; + + // + time = TimeCurrent(); + + // + double cAfter = after; + after = mSl; + before = cAfter; + profit = mProfit; + + // + level++; + + // + result = IsValid(); + + // + return result; + } + + // + string GenerateTag() + { + // + string result = NULL; + + // + string ticketLevelStr = ToString(ticket) + "," + ToString(level); + + // + result = Surround( + XSLTrailToken, + ticketLevelStr // + ); + + // + return result; + } + + // + // Cleanup ... + void Clean() + { + // + ticket = 0; + time = 0; + before = 0; + after = 0; + level = 0; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + ticket > 0 && + time > 0 && + level > 0 + // + ; + + // + return result; + } +}; + +// +// TypeDefs ... + +// +typedef void (*TOnDealsChanged)(int count); + +// +typedef void (*TOnOrdersChanged)(int count); + +// +typedef void (*TOnPositionsChanged)(int count); + +// +typedef void (*TOnStopLoss)(const XDeal &deal); +typedef void (*TOnTakeProfit)(const XDeal &deal); + +// +typedef void (*TOnTradeStateChanged)(const XOnTradeHandlerState &state); + +// +// Classes ... + +// +// Create a Signal Specfic Data Collector ... +class XSCSignalCollector +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructor ... + void XSCSignalCollector() + { + // + XSCDataCollector mBase; + mBase.Clear(); + } + + // + // Deconstructor ... + + // + // Tools ... + + // + // Inheritanced Functions ... + + // + // Cleaning Store ... + void Clear() + { + // + XSCDataCollector mBase; + + // + mBase.Clear(); + } + + // + // Collect All Store ... + int Collect(XSignal &result[]) + { + // + int mResult = 0; + + // + XSCDataCollector mBase; + + // + mResult = mBase.Collect(result); + + // + return mResult; + } + + // + // Add Item To Store ... + bool Add(XSignal &item) + { + // + bool result = false; + + // + XSCDataCollector mBase; + + // + result = mBase.Add(item); + + // + return result; + } + + // + // Add Item(s) To Store ... + int Add(XSignal &items[]) + { + // + int result = 0; + + // + XSCDataCollector mBase; + + // + result = mBase.Add(items); + + // + return result; + } + + // + // Remove an Item from Store ... + bool Remove(XSignal &item) + { + // + bool result = false; + + // + XSCDataCollector mBase; + + // + result = mBase.Remove(item); + + // + return result; + } + + // + // Custom Functions ... + + // + int CollectSignals( + XSignal &result[], // Hold Result + string symbol = NULL, // Trading Symbol + string provider = NULL, // Signal Provider + ENUM_TIMEFRAMES period = NULL, // Trading Timeframe + ENUM_POSITION_TYPE type = NULL, // Long (Buy), Short (Sell) + ENUM_X_ORDER_MODES mode = NULL // Execution Mode + ) + { + // + int mResult = 0; + + // + XSignal signals[]; + int signalsCount = Collect(signals); + if (signalsCount <= 0) + { + return mResult; + } + + // + mResult = ArraySize(result); + + // + // Now we Have to Apply Filters ... + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = signals[i]; + + // + bool isFiltersPassed = + iSignal.IsFiltersPassed( + symbol, + provider, + period, + type, + mode + // + ); + if (!isFiltersPassed) + { + continue; + } + + // + AddRef( + iSignal, + result + // + ); + } + + // + return mResult; + } + + // + // Protected ... +protected: + // + // Tools ... + + // + // Private ... +private: + // + // Props ... + + // + // Tools ... +}; + +// +// Tools ... + +// +bool IsValid(ENUM_X_ORDER_MODES value) +{ + return value != X_ORDER_MODE_NOTHING; +} + +// +// Ages ... + +// +// Retrieve a Position Age ... +int GetAge( + XSignal &signal, // Selected Signal ... + ENUM_TIMEFRAMES period = NULL // Dest Time Frame ... +) +{ + // + int result = -1; + + // + if (period == NULL) + { + period = _Period; + } + + // + result = iBarShift( + signal.symbol, + period, + signal.time); + + // + return result; +} + +// +// Retrieve a Position Age ... +int GetAge( + XPosition &position, // Selected Position ... + ENUM_TIMEFRAMES period = NULL // Dest Time Frame ... +) +{ + // + int result = -1; + + // + if (period == NULL) + { + period = _Period; + } + + // + result = iBarShift( + position.symbol, + period, + position.openAt); + + // + return result; +} + +// +// Retrieve an Order Age ... +int GetAge( + XOrder &order, // Selected Order ... + ENUM_TIMEFRAMES period = NULL // Dest Time Frame ... +) +{ + // + int result = -1; + + // + if (period == NULL) + { + period = _Period; + } + + // + result = iBarShift( + order.symbol, + period, + order.setupAt); + + // + return result; +} + +// +// Retrieve a Deal Age ... +int GetAge( + XDeal &deal, // Selected Deal ... + ENUM_TIMEFRAMES period = NULL // Dest Time Frame ... +) +{ + // + int result = -1; + + // + if (period == NULL) + { + period = _Period; + } + + // + result = iBarShift( + deal.symbol, + period, + deal.time); + + // + return result; +} + +// +// Get Oldest Deal ... +int GetOldest( + XDeal &item, // Hold Result ... + XDeal &items[] // Source Array ... +) +{ + // + int result = -1; + + // + int itemsCount = ArraySize(items); + if (itemsCount <= 0) + { + return result; + } + + // + int tmpAge = 0; + XDeal tmpItem; + for (int i = 0; i < itemsCount; i++) + { + // + XDeal iItem = items[i]; + + // + int iAge = GetAge(iItem); + if (iAge > 0 && + (tmpAge == 0 || tmpAge < iAge)) + { + // + tmpAge = iAge; + tmpItem = iItem; + } + } + + // + if (tmpAge > 0) + { + // + result = tmpAge; + item = tmpItem; + } + + // + return result; +} + +// +// Get Youngest Deal ... +int GetYoungest( + XDeal &item, // Hold Result ... + XDeal &items[] // Source Array ... +) +{ + // + int result = -1; + + // + int itemsCount = ArraySize(items); + if (itemsCount <= 0) + { + return result; + } + + // + int tmpAge = 0; + XDeal tmpItem; + for (int i = 0; i < itemsCount; i++) + { + // + XDeal iItem = items[i]; + + // + int iAge = GetAge(iItem); + if (iAge > 0 && + (tmpAge == 0 || tmpAge > iAge)) + { + // + tmpAge = iAge; + tmpItem = iItem; + } + } + + // + if (tmpAge > 0) + { + // + result = tmpAge; + item = tmpItem; + } + + // + return result; +} + +// +// Get Oldest Order ... +int GetOldest( + XOrder &item, // Hold Result ... + XOrder &items[] // Source Array ... +) +{ + // + int result = -1; + + // + int itemsCount = ArraySize(items); + if (itemsCount <= 0) + { + return result; + } + + // + int tmpAge = 0; + XOrder tmpItem; + for (int i = 0; i < itemsCount; i++) + { + // + XOrder iItem = items[i]; + + // + int iAge = GetAge(iItem); + if (iAge > 0 && + (tmpAge == 0 || tmpAge < iAge)) + { + // + tmpAge = iAge; + tmpItem = iItem; + } + } + + // + if (tmpAge > 0) + { + // + result = tmpAge; + item = tmpItem; + } + + // + return result; +} + +// +// Get Youngest Order ... +int GetYoungest( + XOrder &item, // Hold Result ... + XOrder &items[] // Source Array ... +) +{ + // + int result = -1; + + // + int itemsCount = ArraySize(items); + if (itemsCount <= 0) + { + return result; + } + + // + int tmpAge = 0; + XOrder tmpItem; + for (int i = 0; i < itemsCount; i++) + { + // + XOrder iItem = items[i]; + + // + int iAge = GetAge(iItem); + if (iAge > 0 && + (tmpAge == 0 || tmpAge > iAge)) + { + // + tmpAge = iAge; + tmpItem = iItem; + } + } + + // + if (tmpAge > 0) + { + // + result = tmpAge; + item = tmpItem; + } + + // + return result; +} + +// +// Get Oldes Position ... +int GetOldest( + XPosition &item, // Hold Result ... + XPosition &items[] // Source Array ... +) +{ + // + int result = -1; + + // + int itemsCount = ArraySize(items); + if (itemsCount <= 0) + { + return result; + } + + // + int tmpAge = 0; + XPosition tmpItem; + for (int i = 0; i < itemsCount; i++) + { + // + XPosition iItem = items[i]; + + // + int iAge = GetAge(iItem); + if (iAge > 0 && + (tmpAge == 0 || tmpAge < iAge)) + { + // + tmpAge = iAge; + tmpItem = iItem; + } + } + + // + if (tmpAge > 0) + { + // + result = tmpAge; + item = tmpItem; + } + + // + return result; +} + +// +// Get Youngest Position ... +int GetYoungest( + XPosition &item, // Hold Result ... + XPosition &items[] // Source Array ... +) +{ + // + int result = -1; + + // + int itemsCount = ArraySize(items); + if (itemsCount <= 0) + { + return result; + } + + // + int tmpAge = 0; + XPosition tmpItem; + for (int i = 0; i < itemsCount; i++) + { + // + XPosition iItem = items[i]; + + // + int iAge = GetAge(iItem); + if (iAge > 0 && + (tmpAge == 0 || tmpAge > iAge)) + { + // + tmpAge = iAge; + tmpItem = iItem; + } + } + + // + if (tmpAge > 0) + { + // + result = tmpAge; + item = tmpItem; + } + + // + return result; +} + +// +// Check Filters ... + +// +// Magic Filter ... +template +bool IsMagicFilterPassed( + ulong magic, + bool filterByMagic, + T &item + // +) +{ + // + return !filterByMagic + ? true + : !NotEmpty(magic) + ? false + : magic == item.magic; +} + +// +// Symbol Filter ... +template +bool IsSymbolFilterPassed( + string symbol, + T &item + // +) +{ + // + return !IsValid(symbol) + ? true + : symbol == item.symbol; +} + +// +// Provider Filter ... +template +bool IsProviderFilterPassed( + string provider, + T &item + // +) +{ + // + return !IsValid(provider) + ? true + : provider == item.provider; +} + +// +// Period Filter ... +template +bool IsPeriodFilterPassed( + ENUM_TIMEFRAMES period, + T &item + // +) +{ + // + return !IsValid(period) + ? true + : period == item.period; +} + +// +// Type Filter ... +template +bool IsTypeFilterPassed( + ENUM_POSITION_TYPE type, + T &item + // +) +{ + // + return type == NULL + ? true + : type == item.type; +} +template +bool IsTypeFilterPassed( + ENUM_ORDER_TYPE type, + T &item + // +) +{ + // + return type == NULL + ? true + : type == item.type; +} +template +bool IsTypeFilterPassed( + ENUM_DEAL_TYPE type, + T &item + // +) +{ + // + return type == NULL + ? true + : type == item.type; +} + +// +// Mode Filter ... +template +bool IsModeFilterPassed( + ENUM_X_ORDER_MODES mode, + T &item + // +) +{ + // + return mode == NULL + ? true + : mode == item.mode; +} + +// +// Entry Filter ... +template +bool IsEntryFilterPassed( + ENUM_DEAL_ENTRY entry, + T &item + // +) +{ + // + return entry == NULL + ? true + : entry == item.entry; +} + +// +// Reason Filter ... +template +bool IsReasonFilterPassed( + ENUM_DEAL_REASON reason, + T &item + // +) +{ + // + return reason == NULL + ? true + : reason == item.reason; +} + +// +// State Filter ... +template +bool IsStateFilterPassed( + ENUM_ORDER_STATE state, + T &item + // +) +{ + // + return state == NULL + ? true + : state == item.state; +} + +// + +// +// Find Specific Item Index inside a Collection ... +template +int FindIndex( + T &item, // Item to Find + const T &items[] // Items for Search +) +{ + // + int result = -1; + + // + // Check Item Validation ... + if (!item.IsValid()) + { + return result; + } + + // + int itemsCount = ArraySize(items); + if (itemsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < itemsCount; i++) + { + // + T iItem = items[i]; + + // + // Validate Item ... + if (!iItem.IsValid()) + { + continue; + } + + // + bool isSame = item.IsSameAs(iItem); + if (isSame && result <= -1) + { + // + result = i; + break; + } + } + + // + return result; +} + +// +// +// Calculate Positions Profit Summary ... +double SpecifiedCalculatePositionsProfit( + XPosition &positions[] // Source +) +{ + // + double result = 0; + + // + int positionsCount = ArraySize(positions); + if (positionsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + result += iPosition.profit; + } + + // + return result; +} + +// +// Calculate Required Profit for Hedging ... +double SpecifiedCalculateRequiredProfitForHedge( + XPosition &positions[], // Source + double mMinProfitPerTrade, + double mMinProfitPerVolumeFactor // +) +{ + // + double result = 0; + + // + int positionsCount = ArraySize(positions); + if (positionsCount <= 0) + { + return result; + } + + // + bool isHedgingEnable = mMinProfitPerTrade > 0 && mMinProfitPerVolumeFactor > 0; + if (!isHedgingEnable) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + if (mMinProfitPerTrade > 0 && mMinProfitPerVolumeFactor > 0) + { + // + result += + ((iPosition.volume / mMinProfitPerVolumeFactor) * + mMinProfitPerTrade) + + (-1 * iPosition.swap); + } + } + + // + return result; +} + +// +bool SpecifiedIsPositionsReadyForHedge( + XPosition &positions[], // Source + double mMinProfitPerTrade, + double mMinProfitPerVolumeFactor // +) +{ + // + double profit = SpecifiedCalculatePositionsProfit(positions); + double requiredProfit = SpecifiedCalculateRequiredProfitForHedge( + positions, + mMinProfitPerTrade, + mMinProfitPerVolumeFactor // + ); + + // + bool result = requiredProfit > 0 + ? profit >= requiredProfit + : profit > requiredProfit; + + // + return result; +} + +// +// Retrieve String Representation ... +string ToString(ENUM_X_SIGNAL_EXECUTION_RESULT value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_SIGNAL_EXECUTION_UNKNOWN: + result = "Unknown"; + break; + + // + case X_SIGNAL_EXECUTION_SUCCEED: + result = "Succed"; + break; + + // + case X_SIGNAL_EXECUTION_FAILED_SPREAD: + result = "Spread more than Max Allowed"; + break; + + // + case X_SIGNAL_EXECUTION_FAILED_NO_EQUITY: + result = "No Equity for Trade"; + break; + + // + case X_SIGNAL_EXECUTION_FAILED_PRICE_ERROR: + result = "Price Error"; + break; + + // + case X_SIGNAL_EXECUTION_FAILED_MAX_REACHED: + result = "Max Allowed Positions Reached"; + break; + + // + case X_SIGNAL_EXECUTION_FAILED_INVALID_PARAMS: + result = "Invalid Params"; + break; + } + + // + return result; +} + +// +// Converts Position Type to Order Type ... +ENUM_ORDER_TYPE ToOrderType(ENUM_POSITION_TYPE value) +{ + // + bool isLong = IsLong(value); + + // + ENUM_ORDER_TYPE result = + isLong + ? ORDER_TYPE_BUY + : ORDER_TYPE_SELL; + + // + return result; +} + +// +// Tagging ... + +// +// Generate Specified Tag for Using in Comments ... +string GeneratePeriodTag(ENUM_TIMEFRAMES period) +{ + // + string strPeriod = ToString(period); + return Surround( + XPeriodToken, + strPeriod + // + ); +} + +// +// Extract Period from a Tagged string ... +ENUM_TIMEFRAMES ExtractPeriod(string value) +{ + // + ENUM_TIMEFRAMES result = NULL; + + // + string pStr = ParseStringSurrounded( + value, + XPeriodToken + // + ); + if (!IsValid(pStr)) + { + return result; + } + + // + result = ToPeriod(pStr); + + // + return result; +} + +// Generate Specified Tag for Using in Comments ... +string GenerateProviderTag(string provider) +{ + // + return Surround( + XProviderToken, + provider + // + ); +} + +// +// Extract Provider from a Tagged string ... +string ExtractProvider(string value) +{ + // + return ParseStringSurrounded( + value, + XProviderToken + // + ); +} + +// +// Generate Support Comment Tag ... +string GenerateSupportTag(ulong ticket) +{ + // + return Surround( + XSupportToken, + ticket + // + ); +} + +// +// Extract Support Positions from a Tagged string ... +ulong ExtractSupportedTicket(string value) +{ + // + return ParseLongSurrounded( + value, + XSupportToken + // + ); +} + +// +// Generate EQM Support Comment Tag ... +string GenerateEQMSupportTag(ulong ticket) +{ + // + return Surround( + XEQMSupportToken, + ticket + // + ); +} + +// +// Extract EQM Support Positions from a Tagged string ... +ulong ExtractEQMSupportedTicket(string value) +{ + // + return ParseLongSurrounded( + value, + XEQMSupportToken + // + ); +} + +// +// SL Trails ... + +// +// Extract SL Trail Level ... +int ExtractSLTrailLevel(string comment) +{ + // + int result = 0; + + // + if (!IsValid(comment)) + { + return result; + } + + // + result = ParseIntSurrounded( + comment, + XSLTrailToken + // + ); + + // + return result; +} + +// +// Generate SL Trail Comment Tag ... +string GenerateSLTrailTag(int level) +{ + // + string result = NULL; + + // + if (level <= 0) + { + return result; + } + + // + result = Surround( + XSLTrailToken, + level + // + ); + + // + return result; +} + +// +// Prepare SL Trail Comment ... +string PrepareSLTrailTag( + const string comment // Original Position Comment ... +) +{ + // + string result = NULL; + + // + int level = 0; + result = comment; + + // + // Check Comment Contains SL Trailing or not ... + int lastTrailLevel = ExtractSLTrailLevel(comment); + if (lastTrailLevel <= 0) + { + level++; + } + else + { + // + level = lastTrailLevel + 1; + string lastLevelStr = GenerateSLTrailTag(lastTrailLevel); + StringReplace( + result, + lastLevelStr, + "" + // + ); + } + + // + // Generate level Comment ... + string levelStr = GenerateSLTrailTag(level); + result += levelStr; + + // + return result; +} + +// +// EQM Support Orders ... + +// +int GenerateEQMOrders( + XSignal &orders[], // Result + XPosition &position, // Supported Position + XOHCLSupRes &supRes, // Data Source + bool longs = true, + bool shorts = true // +) +{ + // + int result = 0; + + // + Clean(orders); + + // + if (!supRes.IsValid() || + !position.IsValid()) + { + return result; + } + + // + if (longs) + { + // + double longLevels[]; + + // + Copy( + supRes.res, + longLevels // + ); + + // + double minSup = GetMin( + supRes.sup // + ); + if (minSup > 0) + { + // + Add( + minSup, + longLevels // + ); + } + + // + ArraySort(longLevels); + + // + if (ArraySize(longLevels) > 2) + { + // + for (int i = 0; i < ArraySize(longLevels) - 2; i++) + { + // + double iSL = longLevels[i]; + double iEntry = longLevels[i + 1]; + double iTP = longLevels[i + 2]; + + // + XSignal iSignal; + bool isPrepared = iSignal.PrepareStopLong( + position.symbol, + XEQMSupportToken, + position.period, + iEntry, + position.volume, + iSL, + iTP // + ); + if (isPrepared) + { + // + string comment = GenerateSupportTag(position.ticket); + iSignal.comment = comment; + + // + AddRef( + iSignal, + orders // + ); + } + } + } + } + + // + if (shorts) + { + // + double shortLevels[]; + + // + Copy( + supRes.sup, + shortLevels // + ); + + // + double maxRes = GetMax( + supRes.res // + ); + if (maxRes > 0) + { + // + Add( + maxRes, + shortLevels // + ); + } + + // + ArraySort(shortLevels); + ArrayReverse(shortLevels); + + // + if (ArraySize(shortLevels) > 2) + { + // + for (int i = 0; i < ArraySize(shortLevels) - 2; i++) + { + // + double iSL = shortLevels[i]; + double iEntry = shortLevels[i + 1]; + double iTP = shortLevels[i + 2]; + + // + XSignal iSignal; + bool isPrepared = iSignal.PrepareStopShort( + position.symbol, + XEQMSupportToken, + position.period, + iEntry, + position.volume, + iSL, + iTP // + ); + if (isPrepared) + { + // + string comment = GenerateSupportTag(position.ticket); + iSignal.comment = comment; + + // + AddRef( + iSignal, + orders // + ); + } + } + } + } + + // + result = ArraySize(orders); + + // + return result; +} + +// +// Count Positions from a Collection ... +void CountPositions( + const XPosition &positions[], + int &longs, + double &longProfits, + double &longVolumes, // + // + int &shorts, + double &shortProfits, + double &shortVolumes // +) +{ + // + longs = 0; + longProfits = 0; + longVolumes = 0; + + // + shorts = 0; + shortProfits = 0; + shortVolumes = 0; + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + bool isLong = IsLong(iPosition.type); + if (isLong) + { + // + longs++; + longProfits += iPosition.profit; + longVolumes = iPosition.volume; + } + else + { + // + shorts++; + shortProfits += iPosition.profit; + shortVolumes = iPosition.volume; + } + } +} \ No newline at end of file