From 2bba99ea882a7cb3ea2f47b1f7bc4d0199014137 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Fri, 6 Jun 2025 09:20:17 +0330 Subject: [PATCH] backup ... --- BKPS/14040316/.gitignore | 28 + BKPS/14040316/.gitkeep | 0 .../Classes/x-saherelm.base.class.mq5 | 101 + .../Classes/x-saherelm.x-account.class.mq5 | 398 + .../Classes/x-saherelm.x-alert.class.mq5 | 1438 ++++ .../Classes/x-saherelm.x-app-dialog.class.mq5 | 278 + .../x-saherelm.x-bar.analyser.class.mq5 | 3454 +++++++++ .../Classes/x-saherelm.x-cobject.class.mq5 | 3478 +++++++++ .../x-saherelm.x-data.collector.class.mq5 | 362 + .../Classes/x-saherelm.x-guard.class.mq5 | 2009 +++++ .../Classes/x-saherelm.x-helper.class.mq5 | 151 + .../Classes/x-saherelm.x-http.class.mq5 | 373 + .../Classes/x-saherelm.x-md5.class.mq5 | 445 ++ .../Classes/x-saherelm.x-poi.drawer.class.mq5 | 4385 +++++++++++ .../Classes/x-saherelm.x-rm.panel.class.mq5 | 1162 +++ .../Classes/x-saherelm.x-trade.class.mq5 | 3899 ++++++++++ .../Classes/x-saherelm.x-volume.class.mq5 | 792 ++ .../Documents/BKP/tmp.base.signal.class.mq5 | 214 + .../BKP/tmp.conditionalling.signalling.mq5 | 1433 ++++ .../BKP/x-saherelm.x-expert.class.mq5 | 967 +++ .../Documents/BKP/x-saherelm.x-poi.class.mq5 | 3513 +++++++++ .../BKP/x-saherelm.x.expert.class.mq5 | 1070 +++ BKPS/14040316/Documents/BKP/xcatb.test.ea.mq5 | 1181 +++ .../BKP/xcatbea.x-data.collector.class.mq5 | 209 + .../Diagrams/Position Protection.drawio | 279 + .../Helpers/x-saherelm.x121.x3ma.helper.mq5 | 1556 ++++ .../Helpers/x-saherelm.x121.xca.helper.mq5 | 5275 +++++++++++++ .../Helpers/x-saherelm.x121.xcatb.helper.mq5 | 5548 ++++++++++++++ .../Helpers/x-saherelm.x121.xcc.helper.mq5 | 259 + .../Helpers/x-saherelm.x121.xct.helper.mq5 | 241 + .../Helpers/x-saherelm.x121.xoscs.helper.mq5 | 3498 +++++++++ .../Indicators/x-saherelm.x121.x3ma.mq5 | 788 ++ .../Indicators/x-saherelm.x121.xatr.mq5 | 882 +++ .../Indicators/x-saherelm.x121.xca.mq5 | 2601 +++++++ .../Indicators/x-saherelm.x121.xcatb.mq5 | 2777 +++++++ .../Indicators/x-saherelm.x121.xcc.mq5 | 437 ++ .../Indicators/x-saherelm.x121.xche.mq5 | 624 ++ .../Indicators/x-saherelm.x121.xct.mq5 | 262 + .../Indicators/x-saherelm.x121.xczone.mq5 | 2452 ++++++ .../Indicators/x-saherelm.x121.xdelta.mq5 | 550 ++ .../Indicators/x-saherelm.x121.xdon.mq5 | 692 ++ .../Indicators/x-saherelm.x121.xhk.mq5 | 636 ++ .../Indicators/x-saherelm.x121.xich.mq5 | 625 ++ .../Indicators/x-saherelm.x121.xoscs.mq5 | 1026 +++ .../Indicators/x-saherelm.x121.xstr.mq5 | 812 ++ .../Indicators/x-saherelm.x121.xtb.mq5 | 2966 ++++++++ .../Indicators/x-saherelm.x121.xvolume.mq5 | 567 ++ .../Indicators/x-saherelm.x121.xvwap.mq5 | 712 ++ .../Indicators/x-saherelm.x121.xwz.mq5 | 2780 +++++++ .../14040316/Documents/JsModules/mqlHelper.js | 19 + .../Documents/JsModules/prepareXCATBEA.js | 35 + .../Documents/JsModules/x-color.tools.js | 506 ++ .../Documents/JsModules/x-file.tools.js | 887 +++ .../JsModules/x-mql-project.tools.js | 494 ++ .../Documents/JsModules/x-shell.tools.js | 219 + .../JsModules/x-type-detector.tools.js | 268 + .../Documents/JsModules/x-value.tools.js | 1528 ++++ BKPS/14040316/Documents/MQL5 VSCode.7z | Bin 0 -> 1998962 bytes .../Temlates/signalling.function.template.mq5 | 221 + .../Documents/Temlates/temp.pivot.detect.mq5 | 83 + .../Temlates/x-saherelm.x-ea.template.ea.mq5 | 542 ++ .../Temlates/x-saherelm.x-panel.ea.mq5 | 575 ++ .../Temlates/xwz.signal.senario.template.mq5 | 187 + .../X121XCATBEA_XAUUSDb_M5.x121.log.txt | 43 + .../XCATBEAInputs/inputs.config.filepath.txt | 1 + ...relm.xcatb.ea.base.optimization.inputs.set | Bin 0 -> 9618 bytes BKPS/14040316/Experts/x-saherelm.rr.tools.mq5 | 431 ++ .../Experts/x-saherelm.x121.xcatb.ea.mq5 | 635 ++ .../Helpers/x-saherelm.x121.xcatb.helper.mq5 | 6693 ++++++++++++++++ .../Helpers/x-saherelm.x121.xcc.helper.mq5 | 259 + .../Helpers/x-saherelm.x121.xct.helper.mq5 | 241 + .../Indicators/x-saherelm.x121.xcatb.mq5 | 2706 +++++++ .../Indicators/x-saherelm.x121.xcc.mq5 | 437 ++ .../Indicators/x-saherelm.x121.xct.mq5 | 262 + .../x-saherelm.common.extensions.lib.mq5 | 6759 +++++++++++++++++ .../Libraries/x-saherelm.common.lib.mq5 | 157 + .../x-saherelm.common.models.lib.mq5 | 392 + .../Libraries/x-saherelm.draw.lib.mq5 | 2626 +++++++ .../Libraries/x-saherelm.x-enums.lib.mq5 | 1251 +++ .../Libraries/x-saherelm.x-ohcl.lib.mq5 | 2003 +++++ .../x-saherelm.x-poi.extensions.lib.mq5 | 3804 ++++++++++ .../Libraries/x-saherelm.x-poi.lib.mq5 | 6083 +++++++++++++++ .../Libraries/x-saherelm.x-poi.state.lib.mq5 | 4680 ++++++++++++ .../Libraries/x-saherelm.x-trade.lib.mq5 | 5146 +++++++++++++ .../XCATBEA/Classes/xcatbea.expert.class.mq5 | 2956 +++++++ .../Classes/xcatbea.signaller.class.mq5 | 2147 ++++++ .../Classes/xcatbea.x-poi.detector.class.mq5 | 2738 +++++++ .../Classes/xcatbea.x-poi.drawer.class.mq5 | 1193 +++ .../Classes/xcatbea.x-trade.manager.class.mq5 | 3782 +++++++++ .../XCATBEA/Libraries/xcatbea.lib.mq5 | 2996 ++++++++ .../Libraries/xcatbea.signaller.lib.mq5 | 1404 ++++ .../xcatbea.x-poi.extensions.lib.mq5 | 83 + BKPS/14040316/compile.cmd | 26 + BKPS/14040316/mqlHelper.js | 19 + BKPS/14040316/package.json | 30 + BKPS/14040316/prepareXCATBEA.js | 35 + BKPS/14040316/x-mql-project.tools.js | 494 ++ 97 files changed, 138261 insertions(+) create mode 100644 BKPS/14040316/.gitignore create mode 100644 BKPS/14040316/.gitkeep create mode 100644 BKPS/14040316/Classes/x-saherelm.base.class.mq5 create mode 100644 BKPS/14040316/Classes/x-saherelm.x-account.class.mq5 create mode 100644 BKPS/14040316/Classes/x-saherelm.x-alert.class.mq5 create mode 100644 BKPS/14040316/Classes/x-saherelm.x-app-dialog.class.mq5 create mode 100644 BKPS/14040316/Classes/x-saherelm.x-bar.analyser.class.mq5 create mode 100644 BKPS/14040316/Classes/x-saherelm.x-cobject.class.mq5 create mode 100644 BKPS/14040316/Classes/x-saherelm.x-data.collector.class.mq5 create mode 100644 BKPS/14040316/Classes/x-saherelm.x-guard.class.mq5 create mode 100644 BKPS/14040316/Classes/x-saherelm.x-helper.class.mq5 create mode 100644 BKPS/14040316/Classes/x-saherelm.x-http.class.mq5 create mode 100644 BKPS/14040316/Classes/x-saherelm.x-md5.class.mq5 create mode 100644 BKPS/14040316/Classes/x-saherelm.x-poi.drawer.class.mq5 create mode 100644 BKPS/14040316/Classes/x-saherelm.x-rm.panel.class.mq5 create mode 100644 BKPS/14040316/Classes/x-saherelm.x-trade.class.mq5 create mode 100644 BKPS/14040316/Classes/x-saherelm.x-volume.class.mq5 create mode 100644 BKPS/14040316/Documents/BKP/tmp.base.signal.class.mq5 create mode 100644 BKPS/14040316/Documents/BKP/tmp.conditionalling.signalling.mq5 create mode 100644 BKPS/14040316/Documents/BKP/x-saherelm.x-expert.class.mq5 create mode 100644 BKPS/14040316/Documents/BKP/x-saherelm.x-poi.class.mq5 create mode 100644 BKPS/14040316/Documents/BKP/x-saherelm.x.expert.class.mq5 create mode 100644 BKPS/14040316/Documents/BKP/xcatb.test.ea.mq5 create mode 100644 BKPS/14040316/Documents/BKP/xcatbea.x-data.collector.class.mq5 create mode 100644 BKPS/14040316/Documents/Diagrams/Position Protection.drawio create mode 100644 BKPS/14040316/Documents/Helpers/x-saherelm.x121.x3ma.helper.mq5 create mode 100644 BKPS/14040316/Documents/Helpers/x-saherelm.x121.xca.helper.mq5 create mode 100644 BKPS/14040316/Documents/Helpers/x-saherelm.x121.xcatb.helper.mq5 create mode 100644 BKPS/14040316/Documents/Helpers/x-saherelm.x121.xcc.helper.mq5 create mode 100644 BKPS/14040316/Documents/Helpers/x-saherelm.x121.xct.helper.mq5 create mode 100644 BKPS/14040316/Documents/Helpers/x-saherelm.x121.xoscs.helper.mq5 create mode 100644 BKPS/14040316/Documents/Indicators/x-saherelm.x121.x3ma.mq5 create mode 100644 BKPS/14040316/Documents/Indicators/x-saherelm.x121.xatr.mq5 create mode 100644 BKPS/14040316/Documents/Indicators/x-saherelm.x121.xca.mq5 create mode 100644 BKPS/14040316/Documents/Indicators/x-saherelm.x121.xcatb.mq5 create mode 100644 BKPS/14040316/Documents/Indicators/x-saherelm.x121.xcc.mq5 create mode 100644 BKPS/14040316/Documents/Indicators/x-saherelm.x121.xche.mq5 create mode 100644 BKPS/14040316/Documents/Indicators/x-saherelm.x121.xct.mq5 create mode 100644 BKPS/14040316/Documents/Indicators/x-saherelm.x121.xczone.mq5 create mode 100644 BKPS/14040316/Documents/Indicators/x-saherelm.x121.xdelta.mq5 create mode 100644 BKPS/14040316/Documents/Indicators/x-saherelm.x121.xdon.mq5 create mode 100644 BKPS/14040316/Documents/Indicators/x-saherelm.x121.xhk.mq5 create mode 100644 BKPS/14040316/Documents/Indicators/x-saherelm.x121.xich.mq5 create mode 100644 BKPS/14040316/Documents/Indicators/x-saherelm.x121.xoscs.mq5 create mode 100644 BKPS/14040316/Documents/Indicators/x-saherelm.x121.xstr.mq5 create mode 100644 BKPS/14040316/Documents/Indicators/x-saherelm.x121.xtb.mq5 create mode 100644 BKPS/14040316/Documents/Indicators/x-saherelm.x121.xvolume.mq5 create mode 100644 BKPS/14040316/Documents/Indicators/x-saherelm.x121.xvwap.mq5 create mode 100644 BKPS/14040316/Documents/Indicators/x-saherelm.x121.xwz.mq5 create mode 100644 BKPS/14040316/Documents/JsModules/mqlHelper.js create mode 100644 BKPS/14040316/Documents/JsModules/prepareXCATBEA.js create mode 100644 BKPS/14040316/Documents/JsModules/x-color.tools.js create mode 100644 BKPS/14040316/Documents/JsModules/x-file.tools.js create mode 100644 BKPS/14040316/Documents/JsModules/x-mql-project.tools.js create mode 100644 BKPS/14040316/Documents/JsModules/x-shell.tools.js create mode 100644 BKPS/14040316/Documents/JsModules/x-type-detector.tools.js create mode 100644 BKPS/14040316/Documents/JsModules/x-value.tools.js create mode 100644 BKPS/14040316/Documents/MQL5 VSCode.7z create mode 100644 BKPS/14040316/Documents/Temlates/signalling.function.template.mq5 create mode 100644 BKPS/14040316/Documents/Temlates/temp.pivot.detect.mq5 create mode 100644 BKPS/14040316/Documents/Temlates/x-saherelm.x-ea.template.ea.mq5 create mode 100644 BKPS/14040316/Documents/Temlates/x-saherelm.x-panel.ea.mq5 create mode 100644 BKPS/14040316/Documents/Temlates/xwz.signal.senario.template.mq5 create mode 100644 BKPS/14040316/Documents/XCATBEAInputs/X121XCATBEA_XAUUSDb_M5.x121.log.txt create mode 100644 BKPS/14040316/Documents/XCATBEAInputs/inputs.config.filepath.txt create mode 100644 BKPS/14040316/Documents/XCATBEAInputs/x-saherelm.xcatb.ea.base.optimization.inputs.set create mode 100644 BKPS/14040316/Experts/x-saherelm.rr.tools.mq5 create mode 100644 BKPS/14040316/Experts/x-saherelm.x121.xcatb.ea.mq5 create mode 100644 BKPS/14040316/Helpers/x-saherelm.x121.xcatb.helper.mq5 create mode 100644 BKPS/14040316/Helpers/x-saherelm.x121.xcc.helper.mq5 create mode 100644 BKPS/14040316/Helpers/x-saherelm.x121.xct.helper.mq5 create mode 100644 BKPS/14040316/Indicators/x-saherelm.x121.xcatb.mq5 create mode 100644 BKPS/14040316/Indicators/x-saherelm.x121.xcc.mq5 create mode 100644 BKPS/14040316/Indicators/x-saherelm.x121.xct.mq5 create mode 100644 BKPS/14040316/Libraries/x-saherelm.common.extensions.lib.mq5 create mode 100644 BKPS/14040316/Libraries/x-saherelm.common.lib.mq5 create mode 100644 BKPS/14040316/Libraries/x-saherelm.common.models.lib.mq5 create mode 100644 BKPS/14040316/Libraries/x-saherelm.draw.lib.mq5 create mode 100644 BKPS/14040316/Libraries/x-saherelm.x-enums.lib.mq5 create mode 100644 BKPS/14040316/Libraries/x-saherelm.x-ohcl.lib.mq5 create mode 100644 BKPS/14040316/Libraries/x-saherelm.x-poi.extensions.lib.mq5 create mode 100644 BKPS/14040316/Libraries/x-saherelm.x-poi.lib.mq5 create mode 100644 BKPS/14040316/Libraries/x-saherelm.x-poi.state.lib.mq5 create mode 100644 BKPS/14040316/Libraries/x-saherelm.x-trade.lib.mq5 create mode 100644 BKPS/14040316/XCATBEA/Classes/xcatbea.expert.class.mq5 create mode 100644 BKPS/14040316/XCATBEA/Classes/xcatbea.signaller.class.mq5 create mode 100644 BKPS/14040316/XCATBEA/Classes/xcatbea.x-poi.detector.class.mq5 create mode 100644 BKPS/14040316/XCATBEA/Classes/xcatbea.x-poi.drawer.class.mq5 create mode 100644 BKPS/14040316/XCATBEA/Classes/xcatbea.x-trade.manager.class.mq5 create mode 100644 BKPS/14040316/XCATBEA/Libraries/xcatbea.lib.mq5 create mode 100644 BKPS/14040316/XCATBEA/Libraries/xcatbea.signaller.lib.mq5 create mode 100644 BKPS/14040316/XCATBEA/Libraries/xcatbea.x-poi.extensions.lib.mq5 create mode 100644 BKPS/14040316/compile.cmd create mode 100644 BKPS/14040316/mqlHelper.js create mode 100644 BKPS/14040316/package.json create mode 100644 BKPS/14040316/prepareXCATBEA.js create mode 100644 BKPS/14040316/x-mql-project.tools.js diff --git a/BKPS/14040316/.gitignore b/BKPS/14040316/.gitignore new file mode 100644 index 0000000..8f784cf --- /dev/null +++ b/BKPS/14040316/.gitignore @@ -0,0 +1,28 @@ +# +Logs +Files +Images +Include +Scripts +Profiles +Experts/Advisors +Experts/Examples +Experts/Free Robots +Indicators/Examples +Indicators/Free Indicators + +# +experts.dat +*.ex5 +*.log + +# +node_modules +package-lock.json + +# +.VSCodeCounter + +# +Packs/* +!Packs/.gitkeep diff --git a/BKPS/14040316/.gitkeep b/BKPS/14040316/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/BKPS/14040316/Classes/x-saherelm.base.class.mq5 b/BKPS/14040316/Classes/x-saherelm.base.class.mq5 new file mode 100644 index 0000000..0e7557f --- /dev/null +++ b/BKPS/14040316/Classes/x-saherelm.base.class.mq5 @@ -0,0 +1,101 @@ +/////////////////////////////////////////////////////// +// +// 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 XCBase +{ + // + // Public ... + public: + // + // Protected ... + + // + // Represent Basic Unique Tag ... + virtual string GetTag() { + return NULL; + } + + // + // Retrieve Class Token ... + virtual string GetToken() { + return NULL; + } + + // + // Protected + protected: + // + // Private ... + private: +}; + +// +template +string GenerateSpecifiedCommonSummary( + T &mItem, + string separator = "\n", + bool includeScores = true, + bool setLabel = false // +) +{ + // + string result = NULL; + + // + double bullishScore = 0; + double bearishScore = 0; + mItem.GenerateScore( + bullishScore, + bearishScore // + ); + + // + result = + // + (!setLabel + ? "" + : "Commons:" + separator) + + "---------------" + separator + + "Symbol: " + mItem.symbol + separator + + "Period: " + ToString(mItem.period) + separator + + "Time: " + ToString(mItem.time) + separator + + (includeScores + ? "---------------" + separator + + "Scores:" + separator + + "---------------" + separator + + "Bullish: " + ToString(bullishScore) + separator + + "Bearish: " + ToString(bearishScore) + separator + + "---------------" + separator + : "") + + "" + // + ; + + // + return result; +} + +// diff --git a/BKPS/14040316/Classes/x-saherelm.x-account.class.mq5 b/BKPS/14040316/Classes/x-saherelm.x-account.class.mq5 new file mode 100644 index 0000000..c451091 --- /dev/null +++ b/BKPS/14040316/Classes/x-saherelm.x-account.class.mq5 @@ -0,0 +1,398 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCAccount +// Description: provides all Account 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 ... +// + +// +// END Definitions ... +// + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "../Classes/x-saherelm.base.class.mq5" +#include + +// +// END Import and Inclused requirements ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +// +// a Class for Manage Account ... +class XCAccount : public XCBase +{ + // + // Public ... + public: + // + // Constructor ... + void XCAccount() + { + // + mAccountInfo = new CAccountInfo(); + } + + // + // Deconstructor ... + void ~XCAccount() + { + } + + // + // 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/BKPS/14040316/Classes/x-saherelm.x-alert.class.mq5 b/BKPS/14040316/Classes/x-saherelm.x-alert.class.mq5 new file mode 100644 index 0000000..914d8bf --- /dev/null +++ b/BKPS/14040316/Classes/x-saherelm.x-alert.class.mq5 @@ -0,0 +1,1438 @@ +/////////////////////////////////////////////////////// +// +// 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" +#include "../Classes/x-saherelm.x-data.collector.class.mq5" + +// +// Class Definition ... + +class XCAlert : public XCBase +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructor ... + XCAlert( + 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 + bool saveAlerts = false // Save Alerts + ) + { + // + mPrefix = prefix; + mLogAlerts = logAlerts; + mMailAlerts = mailAlerts; + mPushAlerts = pushAlerts; + mSaveAlerts = saveAlerts; + mEnableAlerts = enableAlerts; + mTerminalAlerts = terminalAlerts; + + // + // Normalize Prefix if Not Provided ... + if (!IsValid(mPrefix)) + { + mPrefix = GetTag(); + } + + // + // Initialize Collector ... + collector = new XCDataCollector(); + collector.Path(mPrefix); + } + + // + // Deconstructor ... + ~XCAlert() + { + // + // Cleanup Resources ... + delete collector; + ZeroMemory(collector); + } + + // + // Override ... + string GetTag() override + { + return GetSpecificToken(this); + } + + // + // Properties Getter(s) / Setter(s) ... + + // + string GetPrefix() + { + return mPrefix; + } + + // + void SetPrefix(string value) + { + // + mPrefix = value; + collector.Path(mPrefix); + } + + // + bool GetLogAlerts() + { + return mLogAlerts; + } + + // + void SetLogAlerts(bool value) + { + mLogAlerts = value; + } + + // + bool GetEnableAlerts() + { + return mEnableAlerts; + } + + // + void SetEnableAlerts(bool value) + { + mEnableAlerts = value; + } + + // + bool GetSaveAlerts() + { + return mSaveAlerts; + } + + // + void SetSaveAlerts(bool value) + { + mSaveAlerts = 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; + } + + // + message = PrepareMessage(message); + + // + Log(message); + Save(message); + } + + // + // Terminal Alert ... + void TerminalAlert(string message) + { + // + // Validate Args ... + if (!CanTerminalAlert()) + { + return; + } + + // + // Prepare Message ... + message = PrepareMessage(message); + + // Send Terminal Alert ... + Alert(message); + Save(message); + } + + // + // Mail Alert ... + void MailAlert(string message) + { + // + // Validate Args ... + if (!CanMailAlert()) + { + return; + } + + // + // Send Mail Alert ... + SendMail(GetPrefix(), message); + Save(message); + } + + // + // Send Push Notification ... + void PushAlert(string message) + { + // + // Validate Args ... + if (!CanPushAlert()) + { + return; + } + + // + // Prepare Message ... + message = PrepareMessage(message); + + // + // Send Push Notification Alert ... + SendNotification(message); + Save(message); + } + + // + // Send an Alert by Handling all Different Specified + // type's of Alert's if they are Enabled ... + void SendAlert(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(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; + } + + // + void Save(string message) + { + // + if (!mSaveAlerts || + !IsValid(message) || + message == mLastSavedMessage || + PrepareMessage(message) == mLastSavedMessage) + { + return; + } + + // + string filePath = collector.GetFilePath("XLogs"); + if (!IsValid(filePath)) + { + return; + } + + // + // Attach Time ... + string savedMessage = ToString(TimeCurrent()) + " " + message; + + // + bool has = collector.Append( + filePath, + savedMessage // + ); + if (has) + { + mLastSavedMessage = message; + } + } + + private: + // + // Props ... + string mPrefix; // Alerts Prefixe + bool mEnableAlerts; // Enable Alerts + bool mSaveAlerts; // Save Alerts + bool mLogAlerts; // Log Alerts + bool mTerminalAlerts; // Terminal Alerts + bool mMailAlerts; // Mail Alerts + bool mPushAlerts; // Push Alerts + + // + string mLastSavedMessage; // For Prevent Multiple Saving Same Mesage ... + XCDataCollector *collector; + + // + // Tools ... + + // + // Clear Escape String and + // Attach Alert Prefix to Message ... + string PrepareMessage(string message) + { + // + StringReplace(message, "\n", " | "); + + // + StringConcatenate(message, GetPrefix(), " > ", message); + + // + return message; + } +}; + +// \ No newline at end of file diff --git a/BKPS/14040316/Classes/x-saherelm.x-app-dialog.class.mq5 b/BKPS/14040316/Classes/x-saherelm.x-app-dialog.class.mq5 new file mode 100644 index 0000000..fc3de5e --- /dev/null +++ b/BKPS/14040316/Classes/x-saherelm.x-app-dialog.class.mq5 @@ -0,0 +1,278 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XCPanel +// 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 + +// +// Imports ... + +// +#include + +// +#include "../Classes/x-saherelm.base.class.mq5" + +// +// Extentions ... + +/** + * Check a Qery Contains in a Content or not ... + * + * @param mQuery: String ... + * @param mContent: String ... + * @param ignoreCase: Boolean ... + * + * @return ( bool ) + */ +bool XContains( + string mQuery, // Search String + string mContent, // Search Content + bool ignoreCase = true // Ignore Case +) +{ + return Contains( + mQuery, + mContent, + ignoreCase // + ); +} + +// +// Implementation ... + +// +// a Base App Dialog Class ... +class XCAppDialog : public CAppDialog +{ + public: + // + // Action ... + + // + // Virual ... + + /** + * Override Close Button Click Action ... + */ + void OnClickButtonClose() + { + // + bool isClosed = ConfirmDialog("Close EA ?"); + + // + if (isClosed) + { + Destroy(); + } + } + + // + // Configuration Actions ... + + /** + * Show or Hide Minimize Button ... + * + * @param show: boolean + */ + void MinimizeButton(bool show) + { + // + int controlIDX = ControlFind("MinMax"); + if (!IsValidIndex(controlIDX)) + { + return; + } + + // + if (show) + { + Control(controlIDX).Show(); + } + else + { + Control(controlIDX).Hide(); + } + } + + /** + * Show or Hide Close Button ... + * + * @param show: boolean + */ + void CloseButton(bool show) + { + // + int controlIDX = ControlFind("Close"); + if (!IsValidIndex(controlIDX)) + { + return; + } + + // + if (show) + { + Control(controlIDX).Show(); + } + else + { + Control(controlIDX).Hide(); + } + } + + /** + * Minimize Functionality Implementation ... + */ + void Minimize() + { + // + m_minimized = true; + Rebound(m_min_rect); + ClientAreaVisible(false); + } + + /** + * Set Background Color ... + * + * @param clr: Color ... + */ + void BackgroundColor(color clr) + { + // + int controlIDX = ControlFind("Client"); + if (!IsValidIndex(controlIDX)) + { + return; + } + + // + CWnd *obj = Control(controlIDX); + CWndClient *wndclient = (CWndClient *)obj; + + // + wndclient.ColorBackground(clr); + } + + // + // Overrides ... + + // + protected: + // + + /** + * Find Specific Control in Dialog ... + * + * @param name: String to Search + * + * @return ( int ) + */ + int ControlFind(string name) + { + // + int result = -1; + + // + if (!IsValid(name)) + { + return result; + } + + // + int count = ControlsTotal(); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + string iName = Control(i).Name(); + + // + bool isContains = XContains( + name, + iName, + true // Ignore Case ... + ); + if (isContains) + { + // + result = i; + break; + } + } + + // + return result; + } + + /** + * Create and Run Confirm Dialog ... + * + * @param message: message for Message Box ... + * + * @return ( bool ) + */ + bool ConfirmDialog(string message = NULL) + { + // + bool result = false; + + // + if (!IsValid(message)) + { + message = "Confirm ?"; + } + + // + int dialogResult = MessageBox(message, NULL, MB_YESNO); + + // + // use 'switch' or 'if' as needed + switch (dialogResult) + { + // + // Yes ... + case IDYES: + result = true; + break; + // + // No ... + case IDNO: + result = false; + break; + // + // Cancel ... + case IDCANCEL: + result = false; + break; + } + + // + return result; + } + + // + private: + // + + // +}; \ No newline at end of file diff --git a/BKPS/14040316/Classes/x-saherelm.x-bar.analyser.class.mq5 b/BKPS/14040316/Classes/x-saherelm.x-bar.analyser.class.mq5 new file mode 100644 index 0000000..a9481fb --- /dev/null +++ b/BKPS/14040316/Classes/x-saherelm.x-bar.analyser.class.mq5 @@ -0,0 +1,3454 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XPOI +// Description: Bar Analysing ... +// +// 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.x-poi.lib.mq5" + +// +// Definitions ... + +// +// Extensions ... +void FillLiquidity( + XOHCL &lBar, + ENUM_X_DIRECTION lDir, + XBoxZone &lq, + datetime to // +) +{ + // + // Normalize Args ... + lq.Clean(); + to = NormalizeTime(to); + + // + // Validate Args ... + bool has = lBar.IsValid() && + HasDirection(lDir); + if (!has) + { + return; + } + + // + lq.to = to; + lq.dir = lDir; + lq.type = "XLQ"; + lq.from = lBar.time; + lq.symbol = lBar.symbol; + lq.period = lBar.period; + lq.upper = IsBullish(lDir) + ? lBar.GetDown() + : lBar.high; + lq.lower = IsBullish(lDir) + ? lBar.low + : lBar.GetUp(); +} + +// +// Implementations ... +class XCBarAnalyser : public XCBase +{ + // + public: + // + + // + // Constructor(s) ... + void XCBarAnalyser() + { + } + + // + // Deconstructor ... + void ~XCBarAnalyser() + { + } + + // + // Getter(s) / Setter(s) ... + + // + // Providers ... + + /** + * Calculate Loopback Data for Specific Bar ... + * + * @param index: Integer, Bar Current Index ... + * @param start: Integer, Start of Loopback ... + * @param end: Integer, End of Loopback ... + * @param count: Integer, Number of Calculating Bars ... + * @param bar: XOHCL instance, Specified Bar ... + * @param loopback: Integer, Loopback Length ... + * @return ( bool ) + */ + bool CalculateLoopbackData( + int &index, + int &start, + int &end, + int &count, + XOHCL &bar, + int loopback = 1 // + ) + { + // + bool result = false; + + // + if (loopback < 1) + { + loopback = 1; + } + + // + index = -1; + start = -1; + end = -1; + count = -1; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + index = bar.Index(); + start = index + 1; + end = start + loopback; + count = end - start; + result = count >= 1; + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Retrieve Loopback HH & LL Data ... + * + * @param hhIDX: Integer, HH Index ... + * @param hh: Double, HH Value ... + * @param llIDX: Integer, LL Index ... + * @param ll: Double, LL Value ... + * @param bar: XOHCL instance ... + * @param loopback: Integer, Loopback Length ... + * + * @return ( bool ) + */ + bool CalculateLoopbackHLData( + int &hhIDX, + double &hh, + int &llIDX, + double &ll, + XOHCL &bar, + int loopback // + ) + { + // + bool result = false; + + // + if (loopback < 1) + { + loopback = 1; + } + + // + int index = -1; + int start = -1; + int end = -1; + int count = -1; + result = CalculateLoopbackData( + index, + start, + end, + count, + bar, + loopback // + ); + if (!result) + { + return result; + } + + // + hhIDX = iHighest( + bar.symbol, + bar.period, + MODE_HIGH, + count, + start // + ); + result = IsValidIndex(hhIDX); + if (!result) + { + return result; + } + + // + llIDX = iLowest( + bar.symbol, + bar.period, + MODE_LOW, + count, + start // + ); + result = IsValidIndex(llIDX); + if (!result) + { + return result; + } + + // + hh = iHigh( + bar.symbol, + bar.period, + hhIDX // + ); + ll = iLow( + bar.symbol, + bar.period, + llIDX // + ); + + // + return result; + } + + /** + * Fill Prices ... + * + * @param prices: double collection + * @param bar: XOHCL instance reference, Provides Start ... + * @param loopback: int, Specified How Many Bars Process ... + * @param type: ENUM_X_PRICE member, Specified Price Type ... + * + * @return ( bool ) + */ + int FillPrice( + double &prices[], + XOHCL &bar, + int loopback = 14, + ENUM_X_PRICE type = X_PRICE_CLOSE // + ) + { + // + int result = 0; + + // + Clean(prices); + + // + loopback = NormalizeInt(loopback, 1); + + // + bool has = IsValid(type) && + bar.IsValid(); + if (!has) + { + return result; + } + + // + string symbol = bar.symbol; + ENUM_TIMEFRAMES period = bar.period; + + // + // Calculate Loopback Data ... + int index = -1; + int start = -1; + int end = -1; + int count = -1; + has = CalculateLoopbackData( + index, + start, + end, + count, + bar, + loopback // + ); + if (!has) + { + return result; + } + + // + for (int i = start; i < end; i++) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + symbol, + period, + i // + ); + if (!isInited) + { + // + iBar.Clean(); + continue; + } + + // + double iPrice = iBar.GetPrice(type); + + // + isInited = NotEmptyZero(iPrice); + if (isInited) + { + // + Add( + iPrice, + prices // + ); + } + + // + iBar.Clean(); + } + + // + result = ArraySize(prices); + has = result == count; + if (!has) + { + // + Clean(prices); + } + + // + ArrayReverse(prices); + + // + return result; + } + + /** + * Calculate Price Range ... + * + * @param ranges: double Collection, Calculated Ranges ... + * @param bar: XOHCL instance Reference, Start Bar ... + * @param forceBody: bool, Force to Calculate Range using Body ... + * @param forceDiff: bool, Force to Calculate Range using Onl Price Diff ... + * @param loopback: int, loopback period for Range Calculations ... + * + * @return ( int ) + */ + int GetPriceRange( + double &ranges[], + XOHCL &bar, + bool forceBody = false, + bool forceDiff = false, + int loopback = 14 // + ) + { + // + int result = 0; + + // + Clean(ranges); + + // + loopback = NormalizeInt(loopback, 1); + + // + if (!bar.IsValid()) + { + return result; + } + + // + bool has = false; + + // + // Select Uppers Prices ... + double uppers[]; + int uppersCount = 0; + if (forceBody) + { + // + has = FillPrice( + uppers, + bar, + loopback, + X_PRICE_UP // + ); + } + else + { + // + has = FillPrice( + uppers, + bar, + loopback, + X_PRICE_HIGH // + ); + } + if (has) + { + uppersCount = ArraySize(uppers); + } + + // + // Select Lower Prices ... + double lowers[]; + int lowersCount = 0; + if (forceBody) + { + // + has = FillPrice( + lowers, + bar, + loopback, + X_PRICE_DOWN // + ); + } + else + { + // + has = FillPrice( + lowers, + bar, + loopback, + X_PRICE_LOW // + ); + } + if (has) + { + lowersCount = ArraySize(lowers); + } + + // + // Validate Filled Prices ... + has = + IsValidSize(uppersCount) && + IsValidSize(lowersCount) && + uppersCount == lowersCount; + if (!has) + { + // + Clean(uppers); + Clean(lowers); + + // + return result; + } + + // + for (int i = 0; i < uppersCount; i++) + { + // + double iDiff = uppers[i] - lowers[i]; + double iValue = + forceDiff + ? iDiff + : lowers[i] + iDiff; + + // + Add( + iValue, + ranges // + ); + } + + // + result = ArraySize(ranges); + ArrayReverse(ranges); + + // + // Cleanup Resources ... + + // + Clean(uppers); + Clean(lowers); + + // + return result; + } + + /** + * Retrieve Price Velocities ... + * + * @param velocities: double Collection, Price Velocities ... + * @param bar: XOHCL instance Reference, Start Bar ... + * @param type: ENUM_X_PRICE member ... + * @param loopback: int, loopback period for Calculations ... + * + * @return ( int ) + */ + int GetPriceVelocity( + double &velocities[], + XOHCL &bar, + ENUM_X_PRICE type = X_PRICE_CLOSE, + int loopback = 14 // + ) + { + // + int result = 0; + + // + Clean(velocities); + loopback = NormalizeInt(loopback, 1); + + // + result = IsValid(type) && + bar.IsValid(); + + // + int to = bar.Index(); + int from = to + loopback; + for (int i = to; i < from; i++) + { + // + double iPrice = GetAppliedPrice( + bar.symbol, + bar.period, + i, + type // + ); + + // + double pPrice = GetAppliedPrice( + bar.symbol, + bar.period, + i + 1, + type // + ); + + // + double iVelocity = MathAbs(iPrice - pPrice); + Add( + iVelocity, + velocities // + ); + } + + // + result = ArraySize(velocities); + + // + return result; + } + + /** + * Calculate Price Change Percent ... + * + * @param bar: XOHCL instance Reference, Start Bar ... + * @param type: ENUM_X_PRICE member, Specified Price Type ... + * @param loopback: int, loopback period for Range Calculated ... + * + * @return ( double ) + */ + double GetPriceChangeRate( + XOHCL &bar, + ENUM_X_PRICE type = X_PRICE_MEDIAN, + int loopback = 14 // + ) + { + // + double result = 0; + + // + bool has = false; + + // + loopback = NormalizeInt(loopback, 1); + + // + has = + bar.IsValid() && + IsValid(type); + if (!has) + { + return result; + } + + // + XOHCL oldBar; + has = oldBar.Init( + bar.symbol, + bar.period, + bar.Index() + loopback // + ); + if (!has) + { + // + oldBar.Clean(); + + // + return result; + } + double newPrice = bar.GetPrice(type); + double oldPrice = oldBar.GetPrice(type); + + // + result = ((newPrice - oldPrice) / oldPrice) / 100; + + // + oldBar.Clean(); + + // + return result; + } + + /** + * Detect Range Block ... + */ + bool DetectRangeBlocks( + XOHCL &bar, + XBoxZone &upper, + XBoxZone &lower, + int loopback = 288, + ENUM_SERIESMODE upperRangeUpperMode = MODE_HIGH, + ENUM_SERIESMODE upperRangeLowerMode = MODE_LOW, + ENUM_SERIESMODE lowerRangeUpperMode = MODE_HIGH, + ENUM_SERIESMODE lowerRangeLowerMode = MODE_LOW // + ) + { + // + bool result = false; + + // + // Normalize Args ... + upper.Clean(); + lower.Clean(); + loopback = NormalizeInt(loopback, 10); + + // + // Validate Args ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL iBar; + result = iBar.Init( + bar.symbol, + bar.period, + bar.Index() + loopback // + ); + if (!result) + { + // + iBar.Clean(); + + // + return result; + } + + // + double hhUpper = iBar.FindHighest(loopback, upperRangeUpperMode); + double hhLower = iBar.FindHighest(loopback, upperRangeLowerMode); + + // + double llUpper = iBar.FindLowest(loopback, lowerRangeUpperMode); + double llLower = iBar.FindLowest(loopback, lowerRangeLowerMode); + + // + double bhhUpper = bar.FindHighest(iBar.Index() - bar.Index(), upperRangeUpperMode); + double bhhLower = bar.FindHighest(iBar.Index() - bar.Index(), upperRangeLowerMode); + + // + double bllUpper = bar.FindLowest(iBar.Index() - bar.Index(), lowerRangeUpperMode); + double bllLower = bar.FindLowest(iBar.Index() - bar.Index(), lowerRangeLowerMode); + + // + hhUpper = MathMax(hhUpper, bhhUpper); + hhLower = MathMax(hhLower, bhhLower); + + // + llUpper = MathMin(llUpper, bllUpper); + llLower = MathMin(llLower, bllLower); + + // + datetime from = GetBarTime( + iBar.symbol, + iBar.period, + iBar.Index() + loopback // + ); + + // + upper.from = from; + upper.type = "XRNG"; + upper.to = bar.time; + upper.upper = hhUpper; + upper.lower = hhLower; + upper.symbol = iBar.symbol; + upper.period = iBar.period; + upper.dir = X_DIRECTION_BEARISH; + + // + lower.from = from; + lower.type = "XRNG"; + lower.to = bar.time; + lower.upper = llUpper; + lower.lower = llLower; + lower.symbol = iBar.symbol; + lower.period = iBar.period; + lower.dir = X_DIRECTION_BULLISH; + + // + result = upper.IsValid() && + lower.IsValid(); + if (!result) + { + // + iBar.Clean(); + upper.Clean(); + lower.Clean(); + } + + // + iBar.Clean(); + + // + return result; + } + + /** + * Calculate Specified Bars Range Volume ... + * + * @param bar: XOHCL instance reference ... + * @param bullishVolume: double + * @param bearishVolume: double + * @param loopback: int + * + * @return ( bool ) + */ + bool CalculateRangeVolume( + XOHCL &bar, + double &bullishVolume, + double &bearishVolume, + int loopback = 5 // + ) + { + // + bool result = false; + + // + // Normalize Args ... + bullishVolume = 0; + bearishVolume = 0; + loopback = NormalizeInt(loopback, 3); + + // + // Validate ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL iBar; + bool has = false; + int start = bar.Index(); + int end = start + loopback; + for (int i = start; i <= end; i++) + { + // + iBar.Clean(); + has = iBar.Init( + bar.symbol, + bar.period, + i // + ); + if (!has) + { + // + iBar.Clean(); + + // + break; + } + + // + bool isBullish = iBar.IsBullish(); + bool isBearish = iBar.IsBearish(); + + // + if (isBullish) + { + bullishVolume += (double)iBar.volume; + } + else if (isBearish) + { + bearishVolume += (double)iBar.volume; + } + else + { + // + bullishVolume += (double)iBar.volume; + bearishVolume += (double)iBar.volume; + } + + // + iBar.Clean(); + } + + // + result = iBar.IsValid(); + + // + iBar.Clean(); + + // + return result; + } + + /** + * Detect Same Bars ... + * + * @param bar: XOHCL instance, Start Bar ... + * @param dir: ENUM_X_DIRECTION member, Holds Result Direction ... + * @param index: Integer, Holds Result Index ... + * @param sameBars: Iteger, Required Same Bar ... + * + * @return ( bool ) + */ + bool HasSameBars( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + int &index, + int sameBars = 3 // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + if (sameBars < 1) + { + sameBars = 1; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + index = bar.Index() + 1; + bool canContinue = true; + int sameBullishBarsFounded = 0; + int sameBearishBarsFounded = 0; + bool canContinueForBullish = true; + bool canContinueForBearish = true; + while (canContinue) + { + // + XOHCL iBar; + result = iBar.Init( + bar.symbol, + bar.period, + index // + ); + if (!result) + { + break; + } + + // + bool isBullish = iBar.IsBullish(); + bool isBearish = iBar.IsBearish(); + result = isBullish || + isBearish; + if (!result) + { + break; + } + + // + if (isBullish) + { + // + sameBullishBarsFounded++; + canContinueForBearish = false; + } + else if (isBearish) + { + // + sameBearishBarsFounded++; + canContinueForBullish = false; + } + else + { + // + sameBullishBarsFounded = 0; + sameBearishBarsFounded = 0; + canContinueForBullish = false; + canContinueForBearish = false; + } + + // + result = canContinueForBullish || + canContinueForBearish; + if (!result) + { + break; + } + + // + canContinueForBullish = + canContinueForBullish && + sameBullishBarsFounded > 0; + + // + canContinueForBearish = + canContinueForBearish && + sameBearishBarsFounded > 0; + + // + canContinue = + canContinueForBullish || + canContinueForBearish; + if (canContinue) + { + index++; + } + } + + // + bool hasBullishSameBars = + sameBullishBarsFounded >= sameBars; + + // + bool hasBearishSameBars = + sameBearishBarsFounded >= sameBars; + + // + result = hasBullishSameBars || + hasBearishSameBars; + if (!result) + { + return result; + } + + // + index--; + + // + dir = + hasBullishSameBars + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; + } + + /** + * Check Fibonacci Level 382 Pressure ... + * + * @param bar: XOHCL instance ... + * @param dir: ENUM_X_DIRECTION member ... + * + * @return ( bool ) + */ + bool HasFiboPressure( + XOHCL &bar, + ENUM_X_DIRECTION forDir, + ENUM_X_FIBO_LEVELS level // + ) + { + // + bool result = false; + + // + result = bar.IsValid() && + HasDirection(forDir); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + bool isBearish = IsBearish(forDir); + + // + double fiboLevelValue = GetFibonacciLevel( + bar.high, + bar.low, + level, + forDir // + ); + + // + bool isBullishPressured = + isBullish && + bar.GetDown() > fiboLevelValue; + bool isBearishPressured = + isBearish && + bar.GetUp() < fiboLevelValue; + + // + result = isBullishPressured || + isBearishPressured; + + // + return result; + } + + /** + * Detect Big Price Change Happens or not ... + * + * @param bar: XOHCL instance reference, Start Bar ... + * @param dir: ENUM_X_DIRECTION member, Event Direction ... + * @param rootIDX: int, Root of Momentum Index ... + * @param type: ENUM_X_PRICE member, Price Type ... + * @param forcBodyInRange: bool, Use Body in Range Detection ... + * @param rangeExtendMultiplier: double, a Multiplier for Checking Price Range ... + * + * @return ( bool ) + */ + bool IsSharp( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + int &rootIDX, + ENUM_X_PRICE type = X_PRICE_CLOSE, + bool forcBodyInRange = true, + double rangeExtendMultiplier = 2.0 // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + rangeExtendMultiplier = NormalizeDouble(rangeExtendMultiplier, 1); + + // + result = + bar.IsValid() && + IsValid(type); + if (!result) + { + return result; + } + + // + double minPriceChangePercent = 0; + int loopback = GetPeriodSharpData( + minPriceChangePercent, + bar.period // + ); + + // + // Retrieve Price Change Percent ... + double priceChangePercent = GetPriceChangeRate( + bar, + type, + loopback // + ); + + // + // Velocities ... + double velocities[]; + int velocitiesCount = GetPriceVelocity( + velocities, + bar, + type, + loopback // + ); + double velocitiesAvg = GetAverage(velocities); + double oldPrice = GetAppliedPrice( + bar.symbol, + bar.period, + bar.Index() + loopback, + type // + ); + double newPrice = bar.GetPrice(type); + double currVelocity = MathAbs(oldPrice - newPrice); + + // + // Calculate HH and LL ... + + // + double hh = 0; + double ll = 0; + int hhIDX = -1; + int llIDX = -1; + result = CalculateLoopbackHLData( + hhIDX, + hh, + llIDX, + ll, + bar, + loopback // + ); + result = + result && + ll > 0 && + hh > ll && + IsValidIndex(llIDX) && + IsValidIndex(hhIDX); + if (!result) + { + return result; + } + + // + int hhDiff = (hhIDX - bar.Index()); + int llDiff = (llIDX - bar.Index()); + + // + // Bool Get Boundary Direction ... + + // + // Check Price Change Rate ... + + // + bool isBullish = + // + hhDiff <= 1 && + llIDX > hhIDX && + priceChangePercent > 0 && + priceChangePercent >= minPriceChangePercent && + currVelocity > (velocitiesAvg * rangeExtendMultiplier) + // + ; + + // + bool isBearish = + // + llDiff <= 1 && + hhIDX > llIDX && + priceChangePercent < 0 && + MathAbs(priceChangePercent) >= minPriceChangePercent && + currVelocity > (velocitiesAvg * rangeExtendMultiplier) + // + ; + + // + result = isBullish || + isBearish; + if (result) + { + // + rootIDX = + isBullish + ? llIDX + : hhIDX; + + // + dir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + return result; + } + + // + // Actions ... + + /** + * Check a Bar is End of an OrderBlock Bar or Not ... + * + * @param bar: XOHCL ... + * @param box: XBoxZone ... + * @param forceFVGBarType: bool, Force all Bars must be Same as Direction ... + * @param forceOBTwoBar: bool, Force Two Bars of OB Start must be InDirection ... + * + * @return ( bool ) + */ + bool IsOB( + XOHCL &bar, + XBoxZone &box, + bool forceFVGBarType = false, + bool forceOBTwoBar = false // + ) + { + // + bool result = false; + + // + box.Clean(); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Check Bar Must be FVG ... + result = IsFVG( + bar, + box, + forceFVGBarType // + ); + if (!result) + { + // + box.Clean(); + + // + return result; + } + + // + box.type = "XOB"; + + // + bool isBullish = box.IsBullish(); + bool isBearish = box.IsBearish(); + + // + // Order Block Includes an FVG which Starts by atleast One + // or More Indirectional Bars ... + XOHCL fvgLastBar; + XOHCL fvgLastBarPrev; + XOHCL fvgLastBarPrev2; + + // + int barIndex = bar.Index(); + int fvgLastBarIndex = barIndex + 3; + result = fvgLastBar.Init( + bar.symbol, + bar.period, + fvgLastBarIndex // + ); + result = + result && + fvgLastBar.GetPreviousBar(fvgLastBarPrev); + result = + result && + fvgLastBarPrev.GetPreviousBar(fvgLastBarPrev2); + if (!result) + { + // + box.Clean(); + fvgLastBar.Clean(); + fvgLastBarPrev.Clean(); + fvgLastBarPrev2.Clean(); + + // + return result; + } + + // + // Check FVG Last Bar ... + + // + bool isBullishBlock = + isBullish && + (fvgLastBar.IsBearish() || + (fvgLastBar.IsBullish() && + fvgLastBarPrev.IsBearish())); + + // + bool isBearishBlock = + isBearish && + (fvgLastBar.IsBullish() || + (fvgLastBar.IsBearish() && + fvgLastBarPrev.IsBullish())); + + // + // Update Box ... + + // + if (isBullishBlock || + isBearishBlock) + { + // + box.from = fvgLastBar.time; + + // + box.lower = MathMin(box.lower, fvgLastBar.low); + box.upper = MathMax(box.upper, fvgLastBar.high); + } + + // + // Apply Force Two Bar ... + if (forceOBTwoBar) + { + // + isBullishBlock = + isBullishBlock && + fvgLastBarPrev.IsBearish(); + + // + isBearishBlock = + isBearishBlock && + fvgLastBarPrev.IsBullish(); + + // + // Update Box ... + if (isBullishBlock || + isBearishBlock) + { + // + box.from = fvgLastBarPrev.time; + box.lower = MathMin(box.lower, fvgLastBarPrev.low); + box.upper = MathMax(box.upper, fvgLastBarPrev.high); + } + } + + // + result = isBullishBlock || + isBearishBlock; + if (!result) + { + // + box.Clean(); + fvgLastBar.Clean(); + fvgLastBarPrev.Clean(); + + // + return result; + } + + // + result = box.IsValid(); + + // + // Cleanup Resources ... + + // + fvgLastBar.Clean(); + fvgLastBarPrev.Clean(); + + // + return result; + } + + /** + * Check a Bar is End of an FVG Bar or Not ... + * + * @param bar: XOHCL ... + * @param box: XBoxZone ... + * @param forceType: bool, Force all Bars must be Same as Direction ... + * + * @return ( bool ) + */ + bool IsFVG( + XOHCL &bar, + XBoxZone &box, + bool forceType = false // + ) + { + // + bool result = false; + + // + box.Clean(); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL pBar; + XOHCL p2Bar; + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + if (!result) + { + // + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + // + bool isBullish = p2Bar.high < bar.low; + bool isBearish = p2Bar.low > bar.high; + + // + result = isBullish || + isBearish; + + // + // Apply Force Type ... + if (result) + { + // + if (isBullish) + { + // + result = + bar.IsBullish() && + pBar.IsBullish() && + p2Bar.IsBullish(); + } + else if (isBearish) + { + // + result = + bar.IsBearish() && + pBar.IsBearish() && + p2Bar.IsBearish(); + } + } + + // + if (result) + { + // + box.to = bar.time; + box.from = p2Bar.time; + box.symbol = bar.symbol; + box.period = bar.period; + box.dir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + box.upper = isBullish + ? bar.low + : p2Bar.low; + box.lower = isBullish + ? p2Bar.high + : bar.high; + box.type = "XFVG"; + } + + // + pBar.Clean(); + p2Bar.Clean(); + + // + result = box.IsValid(); + + // + return result; + } + + /** + * Check a Bar is a Trigger Box or Not ... + * + * @param bar: XOHCL instance Referernce, Specified Start Bar to Check ... + * @param trigger: XBoxZone instance Reference, Holds Detected Trigger Bar ... + * @param ob: XBoxZone instance Reference, Holds Detected Trigger Bar's OB ... + * @param fvg: XBoxZone instance Reference, Holds Detected Trigger Bar's FVG ... + * @param rLiquidity: XBoxZone instance Reference, Holds Detected Trigger Bar's Reversal Side Liquidity ... + * @param fLiquidity: XBoxZone instance Reference, Holds Detected Trigger Bar's Following Side Liquidity ... + * @param swingBar: XOHCL instance Referernce, Holds Detected Trigger Bar's Swing ... + * @param loopback: int, Loopback Bars Count ... + * @param maxAllowedRange: double, Max Allowed Trigger's OB Range ... + * @param minAllowedBlockEdgeLength: int, Min Allowed Block Edge Validation Length ... + * @param forceOBOppositBar: bool, Force OB to Start by Opposite Bar ... + * @param forceFVGBarType: bool, Force FVG to Has Same Bar Type ... + * @param forceGapBarBreakout: bool, Force Gap Bar Breakout OB Edge ... + * @param forceHasSwingBar: bool, Force Has Swing Bar ... + * @param forceHasLiquidity: bool, Force Has Following Liquidity ... + * @param forceHasReversalLiquidity: bool, Force Has Reversal Liquidity ... + * + * @return ( bool ) + */ + bool IsTrigger( + XOHCL &bar, + XBoxZone &trigger, + XBoxZone &ob, + XBoxZone &fvg, + XBoxZone &rLiquidity, + XBoxZone &fLiquidity, + XOHCL &swingBar, + int loopback = 10, + double maxAllowedRange = 0.0, + int minAllowedBlockEdgeLength = 0, + bool forceOBOppositBar = true, + bool forceFVGBarType = true, + bool forceGapBarBreakout = true, + bool forceHasSwingBar = true, + bool forceHasLiquidity = true, + bool forceHasReversalLiquidity = true // + ) + { + // + bool result = false; + + // + // Normalize Args ... + ob.Clean(); + fvg.Clean(); + trigger.Clean(); + swingBar.Clean(); + rLiquidity.Clean(); + fLiquidity.Clean(); + loopback = NormalizeInt(loopback, 5); + + // + // Validate Args ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL pBar; + XOHCL tmpBar; + XOHCL tmpPBar; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + + // + result = bar.GetPreviousBar(pBar); + + // + // Detect Base Order Block ... + result = + result && + // + // Order Block Detection ... + IsOB( + pBar, + ob, + forceFVGBarType, + forceOBOppositBar // + ) && + // + // Gap Detection ... + IsFVG( + pBar, + fvg, + forceFVGBarType // + ); + if (result) + { + // + trigger = ob; + trigger.type = "XTRG"; + } + + // + // Reading Requirements ... + + // + double points = GetPoints(bar.symbol); + + // + bool isBullish = ob.IsBullish(); + bool isBearish = ob.IsBearish(); + + // + int toIDX = trigger.ToIndex(); + int fromIDX = trigger.FromIndex(); + + // + // Validate Gaps Bar Breakeout ... + if (result && + forceGapBarBreakout) + { + // + // Extract Gap Bar ... + tmpBar.Clean(); + tmpPBar.Clean(); + result = + // + // Retrieve Bars ... + fvg.ToBar(tmpBar) && + tmpBar.GetPreviousBar(tmpPBar) && + // + // Validate Gap Bar is Momentum Bar ... + IsMomentum( + tmpPBar, + iDir, + 1 // + ) && + iDir == fvg.dir && + // + // Validate ... + (isBullish + ? tmpPBar.close > ob.upper + : tmpPBar.close < ob.lower); + + // + tmpBar.Clean(); + tmpPBar.Clean(); + } + + // + // Validate Range ... + if (result && + maxAllowedRange > 0) + { + // + double range = ob.GetRange(); + result = range <= (maxAllowedRange * points); + } + + // + // Validating Swing Bar ... + if (result && + forceHasSwingBar) + { + // + int swingIDX = -1; + result = ob.FromBar(tmpBar); + if (result) + { + // + // Detect Swing Bar Index ... + if (isBullish) + { + swingIDX = tmpBar.FindLowestIndex(loopback, MODE_LOW); + } + else if (isBearish) + { + swingIDX = tmpBar.FindHighestIndex(loopback, MODE_HIGH); + } + result = IsValidIndex(swingIDX); + if (result) + { + // + // Initialize Swing Bar ... + result = swingBar.Init( + bar.symbol, + bar.period, + swingIDX // + ); + } + + // + // Update Trigger Block based on Swing Bar ... + result = swingBar.IsValid(); + if (result) + { + // + // Update From ... + trigger.from = ((datetime)MathMin((int)trigger.from, (int)swingBar.time)); + + // + // Update Edge ... + if (isBullish) + { + trigger.lower = MathMin(trigger.lower, swingBar.GetDown()); + } + else if (isBearish) + { + trigger.upper = MathMax(trigger.upper, swingBar.GetUp()); + } + } + } + + // + tmpBar.Clean(); + } + + // + // Validate Min Block Edge ... + if (result && + minAllowedBlockEdgeLength > 0) + { + // + fromIDX = trigger.FromIndex(); + if (result) + { + // + // Looping Back ... + for (int i = fromIDX; i < fromIDX + minAllowedBlockEdgeLength; i++) + { + // + // Initialize i Bar ... + result = tmpBar.Init( + bar.symbol, + bar.period, + i // + ); + result = + result && + (isBullish + ? tmpBar.low > trigger.lower + : tmpBar.high > trigger.upper); + if (!result) + { + break; + } + + // + tmpBar.Clean(); + } + result = tmpBar.IsValid(); + + // + // Update Trigger Block ... + if (result) + { + trigger.from = ((datetime)(MathMin((int)trigger.from, (int)tmpBar.time))); + } + } + + // + tmpBar.Clean(); + } + + // + // Validating Liquidity ... + if (result && + (forceHasLiquidity || + forceHasReversalLiquidity)) + { + // + // Try to Detect Liquidity ... + toIDX = ob.ToIndex(); + for (int i = toIDX; i < toIDX + (loopback * 10); i++) + { + // + // Initialize i Bar ... + result = tmpBar.Init( + bar.symbol, + bar.period, + i // + ); + if (!result) + { + break; + } + + // + // Detect Liquidity ... + bool isRejected = + result && + IsRejected( + tmpBar, + iDir, + false, // Force Bar Type ... + true // Force Fibo Pressure ... + ); + bool isBullishRejected = + isRejected && + IsBullish(iDir); + bool isBearishRejected = + isRejected && + IsBearish(iDir); + + // + // Validate Liquidities ... + if (isBullish) + { + // + if (isBullishRejected && + forceHasLiquidity && + !fLiquidity.IsValid() && + tmpBar.low < trigger.lower) + { + // + // Filling Following Liquidity ... + FillLiquidity( + tmpBar, + trigger.dir, + fLiquidity, + trigger.to // + ); + } + + // + if (isBearishRejected && + !rLiquidity.IsValid() && + forceHasReversalLiquidity && + tmpBar.high > trigger.upper) + { + // + // Filling Revrsal Liquidity ... + FillLiquidity( + tmpBar, + Opposit(trigger.dir), + rLiquidity, + trigger.to // + ); + } + } + else if (isBearish) + { + // + if (isBearishRejected && + forceHasLiquidity && + !fLiquidity.IsValid() && + tmpBar.high > trigger.upper) + { + // + // Filling Following Liquidity ... + FillLiquidity( + tmpBar, + trigger.dir, + fLiquidity, + trigger.to // + ); + } + + // + if (isBullishRejected && + !rLiquidity.IsValid() && + forceHasReversalLiquidity && + tmpBar.low < trigger.lower) + { + // + // Filling Reversal Liquidity ... + FillLiquidity( + tmpBar, + Opposit(trigger.dir), + rLiquidity, + trigger.to // + ); + } + } + + // + if ((!forceHasLiquidity + ? true + : fLiquidity.IsValid()) && + (!forceHasReversalLiquidity + ? true + : rLiquidity.IsValid())) + { + break; + } + + // + tmpBar.Clean(); + } + tmpBar.Clean(); + + // + result = (!forceHasLiquidity + ? true + : fLiquidity.IsValid()) && + (!forceHasReversalLiquidity + ? true + : rLiquidity.IsValid()); + } + + // + // Cleanup Resources ... + + // + pBar.Clean(); + tmpBar.Clean(); + tmpPBar.Clean(); + + // + if (!result) + { + // + ob.Clean(); + fvg.Clean(); + trigger.Clean(); + swingBar.Clean(); + rLiquidity.Clean(); + fLiquidity.Clean(); + + // + return result; + } + + // + return result; + } + + // + // Candlestick ... + + /** + * Check Specified Bar is Doji Pattern or not ... + * + * @param bar: XOHCL instance reference, Specified Bar to Check ... + * @param dir: ENUM_X_DIRECTION member, Specified Doji Direction ... + * @param shadowMultiplier: double, Specified Shadow Multiplier ... + * + * @return ( bool ) + */ + bool IsDoji( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + double shadowMultiplier = 1.5 // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + shadowMultiplier = NormalizeDouble(shadowMultiplier, 1.5, 3); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double body = bar.GetBody(); + double range = bar.GetRange(); + + // + result = + body > 0 && + range > 0 + ? (body / range < 0.1) + : false; + if (result) + { + // + dir = + bar.GetLowShadow() >= (bar.GetHighShadow() * shadowMultiplier) + ? X_DIRECTION_BULLISH + : bar.GetHighShadow() >= (bar.GetLowShadow() * shadowMultiplier) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + // + result = HasDirection(dir); + } + + // + return result; + } + + /** + * Check Specified Bar is Swing or not ... + * + * @param bar: XOHCL instance reference, Specified Bar to Check ... + * @param dir: ENUM_X_DIRECTION member, Specified Doji Direction ... + * @param loopback: int, Specified Loopback ... + * + * @return ( bool ) + */ + bool IsSwing( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + int loopback = 7 // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + loopback = NormalizeInt(loopback, 1); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + // + pBar.Clean(); + return result; + } + + // + XOHCL ppBar; + result = pBar.GetPreviousBar(ppBar); + if (!result) + { + // + pBar.Clean(); + ppBar.Clean(); + return result; + } + + // + bool isBullish = + // + pBar.low < bar.low && + pBar.low < ppBar.low && + bar.GetDown() > pBar.low + // + ; + + // + bool isBearish = + // + pBar.high > bar.high && + pBar.high > ppBar.high && + bar.GetUp() < pBar.high + // + ; + + // + result = isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + ppBar.Clean(); + int pBarIDX = pBar.Index(); + for (int i = pBarIDX + 1; i < pBarIDX + loopback; i++) + { + // + bool has = ppBar.Init( + pBar.symbol, + pBar.period, + i // + ); + + // + isBullish = + has && + isBullish && + pBar.low < ppBar.low; + + // + isBearish = + has && + isBearish && + pBar.high > ppBar.high; + } + + // + result = isBullish || + isBearish; + if (!result) + { + dir = X_DIRECTION_NONE; + } + } + + // + // Cleanup Resources ... + + // + pBar.Clean(); + ppBar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar's Prev Bar is Simple Swing or not ... + * + * @param bar: XOHCL instance reference, Specified Bar to it's Prev Check ... + * @param dir: ENUM_X_DIRECTION member, Specified Doji Direction ... + * + * @return ( bool ) + */ + bool IsSimpleSwing( + XOHCL &bar, + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + // Valdate Args ... + result = bar.IsValid(); + + // + // Reading Requirements ... + XOHCL cBar; + XOHCL pBar; + XOHCL p2Bar; + result = + bar.GetPreviousBar(cBar); + result = + result && + cBar.GetPreviousBar(pBar); + result = + result && + pBar.GetPreviousBar(p2Bar); + if (!result) + { + // + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + // + // Now we Have to Check pBar is Swing Low or High ... + + // + bool isPBarSwingLow = + pBar.low < cBar.low && + pBar.low < p2Bar.low; + + // + bool isPBarSwingHigh = + pBar.high > cBar.high && + pBar.high > p2Bar.high; + + // + result = isPBarSwingLow || + isPBarSwingHigh; + if (result) + { + // + dir = isPBarSwingLow + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + // Cleanup Resourses ... + + // + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar is Hammer Pattern or not ... + * + * @param bar: XOHCL instance reference, Specified Bar to Check ... + * @param dir: ENUM_X_DIRECTION member, Specified Doji Direction ... + * @param bodyMultiplier: double, Specified Body Multiplier ... + * + * @return ( bool ) + */ + bool IsHammer( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + double bodyMultiplier = 2.0 // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + bodyMultiplier = NormalizeDouble(bodyMultiplier, 1.5, 3); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double body = bar.GetBody(); + double lShadow = bar.GetLowShadow(); + double hShadow = bar.GetHighShadow(); + + // + bool isBullish = + hShadow < body && + lShadow > (bodyMultiplier * body); + + // + bool isBearish = + lShadow < body && + hShadow > (bodyMultiplier * body); + + // + result = isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + return result; + } + + /** + * Check Specified Bar is Engulfed Prev Bar or not ... + * + * @param bar: XOHCL instance reference, Specified Bar to Check ... + * @param dir: ENUM_X_DIRECTION member, Specified Doji Direction ... + * + * @return ( bool ) + */ + bool IsEngulfed( + XOHCL &bar, + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + // + pBar.Clean(); + return result; + } + + // + result = bar.GetBody() > pBar.GetBody(); + if (!result) + { + // + pBar.Clean(); + return result; + } + + // + bool isBullish = + bar.IsBullish() && + pBar.IsBearish() && + bar.GetDown() <= pBar.GetDown() && + bar.GetUp() > pBar.GetUp(); + + // + bool isBearish = + bar.IsBearish() && + pBar.IsBullish() && + bar.GetUp() >= pBar.GetUp() && + bar.GetDown() < pBar.GetDown(); + + // + result = isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + // Cleanup Resources ... + + // + pBar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar is Momentum Bar or not ... + * + * @param bar: XOHCL instance reference, Specified Bar to Check ... + * @param dir: ENUM_X_DIRECTION member, Specified Doji Direction ... + * @param forceBarType: bool, Force Apply Bar Type ... + * @param forceFiboPressure: bool, Force Apply Bar Type ... + * + * @return ( bool ) + */ + bool IsRejected( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + bool forceBarType = true, + bool forceFiboPressure = true // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + // + pBar.Clean(); + return result; + } + + // + bool isBullish = + // + bar.low < pBar.low && + bar.GetShadows() > bar.GetBody() && + bar.GetLowShadow() > bar.GetBody() && + bar.GetLowShadow() > bar.GetHighShadow() + // + ; + + // + bool isBearish = + // + bar.high > pBar.high && + bar.GetShadows() > bar.GetBody() && + bar.GetHighShadow() > bar.GetBody() && + bar.GetHighShadow() > bar.GetLowShadow() + // + ; + + // + result = isBullish || + isBearish; + if (!result) + { + // + pBar.Clean(); + return result; + } + + // + // Check Force Type ... + if (forceBarType) + { + // + isBullish = + isBullish && + bar.IsBullish(); + + // + isBearish = + isBearish && + bar.IsBearish(); + + // + result = isBullish || + isBearish; + if (!result) + { + // + pBar.Clean(); + return result; + } + } + + // + // Check Force Fibo Pressure ... + if (forceFiboPressure) + { + // + bool hasBullishFiboPressure = + HasFiboPressure( + bar, + X_DIRECTION_BULLISH, + X_FIBO_LEVEL_236 // + ); + + // + bool hasBearishFiboPressure = + HasFiboPressure( + bar, + X_DIRECTION_BEARISH, + X_FIBO_LEVEL_236 // + ); + + // + isBullish = + isBullish && + hasBullishFiboPressure; + + // + isBearish = + isBearish && + hasBearishFiboPressure; + } + + // + result = isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + pBar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar is Momentum Bar or not ... + * + * @param bar: XOHCL instance reference, Specified Bar to Check ... + * @param dir: ENUM_X_DIRECTION member, Specified Doji Direction ... + * @param loopback: int, Specified Loopback ... + * + * @return ( bool ) + */ + bool IsMomentum( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + int loopback = 2 // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + loopback = NormalizeInt(loopback, 1); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + // + pBar.Clean(); + return result; + } + + // + // Calculate HH and LL ... + double hh = 0; + double ll = 0; + int hhIDX = -1; + int llIDX = -1; + result = CalculateLoopbackHLData( + hhIDX, + hh, + llIDX, + ll, + bar, + loopback // s + ); + result = + result && + ll > 0 && + hh > ll && + IsValidIndex(llIDX) && + IsValidIndex(hhIDX); + if (!result) + { + // + pBar.Clean(); + return result; + } + + // + bool isBullish = + bar.low > ll && + bar.close >= hh && + bar.IsBullish() && + bar.low > pBar.low && + bar.high > pBar.high && + bar.GetBody() > pBar.GetBody() && + bar.GetRange() > pBar.GetRange() && + bar.GetShadows() < pBar.GetShadows(); + + // + bool isBearish = + bar.high < hh && + bar.close <= ll && + bar.IsBearish() && + bar.low < pBar.low && + bar.high < pBar.high && + bar.GetBody() > pBar.GetBody() && + bar.GetRange() > pBar.GetRange() && + bar.GetShadows() < pBar.GetShadows(); + + // + result = isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + pBar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar is Pullback or not ... + * + * @param bar: XOHCL instance reference, Specified Bar to Check ... + * @param dir: ENUM_X_DIRECTION member, Specified Doji Direction ... + * @param loopback: int, Specified Loopback ... + * @param forceBody: bool, Force Using Body ... + * + * @return ( bool ) + */ + bool IsPullback( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + int loopback = 3, + bool forceBody = false // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + loopback = NormalizeInt(loopback, 3); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Check Bar Must Engulfed ... + result = IsEngulfed( + bar, + dir // + ); + if (!result) + { + return result; + } + + // + // Calculate HH and LL ... + double hh = 0; + double ll = 0; + int hhIDX = -1; + int llIDX = -1; + result = CalculateLoopbackHLData( + hhIDX, + hh, + llIDX, + ll, + bar, + loopback // + ); + result = + result && + ll > 0 && + hh > ll && + IsValidIndex(llIDX) && + IsValidIndex(hhIDX); + if (!result) + { + return result; + } + + // + bool isBullish = + bar.high > hh && + bar.low > ll; + + // + bool isBearish = + bar.high < hh && + bar.low < ll; + + // + result = isBullish || + isBearish; + if (result) + { + // + if (forceBody) + { + // + isBullish = + isBullish && + bar.GetUp() > hh && + bar.GetDown() > ll && + llIDX == bar.Index() + 1; + + // + isBearish = + isBearish && + bar.GetUp() < hh && + bar.GetDown() < ll && + hhIDX == bar.Index() + 1; + + // + result = isBullish || + isBearish; + } + + // + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + } + + // + return result; + } + + /** + * Check Specified Bar is Sequence Edge Breaker Bar or not ... + * + * @param bar: XOHCL instance reference, Specified Bar to Check ... + * @param dir: ENUM_X_DIRECTION member, Holds Founded Direction ... + * @param loopback: int, Specified Loopback ... + * + * @return ( bool ) + */ + bool IsSeqBreakEdge( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + int loopback = 3 // + ) + { + // + bool result = false; + + // + // Normalize Args ... + dir = X_DIRECTION_NONE; + loopback = NormalizeInt(loopback, 3); + + // + // Validate Args ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + bool isBullish = false; + bool isBearish = false; + + // + // Check Has Sequence or not ... + XOHCL pBar; + XOHCL iBar; + XOHCL iPBar; + bool has = false; + int index = bar.Index(); + int start = index + 1; + int end = start + loopback - 1; + bool hasBullishSeq = true; + bool hasBearishSeq = true; + for (int i = start; i < end; i++) + { + // + // Initialize Indexed Bar(s) ... + has = iBar.Init( + bar.symbol, + bar.period, + i // + ); + has = + has && + iBar.GetPreviousBar(iPBar); + + // + // Bullish Sequence ... + if (hasBullishSeq) + { + // + hasBullishSeq = + has && + iBar.low > iPBar.low; + } + + // + // Bearish Sequence ... + if (hasBearishSeq) + { + // + hasBearishSeq = + has && + iBar.high < iPBar.high; + } + + // + if (!hasBullishSeq && + !hasBearishSeq) + { + break; + } + + // + iBar.Clean(); + iPBar.Clean(); + } + iBar.Clean(); + iPBar.Clean(); + + // + // Check a Sequence Detect ... + result = hasBullishSeq || + hasBearishSeq; + if (!result) + { + // + pBar.Clean(); + iBar.Clean(); + iPBar.Clean(); + + // + return result; + } + + // + // Retrieve Previous Bar ... + result = bar.GetPreviousBar(pBar); + + // + // Now we Have Ensure has a Sequence ... + + // + isBullish = + result && + hasBearishSeq && + bar.high > pBar.high; + + // + isBearish = + result && + hasBullishSeq && + bar.low < pBar.low; + + // + // Summarizing Result ... + result = isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + // Cleanup Resources ... + pBar.Clean(); + iBar.Clean(); + iPBar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar is Sequence Type Breaker Bar or not ... + * + * @param bar: XOHCL instance reference, Specified Bar to Check ... + * @param dir: ENUM_X_DIRECTION member, Holds Founded Direction ... + * @param loopback: int, Specified Loopback ... + * + * @return ( bool ) + */ + bool IsSeqBreakType( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + int loopback = 3 // + ) + { + // + bool result = false; + + // + // Normalize Args ... + dir = X_DIRECTION_NONE; + loopback = NormalizeInt(loopback, 3); + + // + // Validate Args ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + bool isBullish = false; + bool isBearish = false; + + // + // Check Has Sequence or not ... + XOHCL iBar; + bool has = false; + int index = bar.Index(); + int start = index + 1; + int end = start + loopback; + bool hasBullishSeq = true; + bool hasBearishSeq = true; + for (int i = start; i < end; i++) + { + // + // Initialize Indexed Bar(s) ... + has = iBar.Init( + bar.symbol, + bar.period, + i // + ); + + // + // Bullish Sequence ... + if (hasBullishSeq) + { + // + hasBullishSeq = + has && + iBar.IsBullish(); + } + + // + // Bearish Sequence ... + if (hasBearishSeq) + { + // + hasBearishSeq = + has && + iBar.IsBearish(); + } + + // + if (!hasBullishSeq && + !hasBearishSeq) + { + break; + } + + // + iBar.Clean(); + } + iBar.Clean(); + + // + // Check a Sequence Detect ... + result = hasBullishSeq || + hasBearishSeq; + if (!result) + { + // + iBar.Clean(); + + // + return result; + } + + // + // Now we Have Ensure has a Sequence ... + + // + isBullish = + result && + hasBearishSeq && + bar.IsBullish(); + + // + isBearish = + result && + hasBullishSeq && + bar.IsBearish(); + + // + // Summarizing Result ... + result = isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + // Cleanup Resources ... + iBar.Clean(); + + // + return result; + } + + /** + * Check Specified Bar is Fully Sequence Breker Bar or not ... + * + * @param bar: XOHCL instance reference, Specified Bar to Check ... + * @param dir: ENUM_X_DIRECTION member, Holds Founded Direction ... + * @param loopback: int, Specified Loopback ... + * + * @return ( bool ) + */ + bool IsSeqBreak( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + int loopback = 3 // + ) + { + // + bool result = false; + + // + // Normalize Args ... + dir = X_DIRECTION_NONE; + loopback = NormalizeInt(loopback, 3); + + // + // Validate Args ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Check Seq Edge ... + ENUM_X_DIRECTION seqEdgeDir; + bool isSeqEdgeBreaked = IsSeqBreakEdge( + bar, + seqEdgeDir // + ); + + // + // Check Seq Type ... + ENUM_X_DIRECTION seqTypeDir; + bool isSeqTypeBreaked = IsSeqBreakType( + bar, + seqTypeDir // + ); + + // + // Check Result ... + result = isSeqEdgeBreaked && + isSeqTypeBreaked && + seqEdgeDir == seqTypeDir; + if (result) + { + dir = seqEdgeDir; + } + + // + return result; + } + + // + // + // + + /** + * Check a Bar is Valid for Specified Direction of Positions ... + * + * @param bar: XOHCL instance, Start Bar ... + * @param dir: ENUM_X_DIRECTION member, Provide Direction ... + * + * @return ( bool ) + */ + bool IsValidForTrigger( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + bool allowCond1 = true, + bool allowCond2 = true, + bool allowCond3 = true, + bool allowCond4 = true, + bool allowCond5 = true, + bool allowCond6 = true, + bool allowCond7 = true // + ) + { + // + bool result = false; + + // + // Normalize Args ... + dir = X_DIRECTION_NONE; + + // + // Validate Args ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // Prepare Requirements ... + XOHCL pBar; + XOHCL p2Bar; + int loopback = 3; + bool isBullish = false; + bool isBearish = false; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + + // + // Retrieve Bar's Prev ... + result = bar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + + // + // Handle Detect Trigger Bar ... + if (result) + { + // + // Check States ... + + // + // Rejected ... + bool isRejected = IsRejected( + pBar, + iDir, + false, // Force Type ... + true // Force Fibo Pressure ... + ); + bool isBullishRejected = + isRejected && + IsBullish(iDir); + bool isBearishRejected = + isRejected && + IsBearish(iDir); + + // + // Simple Rejected ... + bool isSimpleRejected = IsRejected( + pBar, + iDir, + false, // Force Type ... + false // Force Fibo Pressure ... + ); + bool isSimpleBullishRejected = + isSimpleRejected && + IsBullish(iDir); + bool isSimpleBearishRejected = + isSimpleRejected && + IsBearish(iDir); + + // + // Full Directional Rejection ... + bool isFullRejected = IsRejected( + pBar, + iDir, + true, // Force Type ... + true // Force Fibo Pressure ... + ); + bool isFullBullishRejected = + isFullRejected && + IsBullish(iDir); + bool isFullBearishRejected = + isRejected && + IsBearish(iDir); + + // + // Engulfed ... + bool isEngulfed = IsEngulfed( + pBar, + iDir // + ); + bool isBullishEngulfed = + isEngulfed && + IsBullish(iDir); + bool isBearishEngulfed = + isEngulfed && + IsBearish(iDir); + + // + // Momentum ... + bool isMomentum = IsMomentum( + pBar, + iDir // + ); + bool isBullishMomentum = + isMomentum && + IsBullish(iDir); + bool isBearishMomentum = + isMomentum && + IsBearish(iDir); + + // + // Simple Swing ... + bool isSwing = IsSimpleSwing( + pBar, + iDir // + ); + bool isBullishSwing = + isSwing && + IsBullish(iDir); + bool isBearishSwing = + isSwing && + IsBearish(iDir); + + // + // Full Swing ... + bool isFullSwing = IsSwing( + pBar, + iDir, + 5 // + ); + bool isFullBullishSwing = + isFullSwing && + IsBullish(iDir); + bool isFullBearishSwing = + isFullSwing && + IsBearish(iDir); + + // + // Sequence Breaker ... + bool isSeqBreak = IsSeqBreak( + pBar, + iDir, + 3 // + ); + bool isBullishSeqBreak = + isSeqBreak && + IsBullish(iDir); + bool isBearishSeqBreak = + isSeqBreak && + IsBearish(iDir); + + // + // Now we have to Combine Conditions ... + + // + // Cond 1 ... + bool isBullishCond1 = false; + bool isBearishCond1 = false; + if (allowCond1) + { + // + // Bullish ... + isBullishCond1 = + // + isFullBullishRejected + // + ; + + // + // Bearish ... + isBearishCond1 = + // + isFullBearishRejected + // + ; + } + + // + // Cond 2 ... + bool isBullishCond2 = false; + bool isBearishCond2 = false; + if (allowCond2) + { + // + // Bullish ... + isBullishCond2 = + // + isBullishSwing && + isBullishRejected + // + ; + + // + // Bearish ... + isBearishCond2 = + // + isBearishSwing && + isBearishRejected + // + ; + } + + // + // Cond 3 ... + bool isBullishCond3 = false; + bool isBearishCond3 = false; + if (allowCond3) + { + // + // Bullish ... + isBullishCond3 = + // + isBullishSwing && + (isBullishRejected || + isBullishEngulfed || + isBullishMomentum) + // + ; + + // + // Bearish ... + isBearishCond3 = + // + isBearishSwing && + (isBearishRejected || + isBearishEngulfed || + isBearishMomentum) + // + ; + } + + // + // Cond 4 ... + bool isBullishCond4 = false; + bool isBearishCond4 = false; + if (allowCond4) + { + // + // Bullish ... + isBullishCond4 = + // + isBullishSwing && + isBullishSeqBreak && + (isBullishRejected || + isBullishEngulfed || + isBullishMomentum) + // + ; + + // + // Bearish ... + isBearishCond4 = + // + isBearishSwing && + isBearishSeqBreak && + (isBearishRejected || + isBearishEngulfed || + isBearishMomentum) + // + ; + } + + // + // Cond 5 ... + bool isBullishCond5 = false; + bool isBearishCond5 = false; + if (allowCond5) + { + // + // Bullish ... + isBullishCond5 = + // + isFullBullishSwing && + (isBullishRejected || + isBullishEngulfed || + isBullishMomentum) + // + ; + + // + // Bearish ... + isBearishCond5 = + // + isFullBearishSwing && + (isBearishRejected || + isBearishEngulfed || + isBearishMomentum) + // + ; + } + + // + // Cond 6 ... + bool isBullishCond6 = false; + bool isBearishCond6 = false; + if (allowCond6) + { + // + // Bullish ... + isBullishCond6 = + // + p2Bar.IsBearish() && + pBar.IsBullish() && + pBar.low < p2Bar.low && + pBar.high > p2Bar.high && + pBar.GetDown() <= p2Bar.GetDown() && + (isBullishEngulfed || + isBullishMomentum || + isSimpleBullishRejected) + // + ; + + // + // Bearish ... + isBearishCond6 = + // + p2Bar.IsBullish() && + pBar.IsBearish() && + pBar.high > p2Bar.high && + pBar.low < p2Bar.low && + pBar.GetUp() >= p2Bar.GetUp() && + (isBearishEngulfed || + isBearishMomentum || + isSimpleBearishRejected) + // + ; + } + + // + // Cond 7 ... + bool isBullishCond7 = false; + bool isBearishCond7 = false; + if (allowCond7) + { + // + // Bullish ... + isBullishCond7 = + // + p2Bar.IsBearish() && + pBar.IsBullish() && + pBar.low < p2Bar.low && + pBar.high > p2Bar.high && + pBar.GetUp() >= p2Bar.GetUp() + // + ; + + // + // Bearish ... + isBearishCond7 = + // + p2Bar.IsBullish() && + pBar.IsBearish() && + pBar.high > p2Bar.high && + pBar.low < p2Bar.low && + pBar.GetDown() <= p2Bar.GetDown() + // + ; + } + + // + // Summarizie Result ... + + // + isBullish = + // + isBullishCond1 || + isBullishCond2 || + isBullishCond3 || + isBullishCond4 || + isBullishCond5 || + isBullishCond6 || + isBullishCond7 + // + ; + + // + isBearish = + // + isBearishCond1 || + isBearishCond2 || + isBearishCond3 || + isBearishCond4 || + isBearishCond5 || + isBearishCond6 || + isBearishCond7 + // + ; + } + + // + // Summarize Result ... + result = (isBullish && + !isBearish) || + (isBearish && + !isBullish); + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + // Cleanup Resources ... + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + // + protected: + // + + // + private: + // + + // + // Props ... + + // + // Actions ... + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14040316/Classes/x-saherelm.x-cobject.class.mq5 b/BKPS/14040316/Classes/x-saherelm.x-cobject.class.mq5 new file mode 100644 index 0000000..91cc37c --- /dev/null +++ b/BKPS/14040316/Classes/x-saherelm.x-cobject.class.mq5 @@ -0,0 +1,3478 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XChartObjects +// Description: provides all require Chart Objects ... +// +// +// 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.x-poi.lib.mq5" +#include "../Libraries/x-saherelm.x-trade.lib.mq5" + +// +#include +#include +#include +#include +#include +#include + +// +// Definitions ... + +enum ENUM_XCHARTOBJECTS +{ + // + // Global ... + X_ZONE_OBJ = 7860, + X_BOX_OBJ = 7861, + X_BAR_ARROW_OBJ = 7862, + // + X_SIGNAL_OBJ = 8860, + X_TREND_OBJ = 8861, + X_XPVPIVOT_OBJ = 8862, + X_OHCL_OBJ = 8863, + X_RR_OBJ = 8864, + // + // Structured ... + X_TRADE_DAY_OBJ = 9860, + X_MARKET_SESSION_OBJ = 9861, + X_SWING_HIGH_OBJ = 9862, + X_SWING_LOW_OBJ = 9863, + X_BULLISH_MOMENTUM_BAR_OBJ = 9864, + X_BEARISH_MOMENTUM_BAR_OBJ = 9865, + X_BULLISH_REJECTION_BAR_OBJ = 9866, + X_BEARISH_REJECTION_BAR_OBJ = 9867, + X_SUPPORT_ZONE_OBJ = 9868, + X_RESISTANCE_ZONE_OBJ = 9869, + X_SUPPLY_ZONE_OBJ = 9870, + X_DEMAND_ZONE_OBJ = 9871, + X_BULLISH_ORDERBLOCK_OBJ = 9872, + X_BEARISH_ORDERBLOCK_OBJ = 9873, + X_BULLISH_FVG_OBJ = 9874, + X_BEARISH_FVG_OBJ = 9875, + X_TICK_ZONE_OBJ = 9876, + X_TICKS_ZONE_OBJ = 9877, + X_CONSOLIDATION_ZONE_OBJ = 9878, +}; + +enum ENUM_X_CHART_IDS +{ + X_TO, + X_FROM, + X_UPPER, + X_LOWER, + X_ENTRY, + X_TARGET, + X_SL, + X_TP, + X_BAR_H_SHW, + X_BAR_BDY, + X_BAR_L_SHW, +}; + +string ToString(ENUM_X_CHART_IDS value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_TO: + result = "TO"; + break; + + // + case X_FROM: + result = "FROM"; + break; + + // + case X_UPPER: + result = "UPPER"; + break; + + // + case X_LOWER: + result = "LOWER"; + break; + + // + case X_ENTRY: + result = "ENTRY"; + break; + + // + case X_TARGET: + result = "TARGET"; + break; + + // + case X_SL: + result = "SL"; + break; + + // + case X_TP: + result = "TP"; + break; + + // + case X_BAR_H_SHW: + result = "HSHW"; + break; + + // + case X_BAR_BDY: + result = "BODY"; + break; + + // + case X_BAR_L_SHW: + result = "LSHW"; + break; + + // + } + + // + return result; +} + +// +// Extensions ... + +/** + * Converts a XBoxZone struct to XSignal instance ... + * + * @param box: XBoxZone instance reference, provide source info ... + * @param signal: XSignal instance reference, holds prepared converted signal ... + * + * @return ( bool ) + */ +bool ToSignal( + XBoxZone &box, + XSignal &signal, + double &rewardRatios[], + double additionalSL = 0 // +) +{ + // + bool result = false; + + // + signal.Clean(); + + // + result = box.IsValid() && + HasChild(rewardRatios); + if (!result) + { + return result; + } + + // + XOHCL entryBar; + int entryIDX = box.ToIndex(); + if (entryIDX > 0) + { + entryIDX--; + } + result = entryBar.Init( + box.symbol, + box.period, + entryIDX // + ); + if (!result) + { + // + entryBar.Clean(); + + // + return result; + } + + // + bool isBullish = box.IsBullish(); + bool isBearish = box.IsBearish(); + + // + ENUM_POSITION_TYPE iType = + isBullish + ? POSITION_TYPE_BUY + : POSITION_TYPE_SELL; + ENUM_X_POSITION_TYPES iXType = + isBullish + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_SHORT; + + // + double points = GetPoints(box.symbol); + + // + double entry = + isBullish + ? box.upper + : box.lower; + entry = entryBar.open; + + // + double sl = + isBullish + ? box.lower + : box.upper; + if (additionalSL > 0) + { + // + sl = + isBullish + ? sl - additionalSL + : sl + additionalSL; + } + + // + double risk = MathAbs(entry - sl); + + // + double tp = 0; + + // + // Calculate Target ... + XTarget targets[]; + + // + double tmp[]; + int idx = -1; + XTarget iTarget; + bool has = false; + double iRatio = 0; + double iReward = 0; + double iRewardPrice = 0; + Copy( + rewardRatios, + tmp // + ); + while (HasChild(tmp)) + { + // + idx = -1; + iRatio = GetMaxWidthIndex( + tmp, + idx // + ); + + // + has = IsValidIndex(idx); + if (!has) + { + break; + } + + // + has = iRatio > 0; + + // + ArrayRemove( + tmp, + idx, + 1 // + ); + + // + bool canSetTP = tp <= 0; + + // + iReward = iRatio * risk; + + // + iRewardPrice = + isBullish + ? entry + iReward + : entry - iReward; + if (canSetTP) + { + tp = iRewardPrice; + } + else + { + // + iTarget.target = iRewardPrice; + AddRef( + iTarget, + targets // + ); + + // + iTarget.Clean(); + } + } + Clean(tmp); + + // + // Filling Signal ... + signal.tp = tp; + signal.sl = sl; + signal.type = iType; + signal.comment = ""; + signal.entry = entry; + signal.time = box.to; + signal.volume = 0.01; + signal.provider = box.type; + signal.symbol = box.symbol; + signal.period = box.period; + signal.mode = X_ORDER_MODE_MARKET; + + // + if (HasChild(targets)) + { + // + Copy( + targets, + signal.targets // + ); + } + + // + result = signal.IsValid(); + + // + // Cleanup Resources ... + + // + if (!result) + { + signal.Clean(); + } + + // + Clean(tmp); + Clean(targets); + iTarget.Clean(); + entryBar.Clean(); + + // + return result; +} + +// +// Implementation ... + +// +// Global Chart Objects ... + +// +// Bas Chart Object ... +class XCBaseObject : public CChartObject +{ + // + public: + // + + // + // Getter(s) / Setter(s) ... + + /** + * Get Object Specified Name ... + * + * @return ( string ) + */ + string ObjName() + { + return mObjName; + } + + /** + * Set Object Specified Name ... + * + * @param value: String ... + */ + void ObjName(string value) + { + mObjName = value; + } + + // + private: + // + + // + // Props ... + string mObjName; // Object Specified Name ... + + // +}; + +class XCBarArrowObject : public XCBaseObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param name: String, Specified Object ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param swing: XCSwing instance ... + * + * @return ( bool ) + */ + bool CreateByBar( + long chart_id, + string name, + int window, + int arrow, + XOHCL &bar, + ENUM_X_PRICE priceType, + double threshold = 5 // + ) + { + // + bool result = false; + + // + result = + // + bar.IsValid() && + IsValid(name) + // + ; + if (!result) + { + return result; + } + + // + datetime time = bar.time; + double price = bar.GetPrice(priceType); + + // + if (threshold > 0) + { + // + double thresholdPrice = threshold * GetPoints(bar.symbol); + if (priceType == X_PRICE_HIGH) + { + price += thresholdPrice; + } + else if (priceType == X_PRICE_LOW) + { + price -= thresholdPrice; + } + } + + // + result = mArrow.Create( + chart_id, + name, + window, + time, + price, + (char)arrow // + ); + + // + if (result) + { + ObjName(name); + } + + // + return result; + } + + // + // Virtual ... + + // + // Setter(s) ... + + /** + * Set Arrow Anchor ... + * + * @param value: ENUM_ARROW_ANCHOR member ... + */ + void ArrowAnchor(ENUM_ARROW_ANCHOR value) + { + mArrow.Anchor(value); + } + + /** + * Set Arrow Color ... + * + * @param value: Color ... + */ + void ArrowColor(color value) + { + mArrow.Color(value); + } + + /** + * Set Arrow Width ... + * + * @param value: Integer ... + */ + void ArrowWidth(int value) + { + mArrow.Width(value); + } + + // + private: + // + CChartObjectArrow mArrow; + + // +}; + +// +// Swing ... +class XCSwingObject : public XCBarArrowObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param swing: XCSwing instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool CreateBySwing( + long chart_id, + int window, + int arrow, + XCSwing &swing, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = + // + swing.IsValid() + // + ; + if (!result) + { + return result; + } + + // + string name = swing.GetTag(); + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + + // + XOHCL bar; + result = swing.FillBar(bar); + if (!result) + { + return result; + } + + // + ENUM_X_PRICE price = swing.IsSwingHigh() + ? X_PRICE_HIGH + : X_PRICE_LOW; + + // + result = CreateByBar( + chart_id, + name, + window, + arrow, + bar, + price // + ); + + // + if (result) + { + ObjName(name); + } + + // + return result; + } +}; + +// +// Swing High ... +class XCSwingHighObject : public XCSwingObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param arrow: Integer, Specified Arrow Code ... + * @param swing: XCSwing instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + int arrow, + XCSwing &swing, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = swing.IsValid() && + swing.IsSwingHigh(); + if (!result) + { + return result; + } + + // + result = CreateBySwing( + chart_id, + window, + arrow, + swing, + prefix // + ); + + // + return result; + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_SWING_HIGH_OBJ; + } + + // +}; + +// +// Swing Low ... +class XCSwingLowObject : public XCSwingObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param arrow: Integer, Specified Arrow Code ... + * @param swing: XCSwing instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + int arrow, + XCSwing &swing, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = swing.IsValid() && + swing.IsSwingLow(); + if (!result) + { + return result; + } + + // + result = CreateBySwing( + chart_id, + window, + arrow, + swing, + prefix // + ); + + // + return result; + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_SWING_LOW_OBJ; + } + + // +}; + +// +// Momentum ... +class XCMomentumBarObject : public XCBarArrowObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param momentumBar: XCMomentumBar instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool CreateByMomentum( + long chart_id, + int window, + int arrow, + XCMomentumBar &momentumBar, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = + // + momentumBar.IsValid() + // + ; + if (!result) + { + return result; + } + + // + string name = momentumBar.GetTag(); + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + + // + XOHCL bar; + result = momentumBar.FillBar(bar); + if (!result) + { + return result; + } + + // + ENUM_X_PRICE price = momentumBar.IsBullish() + ? X_PRICE_LOW + : X_PRICE_HIGH; + + // + result = CreateByBar( + chart_id, + name, + window, + arrow, + bar, + price // + ); + + // + if (result) + { + ObjName(name); + } + + // + return result; + } +}; + +// +// Bullish Momentum Bar ... +class XCBullishMomentumBarObject : public XCMomentumBarObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param arrow: Integer, Specified Arrow Code ... + * @param momentumBar: XCMomentumBar instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + int arrow, + XCMomentumBar &momentumBar, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = momentumBar.IsValid() && + momentumBar.IsBullish(); + if (!result) + { + return result; + } + + // + result = CreateByMomentum( + chart_id, + window, + arrow, + momentumBar, + prefix // + ); + + // + return result; + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_BULLISH_MOMENTUM_BAR_OBJ; + } + + // +}; + +// +// Bearish Momentum Bar ... +class XCBearishMomentumBarObject : public XCMomentumBarObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param arrow: Integer, Specified Arrow Code ... + * @param momentumBar: XCMomentumBar instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + int arrow, + XCMomentumBar &momentumBar, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = momentumBar.IsValid() && + momentumBar.IsBearish(); + if (!result) + { + return result; + } + + // + result = CreateByMomentum( + chart_id, + window, + arrow, + momentumBar, + prefix // + ); + + // + return result; + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_BEARISH_MOMENTUM_BAR_OBJ; + } + + // +}; + +// +// Rejection ... +class XCRejectionBarObject : public XCBarArrowObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param rejectionBar: XCRejectionBar instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool CreateByRejection( + long chart_id, + int window, + int arrow, + XCRejectionBar &rejectionBar, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = + // + rejectionBar.IsValid() + // + ; + if (!result) + { + return result; + } + + // + string name = rejectionBar.GetTag(); + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + + // + XOHCL bar; + result = rejectionBar.FillBar(bar); + if (!result) + { + return result; + } + + // + ENUM_X_PRICE price = rejectionBar.IsBullish() + ? X_PRICE_LOW + : X_PRICE_HIGH; + + // + result = CreateByBar( + chart_id, + name, + window, + arrow, + bar, + price // + ); + + // + if (result) + { + ObjName(name); + } + + // + return result; + } +}; + +// +// Bullish Rejection Bar ... +class XCBullishRejectionBarObject : public XCRejectionBarObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param arrow: Integer, Specified Arrow Code ... + * @param rejectionBar: XCRejectionBar instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + int arrow, + XCRejectionBar &rejectionBar, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = rejectionBar.IsValid() && + rejectionBar.IsBullish(); + if (!result) + { + return result; + } + + // + result = CreateByRejection( + chart_id, + window, + arrow, + rejectionBar, + prefix // + ); + + // + return result; + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_BULLISH_REJECTION_BAR_OBJ; + } + + // +}; + +// +// Bearish Rejection Bar ... +class XCBearishRejectionBarObject : public XCRejectionBarObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param arrow: Integer, Specified Arrow Code ... + * @param rejectionBar: XCRejectionBar instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + int arrow, + XCRejectionBar &rejectionBar, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = rejectionBar.IsValid() && + rejectionBar.IsBearish(); + if (!result) + { + return result; + } + + // + result = CreateByRejection( + chart_id, + window, + arrow, + rejectionBar, + prefix // + ); + + // + return result; + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_BEARISH_REJECTION_BAR_OBJ; + } + + // +}; + +// +// XCZoneObject ... +class XCZoneObject : public XCBaseObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param name: String, Specified Object Identifier on Chart ... + * @param window: Integer, Specified Chart Window ID ... + * @param zone: XCZone instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool CreateByZone( + long chart_id, + string name, + int window, + XCZone &zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + bool isValidFrom = zone.IsValidFrom(); + bool isValidBoundary = zone.IsValidBoundary(); + + // + result = + // + IsValid(name) && + isValidFrom && + isValidBoundary + // + ; + if (!result) + { + return result; + } + + // + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + + // + datetime from = zone.From(); + datetime to = NormalizeTime(zone.To()); + + // + double upper = zone.Upper(); + double lower = zone.Lower(); + + // + result = mRect.Create( + chart_id, + name, + window, + from, + upper, + to, + lower // + ); + + // + if (result) + { + ObjName(name); + } + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_ZONE_OBJ; + } + + // + // Setter(s) ... + + /** + * Set Zone Width ... + * + * @param value: Integer ... + */ + void ZoneWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mRect.Width(value); + } + + /** + * Set Zone Color ... + * + * @param value: Color ... + */ + void ZoneColor(color value) + { + mRect.Color(value); + } + + /** + * Set Zone Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void ZoneStyle(ENUM_LINE_STYLE value) + { + mRect.Style(value); + } + + /** + * Set Zone Fill ... + * + * @param value: Boolean ... + */ + void ZoneFill(bool value) + { + mRect.Fill(value); + } + + // + private: + // + CChartObjectRectangle mRect; + + // +}; + +// +// Support Zone ... +class XCSupportZoneObject : public XCZoneObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param zone: XCSupportZone instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XCSupportZone &zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + string name = zone.GetTag(); + + // + result = CreateByZone( + chart_id, + name, + window, + zone, + prefix // + ); + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_SUPPORT_ZONE_OBJ; + } +}; + +// +// Resistance Zone ... +class XCResistanceZoneObject : public XCZoneObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param zone: XCResistanceZone instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XCResistanceZone &zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + string name = zone.GetTag(); + + // + result = CreateByZone( + chart_id, + name, + window, + zone, + prefix // + ); + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_RESISTANCE_ZONE_OBJ; + } +}; + +// +// Supply Zone ... +class XCSupplyZoneObject : public XCZoneObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param zone: XCSupplyZone instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XCSupplyZone &zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + string name = zone.GetTag(); + + // + result = CreateByZone( + chart_id, + name, + window, + zone, + prefix // + ); + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_SUPPLY_ZONE_OBJ; + } +}; + +// +// Demand Zone ... +class XCDemandZoneObject : public XCZoneObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param zone: XCDemandZone instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XCDemandZone &zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + string name = zone.GetTag(); + + // + result = CreateByZone( + chart_id, + name, + window, + zone, + prefix // + ); + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_DEMAND_ZONE_OBJ; + } +}; + +// +// Bullish Order Block ... +class XCBullishOrderBlockObject : public XCZoneObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param zone: XCOrderBlock instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XCOrderBlock &zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = zone.IsValid() && + zone.IsBullish(); + if (!result) + { + return result; + } + + // + string name = zone.GetTag(); + + // + result = CreateByZone( + chart_id, + name, + window, + zone, + prefix // + ); + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_BULLISH_ORDERBLOCK_OBJ; + } +}; + +// +// Bearish Order Block ... +class XCBearishOrderBlockObject : public XCZoneObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param zone: XCOrderBlock instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XCOrderBlock &zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = zone.IsValid() && + zone.IsBearish(); + if (!result) + { + return result; + } + + // + string name = zone.GetTag(); + + // + result = CreateByZone( + chart_id, + name, + window, + zone, + prefix // + ); + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_BULLISH_ORDERBLOCK_OBJ; + } +}; + +// +// Bullish Fair Value Gaps ... +class XCBullishFairValueGapObject : public XCZoneObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param zone: XCOrderBlock instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XCFVG &zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = zone.IsValid() && + zone.IsBullish(); + if (!result) + { + return result; + } + + // + string name = zone.GetTag(); + + // + result = CreateByZone( + chart_id, + name, + window, + zone, + prefix // + ); + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_BULLISH_FVG_OBJ; + } +}; + +class XCConsolidationZoneObject : public XCBaseObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param zone: XConsolidationZone instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XConsolidationZone &zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + string name = zone.GetTag(); + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + + // + result = mRect.Create( + chart_id, + name, + window, + zone.from, + zone.upper, + zone.to, + zone.lower // + ); + + // + if (result) + { + ObjName(name); + } + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_CONSOLIDATION_ZONE_OBJ; + } + + // + // Setter(s) ... + + /** + * Set Zone Width ... + * + * @param value: Integer ... + */ + void ZoneWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mRect.Width(value); + } + + /** + * Set Zone Color ... + * + * @param value: Color ... + */ + void ZoneColor(color value) + { + mRect.Color(value); + } + + /** + * Set Zone Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void ZoneStyle(ENUM_LINE_STYLE value) + { + mRect.Style(value); + } + + /** + * Set Zone Fill ... + * + * @param value: Boolean ... + */ + void ZoneFill(bool value) + { + mRect.Fill(value); + } + + // + private: + // + CChartObjectRectangle mRect; + + // +}; + +// +// Bearish Fair Value Gaps ... +class XCBearishFairValueGapObject : public XCZoneObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param zone: XCOrderBlock instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XCFVG &zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = zone.IsValid() && + zone.IsBearish(); + if (!result) + { + return result; + } + + // + string name = zone.GetTag(); + + // + result = CreateByZone( + chart_id, + name, + window, + zone, + prefix // + ); + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_BEARISH_FVG_OBJ; + } +}; + +// +// Signal ... +class XCSignalObject : public XCBaseObject +{ + // + public: + // + + // + // Constructor ... + void XCSignalObject() + { + } + + // + // Deconstructor ... + void ~XCSignalObject() + { + } + + /** + * Create a Signal Object on Chart ... + * + * @param chart_id: Long ... + * @param name: String ... + * @param window: Integer ... + * @param signal: XSignal instance ... + * @param length: int, Specified Length of Signal ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + const int window, + XSignal &signal, + int length = 3, + string prefix = NULL // + ) + { + // + bool result = false; + + // + length = NormalizeInt(length, 3); + + // + result = signal.IsValid(); + if (!result) + { + return result; + } + + // + string name = signal.GetTag(); + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + string nameMD5 = ToMD5(name); + + // + int delay = (PeriodSeconds(signal.period) * length); + datetime time1 = (datetime)((int)signal.time - delay); + datetime time2 = (datetime)((int)signal.time + delay); + + // + // TP ... + string tpName = ToString(X_TP) + "_" + nameMD5; + result = mTPTrend.Create( + chart_id, + tpName, + window, + time1, + signal.tp, + time2, + signal.tp // + ); + if (!result) + { + return result; + } + + // + // SL ... + string slName = ToString(X_SL) + "_" + nameMD5; + result = mSLTrend.Create( + chart_id, + slName, + window, + time1, + signal.sl, + time2, + signal.sl // + ); + if (!result) + { + // + mTPTrend.Delete(); + return result; + } + + // + // TARGET ... + bool hasTargets = HasChild(signal.targets); + if (hasTargets) + { + // + int targetsCount = ArraySize(signal.targets); + for (int i = 0; i < targetsCount; i++) + { + // + string targetName = ToString(X_TARGET) + "_" + ToString(i) + "_" + nameMD5; + CChartObjectTrend *mTargetTrend; + mTargetTrend = new CChartObjectTrend(); + result = mTargetTrend.Create( + chart_id, + targetName, + window, + time1, + signal.targets[i].target, + time2, + signal.targets[i].target // + ); + if (!result) + { + // + mTPTrend.Delete(); + mSLTrend.Delete(); + break; + } + + // + mTargetTrends.Add(mTargetTrend); + } + } + + // + // ENTRY ... + string entrName = ToString(X_ENTRY) + "_" + nameMD5; + result = mEntryTrend.Create( + chart_id, + entrName, + window, + time1, + signal.entry, + time2, + signal.entry // + ); + if (!result) + { + // + mTPTrend.Delete(); + mSLTrend.Delete(); + mTargetTrends.Clear(); + return result; + } + + // + // Set Object Name ... + ObjName(name); + + // + return result; + } + + // + // Setter(s) ... + + // + // TP ... + + /** + * Set TP Width ... + * + * @param value: Integer ... + */ + void TPWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mTPTrend.Width(value); + } + + /** + * Set TP Color ... + * + * @param value: Color ... + */ + void TPColor(color value) + { + mTPTrend.Color(value); + } + + /** + * Set TP Style ... + * + * @param value: ENUM_LINE_STYLE ... + */ + void TPStyle(ENUM_LINE_STYLE value) + { + mTPTrend.Style(value); + } + + // + // SL ... + + /** + * Set SL Width ... + * + * @param value: Integer ... + */ + void SLWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mSLTrend.Width(value); + } + + /** + * Set SL Color ... + * + * @param value: Color ... + */ + void SLColor(color value) + { + mSLTrend.Color(value); + } + + /** + * Set SL Style ... + * + * @param value: ENUM_LINE_STYLE ... + */ + void SLStyle(ENUM_LINE_STYLE value) + { + mSLTrend.Style(value); + } + + // + // TARGET ... + + /** + * Set Target Width ... + * + * @param value: Integer ... + */ + void TargetWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + for (int i = 0; i < mTargetTrends.Total(); i++) + { + // + CChartObjectTrend *iTrend = (CChartObjectTrend *)mTargetTrends.At(i); + iTrend.Width(value); + } + } + + /** + * Set Target Color ... + * + * @param value: Color ... + */ + void TargetColor(color value) + { + // + for (int i = 0; i < mTargetTrends.Total(); i++) + { + // + CChartObjectTrend *iTrend = (CChartObjectTrend *)mTargetTrends.At(i); + iTrend.Color(value); + } + } + + /** + * Set Target Style ... + * + * @param value: ENUM_LINE_STYLE ... + */ + void TargetStyle(ENUM_LINE_STYLE value) + { + // + for (int i = 0; i < mTargetTrends.Total(); i++) + { + // + CChartObjectTrend *iTrend = (CChartObjectTrend *)mTargetTrends.At(i); + iTrend.Style(value); + } + } + + // + // ENTRY ... + + /** + * Set Entry Width ... + * + * @param value: Integer ... + */ + void EntryWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mEntryTrend.Width(value); + } + + /** + * Set Entry Color ... + * + * @param value: Color ... + */ + void EntryColor(color value) + { + mEntryTrend.Color(value); + } + + /** + * Set Entry Style ... + * + * @param value: ENUM_LINE_STYLE ... + */ + void EntryStyle(ENUM_LINE_STYLE value) + { + mEntryTrend.Style(value); + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_SIGNAL_OBJ; + } + + // + private: + // + + // + CChartObjectTrend mTPTrend; + CChartObjectTrend mSLTrend; + CChartObjectTrend mEntryTrend; + CArrayObj mTargetTrends; +}; + +// +// XRR Object ... +class XCRRObject : public XCSignalObject +{ + // + // Public ... + public: + // + // Constructor ... + bool CreateBoxRR( + long chart_id, + const int window, + XBoxZone &box, + double &rewardRatios[], + int length = 3, + string prefix = NULL // + ) + { + // + bool result = false; + + // + length = NormalizeInt(length, 3); + + // + result = box.IsValid(); + if (!result) + { + return result; + } + + // + XSignal signal; + result = ToSignal( + box, + signal, + rewardRatios // + ); + if (!result) + { + // + signal.Clean(); + + // + return result; + } + + // + result = Create( + chart_id, + window, + signal, + length, + prefix // + ); + + // + signal.Clean(); + + // + return result; + } +}; + +class XCOHCLObject : public XCBaseObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param pivot: XPVPivot instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XOHCL &bar, + datetime to, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = bar.IsValid() && + IsValid(to); + if (!result) + { + return result; + } + + // + string name = bar.GetTag(); + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + string nameMD5 = ToMD5(name); + + // + // High Shadow ... + string hShadowName = ToString(X_BAR_H_SHW) + "_" + nameMD5; + + // + result = mHighShadowRect.Create( + chart_id, + hShadowName, + window, + bar.time, + bar.high, + to, + bar.GetUp() // + ); + if (!result) + { + return result; + } + + // + // Body ... + string bodyName = ToString(X_BAR_BDY) + "_" + nameMD5; + + // + result = mBodyRect.Create( + chart_id, + bodyName, + window, + bar.time, + bar.GetUp(), + to, + bar.GetDown() // + ); + if (!result) + { + // + mHighShadowRect.Delete(); + mHighShadowRect.Detach(); + return result; + } + + // + // Low Shadow ... + string lShadowName = ToString(X_BAR_L_SHW) + "_" + nameMD5; + + // + result = mLowShadowRect.Create( + chart_id, + lShadowName, + window, + bar.time, + bar.GetDown(), + to, + bar.low // + ); + if (!result) + { + // + mBodyRect.Delete(); + mBodyRect.Detach(); + mHighShadowRect.Delete(); + mHighShadowRect.Detach(); + return result; + } + + // + if (result) + { + ObjName(name); + } + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Set High Shadow Width ... + * + * @param value: Integer ... + */ + void HighShadowWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mHighShadowRect.Width(value); + } + + /** + * Set High Shadow Color ... + * + * @param value: Color ... + */ + void HighShadowColor(color value) + { + mHighShadowRect.Color(value); + } + + /** + * Set High Shadow Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void HighShadowStyle(ENUM_LINE_STYLE value) + { + mHighShadowRect.Style(value); + } + + /** + * Set High Shadow Fill ... + * + * @param value: Boolean ... + */ + void HighShadowFill(bool value) + { + mHighShadowRect.Fill(value); + } + + /** + * Set Body Width ... + * + * @param value: Integer ... + */ + void BodyWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mBodyRect.Width(value); + } + + /** + * Set Body Color ... + * + * @param value: Color ... + */ + void BodyColor(color value) + { + mBodyRect.Color(value); + } + + /** + * Set Body Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void BodyStyle(ENUM_LINE_STYLE value) + { + mBodyRect.Style(value); + } + + /** + * Set Body Fill ... + * + * @param value: Boolean ... + */ + void BodyFill(bool value) + { + mBodyRect.Fill(value); + } + + /** + * Set Low Shadow Width ... + * + * @param value: Integer ... + */ + void LowShadowWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mLowShadowRect.Width(value); + } + + /** + * Set Low Shadow Color ... + * + * @param value: Color ... + */ + void LowShadowColor(color value) + { + mLowShadowRect.Color(value); + } + + /** + * Set Low Shadow Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void LowShadowStyle(ENUM_LINE_STYLE value) + { + mLowShadowRect.Style(value); + } + + /** + * Set Low Shadow Fill ... + * + * @param value: Boolean ... + */ + void LowShadowFill(bool value) + { + mLowShadowRect.Fill(value); + } + + void BarSpes( + int width = 1, + color clr = clrNONE, + ENUM_LINE_STYLE style = STYLE_SOLID, + bool fill = false // + ) + { + // + BodyWidth(width); + LowShadowWidth(width); + HighShadowWidth(width); + + // + BodyColor(clr); + LowShadowColor(clr); + HighShadowColor(clr); + + // + BodyStyle(style); + LowShadowStyle(style); + HighShadowStyle(style); + + // + BodyFill(fill); + LowShadowFill(fill); + HighShadowFill(fill); + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_OHCL_OBJ; + } + + // + private: + // + + // + // Props ... + CChartObjectRectangle mHighShadowRect; + CChartObjectRectangle mBodyRect; + CChartObjectRectangle mLowShadowRect; +}; + +class XCBoxObject : public XCBaseObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param pivot: XPVPivot instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + string name, + double upper, + double lower, + datetime from, + datetime to, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = + upper > 0 && + lower > 0 && + to > from && + IsValid(to) && + IsValid(name) && + IsValid(from) && + upper > lower; + if (!result) + { + return result; + } + + // + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + string nameMD5 = ToMD5(name); + + // + result = mRect.Create( + chart_id, + name, + window, + from, + upper, + to, + lower // + ); + if (!result) + { + return result; + } + + // + if (result) + { + ObjName(name); + } + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Set Width ... + * + * @param value: Integer ... + */ + void BoxWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mRect.Width(value); + } + + /** + * Set Color ... + * + * @param value: Color ... + */ + void BoxColor(color value) + { + mRect.Color(value); + } + + /** + * Set Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void BoxStyle(ENUM_LINE_STYLE value) + { + mRect.Style(value); + } + + /** + * Set Fill ... + * + * @param value: Boolean ... + */ + void BoxFill(bool value) + { + mRect.Fill(value); + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_BOX_OBJ; + } + + // + private: + // + + // + // Props ... + CChartObjectRectangle mRect; +}; + +// +// Zone Ticks ... + +// +// Specify How to Draws Specified Levels ... +struct XTickZoneLevelSpecs +{ + // + double percent; // Max Allowed Percent of Tick Zone ... + + // + // Label Info ... + color labelColor; + string labelFont; + int labelFontSize; + double labelAngel; + + // + // Zone Info ... + bool zoneFill; + int zoneWidth; + color zoneColor; + ENUM_LINE_STYLE zoneStyle; + + // + // Constructor ... + XTickZoneLevelSpecs() + { + Default(); + } + + // + // Tools ... + + /** + * Initialize Drawing Specs ... + * + * @param _percent: Double, Max Allowed Percent ... + * @param _labelColor: Color, Specified Label Color ... + * @param _zoneColoe: Color, Specified Zone Color ... + * @param _zoneFill: Boolean, Specified Fill Zone or not ... + * @param _zoneStyle: ENUM_LINE_STYLE member, Specified Zone Style ... + * @param _labelFontSize: Integer, Specified Label Font Size ... + * @param _labelFont: String, Specified Label Font Name ... + * @param _labelAngel: Double, Specified Label Angel ... + * + * @return ( bool ) + */ + bool Init( + double _percent, + color _labelColor = clrWhite, + color _zoneColor = clrWhite, + bool _zoneFill = false, + ENUM_LINE_STYLE _zoneStyle = STYLE_DOT, + int _zoneWidth = 1, + int _labelFontSize = 12, + string _labelFont = "Arial", + double _labelAngel = 0 // + ) + { + // + bool result = false; + + // + Default(); + + // + result = _percent > 0; + if (!result) + { + return result; + } + + // + percent = _percent; + labelColor = _labelColor; + zoneColor = _zoneColor; + zoneFill = _zoneFill; + zoneStyle = _zoneStyle; + + // + if (_zoneWidth > 0) + { + zoneWidth = _zoneWidth; + } + + // + if (_labelFontSize > 0) + { + labelFontSize = _labelFontSize; + } + + // + if (IsSpecifiedValid(_labelFont)) + { + labelFont = _labelFont; + } + + // + if (_labelAngel >= 0) + { + labelAngel = _labelAngel; + } + + // + result = IsValid(); + + // + return result; + } + + /** + * Set Default Properties ... + */ + void Default() + { + // + percent = 0; + + // + // Label ... + labelAngel = 0; + labelFontSize = 13; + labelFont = "Arial"; + labelColor = clrWhite; + + // + // Zone ... + zoneWidth = 1; + zoneFill = false; + zoneColor = clrWhite; + zoneStyle = STYLE_DOT; + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + // + percent > 0 && + // + // Zone ... + zoneWidth > 0 && + // + // Label ... + labelFontSize > 0 && + IsSpecifiedValid(labelFont) + // + ; + + // + return result; + } + + // +}; + +class XCTickZoneObject : public XCBaseObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param name: String, Specify Chart Object Identifier ... + * @param from: Datetime ... + * @param to: Datetime ... + * @param zone: XCTickZone instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + string name, + datetime from, + datetime to, + XCTickZone *zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = + IsValid(name) && + zone.IsValid() && + IsValid(to) && + IsValid(from); + if (!result) + { + return result; + } + + // + double points = GetPoints(zone.symbol); + if (points <= 0) + { + points = 1; + } + double distance = 1 * points; + + // + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + + // + string rectName = "TKZ_" + name; + result = mRect.Create( + chart_id, + rectName, + window, + from, + zone.high, + to, + zone.low // + ); + if (!result) + { + return result; + } + + // + int fromToDiff = ((int)to - (int)from); + datetime labelsDate = (datetime)((int)to - (fromToDiff / 5)); + + // + string lblName = "LBLT_" + name; + result = mTLabel.Create( + chart_id, + lblName, + window, + labelsDate, + zone.high - distance // + ); + if (!result) + { + return result; + } + + // + mTLabel.Description("T: " + ToString(zone.percent) + "%"); + + // + string lblVName = "LBLV_" + name; + result = mVLabel.Create( + chart_id, + lblVName, + window, + labelsDate, + zone.low + (2.5 * distance) // + ); + if (!result) + { + return result; + } + + // + mVLabel.Description("V: " + ToString(zone.volumePercent) + "%"); + + // + ObjName(name); + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_TICK_ZONE_OBJ; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Set Zone Width ... + * + * @param value: Integer ... + */ + void ZoneWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mRect.Width(value); + } + + /** + * Set Zone Color ... + * + * @param value: Color ... + */ + void ZoneColor(color value) + { + mRect.Color(value); + } + + /** + * Set Zone Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void ZoneStyle(ENUM_LINE_STYLE value) + { + mRect.Style(value); + } + + /** + * Set Zone Fill ... + * + * @param value: Boolean ... + */ + void ZoneFill(bool value) + { + mRect.Fill(value); + } + + /** + * Set Label Color ... + * + * @param value: Color ... + */ + void LabelColor(color value) + { + // + mTLabel.Color(value); + mVLabel.Color(value); + } + + /** + * Set Label Size ... + * + * @param value: Integer ... + */ + void LabelSize(int value) + { + // + mTLabel.FontSize(value); + mVLabel.FontSize(value); + } + + /** + * Set Label Font ... + * + * @param value: String ... + */ + void LabelFont(string value) + { + // + mTLabel.Font(value); + mVLabel.Font(value); + } + + /** + * Set Label Angle ... + * + * @param value: double ... + */ + void LabelAngle(double value) + { + // + mTLabel.Angle(value); + mVLabel.Angle(value); + } + + // + private: + // + // Props ... + CChartObjectRectangle mRect; + CChartObjectLabel mTLabel; + CChartObjectLabel mVLabel; + + // +}; +class XCTicksZoneObject : public XCBaseObject +{ + // + public: + // + + // + void ~XCTicksZoneObject() + { + mZones.Clear(); + } + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param zone: XCTicksZone instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XCTicksZone &zone, + XTickZoneLevelSpecs &specs[], + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + string name = zone.GetTag(); + int levels = zone.Levels(); + result = levels > 0; + if (!result) + { + return result; + } + + // + for (int i = 0; i < levels; i++) + { + // + XCTickZone *iZone = zone.GetZone(i); + XCTickZoneObject *iObj; + iObj = new XCTickZoneObject(); + bool isCreated = iObj.Create( + chart_id, + window, + ToString(i) + "_" + name, + zone.From(), + zone.To(), + iZone, + prefix // + ); + if (!isCreated) + { + break; + } + + // + XTickZoneLevelSpecs iSpec; + bool hasSpecs = FindSpecs( + iZone, + iSpec, + specs // + ); + if (hasSpecs) + { + // + // Label ... + iObj.LabelFont(iSpec.labelFont); + iObj.LabelAngle(iSpec.labelAngel); + iObj.LabelColor(iSpec.labelColor); + iObj.LabelSize(iSpec.labelFontSize); + + // + // Zone ... + iObj.ZoneFill(iSpec.zoneFill); + iObj.ZoneColor(iSpec.zoneColor); + iObj.ZoneWidth(iSpec.zoneWidth); + iObj.ZoneStyle(iSpec.zoneStyle); + } + + // + mZones.Add(iObj); + } + + // + if (result) + { + ObjName(name); + } + else + { + mZones.Clear(); + } + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_TICKS_ZONE_OBJ; + } + + // + // Getter(s) / Setter(s) ... + + // + // Actions ... + + /** + * Destroy Object ... + */ + void Destroy() + { + mZones.Clear(); + } + + /** + * Find Specified TickZone Drawing Specs ... + * + * @param zone: XCTickZone instance, reference to Search For it ... + * @param spec: XTickZoneLevelSpecs instance, reference to Result ... + * @param specs: XTickZoneLevelSpecs instance Collection for Search ... + * + * @return ( bool ) + */ + bool FindSpecs( + XCTickZone *zone, + XTickZoneLevelSpecs &spec, + XTickZoneLevelSpecs &specs[] // + ) + { + // + bool result = false; + + // + int count = ArraySize(specs); + result = + zone.IsValid() && + IsValidSize(count); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XTickZoneLevelSpecs iSpecs = specs[i]; + + // + bool isSpecValidForZone = + !spec.IsValid() + ? zone.percent <= iSpecs.percent + : zone.percent <= iSpecs.percent && + spec.percent > iSpecs.percent; + if (isSpecValidForZone) + { + spec = iSpecs; + } + } + + // + result = spec.IsValid(); + + // + return result; + } + + // + private: + // + // Props ... + CArrayObj mZones; + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14040316/Classes/x-saherelm.x-data.collector.class.mq5 b/BKPS/14040316/Classes/x-saherelm.x-data.collector.class.mq5 new file mode 100644 index 0000000..fb45c04 --- /dev/null +++ b/BKPS/14040316/Classes/x-saherelm.x-data.collector.class.mq5 @@ -0,0 +1,362 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XCDataCollector ... +// Description: Class for Handling Data Read or Write ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm Class for Handling Data Read or Write" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.base.class.mq5" + +// +// Definitions ... + +// +// Implementation ... +class XCDataCollector : public XCBase +{ + // + // Public ... + public: + // + // Constructors ... + XCDataCollector() + { + mPath = "XDataCollector"; + } + + // + // Deconstructor ... + ~XCDataCollector() + { + } + + // + // Properties ... + + // + string Path() + { + return mPath; + } + + // + void Path(string value) + { + mPath = value; + } + + // + // Tools ... + + // + string GetFilePath(string fileName) + { + // + string result = ""; + + // + result = + // + (IsValid(mPath) ? mPath + "\\" : "") + fileName + ".x121.log" + // + ; + + // + return result; + } + + // + int GetFileHandlerForWrite(string filePath) + { + // + int result = INVALID_HANDLE; + + // + if (!IsValid(filePath)) + { + return result; + } + + // + result = FileOpen( + filePath, + FILE_READ | FILE_WRITE | FILE_TXT // + ); + + // + return result; + } + + // + int GetFileHandlerForRead(string filePath) + { + // + int result = INVALID_HANDLE; + + // + if (!IsValid(filePath)) + { + return result; + } + + // + result = FileOpen( + filePath, + FILE_READ | FILE_TXT | FILE_ANSI // + ); + + // + return result; + } + + /** + * Save Specified Content into Specified File Name ... + * + * @param fileName: string, file name ... + * @param content: string, content ... + * + * @return ( bool ) + */ + bool Save( + string fileName, + string content // + ) + { + // + bool result = false; + + // + result = IsValid(fileName) && + IsValid(content); + if (!result) + { + return result; + } + + // + int mHandler = GetFileHandlerForWrite(fileName); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + FileWrite(mHandler, content); + FileFlush(mHandler); + FileClose(mHandler); + + // + return result; + } + + /** + * Append Specified Content into Specified File Name ... + * + * @param fileName: string, file name ... + * @param content: string, content ... + * + * @return ( bool ) + */ + bool Append( + string fileName, + string content // + ) + { + // + bool result = false; + + // + result = IsValid(fileName) && + IsValid(content); + if (!result) + { + return result; + } + + // + int mHandler = GetFileHandlerForWrite(fileName); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + FileSeek(mHandler, 0, SEEK_END); + FileWrite(mHandler, content); + FileFlush(mHandler); + FileClose(mHandler); + + // + return result; + } + + /** + * Read Specified File Content ... + * + * @param fileName: string, file name ... + * @param content: string reference, hold's reading content ... + * + * @return ( bool ) + */ + bool Read( + string fileName, + string &content // + ) + { + // + bool result = false; + + // + // Normalize Args ... + content = NULL; + + // + // Validate Args ... + result = IsValid(fileName); + if (!result) + { + return result; + } + + // + int mHandler = GetFileHandlerForRead(fileName); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // Reading File ... + while (!FileIsEnding(mHandler)) + { + // + string iLine = FileReadString(mHandler); + content += iLine; + } + + // + // Close File ... + FileClose(mHandler); + + // + return result; + } + + /** + * Read Specified File Content ... + * + * @param fileName: string, file name ... + * @param content: string reference collection, hold's reading content lines ... + * + * @return ( bool ) + */ + bool Read( + string fileName, + string &content[] // + ) + { + // + bool result = false; + + // + // Normalize Args ... + Clean(content); + + // + // Validate Args ... + result = IsValid(fileName); + if (!result) + { + return result; + } + + // + int mHandler = GetFileHandlerForRead(fileName); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // Reading File ... + while (!FileIsEnding(mHandler)) + { + // + string iLine = FileReadString(mHandler); + Add( + iLine, + content // + ); + } + + // + // Close File ... + FileClose(mHandler); + + // + return result; + } + + /** + * Check Specified File Exists or not ... + * + * @param fileName: string, Full Path of File to Check ... + * + * @return ( bool ) + */ + bool IsExists(string fileName) + { + // + bool result = false; + + // + // Validate Args ... + result = IsValid(fileName); + if (!result) + { + return result; + } + + // + // Check File Exists or not ... + int mHandler = GetFileHandlerForRead(fileName); + result = mHandler != INVALID_HANDLE; + FileClose(mHandler); + + // + return result; + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + + // + string mPath; // Base Collector Path ... +}; diff --git a/BKPS/14040316/Classes/x-saherelm.x-guard.class.mq5 b/BKPS/14040316/Classes/x-saherelm.x-guard.class.mq5 new file mode 100644 index 0000000..eddbf3a --- /dev/null +++ b/BKPS/14040316/Classes/x-saherelm.x-guard.class.mq5 @@ -0,0 +1,2009 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCXGuard ... +// Description: Guard Provider Class ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm Guard Provider Class" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.x-alert.class.mq5" +#include "../Classes/x-saherelm.x-trade.class.mq5" + +// +// Enumeration ... + +// +// Guard Actions ... +enum ENUM_X_GUARD_ACTIONS +{ + X_GUARD_ACTION_NONE, // Nothing to Do + X_GUARD_ACTION_CLOSE, // Close Specified Position + X_GUARD_ACTION_CLOSE_ALL, // Close All Positions + X_GUARD_ACTION_CLOSE_LONGS, // Close All Long Positions + X_GUARD_ACTION_CLOSE_SHORTS, // Close All Short Position + X_GUARD_ACTION_CLOSE_IN_LOSTS, // Close All In Lost Position + X_GUARD_ACTION_CLOSE_IN_PROFITS, // Close All In Profit Position + X_GUARD_ACTION_CLOSE_IN_LOST_LONGS, // Close All In Lost Long Position + X_GUARD_ACTION_CLOSE_IN_PROFIT_LONGS, // Close All In Profit Long Position + X_GUARD_ACTION_CLOSE_IN_LOST_SHORTS, // Close All In Lost Short Position + X_GUARD_ACTION_CLOSE_IN_PROFITS_SHORT, // Close All In Profit Short Position + X_GUARD_ACTION_PARTIAL_CLOSE, // Partial Close Specified Position + X_GUARD_ACTION_TRAIL_STOP, // Trail Stop of Specified Position + X_GUARD_ACTION_TRAIL_TARGET, // Trail Target of Specified Position + X_GUARD_ACTION_HEDGE, // Hedge Specified Positions +}; + +// +// Definitions ... + +// +// Model a Guard Action ... +struct XGuard +{ + // + // Props ... + ENUM_X_GUARD_ACTIONS action; + datetime time; + + // + string symbol; + string provider; + ENUM_TIMEFRAMES period; + + // + // Specified Position ... + ulong ticket; + + // + // Partial Close ... + double volumeMultiplier; + + // + // SL Trial ... + double sl; + + // + // TP Trial ... + double tp; + + // + bool force; + + // + // Constructor ... + XGuard() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + time = NULL; + action = X_GUARD_ACTION_NONE; + + // + symbol = NULL; + period = NULL; + provider = NULL; + + // + ticket = 0; + + // + volumeMultiplier = 0; + + // + sl = 0; + tp = 0; + + // + force = false; + + // + ZeroMemory(this); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsValid(time) && + IsValid(symbol) && + IsValid(period) && + IsValid(action) && + IsValid(provider) + // + ; + + if (!result) + { + return result; + } + + // + // Validate Model Based On Specified Guard Actions ... + + // + return result; + } +}; + +// +// Extensions ... + +// +bool IsValid(ENUM_X_GUARD_ACTIONS item) +{ + // + bool result = false; + + // + result = item != X_GUARD_ACTION_NONE; + + // + return result; +} + +/** + * Add Guard to Collection ... + * + * @param guard: XGuard instance ... + * @param guards: XGuard instance Collection ... + * + * @return ( int ) + */ +int AddGuard( + XGuard &guard, + XGuard &guards[] // +) +{ + // + int result = 0; + + // + if (!guard.IsValid()) + { + return result; + } + + // + AddRef( + guard, + guards // + ); + + // + result = ArraySize(guards); + + // + return result; +} + +// +// Implementation ... +class XCGuard : public XCBase +{ + // + // public ... + public: + // + // Props ... + double minVolumeFactorForHedge; // Minimum Volume Factor for Hedge Profit Calculation ... + double minProfitPerVolumeFactorForHedge; // Minimum Required Profit per Volume Factor for Hedg ... + + // + // Constructor(s) ... + XCGuard( + XCAlert *_alert, + XCTrade *_trader // + ) + { + // + alert = _alert; + trader = _trader; + + // + minVolumeFactorForHedge = 0.01; + minProfitPerVolumeFactorForHedge = 0.5; + } + + // + // Deconstructor(s) ... + ~XCGuard() + { + // + ZeroMemory(alert); + ZeroMemory(trader); + } + + // + // Tools ... + void DoGuards(XGuard &guards[]) + { + // + bool has = HasChild(guards); + if (!has) + { + return; + } + + // + XGuard tmp[]; + Copy( + guards, + tmp // + ); + while (HasChild(tmp)) + { + // + XGuard iGuard = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + // Do Guard Action ... + DoGuard(iGuard); + } + + // + Clean(tmp); + } + + // + void DoGuard(XGuard &guard) + { + // + bool has = false; + + // + // Validate and Do Guard ... + has = guard.IsValid(); + if (!has) + { + return; + } + + // + // Switch Based on Guard Action ... + switch (guard.action) + { + // + // Close ... + case X_GUARD_ACTION_CLOSE: + DoClose(guard); + break; + + // + // Close All ... + case X_GUARD_ACTION_CLOSE_ALL: + DoCloseAll(guard); + break; + + // + // Close All Long Positions ... + case X_GUARD_ACTION_CLOSE_LONGS: + DoCloseLongs(guard); + break; + + // + // Close All Short Positions ... + case X_GUARD_ACTION_CLOSE_SHORTS: + DoCloseShorts(guard); + break; + + // + // Close In Losts ... + case X_GUARD_ACTION_CLOSE_IN_LOSTS: + DoCloseInLosts(guard); + break; + + // + // Close In Profits ... + case X_GUARD_ACTION_CLOSE_IN_PROFITS: + DoCloseInProfits(guard); + break; + + // + // Close In Lost Longs ... + case X_GUARD_ACTION_CLOSE_IN_LOST_LONGS: + DoCloseInLostLongs(guard); + break; + + // + // Close In Profit Longs ... + case X_GUARD_ACTION_CLOSE_IN_PROFIT_LONGS: + DoCloseInProfitLongs(guard); + break; + + // + // Close In Lost Shorts ... + case X_GUARD_ACTION_CLOSE_IN_LOST_SHORTS: + DoCloseInLostShorts(guard); + break; + + // + // Close In Profit Shorts ... + case X_GUARD_ACTION_CLOSE_IN_PROFITS_SHORT: + DoCloseInProfitShorts(guard); + break; + + // + // Partial Close ... + case X_GUARD_ACTION_PARTIAL_CLOSE: + DoPartialClose(guard); + break; + + // + // Trail Stop ... + case X_GUARD_ACTION_TRAIL_STOP: + DoTrailStop(guard); + break; + + // + // Trail Target ... + case X_GUARD_ACTION_TRAIL_TARGET: + DoTrailTarget(guard); + break; + + // + // Hedge Positions ... + case X_GUARD_ACTION_HEDGE: + DoHedge(guard); + break; + + // + } + } + + // + // protected ... + protected: + // + + // + bool GetPosition( + XPosition &position, + XGuard &guard // + ) + { + // + bool result = false; + + // + position.Clean(); + + // + result = + guard.IsValid() && + guard.ticket > 0; + if (!result) + { + return result; + } + + // + // Get Position ... + result = trader.GetPosition( + guard.ticket, + position // + ); + if (!result) + { + // + position.Clean(); + + // + return result; + } + + // + // Validate Position ... + result = + position.IsValid() && + position.symbol == guard.symbol && + position.provider == guard.provider && + position.period == guard.period; + if (!result) + { + // + position.Clean(); + + // + return result; + } + + // + return result; + } + + // + int GetPositions( + XPosition &positions[], + XGuard &guard // + ) + { + // + int result = 0; + + // + Clean(positions); + + // + bool has = guard.IsValid(); + if (!has) + { + return result; + } + + // + result = trader.GetPositions( + positions, + guard.symbol, + guard.provider, + guard.period, + NULL, // All Types ... + true, // Filter By Magc ... + true // Force Clean ... + ); + + // + result = ArraySize(positions); + + // + return result; + } + + // + int GetLongPositions( + XPosition &positions[], + XGuard &guard // + ) + { + // + int result = 0; + + // + Clean(positions); + + // + bool has = guard.IsValid(); + if (!has) + { + return result; + } + + // + result = trader.GetPositions( + positions, + guard.symbol, + guard.provider, + guard.period, + X_POSITION_TYPE_LONG, // Specified Types ... + true, // Filter By Magc ... + true // Force Clean ... + ); + + // + result = ArraySize(positions); + + // + return result; + } + + // + int GetShortPositions( + XPosition &positions[], + XGuard &guard // + ) + { + // + int result = 0; + + // + Clean(positions); + + // + bool has = guard.IsValid(); + if (!has) + { + return result; + } + + // + result = trader.GetPositions( + positions, + guard.symbol, + guard.provider, + guard.period, + X_POSITION_TYPE_SHORT, // Specified Types ... + true, // Filter By Magc ... + true // Force Clean ... + ); + + // + result = ArraySize(positions); + + // + return result; + } + + // + int GetInProfitPositions( + XPosition &positions[], + XGuard &guard // + ) + { + // + int result = 0; + + // + Clean(positions); + + // + bool has = guard.IsValid(); + if (!has) + { + return result; + } + + // + XPosition allPositions[]; + int allPositionsCount = GetPositions( + allPositions, + guard // + ); + has = IsValidSize(allPositionsCount); + if (!has) + { + return result; + } + + // + while (HasChild(allPositions)) + { + // + XPosition iPosition = allPositions[0]; + ArrayRemove( + allPositions, + 0, + 1 // + ); + + // + if (iPosition.profit > 0) + { + // + AddRef( + iPosition, + positions // + ); + } + + // + iPosition.Clean(); + } + Clean(allPositions); + + // + result = ArraySize(positions); + + // + return result; + } + + // + int GetInLostPositions( + XPosition &positions[], + XGuard &guard // + ) + { + // + int result = 0; + + // + Clean(positions); + + // + bool has = guard.IsValid(); + if (!has) + { + return result; + } + + // + XPosition allPositions[]; + int allPositionsCount = GetPositions( + allPositions, + guard // + ); + has = IsValidSize(allPositionsCount); + if (!has) + { + return result; + } + + // + while (HasChild(allPositions)) + { + // + XPosition iPosition = allPositions[0]; + ArrayRemove( + allPositions, + 0, + 1 // + ); + + // + if (iPosition.profit < 0) + { + // + AddRef( + iPosition, + positions // + ); + } + + // + iPosition.Clean(); + } + Clean(allPositions); + + // + result = ArraySize(positions); + + // + return result; + } + + // + int GetInProfitLongPositions( + XPosition &positions[], + XGuard &guard // + ) + { + // + int result = 0; + + // + Clean(positions); + + // + bool has = guard.IsValid(); + if (!has) + { + return result; + } + + // + XPosition allPositions[]; + int allPositionsCount = GetLongPositions( + allPositions, + guard // + ); + has = IsValidSize(allPositionsCount); + if (!has) + { + return result; + } + + // + while (HasChild(allPositions)) + { + // + XPosition iPosition = allPositions[0]; + ArrayRemove( + allPositions, + 0, + 1 // + ); + + // + if (iPosition.profit > 0) + { + // + AddRef( + iPosition, + positions // + ); + } + + // + iPosition.Clean(); + } + Clean(allPositions); + + // + result = ArraySize(positions); + + // + return result; + } + + // + int GetInLostLongPositions( + XPosition &positions[], + XGuard &guard // + ) + { + // + int result = 0; + + // + Clean(positions); + + // + bool has = guard.IsValid(); + if (!has) + { + return result; + } + + // + XPosition allPositions[]; + int allPositionsCount = GetLongPositions( + allPositions, + guard // + ); + has = IsValidSize(allPositionsCount); + if (!has) + { + return result; + } + + // + while (HasChild(allPositions)) + { + // + XPosition iPosition = allPositions[0]; + ArrayRemove( + allPositions, + 0, + 1 // + ); + + // + if (iPosition.profit < 0) + { + // + AddRef( + iPosition, + positions // + ); + } + + // + iPosition.Clean(); + } + Clean(allPositions); + + // + result = ArraySize(positions); + + // + return result; + } + + // + int GetInProfitShortPositions( + XPosition &positions[], + XGuard &guard // + ) + { + // + int result = 0; + + // + Clean(positions); + + // + bool has = guard.IsValid(); + if (!has) + { + return result; + } + + // + XPosition allPositions[]; + int allPositionsCount = GetShortPositions( + allPositions, + guard // + ); + has = IsValidSize(allPositionsCount); + if (!has) + { + return result; + } + + // + while (HasChild(allPositions)) + { + // + XPosition iPosition = allPositions[0]; + ArrayRemove( + allPositions, + 0, + 1 // + ); + + // + if (iPosition.profit > 0) + { + // + AddRef( + iPosition, + positions // + ); + } + + // + iPosition.Clean(); + } + Clean(allPositions); + + // + result = ArraySize(positions); + + // + return result; + } + + // + int GetInLostShortPositions( + XPosition &positions[], + XGuard &guard // + ) + { + // + int result = 0; + + // + Clean(positions); + + // + bool has = guard.IsValid(); + if (!has) + { + return result; + } + + // + XPosition allPositions[]; + int allPositionsCount = GetShortPositions( + allPositions, + guard // + ); + has = IsValidSize(allPositionsCount); + if (!has) + { + return result; + } + + // + while (HasChild(allPositions)) + { + // + XPosition iPosition = allPositions[0]; + ArrayRemove( + allPositions, + 0, + 1 // + ); + + // + if (iPosition.profit < 0) + { + // + AddRef( + iPosition, + positions // + ); + } + + // + iPosition.Clean(); + } + Clean(allPositions); + + // + result = ArraySize(positions); + + // + return result; + } + + // + // Guard Handlers ... + + // + void DoClose(XGuard &guard) + { + // + bool has = false; + + // + has = guard.IsValid(); + if (!has) + { + return; + } + + // + // Do What we want ... + + // + // Validate Action and Requirements ... + has = + NotEmpty(guard.ticket) && + guard.action == X_GUARD_ACTION_CLOSE; + if (!has) + { + return; + } + + // + // Retrieve Position ... + XPosition position; + has = GetPosition( + position, + guard // + ); + if (!has) + { + // + position.Clean(); + + // + return; + } + + // + string comment = "Guard Close ..."; + + // + has = trader.Close( + position.ticket, + comment // + ); + if (has) + { + // + string message = + "Guard Closed " + + ToString(position.type) + + " Position (" + ToString(position.ticket) + ") Successfully ..."; + + // + alert.SendAlert(message); + } + + // + // Cleanup Resources ... + + // + position.Clean(); + } + + // + void DoCloseAll(XGuard &guard) + { + // + bool has = false; + + // + has = guard.IsValid(); + if (!has) + { + return; + } + + // + // Do What we want ... + has = guard.action == X_GUARD_ACTION_CLOSE_ALL; + if (!has) + { + return; + } + + // + // Retrieve Positions ... + XPosition positions[]; + int count = GetPositions( + positions, + guard // + ); + has = IsValidSize(count); + if (!has) + { + // + Clean(positions); + + // + return; + } + + // + string comment = "Guard Close All ..."; + + // + has = trader.Close( + positions, + comment // + ); + if (has) + { + // + string message = + "Guard Closed " + + ToString(count) + + " Positions Successfully ..."; + + // + alert.SendAlert(message); + } + + // + // Cleanup Resources ... + + // + Clean(positions); + } + + // + void DoCloseInLosts(XGuard &guard) + { + // + bool has = false; + + // + has = guard.IsValid(); + if (!has) + { + return; + } + + // + // Do What we want ... + has = guard.action == X_GUARD_ACTION_CLOSE_IN_LOSTS; + if (!has) + { + return; + } + + // + // Retrieve Positions ... + XPosition positions[]; + int count = GetInLostPositions( + positions, + guard // + ); + has = IsValidSize(count); + if (!has) + { + // + Clean(positions); + + // + return; + } + + // + string comment = "Guard Close All In Losts ..."; + + // + has = trader.Close( + positions, + comment // + ); + if (has) + { + // + string message = + "Guard Closed " + + ToString(count) + + " In Lost Positions Successfully ..."; + + // + alert.SendAlert(message); + } + + // + // Cleanup Resources ... + + // + Clean(positions); + } + + // + void DoCloseInProfits(XGuard &guard) + { + // + bool has = false; + + // + has = guard.IsValid(); + if (!has) + { + return; + } + + // + // Do What we want ... + has = guard.action == X_GUARD_ACTION_CLOSE_IN_PROFITS; + if (!has) + { + return; + } + + // + // Retrieve Positions ... + XPosition positions[]; + int count = GetInProfitPositions( + positions, + guard // + ); + has = IsValidSize(count); + if (!has) + { + // + Clean(positions); + + // + return; + } + + // + string comment = "Guard Close All In Profits ..."; + + // + has = trader.Close( + positions, + comment // + ); + if (has) + { + // + string message = + "Guard Closed " + + ToString(count) + + " In Profit Positions Successfully ..."; + + // + alert.SendAlert(message); + } + + // + // Cleanup Resources ... + + // + Clean(positions); + } + + // + void DoCloseLongs(XGuard &guard) + { + // + bool has = false; + + // + has = guard.IsValid(); + if (!has) + { + return; + } + + // + // Do What we want ... + has = guard.action == X_GUARD_ACTION_CLOSE_LONGS; + if (!has) + { + return; + } + + // + // Retrieve Positions ... + XPosition positions[]; + int count = GetLongPositions( + positions, + guard // + ); + has = IsValidSize(count); + if (!has) + { + // + Clean(positions); + + // + return; + } + + // + string comment = "Guard Close Longs ..."; + + // + has = trader.Close( + positions, + comment // + ); + if (has) + { + // + string message = + "Guard Closed " + + ToString(count) + + " Long Positions Successfully ..."; + + // + alert.SendAlert(message); + } + + // + // Cleanup Resources ... + + // + Clean(positions); + } + + // + void DoCloseInLostLongs(XGuard &guard) + { + // + bool has = false; + + // + has = guard.IsValid(); + if (!has) + { + return; + } + + // + // Do What we want ... + has = guard.action == X_GUARD_ACTION_CLOSE_IN_LOST_LONGS; + if (!has) + { + return; + } + + // + // Retrieve Positions ... + XPosition positions[]; + int count = GetInLostLongPositions( + positions, + guard // + ); + has = IsValidSize(count); + if (!has) + { + // + Clean(positions); + + // + return; + } + + // + string comment = "Guard Close All In Lost Longs ..."; + + // + has = trader.Close( + positions, + comment // + ); + if (has) + { + // + string message = + "Guard Closed " + + ToString(count) + + " In Lost Longs Positions Successfully ..."; + + // + alert.SendAlert(message); + } + + // + // Cleanup Resources ... + + // + Clean(positions); + } + + // + void DoCloseInProfitLongs(XGuard &guard) + { + // + bool has = false; + + // + has = guard.IsValid(); + if (!has) + { + return; + } + + // + // Do What we want ... + has = guard.action == X_GUARD_ACTION_CLOSE_IN_PROFIT_LONGS; + if (!has) + { + return; + } + + // + // Retrieve Positions ... + XPosition positions[]; + int count = GetInProfitLongPositions( + positions, + guard // + ); + has = IsValidSize(count); + if (!has) + { + // + Clean(positions); + + // + return; + } + + // + string comment = "Guard Close All In Profit Longs ..."; + + // + has = trader.Close( + positions, + comment // + ); + if (has) + { + // + string message = + "Guard Closed " + + ToString(count) + + " In Profit Longs Positions Successfully ..."; + + // + alert.SendAlert(message); + } + + // + // Cleanup Resources ... + + // + Clean(positions); + } + + // + void DoCloseShorts(XGuard &guard) + { + // + bool has = false; + + // + has = guard.IsValid(); + if (!has) + { + return; + } + + // + // Do What we want ... + } + + // + void DoCloseInLostShorts(XGuard &guard) + { + // + bool has = false; + + // + has = guard.IsValid(); + if (!has) + { + return; + } + + // + // Do What we want ... + has = guard.action == X_GUARD_ACTION_CLOSE_IN_LOST_SHORTS; + if (!has) + { + return; + } + + // + // Retrieve Positions ... + XPosition positions[]; + int count = GetInLostShortPositions( + positions, + guard // + ); + has = IsValidSize(count); + if (!has) + { + // + Clean(positions); + + // + return; + } + + // + string comment = "Guard Close All In Lost Shorts ..."; + + // + has = trader.Close( + positions, + comment // + ); + if (has) + { + // + string message = + "Guard Closed " + + ToString(count) + + " In Lost Shorts Positions Successfully ..."; + + // + alert.SendAlert(message); + } + + // + // Cleanup Resources ... + + // + Clean(positions); + } + + // + void DoCloseInProfitShorts(XGuard &guard) + { + // + bool has = false; + + // + has = guard.IsValid(); + if (!has) + { + return; + } + + // + // Do What we want ... + has = guard.action == X_GUARD_ACTION_CLOSE_IN_PROFITS_SHORT; + if (!has) + { + return; + } + + // + // Retrieve Positions ... + XPosition positions[]; + int count = GetInProfitShortPositions( + positions, + guard // + ); + has = IsValidSize(count); + if (!has) + { + // + Clean(positions); + + // + return; + } + + // + string comment = "Guard Close All In Profit Shorts ..."; + + // + has = trader.Close( + positions, + comment // + ); + if (has) + { + // + string message = + "Guard Closed " + + ToString(count) + + " In Profit Shorts Positions Successfully ..."; + + // + alert.SendAlert(message); + } + + // + // Cleanup Resources ... + + // + Clean(positions); + } + + // + void DoPartialClose(XGuard &guard) + { + // + bool has = false; + + // + has = guard.IsValid(); + if (!has) + { + return; + } + + // + // Do What we want ... + + // + // Validate Action and Requirements ... + has = + NotEmpty(guard.ticket) && + guard.volumeMultiplier > 0 && + guard.action == X_GUARD_ACTION_PARTIAL_CLOSE; + if (!has) + { + return; + } + + // + // Retrieve Position ... + XPosition position; + has = GetPosition( + position, + guard // + ); + if (!has) + { + // + position.Clean(); + + // + return; + } + + // + // Normalize Volume Multiplier ... + double vMult = guard.volumeMultiplier; + if (vMult > 0.5) + { + vMult = 0.5; + } + if (vMult < 0) + { + vMult = 0.5; + } + + // + // Calculate and Normalize Volume ... + double volume = position.volume * vMult; + volume = NormalizeVolume( + volume, + position.symbol // + ); + + // + string comment = "Guard Partially Closed: " + ToString(volume) + " ..."; + + // + has = trader.ClosePartial( + position.ticket, + volume, + comment // + ); + if (has) + { + // + string message = + "Guard Closed Partially " + + ToString(volume) + " of " + + ToString(position.type) + + " Position (" + ToString(position.ticket) + ") Successfully ..."; + + // + alert.SendAlert(message); + } + + // + // Cleanup Resources ... + + // + position.Clean(); + } + + // + void DoTrailStop(XGuard &guard) + { + // + bool has = false; + + // + has = guard.IsValid(); + if (!has) + { + return; + } + + // + // Do What we want ... + + // + // Validate Action and Requirements ... + has = + guard.sl > 0 && + NotEmpty(guard.ticket) && + guard.action == X_GUARD_ACTION_TRAIL_STOP; + if (!has) + { + return; + } + + // + // Retrieve Position ... + XPosition position; + has = GetPosition( + position, + guard // + ); + if (!has) + { + // + position.Clean(); + + // + return; + } + + // + bool isLong = IsLong(position.type); + + // + // Check Can Trail Stop or not ... + has = + // + // Position Exists ... + has && + // + // Positions in Profit for Trailling Stop ... + position.profit > 0 && + // + // Validate SL based on Position Type ... + (isLong + ? position.price > guard.sl && + (position.sl == 0 || + position.sl < guard.sl) + : position.price < guard.sl && + (position.sl == 0 || + position.sl > guard.sl)); + if (!has) + { + // + position.Clean(); + + // + return; + } + + // + string comment = "Guard Trail Stop ..."; + + // + has = trader.Modify( + position.ticket, + guard.sl, + position.tp, + comment // + ); + if (has) + { + // + double before = NormalizePrice(position.sl, position.symbol); + double after = NormalizePrice(guard.sl, position.symbol); + + // + string message = + "Guard Trail Stop " + + ToString(position.type) + + " Position (" + ToString(position.ticket) + ")" + + " From: " + ToString(before) + + "To: " + ToString(after) + + " Successfully ..."; + + // + alert.SendAlert(message); + } + + // + // Cleanup Resources ... + + // + position.Clean(); + } + + // + void DoTrailTarget(XGuard &guard) + { + // + bool has = false; + + // + has = guard.IsValid(); + if (!has) + { + return; + } + + // + // Do What we want ... + + // + // Validate Action and Requirements ... + has = + guard.tp > 0 && + NotEmpty(guard.ticket) && + guard.action == X_GUARD_ACTION_TRAIL_TARGET; + if (!has) + { + return; + } + + // + // Retrieve Position ... + XPosition position; + has = GetPosition( + position, + guard // + ); + if (!has) + { + // + position.Clean(); + + // + return; + } + + // + bool isLong = IsLong(position.type); + + // + // Check Can Trail Stop or not ... + has = + // + // Position Exists ... + has && + // + // Check TP is not Same ... + guard.tp != position.tp && + // + // Validate TP based on Current Price ... + (isLong + ? guard.tp > position.price + : guard.tp < position.price); + if (!has) + { + // + position.Clean(); + + // + return; + } + + // + string comment = "Guard Trail Target ..."; + + // + has = trader.Modify( + position.ticket, + position.sl, + guard.tp, + comment // + ); + if (has) + { + // + double before = NormalizePrice(position.tp, position.symbol); + double after = NormalizePrice(guard.tp, position.symbol); + + // + string message = + "Guard Trail Target " + + ToString(position.type) + + " Position (" + ToString(position.ticket) + ")" + + " From: " + ToString(before) + + "To: " + ToString(after) + + " Successfully ..."; + + // + alert.SendAlert(message); + } + + // + // Cleanup Resources ... + + // + position.Clean(); + } + + // + void DoHedge(XGuard &guard) + { + // + bool has = false; + + // + has = guard.IsValid(); + if (!has) + { + return; + } + + // + // Do What we want ... + + // + // Validate Action and Requirements ... + has = + (guard.force + ? true + : (minVolumeFactorForHedge > 0 && + minProfitPerVolumeFactorForHedge > 0)) && + guard.action == X_GUARD_ACTION_HEDGE; + if (!has) + { + return; + } + + // + // Retrieve Positions ... + XPosition positions[]; + int count = GetPositions( + positions, + guard // + ); + has = HasChild(positions); + if (!has) + { + // + Clean(positions); + + // + return; + } + + // + // Calculate Positions Profits and Volumes ... + double swaps = 0; + double profits = 0; + double volumes = 0; + double commissions = 0; + for (int i = 0; i < count; i++) + { + // + swaps += positions[i].swap; + profits += positions[i].profit; + volumes += positions[i].volume; + commissions += positions[i].commission; + } + + // + // Check Profits and Volumes for Hedging ... + double hedgeValue = profits + (-1 * swaps) + commissions; + + // + // Check Force Hedging ... + if (!guard.force) + { + // + // Calculate Minimum Required Profit for Hedging ... + double minRequiredProfit = + (volumes / minVolumeFactorForHedge) * minProfitPerVolumeFactorForHedge; + + // + has = hedgeValue >= minRequiredProfit; + } + else + { + has = hedgeValue > 0; + } + + // + if (!has) + { + // + Clean(positions); + + // + return; + } + + // + string comment = "Guard Hedge ..."; + + // + // Loop through Positions and Close them One by One ... + // this is because of Trade Manager to Handle Close Trades ... + int closedCount = 0; + for (int i = 0; i < count; i++) + { + // + has = trader.Close( + positions[i].ticket, + comment // + ); + if (has) + { + closedCount++; + } + } + + // + has = IsValidSize(closedCount); + if (has) + { + // + string message = + "Guard Hedge " + + ToString(closedCount) + + " Positions by: " + + ToString(hedgeValue) + + " Successfully ..."; + + // + alert.SendAlert(message); + } + + // + // Cleanup Resources ... + + // + Clean(positions); + } + + // + // private ... + private: + // + XCTrade *trader; + XCAlert *alert; + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14040316/Classes/x-saherelm.x-helper.class.mq5 b/BKPS/14040316/Classes/x-saherelm.x-helper.class.mq5 new file mode 100644 index 0000000..945ba69 --- /dev/null +++ b/BKPS/14040316/Classes/x-saherelm.x-helper.class.mq5 @@ -0,0 +1,151 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCBaseHelper +// Description: provides all Base 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 + +// +// Includes ... +#include "../Classes/x-saherelm.base.class.mq5" + +// +// Definitions ... + +// +// a Class for Handle base requirements ... +// for indicators ... +class XCBaseHelper : public XCBase +{ + // + // Public ... + public: + // + // Constructor ... + void XCBaseHelper( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period // Trading Time Frame + ) + { + // + mSymbol = symbol; + mPeriod = period; + } + + // + // Deconstructor ... + void ~XCBaseHelper() + { + // + IndicatorRelease(mHandler); + } + + // + // Setter(s) / Getter(s) ... + + // + // Symbol ... + string GetSymbol() + { + return mSymbol; + } + + // + // Period ... + ENUM_TIMEFRAMES GetPeriod() + { + return mPeriod; + } + + // + // Retrieve Bars ... + int CountBars() + { + // + int result = + Bars( + mSymbol, + mPeriod + // + ); + + // + return result; + } + + // + // Retrieve Indicator Calculated Bars ... + int CountCalculatedBars() + { + return BarsCalculated(mHandler); + } + + // + virtual void Free() {} + + // + // Generate Tag ... + virtual string GetTag() + { + // + string result = NULL; + + // + result = + // + GetToken() + + "[" + + GetSymbol() + "|" + + ToString(GetPeriod()) + + "]" + // + ; + + // + return result; + } + + // + // Functions ... + + // + // Protected ... + protected: + // + // Props ... + + // + // Symbol ... + string mSymbol; + + // + // Period ... + ENUM_TIMEFRAMES mPeriod; + + // + // Indicator Handler ... + int mHandler; + + // + // Private ... + private: + // +}; + +// +// Tools .... \ No newline at end of file diff --git a/BKPS/14040316/Classes/x-saherelm.x-http.class.mq5 b/BKPS/14040316/Classes/x-saherelm.x-http.class.mq5 new file mode 100644 index 0000000..631532f --- /dev/null +++ b/BKPS/14040316/Classes/x-saherelm.x-http.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 XCHttp : public XCBase +{ + // + // Public ... + public: + // + // Constructor ... + void XCHttp() + { + XCHttp("", 10000); + } + void XCHttp( + string path, // Base Folder to Store Data + int timeout // base timeout for Requests + ) + { + // + Path(path); + Timeout(timeout); + } + + // + // Deconstructor ... + void ~XCHttp() + { + } + + // + // 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/BKPS/14040316/Classes/x-saherelm.x-md5.class.mq5 b/BKPS/14040316/Classes/x-saherelm.x-md5.class.mq5 new file mode 100644 index 0000000..e5cc201 --- /dev/null +++ b/BKPS/14040316/Classes/x-saherelm.x-md5.class.mq5 @@ -0,0 +1,445 @@ +/////////////////////////////////////////////////////// +// +// 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 XCMD5 +{ + // + // Public Provides ... + public: + // + // Protected Provides ... + + // + // Constructor ... + XCMD5(void) + { + } + + // + // Deconstructor ... + ~XCMD5(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/BKPS/14040316/Classes/x-saherelm.x-poi.drawer.class.mq5 b/BKPS/14040316/Classes/x-saherelm.x-poi.drawer.class.mq5 new file mode 100644 index 0000000..2fe2d02 --- /dev/null +++ b/BKPS/14040316/Classes/x-saherelm.x-poi.drawer.class.mq5 @@ -0,0 +1,4385 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XPOIDrawer +// Description: Provides Point of Interests +// Drawing Tools ... +// +// 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 "../Classes/x-saherelm.x-cobject.class.mq5" +#include "../Libraries/x-saherelm.x-poi.extensions.lib.mq5" +#include "../Libraries/x-saherelm.x-poi.state.lib.mq5" + +// +// Definitions ... + +// +// Extensions ... + +void AddObjects( + CArrayObj *&source, + CArrayObj &dest // +) +{ + // + bool has = source != NULL && + source.Total() > 0; + if (!has) + { + return; + } + + // + for (int i = 0; i < source.Total(); i++) + { + dest.Add(source.At(i)); + } +} + +// +// Implementations ... +class XCPOIDrawer : public XCBase +{ + // + public: + // + + // + // Constructor ... + void XCPOIDrawer() + { + // + Default(); + } + + // + // Deconstructor ... + void ~XCPOIDrawer() + { + // + Clean(mTicksZoneSpecs); + } + + // + // Setter Getter (s) ... + + /** + * Get Prefix ... + * + * @return ( string ) + */ + string Prefix() + { + return mPrefix; + } + + /** + * Set Prifx ... + * + * @param value: String ... + */ + void Prefix(string value) + { + mPrefix = value; + } + + /** + * Get Chart ID ... + * + * @return ( long ) + */ + long ChartIdentification() + { + return mChartIdentification; + } + + /** + * Set Chart ID ... + * + * @param value: Long ... + */ + void ChartIdentification(long value) + { + // + if (value < 0) + { + value = 0; + } + + // + mChartIdentification = value; + } + + /** + * Get SubWindow Id ... + * + * @return ( int ) + */ + int SubWindowIdentification() + { + return mSubWindowIdentification; + } + + /** + * Set SubWindow Id ... + * + * @param value: Integer ... + */ + void SubWindowIdentification(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mSubWindowIdentification = value; + } + + // + // XOHCL ... + + /** + * Get Bar Width ... + * + * @return ( int ) + */ + int BarWidth() + { + return mBarWidth; + } + + /** + * Set Bar Width ... + * + * @param value: Integer ... + */ + void BarWidth(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mBarWidth = value; + } + + /** + * Get Bar Bullish Color ... + * + * @return ( color ) + */ + color BarBullishColor() + { + return mBarBullishColor; + } + + /** + * Set Bar Bullish Color ... + * + * @param value: Color ... + */ + void BarBullishColor(color value) + { + mBarBullishColor = value; + } + + /** + * Get Bar Bearish Color ... + * + * @return ( color ) + */ + color BarBearishColor() + { + return mBarBearishColor; + } + + /** + * Set Bar Bearish Color ... + * + * @param value: Color ... + */ + void BarBearishColor(color value) + { + mBarBearishColor = value; + } + + /** + * Get Fill Bar High Shadow State ... + * + * @return ( bool ) + */ + bool BarFillHighShadow() + { + return mBarFillHighShadow; + } + + /** + * Set Fill Bar High Shadow State ... + * + * @param value: Boolean ... + */ + void BarFillHighShadow(bool value) + { + mBarFillHighShadow = value; + } + + /** + * Get Bar High Shadow Style ... + * + * @return ( ENUM_LINE_STYLE ) + */ + ENUM_LINE_STYLE BarHighShadowStyle() + { + return mBarHighShadowStyle; + } + + /** + * Set Bar High Shadow Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void BarHighShadowStyle(ENUM_LINE_STYLE value) + { + mBarHighShadowStyle = value; + } + + /** + * Get Fill Bar Body State ... + * + * @return ( bool ) + */ + bool BarFillBody() + { + return mBarFillBody; + } + + /** + * Set Fill Bar Body State ... + * + * @param value: Boolean ... + */ + void BarFillBody(bool value) + { + mBarFillBody = value; + } + + /** + * Get Bar Body Style ... + * + * @return ( ENUM_LINE_STYLE ) + */ + ENUM_LINE_STYLE BarBodyStyle() + { + return mBarBodyStyle; + } + + /** + * Set Bar Body Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void BarBodyStyle(ENUM_LINE_STYLE value) + { + mBarBodyStyle = value; + } + + /** + * Get Fill Bar Low Show State ... + * + * @return ( bool ) + */ + bool BarFillLowShadow() + { + return mBarFillLowShadow; + } + + /** + * Set Fill Bar Low Show State ... + * + * @param value: Boolean ... + */ + void BarFillLowShadow(bool value) + { + mBarFillLowShadow = value; + } + + /** + * Get Bar Low Shadow Style ... + * + * @return ( ENUM_LINE_STYLE ) + */ + ENUM_LINE_STYLE BarLowShadowStyle() + { + return mBarLowShadowStyle; + } + + /** + * Set Bar Low Shadow Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void BarLowShadowStyle(ENUM_LINE_STYLE value) + { + mBarLowShadowStyle = value; + } + + // + // Swing Low ... + + /** + * Get Swing Low Width ... + * + * @return ( int ) + */ + int SwingLowWidth() + { + return mSwingLowWidth; + } + + /** + * Set Swing Low Width ... + * + * @param value: Integer ... + */ + void SwingLowWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mSwingLowWidth = value; + } + + /** + * Get Swing Low Arrow Code ... + * + * @return ( int ) + */ + int SwingLowArrow() + { + return mSwingLowArrow; + } + + /** + * Set Swing Low Arrow Code ... + * + * @param value: Integer ... + */ + void SwingLowArrow(int value) + { + // + mSwingLowArrow = value; + } + + /** + * Get Swing Low Color ... + * + * @return ( color ) + */ + color SwingLowColor() + { + return mSwingLowColor; + } + + /** + * Set Swing Low Color ... + * + * @param value: Color ... + */ + void SwingLowColor(color value) + { + mSwingLowColor = value; + } + + // + // Swing High ... + + /** + * Get Swing High Width ... + * + * @return ( int ) + */ + int SwingHighWidth() + { + return mSwingHighWidth; + } + + /** + * Set Swing High Width ... + * + * @param value: Integer ... + */ + void SwingHighWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mSwingHighWidth = value; + } + + /** + * Get Swing High Arrow Code ... + * + * @return ( int ) + */ + int SwingHighArrow() + { + return mSwingHighArrow; + } + + /** + * Set Swing High Arrow Code ... + * + * @param value: Integer ... + */ + void SwingHighArrow(int value) + { + // + mSwingHighArrow = value; + } + + /** + * Get Swing High Color ... + * + * @return ( color ) + */ + color SwingHighColor() + { + return mSwingHighColor; + } + + /** + * Set Swing High Color ... + * + * @param value: Color ... + */ + void SwingHighColor(color value) + { + mSwingHighColor = value; + } + + // + // Bullish Momentum Bar ... + + /** + * Get Bullish Momentum Bar Width ... + * + * @return ( int ) + */ + int BullishMomentumBarWidth() + { + return mBullishMomentumBarWidth; + } + + /** + * Set Bullish Momentum Bar Width ... + * + * @param value: Integer ... + */ + void BullishMomentumBarWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mBullishMomentumBarWidth = value; + } + + /** + * Get Bullish Momentum Bar Arrow Code ... + * + * @return ( int ) + */ + int BullishMomentumBarArrow() + { + return mBullishMomentumBarArrow; + } + + /** + * Set Bullish Momentum Bar Arrow Code ... + * + * @param value: Integer ... + */ + void BullishMomentumBarArrow(int value) + { + // + mBullishMomentumBarArrow = value; + } + + /** + * Get Bullish Momentum Bar Color ... + * + * @return ( color ) + */ + color BullishMomentumBarColor() + { + return mBullishMomentumBarColor; + } + + /** + * Set Bullish Momentum Bar Color ... + * + * @param value: Color ... + */ + void BullishMomentumBarColor(color value) + { + mBullishMomentumBarColor = value; + } + + // + // Bearish Momentum Bar ... + + /** + * Get Bearish Momentum Bar Width ... + * + * @return ( int ) + */ + int BearishMomentumBarWidth() + { + return mBearishMomentumBarWidth; + } + + /** + * Set Bearish Momentum Bar Width ... + * + * @param value: Integer ... + */ + void BearishMomentumBarWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mBearishMomentumBarWidth = value; + } + + /** + * Get Bearish Momentum Bar Arrow Code ... + * + * @return ( int ) + */ + int BearishMomentumBarArrow() + { + return mBearishMomentumBarArrow; + } + + /** + * Set Bearish Momentum Bar Arrow Code ... + * + * @param value: Integer ... + */ + void BearishMomentumBarArrow(int value) + { + // + mBearishMomentumBarArrow = value; + } + + /** + * Get Bearish Momentum Bar Color ... + * + * @return ( color ) + */ + color BearishMomentumBarColor() + { + return mBearishMomentumBarColor; + } + + /** + * Set Bearish Momentum Bar Color ... + * + * @param value: Color ... + */ + void BearishMomentumBarColor(color value) + { + mBearishMomentumBarColor = value; + } + + // + // Bullish Rejection Bar ... + + /** + * Get Bullish Rejection Bar Width ... + * + * @return ( int ) + */ + int BullishRejectionBarWidth() + { + return mBullishRejectionBarWidth; + } + + /** + * Set Bullish Rejection Bar Width ... + * + * @param value: Integer ... + */ + void BullishRejectionBarWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mBullishRejectionBarWidth = value; + } + + /** + * Get Bullish Rejection Bar Arrow Code ... + * + * @return ( int ) + */ + int BullishRejectionBarArrow() + { + return mBullishRejectionBarArrow; + } + + /** + * Set Bullish Rejection Bar Arrow Code ... + * + * @param value: Integer ... + */ + void BullishRejectionBarArrow(int value) + { + // + mBullishRejectionBarArrow = value; + } + + /** + * Get Bullish Rejection Bar Color ... + * + * @return ( color ) + */ + color BullishRejectionBarColor() + { + return mBullishRejectionBarColor; + } + + /** + * Set Bullish Rejection Bar Color ... + * + * @param value: Color ... + */ + void BullishRejectionBarColor(color value) + { + mBullishRejectionBarColor = value; + } + + // + // Bearish Rejection Bar ... + + /** + * Get Bearish Rejection Bar Width ... + * + * @return ( int ) + */ + int BearishRejectionBarWidth() + { + return mBearishRejectionBarWidth; + } + + /** + * Set Bearish Rejection Bar Width ... + * + * @param value: Integer ... + */ + void BearishRejectionBarWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mBearishRejectionBarWidth = value; + } + + /** + * Get Bearish Rejection Bar Arrow Code ... + * + * @return ( int ) + */ + int BearishRejectionBarArrow() + { + return mBearishRejectionBarArrow; + } + + /** + * Set Bearish Rejection Bar Arrow Code ... + * + * @param value: Integer ... + */ + void BearishRejectionBarArrow(int value) + { + // + mBearishRejectionBarArrow = value; + } + + /** + * Get Bearish Rejection Bar Color ... + * + * @return ( color ) + */ + color BearishRejectionBarColor() + { + return mBearishRejectionBarColor; + } + + /** + * Set Bearish Rejection Bar Color ... + * + * @param value: Color ... + */ + void BearishRejectionBarColor(color value) + { + mBearishRejectionBarColor = value; + } + + // + // Supply Zone ... + + /** + * Get Fill Supply Zone ... + * + * @return ( bool ) + */ + bool SupplyZoneFill() + { + return mSupplyZoneFill; + } + + /** + * Set Fill Supply Zone ... + * + * @param value: Boolean ... + */ + void SupplyZoneFill(bool value) + { + mSupplyZoneFill = value; + } + + /** + * Get Supply Zone Width ... + * + * @return ( int ) + */ + int SupplyZoneWidth() + { + return mSupplyZoneWidth; + } + + /** + * Set Supply Zone Width ... + * + * @param value: Integer ... + */ + void SupplyZoneWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mSupplyZoneWidth = value; + } + + /** + * Get Supply Zone Color ... + * + * @return ( color ) + */ + color SupplyZoneColor() + { + return mSupplyZoneColor; + } + + /** + * Set Supply Zone Color ... + * + * @param value: Color ... + */ + void SupplyZoneColor(color value) + { + mSupplyZoneColor = value; + } + + /** + * Get Supply Zone Style ... + * + * @return ( ENUM_LINE_STYLE ) + */ + ENUM_LINE_STYLE SupplyZoneStyle() + { + return mSupplyZoneStyle; + } + + /** + * Set Supply Zone Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void SupplyZoneStyle(ENUM_LINE_STYLE value) + { + mSupplyZoneStyle = value; + } + + // + // Demand Zone ... + + /** + * Get Fill Demand Zone ... + * + * @return ( bool ) + */ + bool DemandZoneFill() + { + return mDemandZoneFill; + } + + /** + * Set Fill Demand Zone ... + * + * @param value: Boolean ... + */ + void DemandZoneFill(bool value) + { + mDemandZoneFill = value; + } + + /** + * Get Demand Zone Width ... + * + * @return ( int ) + */ + int DemandZoneWidth() + { + return mDemandZoneWidth; + } + + /** + * Set Demand Zone Width ... + * + * @param value: Integer ... + */ + void DemandZoneWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mDemandZoneWidth = value; + } + + /** + * Get Demand Zone Color ... + * + * @return ( color ) + */ + color DemandZoneColor() + { + return mDemandZoneColor; + } + + /** + * Set Demand Zone Color ... + * + * @param value: Color ... + */ + void DemandZoneColor(color value) + { + mDemandZoneColor = value; + } + + /** + * Get Demand Zone Style ... + * + * @return ( ENUM_LINE_STYLE ) + */ + ENUM_LINE_STYLE DemandZoneStyle() + { + return mDemandZoneStyle; + } + + /** + * Set Demand Zone Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void DemandZoneStyle(ENUM_LINE_STYLE value) + { + mDemandZoneStyle = value; + } + + // + // Resistance Zone ... + + /** + * Get Fill Resistance Zone ... + * + * @return ( bool ) + */ + bool ResistanceZoneFill() + { + return mResistanceZoneFill; + } + + /** + * Set Fill Resistance Zone ... + * + * @param value: Boolean ... + */ + void ResistanceZoneFill(bool value) + { + mResistanceZoneFill = value; + } + + /** + * Get Resistance Zone Width ... + * + * @return ( int ) + */ + int ResistanceZoneWidth() + { + return mResistanceZoneWidth; + } + + /** + * Set Resistance Zone Width ... + * + * @param value: Integer ... + */ + void ResistanceZoneWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mResistanceZoneWidth = value; + } + + /** + * Get Resistance Zone Color ... + * + * @return ( color ) + */ + color ResistanceZoneColor() + { + return mResistanceZoneColor; + } + + /** + * Set Resistance Zone Color ... + * + * @param value: Color ... + */ + void ResistanceZoneColor(color value) + { + mResistanceZoneColor = value; + } + + /** + * Get Resistance Zone Style ... + * + * @return ( ENUM_LINE_STYLE ) + */ + ENUM_LINE_STYLE ResistanceZoneStyle() + { + return mResistanceZoneStyle; + } + + /** + * Set Resistance Zone Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void ResistanceZoneStyle(ENUM_LINE_STYLE value) + { + mResistanceZoneStyle = value; + } + + // + // Support Zone ... + + /** + * Get Fill Support Zone ... + * + * @return ( bool ) + */ + bool SupportZoneFill() + { + return mSupportZoneFill; + } + + /** + * Set Fill Support Zone ... + * + * @param value: Boolean ... + */ + void SupportZoneFill(bool value) + { + mSupportZoneFill = value; + } + + /** + * Get Support Zone Width ... + * + * @return ( int ) + */ + int SupportZoneWidth() + { + return mSupportZoneWidth; + } + + /** + * Set Support Zone Width ... + * + * @param value: Integer ... + */ + void SupportZoneWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mSupportZoneWidth = value; + } + + /** + * Get Support Zone Color ... + * + * @return ( color ) + */ + color SupportZoneColor() + { + return mSupportZoneColor; + } + + /** + * Set Support Zone Color ... + * + * @param value: Color ... + */ + void SupportZoneColor(color value) + { + mSupportZoneColor = value; + } + + /** + * Get Support Zone Style ... + * + * @return ( ENUM_LINE_STYLE ) + */ + ENUM_LINE_STYLE SupportZoneStyle() + { + return mSupportZoneStyle; + } + + /** + * Set Support Zone Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void SupportZoneStyle(ENUM_LINE_STYLE value) + { + mSupportZoneStyle = value; + } + + // + // Bullish Order Block ... + + /** + * Get Fill Bullish Order Block ... + * + * @return ( bool ) + */ + bool BullishOrderBlockFill() + { + return mBullishOrderBlockFill; + } + + /** + * Set Fill Bullish Order Block ... + * + * @param value: Boolean ... + */ + void BullishOrderBlockFill(bool value) + { + mBullishOrderBlockFill = value; + } + + /** + * Get Bullish Order Block Width ... + * + * @return ( int ) + */ + int BullishOrderBlockWidth() + { + return mBullishOrderBlockWidth; + } + + /** + * Set Bullish Order Block Width ... + * + * @param value: Integer ... + */ + void BullishOrderBlockWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mBullishOrderBlockWidth = value; + } + + /** + * Get Bullish Order Block Color ... + * + * @return ( color ) + */ + color BullishOrderBlockColor() + { + return mBullishOrderBlockColor; + } + + /** + * Set Bullish Order Block Color ... + * + * @param value: Color ... + */ + void BullishOrderBlockColor(color value) + { + mBullishOrderBlockColor = value; + } + + /** + * Get Bullish Order Block Style ... + * + * @return ( ENUM_LINE_STYLE ) + */ + ENUM_LINE_STYLE BullishOrderBlockStyle() + { + return mBullishOrderBlockStyle; + } + + /** + * Set Bullish Order Block Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void BullishOrderBlockStyle(ENUM_LINE_STYLE value) + { + mBullishOrderBlockStyle = value; + } + + // + // Bearish Order Block ... + + /** + * Get Fill Bearish Order Block ... + * + * @return ( bool ) + */ + bool BearishOrderBlockFill() + { + return mBearishOrderBlockFill; + } + + /** + * Set Fill Bearish Order Block ... + * + * @param value: Boolean ... + */ + void BearishOrderBlockFill(bool value) + { + mBearishOrderBlockFill = value; + } + + /** + * Get Bearish Order Block Width ... + * + * @return ( int ) + */ + int BearishOrderBlockWidth() + { + return mBearishOrderBlockWidth; + } + + /** + * Set Bearish Order Block Width ... + * + * @param value: Integer ... + */ + void BearishOrderBlockWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mBearishOrderBlockWidth = value; + } + + /** + * Get Bearish Order Block Color ... + * + * @return ( color ) + */ + color BearishOrderBlockColor() + { + return mBearishOrderBlockColor; + } + + /** + * Set Bearish Order Block Color ... + * + * @param value: Color ... + */ + void BearishOrderBlockColor(color value) + { + mBearishOrderBlockColor = value; + } + + /** + * Get Bearish Order Block Style ... + * + * @return ( ENUM_LINE_STYLE ) + */ + ENUM_LINE_STYLE BearishOrderBlockStyle() + { + return mBearishOrderBlockStyle; + } + + /** + * Set Bearish Order Block Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void BearishOrderBlockStyle(ENUM_LINE_STYLE value) + { + mBearishOrderBlockStyle = value; + } + + // + // Bullish FVG ... + + /** + * Get Fill Bullish FVG ... + * + * @return ( bool ) + */ + bool BullishFVGFill() + { + return mBullishFVGFill; + } + + /** + * Set Fill Bullish FVG ... + * + * @param value: Boolean ... + */ + void BullishFVGFill(bool value) + { + mBullishFVGFill = value; + } + + /** + * Get Bullish FVG Width ... + * + * @return ( int ) + */ + int BullishFVGWidth() + { + return mBullishFVGWidth; + } + + /** + * Set Bullish FVG Width ... + * + * @param value: Integer ... + */ + void BullishFVGWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mBullishFVGWidth = value; + } + + /** + * Get Bullish FVG Color ... + * + * @return ( color ) + */ + color BullishFVGColor() + { + return mBullishFVGColor; + } + + /** + * Set Bullish FVG Color ... + * + * @param value: Color ... + */ + void BullishFVGColor(color value) + { + mBullishFVGColor = value; + } + + /** + * Get Bullish FVG Style ... + * + * @return ( ENUM_LINE_STYLE ) + */ + ENUM_LINE_STYLE BullishFVGStyle() + { + return mBullishFVGStyle; + } + + /** + * Set Bullish FVG Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void BullishFVGStyle(ENUM_LINE_STYLE value) + { + mBullishFVGStyle = value; + } + + // + // Bearish FVG ... + + /** + * Get Fill Bearish FVG ... + * + * @return ( bool ) + */ + bool BearishFVGFill() + { + return mBearishFVGFill; + } + + /** + * Set Fill Bearish FVG ... + * + * @param value: Boolean ... + */ + void BearishFVGFill(bool value) + { + mBearishFVGFill = value; + } + + /** + * Get Bearish FVG Width ... + * + * @return ( int ) + */ + int BearishFVGWidth() + { + return mBearishFVGWidth; + } + + /** + * Set Bearish FVG Width ... + * + * @param value: Integer ... + */ + void BearishFVGWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mBearishFVGWidth = value; + } + + /** + * Get Bearish FVG Color ... + * + * @return ( color ) + */ + color BearishFVGColor() + { + return mBearishFVGColor; + } + + /** + * Set Bearish FVG Color ... + * + * @param value: Color ... + */ + void BearishFVGColor(color value) + { + mBearishFVGColor = value; + } + + /** + * Get Bearish FVG Style ... + * + * @return ( ENUM_LINE_STYLE ) + */ + ENUM_LINE_STYLE BearishFVGStyle() + { + return mBearishFVGStyle; + } + + /** + * Set Bearish FVG Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void BearishFVGStyle(ENUM_LINE_STYLE value) + { + mBearishFVGStyle = value; + } + + // + // Virtuals ... + + /** + * Apply Default Configurations ... + */ + virtual void Default() + { + // + // Apply Default Props ... + + // + Prefix(NULL); + ChartIdentification(0); + SubWindowIdentification(0); + + // + BarWidth(1); + BarBearishColor(clrRed); + BarBullishColor(clrLime); + BarFillBody(false); + BarFillHighShadow(false); + BarFillLowShadow(false); + BarBodyStyle(STYLE_DOT); + BarLowShadowStyle(STYLE_DOT); + BarHighShadowStyle(STYLE_DOT); + + // + int arrowWidth = 1; + + // + SwingLowArrow(108); + SwingLowColor(clrAqua); + SwingLowWidth(arrowWidth); + + // + SwingHighArrow(108); + SwingHighWidth(arrowWidth); + SwingHighColor(clrMagenta); + + // + arrowWidth++; + + // + BullishMomentumBarArrow(225); + BullishMomentumBarWidth(arrowWidth); + BullishMomentumBarColor(clrAqua); + + // + BearishMomentumBarArrow(226); + BearishMomentumBarWidth(arrowWidth); + BearishMomentumBarColor(clrMagenta); + + // + arrowWidth++; + + // + BullishRejectionBarArrow(217); + BullishRejectionBarWidth(arrowWidth); + BullishRejectionBarColor(clrAqua); + + // + BearishRejectionBarArrow(218); + BearishRejectionBarWidth(arrowWidth); + BearishRejectionBarColor(clrMagenta); + + // + SupportZoneFill(false); + SupportZoneWidth(1); + SupportZoneStyle(STYLE_DOT); + SupportZoneColor(clrLime); + + // + ResistanceZoneFill(false); + ResistanceZoneWidth(1); + ResistanceZoneStyle(STYLE_DOT); + ResistanceZoneColor(clrRed); + + // + SupplyZoneFill(false); + SupplyZoneWidth(1); + SupplyZoneStyle(STYLE_DOT); + SupplyZoneColor(clrRed); + + // + DemandZoneFill(false); + DemandZoneWidth(1); + DemandZoneStyle(STYLE_DOT); + DemandZoneColor(clrGreen); + + // + BullishOrderBlockFill(false); + BullishOrderBlockWidth(1); + BullishOrderBlockStyle(STYLE_DASHDOT); + BullishOrderBlockColor(clrLime); + + // + BearishOrderBlockFill(false); + BearishOrderBlockWidth(1); + BearishOrderBlockStyle(STYLE_DASHDOT); + BearishOrderBlockColor(clrRed); + + // + BullishFVGFill(false); + BullishFVGWidth(1); + BullishFVGStyle(STYLE_DOT); + BullishFVGColor(clrLime); + + // + BearishFVGFill(false); + BearishFVGWidth(1); + BearishFVGStyle(STYLE_DOT); + BearishFVGColor(clrRed); + + // + // Add Default TickZone Specs ... + bool isSpecsInited = false; + bool fillTickZone = false; + XTickZoneLevelSpecs specs10; + isSpecsInited = specs10.Init( + 10, + clrWhite, + clrWhite, + fillTickZone // + ); + if (isSpecsInited) + { + AddTickZoneLevelSpecs(specs10); + } + + // + XTickZoneLevelSpecs specs20; + isSpecsInited = specs20.Init( + 20, + clrOrange, + clrOrange, + fillTickZone // + ); + if (isSpecsInited) + { + AddTickZoneLevelSpecs(specs20); + } + + // + XTickZoneLevelSpecs specs30; + isSpecsInited = specs30.Init( + 30, + clrOrange, + clrOrange, + fillTickZone // + ); + if (isSpecsInited) + { + AddTickZoneLevelSpecs(specs30); + } + + // + XTickZoneLevelSpecs specs40; + isSpecsInited = specs40.Init( + 40, + clrOrange, + clrOrange, + fillTickZone // + ); + if (isSpecsInited) + { + AddTickZoneLevelSpecs(specs40); + } + + // + XTickZoneLevelSpecs specs50; + isSpecsInited = specs50.Init( + 50, + clrYellow, + clrYellow, + fillTickZone // + ); + if (isSpecsInited) + { + AddTickZoneLevelSpecs(specs50); + } + + // + XTickZoneLevelSpecs specs60; + isSpecsInited = specs60.Init( + 60, + clrYellow, + clrYellow, + fillTickZone // + ); + if (isSpecsInited) + { + AddTickZoneLevelSpecs(specs60); + } + + // + XTickZoneLevelSpecs specs70; + isSpecsInited = specs70.Init( + 70, + clrYellow, + clrYellow, + fillTickZone // + ); + if (isSpecsInited) + { + AddTickZoneLevelSpecs(specs70); + } + + // + XTickZoneLevelSpecs specs80; + isSpecsInited = specs80.Init( + 80, + clrRed, + clrRed, + fillTickZone // + ); + if (isSpecsInited) + { + AddTickZoneLevelSpecs(specs80); + } + + // + XTickZoneLevelSpecs specs90; + isSpecsInited = specs90.Init( + 90, + clrRed, + clrRed, + fillTickZone // + ); + if (isSpecsInited) + { + AddTickZoneLevelSpecs(specs90); + } + + // + XTickZoneLevelSpecs specs100; + isSpecsInited = specs100.Init( + 100, + clrRed, + clrRed, + fillTickZone // + ); + if (isSpecsInited) + { + AddTickZoneLevelSpecs(specs100); + } + + // + } + + // + // Object Creators ... + + // + // Swings ... + + /** + * Create Swing High Object ... + * + * @param swing: XCSwing instance ... + * @param object: XCSwingHighObject pointer ... + * + * @return ( bool ) + */ + bool CreateSwingHigh( + XCSwing &swing, + XCSwingHighObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + swing.IsValid() && + swing.IsSwingHigh(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + int arrow = SwingHighArrow(); + int width = SwingHighWidth(); + color crl = SwingHighColor(); + + // + object = new XCSwingHighObject(); + result = object.Create( + chartID, + window, + arrow, + swing, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ArrowColor(crl); + object.ArrowWidth(width); + object.ArrowAnchor(ANCHOR_BOTTOM); + + // + return result; + } + + /** + * Create Swing Low Object ... + * + * @param swing: XCSwing instance ... + * @param object: XCSwingLowObject pointer ... + * + * @return ( bool ) + */ + bool CreateSwingLow( + XCSwing &swing, + XCSwingLowObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + swing.IsValid() && + swing.IsSwingLow(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + int arrow = SwingLowArrow(); + int width = SwingLowWidth(); + color crl = SwingLowColor(); + + // + object = new XCSwingLowObject(); + result = object.Create( + chartID, + window, + arrow, + swing, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ArrowColor(crl); + object.ArrowWidth(width); + object.ArrowAnchor(ANCHOR_TOP); + + // + return result; + } + + // + // Momentum Bars ... + + /** + * Create Bullish Momentum Bar Object ... + * + * @param momentumBar: XCMomentumBar instance ... + * @param object: XCBullishMomentumObject pointer ... + * + * @return ( bool ) + */ + bool CreateBullishMomentumBar( + XCMomentumBar &momentumBar, + XCBullishMomentumBarObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + momentumBar.IsValid() && + momentumBar.IsBullish(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + int arrow = BullishMomentumBarArrow(); + int width = BullishMomentumBarWidth(); + color crl = BullishMomentumBarColor(); + + // + object = new XCBullishMomentumBarObject(); + result = object.Create( + chartID, + window, + arrow, + momentumBar, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ArrowColor(crl); + object.ArrowWidth(width); + object.ArrowAnchor(ANCHOR_TOP); + + // + return result; + } + + /** + * Create Bearish Momentum Bar Object ... + * + * @param momentumBar: XCMomentumBar instance ... + * @param object: XCBearishMomentumObject pointer ... + * + * @return ( bool ) + */ + bool CreateBearishMomentumBar( + XCMomentumBar &momentumBar, + XCBearishMomentumBarObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + momentumBar.IsValid() && + momentumBar.IsBearish(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + int arrow = BearishMomentumBarArrow(); + int width = BearishMomentumBarWidth(); + color crl = BearishMomentumBarColor(); + + // + object = new XCBearishMomentumBarObject(); + result = object.Create( + chartID, + window, + arrow, + momentumBar, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ArrowColor(crl); + object.ArrowWidth(width); + object.ArrowAnchor(ANCHOR_BOTTOM); + + // + return result; + } + + // + // Rejection Bars ... + + /** + * Create Bullish Rejection Bar Object ... + * + * @param momentumBar: XCRejectionBar instance ... + * @param object: XCBullishRejectionObject pointer ... + * + * @return ( bool ) + */ + bool CreateBullishRejectionBar( + XCRejectionBar &rejectionBar, + XCBullishRejectionBarObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + rejectionBar.IsValid() && + rejectionBar.IsBullish(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + int arrow = BullishRejectionBarArrow(); + int width = BullishRejectionBarWidth(); + color crl = BullishRejectionBarColor(); + + // + object = new XCBullishRejectionBarObject(); + result = object.Create( + chartID, + window, + arrow, + rejectionBar, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ArrowColor(crl); + object.ArrowWidth(width); + object.ArrowAnchor(ANCHOR_TOP); + + // + return result; + } + + /** + * Create Bearish Rejection Bar Object ... + * + * @param rejectionBar: XCRejectionBar instance ... + * @param object: XCBearishRejectionObject pointer ... + * + * @return ( bool ) + */ + bool CreateBearishRejectionBar( + XCRejectionBar &rejectionBar, + XCBearishRejectionBarObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + rejectionBar.IsValid() && + rejectionBar.IsBearish(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + int arrow = BearishRejectionBarArrow(); + int width = BearishRejectionBarWidth(); + color crl = BearishRejectionBarColor(); + + // + object = new XCBearishRejectionBarObject(); + result = object.Create( + chartID, + window, + arrow, + rejectionBar, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ArrowColor(crl); + object.ArrowWidth(width); + object.ArrowAnchor(ANCHOR_BOTTOM); + + // + return result; + } + + // + // Support and Resistance ... + + /** + * Create Support Object ... + * + * @param zone: XCSupportZone instance ... + * @param object: XCSupportZoneObject pointer ... + * + * @return ( bool ) + */ + bool CreateSupportZone( + XCSupportZone &zone, + XCSupportZoneObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + zone.IsValid(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + bool fill = SupportZoneFill(); + int width = SupportZoneWidth(); + color crl = SupportZoneColor(); + ENUM_LINE_STYLE style = SupportZoneStyle(); + + // + object = new XCSupportZoneObject(); + result = object.Create( + chartID, + window, + zone, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ZoneFill(fill); + object.ZoneColor(crl); + object.ZoneWidth(width); + object.ZoneStyle(style); + + // + return result; + } + + /** + * Create Resistance Object ... + * + * @param zone: XCResistanceZone instance ... + * @param object: XCResistanceZoneObject pointer ... + * + * @return ( bool ) + */ + bool CreateResistanceZone( + XCResistanceZone &zone, + XCResistanceZoneObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + zone.IsValid(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + bool fill = ResistanceZoneFill(); + int width = ResistanceZoneWidth(); + color crl = ResistanceZoneColor(); + ENUM_LINE_STYLE style = ResistanceZoneStyle(); + + // + object = new XCResistanceZoneObject(); + result = object.Create( + chartID, + window, + zone, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ZoneFill(fill); + object.ZoneColor(crl); + object.ZoneWidth(width); + object.ZoneStyle(style); + + // + return result; + } + + // + // Supply and Demand Zones ... + + /** + * Create Supply Object ... + * + * @param zone: XCSupplyZone instance ... + * @param object: XCSupplyZoneObject pointer ... + * + * @return ( bool ) + */ + bool CreateSupplyZone( + XCSupplyZone &zone, + XCSupplyZoneObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + zone.IsValid(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + bool fill = SupplyZoneFill(); + int width = SupplyZoneWidth(); + color crl = SupplyZoneColor(); + ENUM_LINE_STYLE style = SupplyZoneStyle(); + + // + object = new XCSupplyZoneObject(); + result = object.Create( + chartID, + window, + zone, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ZoneFill(fill); + object.ZoneColor(crl); + object.ZoneWidth(width); + object.ZoneStyle(style); + + // + return result; + } + + /** + * Create Demand Object ... + * + * @param zone: XCDemandZone instance ... + * @param object: XCDemandZoneObject pointer ... + * + * @return ( bool ) + */ + bool CreateDemandZone( + XCDemandZone &zone, + XCDemandZoneObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + zone.IsValid(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + bool fill = DemandZoneFill(); + int width = DemandZoneWidth(); + color crl = DemandZoneColor(); + ENUM_LINE_STYLE style = DemandZoneStyle(); + + // + object = new XCDemandZoneObject(); + result = object.Create( + chartID, + window, + zone, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ZoneFill(fill); + object.ZoneColor(crl); + object.ZoneWidth(width); + object.ZoneStyle(style); + + // + return result; + } + + // + // Order Blocks ... + + /** + * Create Bullish Order Block Object ... + * + * @param zone: XCOrderBlock instance ... + * @param object: XCBullishOrderBlockObject pointer ... + * + * @return ( bool ) + */ + bool CreateBullishOrderBlock( + XCOrderBlock &zone, + XCBullishOrderBlockObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + zone.IsValid() && + zone.IsBullish(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + bool fill = BullishOrderBlockFill(); + int width = BullishOrderBlockWidth(); + color crl = BullishOrderBlockColor(); + ENUM_LINE_STYLE style = BullishOrderBlockStyle(); + + // + object = new XCBullishOrderBlockObject(); + result = object.Create( + chartID, + window, + zone, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ZoneFill(fill); + object.ZoneColor(crl); + object.ZoneWidth(width); + object.ZoneStyle(style); + + // + return result; + } + + /** + * Create Bearish Order Block Object ... + * + * @param zone: XCOrderBlock instance ... + * @param object: XCBearishOrderBlockObject pointer ... + * + * @return ( bool ) + */ + bool CreateBearishOrderBlock( + XCOrderBlock &zone, + XCBearishOrderBlockObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + zone.IsValid() && + zone.IsBearish(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + bool fill = BearishOrderBlockFill(); + int width = BearishOrderBlockWidth(); + color crl = BearishOrderBlockColor(); + ENUM_LINE_STYLE style = BearishOrderBlockStyle(); + + // + object = new XCBearishOrderBlockObject(); + result = object.Create( + chartID, + window, + zone, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ZoneFill(fill); + object.ZoneColor(crl); + object.ZoneWidth(width); + object.ZoneStyle(style); + + // + return result; + } + + bool CreateOrderBlock( + XCOrderBlock &zone, + XCBaseObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + bool isBullish = zone.IsBullish(); + if (isBullish) + { + // + XCBullishOrderBlockObject *iObj; + result = CreateBullishOrderBlock( + zone, + iObj // + ); + if (result) + { + object = (XCBaseObject *)iObj; + } + } + else + { + // + XCBearishOrderBlockObject *iObj; + result = CreateBearishOrderBlock( + zone, + iObj // + ); + if (result) + { + object = (XCBaseObject *)iObj; + } + } + + // + return result; + } + + // + // Fair Value Gaps ... + + /** + * Create Bullish Fair Value Gap Object ... + * + * @param zone: XCFVG instance ... + * @param object: XCBullishOrderBlockObject pointer ... + * + * @return ( bool ) + */ + bool CreateBullishFairValueGap( + XCFVG &zone, + XCBullishFairValueGapObject *&object // + ) + { + // + bool result = false; + + // + result = zone.IsValid() && + zone.IsBullish(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + bool fill = BullishFVGFill(); + int width = BullishFVGWidth(); + color crl = BullishFVGColor(); + ENUM_LINE_STYLE style = BullishFVGStyle(); + + // + object = new XCBullishFairValueGapObject(); + result = object.Create( + chartID, + window, + zone, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ZoneFill(fill); + object.ZoneColor(crl); + object.ZoneWidth(width); + object.ZoneStyle(style); + + // + return result; + } + + /** + * Create Bearish Fair Value Gap Object ... + * + * @param zone: XCFVG instance ... + * @param object: XCBearishOrderBlockObject pointer ... + * + * @return ( bool ) + */ + bool CreateBearishFairValueGap( + XCFVG &zone, + XCBearishFairValueGapObject *&object // + ) + { + // + bool result = false; + + // + result = zone.IsValid() && + zone.IsBearish(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + bool fill = BearishFVGFill(); + int width = BearishFVGWidth(); + color crl = BearishFVGColor(); + ENUM_LINE_STYLE style = BearishFVGStyle(); + + // + object = new XCBearishFairValueGapObject(); + result = object.Create( + chartID, + window, + zone, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ZoneFill(fill); + object.ZoneColor(crl); + object.ZoneWidth(width); + object.ZoneStyle(style); + + // + return result; + } + + bool CreateFairValueGap( + XCFVG &zone, + XCBaseObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + bool isBullish = zone.IsBullish(); + if (isBullish) + { + // + XCBullishFairValueGapObject *iObj; + result = CreateBullishFairValueGap( + zone, + iObj // + ); + if (result) + { + object = (XCBaseObject *)iObj; + } + } + else + { + // + XCBearishFairValueGapObject *iObj; + result = CreateBearishFairValueGap( + zone, + iObj // + ); + if (result) + { + object = (XCBaseObject *)iObj; + } + } + + // + return result; + } + + // + // Ticks Zone ... + + /** + * Add Tick Zone Draw Specifications ... + * + * @param specs: XTickZoneLevelSpecs instance ... + */ + void AddTickZoneLevelSpecs( + XTickZoneLevelSpecs &specs // + ) + { + // + if (!specs.IsValid()) + { + return; + } + + // + bool isExists = false; + int count = ArraySize(mTicksZoneSpecs); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XTickZoneLevelSpecs iSpec = mTicksZoneSpecs[i]; + + // + isExists = specs.percent == iSpec.percent; + if (isExists) + { + break; + } + } + } + if (isExists) + { + return; + } + + // + AddRef( + specs, + mTicksZoneSpecs // + ); + } + + /** + * Draw Specified Ticker Zone ... + * + * @param zone: XCTicksZone instance Specified Ticker Zone ... + * @param object: XCTicksZoneObject pointer ... + * + * @return ( bool ) + */ + bool CreateTicksZone( + XCTicksZone &zone, + XCTicksZoneObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + object = new XCTicksZoneObject(); + result = object.Create( + chartID, + window, + zone, + mTicksZoneSpecs, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Create Consolidation Zone Object ... + * + * @param zone: XConsolidationZone instance Reference ... + * + * @return ( bool ) + */ + bool CreateConsolidationZone( + XConsolidationZone &zone, + XCConsolidationZoneObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + color czColor = IsBullish(zone.dir) + ? BarBullishColor() + : BarBearishColor(); + + // + object = new XCConsolidationZoneObject(); + result = object.Create( + chartID, + window, + zone, + prefix // + ); + + // + if (result) + { + object.ZoneColor(czColor); + } + + // + return result; + } + + /** + * Create Bar Object ... + * + * @param bar: XOHCL instance Reference ... + * @param object: XCOHCLObject pointer Reference .. + * @param to: Datetime ... + * + * @return ( bool ) + */ + bool CreateBar( + XOHCL &bar, + XCOHCLObject *&object, + datetime to = NULL // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + to = NormalizeTime(to); + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + int width = BarWidth(); + + // + color mBullishColor = BarBullishColor(); + color mBearishColor = BarBearishColor(); + + // + bool fillBody = BarFillBody(); + bool fillHighShadow = BarFillHighShadow(); + bool fillLowShadow = BarFillLowShadow(); + + // + ENUM_LINE_STYLE bodyStyle = BarBodyStyle(); + ENUM_LINE_STYLE highShadowStyle = BarHighShadowStyle(); + ENUM_LINE_STYLE lowShadowStyle = BarLowShadowStyle(); + + // + object = new XCOHCLObject(); + result = object.Create( + chartID, + window, + bar, + to, + prefix // + ); + if (result) + { + // + // Apply Styling ... + + // + object.BodyWidth(width); + object.LowShadowWidth(width); + object.HighShadowWidth(width); + + // + object.BodyStyle(bodyStyle); + object.LowShadowStyle(lowShadowStyle); + object.HighShadowStyle(highShadowStyle); + + // + bool isBullish = bar.IsBullish(); + if (isBullish) + { + // + object.BodyColor(mBullishColor); + object.LowShadowColor(mBullishColor); + object.HighShadowColor(mBullishColor); + } + else + { + // + object.BodyColor(mBearishColor); + object.LowShadowColor(mBearishColor); + object.HighShadowColor(mBearishColor); + } + + // + object.BodyFill(fillBody); + object.HighShadowFill(fillHighShadow); + object.LowShadowFill(fillLowShadow); + } + + // + return result; + } + + /** + * Create Bar Arrow Object ... + * + * @param bar: XOHCL instance Reference ... + * @param priceType: ENUM_X_PRICE member ... + * @param arrow: int, Arrow Code ... + * @param clr: color, Arro Color ... + * @param width: int, Arrow Width ... + * @param anchor: ENUM_ARROW_ANCHOR, anchor of Arrow ... + * @param name: string, name of Arrow ... + * + * @return ( bool ) + */ + bool CreateBarArrow( + XOHCL &bar, + XCBarArrowObject *&object, + ENUM_X_PRICE priceType, + int arrow = 159, + color clr = clrYellow, + int width = 3, + ENUM_ARROW_ANCHOR anchor = ANCHOR_BOTTOM, + string name = NULL // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + string barTag = bar.GetTag(name); + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + color mBullishColor = BarBullishColor(); + color mBearishColor = BarBearishColor(); + + // + prefix = + (IsValid(prefix) + ? prefix + "_" + : prefix) + + barTag; + + // + object = new XCBarArrowObject(); + result = object + .CreateByBar( + chartID, + prefix, + window, + arrow, + bar, + priceType // + ); + if (result) + { + // + object.ArrowColor(clr); + object.ArrowWidth(width); + } + + // + return result; + } + + /** + * Create Specific Box on Chart ... + * + * @param upper: Double ... + * @param lower: Double ... + * @param from: Datetime ... + * @param to: Datetime ... + * @param clr: Color ... + * @param width: Integer ... + * @param fill: Boolean ... + * @param style: ENUM_LINE_STYLE member ... + * + * @return ( bool ) + */ + bool CreateBox( + XCBoxObject *&object, + string name, + double upper, + double lower, + datetime from, + datetime to, + color clr = clrYellowGreen, + int width = 1, + bool fill = false, + ENUM_LINE_STYLE style = STYLE_SOLID // + ) + { + // + bool result = false; + + // + object = NULL; + + // + to = NormalizeTime(to); + + // + string dateStr = ToFormatString(from) + "|" + ToFormatString(to); + string dateMD5 = ToMD5(dateStr); + if (!IsValid(name)) + { + // + name = "XBox_" + + ToString(upper) + "_" + + ToString(lower) + "_" + + dateMD5; + } + + // + result = + upper > 0 && + lower > 0 && + to > from && + IsValid(to) && + IsValid(name) && + IsValid(from) && + upper > lower; + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + object = new XCBoxObject(); + result = object.Create( + chartID, + window, + name, + upper, + lower, + from, + to, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.BoxColor(clr); + object.BoxFill(fill); + object.BoxWidth(width); + object.BoxStyle(style); + + // + return result; + } + + /** + * Create Specific Box on Chart ... + * + * @param box: XBoxZone instance Reference ... + * @param clr: Color ... + * @param width: Integer ... + * @param fill: Boolean ... + * @param style: ENUM_LINE_STYLE member ... + * + * @return ( bool ) + */ + bool DrawBox( + XBoxZone &box, + XCBoxObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = box.IsValid(); + if (!result) + { + return result; + } + + // + int width = 1; + bool fill = false; + color clr = + box.IsBullish() + ? BullishFVGColor() + : BearishFVGColor(); + ENUM_LINE_STYLE style = STYLE_DASHDOTDOT; + string name = box.GetTag(); + + // + result = CreateBox( + object, + name, + box.upper, + box.lower, + box.from, + box.to, + clr, + width, + fill, + style // + ); + + // + return result; + } + + /** + * Create Specific Box on Chart ... + * + * @param box: XBoxZone instance Reference ... + * @param clr: Color ... + * @param width: Integer ... + * @param fill: Boolean ... + * @param style: ENUM_LINE_STYLE member ... + * + * @return ( bool ) + */ + bool CreateBox( + XBoxZone &box, + XCBoxObject *&object, + color clr = clrYellowGreen, + int width = 1, + bool fill = false, + ENUM_LINE_STYLE style = STYLE_SOLID // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = box.IsValid(); + if (!result) + { + return result; + } + + // + string name = box.GetTag(); + + // + result = CreateBox( + object, + name, + box.upper, + box.lower, + box.from, + box.to, + clr, + width, + fill, + style // + ); + + // + return result; + } + + /** + * Draw Specified Signal ... + * + * @param signal: XSignal instance ... + */ + bool DrawSignal( + XSignal &signal, + XCSignalObject *&object, + int length = 3 // + ) + { + // + bool result = false; + + // + object = NULL; + length = NormalizeInt(length, 3); + + // + result = signal.IsValid(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + object = new XCSignalObject(); + result = object.Create( + chartID, + window, + signal, + length, + prefix // + ); + if (!result) + { + return result; + } + + // + object.TPWidth(1); + object.TPColor(clrGreen); + object.TPWidth(STYLE_DOT); + + // + object.SLWidth(1); + object.SLColor(clrRed); + object.SLWidth(STYLE_DOT); + + // + object.TargetWidth(1); + object.TargetColor(clrLightBlue); + object.TargetWidth(STYLE_DOT); + + // + object.EntryWidth(1); + object.EntryColor(clrYellow); + object.EntryWidth(STYLE_DOT); + + // + return result; + } + + /** + * Draw Signal Box ... + * + * @param box: XSignalBox instance Reference ... + * @param objects: XCBaseObject pointer instance Reference ... + * + * @return ( bool ) + */ + bool DrawSignalBox( + XSignalBox &box, + XCBaseObject *&objects[], + color clr = CLR_NONE // + ) + { + // + bool result = false; + + // + Clean(objects); + + // + bool has = false; + bool hasColor = clr != CLR_NONE; + + // + // Order Block ... + if (box.ob.IsValid()) + { + // + XCBoxObject *iObj; + has = DrawBox( + box.ob, + iObj // + ); + if (has) + { + // + iObj.BoxStyle(STYLE_DASH); + + // + if (hasColor) + { + iObj.BoxColor(clr); + } + + // + Add( + (XCBaseObject *)iObj, + objects // + ); + } + } + + // + // Fair Value Gap ... + if (box.fvg.IsValid()) + { + // + XCBoxObject *iObj; + has = DrawBox( + box.fvg, + iObj // + ); + if (has) + { + // + iObj.BoxStyle(STYLE_SOLID); + + // + if (hasColor) + { + iObj.BoxColor(clr); + } + + // + Add( + (XCBaseObject *)iObj, + objects // + ); + } + } + + // + // Sharp Zone ... + if (box.sharp.IsValid()) + { + // + XCBoxObject *iObj; + has = DrawBox( + box.sharp, + iObj // + ); + if (has) + { + // + iObj.BoxStyle(STYLE_DOT); + + // + if (hasColor) + { + iObj.BoxColor(clr); + } + + // + Add( + (XCBaseObject *)iObj, + objects // + ); + } + } + + // + result = HasChild(objects); + + // + return result; + } + + /** + * Draw Specified POI State ... + * + * @param state: XPOIState instance Reference ... + * @param drawnObjects: CArrayObj instance for Holding Drawn Objects ... + * @param drawTicksZone: Boolean ... + * @param ignoreSwingHighs: Boolean ... + * @param ignoreSwingLows: Boolean ... + * @param ignoreSupportZones: Boolean ... + * @param ignoreResistanceZones: Boolean ... + * @param ignoreSupplyZones: Boolean ... + * @param ignoreDemandZones: Boolean ... + * @param ignoreBullishOrderBlocks: Boolean ... + * @param ignoreBearishOrderBlocks: Boolean ... + * @param ignoreBullishFairValueGaps: Boolean ... + * @param ignoreBearishFairValueGaps: Boolean ... + * @param ignoreBullishRejectionBars: Boolean ... + * @param ignoreBearishRejectionBars: Boolean ... + * @param ignoreBullishMomentumBars: Boolean ... + * @param ignoreBearishMomentumBars: Boolean ... + */ + int DrawState( + XPOIState &state, + XCBaseObject *&drawnObjects[], + // + // Bullish ... + bool ignoreSwingLows = false, + bool ignoreDemandZones = false, + bool ignoreSupportZones = false, + bool ignoreBullishSharps = false, + bool ignoreBullishSpikes = false, + bool ignoreBullishPullbacks = false, + bool ignoreBullishMomentums = false, + bool ignoreBullishRejections = false, + bool ignoreBullishOrderBlocks = false, + bool ignoreBullishFairValueGaps = false, + bool ignoreBullishConsolidationZones = false, + // + // Bearish ... + bool ignoreSwingHighs = false, + bool ignoreSupplyZones = false, + bool ignoreResistanceZones = false, + bool ignoreBearishSharps = false, + bool ignoreBearishSpikes = false, + bool ignoreBearishPullbacks = false, + bool ignoreBearishMomentums = false, + bool ignoreBearishRejections = false, + bool ignoreBearishOrderBlocks = false, + bool ignoreBearishFairValueGaps = false, + bool ignoreBearishConsolidationZones = false // + ) + { + // + int result = 0; + + // + if (!state.IsValid() || + !state.HasChild()) + { + return result; + } + + // + Clean(drawnObjects); + + // + // Swings ... + + // + // SwingHighs ... + if (!ignoreSwingHighs) + { + // + int count = state.CountSwingHighs(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSwing *iSwing = state.swingHighs[i]; + XCSwingHighObject *iObj; + + // + bool isCreated = CreateSwingHigh( + iSwing, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // SwingLows ... + if (!ignoreSwingLows) + { + // + int count = state.CountSwingLows(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSwing *iSwing = state.swingLows[i]; + XCSwingLowObject *iObj; + + // + bool isCreated = CreateSwingLow( + iSwing, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // Support / Resistance ... + + // + // SupportZones ... + if (!ignoreSupportZones) + { + // + int count = state.CountSupportZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSupportZone *iZone = state.supportZones[i]; + XCSupportZoneObject *iObj; + + // + bool isCreated = CreateSupportZone( + iZone, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // ResistanceZones ... + if (!ignoreResistanceZones) + { + // + int count = state.CountResistanceZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCResistanceZone *iZone = state.resistanceZones[i]; + XCResistanceZoneObject *iObj; + + // + bool isCreated = CreateResistanceZone( + iZone, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // Supply / Demand ... + + // + // SupplyZones ... + if (!ignoreSupplyZones) + { + // + int count = state.CountSupplyZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSupplyZone *iZone = state.supplyZones[i]; + XCSupplyZoneObject *iObj; + + // + bool isCreated = CreateSupplyZone( + iZone, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // DemandZones ... + if (!ignoreDemandZones) + { + // + int count = state.CountDemandZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCDemandZone *iZone = state.demandZones[i]; + XCDemandZoneObject *iObj; + + // + bool isCreated = CreateDemandZone( + iZone, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // Order Blocks ... + + // + // BullishOrderBlocks ... + if (!ignoreBullishOrderBlocks) + { + // + int count = state.CountBullishOrderBlocks(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iZone = state.bullishOrderBlocks[i]; + XCBullishOrderBlockObject *iObj; + + // + bool isCreated = CreateBullishOrderBlock( + iZone, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // BearishOrderBlocks ... + if (!ignoreBearishOrderBlocks) + { + // + int count = state.CountBearishOrderBlocks(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iZone = state.bearishOrderBlocks[i]; + XCBearishOrderBlockObject *iObj; + + // + bool isCreated = CreateBearishOrderBlock( + iZone, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // Fair Value Gaps ... + + // + // BullishFairValueGaps ... + if (!ignoreBullishFairValueGaps) + { + // + int count = state.CountBullishFairValueGaps(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCFVG *iZone = state.bullishFairValueGaps[i]; + XCBullishFairValueGapObject *iObj; + + // + bool isCreated = CreateBullishFairValueGap( + iZone, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // BearishFairValueGaps ... + if (!ignoreBearishFairValueGaps) + { + // + int count = state.CountBearishFairValueGaps(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCFVG *iZone = state.bearishFairValueGaps[i]; + XCBearishFairValueGapObject *iObj; + + // + bool isCreated = CreateBearishFairValueGap( + iZone, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // Rejections ... + + // + // BullishRejectionBars ... + if (!ignoreBullishRejections) + { + // + int count = state.CountBullishRejections(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCRejectionBar *iBar = state.bullishRejections[i]; + XCBullishRejectionBarObject *iObj; + + // + bool isCreated = CreateBullishRejectionBar( + iBar, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // BearishRejectionBars ... + if (!ignoreBearishRejections) + { + // + int count = state.CountBearishRejections(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCRejectionBar *iBar = state.bearishRejections[i]; + XCBearishRejectionBarObject *iObj; + + // + bool isCreated = CreateBearishRejectionBar( + iBar, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // Momentums ... + + // + // BullishMomentumBars ... + if (!ignoreBullishMomentums) + { + // + int count = state.CountBullishMomentums(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCMomentumBar *iBar = state.bullishMomentums[i]; + XCBullishMomentumBarObject *iObj; + + // + bool isCreated = CreateBullishMomentumBar( + iBar, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // BearishMomentumBars ... + if (!ignoreBearishMomentums) + { + // + int count = state.CountBearishMomentums(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCMomentumBar *iBar = state.bearishMomentums[i]; + XCBearishMomentumBarObject *iObj; + + // + bool isCreated = CreateBearishMomentumBar( + iBar, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // Pullbacks ... + + // + // Bullish ... + if (!ignoreBullishPullbacks) + { + // + int count = state.CountBullishPullbacks(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCBoxObject *iObj; + bool isCreated = DrawBox( + state.bullishPullbacks[i], + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // Bearish ... + if (!ignoreBearishPullbacks) + { + // + int count = state.CountBearishPullbacks(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCBoxObject *iObj; + bool isCreated = DrawBox( + state.bearishPullbacks[i], + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // Consolidation Zones ... + + // + // Bullish Consolidation Zones ... + if (!ignoreBullishConsolidationZones) + { + // + int count = state.CountBullishConsolidationZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCConsolidationZoneObject *iObj; + bool isCreated = CreateConsolidationZone( + state.bullishConsolidationZones[i], + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // Bearish Consolidation Zones ... + if (!ignoreBearishConsolidationZones) + { + // + int count = state.CountBearishConsolidationZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCConsolidationZoneObject *iObj; + bool isCreated = CreateConsolidationZone( + state.bearishConsolidationZones[i], + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // Spikes ... + + // + // Bullish ... + if (!ignoreBullishSpikes) + { + // + int count = state.CountBullishSpikes(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCBoxObject *iObj; + bool isCreated = DrawBox( + state.bullishSpikes[i], + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // Bearish ... + if (!ignoreBearishSpikes) + { + // + int count = state.CountBearishSpikes(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCBoxObject *iObj; + bool isCreated = DrawBox( + state.bearishSpikes[i], + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // Sharps ... + + // + // Bullish ... + if (!ignoreBullishSharps) + { + // + int count = state.CountBullishSharps(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCBoxObject *iObj; + bool isCreated = DrawBox( + state.bullishSharps[i], + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // Bearish ... + if (!ignoreBearishSharps) + { + // + int count = state.CountBearishSharps(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCBoxObject *iObj; + bool isCreated = DrawBox( + state.bearishSharps[i], + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + result = ArraySize(drawnObjects); + + // + return result; + } + + // + protected: + // + + // + private: + // + + // + // Props ... + + // + string mPrefix; // Prefix of Created Objects ... + long mChartIdentification; // Chart Id ... + int mSubWindowIdentification; // Sub Window ... + + // + // XOHCL ... + int mBarWidth; // Bar Width ... + color mBarBullishColor; // Bar Bullish Color ... + color mBarBearishColor; // Bar Bearish Color ... + bool mBarFillHighShadow; // Fill Bar High Shadow ... + ENUM_LINE_STYLE mBarHighShadowStyle; // Bar High Shadow Style ... + bool mBarFillBody; // Fill Bar Body ... + ENUM_LINE_STYLE mBarBodyStyle; // Bar Body Style ... + bool mBarFillLowShadow; // Fill Bar Low Show ... + ENUM_LINE_STYLE mBarLowShadowStyle; // Bar Low Shadow Style ... + + // + // Swing Low ... + int mSwingLowWidth; // Swing Low Width ... + int mSwingLowArrow; // Swing Low Arrow Code ... + color mSwingLowColor; // Swing Low Color ... + + // + // Swing High ... + int mSwingHighWidth; // Swing High Width ... + int mSwingHighArrow; // Swing High Arrow Code ... + color mSwingHighColor; // Swing High Color ... + + // + // Bullish Momentum Bar ... + int mBullishMomentumBarWidth; // Bullish Momentum Bar Width ... + int mBullishMomentumBarArrow; // Bullish Momentum Bar Arrow Code ... + color mBullishMomentumBarColor; // Bullish Momentum Bar Color ... + + // + // Bearish Momentum Bar ... + int mBearishMomentumBarWidth; // Bearish Momentum Bar Width ... + int mBearishMomentumBarArrow; // Bearish Momentum Bar Arrow Code ... + color mBearishMomentumBarColor; // Bearish Momentum Bar Color ... + + // + // Bullish Rejection Bar ... + int mBullishRejectionBarWidth; // Bullish Rejection Bar High Width ... + int mBullishRejectionBarArrow; // Bullish Rejection Bar High Arrow Code ... + color mBullishRejectionBarColor; // Bullish Rejection Bar High Color ... + + // + // Bearish Rejection Bar ... + int mBearishRejectionBarWidth; // Bearish Rejection Bar Width ... + int mBearishRejectionBarArrow; // Bearish Rejection Bar Arrow Code ... + color mBearishRejectionBarColor; // Bearish Rejection Bar Color ... + + // + // Supply Zone ... + bool mSupplyZoneFill; // Fill Supply Zone ... + int mSupplyZoneWidth; // Supply Zone Width ... + color mSupplyZoneColor; // Supply Zone Color ... + ENUM_LINE_STYLE mSupplyZoneStyle; // Supply Zone Style ... + + // + // Demand Zone ... + bool mDemandZoneFill; // Fill Demand Zone ... + int mDemandZoneWidth; // Demand Zone Width ... + color mDemandZoneColor; // Demand Zone Color ... + ENUM_LINE_STYLE mDemandZoneStyle; // Demand Zone Style ... + + // + // Resistance Zone ... + bool mResistanceZoneFill; // Fill Resistance Zone ... + int mResistanceZoneWidth; // Resistance Zone Width ... + color mResistanceZoneColor; // Resistance Zone Color ... + ENUM_LINE_STYLE mResistanceZoneStyle; // Resistance Zone Style ... + + // + // Support Zone ... + bool mSupportZoneFill; // Fill Support Zone ... + int mSupportZoneWidth; // Support Zone Width ... + color mSupportZoneColor; // Support Zone Color ... + ENUM_LINE_STYLE mSupportZoneStyle; // Support Zone Style ... + + // + // Bullish Order Block ... + bool mBullishOrderBlockFill; // Fill Bullish Order Block ... + int mBullishOrderBlockWidth; // Bullish Order Block Width ... + color mBullishOrderBlockColor; // Bullish Order Block Color ... + ENUM_LINE_STYLE mBullishOrderBlockStyle; // Bullish Order Block Style ... + + // + // Bearish Order Block ... + bool mBearishOrderBlockFill; // Fill Bearish Order Block ... + int mBearishOrderBlockWidth; // Bearish Order Block Width ... + color mBearishOrderBlockColor; // Bearish Order Block Color ... + ENUM_LINE_STYLE mBearishOrderBlockStyle; // Bearish Order Block Style ... + + // + // Bullish FVG ... + bool mBullishFVGFill; // Fill Bullish FVG ... + int mBullishFVGWidth; // Bullish FVG Width ... + color mBullishFVGColor; // Bullish FVG Color ... + ENUM_LINE_STYLE mBullishFVGStyle; // Bullish FVG Style ... + + // + // Bearish FVG ... + bool mBearishFVGFill; // Fill Bearish FVG ... + int mBearishFVGWidth; // Bearish FVG Width ... + color mBearishFVGColor; // Bearish FVG Color ... + ENUM_LINE_STYLE mBearishFVGStyle; // Bearish FVG Style ... + + // + // Ticks Zone ... + XTickZoneLevelSpecs mTicksZoneSpecs[]; // Zone Draw Specifications ... + + // +}; \ No newline at end of file diff --git a/BKPS/14040316/Classes/x-saherelm.x-rm.panel.class.mq5 b/BKPS/14040316/Classes/x-saherelm.x-rm.panel.class.mq5 new file mode 100644 index 0000000..d3808dc --- /dev/null +++ b/BKPS/14040316/Classes/x-saherelm.x-rm.panel.class.mq5 @@ -0,0 +1,1162 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XCRMPanel +// 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 + +// +// Imports ... +#include "../Classes/x-saherelm.x-app-dialog.class.mq5" +#include "../Classes/x-saherelm.x-trade.class.mq5" + +// +#include +#include +#include +#include +#include +#include + +// +// Implementation ... + +// +class XCRMPanel : public XCAppDialog +{ + // + public: + // + // Event Binding ... + // EVENT_MAP_BEGIN(XCRMPanel) + // ON_EVENT(ON_CLICK, btnBuy, HandleBtnBuyClicked) + // ON_EVENT(ON_CLICK, btnSell, HandleBtnSellClicked) + // EVENT_MAP_END(XCRMPanel) + + // + // Constructor(s) ... + void XCRMPanel() + { + // + Default(); + } + + // + // Deconstructor ... + void ~XCRMPanel() + { + // + HandleRemoveObjects(); + + // + ZeroMemory(mTrader); + } + + // + // Props ... + + // + int SubWindow() + { + return subWindow; + } + + // + void SubWindow(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + subWindow = value; + } + + // + // BUY ... + + // + string BtnBuyLabel() + { + return buyLabelStr; + } + + // + void BtnBuyLabel(string value) + { + buyLabelStr = value; + } + + // + color BtnBuyBGColor() + { + return btnBuyBGColor; + } + + // + void BtnBuyBGColor(color value) + { + btnBuyBGColor = value; + } + + // + // SELL ... + + // + string BtnSellLabel() + { + return sellLabelStr; + } + + // + void BtnSellLabel(string value) + { + sellLabelStr = value; + } + + // + color BtnSellBGColor() + { + return btnSellBGColor; + } + + // + void BtnSellBGColor(color value) + { + btnSellBGColor = value; + } + + // + double RiskPercent() + { + return riskPercent; + } + + // + void RiskPercent(double value) + { + // + if (value < minAllowedRiskPercent) + { + value = minAllowedRiskPercent; + } + + // + if (value > maxAllowedRiskPercent) + { + value = maxAllowedRiskPercent; + } + + // + riskPercent = value; + + // + tbRisk.Text((string)value); + } + + // + // + // + + bool HasSL() + { + return slLine != NULL; + } + + double ReadSL() + { + // + double result = 0; + + // + if (HasSL()) + { + // + result = slLine.GetDouble(OBJPROP_PRICE); + result = NormalizePrice(result, _Symbol); + } + + // + return result; + } + + bool HasTP() + { + return tpLine != NULL; + } + + double ReadTP() + { + // + double result = 0; + + // + if (HasTP()) + { + // + result = tpLine.GetDouble(OBJPROP_PRICE); + result = NormalizePrice(result, _Symbol); + } + + // + return result; + } + + bool HasEntry() + { + return entryLine != NULL; + } + + double ReadEntry() + { + // + double result = 0; + + // + if (HasEntry()) + { + // + result = entryLine.GetDouble(OBJPROP_PRICE); + result = NormalizePrice(result, _Symbol); + } + + // + return result; + } + + bool GetDirection(ENUM_X_DIRECTION &dir) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + result = HasTP() && + HasSL() && + HasEntry(); + + // + if (!result) + { + return result; + } + + // + double sl = ReadSL(); + double tp = ReadTP(); + double entry = ReadEntry(); + + // + result = sl > 0 && + tp > 0 && + entry > 0; + if (!result) + { + return result; + } + + // + bool isBullish = + tp > entry && + tp > sl && + entry > sl; + bool isBearish = + tp < entry && + tp < sl && + entry < sl; + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + dir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; + } + + // + // Tools ... + + // + void Default() + { + // + string prefix = CreateInstanceId(); + + // + defaultR2R = 2; + riskPercent = 1; + defaultRisk = 50; + minAllowedRiskPercent = 0.5; + maxAllowedRiskPercent = 10.0; + + // + disabledBtnColor = clrLightGray; + disabledBtnBGColor = clrGray; + + // + tbRiskID = prefix + "_RiskTB"; + + // + buyLabelStr = "Buy"; + btnBuyBGColor = clrLime; + btnBuyColor = clrDarkBlue; + btnBuyID = prefix + "_" + buyLabelStr; + + // + sellLabelStr = "Sell"; + btnSellBGColor = clrRed; + btnSellColor = clrDarkBlue; + btnSellID = prefix + "_" + sellLabelStr; + + // + slLine = NULL; + slColor = clrMagenta; + slID = prefix + "_SL"; + + // + tpLine = NULL; + tpColor = clrAqua; + tpID = prefix + "_TP"; + + // + entryLine = NULL; + entryColor = clrYellow; + entryID = prefix + "_Entry"; + + // + btnDrawRemoveID = prefix + "_DrawRemove"; + drawLabelStr = "Draw"; + removeLabelStr = "Remove"; + btnDrawColor = clrWhite; + btnDrawBGColor = clrDarkBlue; + btnRemoveColor = clrYellow; + btnRemoveBGColor = clrDarkRed; + + // + slippage = 10; + magicNumber = 1694056; + + // + // Create Trader Instance and Configure it ... + mTrader = new XCTrade( + slippage, + magicNumber // + ); + } + + // + void UpdateState() + { + // + bool canEnable = HasSL() && + HasTP() && + HasEntry(); + + // + if (canEnable) + { + SetRemoveMode(); + } + else + { + SetDrawMode(); + } + + // + double entry = GetBid(_Symbol); + ENUM_X_DIRECTION dir; + if (GetDirection(dir)) + { + entry = GetEntry(_Symbol, dir); + } + + // + if (HasEntry()) + { + double iEntry = ReadEntry(); + if (iEntry != entry) + { + SetEntry(entry); + } + } + } + + // + // Handlers ... + + /** + * Handle Btn Buy Clicked ... + */ + void HandleBtnBuyClicked() + { + // + ENUM_X_DIRECTION dir; + bool has = GetDirection(dir); + bool isBullish = has & + IsBullish(dir); + if (!has || !isBullish) + { + return; + } + + // + double tp = ReadTP(); + double sl = ReadSL(); + double entry = ReadEntry(); + + // + mTrader.Buy( + _Symbol, + _Period, + volume, + entry, + sl, + tp // + ); + } + + /** + * Handle Btn Sell Clicked ... + */ + void HandleBtnSellClicked() + { + // + ENUM_X_DIRECTION dir; + bool has = GetDirection(dir); + bool isBearish = has & + IsBearish(dir); + if (!has || !isBearish) + { + return; + } + + // + double tp = ReadTP(); + double sl = ReadSL(); + double entry = ReadEntry(); + + // + mTrader.Sell( + _Symbol, + _Period, + volume, + entry, + sl, + tp // + ); + } + + /** + * Handle Draw Remove Position ... + */ + void HandleBtnDrawRemoveClicked() + { + // + string btnText = btnDrawRemove.Text(); + if (btnText == drawLabelStr) + { + HandleDrawObjects(); + } + else if (btnText == removeLabelStr) + { + HandleRemoveObjects(); + } + } + + /** + * Handle Risk Percent Changed ... + */ + void HandleOnRiskPercentChanged() + { + // + string tbRiskStr = tbRisk.Text(); + + // + double tbNewRisk = (double)tbRiskStr; + RiskPercent(tbNewRisk); + } + + // + // Virtuals ... + + // + virtual bool OnEvent( + const int id, + const long &lparam, + const double &dparam, + const string &sparam // + ) + { + // + bool result = false; + + // + XCAppDialog::OnEvent(id, lparam, dparam, sparam); + + // + // Check if the event is a button click + if (id == ON_CLICK + CHARTEVENT_CUSTOM) + { + // + // Verify if the clicked object is this button + if (lparam == btnBuy.Id()) + { + // + HandleBtnBuyClicked(); + result = true; + } + else if (lparam == btnSell.Id()) + { + // + HandleBtnSellClicked(); + result = true; + } + else if (lparam == btnDrawRemove.Id()) + { + // + HandleBtnDrawRemoveClicked(); + result = true; + } + } + else if (id == ON_END_EDIT + CHARTEVENT_CUSTOM) + { + // + if (lparam == tbRisk.Id()) + { + // + HandleOnRiskPercentChanged(); + result = true; + } + } + else if (id == CHARTEVENT_OBJECT_DRAG) + { + // + if (sparam == entryLine.Name()) + { + // + CalculateData(); + result = true; + } + else if (sparam == tpLine.Name()) + { + // + CalculateData(); + result = true; + } + else if (sparam == slLine.Name()) + { + // + CalculateData(); + result = true; + } + } + + // + return result; + } + + // + // Overrides ... + + // + bool Create( + const long chart, + const string name, + const int subwin, + const int x1, + const int y1, + const int x2, + const int y2 // + ) + { + // + bool result = false; + + // + // Create App Dialog instance it Self ... + result = XCAppDialog::Create( + chart, + name, + subwin, + x1, + y1, + x2, + y2 // + ); + if (!result) + { + return result; + } + + // + chartId = chart; + subWindow = subwin; + + // + // Configure Dialog ... + BackgroundColor(clrBlack); + + // + int top = Top(); + int left = Left(); + int right = Right(); + int bottom = Bottom(); + + // + int width = Width(); + int height = Height(); + + // + int desiredWidth = width - left; + int desiredHeight = height - top; + + // + int btnWidth = desiredWidth / 2; + int btnHeight = desiredHeight / 3; + + // + // Risk Edit ... + int tbRiskX1 = 0; + int tbRiskY1 = 0; + int tbRiskX2 = tbRiskX1 + (btnWidth * 2); + int tbRiskY2 = tbRiskY1 + btnHeight; + result = tbRisk.Create( + chart, + tbRiskID, + subWindow, + tbRiskX1, + tbRiskY1, + tbRiskX2, + tbRiskY2 // + ); + if (!result) + { + return result; + } + + // + result = tbRisk.Text((string)riskPercent); + result = tbRisk.TextAlign(ALIGN_CENTER); + + // + result = Add(tbRisk); + + // + // Create Draw/Remove Button ... + int btnDrawX1 = 0; + int btnDrawY1 = desiredHeight - (btnHeight * 2); + int btnDrawX2 = btnDrawX1 + (btnWidth * 2); + int btnDrawY2 = btnDrawY1 + btnHeight; + result = btnDrawRemove.Create( + chart, + btnDrawRemoveID, + subWindow, + btnDrawX1, + btnDrawY1, + btnDrawX2, + btnDrawY2 // + ); + if (!result) + { + return result; + } + + // + result = btnDrawRemove.Text(drawLabelStr); + result = btnDrawRemove.Color(btnDrawColor); + result = btnDrawRemove.ColorBackground(btnDrawBGColor); + + // + result = Add(btnDrawRemove); + + // + // Create Buy Button ... + int btnBuyX1 = 0; + int btnBuyY1 = desiredHeight - btnHeight; + int btnBuyX2 = btnBuyX1 + btnWidth; + int btnBuyY2 = btnBuyY1 + btnHeight; + result = btnBuy.Create( + chart, + btnBuyID, + subWindow, + btnBuyX1, + btnBuyY1, + btnBuyX2, + btnBuyY2 // + ); + if (!result) + { + return result; + } + + // + result = btnBuy.Text(buyLabelStr); + result = btnBuy.Color(btnBuyColor); + result = btnBuy.ColorBackground(btnBuyBGColor); + + // + result = Add(btnBuy); + + // + // Create Sell Button ... + int btnSellX1 = btnBuyX2; + int btnSellY1 = btnBuyY1; + int btnSellX2 = btnSellX1 + btnWidth; + int btnSellY2 = btnSellY1 + btnHeight; + result = btnSell.Create( + chart, + btnSellID, + subWindow, + btnSellX1, + btnSellY1, + btnSellX2, + btnSellY2 // + ); + if (!result) + { + return result; + } + + // + result = btnSell.Text(sellLabelStr); + result = btnSell.Color(btnSellColor); + result = btnSell.ColorBackground(btnSellBGColor); + + // + result = Add(btnSell); + + // + if (result) + { + // + UpdateState(); + CalculateData(); + } + + // + return result; + } + + // + protected: + // + XCTrade *mTrader; + int slippage; + long magicNumber; + + // + long chartId; + int subWindow; + + // + string slID; + color slColor; + CChartObjectHLine *slLine; + + // + string tpID; + color tpColor; + CChartObjectHLine *tpLine; + + // + string entryID; + color entryColor; + CChartObjectHLine *entryLine; + + // + double riskPercent; + double minAllowedRiskPercent; + double maxAllowedRiskPercent; + + // + double volume; + + // + double defaultR2R; + double defaultRisk; + + // + color disabledBtnColor; + color disabledBtnBGColor; + + // + // Risk Percent Edit ... + CEdit tbRisk; + string tbRiskID; + + // + // BUY Button ... + CButton btnBuy; + string btnBuyID; + string buyLabelStr; + color btnBuyColor; + color btnBuyBGColor; + + // + // SELL Button ... + CButton btnSell; + string btnSellID; + string sellLabelStr; + color btnSellColor; + color btnSellBGColor; + + // + // DRAW / REMOVE Button ... + CButton btnDrawRemove; + string btnDrawRemoveID; + string drawLabelStr; + string removeLabelStr; + color btnDrawColor; + color btnDrawBGColor; + color btnRemoveColor; + color btnRemoveBGColor; + + // + private: + // + + bool EnableBuy(bool value) + { + // + bool result = false; + + // + btnBuy.Locking(!value); + btnSell.Pressed(value); + if (!value) + { + // + // Disabled ... + btnBuy.Color(disabledBtnColor); + btnBuy.ColorBackground(disabledBtnBGColor); + } + else + { + // + // Enable ... + btnBuy.Color(btnBuyColor); + btnBuy.ColorBackground(btnBuyBGColor); + } + + // + return result; + } + + bool EnableSell(bool value) + { + // + bool result = false; + + // + btnSell.Locking(!value); + btnSell.Pressed(value); + if (!value) + { + // + // Disabled ... + btnSell.Color(disabledBtnColor); + btnSell.ColorBackground(disabledBtnBGColor); + } + else + { + // + // Enable ... + btnSell.Color(btnSellColor); + btnSell.ColorBackground(btnSellBGColor); + } + + // + return result; + } + + bool SetDrawMode() + { + // + bool result = false; + + // + result = btnDrawRemove.Text(drawLabelStr); + result = btnDrawRemove.Color(btnDrawColor); + result = btnDrawRemove.ColorBackground(btnDrawBGColor); + + // + return result; + } + + bool SetRemoveMode() + { + // + bool result = false; + + // + result = btnDrawRemove.Text(removeLabelStr); + result = btnDrawRemove.Color(btnRemoveColor); + result = btnDrawRemove.ColorBackground(btnRemoveBGColor); + + // + return result; + } + + void HandleDrawObjects() + { + // + double entry = GetBid(_Symbol); + double points = GetPoints(_Symbol); + double riskRatio = defaultRisk * points; + double rewardRatio = riskRatio * defaultR2R; + double sl = entry - riskRatio; + double tp = entry + rewardRatio; + + // + datetime rectTime1 = iTime( + _Symbol, + _Period, + 20 // + ); + datetime rectTime2 = iTime( + _Symbol, + _Period, + 19 // + ); + + // + bool has = false; + + // + // Create Entry Line ... + entryLine = new CChartObjectHLine(); + has = entryLine.Create( + chartId, + entryID, + subWindow, + entry // + ); + if (!has) + { + // + HandleRemoveObjects(); + return; + } + entryLine.Selectable(false); + entryLine.Color(entryColor); + + // + // Create SL Line ... + slLine = new CChartObjectHLine(); + has = slLine.Create( + chartId, + slID, + subWindow, + sl // + ); + if (!has) + { + // + HandleRemoveObjects(); + return; + } + slLine.Color(slColor); + slLine.Selectable(true); + + // + // Create TP Line ... + tpLine = new CChartObjectHLine(); + has = tpLine.Create( + chartId, + tpID, + subWindow, + tp // + ); + if (!has) + { + // + HandleRemoveObjects(); + return; + } + tpLine.Color(tpColor); + tpLine.Selectable(true); + + // + CalculateData(); + } + + void HandleRemoveObjects() + { + // + if (HasSL()) + { + // + slLine.Delete(); + slLine.Detach(); + ZeroMemory(slLine); + } + + // + if (HasTP()) + { + // + tpLine.Delete(); + tpLine.Detach(); + ZeroMemory(tpLine); + } + + // + if (HasEntry()) + { + // + entryLine.Delete(); + entryLine.Detach(); + ZeroMemory(entryLine); + } + + // + UpdateState(); + CalculateData(); + } + + void CalculateData() + { + // + EnableBuy(false); + EnableSell(false); + + // + ENUM_X_DIRECTION dir; + bool has = GetDirection(dir); + if (!has) + { + return; + } + + // + bool isBullish = IsBullish(dir); + bool isBearish = IsBearish(dir); + + // + if (isBullish) + { + // + EnableBuy(true); + EnableSell(false); + } + else if (isBearish) + { + // + EnableSell(true); + EnableBuy(false); + } + + // + double sl = ReadSL(); + double tp = ReadTP(); + double entry = ReadEntry(); + double points = GetPoints(_Symbol); + + // + double risk = MathAbs(entry - sl); + int riskPoints = (int)(risk / points); + double riskRewardRatio = MathAbs(tp - entry) / risk; + riskRewardRatio = NormalizeDouble(riskRewardRatio, 2); + + // + double balance = GetBalance(); + + // + double riskAmount = riskPercent * (balance / 100); + riskAmount = NormalizePrice(riskAmount, _Symbol); + + // + double rewardAmount = riskAmount * riskRewardRatio; + rewardAmount = NormalizePrice(rewardAmount, _Symbol); + + // + string currency = mTrader.mAccount.GetCurrency(); + + // + volume = mTrader + .mAccount + .CalculateVolume( + _Symbol, + riskAmount, + riskPoints // + ); + volume = NormalizeVolume(volume, _Symbol); + + // + string slDesc = "SL: " + ToString(sl) + + ", Risk: " + ToString(riskPoints) + " pt (" + ToString(riskPercent) + "%)" + + ", Amount: " + ToString(riskAmount) + currency; + slLine.Tooltip(slDesc); + slLine.Description(slDesc); + + // + string tpDesc = "TP: " + ToString(tp) + " (" + ToString(rewardAmount) + " " + currency + ")" + + ", R2R: 1:" + ToString(riskRewardRatio); + tpLine.Tooltip(tpDesc); + tpLine.Description(tpDesc); + + // + string entryDesc = "Entry: " + ToString(entry) + + ", Volume: " + ToString(volume); + entryLine.Tooltip(entryDesc); + entryLine.Description(entryDesc); + + // + } + + void SetEntry(double value) + { + // + if (value <= 0 || + !HasEntry()) + { + return; + } + + // + bool has = entryLine + .SetDouble(OBJPROP_PRICE, value); + } + + double GetBalance() + { + // + double result = 0; + + // + // TODO: Change This ... + return mTrader.mAccount.GetBalance(); + + // + return result; + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14040316/Classes/x-saherelm.x-trade.class.mq5 b/BKPS/14040316/Classes/x-saherelm.x-trade.class.mq5 new file mode 100644 index 0000000..788e38a --- /dev/null +++ b/BKPS/14040316/Classes/x-saherelm.x-trade.class.mq5 @@ -0,0 +1,3899 @@ +/////////////////////////////////////////////////////// +// +// 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 "../Classes/x-saherelm.x-account.class.mq5" +#include "../Classes/x-saherelm.x-alert.class.mq5" +#include "../Libraries/x-saherelm.x-trade.lib.mq5" + +// +// Definitions ... + +// +// Overrides ... + +// +// XCTrade Base Class ... +class XCTradeBase : 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 XCTrade : public XCBase +{ + // + // Public ... + public: + // + // Props ... + XCAccount *mAccount; // Account Info Provider + + // + // Constructors ... + void XCTrade( + int slippage, // Specify Slippage + ulong magicNumber, // Specify Magic Number + double maxAllowedSpread = 0, // Max Allowed Spred for Opening Trades + int maxAllowedPositions = 0, // Max Allowed Positions + double maxAllowedDrawdownFactor = 0 // Max Allowed Drawdown Factor + ) + { + // + // Setting Props ... + mSlippage = slippage; + mMagicNumber = magicNumber; + + // + mMaxAllowedSpread = maxAllowedSpread; + mMaxAllowedPositions = maxAllowedPositions; + mMaxAllowedDrawdownFactor = maxAllowedDrawdownFactor; + + // + mAccount = new XCAccount(); + + // + // Instance Base Trader Class ... + mTrader = new XCTradeBase(); + + // + // 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 ... + ~XCTrade() + { + // + // Remove Pointer ... + delete mTrader; + delete mAccount; + + // + ZeroMemory(mTrader); + ZeroMemory(mAccount); + + // + Clean(mOnModifyEventHandlers); + Clean(mStopLossEventHandlers); + Clean(mTakeProfitEventHandlers); + Clean(mOnForceCloseEventHandlers); + Clean(mDealsChangedEventHandlers); + Clean(mOrdersChangedEventHandlers); + Clean(mOnPartialCloseEventHandlers); + Clean(mPositionsChangedEventHandlers); + Clean(mTradeStateChangedEventHandlers); + } + + // + // Props ... + + // + // Retrieve Slippage ... + int GetSlippage() + { + return mSlippage; + } + + // + // Retrieve Magic Number ... + ulong GetMagicNumber() + { + return mMagicNumber; + } + + // + double GetMaxAllowedSpread() + { + return mMaxAllowedSpread; + } + + // + int GetMaxAllowedPositions() + { + return mMaxAllowedPositions; + } + + // + void SetMaxAllowedPositions(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mMaxAllowedPositions = value; + } + + // + double GetMaxAllowedDrawdownFactor() + { + return mMaxAllowedDrawdownFactor; + } + + // + // Add Event Listeners ... + + // + void AddOnModifyPositionEventHandler(TOnModify handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnModifyEventHandlers + // + ); + } + + // + void AddOnForceClosePositionEventHandler(TOnForceClose handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnForceCloseEventHandlers + // + ); + } + + // + void AddOnPartialClosePositionEventHandler(TOnPartialClose handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnPartialCloseEventHandlers + // + ); + } + + // + // Add New Deals Changed Event Handler ... + void AddOnTradeStateChangedEventHandler(TOnTradeStateChanged handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mTradeStateChangedEventHandlers + // + ); + } + + // + // Add New Deals Changed Event Handler ... + void AddOnDealsChangedEventHandler(TOnDealsChanged handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mDealsChangedEventHandlers + // + ); + } + + // + // Add New Orders Changed Event Handler ... + void AddOnOrdersChangedEventHandler(TOnOrdersChanged handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOrdersChangedEventHandlers + // + ); + } + + // + // Add New Positions Changed Event Handler ... + void AddOnPositionsChangedEventHandler(TOnPositionsChanged handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mPositionsChangedEventHandlers + // + ); + } + + // + // Add New Stop Loss Event Handler ... + void AddOnStopLossEventHandler(TOnStopLoss handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mStopLossEventHandlers + // + ); + } + + // + // Add New Stop Loss Event Handler ... + void AddOnTakeProfitEventHandler(TOnTakeProfit handler) + { + // + if (handler == NULL) + { + return; + } + + // + 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 = GetSpread(mSignal.symbol); + 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; + } + + // + // 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(); + if (!Contains(mSComment, mSignal.comment)) + { + 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 ... + } + } + + // + 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 ... + XPosition position; + result = + GetPosition( + ticket, + position // + ) && + (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 + // + ); + if (result) + { + // + NotifyModifyEvent( + ticket, + position.profit, + 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 ... + XPosition position; + result = GetPosition( + ticket, + position // + ); + 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 + // + ); + if (result) + { + // + NotifyForceCloseEvent( + ticket, + position, + 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_X_POSITION_TYPES 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; + + // + XPosition position; + result = GetPosition( + ticket, + position // + ); + if (!result) + { + return result; + } + + // + // Use Default Partial Close Comment ... + if (!IsValid(comment)) + { + // + comment += "PClose " + GetPositionComment(ticket); + } + + // + result = mTrader.PositionClosePartial( + ticket, + volume, + mSlippage, + comment + // + ); + if (result) + { + // + NotifyPartialCloseEvent( + ticket, + position.profit, + 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_X_POSITION_TYPES 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 + ) + { + // + bool isInited = result + .ByIndex(index); + + // + return isInited; + } + + // + // Retrieve Specific Position by Ticket ... + bool GetPosition( + ulong ticket, // Specified Ticket + XPosition &result // Hold's Result + ) + { + // + bool isInited = result + .ByTicket(ticket); + + // + return isInited; + } + + // + double GetPositionCommission( + ulong ticket // Specified Ticket + ) + { + // + double result = 0; + + // + XPosition position; + bool hasPosition = GetPosition( + ticket, + position // + ); + if (!hasPosition) + { + return result; + } + + // + XDeal deals[]; + int dealsCount = GetDeals( + deals, + position.symbol, + position.provider, + position.period, + NULL, + DEAL_ENTRY_IN // + ); + if (IsValidSize(dealsCount)) + { + // + for (int i = 0; i < dealsCount; i++) + { + // + XDeal iDeal = deals[i]; + if (iDeal.positionId == ticket) + { + // + result = iDeal.commission; + break; + } + } + } + + // + return result; + } + + // + // 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_X_POSITION_TYPES 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; + } + + // + void GetPositions( + XPosition &longs[], // Hold's Longs Result + XPosition &shorts[], // Hold's Shorts Result + string symbol = NULL, // Trading Symbol + string provider = NULL, // Signal Provider + ENUM_TIMEFRAMES period = NULL, // Trading Period + bool filterByMagic = true, // Get Only Self Open Positions + bool forceClean = true // Clean Result Array + ) + { + // + // Retrieve Long Positions ... + GetPositions( + longs, + symbol, + provider, + period, + X_POSITION_TYPE_LONG, + filterByMagic, + forceClean // + ); + + // + // Retrieve Short Positions ... + GetPositions( + shorts, + symbol, + provider, + period, + X_POSITION_TYPE_SHORT, + filterByMagic, + forceClean // + ); + } + + // + // 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_X_POSITION_TYPES 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_X_POSITION_TYPES 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_X_POSITION_TYPES 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_X_POSITION_TYPES 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); + } + + // + bool GetLastDeal( + XDeal &result // Hold's Result + ) + { + // + bool mResult = false; + + // + mResult = HistorySelect(0, TimeCurrent()); + if (!mResult) + { + return mResult; + } + + // + int lastDealIndex = HistoryDealsTotal() - 1; + + // + mResult = GetDeal( + lastDealIndex, + result // + ); + + // + return mResult; + } + + // + // 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; + } + + // + // Support Functions ... + + // + // Check a Position has Support or not ... + bool HasSupport( + ulong ticket, + bool forceOpen = true // + ) + { + // + bool result = false; + + // + result = ticket > 0; + if (!result) + { + return result; + } + + // + if (forceOpen) + { + // + result = IsOpen(ticket); + if (!result) + { + return result; + } + } + + // + XPosition positions[]; + int positionsCount = GetPositions(positions); + result = IsValidSize(positionsCount); + if (!result) + { + return result; + } + + // + // Extract Support Positions ... + XPosition supports[]; + int supportsCount = ExtractSupports( + positions, + supports // + ); + result = IsValidSize(supportsCount); + if (!result) + { + return result; + } + + // + // Loop Through Supports ... + for (int i = 0; i < supportsCount; i++) + { + // + XPosition iSupport = supports[i]; + + // + ulong supportedTicket = ExtractSupportedTicket(iSupport.comment); + ulong eqmSupportedTicket = ExtractEQMSupportedTicket(iSupport.comment); + + // + result = + // + (supportedTicket > 0 && ticket == supportedTicket) + // + || + // + (eqmSupportedTicket > 0 && ticket == eqmSupportedTicket) + // + ; + if (result) + { + break; + } + } + + // + return result; + } + + // + // Retrieve Specific Position's Supports ... + int GetSupports( + ulong ticket, + XPosition &dest[], // Result ... + bool forceOpen = true // + ) + { + // + int result = 0; + + // + Clean(dest); + + // + bool hasSupport = HasSupport( + ticket, + forceOpen // + ); + if (!hasSupport) + { + return result; + } + + // + XPosition positions[]; + int positionsCount = GetPositions(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + // Extract Support Positions ... + XPosition supports[]; + int supportsCount = ExtractSupports( + positions, + supports // + ); + if (!IsValidSize(supportsCount)) + { + return result; + } + + // + // Loop Through Supports ... + for (int i = 0; i < supportsCount; i++) + { + // + XPosition iSupport = supports[i]; + + // + ulong supportedTicket = ExtractSupportedTicket(iSupport.comment); + ulong eqmSupportedTicket = ExtractEQMSupportedTicket(iSupport.comment); + + // + bool isOwn = + // + (supportedTicket > 0 && ticket == supportedTicket) + // + || + // + (eqmSupportedTicket > 0 && ticket == eqmSupportedTicket) + // + ; + if (isOwn) + { + // + AddRef( + iSupport, + dest // + ); + } + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // Retrieve Specific Position's Supports ... + int GetSupports( + ulong ticket, + XOrder &dest[], // Result ... + bool forceOpen = true // + ) + { + // + int result = 0; + + // + Clean(dest); + + // + bool hasSupport = HasSupport( + ticket, + forceOpen // + ); + if (!hasSupport) + { + return result; + } + + // + XOrder orders[]; + int ordersCount = GetOrders( + orders, + NULL, // All Symbols ... + NULL, // All Providers ... + NULL, // All Periods ... + X_POSITION_TYPE_ALL, // All Types ... + ORDER_STATE_PLACED, // Untriggere Orders ... + true // + ); + if (!IsValidSize(ordersCount)) + { + return result; + } + + // + // Extract Support Positions ... + XOrder supports[]; + int supportsCount = ExtractSupports( + orders, + supports // + ); + if (!IsValidSize(supportsCount)) + { + return result; + } + + // + // Loop Through Supports ... + for (int i = 0; i < supportsCount; i++) + { + // + XOrder iSupport = supports[i]; + + // + ulong supportedTicket = ExtractSupportedTicket(iSupport.comment); + ulong eqmSupportedTicket = ExtractEQMSupportedTicket(iSupport.comment); + + // + bool isOwn = + // + (supportedTicket > 0 && ticket == supportedTicket) + // + || + // + (eqmSupportedTicket > 0 && ticket == eqmSupportedTicket) + // + ; + if (isOwn) + { + // + AddRef( + iSupport, + dest // + ); + } + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // Tools ... + + // + // 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; + } + + // + // Prepare Dynamic Volume ... + double GetDynamicVolume( + string _symbol, + double _balanceFactor, + double _volumeStep // + ) + { + // + double result = 0; + + // + // Validate Inputs ... + if (!IsValid(_symbol) || + _volumeStep <= 0 || + _balanceFactor <= 0) + { + return result; + } + + // + // Retrieve Account Balance ... + double balance = mAccount.GetBalance(); + + // + double bStep = balance / _balanceFactor; + bStep = MathFloor(bStep); + if (bStep == 0) + { + bStep = 1; + } + + // + result = bStep * _volumeStep; + + // + result = NormalizeVolume( + result, + _symbol // + ); + + // + 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); + } + } + + // + void NotifyModifyEvent( + ulong ticket, + double profit, + string comment // + ) + { + // + int count = ArraySize(mOnModifyEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + TOnModify iHandler = mOnModifyEventHandlers[i]; + iHandler( + ticket, + profit, + comment // + ); + } + } + + // + void NotifyForceCloseEvent( + ulong ticket, + XPosition &position, + string comment // + ) + { + // + int count = ArraySize(mOnForceCloseEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + TOnForceClose iHandler = mOnForceCloseEventHandlers[i]; + iHandler( + ticket, + position, + comment // + ); + } + } + + // + void NotifyPartialCloseEvent( + ulong ticket, + double profit, + string comment // + ) + { + // + int count = ArraySize(mOnPartialCloseEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + TOnModify iHandler = mOnPartialCloseEventHandlers[i]; + iHandler( + ticket, + profit, + comment // + ); + } + } + + // + // 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; + } + + // + 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) ... + + // + double mMaxAllowedSpread; // Max Allowed Spred for Opening Trades + int mMaxAllowedPositions; // Max Allowed Same Positions + double mMaxAllowedDrawdownFactor; // Max Allowed Drawdown Factor + + // + XCTradeBase *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[]; + + // + TOnModify mOnModifyEventHandlers[]; + TOnForceClose mOnForceCloseEventHandlers[]; + TOnPartialClose mOnPartialCloseEventHandlers[]; + + // + // 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/BKPS/14040316/Classes/x-saherelm.x-volume.class.mq5 b/BKPS/14040316/Classes/x-saherelm.x-volume.class.mq5 new file mode 100644 index 0000000..09720c3 --- /dev/null +++ b/BKPS/14040316/Classes/x-saherelm.x-volume.class.mq5 @@ -0,0 +1,792 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XCVolume +// Description: provides all Requirements for Volume Managing ... +// +// +// 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 + +// +// Template Variables of Inputs for Using ... +// input group "Volume"; +// input ENUM_X_VOLUME_SELECT_TYPE eaVolumeSelect = X_VOLUME_STATIC; // Volume Applying Type +// input double eaStaticVoluem = X_MIN_VOLUME; // Static Volume +// input double eaDynamicVolumeStepBalance = 0.0; // Step of Balance for Increase Volume +// input double eaDynamicVolumeStepVolume = X_MIN_VOLUME; // Step of Volume Increasing +// input double eaConstantRiskBalance = 0.0; // Constant Risk Balance per Trade +// input double eaConstantPercent = 0.0; // Constant Percent of Balance Per Trade +// input double eaConstantBalance = 0.0; // Constant Balance for Calculations +// XCVolume *eaVolume; +// eaVolume = new XCVolume(); +// bool result = eaVolume.Init( +// eaVolumeSelect, +// eaStaticVoluem, +// eaDynamicVolumeStepBalance, +// eaDynamicVolumeStepVolume, +// eaConstantRiskBalance, +// eaConstantPercent, +// eaConstantBalance // +// ); +// if (!result) { +// return INIT_FAILED; +// } + +// +// Imports ... +#include "../Classes/x-saherelm.x-account.class.mq5" +#include "../Libraries/x-saherelm.x-trade.lib.mq5" + +// +// Definitions ... +#define X_MIN_VOLUME 0.01 + +// +enum ENUM_X_VOLUME_SELECT_TYPE +{ + X_VOLUME_NONE, // None + X_VOLUME_STATIC, // Static Volume + X_VOLUME_CURRENT, // Current Balance + X_VOLUME_EQUITY, // Current Equity + X_VOLUME_CONSTANT // Constant Value +}; + +// +bool IsValid(ENUM_X_VOLUME_SELECT_TYPE value) +{ + // + bool result = false; + + // + result = value != X_VOLUME_NONE; + + // + return result; +} + +// +string ToString(ENUM_X_VOLUME_SELECT_TYPE value) +{ + // + string result = NULL; + + // + result = EnumToString(value); + + // + return result; +} + +// +// Implementation ... +class XCVolume : public XCBase +{ + // + // Public ... + public: + // + // Props ... + XCAccount *account; + + // + // Constructor ... + XCVolume() + { + // + account = new XCAccount(); + + // + Default(); + } + + // + // Deconstructor ... + ~XCVolume() + { + // + ZeroMemory(account); + } + + // + bool Init( + ENUM_X_VOLUME_SELECT_TYPE _SelectType, + double _StaticVolume, + double _DynamicVolumeStepBalance, + double _DynamicVolumeStepVolume, + double _ConstantRiskBalance, + double _ConstantPercent, + double _ConstantBalance // + ) + { + // + bool result = false; + + // + mVolumeType = _SelectType; + mStaticVolume = _StaticVolume; + mConstantPercent = _ConstantPercent; + mConstantBalance = _ConstantBalance; + mConstantRiskBalance = _ConstantRiskBalance; + mDynamicVolumeStepVolume = _DynamicVolumeStepVolume; + mDynamicVolumeStepBalance = _DynamicVolumeStepBalance; + + // + result = + // + CanUseStaticVolume() || + CanUseDynamicVolume() || + CanUseConstantRiskBalance() || + CanUseConstantBalancePercent() + // + ; + + // + return result; + } + + // + // Prperties ... + + /** + * Get Volume Calculating Method ... + * + * @return (ENUM_X_VOLUME_SELECT_TYPE) + */ + ENUM_X_VOLUME_SELECT_TYPE VolumeType() + { + return mVolumeType; + } + + /** + * Set Volume Calculating Method ... + * + * @param value: ENUM_X_VOLUME_SELECT_TYPE member ... + */ + void VolumeType(ENUM_X_VOLUME_SELECT_TYPE value) + { + mVolumeType = value; + } + + /** + * Get Static Volume ... + * + * @return ( double ) + */ + double StaticVolume() + { + return mStaticVolume; + } + + /** + * Set Static Volume ... + * + * @param value: double + */ + void StaticVolume(double value) + { + // + value = NormalizeDouble(value, 0.01, 1); + + // + mStaticVolume = value; + } + + /** + * Get Dynamic Volume Step Balance ... + * used to Calculate Final Lottage ... + * + * @return ( double ) + */ + double DynamicVolumeStepBalance() + { + return mDynamicVolumeStepBalance; + } + + /** + * Set Dynamic Volume Step Balance ... + * used to Calculate Final Lottage ... + * + * @param value: Argument 1 + */ + void DynamicVolumeStepBalance(double value) + { + // + value = NormalizeDouble(value, 0); + + // + mDynamicVolumeStepBalance = value; + } + + /** + * Get Dynamic Volume Step Volume ... + * used to Calculate Final Lottage ... + * how much increase Final Volume based oBalance Step ... + * + * @return ( double ) + */ + double DynamicVolumeStepVolume() + { + return mDynamicVolumeStepVolume; + } + + /** + * Get Dynamic Volume Step Volume ... + * used to Calculate Final Lottage ... + * how much increase Final Volume based oBalance Step ... + * + * @param value: double + */ + void DynamicVolumeStepVolume(double value) + { + // + value = NormalizeDouble(value, 0.01, 0.1); + + // + mDynamicVolumeStepVolume = value; + } + + /** + * Get Constant Balance Use for Dyamic Volume Calculation ... + * + * @return ( double ) + */ + double ConstantBalance() + { + return mConstantBalance; + } + + /** + * Set Constant Balance Use for Dyamic Volume Calculation ... + * + * @param value: Argument 1 + */ + void ConstantBalance(double value) + { + // + value = NormalizeDouble(value, 0); + + // + mConstantBalance = value; + } + + /** + * Get Constant Risk Value Based on Account Currency ... + * + * @return ( double ) + */ + double ConstantRiskBalance() + { + return mConstantRiskBalance; + } + + /** + * Get Constant Risk Value Based on Account Currency ... + * + * @param value: double + */ + void ConstantRiskBalance(double value) + { + // + value = NormalizeDouble(value, 0); + + // + mConstantRiskBalance = value; + } + + /** + * Get Constant Percent Based On Selected Balance ... + * + * @return ( double ) + */ + double ConstantPercent() + { + return mConstantPercent; + } + + /** + * Set Constant Percent Based On Selected Balance ... + * + * @param value: double ... + */ + void ConstantPercent(double value) + { + // + value = NormalizeDouble(value, 0, 100); + + // + mConstantPercent = value; + } + + // + // Tools ... + + /** + * Retrieve Balance based on Provided Volume Type ... + * + * @return ( double ) + */ + double GetBalance() + { + // + double result = 0; + + // + if (!IsValid(mVolumeType)) + { + return result; + } + + // + if (mConstantBalance > 0 && + mVolumeType == X_VOLUME_CONSTANT) + { + result = mConstantBalance; + } + else if (mVolumeType == X_VOLUME_CURRENT) + { + result = account.GetBalance(); + } + else if (mVolumeType == X_VOLUME_EQUITY) + { + result = account.GetEquity(); + } + + // + return result; + } + + /** + * Retrieve Balance based on Provided Volume Type ... + * + * @return ( double ) + */ + double GetBalance(ENUM_X_VOLUME_SELECT_TYPE type) + { + // + double result = 0; + + // + if (!IsValid(type)) + { + return result; + } + + // + if (mConstantBalance > 0 && + type == X_VOLUME_CONSTANT) + { + result = mConstantBalance; + } + else if (type == X_VOLUME_CURRENT) + { + result = account.GetBalance(); + } + else if (type == X_VOLUME_EQUITY) + { + result = account.GetEquity(); + } + + // + return result; + } + + /** + * Calculate Volume Based On Given Configuration ... + * + * @param symbol: string, Trading Symbol ... + * @param entry: double, Entry Price ... + * @param sl: double, Stop Loss Price ... + * + * @return ( double ) + */ + double CalculateVolume( + string symbol, + double entry, + double sl // + ) + { + // + double result = X_MIN_VOLUME; + + // + bool has = false; + + // + // Validate Args ... + has = + sl > 0 && + entry > 0 && + IsValid(symbol); + if (!has) + { + return result; + } + + // + // Retrieve Balance Type ... + double balance = GetBalance(); + double points = GetPoints(symbol); + double riskPrice = MathAbs(entry - sl); + double riskInPoints = riskPrice / points; + + // + has = CanUseStaticVolume(); + if (has) + { + result = mStaticVolume; + } + + // + has = CanUseDynamicVolume(); + if (has) + { + // + double multiplier = balance / mDynamicVolumeStepBalance; + if (multiplier < 0) + { + multiplier = 1; + } + + // + result = multiplier * mDynamicVolumeStepVolume; + } + + // + has = CanUseConstantRiskBalance(); + if (has) + { + // + result = account.CalculateVolume( + symbol, + mConstantRiskBalance, + riskInPoints // + ); + } + + // + has = CanUseConstantBalancePercent(); + if (has) + { + // + double riskAmountPerBalance = (mConstantPercent * balance) / 100; + + // + result = account.CalculateVolume( + symbol, + riskAmountPerBalance, + riskInPoints // + ); + } + + // + if (result < X_MIN_VOLUME) + { + result = X_MIN_VOLUME; + } + + // + // Normalize Volume ... + result = NormalizeVolume(result, symbol); + + // + return result; + } + + /** + * Calculate Volume Based On Given Configuration ... + * + * @param signal: XSignal instance reference, provided required Data ... + * + * @return ( double ) + */ + double CalculateVolume(XSignal &signal) + { + // + double result = X_MIN_VOLUME; + + // + if (!signal.IsValid()) + { + return result; + } + + // + result = CalculateVolume( + signal.symbol, + signal.entry, + signal.sl // + ); + + // + return result; + } + + /** + * Calculate Specified Percent of Selected Balance for Volume ... + * + * @param percent: double, percent of Balance Risking ... + * @param symbol: string, Trading Symbol ... + * @param entry: double, Entry Price ... + * @param sl: double Stop Loss Price ... + * + * @return ( double ) + */ + double CalculateVolume( + ENUM_X_VOLUME_SELECT_TYPE selectType, + double percent, + string symbol, + double entry, + double sl // + ) + { + // + double result = X_MIN_VOLUME; + + // + bool has = false; + + // + // Validate Args ... + has = + sl > 0 && + entry > 0 && + percent > 0 && + IsValid(symbol) && + IsValid(selectType) && + (selectType == X_VOLUME_EQUITY || + selectType == X_VOLUME_CURRENT); + if (!has) + { + return result; + } + + // + // Retrieve Balance Type ... + double points = GetPoints(symbol); + double riskPrice = MathAbs(entry - sl); + double balance = GetBalance(selectType); + double riskInPoints = riskPrice / points; + + // + double riskAmountPerBalance = (percent * balance) / 100; + + // + result = account.CalculateVolume( + symbol, + riskAmountPerBalance, + riskInPoints // + ); + + // + return result; + } + + // + // Protected ... + protected: + // + // Tools ... + + /** + * Set Default Props ... + */ + void Default() + { + // + VolumeType(X_VOLUME_STATIC); + StaticVolume(0.01); + + // + ConstantBalance(0); + ConstantPercent(0); + ConstantRiskBalance(0); + + // + DynamicVolumeStepBalance(0); + DynamicVolumeStepVolume(0.01); + } + + /** + * Check Configuration is Valid For Static Volume ... + * + * @return ( bool ) + */ + bool CanUseStaticVolume() + { + // + bool result = false; + + // + result = IsValid(mVolumeType); + if (!result) + { + return result; + } + + // + // Static Volume ... + result = + // + mVolumeType == X_VOLUME_STATIC && + mStaticVolume > 0 && + // + mDynamicVolumeStepBalance == 0 && + // + mConstantBalance == 0 && + mConstantPercent == 0 && + mConstantRiskBalance == 0 + // + ; + + // + return result; + } + + /** + * Check Configuration is Valid For Dynamic Volume ... + * + * @return ( bool ) + */ + bool CanUseDynamicVolume() + { + // + bool result = false; + + // + result = IsValid(mVolumeType); + if (!result) + { + return result; + } + + // + result = + // + (mVolumeType == X_VOLUME_CURRENT || + mVolumeType == X_VOLUME_EQUITY || + (mVolumeType == X_VOLUME_CONSTANT && + mConstantBalance > 0)) && + // + mDynamicVolumeStepBalance > 0 && + mDynamicVolumeStepVolume > 0 && + // + mStaticVolume == 0 && + mConstantPercent == 0 && + mConstantRiskBalance == 0 + // + ; + + // + return result; + } + + /** + * Check Configuration is Valid For Constant Risk Balance ... + * + * @return ( bool ) + */ + bool CanUseConstantRiskBalance() + { + // + bool result = false; + + // + result = IsValid(mVolumeType); + if (!result) + { + return result; + } + + // + result = + // + (mVolumeType == X_VOLUME_CURRENT || + mVolumeType == X_VOLUME_EQUITY || + (mVolumeType == X_VOLUME_CONSTANT && + mConstantBalance > 0)) && + // + mConstantRiskBalance > 0 && + // + mStaticVolume == 0 && + mConstantPercent == 0 && + mDynamicVolumeStepBalance == 0 + // + ; + + // + return result; + } + + /** + * Check Configuration is Valid For Constant Risk Percent ... + * + * @return ( bool ) + */ + bool CanUseConstantBalancePercent() + { + // + bool result = false; + + // + result = IsValid(mVolumeType); + if (!result) + { + return result; + } + + // + result = + // + (mVolumeType == X_VOLUME_CURRENT || + mVolumeType == X_VOLUME_EQUITY || + (mVolumeType == X_VOLUME_CONSTANT && + mConstantBalance > 0)) && + // + mConstantPercent > 0 && + // + mStaticVolume == 0 && + mConstantRiskBalance == 0 && + mDynamicVolumeStepBalance == 0 + // + ; + + // + return result; + } + + // + // Private ... + private: + // + // Props ... + + // + ENUM_X_VOLUME_SELECT_TYPE mVolumeType; // Balance Type ... + + // + // Static Volume ... + double mStaticVolume; // Static Volume ... + + // + double mDynamicVolumeStepBalance; // Step of Balance ... + double mDynamicVolumeStepVolume; // Step of Volume ... + + // + double mConstantBalance; // Constant Balance .... + double mConstantRiskBalance; // Constant Risk Balance ... + double mConstantPercent; // Constant Percent of Balance ... +}; + +// \ No newline at end of file diff --git a/BKPS/14040316/Documents/BKP/tmp.base.signal.class.mq5 b/BKPS/14040316/Documents/BKP/tmp.base.signal.class.mq5 new file mode 100644 index 0000000..7ddfc92 --- /dev/null +++ b/BKPS/14040316/Documents/BKP/tmp.base.signal.class.mq5 @@ -0,0 +1,214 @@ + +// +// a Base Class by Support Alert ... +class XCBaseAlert : public XCBase +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructor(s) ... + void XCBaseAlert() + { + // + // Instance Alert ... + mAlert = new XCAlert(); + } + + // + // Deconstructors ... + void ~XCBaseAlert() + { + // + delete mAlert; + + // + ZeroMemory(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 SendAlert(string message) + { + mAlert.SendAlert(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 ... + XCAlert *mAlert; + + // + // Private ... + private: +}; diff --git a/BKPS/14040316/Documents/BKP/tmp.conditionalling.signalling.mq5 b/BKPS/14040316/Documents/BKP/tmp.conditionalling.signalling.mq5 new file mode 100644 index 0000000..41babe8 --- /dev/null +++ b/BKPS/14040316/Documents/BKP/tmp.conditionalling.signalling.mq5 @@ -0,0 +1,1433 @@ + XBoxZone iPeak; + XBoxZone iVale; + XBoxZone iOBBull; + XBoxZone iOBBear; + XBoxZone iMTBull; + XBoxZone iMTBear; + + // + iPeak.Clean(); + iVale.Clean(); + iOBBull.Clean(); + iOBBear.Clean(); + iMTBull.Clean(); + iMTBear.Clean(); + + // + // Select MT Block ... + // if (result) + // { + // // + // // New MT Pivot Detected ... + // if (detector.newMTBullishPivotDetected) + // { + // // + // idx = GetYoungest(detector.mtBullishPivots); + // if (IsValidIndex(idx)) + // { + // iMTBull = detector.mtBullishPivots[idx]; + // } + // } + // else if (detector.newMTBearishPivotDetected) + // { + // // + // idx = GetYoungest(detector.mtBearishPivots); + // if (IsValidIndex(idx)) + // { + // iMTBear = detector.mtBearishPivots[idx]; + // } + // } + + // // + // // Draw MT ... + + // // + // // Bullish ... + // has = iMTBull.IsValid(); + // if (has) + // { + // // + // iMTBull.to = conditions.bars[zIDX].time; + + // // + // XCBoxObject *iObj; + // has = drawer + // .drawer + // .DrawBox( + // iMTBull, + // iObj // + // ); + // if (has) + // { + // drawer.ApplyMTBullishPivotStyle(iObj); + // } + // } + + // // + // // Bearish ... + // has = iMTBear.IsValid(); + // if (has) + // { + // // + // iMTBear.to = conditions.bars[zIDX].time; + + // // + // XCBoxObject *iObj; + // has = drawer + // .drawer + // .DrawBox( + // iMTBear, + // iObj // + // ); + // if (has) + // { + // drawer.ApplyMTBearishPivotStyle(iObj); + // } + // } + // } + + // + // Select Peak and Vale ... + // this used to Signalling Better ... + // if (result) + // { + // // + // // Select Peak ... + // idx = GetLowest( + // conditions.bars[cIDX], + // detector.peakPivots // + // ); + // if (IsValidIndex(idx)) + // { + // // + // iPeak = detector.peakPivots[idx]; + // iPeak.to = conditions.bars[zIDX].time; + // } + + // // + // // Select Vale ... + // idx = GetHighest( + // conditions.bars[cIDX], + // detector.valePivots // + // ); + // if (IsValidIndex(idx)) + // { + // // + // iVale = detector.valePivots[idx]; + // iVale.to = conditions.bars[zIDX].time; + // } + + // // + // // Checkig Result ... + // result = + // iPeak.IsValid() && + // iVale.IsValid(); + + // // + // // Draw Peak and Vales ... + // if (result) + // { + // // + // // Object Definitions ... + // XCBoxObject *iObj; + + // // + // // Draw Peak ... + // has = drawer + // .drawer + // .DrawBox( + // iPeak, + // iObj // + // ); + // if (has) + // { + // drawer.ApplyPeakPivotStyle(iObj); + // } + // ZeroMemory(iObj); + + // // + // // Draw Vale ... + // has = drawer + // .drawer + // .DrawBox( + // iVale, + // iObj // + // ); + // if (has) + // { + // drawer.ApplyValePivotStyle(iObj); + // } + // ZeroMemory(iObj); + // } + // } + + + // // + // // We Have to Detect Youngest Order Block ... + // // or Mitigation Block ... + // if (isCond1Bullish) + // { + // // // + // // // OB ... + // // idx = GetYoungest(detector.obBullishPivots); + // // has = IsValidIndex(idx); + // // if (has) + // // { + // // iOB = detector.obBullishPivots[idx]; + // // } + + // // + // // MT ... + // idx = GetYoungest(detector.mtBullishPivots); + // has = IsValidIndex(idx); + // if (has) + // { + // iOB = detector.mtBullishPivots[idx]; + // } + // } + // else if (isCond1Bearish) + // { + // // + // // OB + // // idx = GetYoungest(detector.obBearishPivots); + // // has = IsValidIndex(idx); + // // if (has) + // // { + // // iOB = detector.obBearishPivots[idx]; + // // } + + // // + // // MT + // idx = GetYoungest(detector.mtBearishPivots); + // has = IsValidIndex(idx); + // if (has) + // { + // iMT = detector.mtBearishPivots[idx]; + // } + // } + + // // + // // Now we can Do some Verifications Using these ... + // result = + // isCond1Bullish + // ? iMT.IsBullish() + // : iMT.IsBearish(); + // if (!result) + // { + // // + // isCond1Bullish = false; + // isCond1Bearish = false; + // } + + // + // All Requirements based on Cond 1 ... + +/////////////////////////////////////////////////////////////// + + // + XOHCL pBar; + has = bar.GetPreviousBar(pBar); + if (has) + { + // + ENUM_X_DIRECTION seqDir; + + // + bool isSeqBreaked = barAnalyser + .IsSeqBreak( + pBar, + seqDir // + ); + bool isBullishSeqBreaked = + isSeqBreaked && + IsBullish(seqDir); + bool isBearishSeqBreaked = + isSeqBreaked && + IsBearish(seqDir); + + // + if (isSeqBreaked) + { + Print("Detect Sequence Breaker Bar ..."); + } + } + pBar.Clean(); + +/////////////////////////////////////////////////////////////// + + + /** + * Detect Spike ... + * + * @param bar: XOHCL instance reference, Start Bar ... + * @param dir: ENUM_X_DIRECTION member, Event Direction ... + * @param type: ENUM_X_PRICE member, Price Type ... + * @param forcBodyInRange: bool, Use Body in Range Detection ... + * @param rangeExtendMultiplier: double, a Multiplier for Checking Price Range ... + * @param sameBars: int, Specified How Many Same Bars Required for an Spike ... + * + * @return ( bool ) + */ + bool IsSpike( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + int &rootIDX, + ENUM_X_PRICE type = X_PRICE_CLOSE, + bool forcBodyInRange = true, + double rangeExtendMultiplier = 2.0, + int sameBars = 3 // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + sameBars = NormalizeInt(sameBars, 2); + + // + result = IsValid(type) && + bar.IsValid(); + if (!result) + { + return result; + } + + // + // First We Have to Has a Big Change ... + int sharpRootIDX = -1; + result = IsSharp( + bar, + dir, + sharpRootIDX, + type, + forcBodyInRange, + rangeExtendMultiplier // + ); + if (!result) + { + return result; + } + + // + // Check Has Same Bars ... + int sameBarsIndex = -1; + ENUM_X_DIRECTION sameBarsDir; + result = HasSameBars( + bar, + sameBarsDir, + sameBarsIndex, + sameBars // + ); + if (!result) + { + return result; + } + + // + // Check Same Bars Direction sames To Price Change ... + result = sameBarsDir == dir; + if (!result) + { + return result; + } + + // + rootIDX = sharpRootIDX; + + // + return result; + } + + /** + * Check a Bar is Support Bar or not ... + * + * @param bar: XOHCL instance ... + * @param supportBar: XOHCL instance, Provides Fouded Support Bar ... + * @param range: Integer, Specified Verifiation Range ... + * + * @return ( bool ) + */ + bool HasSupport( + XOHCL &bar, + XOHCL &supportBar, + int range = 21 // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int supportIDX = bar.Index() + range; + result = supportBar.Init( + bar.symbol, + bar.period, + supportIDX // + ); + if (!result) + { + // + supportBar.Clean(); + return result; + } + + // + result = bar.low > supportBar.low; + if (!result) + { + // + supportBar.Clean(); + return result; + } + + // + // Validate Point ... + for (int i = 1; i < range; i++) + { + // + XOHCL iPBar; + XOHCL iNBar; + bool iHas = false; + + // + iHas = iPBar.Init( + bar.symbol, + bar.period, + supportIDX + i // + ); + result = iHas; + if (!result) + { + break; + } + + // + iHas = iNBar.Init( + bar.symbol, + bar.period, + supportIDX - i // + ); + result = iHas; + if (!result) + { + break; + } + + // + result = supportBar.low < iPBar.low && + supportBar.low < iNBar.low; + if (!result) + { + break; + } + } + + // + return result; + } + + /** + * Check a Bar is Resistance Bar or not ... + * + * @param bar: XOHCL instance ... + * @param resistanceBar: XOHCL instance, Provides Fouded Support Bar ... + * @param range: Integer, Specified Verifiation Range ... + * + * @return ( bool ) + */ + bool HasResistance( + XOHCL &bar, + XOHCL &resistanceBar, + int range = 21 // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int resistanceIDX = bar.Index() + range; + result = resistanceBar.Init( + bar.symbol, + bar.period, + resistanceIDX // + ); + if (!result) + { + // + resistanceBar.Clean(); + return result; + } + + // + result = bar.high < resistanceBar.high; + if (!result) + { + // + resistanceBar.Clean(); + return result; + } + + // + // Validate Point ... + for (int i = 1; i < range; i++) + { + // + XOHCL iPBar; + XOHCL iNBar; + bool iHas = false; + + // + iHas = iPBar.Init( + bar.symbol, + bar.period, + resistanceIDX + i // + ); + result = iHas; + if (!result) + { + break; + } + + // + iHas = iNBar.Init( + bar.symbol, + bar.period, + resistanceIDX - i // + ); + result = iHas; + if (!result) + { + break; + } + + // + result = resistanceBar.high > iPBar.high && + resistanceBar.high > iNBar.high; + if (!result) + { + break; + } + } + + // + return result; + } + + /** + * Detect a Fair Value Gap Based on Given Bar ... + * + * @param bar: XOHCL instance, Specified Start Bar ... + * @param fromBar: XOHCL instance, Provides Start Bar of FVG ... + * @param toBar: XOHCL instance, Provides End Bar of FVG ... + * @param dir: ENUM_X_DIRECTION member, Specified Founded Order Block Direction ... + * @param sameBars: Integer, Specified Min Same Bars for Detecting Order Block ... + * @return ( bool ) + */ + bool HasFairValueGap( + XOHCL &bar, + XOHCL &fromBar, + XOHCL &toBar, + ENUM_X_DIRECTION &dir, + int sameBars = 3 // + ) + { + // + bool result = false; + + // + toBar.Clean(); + fromBar.Clean(); + dir = X_DIRECTION_NONE; + sameBars = NormalizeInt(sameBars, 1); + + // + result = bar.IsValid(); + if (!result) + { + // + toBar.Clean(); + fromBar.Clean(); + return result; + } + + // + int index = 0; + result = HasSameBars( + bar, + dir, + index, + sameBars // + ); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(dir); + + // + int to = bar.Index(); + int from = + index > (to + sameBars) + ? to + sameBars + : index; + for (int i = from; i > to; i--) + { + // + result = fromBar.Init( + bar.symbol, + bar.period, + i // + ); + if (!result) + { + break; + } + + // + result = toBar.Init( + bar.symbol, + bar.period, + i - 2 // + ); + if (!result) + { + break; + } + + // + result = isBullish + ? fromBar.high < toBar.low + : fromBar.low > toBar.high; + if (result) + { + break; + } + } + + // + if (!result) + { + // + toBar.Clean(); + fromBar.Clean(); + dir = X_DIRECTION_NONE; + } + + // + return result; + } + + /** + * Detect an Order Block Based on Given Bar ... + * + * @param bar: XOHCL instance, Specified Start Bar ... + * @param ob: XOHCL instance, Fill it if Order Block Found ... + * @param dir: ENUM_X_DIRECTION member, Specified Founded Order Block Direction ... + * @param sameBars: Integer, Specified Min Same Bars for Detecting Order Block ... + * + * @return ( bool ) + */ + bool HasOrderBlock( + XOHCL &bar, + XOHCL &ob, + ENUM_X_DIRECTION &dir, + int sameBars = 3, + bool forceSpike = true, + bool forceFairValueGap = true, + bool forceSupportResistance = true // + ) + { + // + bool result = false; + + // + ob.Clean(); + dir = X_DIRECTION_NONE; + sameBars = NormalizeInt(sameBars, 1); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL sBar; + if (bar.Index() == 0) + { + // + result = bar.GetPreviousBar(sBar); + if (!result) + { + // + sBar.Clean(); + return result; + } + } + else + { + sBar = bar; + } + + // + // First Step We Have to Check Same Bars ... + int spikeRootIDX = -1; + int sameBarsIndex = -1; + result = HasSameBars( + bar, + dir, + sameBarsIndex, + sameBars // + ); + if (!result) + { + // + ob.Clean(); + return result; + } + + // + // Must an Spike Happens ... + if (forceSpike) + { + // + ENUM_X_DIRECTION spikeDir; + result = IsSpike( + bar, + spikeDir, + spikeRootIDX, // Spike Root Index ... + X_PRICE_CLOSE, // Price Type ... + true, // Force Body ... + 1.5, // Range Extend Multiplier ... + sameBars // + ); + result = + result && + dir == spikeDir; + if (!result) + { + // + ob.Clean(); + return result; + } + } + + // + // Select OB Candidate Bars ... + + XOHCL sameBar; + XOHCL rootBar; + XOHCL rootPBar; + result = sameBar.Init( + bar.symbol, + bar.period, + sameBarsIndex + 1 // + ); + if (!result) + { + // + sBar.Clean(); + sameBar.Clean(); + return result; + } + result = rootBar.Init( + bar.symbol, + bar.period, + spikeRootIDX // + ); + if (!result) + { + // + sBar.Clean(); + rootBar.Clean(); + sameBar.Clean(); + return result; + } + result = rootBar.GetPreviousBar(rootPBar); + if (!result) + { + // + sBar.Clean(); + rootBar.Clean(); + sameBar.Clean(); + rootPBar.Clean(); + return result; + } + + // + // Select ob Bar ... + if (rootBar.GetDirection() == Opposit(dir)) + { + ob = rootBar; + } + else if (rootPBar.GetDirection() == Opposit(dir)) + { + ob = rootPBar; + } + else if (sameBar.GetDirection() == Opposit(dir)) + { + ob = sameBar; + } + else + { + ob.Clean(); + } + + // + // Select Order Block Bar ... + result = ob.IsValid(); + ENUM_X_DIRECTION obDir = ob.GetDirection(); + result = + result && + dir == Opposit(obDir); + if (!result) + { + // + sBar.Clean(); + rootBar.Clean(); + sameBar.Clean(); + rootPBar.Clean(); + + // + return result; + } + + // + // if Bullish OB => Supports ... + // if Bearish OB => Resistance ... + if (forceSupportResistance) + { + // + XOHCL supResBar; + + // + // Check Support ... + bool isSupport = HasSupport( + ob, + supResBar // + ); + + // + // Check Resistance ... + bool isResistance = HasResistance( + ob, + supResBar // + ); + + // + supResBar.Clean(); + + // + result = + result && + (IsBullish(dir) + ? isSupport + : isResistance); + + // + if (!result) + { + // + ob.Clean(); + sBar.Clean(); + rootBar.Clean(); + sameBar.Clean(); + rootPBar.Clean(); + + // + return result; + } + } + + // + // Force Check Fair ValueGaps ... + if (forceFairValueGap) + { + // + XOHCL toBar; + XOHCL fromBar; + ENUM_X_DIRECTION fvgDir; + bool isFVG = HasFairValueGap( + bar, + fromBar, + toBar, + fvgDir, + sameBars // + ); + + // + result = + isFVG && + result && + dir == fvgDir; + + // + toBar.Clean(); + fromBar.Clean(); + } + + // + // Cleanup Resource ... + + // + sBar.Clean(); + rootBar.Clean(); + sameBar.Clean(); + rootPBar.Clean(); + + // + return result; + } + + /** + * Check a Bar has Consolidation Zone or not ... + * + * @param bar: XOHCL instance, Specified Start Bar ... + * @param zone: XConsolidationZone instance, consolidation Zone Object ... + * @param minLoopback: int, min Allowed Lopback for Consolidating ... + * @param range: double, Consolidation Range ... + * @param upperAppliedTo: ENUM_X_PRICE member, Upper Selection Price ... + * @param lowerAppliedTo: ENUM_X_PRICE member, Lower Selection Price ... + * + * @return ( bool ) + */ + bool HasConsolidationZone( + XOHCL &bar, + XConsolidationZone &zone, + int minLoopback = 7, + double range = 50, + ENUM_X_PRICE upperAppliedTo = X_PRICE_HIGH, + ENUM_X_PRICE lowerAppliedTo = X_PRICE_LOW // + ) + { + // + bool result = false; + + // + zone.Clean(); + range = NormalizeDouble(range, 50); + minLoopback = NormalizeInt(minLoopback, 7); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double points = GetPoints(bar.symbol); + int index = bar.Index() + 1; + int length = minLoopback; + + // + double upperPrice[]; + int upperPriceCount = FillPrice( + upperPrice, + bar, + length, + upperAppliedTo // + ); + + // + double lowerPrice[]; + int lowerPriceCount = FillPrice( + lowerPrice, + bar, + length, + lowerAppliedTo // + ); + + // + result = upperPriceCount == lowerPriceCount && + lowerPriceCount == length; + if (!result) + { + // + Clean(upperPrice); + Clean(lowerPrice); + + // + return result; + } + + // + double upper = upperPrice[ArrayMaximum(upperPrice)]; + double lower = lowerPrice[ArrayMinimum(lowerPrice)]; + + // + bool isBullishBreake = + bar.low > lower && + bar.high > upper && + bar.GetUp() > upper; + bool isBearishBreake = + bar.high < upper && + bar.low < lower && + bar.GetDown() < lower; + result = isBullishBreake || + isBearishBreake; + if (!result) + { + // + Clean(upperPrice); + Clean(lowerPrice); + + // + return result; + } + + // + double delta = upper - lower; + result = delta <= range * points; + if (!result) + { + // + Clean(upperPrice); + Clean(lowerPrice); + + // + return result; + } + + // + while (delta <= range * points) + { + // + length++; + + // + upperPriceCount = FillPrice( + upperPrice, + bar, + length, + upperAppliedTo // + ); + + // + lowerPriceCount = FillPrice( + lowerPrice, + bar, + length, + lowerAppliedTo // + ); + + // + bool isValid = upperPriceCount == lowerPriceCount && + lowerPriceCount == length; + if (!isValid) + { + break; + } + + // + double iUpper = upperPrice[ArrayMaximum(upperPrice)]; + double iLower = lowerPrice[ArrayMinimum(lowerPrice)]; + + // + delta = iUpper - iLower; + if (delta <= range * points) + { + // + upper = iUpper; + lower = iLower; + } + } + + // + Clean(upperPrice); + Clean(lowerPrice); + + // + // Filling Zone ... + zone.upper = upper; + zone.lower = lower; + zone.symbol = bar.symbol; + zone.period = bar.period; + zone.to = iTime( + bar.symbol, + bar.period, + bar.Index() + 1 // + ); + zone.from = iTime( + bar.symbol, + bar.period, + bar.Index() + length // + ); + zone.dir = isBullishBreake + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = zone.IsValid(); + if (!result) + { + zone.Clean(); + } + + // + return result; + } + +/////////////////////////////////////////////////////////////////// + + // + // DOJI ... + bool isDoji = IsDoji( + bar, + iDir // + ); + bool isBullishDoji = + isDoji && + IsBullish(iDir); + bool isBearishDoji = + isDoji && + IsBearish(iDir); + + // + // SWING ... + bool isSwing = IsSwing( + bar, + iDir // + ); + bool isBullishSwing = + isSwing && + IsBullish(iDir); + bool isBearishSwing = + isSwing && + IsBearish(iDir); + + // + // HAMMER ... + bool isHammer = IsHammer( + bar, + iDir // + ); + bool isBullishHammer = + isHammer && + IsBullish(iDir); + bool isBearishHammer = + isHammer && + IsBearish(iDir); + + // + // ENGULF ... + bool isEngulfed = IsEngulfed( + bar, + iDir // + ); + bool isBullishEngulfed = + isEngulfed && + IsBullish(iDir); + bool isBearishEngulfed = + isEngulfed && + IsBearish(iDir); + + // + // REJECTED ... + bool isRejected = IsRejected( + bar, + iDir // + ); + bool isBullishRejected = + isRejected && + IsBullish(iDir); + bool isBearishRejected = + isRejected && + IsBearish(iDir); + + // + // MOMENTUM ... + bool isMomentum = IsMomentum( + bar, + iDir // + ); + bool isBullishMomentum = + isMomentum && + IsBullish(iDir); + bool isBearishMomentum = + isMomentum && + IsBearish(iDir); + + // + // Summarize Conditions ... + + // + bool isBullishOr = + isBullishDoji || + isBullishSwing || + isBullishHammer || + isBullishEngulfed || + isBullishRejected || + isBullishMomentum; + + // + bool isBearishOr = + isBearishDoji || + isBearishSwing || + isBearishHammer || + isBearishEngulfed || + isBearishRejected || + isBearishMomentum; + + // + bool isBullish = + isBullishOr && + !isBearishOr; + + // + bool isBearish = + !isBullishOr && + isBearishOr; + +/////////////////////////////////////////////////////////////////// + + bool IsVPattern( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + ENUM_X_PRICE pType = X_PRICE_CLOSE, + int loopback = 3 // + ) + { + // + bool result = false; + + // + // Normalize Args ... + dir = X_DIRECTION_NONE; + loopback = NormalizeInt(loopback, 3); + + // + // Loopback Must an Odd Number ... + // here we Validate and Normalize it ... + double iLoopbackCheck = ((double)(loopback - 1)) / 2; + if (iLoopbackCheck != 0) + { + loopback++; + } + + // + // Validate Args ... + result = + bar.IsValid() && + IsValid(pType); + if (!result) + { + return result; + } + + // + XOHCL iBar; + int index = -1; + XOHCL iSwingBar; + double prices[]; + bool has = false; + double iPrice = 0; + int pricesCount = 0; + int swingBarIDX = -1; + int loopbackHalf = 0; + bool isBullish = false; + bool isBearish = false; + bool hasBullishSeq = false; + bool hasBearishSeq = false; + + // + if (result) + { + // + // Retrieve Price Type Collection ... + index = bar.Index(); + pricesCount = FillPrice( + prices, + bar, + loopback, + pType // + ); + result = pricesCount == loopback; + if (result) + { + // + loopbackHalf = (loopback - 1) / 2; + swingBarIDX = index + loopbackHalf + 1; + has = IsValidIndex(swingBarIDX); + + // + // Check for Bullish and Bearish ... + if (has) + { + // + hasBullishSeq = true; + hasBearishSeq = true; + iPrice = prices[swingBarIDX]; + for (int i = 0; i < loopbackHalf - 1; i++) + { + // + // Side Values ... + + // + // Prev ... + double iPPrice = prices[swingBarIDX + i]; + double iP2Price = prices[swingBarIDX + i + 1]; + + // + // Next ... + double iNPrice = prices[swingBarIDX - i]; + double iN2Price = prices[swingBarIDX - i - 1]; + + // + if (hasBullishSeq) + { + // + // For Bullish Seq ... + // Prevs Must: iPPrice < iP2Price + // Nexts Must: iNPrice < iN2Price + hasBullishSeq = + iPrice < iPPrice && + iPrice < iNPrice && + iPPrice <= iP2Price && + iNPrice <= iN2Price; + } + + // + if (hasBearishSeq) + { + // + // For Bearish Seq ... + // Prevs Must: iPPrice > iP2Price + // Nexts Must: iNPrice > iN2Price + hasBearishSeq = + iPrice > iPPrice && + iPrice > iNPrice && + iPPrice >= iP2Price && + iNPrice >= iN2Price; + } + + // + if (!hasBullishSeq && + !hasBearishSeq) + { + break; + } + } + } + + // + result = + has && + (hasBullishSeq || + hasBearishSeq); + } + } + + // + // Here we Make Sure the Propper Sequence is Exists ... + if (result) + { + // + // Try to Check onther Conditions ... + has = iSwingBar.Init( + bar.symbol, + bar.period, + swingBarIDX // + ); + + // + if (has) + { + // + // Draw Requirement to Now ... + string iName = "S_1"; + datetime iTime = iSwingBar.time; + + // + CChartObjectVLine *iObj = new CChartObjectVLine(); + has = iObj.Create( + 0, + iName, + 0, + iTime // + ); + + // + iName = "SP_1"; + iTime = GetBarTime( + bar.symbol, + bar.period, + swingBarIDX + loopbackHalf); + CChartObjectVLine *iObj1 = new CChartObjectVLine(); + has = iObj1.Create( + 0, + iName, + 0, + iTime // + ); + + // + Print("Salam ..."); + } + } + + // + // Summarize Result ... + result = isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + // Cleanup Resource ... + iBar.Clean(); + iSwingBar.Clean(); + + // + return result; + } + +/////////////////////////////////////////////////////////////////// + +template +bool IsBoolean(T value) +{ + // + bool result = false; + + // + string normalizedValue = ToString(value); + StringToLower(normalizedValue); + normalizedValue = Trim(normalizedValue); + + // + result = + !IsValid(normalizedValue) + ? false + : (normalizedValue == "true" || + normalizedValue == "false"); + + // + return result; +} + +/////////////////////////////////////////////////////////////////// + diff --git a/BKPS/14040316/Documents/BKP/x-saherelm.x-expert.class.mq5 b/BKPS/14040316/Documents/BKP/x-saherelm.x-expert.class.mq5 new file mode 100644 index 0000000..ac4719e --- /dev/null +++ b/BKPS/14040316/Documents/BKP/x-saherelm.x-expert.class.mq5 @@ -0,0 +1,967 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XCBaseExpert +// 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 + +// +// Imports ... +#include "../Classes/x-saherelm.x-alert.class.mq5" +#include "../Classes/x-saherelm.x-trade.class.mq5" + +// +// Definitions ... +string XCBaseExpertToken = "XCBaseEA"; + +// +// Inputs ... + +// +// Implementations ... +class XCBaseExpert : public XCBaseAlert +{ + // + public: + // + + // + XCTrade *mTrader; // Trader of Expert Adviser ... + + // + // Constructur(s) ... + void XCBaseExpert() + { + } + + // + // Deconstructor ... + void ~XCBaseExpert() + { + // + delete mTrader; + + // + ZeroMemory(mTrader); + } + + // + // Getter(s) / Setter(s) ... + + // + // Common ... + + /** + * Get Magic Number ... + * + * @return ( long ) + */ + long MagicNumber() + { + return mMagicNumber; + } + + /** + * Set Magic Number ... + * + * @param value: Long ... + */ + void MagicNumber(long value) + { + // + mMagicNumber = value; + ReConfigure(); + } + + /** + * Get Slippage ... + * + * @return ( int ) + */ + int Slippage() + { + return mSlippage; + } + + /** + * Set Slippage ... + * + * @param value: Integer ... + */ + void Slippage(int value) + { + // + mSlippage = value; + ReConfigure(); + } + + /** + * Get Tag Prefix ... + * + * @return ( string ) + */ + string TagPrefix() + { + return mTagPrefix; + } + + /** + * Set Tag Prefix ... + * + * @param value: String ... + */ + void TagPrefix(string value) + { + // + mTagPrefix = value; + ReConfigure(); + } + + // + // Symbol ... + + /** + * Get Period ... + * + * @return ( ENUM_TIMEFRAMES ) + */ + ENUM_TIMEFRAMES GetPeriod() + { + return mPeriod; + } + + /** + * Set Period ... + * + * @param value: ENUM_TIMEFRAMES member ... + */ + void SetPeriod(ENUM_TIMEFRAMES value) + { + // + mPeriod = value; + ReConfigure(); + } + + /** + * Get Symbol ... + * + * @return ( string ) + */ + string GetSymbol() + { + return mSymbol; + } + + /** + * Set Symbol ... + * + * @param value: String ... + */ + void SetSymbol(string value) + { + // + mSymbol = value; + ReConfigure(); + } + + /** + * Get Multi Symbol is Enable or Not ... + * + * @return ( bool ) + */ + bool MultiSymbol() + { + return mMultiSymbol; + } + + /** + * Set Multi Symbol is Enable or Not ... + * + * @param value: Boolean ... + */ + void MultiSymbol(bool value) + { + // + mMultiSymbol = value; + ReConfigure(); + } + + /** + * Get Multi Provided Symbols ... + * + * @return ( string ) + */ + string Symbols() + { + return mSymbols; + } + + /** + * Set Multi Provided Symbols ... + * + * @param value: String ... + */ + void Symbols(string value) + { + // + mSymbols = value; + ReConfigure(); + } + + // + // Signalling ... + + /** + * Get Force Disable Signalling ... + * + * @return ( bool ) + */ + bool Disabled() + { + return mDisabled; + } + + /** + * Set Force Disable Signalling ... + * + * @param value: Boolean ... + */ + void Disabled(bool value) + { + // + mDisabled = value; + ReConfigure(); + } + + /** + * Get Allow Long Signals ... + * + * @return ( bool ) + */ + bool AllowLong() + { + return mAllowLong; + } + + /** + * Set Allow Long Signals ... + * + * @param value: Boolean ... + */ + void AllowLong(bool value) + { + // + mAllowLong = value; + ReConfigure(); + } + + /** + * Get Allow Short Signalling ... + * + * @return ( bool ) + */ + bool AllowShort() + { + return mAllowShort; + } + + /** + * Set Allow Short Signalling ... + * + * @param value: Boolean ... + */ + void AllowShort(bool value) + { + // + mAllowShort = value; + ReConfigure(); + } + + // + // Reports ... + + /** + * Get Report New Month State ... + * + * @return ( bool ) + */ + bool ReportNewMonths() + { + return mReportNewMonths; + } + + /** + * Set Report New Month State ... + * + * @param value: Boolean ... + */ + void ReportNewMonths(bool value) + { + // + mReportNewMonths = value; + ReConfigure(); + } + + /** + * Get Report New Weeks State ... + * + * @return ( bool ) + */ + bool ReportNewWeeks() + { + return mReportNewWeeks; + } + + /** + * Set Report New Weeks State ... + * + * @param value: Boolean ... + */ + void ReportNewWeeks(bool value) + { + // + mReportNewWeeks = value; + ReConfigure(); + } + + /** + * Get Report New Days State ... + * + * @return ( bool ) + */ + bool ReportNewDays() + { + return mReportNewDays; + } + + /** + * Set Report New Days State ... + * + * @param value: Boolean ... + */ + void ReportNewDays(bool value) + { + // + mReportNewDays = value; + ReConfigure(); + } + + /** + * Get Report New Hours State ... + * + * @return ( bool ) + */ + bool ReportNewHours() + { + return mReportNewHours; + } + + /** + * Set Report New Hours State ... + * + * @param value: Boolean ... + */ + void ReportNewHours(bool value) + { + // + mReportNewHours = value; + ReConfigure(); + } + + // + // Actions ... + + /** + * Handle Expert OnInit Event ... + * + * @return ( bool ) + */ + bool HandleOnInit() + { + // + bool result = false; + + // + string message = ""; + + // + // Validate Input ... + result = ValidateInputs(); + if (!result) + { + // + message = "Invalid Inputs ...."; + + // + SendAlert(message); + } + + // + // Initial All Requirements ... + result = InitEA(); + if (!result) + { + return result; + } + + // + // Initial All GUI Requirements ... + result = InitGUI(); + if (!result) + { + return result; + } + + // + message = "Initialized Successfully ..."; + SendAlert(message); + + // + return result; + } + + /** + * Handle Expert OnDeInit Event ... + */ + void HandleOnDeInit() + { + // + // Destroy all GUI Requirements ... + DestroyGUI(); + + // + // Alert De Initialization Succeeded ... + string msg = "De Initialized Successfully ..."; + Alert(msg); + + // + // Destroy all EA Requirements ... + DestroyEA(); + } + + /** + * Handle Expert OnTick Event ... + */ + void HandleOnTick() + { + // + UpdateGUI(); + HandleReportTime(); + HandleStrategiesOnTick(); + HandleStrategiesGuard(); + } + + /** + * Handle Expert OnTrade Event ... + */ + void HandleOnTrade() + { + mTrader.HandleOnTrade(); + } + + /** + * Handle Expert OnTimer Event ... + */ + void HandleOnTimer() + { + } + + /** + * Handle Expert OnChart Event ... + */ + void HandleOnChartEvent( + const int id, + const long &lparam, + const double &dparam, + const string &sparam // + ) + { + } + + // + // Virtual Actions ... + + /** + * Apply Default Configurations ... + */ + virtual void DefaultConfigure() + { + // + // Commons ... + Slippage(10); + TagPrefix(""); + MagicNumber(1694056); + + // + // Symbol ... + SetSymbol(_Symbol); + SetPeriod(_Period); + MultiSymbol(false); + Symbols("EURUSDb,GBPUSDb,USDJPYb,USDCHFb,DowJones30,XAUUSDb"); + + // + // Signalling ... + Disabled(false); + AllowLong(true); + AllowShort(true); + + // + string tag = GetTag(); + + // + // Alert ... + SetAlertPrefix(tag); + SetAlertLogAlerts(true); + SetAlertPushAlerts(true); + SetAlertMailAlerts(false); + SetAlertEnableAlerts(true); + SetAlertTerminalAlerts(false); + + // + // Reports ... + ReportNewDays(true); + ReportNewWeeks(false); + ReportNewHours(false); + ReportNewMonths(false); + } + + /** + * Vaslidate Inputs ... + * + * @return ( virtual bool ) + */ + virtual bool ValidateInputs() + { + // + bool result = false; + + // + string errMessage = ""; + + // + bool isCommonValid = ( + // + mSlippage > 0 && + mMagicNumber > 0 + // + ); + if (!isCommonValid) + { + // + errMessage += "common configurations error;" + "\n"; + } + + // + result = + // + // Common ... + isCommonValid && + // + // Otere ... + true + // + ; + + // + if (!result) + { + // + // Since here Logger not Initiallized, we Use Raw Print Command ... + errMessage = " Errors: \n" + errMessage; + SendAlert(errMessage); + } + + // + return result; + } + + // + // Initializers and DeInitializers ... + + /** + * Initial EA Requirements ... + * + * @return ( virtual bool ) + */ + virtual bool InitEA() + { + // + bool result = false; + + // + // Initialize Indicator Helpers ... + + // + // Create Trader Instance and Configure it ... + mTrader = new XCTrade( + mSlippage, + mMagicNumber // + ); + + // + return result; + } + + /** + * Destroy Initialized Requirements ... + */ + virtual void DestroyEA() + { + // + delete mTrader; + + // + ZeroMemory(mTrader); + } + + /** + * GUI Initialize if required ... + * + * @return ( virtual bool ) + */ + virtual bool InitGUI() + { + // + bool result = false; + + // + result = true; + + // + return result; + } + + /** + * Update All GUI Contents ... + */ + virtual void UpdateGUI() + { + } + + /** + * Destroy all Initialized GUi Elements ... + */ + virtual void DestroyGUI() + { + } + + // + // Event Handlers ... + + /** + * Calls When a Position's SL Triggered ... + * + * @param deal: XDeal instance ... + */ + virtual void HandleOnStopLossTriggered(const XDeal &deal) + { + HandleReportBalance(); + } + + /** + * Calls When a Position's TP Triggered ... + * + * @param deal: XDeal instance ... + */ + virtual void HandleOnTakeProfitTriggered(const XDeal &deal) + { + HandleReportBalance(); + } + + /** + * Handle Force Close a Position ... + * + * @param ticket: Position Ticket ... + * @param position: XPosition ... + * @param comment: Closing Comment ... + */ + virtual void HandleOnPositionForceClosed( + const ulong ticket, + const XPosition &position, + const string comment // + ) + { + HandleReportBalance(); + } + + /** + * Handle Position Modified ... + * + * @param ticket: ULONG ... + * @param profit: Double ... + * @param comment: String ... + */ + virtual void HandleOnPositionModified( + const ulong ticket, + const double profit, + const string comment // + ) + { + } + + /** + * Handle Position Partially Closed ... + * + * @param ticket: ULONG ... + * @param profit: Double ... + * @param comment: String ... + */ + virtual void HandleOnPositionPartialClosed( + const ulong ticket, + const double profit, + const string comment // + ) + { + } + + /** + * Handle Deals Changed ... + * + * @param count: Integer, Number of Changes ... + */ + virtual void HandleOnDealsChanged(int count) + { + } + + /** + * Handle Orders Changed ... + * + * @param count: Integer, Number of Changes ... + */ + virtual void HandleOnOrdersChanged(int count) + { + } + + /** + * Handle Positions Changed ... + * + * @param count: Integer, Number of Changes ... + */ + virtual void HandleOnPositionsChanged(int count) + { + } + + /** + * Do All Signalling Processing Here ... + */ + virtual void HandleStrategiesOnTick() + { + } + + /** + * Check Strategies for Guards and then Apply Them ... + */ + virtual void HandleStrategiesGuard() + { + } + + // + // Time Handlers ... + + virtual void HandleOnNewMonth() + { + } + + virtual void HandleOnNewWeek() + { + } + + virtual void HandleOnNewDay() + { + } + + virtual void HandleOnNewHour() + { + } + + virtual void ReConfigure() + { + } + + /** + * Generate Identifier Tag ... + * + * @return ( virtual string ) + */ + virtual string GetTag() + { + // + string result = NULL; + + // + string tagPrefix = TagPrefix(); + if (IsValid(tagPrefix)) + { + result = tagPrefix; + } + else + { + result = ""; + } + + // + result = + XCBaseExpertToken + result; + + // + return result; + } + + // + protected: + // + + // + // Props ... + + // + XTimeTracker mTimeTracker; // Time Tracker for Providing Reports ... + + // + // Actions ... + + /** + * Report Account Balance ... + */ + void HandleReportBalance() + { + // + if (!IsRunningOnTestMode()) + { + return; + } + + // + string msg = "Balance: " + ToString(mTrader.mAccount.GetBalance()); + Log(msg); + } + + /** + * Time Reporting based on Inputs ... + */ + void HandleReportTime() + { + // + // Monthly Report .... + if (mTimeTracker.IsNewMonth()) + { + // + HandleOnNewMonth(); + + // + if (mReportNewMonths) + { + // + string msg = "New Month ..."; + + // + SendAlert(msg); + } + } + + // + // Weekly Report .... + if (mTimeTracker.IsNewWeek()) + { + // + HandleOnNewWeek(); + + // + if (mReportNewWeeks) + { + // + string msg = "New Week ..."; + + // + SendAlert(msg); + } + } + + // + // Daily Report .... + if (mTimeTracker.IsNewDay()) + { + // + HandleOnNewDay(); + + // + if (mReportNewDays) + { + // + string msg = "New Day ..."; + + // + SendAlert(msg); + } + } + + // + // Hourly Report .... + if (mTimeTracker.IsNewHour()) + { + // + HandleOnNewHour(); + + // + if (mReportNewHours) + { + // + string msg = "New Hour ..."; + + // + SendAlert(msg); + } + } + } + + // + private: + // + + // + // Props ... + + // + // Common ... + long mMagicNumber; // Magic Number ... + int mSlippage; // Slippage ... + string mTagPrefix; // Tag Prefix ... + + // + // Symbol ... + ENUM_TIMEFRAMES mPeriod; // Period ... + string mSymbol; // Symbol ... + bool mMultiSymbol; // Multi Symbol is Enable or Not ... + string mSymbols; // Multi Provided Symbols ... + + // + // Signalling ... + bool mDisabled; // Force Disable Signalling ... + bool mAllowLong; // Allow Long Signals ... + bool mAllowShort; // Allow Short Signals ... + + // + // Reports ... + bool mReportNewMonths; // Report New Month ... + bool mReportNewWeeks; // Report New Weeks ... + bool mReportNewDays; // Report New Days ... + bool mReportNewHours; // Report New Hours ... + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14040316/Documents/BKP/x-saherelm.x-poi.class.mq5 b/BKPS/14040316/Documents/BKP/x-saherelm.x-poi.class.mq5 new file mode 100644 index 0000000..d3338fa --- /dev/null +++ b/BKPS/14040316/Documents/BKP/x-saherelm.x-poi.class.mq5 @@ -0,0 +1,3513 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XPOI +// Description: Provides Point of Interests ... +// - Swing Highs; +// - Swing Lows; +// +// 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.x-alert.class.mq5" +#include "../Classes/x-saherelm.x-bar.analyser.class.mq5" +#include "../Libraries/x-saherelm.x-poi.state.lib.mq5" + +// +// Implementation ... + +// +// POI Detector Class ... +class XCPOIDetector : public XCBaseAlert +{ + // + public: + // + + // + // Constructors ... + /** + * Create an Instance ... + * + * @param symbol: String ... + * @param period: ENUM_TIMEFRAMES member ... + */ + void XCPOIDetector( + string symbol, + ENUM_TIMEFRAMES period) + { + // + // Attach Required Properties ... + mSymbol = symbol; + mPeriod = period; + + // + // Initialize Bar Tracker ... + mBarTracker.Init( + mSymbol, + mPeriod // + ); + + // + mBarAnalyser = new XCBarAnalyser(); + + // + // Apply Default Configurations ... + Default(); + } + + // + // Deconstructor ... + void ~XCPOIDetector() + { + Destroy(); + } + + // + // Getter(s) / Setter(s) ... + + /** + * Retrieve Detector Symbol ... + * + * @return ( string ) + */ + string GetSymbol() + { + return mSymbol; + } + + /** + * Retrieve Detector Period ... + * + * @return ( ENUM_TIMEFRAMES ) + */ + ENUM_TIMEFRAMES GetPeriod() + { + return mPeriod; + } + + /** + * Get Max Required POI(s) allowed to Holds ... + * + * @return ( int ) + */ + int MaxRequiredPOIs() + { + return mMaxRequiredPOIs; + } + + /** + * Set Max Required POI(s) allowed to Holds ... + * + * @param value: int ... + */ + void MaxRequiredPOIs(int value) + { + // + if (value < 0) + { + value = 5; + } + + // + mMaxRequiredPOIs = value; + } + + /** + * Get Max Allowed Loopback for POI(s) Detection on Initialization Process ... + * + * @return ( int ) + */ + int MaxAllowedLoopbackForInit() + { + return maxAllowedLoopbackForInit; + } + + /** + * Set Max Allowed Loopback for POI(s) Detection on Initialization Process ... + * + * @param value: int ... + */ + void MaxAllowedLoopbackForInit(int value) + { + // + if (value < 0) + { + value = 578; + } + + // + maxAllowedLoopbackForInit = value; + } + + // + // + // + + /** + * Get Swing Range Validation ... + * + * @return ( int ) + */ + int SwingRange() + { + return mSwingRange; + } + + /** + * Set Swing Range Validation ... + * + * @param value: int ... + */ + void SwingRange(int value) + { + // + value = NormalizeInt(value, 1); + + // + mSwingRange = value; + } + + /** + * Get Pullback Range Validation ... + * + * @return ( int ) + */ + int PullbackRange() + { + return mPullbackRange; + } + + /** + * Set Pullback Range Validation ... + * + * @param value: int ... + */ + void PullbackRange(int value) + { + // + value = NormalizeInt(value, 1); + + // + mPullbackRange = value; + } + + /** + * Get Momentum Detecting Loopback ... + * + * @return ( int ) + */ + int MomentumLoopback() + { + return mMomentumLoopback; + } + + /** + * Set Momentum Detecting Loopback ... + * + * @param value: int ... + */ + void MomentumLoopback(int value) + { + // + value = NormalizeInt(value, 1); + + // + mMomentumLoopback = value; + } + + /** + * Get Rejection Detecting Force Bar Type State ... + * + * @return ( bool ) + */ + bool RejectionForceBarType() + { + return mRejectionForceBarType; + } + + /** + * Set Rejection Detecting Force Bar Type State ... + * + * @param value: bool ... + */ + void RejectionForceBarType(bool value) + { + mRejectionForceBarType = value; + } + + /** + * Get Rejection Detecting Force Fibo Pressure State ... + * + * @return ( bool ) + */ + bool RejectionForceFiboPressure() + { + return mRejectionForceFiboPressure; + } + + /** + * Set Rejection Detecting Force Fibo Pressure State ... + * + * @param value: bool ... + */ + void RejectionForceFiboPressure(bool value) + { + mRejectionForceFiboPressure = value; + } + + /** + * Get Minimum Length of Cnsolidation Zone ... + * + * @return ( int ) + */ + int ConsolidationZoneMinLoopback() + { + return mConsolidationZoneMinLoopback; + } + + /** + * Set Minimum Length of Cnsolidation Zone ... + * + * @param value: int ... + */ + void ConsolidationZoneMinLoopback(int value) + { + // + value = NormalizeInt(value, 1); + + // + mConsolidationZoneMinLoopback = value; + } + + /** + * Get Consolidation Zone Range in Point ... + * + * @return ( double ) + */ + double ConsolidationZoneRangeInPoint() + { + return mConsolidationZoneRangeInPoint; + } + + /** + * Set Consolidation Zone Range in Point ... + * + * @param value: double ... + */ + void ConsolidationZoneRangeInPoint(double value) + { + // + value = NormalizeDouble(value, 0); + + // + mConsolidationZoneRangeInPoint = value; + } + + /** + * Get Consolidation Zone Lower Applied To ... + * + * @return ( ENUM_X_PRICE ) + */ + ENUM_X_PRICE ConsolidationZonesLowerAppliedTo() + { + return mConsolidationZonesLowerAppliedTo; + } + + /** + * Get Consolidation Zone Lower Applied To ... + * + * @param value: ENUM_X_PRICE member ... + */ + void ConsolidationZonesLowerAppliedTo(ENUM_X_PRICE value) + { + mConsolidationZonesLowerAppliedTo = value; + } + + /** + * Get Consolidation Zone Upper Applied To ... + * + * @return ( ENUM_X_PRICE ) + */ + ENUM_X_PRICE ConsolidationZonesUpperAppliedTo() + { + return mConsolidationZonesUpperAppliedTo; + } + + /** + * Get Consolidation Zone Upper Applied To ... + * + * @param value: ENUM_X_PRICE member ... + */ + void ConsolidationZonesUpperAppliedTo(ENUM_X_PRICE value) + { + mConsolidationZonesUpperAppliedTo = value; + } + + /** + * Get Spike Detection Price Type ... + * + * @return ( ENUM_X_PRICE ) + */ + ENUM_X_PRICE SpikePriceType() + { + return mSpikePriceType; + } + + /** + * Set Spike Detection Price Type ... + * + * @param value: ENUM_X_PRICE member ... + */ + void SpikePriceType(ENUM_X_PRICE value) + { + mSpikePriceType = value; + } + + /** + * Get Spike Detection Force Body In Range State ... + * + * @return ( bool ) + */ + bool SpikeForcBodyInRange() + { + return mSpikeForcBodyInRange; + } + + /** + * Set Spike Detection Force Body In Range State ... + * + * @param value: bool ... + */ + void SpikeForcBodyInRange(bool value) + { + mSpikeForcBodyInRange = value; + } + + /** + * Get Spike Detection Range Extends Multiplier ... + * + * @return ( double ) + */ + double SpikeRangeExtendMultiplier() + { + return mSpikeRangeExtendMultiplier; + } + + /** + * Set Spike Detection Range Extends Multiplier ... + * + * @param value: double ... + */ + void SpikeRangeExtendMultiplier(double value) + { + // + value = NormalizeDouble(value, 1); + + // + mSpikeRangeExtendMultiplier = value; + } + + /** + * Get Spike Detection Same Bars ... + * + * @return ( int ) + */ + int SpikeSameBars() + { + return mSpikeSameBars; + } + + /** + * Set Spike Detection Same Bars ... + * + * @param value: int ... + */ + void SpikeSameBars(int value) + { + // + value = NormalizeInt(value, 1); + + // + mSpikeSameBars = value; + } + + /** + * Get Support and Resistance Detection Range ... + * + * @return ( int ) + */ + int SupResRange() + { + return mSupResRange; + } + + /** + * Set Support and Resistance Detection Range ... + * + * @param value: int ... + */ + void SupResRange(int value) + { + // + value = NormalizeInt(value, 5); + + // + mSupResRange = value; + } + + /** + * Get use Support and Resistance Range as Start ... + * + * @return ( bool ) + */ + bool SupResRangeAsStart() + { + return mSupResRangeAsStart; + } + + /** + * Set use Support and Resistance Range as Start ... + * + * @param value: bool ... + */ + void SupResRangeAsStart(bool value) + { + mSupResRangeAsStart = value; + } + + /** + * Get Force Activations in Supply/Demand and Support/Resistance Detections State ... + * + * @return ( bool ) + */ + bool SupResForceActivation() + { + return mSupResForceActivation; + } + + /** + * Set Force Activations in Supply/Demand and Support/Resistance Detections State ... + * + * @param value: bool ... + */ + void SupResForceActivation(bool value) + { + mSupResForceActivation = value; + } + + /** + * Get FairValueGap Detection Same Bars ... + * + * @return ( int ) + */ + int FairValueGapSameBars() + { + return mFairValueGapSameBars; + } + + /** + * Set FairValueGap Detection Same Bars ... + * + * @param value: int ... + */ + void FairValueGapSameBars(int value) + { + // + value = NormalizeInt(value, 2); + + // + mFairValueGapSameBars = value; + } + + /** + * Get FairValueGap Detection Force Check Activation State ... + * + * @return ( bool ) + */ + bool FairValueGapForceActivation() + { + return mFairValueGapForceActivation; + } + + /** + * Set FairValueGap Detection Force Check Activation State ... + * + * @param value: bool ... + */ + void FairValueGapForceActivation(bool value) + { + mFairValueGapForceActivation = value; + } + + /** + * Get OrderBlock Detection Same Bars ... + * + * @return ( int ) + */ + int OrderBlockSameBars() + { + return mOrderBlockSameBars; + } + + /** + * Set OrderBlock Detection Same Bars ... + * + * @param value: int ... + */ + void OrderBlockSameBars(int value) + { + // + value = NormalizeInt(value, 1); + + // + mOrderBlockSameBars = value; + } + + /** + * Get Order Blocs Detection Force Spike State ... + * + * @return ( bool ) + */ + bool OrderBlockForceSpike() + { + return mOrderBlockForceSpike; + } + + /** + * Set Order Blocs Detection Force Spike State ... + * + * @param value: bool ... + */ + void OrderBlockForceSpike(bool value) + { + mOrderBlockForceSpike = value; + } + + /** + * Get Order Blocs Detection Force Fair Value Gaps State ... + * + * @return ( bool ) + */ + bool OrderBlockForceFairValueGap() + { + return mOrderBlockForceFairValueGap; + } + + /** + * Set Order Blocs Detection Force Fair Value Gaps State ... + * + * @param value: bool ... + */ + void OrderBlockForceFairValueGap(bool value) + { + mOrderBlockForceFairValueGap = value; + } + + /** + * Get Order Blocs Detection Force Support/Resisatnce ... + * + * @return ( bool ) + */ + bool OrderBlockForceSupportResistance() + { + return mOrderBlockForceSupportResistance; + } + + /** + * Set Order Blocs Detection Force Support/Resisatnce ... + * + * @param value: bool ... + */ + void OrderBlockForceSupportResistance(bool value) + { + mOrderBlockForceSupportResistance = value; + } + + /** + * Get OrderBlock Detection Force Check Activation State ... + * + * @return ( bool ) + */ + bool OrderBlockForceActivation() + { + return mOrderBlockForceActivation; + } + + /** + * Set OrderBlock Detection Force Check Activation State ... + * + * @param value: bool ... + */ + void OrderBlockForceActivation(bool value) + { + mOrderBlockForceActivation = value; + } + + // + // + // + // + // + // + + // + // Actions ... + + /** + * Apply Default Configurations ... + */ + virtual void Default() + { + // + // Default Props ... + MaxRequiredPOIs(100); + MaxAllowedLoopbackForInit(578); + + // + SwingRange(7); + MomentumLoopback(2); + + // + PullbackRange(3); + + // + MomentumLoopback(2); + + // + RejectionForceBarType(true); + RejectionForceFiboPressure(true); + + // + ConsolidationZoneMinLoopback(7); + ConsolidationZoneRangeInPoint(50); + ConsolidationZonesLowerAppliedTo(X_PRICE_LOW); + ConsolidationZonesUpperAppliedTo(X_PRICE_HIGH); + + // + SpikePriceType(X_PRICE_CLOSE); + SpikeForcBodyInRange(true); + SpikeRangeExtendMultiplier(2.0); + SpikeSameBars(3); + + // + SupResRange(21); + SupResRangeAsStart(true); + SupResForceActivation(true); + + // + FairValueGapSameBars(3); + + // + OrderBlockSameBars(3); + OrderBlockForceSpike(true); + OrderBlockForceFairValueGap(true); + OrderBlockForceSupportResistance(false); + } + + /** + * Add Event Listener ... + * + * @param listener: TOnPOIEvent instance ... + */ + void AddEventListener(TOnPOIEvent listener) + { + // + Add( + listener, + mEventListeners // + ); + } + + /** + * Initialize Instance ... + */ + void Init( + int barIndex = 0, + bool ignoreMaxAllowed = true // + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (maxAllowedLoopbackForInit <= 0) + { + return; + } + + // + mLock = true; + bool canContinue = true; + int index = barIndex + maxAllowedLoopbackForInit; + if (!IsValidIndex(index)) + { + // + mLock = false; + return; + } + + // + while (canContinue) + { + // + XOHCL iBar; + bool has = iBar.Init( + mSymbol, + mPeriod, + index // + ); + index--; + + // + int count = 0; + ENUM_XPOI_EVENTS iEvent = X_POI_EVENT_NONE; + + // + // Swings ... + DetectSwing( + iBar, + iEvent // + ); + + // + // Momentum ... + DetectMomentum( + iBar, + iEvent // + ); + + // + // Rejection ... + DetectRejection( + iBar, + iEvent // + ); + + // + // Pullback ... + DetetctPullback( + iBar, + iEvent // + ); + + // + // Consolidation Zone ... + DetectConsolidationZone( + iBar, + iEvent // + ); + + // + // Spike ... + DetectSharp( + iBar, + iEvent // + ); + + // + // Spike ... + DetectSpike( + iBar, + iEvent // + ); + + // + // Support ... + DetectSupportZone( + iBar, + iEvent // + ); + + // + // Resistance ... + DetectResistanceZone( + iBar, + iEvent // + ); + + // + // Supply ... + DetectSupplyZone( + iBar, + iEvent // + ); + + // + // Demand ... + DetectDemandZone( + iBar, + iEvent // + ); + + // + // FairValueGap ... + DetectFairValueGap( + iBar, + iEvent // + ); + + // + // OrderBlock ... + DetectOrderBlock( + iBar, + iEvent // + ); + + // + canContinue = + has && + index >= 0; + + // + iBar.Clean(); + } + + // + ReverseCollections(); + + // + mLock = false; + } + + /** + * Update POI(s) ... + * @param events: ENUM_XPOI_EVENTS member Collection ... + */ + void Update( + ENUM_XPOI_EVENTS &events[], + int barIndex = 0 // + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Clean(events); + + // + if (mLock) + { + return; + } + + // + // Check Bar Tracker if Waits ... + if (!mBarTracker.IsNewBar()) + { + return; + } + + // + mLock = true; + + // + XOHCL iBar; + bool has = iBar.Init( + mSymbol, + mPeriod, + barIndex // + ); + + // + if (!has) + { + // + iBar.Clean(); + + // + return; + } + + // + int count = 0; + ENUM_XPOI_EVENTS iEvent = X_POI_EVENT_NONE; + + // + // Swings ... + has = DetectSwing( + iBar, + iEvent // + ); + if (has) + { + // + Add( + iEvent, + events // + ); + } + + // + // Momentum ... + has = DetectMomentum( + iBar, + iEvent // + ); + if (has) + { + // + Add( + iEvent, + events // + ); + } + + // + // Rejection ... + has = DetectRejection( + iBar, + iEvent // + ); + if (has) + { + // + Add( + iEvent, + events // + ); + } + + // + // Pullback ... + has = DetetctPullback( + iBar, + iEvent // + ); + if (has) + { + // + Add( + iEvent, + events // + ); + } + + // + // Consolidation Zone ... + has = DetectConsolidationZone( + iBar, + iEvent // + ); + if (has) + { + // + Add( + iEvent, + events // + ); + } + + // + // Sharp ... + has = DetectSharp( + iBar, + iEvent // + ); + if (has) + { + // + Add( + iEvent, + events // + ); + } + + // + // Spike ... + has = DetectSpike( + iBar, + iEvent // + ); + if (has) + { + // + Add( + iEvent, + events // + ); + } + + // + // Support ... + has = DetectSupportZone( + iBar, + iEvent // + ); + if (has) + { + // + Add( + iEvent, + events // + ); + } + + // + // Resistance ... + has = DetectResistanceZone( + iBar, + iEvent // + ); + if (has) + { + // + Add( + iEvent, + events // + ); + } + + // + // Supply ... + has = DetectSupplyZone( + iBar, + iEvent // + ); + if (has) + { + // + Add( + iEvent, + events // + ); + } + + // + // Demand ... + has = DetectDemandZone( + iBar, + iEvent // + ); + if (has) + { + // + Add( + iEvent, + events // + ); + } + + // + // FairValueGap ... + has = DetectFairValueGap( + iBar, + iEvent // + ); + if (has) + { + // + Add( + iEvent, + events // + ); + } + + // + // OrderBlock ... + has = DetectOrderBlock( + iBar, + iEvent // + ); + if (has) + { + // + Add( + iEvent, + events // + ); + } + + // + iBar.Clean(); + mLock = false; + + // + if (HasChild(events)) + { + CleanupUnusedCollections(); + } + } + + /** + * Get Current State of POIs ... + * + * @param state: XPOIState instance ... + */ + void GetState( + XPOIState &state // + ) + { + // + state.Clean(); + + // + state.symbol = mSymbol; + state.period = mPeriod; + state.time = TimeCurrent(); + + // + // Swings ... + + // + Copy( + mSwings, + state.swings // + ); + + // + Copy( + mSwingLows, + state.swingLows // + ); + + // + Copy( + mSwingHighs, + state.swingHighs // + ); + + // + // Pullbacks ... + + // + Copy( + mPullbacks, + state.pullbacks // + ); + + // + Copy( + mBullishPullbacks, + state.bullishPullbacks // + ); + + // + Copy( + mBearishPullbacks, + state.bearishPullbacks // + ); + + // + // Momentums ... + + // + Copy( + mMomentums, + state.momentums // + ); + + // + Copy( + mBullishMomentums, + state.bullishMomentums // + ); + + // + Copy( + mBearishMomentums, + state.bearishMomentums // + ); + + // + // Rejections ... + + // + Copy( + mRejections, + state.rejections // + ); + + // + Copy( + mBullishRejections, + state.bullishRejections // + ); + + // + Copy( + mBearishRejections, + state.bearishRejections // + ); + + // + // Support and Resistances ... + + // + Copy( + mSupportZones, + state.supportZones // + ); + + // + Copy( + mResistanceZones, + state.resistanceZones // + ); + + // + // Supply and Demand ... + + // + Copy( + mSupplyZones, + state.supplyZones // + ); + + // + Copy( + mDemandZones, + state.demandZones // + ); + + // + // Spikes ... + + // + Copy( + mSpikes, + state.spikes // + ); + + // + Copy( + mBullishSpikes, + state.bullishSpikes // + ); + + // + Copy( + mBearishSpikes, + state.bearishSpikes // + ); + + // + // Sharps ... + + // + Copy( + mSharps, + state.sharps // + ); + + // + Copy( + mBullishSharps, + state.bullishSharps // + ); + + // + Copy( + mBearishSharps, + state.bearishSharps // + ); + + // + // Consolidation Zones ... + + // + Copy( + mConsolidationZones, + state.consolidationZones // + ); + + // + Copy( + mBullishConsolidationZones, + state.bullishConsolidationZones // + ); + + // + Copy( + mBearishConsolidationZones, + state.bearishConsolidationZones // + ); + + // + // Fair Value Gaps ... + + // + Copy( + mFairValueGaps, + state.fairValueGaps // + ); + + // + Copy( + mBullishFairValueGaps, + state.bullishFairValueGaps // + ); + + // + Copy( + mBearishFairValueGaps, + state.bearishFairValueGaps // + ); + + // + // Order Blocks ... + + // + Copy( + mOrderBlocks, + state.orderBlocks // + ); + + // + Copy( + mBullishOrderBlocks, + state.bullishOrderBlocks // + ); + + // + Copy( + mBearishOrderBlocks, + state.bearishOrderBlocks // + ); + } + + /** + * Destroy Instance ... + */ + void Destroy() + { + // + mBarTracker.Clean(); + ZeroMemory(mBarAnalyser); + + // + CleanCollections(); + } + + // + // + // + // + // + // + + /** + * Detect Swing ... + * + * @param bar: XOHCL instance ... + * @param state: ENUM_XPOI_EVENTS member ... + * + * @return ( bool ) + */ + bool DetectSwing( + XOHCL &bar, + ENUM_XPOI_EVENTS &state // + ) + { + // + bool result = false; + + // + state = X_POI_EVENT_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL sBar; + if (bar.Index() == 0) + { + // + result = bar.GetPreviousBar(sBar); + if (!result) + { + // + sBar.Clean(); + return result; + } + } + else + { + sBar = bar; + } + + // + ENUM_X_DIRECTION iDir; + result = mBarAnalyser.IsSwing( + sBar, + iDir, + mSwingRange // + ); + + // + result = result && + HasDirection(iDir); + if (!result) + { + // + sBar.Clean(); + return result; + } + + // + bool checkBar = bar.Index() != sBar.Index(); + + // + bool isBullish = + IsBullish(iDir) && + (!checkBar + ? true + : bar.low > sBar.low); + bool isBearish = + IsBearish(iDir) && + (!checkBar + ? true + : bar.high < sBar.high); + result = isBullish || + isBearish; + if (!result) + { + // + sBar.Clean(); + return result; + } + + // + XOHCL swingBar; + result = sBar.GetPreviousBar(swingBar); + if (!result) + { + // + sBar.Clean(); + swingBar.Clean(); + return result; + } + + // + ENUM_XPOIS type = + isBullish + ? X_POI_SWING_LOW + : X_POI_SWING_HIGH; + + // + // Swing Object ... + XCSwing *swing; + swing = new XCSwing(); + result = swing.Init( + swingBar, + type // + ); + if (!result) + { + // + sBar.Clean(); + swingBar.Clean(); + return result; + } + + // + // Add ... + + // + int idx = FindIndex( + swing, + mSwings // + ); + result = !IsValidIndex(idx); + if (!result) + { + // + sBar.Clean(); + swingBar.Clean(); + return result; + } + + // + // Add All Collection ... + Add( + swing, + mSwings // + ); + + // + // Bullish Swings (Swing Low) ... + if (isBullish) + { + // + Add( + swing, + mSwingLows // + ); + } + + // + // Bearish Swings (Swing High) ... + if (isBearish) + { + // + Add( + swing, + mSwingHighs // + ); + } + + // + // Prepare State ... + state = + isBullish + ? X_SWING_LOW_DETECTED + : X_SWING_HIGH_DETECTED; + + // + // Cleanup Resources ... + + // + sBar.Clean(); + swingBar.Clean(); + + // + return result; + } + + /** + * Detect Momentums ... + * + * @param bar: XOHCL instance ... + * @param state: ENUM_XPOI_EVENTS member ... + * + * @return ( bool ) + */ + bool DetectMomentum( + XOHCL &bar, + ENUM_XPOI_EVENTS &state // + ) + { + // + bool result = false; + + // + state = X_POI_EVENT_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL sBar; + if (bar.Index() == 0) + { + // + result = sBar.Init( + bar.symbol, + bar.period, + bar.Index() + 1 // + ); + if (!result) + { + // + sBar.Clean(); + return result; + } + } + else + { + sBar = bar; + } + + // + ENUM_X_DIRECTION iDir; + result = mBarAnalyser.IsMomentum( + sBar, + iDir, + mMomentumLoopback // + ); + + // + result = result && + HasDirection(iDir); + if (!result) + { + // + sBar.Clean(); + return result; + } + + // + bool isBullish = IsBullish(iDir); + bool isBearish = IsBearish(iDir); + + // + ENUM_XPOIS type = + isBullish + ? X_POI_MOMENTUM_BAR + : X_POI_MOMENTUM_BAR; + + // + // Swing Object ... + XCMomentumBar *momentum; + momentum = new XCMomentumBar(); + result = momentum.Init( + sBar // + ); + if (!result) + { + // + sBar.Clean(); + return result; + } + + // + int idx = FindIndex( + momentum, + mMomentums // + ); + result = !IsValidIndex(idx); + if (!result) + { + // + sBar.Clean(); + return result; + } + + // + // Momentums ... + Add( + momentum, + mMomentums // + ); + + // + if (isBullish) + { + // + Add( + momentum, + mBullishMomentums // + ); + } + + // + if (isBearish) + { + // + Add( + momentum, + mBearishMomentums // + ); + } + + // + state = + isBullish + ? X_BULLISH_MOMENTUM_BAR_DETECTED + : X_BEARISH_MOMENTUM_BAR_DETECTED; + + // + sBar.Clean(); + + // + return result; + } + + /** + * Detect Rejections ... + * + * @param bar: XOHCL instance ... + * @param state: ENUM_XPOI_EVENTS member ... + * + * @return ( bool ) + */ + bool DetectRejection( + XOHCL &bar, + ENUM_XPOI_EVENTS &state // + ) + { + // + bool result = false; + + // + state = X_POI_EVENT_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL sBar; + if (bar.Index() == 0) + { + // + result = sBar.Init( + bar.symbol, + bar.period, + bar.Index() + 1 // + ); + if (!result) + { + // + sBar.Clean(); + return result; + } + } + else + { + sBar = bar; + } + + // + ENUM_X_DIRECTION iDir; + result = mBarAnalyser.IsRejected( + sBar, + iDir, + mRejectionForceBarType, + mRejectionForceFiboPressure // + ); + + // + result = result && + HasDirection(iDir); + if (!result) + { + // + sBar.Clean(); + return result; + } + + // + bool isBullish = IsBullish(iDir); + bool isBearish = IsBearish(iDir); + + // + ENUM_XPOIS type = + isBullish + ? X_POI_MOMENTUM_BAR + : X_POI_MOMENTUM_BAR; + + // + // Swing Object ... + XCRejectionBar *rejection; + rejection = new XCRejectionBar(); + result = rejection.Init( + sBar // + ); + if (!result) + { + // + sBar.Clean(); + return result; + } + + // + int idx = FindIndex( + rejection, + mRejections // + ); + result = !IsValidIndex(idx); + if (!result) + { + // + sBar.Clean(); + return result; + } + + // + Add( + rejection, + mRejections // + ); + + // + if (isBullish) + { + // + Add( + rejection, + mBullishRejections // + ); + } + + // + if (isBearish) + { + // + Add( + rejection, + mBearishRejections // + ); + } + + // + state = + isBullish + ? X_BULLISH_REJECTION_BAR_DETECTED + : X_BEARISH_REJECTION_BAR_DETECTED; + + // + return result; + } + + /** + * Detect Pullback ... + * + * @param bar: XOHCL instance ... + * @param state: ENUM_XPOI_EVENTS member ... + * + * @return ( bool ) + */ + bool DetetctPullback( + XOHCL &bar, + ENUM_XPOI_EVENTS &state // + ) + { + // + bool result = false; + + // + state = X_POI_EVENT_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL sBar; + if (bar.Index() == 0) + { + // + result = sBar.Init( + bar.symbol, + bar.period, + bar.Index() + 1 // + ); + if (!result) + { + // + sBar.Clean(); + return result; + } + } + else + { + sBar = bar; + } + + // + ENUM_X_DIRECTION iDir; + result = mBarAnalyser.IsPullback( + sBar, + iDir, + mPullbackRange, + true // Force Body ... + ); + if (!result) + { + // + sBar.Clean(); + return result; + } + + // + bool isBullish = IsBullish(iDir); + bool isBearish = IsBearish(iDir); + result = isBullish || + isBearish; + if (!result) + { + // + sBar.Clean(); + return result; + } + + // + XOHCL fromBar; + result = fromBar.Init( + bar.symbol, + bar.period, + sBar.Index() + mPullbackRange // + ); + if (!result) + { + // + fromBar.Clean(); + return result; + } + + // + XBoxZone box; + + // + box.dir = iDir; + box.to = sBar.time; + box.from = fromBar.time; + box.symbol = fromBar.symbol; + box.period = fromBar.period; + box.lower = MathMin(sBar.low, fromBar.low); + box.upper = MathMax(sBar.high, fromBar.high); + box.type = ToString(iDir) + "_XPullBK" + box.symbol + "_" + ToString(box.period); + + // + result = box.IsValid(); + if (result) + { + // + AddRef( + box, + mPullbacks // + ); + + // + if (isBullish) + { + // + AddRef( + box, + mBullishPullbacks // + ); + } + + // + if (isBearish) + { + // + AddRef( + box, + mBearishPullbacks // + ); + } + + // + state = + isBullish + ? X_BULLISH_PULLBACK_DETECTED + : X_BEARISH_PULLBACK_DETECTED; + } + + // + // Cleanup Resources ... + + // + box.Clean(); + sBar.Clean(); + fromBar.Clean(); + + // + return result; + } + + /** + * Detect Consolidation Zones ... + * + * @param bar: XOHCL instance ... + * @param state: ENUM_XPOI_EVENTS member ... + * + * @return ( bool ) + */ + bool DetectConsolidationZone( + XOHCL &bar, + ENUM_XPOI_EVENTS &state // + ) + { + // + bool result = false; + + // + state = X_POI_EVENT_NONE; + + // + XOHCL sBar; + if (bar.Index() == 0) + { + // + result = sBar.Init( + bar.symbol, + bar.period, + bar.Index() + 1 // + ); + if (!result) + { + // + sBar.Clean(); + return result; + } + } + else + { + sBar = bar; + } + + // + XConsolidationZone cZone; + result = mBarAnalyser.HasConsolidationZone( + sBar, + cZone, + mConsolidationZoneMinLoopback, + mConsolidationZoneRangeInPoint, + mConsolidationZonesUpperAppliedTo, + mConsolidationZonesLowerAppliedTo // + ); + if (!result) + { + // + sBar.Clean(); + cZone.Clean(); + + // + return result; + } + + // + // Add ... + + // + bool isBullish = IsBullish(cZone.dir); + bool isBearish = IsBearish(cZone.dir); + + // + int idx = FindIndex( + cZone, + mConsolidationZones // + ); + result = !IsValidIndex(idx); + if (!result) + { + // + sBar.Clean(); + cZone.Clean(); + + // + return result; + } + + // + AddRef( + cZone, + mConsolidationZones // + ); + + // + if (isBullish) + { + // + AddRef( + cZone, + mBullishConsolidationZones // + ); + } + + // + if (isBearish) + { + // + AddRef( + cZone, + mBearishConsolidationZones // + ); + } + + // + state = + IsBullish(cZone.dir) + ? X_BULLISH_CONSOLIDATION_ZONE_DETECTED + : X_BEARISH_CONSOLIDATION_ZONE_DETECTED; + + // + cZone.Clean(); + + // + return result; + } + + /** + * Detect Sharp Change ... + * + * @param bar: XOHCL instance ... + * @param state: ENUM_XPOI_EVENTS member ... + * + * @return ( bool ) + */ + bool DetectSharp( + XOHCL &bar, + ENUM_XPOI_EVENTS &state // + ) + { + // + bool result = false; + + // + state = X_POI_EVENT_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int sharpRootIDX = -1; + ENUM_X_DIRECTION iDir; + result = mBarAnalyser.IsSharp( + bar, + iDir, + sharpRootIDX, + mSpikePriceType, + mSpikeForcBodyInRange, + mSpikeRangeExtendMultiplier // + ); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(iDir); + bool isBearish = IsBearish(iDir); + + // + XOHCL fromBar; + result = fromBar.Init( + bar.symbol, + bar.period, + sharpRootIDX // + ); + if (!result) + { + // + fromBar.Clean(); + return result; + } + + // + XBoxZone box; + + // + box.dir = iDir; + box.to = bar.time; + box.from = fromBar.time; + box.symbol = fromBar.symbol; + box.period = fromBar.period; + box.type = ToString(iDir) + "_XSharp" + box.symbol + "_" + ToString(box.period); + + // + box.upper = + isBullish + ? bar.high + : fromBar.high; + + // + box.lower = + isBullish + ? fromBar.low + : bar.low; + + // + result = box.IsValid(); + if (result) + { + // + AddRef( + box, + mSharps // + ); + + // + if (isBullish) + { + // + AddRef( + box, + mBullishSharps // + ); + } + + // + if (isBearish) + { + // + AddRef( + box, + mBearishSharps // + ); + } + + // + state = + isBullish + ? X_BULLISH_SHARP_DETECTED + : X_BEARISH_SHARP_DETECTED; + } + + // + // Cleanup Resources ... + + // + box.Clean(); + fromBar.Clean(); + + // + return result; + } + + /** + * Detect Spike ... + * + * @param bar: XOHCL instance ... + * @param state: ENUM_XPOI_EVENTS member ... + * + * @return ( bool ) + */ + bool DetectSpike( + XOHCL &bar, + ENUM_XPOI_EVENTS &state // + ) + { + // + bool result = false; + + // + state = X_POI_EVENT_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int rootIDX = -1; + ENUM_X_DIRECTION iDir; + result = mBarAnalyser.IsSpike( + bar, + iDir, + rootIDX, + mSpikePriceType, + mSpikeForcBodyInRange, + mSpikeRangeExtendMultiplier, + mSpikeSameBars // + ); + if (!result) + { + return result; + } + + // + // Chek Same Bars ... + int sameBarsIndex = -1; + ENUM_X_DIRECTION sameBarsDir; + result = mBarAnalyser.HasSameBars( + bar, + sameBarsDir, + sameBarsIndex, + mSpikeSameBars // + ); + if (!result) + { + return result; + } + + // + // Validate Same Bars Dir and Spike Dir ... + result = iDir == sameBarsDir; + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(iDir); + bool isBearish = IsBearish(iDir); + + // + XOHCL fromBar; + result = fromBar.Init( + bar.symbol, + bar.period, + rootIDX // + ); + if (!result) + { + // + fromBar.Clean(); + return result; + } + + // + XBoxZone box; + + // + box.dir = iDir; + box.to = bar.time; + box.from = fromBar.time; + box.symbol = fromBar.symbol; + box.period = fromBar.period; + box.type = ToString(iDir) + "_XSpike_" + box.symbol + "_" + ToString(box.period); + + // + box.upper = + isBullish + ? bar.high + : fromBar.high; + + // + box.lower = + isBullish + ? fromBar.low + : bar.low; + + // + result = box.IsValid(); + if (result) + { + // + AddRef( + box, + mSpikes // + ); + + // + if (isBullish) + { + // + AddRef( + box, + mBullishSpikes // + ); + } + + // + if (isBearish) + { + // + AddRef( + box, + mBearishSpikes // + ); + } + + // + state = + isBullish + ? X_BULLISH_SPIKE_DETECTED + : X_BEARISH_SPIKE_DETECTED; + } + + // + // Cleanup Resources ... + + // + box.Clean(); + fromBar.Clean(); + + // + return result; + } + + /** + * Detect Support Zone ... + * + * @param bar: XOHCL instance ... + * @param state: ENUM_XPOI_EVENTS member ... + * + * @return ( bool ) + */ + bool DetectSupportZone( + XOHCL &bar, + ENUM_XPOI_EVENTS &state // + ) + { + // + bool result = false; + + // + state = X_POI_EVENT_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL supportBar; + result = mBarAnalyser + .HasSupport( + bar, + supportBar, + mSupResRange // + ); + if (!result) + { + // + supportBar.Clean(); + + // + return result; + } + + // + XCSupportZone *supportZone; + supportZone = new XCSupportZone(); + result = supportZone.Init( + supportBar, + mSupResRange, + mSupResRangeAsStart // Use Range As Start ... + ); + if (!result) + { + // + supportBar.Clean(); + ZeroMemory(supportZone); + + // + return result; + } + + // + // Check Zone Not Activated ... + if (mSupResForceActivation) + { + // + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = supportZone.IsActivated( + X_DIRECTION_BULLISH, + activationBar, + isActivationBarBodyIn, + false, + bar.period // + ); + result = !isActivated; + if (!result) + { + // + supportBar.Clean(); + activationBar.Clean(); + ZeroMemory(supportZone); + + // + return result; + } + + // + activationBar.Clean(); + } + + // + // Add ... + + // + int idx = FindIndex( + supportZone, + mSupportZones // + ); + result = !IsValidIndex(idx); + if (!result) + { + // + supportBar.Clean(); + ZeroMemory(supportZone); + + // + return result; + } + + // + Add( + supportZone, + mSupportZones // + ); + + // + state = X_SUPPORT_ZONE_DETECTED; + + // + supportBar.Clean(); + + // + return result; + } + + /** + * Detect Resistance Zone ... + * + * @param bar: XOHCL instance ... + * @param state: ENUM_XPOI_EVENTS member ... + * + * @return ( bool ) + */ + bool DetectResistanceZone( + XOHCL &bar, + ENUM_XPOI_EVENTS &state // + ) + { + // + bool result = false; + + // + state = X_POI_EVENT_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL resistanceBar; + result = mBarAnalyser + .HasResistance( + bar, + resistanceBar, + mSupResRange // + ); + if (!result) + { + // + resistanceBar.Clean(); + + // + return result; + } + + // + XCResistanceZone *resistanceZone; + resistanceZone = new XCResistanceZone(); + result = resistanceZone.Init( + resistanceBar, + mSupResRange, + mSupResRangeAsStart // Use Range As Start ... + ); + if (!result) + { + // + resistanceBar.Clean(); + ZeroMemory(resistanceZone); + + // + return result; + } + + // + // Check Zone Not Activated ... + if (mSupResForceActivation) + { + // + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = resistanceZone.IsActivated( + X_DIRECTION_BULLISH, + activationBar, + isActivationBarBodyIn, + false, + bar.period // + ); + result = !isActivated; + if (!result) + { + // + resistanceBar.Clean(); + activationBar.Clean(); + ZeroMemory(resistanceZone); + + // + return result; + } + + // + activationBar.Clean(); + } + + // + // Add ... + + // + int idx = FindIndex( + resistanceZone, + mResistanceZones // + ); + result = !IsValidIndex(idx); + if (!result) + { + // + resistanceBar.Clean(); + ZeroMemory(resistanceZone); + + // + return result; + } + + // + Add( + resistanceZone, + mResistanceZones // + ); + + // + state = X_RESISTANCE_ZONE_DETECTED; + + // + resistanceBar.Clean(); + + // + return result; + } + + /** + * Detect Supply Zone ... + * + * @param bar: XOHCL instance ... + * @param state: ENUM_XPOI_EVENTS member ... + * + * @return ( bool ) + */ + bool DetectSupplyZone( + XOHCL &bar, + ENUM_XPOI_EVENTS &state // + ) + { + // + bool result = false; + + // + state = X_POI_EVENT_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int mSupDemRange = mSupResRange * 2; + + // + XOHCL supplyBar; + result = mBarAnalyser + .HasResistance( + bar, + supplyBar, + mSupDemRange // + ); + if (!result) + { + // + supplyBar.Clean(); + + // + return result; + } + + // + XCSupplyZone *supplyZone; + supplyZone = new XCSupplyZone(); + result = supplyZone.Init( + supplyBar, + mSupDemRange, + mSupResRangeAsStart // Use Range As Start ... + ); + if (!result) + { + // + supplyBar.Clean(); + ZeroMemory(supplyZone); + + // + return result; + } + + // + // Check Zone Not Activated ... + if (mSupResForceActivation) + { + // + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = supplyZone.IsActivated( + X_DIRECTION_BULLISH, + activationBar, + isActivationBarBodyIn, + false, + bar.period // + ); + result = !isActivated; + if (!result) + { + // + supplyBar.Clean(); + activationBar.Clean(); + ZeroMemory(supplyZone); + + // + return result; + } + + // + activationBar.Clean(); + } + + // + // Add ... + + // + int idx = FindIndex( + supplyZone, + mSupplyZones // + ); + result = !IsValidIndex(idx); + if (!result) + { + // + supplyBar.Clean(); + ZeroMemory(supplyZone); + + // + return result; + } + + // + Add( + supplyZone, + mSupplyZones // + ); + + // + state = X_SUPPLY_ZONE_DETECTED; + + // + supplyBar.Clean(); + + // + return result; + } + + /** + * Detect Demand Zone ... + * + * @param bar: XOHCL instance ... + * @param state: ENUM_XPOI_EVENTS member ... + * + * @return ( bool ) + */ + bool DetectDemandZone( + XOHCL &bar, + ENUM_XPOI_EVENTS &state // + ) + { + // + bool result = false; + + // + state = X_POI_EVENT_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int mSupDemRange = mSupResRange * 2; + + // + XOHCL demandBar; + result = mBarAnalyser + .HasSupport( + bar, + demandBar, + mSupDemRange // + ); + if (!result) + { + // + demandBar.Clean(); + + // + return result; + } + + // + XCDemandZone *demandZone; + demandZone = new XCDemandZone(); + result = demandZone.Init( + demandBar, + mSupDemRange, + mSupResRangeAsStart // Use Range As Start ... + ); + if (!result) + { + // + demandBar.Clean(); + ZeroMemory(demandZone); + + // + return result; + } + + // + // Check Zone Not Activated ... + if (mSupResForceActivation) + { + // + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = demandZone.IsActivated( + X_DIRECTION_BULLISH, + activationBar, + isActivationBarBodyIn, + false, + bar.period // + ); + result = !isActivated; + if (!result) + { + // + demandBar.Clean(); + activationBar.Clean(); + ZeroMemory(demandZone); + + // + return result; + } + + // + activationBar.Clean(); + } + + // + // Add ... + + // + int idx = FindIndex( + demandZone, + mDemandZones // + ); + result = !IsValidIndex(idx); + if (!result) + { + // + demandBar.Clean(); + ZeroMemory(demandZone); + + // + return result; + } + + // + Add( + demandZone, + mDemandZones // + ); + + // + state = X_DEMAND_ZONE_DETECTED; + + // + demandBar.Clean(); + + // + return result; + } + + /** + * Detect Fair Value Gaps ... + * + * @param bar: XOHCL instance ... + * @param state: ENUM_XPOI_EVENTS member ... + * + * @return ( bool ) + */ + bool DetectFairValueGap( + XOHCL &bar, + ENUM_XPOI_EVENTS &state // + ) + { + // + bool result = false; + + // + state = X_POI_EVENT_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL fvgStartBar; + XOHCL fvgEndBar; + ENUM_X_DIRECTION fvgDir; + result = mBarAnalyser.HasFairValueGap( + bar, + fvgStartBar, + fvgEndBar, + fvgDir, + mFairValueGapSameBars // + ); + if (!result) + { + // + fvgEndBar.Clean(); + fvgStartBar.Clean(); + + // + return result; + } + + // + XCFVG *fvg; + fvg = new XCFVG(); + result = fvg.Init( + fvgStartBar, + fvgEndBar, + fvgDir // + ); + if (!result) + { + // + ZeroMemory(fvg); + fvgEndBar.Clean(); + fvgStartBar.Clean(); + + // + return result; + } + + // + bool isBullish = IsBullish(fvgDir); + bool isBearish = IsBearish(fvgDir); + + // + // Check Zone Not Activated ... + if (mFairValueGapForceActivation) + { + // + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = fvg.IsActivated( + fvgDir, + activationBar, + isActivationBarBodyIn, + false, + bar.period // + ); + result = !isActivated; + if (!result) + { + // + ZeroMemory(fvg); + fvgEndBar.Clean(); + fvgStartBar.Clean(); + activationBar.Clean(); + + // + return result; + } + + // + activationBar.Clean(); + } + + // + int idx = FindIndex( + fvg, + mFairValueGaps // + ); + result = !IsValidIndex(idx); + if (!result) + { + // + ZeroMemory(fvg); + fvgEndBar.Clean(); + fvgStartBar.Clean(); + + // + return result; + } + + // + Add( + fvg, + mFairValueGaps // + ); + + // + if (isBullish) + { + // + Add( + fvg, + mBullishFairValueGaps // + ); + } + + // + if (isBearish) + { + // + Add( + fvg, + mBearishFairValueGaps // + ); + } + + // + state = + isBullish + ? X_BULLISH_FVG_DETECTED + : X_BEARISH_FVG_DETECTED; + + // + fvgEndBar.Clean(); + fvgStartBar.Clean(); + + // + return result; + } + + /** + * Detect Order Blocks ... + * + * @param bar: XOHCL instance ... + * @param state: ENUM_XPOI_EVENTS member ... + * + * @return ( bool ) + */ + bool DetectOrderBlock( + XOHCL &bar, + ENUM_XPOI_EVENTS &state // + ) + { + // + bool result = false; + + // + state = X_POI_EVENT_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL obBar; + ENUM_X_DIRECTION obDir; + result = mBarAnalyser.HasOrderBlock( + bar, + obBar, + obDir, + mOrderBlockSameBars, + mOrderBlockForceSpike, + mOrderBlockForceFairValueGap, + mOrderBlockForceSupportResistance // + ); + if (!result) + { + // + obBar.Clean(); + + // + return result; + } + + // + XCOrderBlock *ob; + ob = new XCOrderBlock(); + result = ob.Init( + obBar, + obDir // + ); + if (!result) + { + // + obBar.Clean(); + ZeroMemory(ob); + + // + return result; + } + + // + bool isBullish = IsBullish(obDir); + bool isBearish = IsBearish(obDir); + + // + // Check Zone Not Activated ... + if (mOrderBlockForceActivation) + { + // + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = ob.IsActivated( + obDir, + activationBar, + isActivationBarBodyIn, + false, + bar.period // + ); + result = !isActivated; + if (!result) + { + // + obBar.Clean(); + activationBar.Clean(); + ZeroMemory(ob); + + // + return result; + } + + // + activationBar.Clean(); + } + + // + int idx = FindIndex( + ob, + mOrderBlocks // + ); + result = !IsValidIndex(idx); + if (!result) + { + // + obBar.Clean(); + ZeroMemory(ob); + + // + return result; + } + + // + Add( + ob, + mOrderBlocks // + ); + + // + if (isBullish) + { + // + Add( + ob, + mBullishOrderBlocks // + ); + } + + // + if (isBearish) + { + // + Add( + ob, + mBearishOrderBlocks // + ); + } + + // + state = + isBullish + ? X_BULLISH_ORDERBLOCK_DETECTED + : X_BEARISH_ORDERBLOCK_DETECTED; + + // + obBar.Clean(); + + // + return result; + } + + // + protected: + // + + /** + * Notify Event Listeners ... + * + * @param event: ENUM_XPOI_EVENTS member, Specified Occured Event ... + * @param param: XCBasePOI implementation, Specified Event Object ... + */ + void NotifyEventListeners( + ENUM_XPOI_EVENTS event, + XCBasePOI *param // + ) + { + // + int count = ArraySize(mEventListeners); + if (!IsValidSize(count)) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + mEventListeners[i]( + event, + param // + ); + } + } + + // + private: + // + + // + // Props ... + string mSymbol; // Market Symbol ... + ENUM_TIMEFRAMES mPeriod; // Market Period ... + XBarTracker mBarTracker; // Market Bar Tracker ... + XCBarAnalyser *mBarAnalyser; // Bar Analyser ... + + // + bool mLock; + + // + int mMaxRequiredPOIs; // Max Allowed Holds POI(s) ... + int maxAllowedLoopbackForInit; // Max Allowed Loopback for POI(s) Detection on Initialization Process ... + + // + TOnPOIEvent mEventListeners[]; // Event Listeners ... + + // + // Swings ... + XCSwing *mSwings[]; // Holds Founded Swing ... + XCSwing *mSwingLows[]; // Holds Founded Swing Lows ... + XCSwing *mSwingHighs[]; // Holds Founded Swing Highs ... + int mSwingRange; // Swing Detection Range ... + + // + // Pullbacks ... + XBoxZone mPullbacks[]; // Holds Founded Pullbacks ... + XBoxZone mBullishPullbacks[]; // Holds Founded Bullish Pullbacks ... + XBoxZone mBearishPullbacks[]; // Holds Founded Bearish Pullbacks ... + int mPullbackRange; // Pullback Detection Range ... + + // + // Momentums ... + XCMomentumBar *mMomentums[]; // Holds Founded Momentum Bars ... + XCMomentumBar *mBullishMomentums[]; // Holds Founded Bullish Momentum Bars ... + XCMomentumBar *mBearishMomentums[]; // Holds Founded Bearish Momentum Bars ... + int mMomentumLoopback; // Momentum Detecting Loopback ... + + // + // Rejections ... + XCRejectionBar *mRejections[]; // Holds Founded Rejection Bars ... + XCRejectionBar *mBullishRejections[]; // Holds Founded Bullish Rejection Bars ... + XCRejectionBar *mBearishRejections[]; // Holds Founded Bearish Rejection Bars ... + bool mRejectionForceBarType; // Rejection Detecting Force Bar Type ... + bool mRejectionForceFiboPressure; // Rejection Detecting Force Fibo Pressure ... + + // + // Consolidation Zones ... + XConsolidationZone mConsolidationZones[]; // Holds Founded Consolidation Zones ... + XConsolidationZone mBullishConsolidationZones[]; // Holds Founded Bullish Consolidation Zones ... + XConsolidationZone mBearishConsolidationZones[]; // Holds Founded Bearish Consolidation Zones ... + int mConsolidationZoneMinLoopback; // Minimum Length of Cnsolidation Zone ... + double mConsolidationZoneRangeInPoint; // Consolidation Zone Range in Point ... + ENUM_X_PRICE mConsolidationZonesLowerAppliedTo; // Consolidation Zone Upper Applied To ... + ENUM_X_PRICE mConsolidationZonesUpperAppliedTo; // Consolidation Zone Lower Applied To ... + + // + // Spike/Sharp Zones ... + XBoxZone mSharps[]; // Holds Founded Sharps ... + XBoxZone mBullishSharps[]; // Holds Founded Bullish Sharps ... + XBoxZone mBearishSharps[]; // Holds Founded Bearish Sharps ... + XBoxZone mSpikes[]; // Holds Founded Spikes ... + XBoxZone mBullishSpikes[]; // Holds Founded Bullish Spikes ... + XBoxZone mBearishSpikes[]; // Holds Founded Bearish Spikes ... + ENUM_X_PRICE mSpikePriceType; // Spike Detection Price Type ... + bool mSpikeForcBodyInRange; // Spike Detection Force Body In Range ... + double mSpikeRangeExtendMultiplier; // Spike Detection Range Extends Multiplier ... + int mSpikeSameBars; // Spike Detection Same Bars ... + + // + // Support and Resistance ... + // Supply and Demand ... + + // + int mSupResRange; // Support and Resistance Detection Range ... + bool mSupResRangeAsStart; // use Support and Resistance Range as Start ... + bool mSupResForceActivation; // Force Activations in Supply/Demand and Support/Resistance Detections ... + + // + XCSupplyZone *mSupplyZones[]; // Holds Detected Supply Zones ... + XCDemandZone *mDemandZones[]; // Holds Detected Demand Zones ... + + // + XCSupportZone *mSupportZones[]; // Holds Detected Support Zones ... + XCResistanceZone *mResistanceZones[]; // Holds Detected Resistance Zones ... + + // + // Fair Value Gaps ... + XCFVG *mFairValueGaps[]; // Holds Founded FairValueGaps ... + XCFVG *mBullishFairValueGaps[]; // Holds Founded Bullish FairValueGaps ... + XCFVG *mBearishFairValueGaps[]; // Holds Founded Bearish FairValueGaps ... + int mFairValueGapSameBars; // FairValueGap Detection Same Bars ... + bool mFairValueGapForceActivation; // FairValueGap Detection Force Check Activation ... + + // + // Order Blocks ... + XCOrderBlock *mOrderBlocks[]; // Holds Founded OrderBlocks ... + XCOrderBlock *mBullishOrderBlocks[]; // Holds Founded Bullish OrderBlocks ... + XCOrderBlock *mBearishOrderBlocks[]; // Holds Founded Bearish OrderBlocks ... + int mOrderBlockSameBars; // OrderBlock Detection Same Bars ... + bool mOrderBlockForceSpike; // Order Blocs Detection Force Spike ... + bool mOrderBlockForceFairValueGap; // Order Blocs Detection Force Fair Value Gaps ... + bool mOrderBlockForceSupportResistance; // Order Blocs Detection Force Support/Resisatnce ... + bool mOrderBlockForceActivation; // Order Blocs Detection Force Check Activation ... + + /** + * Clean All Collections ... + */ + void CleanCollections() + { + // + Clean(mSwings); + Clean(mSwingLows); + Clean(mSwingHighs); + Clean(mMomentums); + Clean(mBullishMomentums); + Clean(mBearishMomentums); + Clean(mRejections); + Clean(mBullishRejections); + Clean(mBearishRejections); + Clean(mConsolidationZones); + Clean(mBullishConsolidationZones); + Clean(mBearishConsolidationZones); + Clean(mSpikes); + Clean(mBullishSpikes); + Clean(mBearishSpikes); + Clean(mSupplyZones); + Clean(mDemandZones); + Clean(mSupportZones); + Clean(mResistanceZones); + Clean(mFairValueGaps); + Clean(mBullishFairValueGaps); + Clean(mBearishFairValueGaps); + Clean(mOrderBlocks); + Clean(mBullishOrderBlocks); + Clean(mBearishOrderBlocks); + } + + /** + * Reverse Collections ... + */ + void ReverseCollections() + { + // + ArrayReverse(mSwings); + ArrayReverse(mSwingLows); + ArrayReverse(mSwingHighs); + ArrayReverse(mMomentums); + ArrayReverse(mBullishMomentums); + ArrayReverse(mBearishMomentums); + ArrayReverse(mRejections); + ArrayReverse(mBullishRejections); + ArrayReverse(mBearishRejections); + ArrayReverse(mConsolidationZones); + ArrayReverse(mBullishConsolidationZones); + ArrayReverse(mBearishConsolidationZones); + ArrayReverse(mSpikes); + ArrayReverse(mBullishSpikes); + ArrayReverse(mBearishSpikes); + ArrayReverse(mSupplyZones); + ArrayReverse(mDemandZones); + ArrayReverse(mSupportZones); + ArrayReverse(mResistanceZones); + ArrayReverse(mFairValueGaps); + ArrayReverse(mBullishFairValueGaps); + ArrayReverse(mBearishFairValueGaps); + ArrayReverse(mOrderBlocks); + ArrayReverse(mBullishOrderBlocks); + ArrayReverse(mBearishOrderBlocks); + } + + /** + * Cleanup Unused Collection Items ... + * + * @param maxAllowed: int, Max Allowed ... + */ + void CleanupUnusedCollections( + int maxAllowed = 0 // + ) + { + // + maxAllowed = MaxRequiredPOIs(); + + // + if (maxAllowed <= 0) + { + return; + } + + // + CleanupArray(mSwings, maxAllowed); + CleanupArray(mSwingLows, maxAllowed); + CleanupArray(mSwingHighs, maxAllowed); + CleanupArray(mMomentums, maxAllowed); + CleanupArray(mBullishMomentums, maxAllowed); + CleanupArray(mBearishMomentums, maxAllowed); + CleanupArray(mRejections, maxAllowed); + CleanupArray(mBullishRejections, maxAllowed); + CleanupArray(mBearishRejections, maxAllowed); + CleanupArray(mConsolidationZones, maxAllowed); + CleanupArray(mBullishConsolidationZones, maxAllowed); + CleanupArray(mBearishConsolidationZones, maxAllowed); + CleanupArray(mSpikes, maxAllowed); + CleanupArray(mBullishSpikes, maxAllowed); + CleanupArray(mBearishSpikes, maxAllowed); + CleanupArray(mSupplyZones, maxAllowed); + CleanupArray(mDemandZones, maxAllowed); + CleanupArray(mSupportZones, maxAllowed); + CleanupArray(mResistanceZones, maxAllowed); + CleanupArray(mFairValueGaps, maxAllowed); + CleanupArray(mBullishFairValueGaps, maxAllowed); + CleanupArray(mBearishFairValueGaps, maxAllowed); + CleanupArray(mOrderBlocks, maxAllowed); + CleanupArray(mBullishOrderBlocks, maxAllowed); + CleanupArray(mBearishOrderBlocks, maxAllowed); + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14040316/Documents/BKP/x-saherelm.x.expert.class.mq5 b/BKPS/14040316/Documents/BKP/x-saherelm.x.expert.class.mq5 new file mode 100644 index 0000000..ef09eb3 --- /dev/null +++ b/BKPS/14040316/Documents/BKP/x-saherelm.x.expert.class.mq5 @@ -0,0 +1,1070 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Base Expert Class +// ------------------------------------------------- +// Name: XCExpert ... +// Description: Base Expert Class ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm Base Expert Class" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.x-guard.class.mq5" +#include "../Classes/x-saherelm.x-trade.class.mq5" +#include "../Classes/x-saherelm.x-volume.class.mq5" + +// +// Definitions ... + +// +// Implementation ... +class XCExpert : public XCBase +{ + // + // public ... + public: + // + // Props ... + + // + // Common ... + long eaMagicNumber; // Magic Number + int eaSlippage; // Slippgae + string eaLogSuffix; // Log Suffix + + // + // Volume ... + ENUM_X_VOLUME_SELECT_TYPE eaVolumeSelect; // Volume Applying Type + double eaStaticVoluem; // Static Volume + double eaDynamicVolumeStepBalance; // Step of Balance for Increase Volume + double eaDynamicVolumeStepVolume; // Step of Volume Increasing + double eaConstantRiskBalance; // Constant Risk Balance per Trade + double eaConstantPercent; // Constant Percent of Balance Per Trade + double eaConstantBalance; // Constant Balance for Calculations + + // + // Management ... + string eaSymbols; // Allowed Trading Symbols + bool eaAllowGuards; // Allow Guards + bool eaAllowTrade; // Allow Trade on Signals + bool eaAllowLongs; // Allow Long Trades + bool eaAllowShorts; // Allow Short Trades + ENUM_XCATBEA_TRADE_RESTRICTION_PERIOD eaRestrictionsPeriod; // Restrictions Period + int eaMaxAllowedTPs; // Max Allowed TP(s) in Restrictions Period + int eaMaxAllowedSLs; // Max Allowed SL(s) in Restrictions Period + int eaMaxAllowedTrades; // Max Allowed Trades in Restrictions Period + int eaMaxAllowedPositions; // Max Allowed Same Time Trades + double eaMaxAllowedSpread; // Max Allowed Spread For Trade + double eaMaxAllowedDrawdownFactor; // Max Allowed DrawDown for Trade + string eaCloseAllOpenTradesAt; // Close All Open Trades per Day At Specified Time + + // + // Alert ... + bool eaEnableAlerts; // Enable Alerts + bool eaSaveAlerts; // Save Alerts + bool eaLogAlerts; // Log Alerts + bool eaMailAlerts; // Mail Alerts + bool eaPushAlerts; // Push Alerts + bool eaTerminalAlerts; // Terminal Alerts + + // + // Time Report ... + bool eaReportNewMonths; // Report New Month + bool eaReportNewWeeks; // Report New Weeks + bool eaReportNewDays; // Report New Days + bool eaReportNewHours; // Report New Hours + bool eaReportTrades; // Report Trades + bool eaReportSignals; // Report Signals + bool eaReportProtector; // Report Protector Actions + bool eaReportRestrictions; // Report Restrictions + bool eaReportAfterTradesBalance; // Report Balance after a Trade Finished + + // + // Collector ... + bool eaSaveTrades; // Save Trades + bool eaSaveSignals; // Save Signals + bool eaSaveWins; // Save Winning Conditions + bool eaSaveLosts; // Save Lost Conditions + bool eaSaveRestrictions; // Save Restriction Reports + + // + // Trade Event Handlers ... + TOnModify OnModifyEventHandler; + TOnStopLoss OnStopLossEventHandler; + TOnForceClose OnForceCloseEventHandler; + TOnTakeProfit OnTakeProfitEventHandler; + TOnPartialClose OnPartialCloseEventHandler; + TOnDealsChanged OnDealsChangedEventHandler; + TOnOrdersChanged OnOrdersChangedEventHandler; + TOnPositionsChanged OnPositionsChangedEventHandler; + TOnTradeStateChanged OnTradeStateChangedEventHandler; + + // + // Requirements ... + + // + XCAlert *eaAlert; // EA Scope Alert Handler ... + XCTrade *eaTrade; // EA Scope Trade Handler ... + XCGuard *eaGuard; // EA Scope Guard Handler ... + XCVolume *eaVolume; // EA Scope Voluem Handler ... + XTimeTracker eaTimeTracker; // EA Scope Time Tracker ... + + // + // Tools / Actions / Handlers ... + + // + // Validators ... + + /** + * Validate Inputs ... + * + * @return ( bool ) + */ + bool ValidateInputs() + { + // + bool result = false; + + // + // Implement all Inputs Validation ... + result = eaMagicNumber > 0 && + eaSignalR2R > 0; + + // + return result; + } + + // + // Expert Advisor Event Handlers ... + + /** + * Handle Initialization of Expert ... + * + * @return ( bool ) + */ + bool HandleOnInit() + { + // + bool result = false; + + // + // Validate Inputs ... + result = ValidateInputs(); + if (!result) + { + return result; + } + + // + // Initialize Alert Handler ... + eaAlert = new XCAlert(); + eaAlert.SetPrefix(eaLogSuffix); + eaAlert.SetLogAlerts(eaLogAlerts); + eaAlert.SetMailAlerts(eaMailAlerts); + eaAlert.SetPushAlerts(eaPushAlerts); + eaAlert.SetEnableAlerts(eaEnableAlerts); + eaAlert.SetTerminalAlerts(eaTerminalAlerts); + + // + // Initialize Volume Manager ... + eaVolume = new XCVolume(); + result = eaVolume.Init( + eaVolumeSelect, + eaStaticVoluem, + eaDynamicVolumeStepBalance, + eaDynamicVolumeStepVolume, + eaConstantRiskBalance, + eaConstantPercent, + eaConstantBalance // + ); + if (!result) + { + return result; + } + + // + // Initialize Trader ... + eaTrade = new XCTrade( + eaSlippage, + eaMagicNumber, + eaMaxAllowedSpread, + eaMaxAllowedPositions, + eaMaxAllowedDrawdownFactor // + ); + eaTrade.AddOnStopLossEventHandler(OnStopLossEventHandler); + eaTrade.AddOnTakeProfitEventHandler(OnTakeProfitEventHandler); + eaTrade.AddOnModifyPositionEventHandler(OnModifyEventHandler); + eaTrade.AddOnDealsChangedEventHandler(OnDealsChangedEventHandler); + eaTrade.AddOnOrdersChangedEventHandler(OnOrdersChangedEventHandler); + eaTrade.AddOnForceClosePositionEventHandler(OnForceCloseEventHandler); + eaTrade.AddOnPartialClosePositionEventHandler(OnPartialCloseEventHandler); + eaTrade.AddOnPositionsChangedEventHandler(OnPositionsChangedEventHandler); + eaTrade.AddOnTradeStateChangedEventHandler(OnTradeStateChangedEventHandler); + + // + // Initialize Guard Handler ... + eaGuard = new XCGuard( + eaAlert, + eaTrade // + ); + + // + // Initialize Trae Manager ... + eaTradeManager = new XCXCATBEATradeManager( + eaAlert, + eaTrade // + ); + + // + eaTradeManager.SaveWins(eaSaveWins); + eaTradeManager.SaveLosts(eaSaveLosts); + eaTradeManager.SaveTrades(eaSaveTrades); + eaTradeManager.SaveSignals(eaSaveSignals); + eaTradeManager.SaveRestrictions(eaSaveRestrictions); + + // + // Enable Force Close At ... + eaTradeManager.SetForceCloseTradesAt(eaCloseAllOpenTradesAt); + + // + // Setting Trade Reports ... + eaTradeManager + .SetTradeReports( + eaReportTrades, + eaReportSignals, + eaReportProtector, + eaReportRestrictions, + eaReportAfterTradesBalance // + ); + + // + // Setting Trade Permissions ... + eaTradeManager + .SetTradePermissions( + eaAllowTrade, + eaAllowLongs, + eaAllowShorts // + ); + + // + // Setting Trade Restrictions ... + eaTradeManager + .SetTradeRestrictions( + eaRestrictionsPeriod, + eaMaxAllowedTPs, + eaMaxAllowedSLs, + eaMaxAllowedTrades // + ); + + // + // Parsing Symbols ... + + // + string symbols[]; + int symbolsCount = 0; + if (IsValid(eaSymbols)) + { + // + symbolsCount = SplitContent( + symbols, + eaSymbols, + "," // + ); + } + + // + // Adding Default Symbol, if eaSymbols not Filled ... + if (!HasChild(symbols)) + { + // + Add( + _Symbol, + symbols // + ); + + // + symbolsCount = ArraySize(symbols); + } + bool hasSymbols = HasChild(symbols); + + // + // Initializing Sessions ... + string sessions[]; + int sessionsCount = 0; + bool hasSession = IsValid(eaSessions); + if (hasSession) + { + // + // Extract Per Symbol Sessions ... + sessionsCount = SplitContent( + sessions, + eaSessions, + "," // + ); + + // + // Try to Extract Start and End Times Series ... + hasSession = IsValidSize(sessionsCount); + if (hasSession) + { + // + // Iterate Sessions ... + for (int i = 0; i < sessionsCount; i++) + { + // + // Ignore unused Cases and Extracts only Content ... + string iSessionDescriptorStr = ExtractString(sessions[i]); + bool isInited = IsValid(iSessionDescriptorStr); + if (isInited) + { + // + // Extract Session Descriptor Data ... + string parts[]; + int partsCount = SplitContent( + parts, + iSessionDescriptorStr, + "_" // + ); + isInited = IsValidSize(partsCount) && partsCount == 3; + if (isInited) + { + // + string iName = parts[0]; + string iStart = parts[1]; + string iEnd = parts[2]; + isInited = IsValid(iName) && + IsValid(iStart) && + IsValid(iEnd); + if (isInited) + { + // + // Set Active Session Per Symbols ... + if (hasSymbols) + { + // + for (int j = 0; j < symbolsCount; j++) + { + // + eaTradeManager + .SetTradeSession( + symbols[j], + iStart, + iEnd, + iName // + ); + } + } + } + } + } + } + } + } + + // + // Initialize Signallers ... + if (hasSymbols) + { + // + // Prepare Signaller Inputs ... + XCATBEASignallerInputs iSignallerInputs; + + // + // Common Configs ... + + // + // Provider Name ... + iSignallerInputs.period = _Period; + iSignallerInputs.allowDraws = true; + iSignallerInputs.provider = "XTRGB"; + iSignallerInputs.allowGuards = eaAllowGuards; + iSignallerInputs.riskToRewardRatio = eaSignalR2R; + iSignallerInputs.slATRMultiplier = eaSLATRMultiplier; + + // + // CATB Indicator ... + iSignallerInputs.catbInputs.Default(); + iSignallerInputs.catbInputs.Hide(); + + // + // Make Available all Requirement Buffers of XCATB indicator ... + iSignallerInputs.catbInputs.showPV = false; + iSignallerInputs.catbInputs.showKI = false; + iSignallerInputs.catbInputs.showSar = false; + iSignallerInputs.catbInputs.showTrend = false; + iSignallerInputs.catbInputs.showATRBand = false; + iSignallerInputs.catbInputs.showPVGolden = false; + + // + // Signalling Configurations ... + iSignallerInputs.signallerConfigs.allowSignallingBasedOnConditions = eaAllowSignallingBasedOnConditions; + iSignallerInputs.signallerConfigs.allowSignallingBasedOnTriggerBlocks = eaAllowSignallingBasedOnTriggerBlocks; + iSignallerInputs.signallerConfigs.secondsTriggersSLUsingFirstTriggerBlock = eaSecondsTriggersSLUsingFirstTriggerBlock; + iSignallerInputs.signallerConfigs.applyValidateAndFilterOnSelectInsideOthers = eaApplyValidateAndFilterOnSelectInsideOthers; + iSignallerInputs.signallerConfigs.allowSignallingBasedOnTriggerBlocksInsideOther = eaAllowSignallingBasedOnTriggerBlocksInsideOther; + iSignallerInputs.signallerConfigs.allowSignallingConditions1 = eaAllowSignallingConditions1; + iSignallerInputs.signallerConfigs.allowSignallingConditions2 = eaAllowSignallingConditions2; + iSignallerInputs.signallerConfigs.allowSignallingConditions3 = eaAllowSignallingConditions3; + iSignallerInputs.signallerConfigs.allowSignallingConditions4 = eaAllowSignallingConditions4; + iSignallerInputs.signallerConfigs.allowSignallingConditions5 = eaAllowSignallingConditions5; + iSignallerInputs.signallerConfigs.allowSignallingConditions6 = eaAllowSignallingConditions6; + // + // Prepare Trigger Block Validations ... + + // + iSignallerInputs.validations.forceHasSwing = eaForceHasSwing; + iSignallerInputs.validations.forceOBBarType = eaForceOBBarType; + iSignallerInputs.validations.minRequiredOBBar = eaMinRequiredOBBar; + iSignallerInputs.validations.forceFVGBarType = eaForceFVGBarType; + iSignallerInputs.validations.liquidityLoopback = eaLiquidityLoopback; + iSignallerInputs.validations.maxAllowedRange = eaMaxAllowedRange; + iSignallerInputs.validations.minAllowedRange = eaMinAllowedRange; + iSignallerInputs.validations.forceHasFLiquidity = eaForceHasFLiquidity; + iSignallerInputs.validations.forceHasRLiquidity = eaForceHasRLiquidity; + iSignallerInputs.validations.validateGapSequence = eaValidateGapSequence; + iSignallerInputs.validations.minAllowedBlockLength = eaMinAllowedBlockLength; + iSignallerInputs.validations.validateBlockEdgeBreakout = eaValidateBlockEdgeBreakout; + + // + // Prepare Trigger Block Filters ... + + // + iSignallerInputs.filters.filterBasedOnPV = eaFilterBasedOnPV; + iSignallerInputs.filters.bosLoopback = eaBosLoopback; + + // + iSignallerInputs.filters.filterBasedOnSar = eaFilterBasedOnSar; + iSignallerInputs.filters.forceSarSwitched = eaForceSarSwitched; + iSignallerInputs.filters.forceSarOnBothSide = eaForceSarOnBothSide; + iSignallerInputs.filters.forceSarHasBreakout = eaForceSarHasBreakout; + iSignallerInputs.filters.forceSarHasReversalSide = eaForceSarHasReversalSide; + + // + iSignallerInputs.filters.filterBasedOnRSI = eaFilterBasedOnRSI; + iSignallerInputs.filters.forceHasRSITrending = eaForceHasRSITrending; + iSignallerInputs.filters.forceHasRSIVPattern = eaForceHasRSIVPattern; + iSignallerInputs.filters.forceHasRSICrossing = eaForceHasRSICrossing; + + // + iSignallerInputs.filters.filterBasedOnADX = eaFilterBasedOnADX; + iSignallerInputs.filters.forceHasADXTrending = eaForceHasADXTrending; + iSignallerInputs.filters.forceHasADXCrossing = eaForceHasADXCrossing; + + // + iSignallerInputs.filters.filterBasedOnATR = eaFilterBasedOnATR; + iSignallerInputs.filters.forceHasATRTrending = eaForceHasATRTrending; + iSignallerInputs.filters.forceHasATRBreakout = eaForceHasATRBreakout; + + // + iSignallerInputs.filters.filterBasedOnTrend = eaFilterBasedOnTrend; + iSignallerInputs.filters.forceHasTrendDir = eaForceHasTrendDir; + iSignallerInputs.filters.forceHasTrendPlace = eaForceHasTrendPlace; + iSignallerInputs.filters.forceHasTrendChange = eaForceHasTrendChange; + iSignallerInputs.filters.forceHasTrendTrending = eaForceHasTrendTrending; + iSignallerInputs.filters.forceHasTrendRejection = eaForceHasTrendRejection; + iSignallerInputs.filters.forceHasTrendLineInside = eaForceHasTrendLineInside; + iSignallerInputs.filters.forceHasTrendDirOnBothSide = eaForceHasTrendDirOnBothSide; + + // + iSignallerInputs.filters.filterBasedOnKI = eaFilterBasedOnKI; + iSignallerInputs.filters.filterBasedOnDelta = eaFilterBasedOnDelta; + iSignallerInputs.filters.filterBasedOnVolume = eaFilterBasedOnVolume; + iSignallerInputs.filters.filterBasedOnSignalBar = eaFilterBasedOnSignalBar; + iSignallerInputs.filters.filterBasedOnHKSignalBar = eaFilterBasedOnHKSignalBar; + + // + // Loop through Symbols and Initialize Signaller + // for it, then Attached it to eaSignallers ... + for (int i = 0; i < symbolsCount; i++) + { + // + iSignallerInputs.symbol = symbols[i]; + if (iSignallerInputs.IsValid()) + { + // + // Initialize Signaller ... + XCXCATBEASignaller *iSignaller = new XCXCATBEASignaller(iSignallerInputs); + + // + // Add it to the Signallers List ... + Add( + iSignaller, + eaSignallers // + ); + + // + ZeroMemory(iSignaller); + } + } + + // + // Cleanup Resources ... + iSignallerInputs.Clean(); + } + + // + // since atleast one Signaller must + // exists to Expert works ... + // we check it as Last Step ... + result = hasSymbols && + HasChild(eaSignallers); + if (result) + { + // + string message = "Initialized Successfully ..."; + eaAlert.SendAlert(message); + } + else + { + // + string message = "Initialization Failed ..."; + eaAlert.SendAlert(message); + } + + // + return result; + } + + /** + * Handle De Initialization of Expert ... + */ + void HandleOnDeInit() + { + // + delete eaTrade; + ZeroMemory(eaTrade); + + // + delete eaGuard; + ZeroMemory(eaGuard); + + // + delete eaVolume; + ZeroMemory(eaVolume); + + // + eaTimeTracker.Clean(); + + // + Clean(eaSignallers); + + // + delete eaTradeManager; + ZeroMemory(eaTradeManager); + + // + string message = "DeInitialized Successfully ..."; + eaAlert.SendAlert(message); + + // + delete eaAlert; + ZeroMemory(eaAlert); + } + + /** + * Handle Tick ... + */ + void HandleOnTick() + { + // + // Time Report Handling ... + HandleTimeReport(); + + // + // Position Management / Protections Handling ... + eaTradeManager.Manage(); + + // + // Check Signallers Registered ... + bool has = HasChild(eaSignallers); + if (!has) + { + return; + } + + // + // Define Collection of Requirements ... + XGuard guards[]; + XCATBEAStrategyConditions conditions[]; + + // + // Loop through Registered Signallers to Proccess Ticks and + // Collect: + // - Guards; + // - Triggered Conditions; + // - ... + int count = ArraySize(eaSignallers); + for (int i = 0; i < count; i++) + { + // + // Retrieve indexed Signaller ... + XCXCATBEASignaller *iSignaller = eaSignallers[i]; + + // + string iSymbol = iSignaller.GetSymbol(); + string iProvider = iSignaller.GetProvider(); + ENUM_TIMEFRAMES iPeriod = iSignaller.GetPeriod(); + + // + // Now we Have to Check Handle Tick Resoult ... + + // + // Requirements ... + XGuard iGuards[]; // Hold Provided Guards ... + XPosition iPositions[]; // Retrieve Signaller Positions ... + XCATBEAStrategyConditions iConditions; // Recieve Triggered Conditions ... + + // + // Check Active Session ... + bool isActiveSession = eaTradeManager.IsActiveSession(iSymbol); + + // + // Reading Signaller Positions ... + eaTradeManager.GetPositions( + iPositions, + iSymbol, + iProvider, + iPeriod // + ); + + // + // Processing Tick for Signaller ... + iSignaller.ProcessTick( + iPositions, + iGuards, + iConditions, + isActiveSession // + ); + + // + // Check Results ... + has = HasChild(iGuards); + if (has) + { + // + Copy( + iGuards, + guards, + false // Force Clean ... + ); + } + + // + // Check Triggered Conditions ... + has = iConditions.IsValid() && + iConditions.IsSetuped() && + iConditions.CanTrigger(); + if (has) + { + // + AddRef( + iConditions, + conditions // + ); + } + + // + // Cleanup Resources ... + Clean(iGuards); + Clean(iPositions); + iConditions.Clean(); + } + + // + // Do Actions Based on Provided Info ... + + // + // Guards ... + has = HasChild(guards); + if (has) + { + // + // Handle Guards Firing ... + eaGuard.DoGuards(guards); + } + + // + // Triggers ... + has = HasChild(conditions); + if (has) + { + // + // Handle Conditions Triggering ... + TriggerConditions(conditions); + } + + // + // Cleanup Resources ... + + // + Clean(guards); + Clean(conditions); + } + + /** + * Handle Trade ... + */ + void HandleOnTrade() + { + } + + /** + * Handle Timer ... + */ + void HandleOnTimer() + { + } + + /** + * Handle Chart Event ... + * + * @param id: int, Event id ... + * @param lparam: long, Event Long Parameter ... + * @param dparam: double, Event Double Parameter ... + * @param sparam: string, Event String Parameter ... + */ + void HandleOnChartEvent( + const int id, + const long &lparam, + const double &dparam, + const string &sparam // + ) + { + } + + // + // Trade Event Handlers ... + + /** + * Handle Stop Loss Event Triggered ... + * + * @param deal: XDeal instance refrence, provides Triggered Deal info ... + */ + void HandleOnStopLossTriggered(const XDeal &deal) + { + } + + /** + * Handle Take Profit Event Triggered ... + * + * @param deal: XDeal instance refrence, provides Triggered Deal info ... + */ + void HandleOnTakeProfitTriggered(const XDeal &deal) + { + } + + /** + * Handle Position Force Closed Event ... + * + * @param ticket: ulong, triggered Positions ticket ... + * @param position: XPosition instance refrence, Triggered Position ... + * @param comment: string, Comment ... + */ + void HandleOnPositionForceClosed( + const ulong ticket, + const XPosition &position, + const string comment // + ) + { + } + + /** + * Handle Position Modified Event ... + * + * @param ticket: ulong, triggered Positions ticket ... + * @param profit: double, Position Profit ... + * @param comment: string, Comment ... + */ + void HandleOnPositionModified( + const ulong ticket, + const double profit, + const string comment // + ) + { + } + + /** + * Handle Position Partially Closed Event ... + * + * @param ticket: ulong, triggered Positions ticket ... + * @param profit: double, Position Profit ... + * @param comment: string, Comment ... + */ + void HandleOnPositionPartialClosed( + const ulong ticket, + const double profit, + const string comment // + ) + { + } + + /** + * Handle Deals Changed ... + * + * @param count: int, number of changes ... + * if the count is positive, means new added ... + * if the count is negative, means removed ... + */ + void HandleOnDealsChanged(int count) + { + } + + /** + * Handle Orders Changed ... + * + * @param count: int, number of changes ... + * if the count is positive, means new added ... + * if the count is negative, means removed ... + */ + void HandleOnOrdersChanged(int count) + { + } + + /** + * Handle Positions Changed ... + * + * @param count: int, number of changes ... + * if the count is positive, means new added ... + * if the count is negative, means removed ... + */ + void HandleOnPositionsChanged(int count) + { + } + + /** + * Handle all Trades States Changed Event ... + * + * @param state: XOnTradeHandlerState instance refrence, Changed Trade State data ... + */ + void HandleOnTradeStateChanged(const XOnTradeHandlerState &state) + { + } + + // + // protected ... + protected: + // + + /** + * Report Time Changes based on Given Configurations ... + */ + void HandleTimeReport() + { + // + if (eaAlert == NULL) + { + return; + } + + // + // Monthly Report .... + if (eaReportNewMonths && + eaTimeTracker.IsNewMonth()) + { + // + string msg = "New Month ..."; + + // + eaAlert.SendAlert(msg); + } + + // + // Weekly Report .... + if (eaReportNewWeeks && + eaTimeTracker.IsNewWeek()) + { + // + string msg = "New Week ..."; + + // + eaAlert.SendAlert(msg); + } + + // + // Daily Report .... + if (eaReportNewDays && + eaTimeTracker.IsNewDay()) + { + // + string msg = "New Day ..."; + + // + eaAlert.SendAlert(msg); + } + + // + // Hourly Report .... + if (eaReportNewHours && + eaTimeTracker.IsNewHour()) + { + // + string msg = "New Hour ..."; + + // + eaAlert.SendAlert(msg); + } + } + + /** + * Update Signal Targets ... + */ + void UpdateSignalTargets(XSignal &signal) + { + // + bool has = signal.IsValid(); + if (!has) + { + return; + } + + // + // Clean Signal Targets ... + Clean(signal.targets); + + // + // Calculate Requirements ... + double r2r = eaSignalR2R > 0 + ? eaSignalR2R + : 1; + double risk = signal.GetRisk(); + double reward = risk * r2r; + + // + double isLong = IsLong(signal.type); + + // + // Handling Signal TP ... + signal.tp = + isLong + ? signal.entry + reward + : signal.entry - reward; + + // + // Try to Apply Money Management ... + + // + // Sort Targets ... + ENUM_X_DIRECTION sortingDir = + isLong + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + ApplySortOnTargets( + sortingDir, + signal.targets // + ); + } + + /** + * Convert a Triggered Conditions to Signal and + * Execute it ... + */ + void TriggerConditions(XCATBEAStrategyConditions &conditions[]) + { + // + int count = 0; + bool has = false; + + // + has = HasChild(conditions); + if (!has) + { + return; + } + + // + count = ArraySize(conditions); + for (int i = 0; i < count; i++) + { + // + // Retrieve Indexed Conditions ... + XCATBEAStrategyConditions iConditions = conditions[i]; + + // + // Define Signal Structure ... + XSignal iSignal; + + // + // Check Conditions is Valid Triggered Conditions ... + has = + iConditions.IsValid() && + iConditions.IsSetuped() && + iConditions.CanTrigger(); + if (has) + { + // + // Preparing Signal ... + has = ToSignal( + iSignal, + iConditions // + ); + } + + // + // Validate Signal ... + has = iSignal.IsValid(); + if (has) + { + // + // Retrieve Signal Type ... + bool isLong = IsLong(iSignal.type); + + // + // Update Signal Entry ... + iSignal.entry = GetEntry( + iSignal.symbol, + iSignal.type // + ); + + // + // Update Signal Targets ... + UpdateSignalTargets(iSignal); + + // + // Handle Volume Management ... + double iVolume = eaVolume.CalculateVolume(iSignal); + has = iVolume > X_MIN_VOLUME && + iVolume != iSignal.volume; + if (has) + { + iSignal.volume = iVolume; + } + + // + // Execute Signal ... + has = eaTradeManager.Execute( + iSignal, + iConditions // + ); + } + + // + // Cleanup Resources ... + + // + iSignal.Clean(); + iConditions.Clean(); + } + } + + // + // private ... + private: + // + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14040316/Documents/BKP/xcatb.test.ea.mq5 b/BKPS/14040316/Documents/BKP/xcatb.test.ea.mq5 new file mode 100644 index 0000000..6bdc6fa --- /dev/null +++ b/BKPS/14040316/Documents/BKP/xcatb.test.ea.mq5 @@ -0,0 +1,1181 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center XCATB MQL5 Expert Advisor +// ------------------------------------------------- +// Name: XCAEA +// Description: an Exper Advisor which used XCATB +// +// 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 "EA based on X121 XCATB indicator" +#property strict + +// +// Include Common Library ... +#include "../Classes/x-saherelm.x-guard.class.mq5" +#include "../Classes/x-saherelm.x-volume.class.mq5" +#include "../XCATBEA/Classes/xcatbea.signaller.class.mq5" +#include "../XCATBEA/Classes/xcatbea.x-trade.manager.class.mq5" + +// +#define ShortName "XCATBEA" + +// +// Inputs ... + +// +// Common ... +input group "Common"; +input long eaMagicNumber = 1694056; // Magic Number +input int eaSlippage = 10; // Slippgae +input string eaLogSuffix = ""; // Log Suffix + +// +// Detector ... +input group "Detector"; + +// +// Validating ... +input group "Validations"; +input bool eaForceHasSwing = false; // Force Block to Has Propper Swing +input bool eaForceOBBarType = false; // Force Order Block to Has InDirectional Bars +input int eaMinRequiredOBBar = 0; // Min Required OB Bar +input bool eaForceFVGBarType = false; // Force Fair Value Gaps Bars Type +input int eaLiquidityLoopback = 0; // Liquidity Detection Loopback +input double eaMaxAllowedRange = 0.0; // Max Allowed Order Block Range +input double eaMinAllowedRange = 0.0; // Min Allowed Order Block Range +input bool eaForceHasFLiquidity = false; // Force Order Block To Has Reversal Liquidity +input bool eaForceHasRLiquidity = false; // Force Order Block to Has Following Liquidity +input bool eaValidateGapSequence = false; // Validate Fair Value Gaps Bar Sequences +input int eaMinAllowedBlockLength = 0; // Min Allowed Block Length +input bool eaValidateBlockEdgeBreakout = false; // Validate Order Block Edge Breakeout + +// +// Filtering ... +input group "Filters"; +input bool eaFilterBasedOnKI = false; // Filter Based On KI Flats +input bool eaFilterBasedOnPV = false; // Filter Based On PV +input int eaBosLoopback = 0; // PV Based Filtering BOS Lookup +input bool eaFilterBasedOnSar = false; // Filter Based On SAR +input bool eaForceSarSwitched = false; // SAR Switched on Sides for Filtering +input bool eaForceSarOnBothSide = false; // SAR Check on Both Sides for Filtering +input bool eaForceSarHasBreakout = false; // SAR Must Breakout +input bool eaForceSarHasReversalSide = false; // SAR Must Has Reversal Direction +input bool eaFilterBasedOnRSI = false; // Filter Based On RSI +input bool eaForceHasRSITrending = false; // RSI Must Has V Trending +input bool eaForceHasRSIVPattern = false; // RSI Must Has Pattern +input bool eaForceHasRSICrossing = false; // RSI Must Has Crossing Levels +input bool eaFilterBasedOnADX = false; // Filter Based On ADX +input bool eaForceHasADXTrending = false; // ADX Must Has Trending +input bool eaForceHasADXCrossing = false; // ADX Must Has Crossing +DI/-DI +input bool eaFilterBasedOnATR = false; // Filter Based On ATR +input bool eaForceHasATRTrending = false; // ATR Must Has Trending +input bool eaForceHasATRBreakout = false; // ATR Must Has Breakout +input bool eaFilterBasedOnTrend = false; // Filter Based On Trend +input bool eaForceHasTrendDir = false; // TREND Must Has Following Direction +input bool eaForceHasTrendPlace = false; // TREND Place Based Filtering +input bool eaForceHasTrendChange = false; // TREND Change Filtering +input bool eaForceHasTrendTrending = false; // TREND Must Has Trending +input bool eaForceHasTrendRejection = false; // TREND Line Must Rejected +input bool eaForceHasTrendLineInside = false; // TREND Line has Inside +input bool eaForceHasTrendDirOnBothSide = false; // TREND Must Has Following Direction in Both Side +input bool eaFilterBasedOnDelta = false; // Filter Based On Delta +input bool eaFilterBasedOnVolume = false; // Filter Based On Volume +input bool eaFilterBasedOnSignalBar = false; // Filter Based on Signal Bar +input bool eaFilterBasedOnHKSignalBar = false; // Filter Based On HK Signal Bar + +// +// Signal ... +input group "Signal"; +input int eaSignalR2R = 2; // Risk Reward Ratio +input double eaSLATRMultiplier = 0; // ATR Multiplier for SL +input bool eaAllowSignallingBasedOnConditions; // Signalling Based on Market Conditions +input bool eaAllowSignallingBasedOnTriggerBlocks; // Signalling Based on Trigger Blocks +input bool eaAllowSignallingBasedOnTriggerBlocksInsideOther; // Signalling Based on Trigger Blocks Seccond inputs +input bool eaSecondsTriggersSLUsingFirstTriggerBlock; // Use First Trigger Block for SL of Seconds Trigger Block Signalss +input bool eaApplyValidateAndFilterOnSelectInsideOthers; // Select Trigger Blocks by Applying Validations and Filterss +input bool eaAllowSignallingConditions1; // Allow Market Conditions Signaller to Using Sar Signals +input bool eaAllowSignallingConditions2; // Allow Market Conditions Signaller to Using Trend Signals +input bool eaAllowSignallingConditions3; // Allow Market Conditions Signaller to Using Delta Signals +input bool eaAllowSignallingConditions4; // Allow Market Conditions Signaller to Using Volume Signals +input bool eaAllowSignallingConditions5; // Allow Market Conditions Signaller to Using Signal Bar Signals +input bool eaAllowSignallingConditions6; // Allow Market Conditions Signaller to Using HK Signal Bar Signals + +// +// Volume ... +input group "Volume"; +input ENUM_X_VOLUME_SELECT_TYPE eaVolumeSelect = X_VOLUME_EQUITY; // Volume Applying Type +input double eaStaticVoluem = 0.0; // Static Volume +input double eaDynamicVolumeStepBalance = 0.0; // Step of Balance for Increase Volume +input double eaDynamicVolumeStepVolume = X_MIN_VOLUME; // Step of Volume Increasing +input double eaConstantRiskBalance = 0.0; // Constant Risk Balance per Trade +input double eaConstantPercent = 0.5; // Constant Percent of Balance Per Trade +input double eaConstantBalance = 0.0; // Constant Balance for Calculations + +// +// Management ... +// eaSessions => (ST_04:00_08:30),(TL_10:30_12:00),(NY_16:00_20:00) +input group "Management"; +input bool eaAllowGuards = false; // Allow Guards +input bool eaAllowTrade = true; // Allow Trade on Signals +input bool eaAllowLongs = true; // Allow Long Trades +input bool eaAllowShorts = true; // Allow Short Trades +input string eaSessions = ""; // Active Sessions +input ENUM_XCATBEA_TRADE_RESTRICTION_PERIOD eaRestrictionsPeriod = XCATBEA_TRADE_RESTRICATION_NONE; // Restrictions Period +input int eaMaxAllowedTPs = 0; // Max Allowed TP(s) in Restrictions Period +input int eaMaxAllowedSLs = 0; // Max Allowed SL(s) in Restrictions Period +input int eaMaxAllowedTrades = 0; // Max Allowed Trades in Restrictions Period +input int eaMaxAllowedPositions = 5; // Max Allowed Same Time Trades +input double eaMaxAllowedSpread = 25; // Max Allowed Spread For Trade +input double eaMaxAllowedDrawdownFactor = 0.3; // Max Allowed DrawDown for Trade +input string eaCloseAllOpenTradesAt = ""; // Close All Open Trades per Day At Specified Time + +// +// Alert ... +// Here we Provider All Requirements for +// Configuring Alert Provider ... +input group "Alert"; +input bool eaEnableAlerts = true; // Enable Alerts +input bool eaLogAlerts = true; // Log Alerts +input bool eaMailAlerts = false; // Mail Alerts +input bool eaPushAlerts = true; // Push Alerts +input bool eaTerminalAlerts = false; // Terminal Alerts + +// +// Time Report ... +input group "Reports"; +input bool eaReportNewMonths = false; // Report New Month +input bool eaReportNewWeeks = false; // Report New Weeks +input bool eaReportNewDays = true; // Report New Days +input bool eaReportNewHours = false; // Report New Hours +input bool eaReportTrades = true; // Report Trades +input bool eaReportSignals = true; // Report Signals +input bool eaReportRestrictions = true; // Report Restrictions +input bool eaReportProtector = true; // Report Protector Actions +input bool eaReportAfterTradesBalance = true; // Report Balance after a Trade Finished + +// +// Collector ... +input group "Collector"; +input bool eaSaveTrades = false; // Save Trades +input bool eaSaveSignals = false; // Save Signals +input bool eaSaveWins = false; // Save Winning Conditions +input bool eaSaveLosts = false; // Save Lost Conditions +input bool eaSaveRestrictions = false; // Save Restriction Reports + +// +// Variables ... + +// +XCAlert *eaAlert; // EA Scope Alert Handler ... +XCTrade *eaTrade; // EA Scope Trade Handler ... +XCGuard *eaGuard; // EA Scope Guard Handler ... +string eaTag = ""; // Specified Alert Tag for EA ... +XCVolume *eaVolume; // EA Scope Voluem Handler ... +XTimeTracker eaTimeTracker; // EA Scope Time Tracker ... +XCXCATBEASignaller *eaSignallers[]; // EA Signallers Collection ... +XCXCATBEATradeManager *eaTradeManager; // EA Scope Trade Manager ... + +// +// Event Handlers ... + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs and Required Parameters + // for EA to Works fine ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initial Requirements ... + InitRequirements(); + + // + // Initialize Volume Manger ... + if (!InitVolume()) + { + return INIT_FAILED; + } + + // + 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 + + // + delete eaAlert; + ZeroMemory(eaAlert); + + // + delete eaTrade; + ZeroMemory(eaTrade); + + // + delete eaGuard; + ZeroMemory(eaGuard); + + // + delete eaVolume; + ZeroMemory(eaVolume); + + // + eaTimeTracker.Clean(); + + // + Clean(eaSignallers); + + // + delete eaTradeManager; + ZeroMemory(eaTradeManager); + + // + DestroyTimer(); +} + +// +// On Tick Handler ... +void OnTick() +{ + // + // Time Report Handling ... + HandleTimeReport(); + + // + // Position Management / Protections Handling ... + eaTradeManager.Manage(); + + // + // Count Signallers ... + bool has = HasChild(eaSignallers); + if (!has) + { + return; + } + + // + XGuard guards[]; + XCATBEAStrategyConditions conditions[]; + + // + int count = ArraySize(eaSignallers); + for (int i = 0; i < count; i++) + { + // + // Retrieve indexed Signaller ... + XCXCATBEASignaller *iSignaller = eaSignallers[i]; + + // + string iSymbol = iSignaller.GetSymbol(); + string iProvider = iSignaller.GetProvider(); + ENUM_TIMEFRAMES iPeriod = iSignaller.GetPeriod(); + + // + // Now we Have to Check Handle Tick Resoult ... + + // + // Requirements ... + XGuard iGuards[]; // Hold Provided Guards ... + XPosition iPositions[]; // Retrieve Signaller Positions ... + XCATBEAStrategyConditions iConditions; // Recieve Triggered Conditions ... + + // + // Reading Signaller Positions ... + eaTradeManager.GetPositions( + iPositions, + iSymbol, + iProvider, + iPeriod // + ); + + // + // Processing Tick for Signaller ... + iSignaller.ProcessTick( + iPositions, + iGuards, + iConditions // + ); + + // + // Check Results ... + has = HasChild(iGuards); + if (has) + { + // + Copy( + iGuards, + guards, + false // Force Clean ... + ); + } + + // + // Check Triggered Conditions ... + has = iConditions.IsValid() && + iConditions.IsSetuped() && + iConditions.CanTrigger(); + if (has) + { + // + AddRef( + iConditions, + conditions // + ); + } + + // + // Cleanup Resources ... + Clean(iGuards); + Clean(iPositions); + iConditions.Clean(); + } + + // + // Do Actions Based on Provided Info ... + + // + // Guards ... + has = HasChild(guards); + if (has) + { + // + // Handle Guards Firing ... + eaGuard.DoGuards(guards); + } + + // + // Triggers ... + has = HasChild(conditions); + if (has) + { + // + // Handle Conditions Triggering ... + TriggerConditions(conditions); + } + + // + // Cleanup Resources ... + + // + Clean(guards); + Clean(conditions); +} + +// +// Handle On Trade Event ... +void OnTrade() +{ + eaTrade.HandleOnTrade(); +} + +// +// On Timer ... +void OnTimer() +{ +} + +// +// Chart Event Handler ... +void OnChartEvent( + const int id, + const long &lparam, + const double &dparam, + const string &sparam // +) +{ +} + +// +// Event Listeners ... + +/** + * Handle StopLoss Triggered Positions ... + * + * @param deal: XDeal instance ... + */ +void OnStopLossTriggered(const XDeal &deal) +{ + eaTradeManager.HandleSL(deal); +} + +/** + * Handle Take Profit Triggered Positions ... + * + * @param deal: XDeal instance ... + */ +void OnTakeProfitTriggered(const XDeal &deal) +{ + eaTradeManager.HandleTP(deal); +} + +/** + * Handle Force Close a Position ... + * + * @param ticket: ULONG ... + * @param position: XPosition instance ... + * @param comment: string ... + */ +void OnPositionForceClosed( + const ulong ticket, + const XPosition &position, + const string comment // +) +{ + eaTradeManager.HandleForceClose(position); +} + +/** + * Handle Position Partially Closed Event ... + * + * @param ticket: ULONG ... + * @param profit: double ... + * @param comment: string ... + */ +void OnPositionPartiallyClosed( + const ulong ticket, + const double profit, + const string comment // +) +{ + eaTradeManager.HandlePartiallyClosed( + ticket, + profit, + comment // + ); +} + +/** + * Handle Deals Changes ... + * + * @param count: Integer, Number of Changes ... + */ +void OnDealsChanged(int count) +{ +} + +/** + * Handle Orders Changes ... + * + * @param count: Integer, Number of Changes ... + */ +void OnOrdersChanged(int count) +{ +} + +/** + * Handle Positions Changes ... + * + * @param count: Integer, Number of Changes ... + */ +void OnPositionsChanged(int count) +{ +} + +// +// Custom Functions ... + +/** + * Validate all Inputs of Expert Adviser ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + string errMessage = ""; + + // + bool isCommonValid = ( + // + eaSlippage > 0 && + eaMagicNumber > 0 + // + ); + if (!isCommonValid) + { + // + errMessage += "common configurations error;" + "\n"; + } + + // + result = + // + // Common ... + isCommonValid && + // + // Otere ... + true + // + ; + + // + if (!result) + { + // + // Since here Logger not Initiallized, we Use Raw Print Command ... + Print(ShortName + " Errors: \n", errMessage); + } + + // + return result; +} + +/** + * Initialize Timer ... + * + * @return ( bool ) + */ +bool InitTimer() +{ + // + bool result = false; + + // + // TODO: Initialize Timer if necessary ... + // result = EventSetTimer(1); + // result = EventSetMillisecondTimer(100); + result = true; + + // + return result; +} + +/** + * Destroy Timer ... + */ +void DestroyTimer() +{ + // + // TODO: Use This ... + // EventKillTimer(); +} + +/** + * Initial Volume Manager Class Based on Given Configuration ... + * + * @return ( bool ) + */ +bool InitVolume() +{ + // + bool result = false; + + // + eaVolume = new XCVolume(); + + // + result = eaVolume.Init( + eaVolumeSelect, + eaStaticVoluem, + eaDynamicVolumeStepBalance, + eaDynamicVolumeStepVolume, + eaConstantRiskBalance, + eaConstantPercent, + eaConstantBalance // + ); + + // + return result; +} + +/** + * Initial Requirements of EA ... + */ +void InitRequirements() +{ + // + // Preparing Tags ... + eaTag = + (IsValid(eaLogSuffix) + ? eaLogSuffix + "_" + : "") + + ShortName; + + // + eaAlert = new XCAlert(); + eaAlert.SetPrefix(eaLogSuffix); + eaAlert.SetLogAlerts(eaLogAlerts); + eaAlert.SetMailAlerts(eaMailAlerts); + eaAlert.SetPushAlerts(eaPushAlerts); + eaAlert.SetEnableAlerts(eaEnableAlerts); + eaAlert.SetTerminalAlerts(eaTerminalAlerts); + + // + // EA Trade ... + eaTrade = new XCTrade( + eaSlippage, + eaMagicNumber, + eaMaxAllowedSpread, + eaMaxAllowedPositions, + eaMaxAllowedDrawdownFactor // + ); + + // + eaTrade.AddOnStopLossEventHandler(OnStopLossTriggered); + eaTrade.AddOnTakeProfitEventHandler(OnTakeProfitTriggered); + eaTrade.AddOnForceClosePositionEventHandler(OnPositionForceClosed); + eaTrade.AddOnPartialClosePositionEventHandler(OnPositionPartiallyClosed); + + // + // EA Trae Manager ... + eaTradeManager = new XCXCATBEATradeManager( + eaTrade // + ); + + // + eaTradeManager.SetAlertPrefix(eaTag); + eaTradeManager.SetAlertLogAlerts(eaLogAlerts); + eaTradeManager.SetAlertMailAlerts(eaMailAlerts); + eaTradeManager.SetAlertPushAlerts(eaPushAlerts); + eaTradeManager.SetAlertEnableAlerts(eaEnableAlerts); + eaTradeManager.SetAlertTerminalAlerts(eaTerminalAlerts); + + // + eaTradeManager.SaveWins(eaSaveWins); + eaTradeManager.SaveLosts(eaSaveLosts); + eaTradeManager.SaveTrades(eaSaveTrades); + eaTradeManager.SaveSignals(eaSaveSignals); + eaTradeManager.SaveRestrictions(eaSaveRestrictions); + + // + // Setting Trade Reports ... + eaTradeManager + .SetTradeReports( + eaReportTrades, + eaReportSignals, + eaReportProtector, + eaReportRestrictions, + eaReportAfterTradesBalance // + ); + + // + // Setting Trade Permissions ... + eaTradeManager + .SetTradePermissions( + eaAllowTrade, + eaAllowLongs, + eaAllowShorts // + ); + + // + // Setting Trade Restrictions ... + eaTradeManager + .SetTradeRestrictions( + eaRestrictionsPeriod, + eaMaxAllowedTPs, + eaMaxAllowedSLs, + eaMaxAllowedTrades // + ); + + // + // EA Guard Initialization ... + eaGuard = new XCGuard( + eaTrade // + ); + + // + eaGuard.SetAlertPrefix(eaTag); + eaGuard.SetAlertLogAlerts(eaLogAlerts); + eaGuard.SetAlertMailAlerts(eaMailAlerts); + eaGuard.SetAlertPushAlerts(eaPushAlerts); + eaGuard.SetAlertEnableAlerts(eaEnableAlerts); + eaGuard.SetAlertTerminalAlerts(eaTerminalAlerts); + + // + // Initializing Sessions ... + string sessions[]; + int sessionsCount = 0; + bool hasSession = IsValid(eaSessions); + if (hasSession) + { + // + // Extract Per Symbol Sessions ... + sessionsCount = SplitContent( + sessions, + eaSessions, + "," // + ); + + // + // Try to Extract Start and End Times Series ... + hasSession = IsValidSize(sessionsCount); + if (hasSession) + { + // + // Iterate Sessions ... + for (int i = 0; i < sessionsCount; i++) + { + // + // Ignore unused Cases and Extracts only Content ... + string iSessionDescriptorStr = ExtractString(sessions[i]); + bool isInited = IsValid(iSessionDescriptorStr); + if (isInited) + { + // + // Extract Session Descriptor Data ... + string parts[]; + int partsCount = SplitContent( + parts, + iSessionDescriptorStr, + "_" // + ); + isInited = IsValidSize(partsCount) && partsCount == 3; + if (isInited) + { + // + string iName = parts[0]; + string iStart = parts[1]; + string iEnd = parts[2]; + isInited = IsValid(iName) && + IsValid(iStart) && + IsValid(iEnd); + if (isInited) + { + // + // Set Active Session ... + eaTradeManager + .SetTradeSession( + _Symbol, + iStart, + iEnd, + iName // + ); + } + } + } + } + } + } + + // + // Initializing Signaller(s) ... + string symbols[]; + Add( + _Symbol, + symbols // + ); + bool hasSymbols = HasChild(symbols); + if (hasSymbols) + { + // + // Prepare Signaller Inputs ... + XCATBEASignallerInputs iSignallerInputs; + + // + // Common Configs ... + + // + // Provider Name ... + iSignallerInputs.period = _Period; + iSignallerInputs.provider = "XTRGB"; + iSignallerInputs.allowGuards = eaAllowGuards; + iSignallerInputs.riskToRewardRatio = eaSignalR2R; + iSignallerInputs.allowDraws = IsRunningOnTestMode(); + iSignallerInputs.slATRMultiplier = eaSLATRMultiplier; + + // + // CATB Indicator ... + iSignallerInputs.catbInputs.Default(); + iSignallerInputs.catbInputs.Hide(); + + // + // Make Available all Requirement Buffers of XCATB indicator ... + iSignallerInputs.catbInputs.showPV = true; + iSignallerInputs.catbInputs.showKI = true; + iSignallerInputs.catbInputs.showATRBand = true; + iSignallerInputs.catbInputs.showPVGolden = true; + + // + // Trigger Block Validations ... + iSignallerInputs.validations.forceHasSwing = eaForceHasSwing; + iSignallerInputs.validations.forceOBBarType = eaForceOBBarType; + iSignallerInputs.validations.minRequiredOBBar = eaMinRequiredOBBar; + iSignallerInputs.validations.forceFVGBarType = eaForceFVGBarType; + iSignallerInputs.validations.liquidityLoopback = eaLiquidityLoopback; + iSignallerInputs.validations.maxAllowedRange = eaMaxAllowedRange; + iSignallerInputs.validations.minAllowedRange = eaMinAllowedRange; + iSignallerInputs.validations.forceHasFLiquidity = eaForceHasFLiquidity; + iSignallerInputs.validations.forceHasRLiquidity = eaForceHasRLiquidity; + iSignallerInputs.validations.validateGapSequence = eaValidateGapSequence; + iSignallerInputs.validations.minAllowedBlockLength = eaMinAllowedBlockLength; + iSignallerInputs.validations.validateBlockEdgeBreakout = eaValidateBlockEdgeBreakout; + + // + // Signalling Configurations ... + iSignallerInputs.signallerConfigs.allowSignallingBasedOnConditions = eaAllowSignallingBasedOnConditions; + iSignallerInputs.signallerConfigs.allowSignallingBasedOnTriggerBlocks = eaAllowSignallingBasedOnTriggerBlocks; + iSignallerInputs.signallerConfigs.secondsTriggersSLUsingFirstTriggerBlock = eaSecondsTriggersSLUsingFirstTriggerBlock; + iSignallerInputs.signallerConfigs.applyValidateAndFilterOnSelectInsideOthers = eaApplyValidateAndFilterOnSelectInsideOthers; + iSignallerInputs.signallerConfigs.allowSignallingBasedOnTriggerBlocksInsideOther = eaAllowSignallingBasedOnTriggerBlocksInsideOther; + iSignallerInputs.signallerConfigs.allowSignallingConditions1 = eaAllowSignallingConditions1; + iSignallerInputs.signallerConfigs.allowSignallingConditions2 = eaAllowSignallingConditions2; + iSignallerInputs.signallerConfigs.allowSignallingConditions3 = eaAllowSignallingConditions3; + iSignallerInputs.signallerConfigs.allowSignallingConditions4 = eaAllowSignallingConditions4; + iSignallerInputs.signallerConfigs.allowSignallingConditions5 = eaAllowSignallingConditions5; + iSignallerInputs.signallerConfigs.allowSignallingConditions6 = eaAllowSignallingConditions6; + + // + // Trigger Block Filters ... + + // + iSignallerInputs.filters.filterBasedOnPV = eaFilterBasedOnPV; + iSignallerInputs.filters.bosLoopback = eaBosLoopback; + + // + iSignallerInputs.filters.filterBasedOnSar = eaFilterBasedOnSar; + iSignallerInputs.filters.forceSarSwitched = eaForceSarSwitched; + iSignallerInputs.filters.forceSarOnBothSide = eaForceSarOnBothSide; + iSignallerInputs.filters.forceSarHasBreakout = eaForceSarHasBreakout; + iSignallerInputs.filters.forceSarHasReversalSide = eaForceSarHasReversalSide; + + // + iSignallerInputs.filters.filterBasedOnRSI = eaFilterBasedOnRSI; + iSignallerInputs.filters.forceHasRSITrending = eaForceHasRSITrending; + iSignallerInputs.filters.forceHasRSIVPattern = eaForceHasRSIVPattern; + iSignallerInputs.filters.forceHasRSICrossing = eaForceHasRSICrossing; + + // + iSignallerInputs.filters.filterBasedOnADX = eaFilterBasedOnADX; + iSignallerInputs.filters.forceHasADXTrending = eaForceHasADXTrending; + iSignallerInputs.filters.forceHasADXCrossing = eaForceHasADXCrossing; + + // + iSignallerInputs.filters.filterBasedOnATR = eaFilterBasedOnATR; + iSignallerInputs.filters.forceHasATRTrending = eaForceHasATRTrending; + iSignallerInputs.filters.forceHasATRBreakout = eaForceHasATRBreakout; + + // + iSignallerInputs.filters.filterBasedOnTrend = eaFilterBasedOnTrend; + iSignallerInputs.filters.forceHasTrendDir = eaForceHasTrendDir; + iSignallerInputs.filters.forceHasTrendPlace = eaForceHasTrendPlace; + iSignallerInputs.filters.forceHasTrendChange = eaForceHasTrendChange; + iSignallerInputs.filters.forceHasTrendTrending = eaForceHasTrendTrending; + iSignallerInputs.filters.forceHasTrendRejection = eaForceHasTrendRejection; + iSignallerInputs.filters.forceHasTrendLineInside = eaForceHasTrendLineInside; + iSignallerInputs.filters.forceHasTrendDirOnBothSide = eaForceHasTrendDirOnBothSide; + + // + iSignallerInputs.filters.filterBasedOnKI = eaFilterBasedOnKI; + iSignallerInputs.filters.filterBasedOnDelta = eaFilterBasedOnDelta; + iSignallerInputs.filters.filterBasedOnVolume = eaFilterBasedOnVolume; + iSignallerInputs.filters.filterBasedOnSignalBar = eaFilterBasedOnSignalBar; + iSignallerInputs.filters.filterBasedOnHKSignalBar = eaFilterBasedOnHKSignalBar; + + // + + // + // Loop Through Symbols for Signalling Initializing ... + int symbolsCount = ArraySize(symbols); + for (int i = 0; i < symbolsCount; i++) + { + // + string iSymbol = symbols[i]; + + // + iSignallerInputs.symbol = iSymbol; + if (iSignallerInputs.IsValid()) + { + // + // Initialize Signaller ... + XCXCATBEASignaller *iSignaller = new XCXCATBEASignaller(iSignallerInputs); + + // + // Add it to the Signallers List ... + Add( + iSignaller, + eaSignallers // + ); + + // + ZeroMemory(iSignaller); + } + } + + // + // Cleanup Resources ... + iSignallerInputs.Clean(); + } + + // +} + +/** + * Handling Time Reporting ... + */ +void HandleTimeReport() +{ + // + if (eaAlert == NULL) + { + return; + } + + // + // Monthly Report .... + if (eaReportNewMonths && + eaTimeTracker.IsNewMonth()) + { + // + string msg = "New Month ..."; + + // + eaAlert.SendAlert(msg); + } + + // + // Weekly Report .... + if (eaReportNewWeeks && + eaTimeTracker.IsNewWeek()) + { + // + string msg = "New Week ..."; + + // + eaAlert.SendAlert(msg); + } + + // + // Daily Report .... + if (eaReportNewDays && + eaTimeTracker.IsNewDay()) + { + // + string msg = "New Day ..."; + + // + eaAlert.SendAlert(msg); + } + + // + // Hourly Report .... + if (eaReportNewHours && + eaTimeTracker.IsNewHour()) + { + // + string msg = "New Hour ..."; + + // + eaAlert.SendAlert(msg); + } +} + +/** + * Update Signal Targets ... + */ +void UpdateSignalTargets(XSignal &signal) +{ + // + bool has = signal.IsValid(); + if (!has) + { + return; + } + + // + // Clean Signal Targets ... + Clean(signal.targets); + + // + // Calculate Requirements ... + double r2r = eaSignalR2R > 0 + ? eaSignalR2R + : 1; + double risk = signal.GetRisk(); + double reward = risk * r2r; + + // + double isLong = IsLong(signal.type); + + // + // Handling Signal TP ... + signal.tp = + isLong + ? signal.entry + reward + : signal.entry - reward; + + // + // Try to Apply Money Management ... + + // + // if (r2r <= 1) + // { + // return; + // } + + // + // XTarget iTarget; + + // // + // // Partial Close 0.5 of Position on Reward 1 ... + // reward = risk * 1; + // iTarget.target = + // isLong + // ? signal.entry + reward + // : signal.entry - reward; + // iTarget.volumeMultiplier = 0.5; + + // // + // AddRef(iTarget, signal.targets); + // iTarget.Clean(); + + // // + // if (r2r <= 2) + // { + // return; + // } + + // + // Making Loop ... + // for (int i = 2; i < ((int)r2r - 1); i++) + // { + // // + // iTarget.Clean(); + + // // + // reward = i * risk; + // iTarget.target = + // isLong + // ? signal.entry + reward + // : signal.entry - reward; + // iTarget.volumeMultiplier = 1 / (r2r - 2); + + // // + // AddRef(iTarget, signal.targets); + // } + + // + // Sort Targets ... + ENUM_X_DIRECTION sortingDir = + isLong + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + ApplySortOnTargets( + sortingDir, + signal.targets // + ); +} + +/** + * Convert a Triggered Conditions to Signal and + * Execute it ... + */ +void TriggerConditions(XCATBEAStrategyConditions &conditions[]) +{ + // + int count = 0; + bool has = false; + + // + has = HasChild(conditions); + if (!has) + { + return; + } + + // + count = ArraySize(conditions); + for (int i = 0; i < count; i++) + { + // + // Retrieve Indexed Conditions ... + XCATBEAStrategyConditions iConditions = conditions[i]; + + // + // Prepare Signal Based on Conditions ... + XSignal iSignal; + + // + // Check if a Trigger Block Attached and Has Signal ... + // use it ... + has = + iConditions.IsValid() && + iConditions.IsSetuped() && + iConditions.CanTrigger() && + iConditions.triggerBlock.IsValid() && + iConditions.triggerBlock.signal.IsValid(); + if (has) + { + iSignal = iConditions.triggerBlock.signal; + } + + // + // if we Have any other Signalling senarios we can Handle them here ... + + // + // Validate Signal ... + has = iSignal.IsValid(); + if (has) + { + // + // Retrieve Signal Type ... + bool isLong = IsLong(iSignal.type); + + // + // Update Signal Entry ... + iSignal.entry = GetEntry( + iSignal.symbol, + iSignal.type // + ); + + // + // Update Signal Targets ... + UpdateSignalTargets(iSignal); + + // + // Handle Volume Management ... + double iVolume = eaVolume.CalculateVolume(iSignal); + has = iVolume > X_MIN_VOLUME && + iVolume != iSignal.volume; + if (has) + { + iSignal.volume = iVolume; + } + + // + // Execute Signal ... + has = eaTradeManager.Execute( + iSignal, + iConditions // + ); + } + + // + // Cleanup Resources ... + + // + iSignal.Clean(); + iConditions.Clean(); + } +} + +// \ No newline at end of file diff --git a/BKPS/14040316/Documents/BKP/xcatbea.x-data.collector.class.mq5 b/BKPS/14040316/Documents/BKP/xcatbea.x-data.collector.class.mq5 new file mode 100644 index 0000000..d16da67 --- /dev/null +++ b/BKPS/14040316/Documents/BKP/xcatbea.x-data.collector.class.mq5 @@ -0,0 +1,209 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XCXCATBEADataCollector ... +// Description: Class for XCATBEA Data Collector ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm Class for XCATBEA Data Collector" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.base.class.mq5" + +// +// Definitions ... + +// +// Implementation ... +class XCXCATBEADataCollector : public XCBase +{ + // + // Public ... + public: + // + // Constructors ... + XCXCATBEADataCollector() + { + } + + // + // Deconstructor ... + ~XCXCATBEADataCollector() + { + } + + // + // Properties ... + + // + string Path() + { + return mPath; + } + + // + void Path(string value) + { + // + // Normalizing Collector Path ... + if (IsValid(value)) + { + mPath = value; + } + else + { + mPath = "XCXCATBEADataCollector"; + } + } + + // + // Tools ... + + // + string GetFilePath(string fileName) + { + // + string result = ""; + + // + result = + // + mPath + "\\" + fileName + ".x121.log" + // + ; + + // + return result; + } + + // + int GetFileHandlerForWrite(string filePath) + { + // + int result = INVALID_HANDLE; + + // + if (!IsValid(filePath)) + { + return result; + } + + // + result = FileOpen( + filePath, + FILE_READ | FILE_WRITE | FILE_TXT // + ); + + // + return result; + } + + /** + * Save Specified Content into Specified File Name ... + * + * @param fileName: string, file name ... + * @param content: string, content ... + * + * @return ( bool ) + */ + bool Save( + string fileName, + string content // + ) + { + // + bool result = false; + + // + result = IsValid(content); + if (!result) + { + return result; + } + + // + // + int mHandler = GetFileHandlerForWrite(fileName); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + FileWrite(mHandler, content); + FileFlush(mHandler); + FileClose(mHandler); + + // + return result; + } + + /** + * Append Specified Content into Specified File Name ... + * + * @param fileName: string, file name ... + * @param content: string, content ... + * + * @return ( bool ) + */ + bool Append( + string fileName, + string content // + ) + { + // + bool result = false; + + // + result = IsValid(content); + if (!result) + { + return result; + } + + // + // + int mHandler = GetFileHandlerForWrite(fileName); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + FileSeek(mHandler, 0, SEEK_END); + FileWrite(mHandler, content); + FileFlush(mHandler); + FileClose(mHandler); + + // + return result; + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + + // + string mPath; // Base Collector Path ... +}; diff --git a/BKPS/14040316/Documents/Diagrams/Position Protection.drawio b/BKPS/14040316/Documents/Diagrams/Position Protection.drawio new file mode 100644 index 0000000..d425cb2 --- /dev/null +++ b/BKPS/14040316/Documents/Diagrams/Position Protection.drawio @@ -0,0 +1,279 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/BKPS/14040316/Documents/Helpers/x-saherelm.x121.x3ma.helper.mq5 b/BKPS/14040316/Documents/Helpers/x-saherelm.x121.x3ma.helper.mq5 new file mode 100644 index 0000000..54cefa5 --- /dev/null +++ b/BKPS/14040316/Documents/Helpers/x-saherelm.x121.x3ma.helper.mq5 @@ -0,0 +1,1556 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XCX121X3MAHelper +// 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.x-helper.class.mq5" + +// +// Definitions ... + +// +// Buffers ... +enum ENUM_X121_X3MA_BUFFERS +{ + // + X121_X3MA_FAST = 0, + X121_X3MA_FAST_COLOR = 1, + X121_X3MA_FAST_STATE = 6, + X121_X3MA_MEDIUM = 2, + X121_X3MA_MEDIUM_COLOR = 3, + X121_X3MA_MEDIUM_STATE = 7, + X121_X3MA_SLOW = 4, + X121_X3MA_SLOW_COLOR = 5, + X121_X3MA_SLOW_STATE = 8, +}; + +// +// Input Models ... +struct X121X3MAInputs +{ + // + // Props ... + + // + // FAST ... + int fastLength; + ENUM_MA_METHOD fastMethod; + ENUM_APPLIED_PRICE fastAppliedTo; + + // + // MEDIUM ... + int mediumLength; + ENUM_MA_METHOD mediumMethod; + ENUM_APPLIED_PRICE mediumAppliedTo; + + // + // SLOW ... + int slowLength; + ENUM_MA_METHOD slowMethod; + ENUM_APPLIED_PRICE slowAppliedTo; + + // + // Presentation ... + + // + int startCalculationForLastBars; + + // + bool applyColor; + + // + bool showFast; + bool showSlow; + bool showMedium; + + // + // Constructor ... + X121X3MAInputs() + { + Default(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + // FAST ... + fastLength = 0; + fastMethod = MODE_SMA; + fastAppliedTo = PRICE_CLOSE; + + // + // MEDIUM ... + mediumLength = 0; + mediumMethod = MODE_SMA; + mediumAppliedTo = PRICE_CLOSE; + + // + // SLOW ... + slowLength = 0; + slowMethod = MODE_SMA; + slowAppliedTo = PRICE_CLOSE; + + // + startCalculationForLastBars = 0; + + // + applyColor = false; + + // + showFast = false; + showSlow = false; + showMedium = false; + + // + ZeroMemory(this); + } + + // + // Default ... + void Default() + { + // + // FAST ... + fastLength = 6; + fastMethod = MODE_SMA; + fastAppliedTo = PRICE_CLOSE; + + // + // MEDIUM ... + mediumLength = 21; + mediumMethod = MODE_SMA; + mediumAppliedTo = PRICE_CLOSE; + + // + // SLOW ... + slowLength = 34; + slowMethod = MODE_SMA; + slowAppliedTo = PRICE_CLOSE; + + // + startCalculationForLastBars = 1000; + + // + applyColor = true; + + // + showFast = true; + showSlow = true; + showMedium = true; + } + + // + // Hide all Visible Buffers ... + void Hide() + { + // + showFast = false; + showSlow = false; + showMedium = false; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + fastLength > 2 && + mediumLength > 2 && + slowLength > 2 && + mediumLength > fastLength && + mediumLength < slowLength + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(fastLength, mediumLength); + result = MathMax(result, slowLength); + + // + return result; + } +}; + +// +// Conditions ... +struct X121X3MAConditions +{ + // + // Common ... + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + // Buffers ... + + // + double fastBuffer[]; + double mediumBuffer[]; + double slowBuffer[]; + double fastStateBuffer[]; + double mediumStateBuffer[]; + double slowStateBuffer[]; + + // + // Conditions ... + + // + bool isFastOverMedium; + bool isFastUnderMedium; + + // + bool isFastCrossedOverMedium; + bool isFastCrossedUnderMedium; + + // + bool isFastOverSlow; + bool isFastUnderSlow; + + // + bool isFastCrossedOverSlow; + bool isFastCrossedUnderSlow; + + // + bool isMediumOverSlow; + bool isMediumUnderSlow; + + // + bool isMediumCrossedOverSlow; + bool isMediumCrossedUnderSlow; + + // + bool is3MaBullishOrdered; + bool is3MaBearishOrdered; + + // + bool is3MaSwitchedToBullishOrdered; + bool is3MaSwitchedToBearishOrdered; + + // + bool is3MaBullishState; + bool is3MaBearishState; + + // + bool is3MaSwitchedToBullishState; + bool is3MaSwitchedToBearishState; + + // + bool is3MaBullish; + bool is3MaBearish; + + // + bool is3MaSwitchedToBullish; + bool is3MaSwitchedToBearish; + + // + bool is3MaFinishedFromBullish; + bool is3MaFinishedFromBearish; + + // + // Constructor ... + X121X3MAConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + // Commons ... + symbol = NULL; + period = NULL; + time = NULL; + + // + // Buffers ... + + // + Clean(fastBuffer); + Clean(mediumBuffer); + Clean(slowBuffer); + Clean(fastStateBuffer); + Clean(mediumStateBuffer); + Clean(slowStateBuffer); + + // + ArraySetAsSeries(fastBuffer, true); + ArraySetAsSeries(mediumBuffer, true); + ArraySetAsSeries(slowBuffer, true); + ArraySetAsSeries(fastStateBuffer, true); + ArraySetAsSeries(mediumStateBuffer, true); + ArraySetAsSeries(slowStateBuffer, true); + + // + // Conditions ... + + // + isFastOverMedium = false; + isFastUnderMedium = false; + + // + isFastCrossedOverMedium = false; + isFastCrossedUnderMedium = false; + + // + isFastOverSlow = false; + isFastUnderSlow = false; + + // + isFastCrossedOverSlow = false; + isFastCrossedUnderSlow = false; + + // + isMediumOverSlow = false; + isMediumUnderSlow = false; + + // + isMediumCrossedOverSlow = false; + isMediumCrossedUnderSlow = false; + + // + is3MaBullishOrdered = false; + is3MaBearishOrdered = false; + + // + is3MaSwitchedToBullishOrdered = false; + is3MaSwitchedToBearishOrdered = false; + + // + is3MaBullishState = false; + is3MaBearishState = false; + + // + is3MaSwitchedToBullishState = false; + is3MaSwitchedToBearishState = false; + + // + is3MaBullish = false; + is3MaBearish = false; + + // + is3MaSwitchedToBullish = false; + is3MaSwitchedToBearish = false; + + // + is3MaFinishedFromBullish = false; + is3MaFinishedFromBearish = false; + + // + ZeroMemory(this); + } + + /** + * Generate Conditions Scores ... + * + * @param bullishScore: Double, Directional Scores Reference ... + * @param bearishScore: Double, Directional Scores Reference ... + */ + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + // + bullishScore = 0; + bearishScore = 0; + + // + double score = 1; + double minScore = 0.5; + double highScore = 1.5; + + // + if (isFastOverSlow) + { + bullishScore += minScore; + } + if (isFastOverMedium) + { + bullishScore += minScore; + } + if (isMediumOverSlow) + { + bullishScore += minScore; + } + if (isFastCrossedOverSlow) + { + bullishScore += score; + } + if (isFastCrossedOverMedium) + { + bullishScore += score; + } + if (isMediumCrossedOverSlow) + { + bullishScore += score; + } + + // + if (is3MaBullish) + { + bullishScore += minScore; + } + if (is3MaBullishState) + { + bullishScore += minScore; + } + if (is3MaBullishOrdered) + { + bullishScore += minScore; + } + if (is3MaSwitchedToBullish) + { + bullishScore += minScore; + } + if (is3MaFinishedFromBearish) + { + bullishScore += minScore; + } + if (is3MaSwitchedToBullishState) + { + bullishScore += minScore; + } + if (is3MaSwitchedToBullishOrdered) + { + bullishScore += minScore; + } + + // + if (isFastUnderSlow) + { + bearishScore += minScore; + } + if (isMediumUnderSlow) + { + bearishScore += minScore; + } + if (isFastUnderMedium) + { + bearishScore += minScore; + } + if (isFastCrossedUnderSlow) + { + bearishScore += score; + } + if (isFastCrossedUnderMedium) + { + bearishScore += score; + } + if (isMediumCrossedUnderSlow) + { + bearishScore += score; + } + + // + if (is3MaBearish) + { + bearishScore += minScore; + } + if (is3MaBearishState) + { + bearishScore += minScore; + } + if (is3MaBearishOrdered) + { + bearishScore += minScore; + } + if (is3MaSwitchedToBearish) + { + bearishScore += minScore; + } + if (is3MaFinishedFromBullish) + { + bearishScore += minScore; + } + if (is3MaSwitchedToBearishState) + { + bearishScore += minScore; + } + if (is3MaSwitchedToBearishOrdered) + { + bearishScore += minScore; + } + } + + /** + * Generate Summary String for Represent Conditions State ... + * + * @param onlyCommons: Boolean, Just Generate Only Commons Conditions ... + * @param onlyConditions: Boolean, Just Generate Only Conditions ... + * @param includeScores: Boolean, Attach Scores Representations on Result ... + * @param ignoreFalseConditions: Boolean, Ignore False Conditions on Result ... + * @param separator: String, Separate Lines ... + * + * @return ( string ) + */ + string GenerateSummary( + bool onlyCommons = false, + bool onlyConditions = false, + bool includeScores = true, + bool ignoreFalseConditions = true, + string separator = "\n" // + ) + { + // + string result = NULL; + + // + double bullishScore = 0; + double bearishScore = 0; + GenerateScore( + bullishScore, + bearishScore // + ); + + // + string scoresStr = + // + "Scores: " + separator + + "---------------" + separator + + "Bullish: " + ToString(bullishScore) + separator + + "Bearish: " + ToString(bearishScore) + separator + + "" + // + ; + + // + string commonStr = GenerateSpecifiedCommonSummary( + this, + separator, + includeScores // + ); + + // + string conditionsStr = + // + "-----------------------" + separator + + "X3MA: " + separator + + "-----------------------" + separator + + ToString("isFastOverMedium", isFastOverMedium, ignoreFalseConditions, separator) + + ToString("isFastUnderMedium", isFastUnderMedium, ignoreFalseConditions, separator) + + ToString("isFastCrossedOverMedium", isFastCrossedOverMedium, ignoreFalseConditions, separator) + + ToString("isFastCrossedUnderMedium", isFastCrossedUnderMedium, ignoreFalseConditions, separator) + + ToString("isFastOverSlow", isFastOverSlow, ignoreFalseConditions, separator) + + ToString("isFastUnderSlow", isFastUnderSlow, ignoreFalseConditions, separator) + + ToString("isFastCrossedOverSlow", isFastCrossedOverSlow, ignoreFalseConditions, separator) + + ToString("isFastCrossedUnderSlow", isFastCrossedUnderSlow, ignoreFalseConditions, separator) + + ToString("isMediumOverSlow", isMediumOverSlow, ignoreFalseConditions, separator) + + ToString("isMediumUnderSlow", isMediumUnderSlow, ignoreFalseConditions, separator) + + ToString("isMediumCrossedOverSlow", isMediumCrossedOverSlow, ignoreFalseConditions, separator) + + ToString("isMediumCrossedUnderSlow", isMediumCrossedUnderSlow, ignoreFalseConditions, separator) + + ToString("is3MaBullishOrdered", is3MaBullishOrdered, ignoreFalseConditions, separator) + + ToString("is3MaBearishOrdered", is3MaBearishOrdered, ignoreFalseConditions, separator) + + ToString("is3MaSwitchedToBullishOrdered", is3MaSwitchedToBullishOrdered, ignoreFalseConditions, separator) + + ToString("is3MaSwitchedToBearishOrdered", is3MaSwitchedToBearishOrdered, ignoreFalseConditions, separator) + + ToString("is3MaBullishState", is3MaBullishState, ignoreFalseConditions, separator) + + ToString("is3MaBearishState", is3MaBearishState, ignoreFalseConditions, separator) + + ToString("is3MaSwitchedToBullishState", is3MaSwitchedToBullishState, ignoreFalseConditions, separator) + + ToString("is3MaSwitchedToBearishState", is3MaSwitchedToBearishState, ignoreFalseConditions, separator) + + ToString("is3MaBullish", is3MaBullish, ignoreFalseConditions, separator) + + ToString("is3MaBearish", is3MaBearish, ignoreFalseConditions, separator) + + ToString("is3MaSwitchedToBullish", is3MaSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("is3MaSwitchedToBearish", is3MaSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("is3MaFinishedFromBullish", is3MaFinishedFromBullish, ignoreFalseConditions, separator) + + ToString("is3MaFinishedFromBearish", is3MaFinishedFromBearish, ignoreFalseConditions, separator) + + // + "" + // + ; + + // + result = + // + "[" + GetTag() + "]" + separator + + (onlyConditions + ? "" + : commonStr) + + (!includeScores + ? "" + : scoresStr) + + " " + separator + + (onlyCommons + ? "" + : conditionsStr) + + "" + // + ; + + // + return result; + } + + /** + * Retrieve nique Tag Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + return GetTypeName(this); + } + + // +}; + +// +// Class ... +class XCX121X3MAHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructors ... + XCX121X3MAHelper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCX121X3MAHelper() + { + // + mInputs.Clean(); + + // + Clean(fastBuffer); + Clean(mediumBuffer); + Clean(slowBuffer); + Clean(fastStateBuffer); + Clean(mediumStateBuffer); + Clean(slowStateBuffer); + } + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + X121X3MAInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + ArraySetAsSeries(fastBuffer, true); + ArraySetAsSeries(mediumBuffer, true); + ArraySetAsSeries(slowBuffer, true); + ArraySetAsSeries(fastStateBuffer, true); + ArraySetAsSeries(mediumStateBuffer, true); + ArraySetAsSeries(slowStateBuffer, true); + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.x3ma", + "", // FAST ... + mInputs.fastLength, + mInputs.fastMethod, + mInputs.fastAppliedTo, + "", // MEDIUM ... + mInputs.mediumLength, + mInputs.mediumMethod, + mInputs.mediumAppliedTo, + "", // SLOW ... + mInputs.slowLength, + mInputs.slowMethod, + mInputs.slowAppliedTo, + "", // Presentation ... + mInputs.startCalculationForLastBars, + mInputs.applyColor, + mInputs.showFast, + mInputs.showSlow, + mInputs.showMedium + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + X121X3MAInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + X121X3MAInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Readers ... + + // + // FAST ... + + // + double GetFast( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(fastBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fastBuffer[barIndex]; + } + + // + 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(start); + + // + // Copy Items ... + return Copy( + 0, + count, + fastBuffer, + buffer, + forceClean + // + ); + } + + // + // FAST STATE ... + + // + double GetFastState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(fastStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fastStateBuffer[barIndex]; + } + + // + int CopyFastState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + fastStateBuffer, + buffer, + forceClean + // + ); + } + + // + // MEDIUM ... + + // + double GetMedium( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(mediumBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return mediumBuffer[barIndex]; + } + + // + int CopyMedium( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + mediumBuffer, + buffer, + forceClean + // + ); + } + + // + // MEDIUM STATE ... + + // + double GetMediumState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(mediumStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return mediumStateBuffer[barIndex]; + } + + // + int CopyMediumState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + mediumStateBuffer, + buffer, + forceClean + // + ); + } + + // + // SLOW ... + + // + double GetSlow( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(slowBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return slowBuffer[barIndex]; + } + + // + 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(start); + + // + // Copy Items ... + return Copy( + 0, + count, + slowBuffer, + buffer, + forceClean + // + ); + } + + // + // SLOW STATE ... + + // + double GetSlowState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(slowStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return slowStateBuffer[barIndex]; + } + + // + int CopySlowState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + slowStateBuffer, + buffer, + forceClean + // + ); + } + + // + void Free() override + { + Cleanup(10); + } + + // + bool GetConditions( + X121X3MAConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = true; + + // + if (loopback < 5) + { + loopback = 5; + } + + // + conditions.Clean(); + + // + conditions.symbol = mSymbol; + conditions.period = mPeriod; + conditions.time = TimeCurrent(); + + // + int zIndex = barIndex; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + XOHCL zBar; + result = zBar.Init( + mSymbol, + mPeriod, + zIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL cBar; + result = cBar.Init( + mSymbol, + mPeriod, + cIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL pBar; + result = pBar.Init( + mSymbol, + mPeriod, + pIndex // + ); + if (!result) + { + return result; + } + + // + // Buffers ... + + // + // FAST ... + + // + CopyFast( + zIndex, + loopback, + conditions.fastBuffer // + ); + + // + CopyFastState( + zIndex, + loopback, + conditions.fastStateBuffer // + ); + + // + // MEDIUM ... + + // + CopyMedium( + zIndex, + loopback, + conditions.mediumBuffer // + ); + + // + CopyMediumState( + zIndex, + loopback, + conditions.mediumStateBuffer // + ); + + // + // SLOW ... + + // + CopySlow( + zIndex, + loopback, + conditions.slowBuffer // + ); + + // + CopySlowState( + zIndex, + loopback, + conditions.slowStateBuffer // + ); + + // + // Conditions ... + + // + int zIDX = 0; + int cIDX = 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + int p3IDX = p2IDX + 1; + int p4IDX = p3IDX + 1; + + // + // Calculate ... + + // + // FAST ... + + // + double cFast = conditions.fastBuffer[cIDX]; + double pFast = conditions.fastBuffer[pIDX]; + double p2Fast = conditions.fastBuffer[p2IDX]; + + // + double cFastState = conditions.fastStateBuffer[cIDX]; + double pFastState = conditions.fastStateBuffer[pIDX]; + double p2FastState = conditions.fastStateBuffer[p2IDX]; + + // + // MEDIUM ... + + // + double cMedium = conditions.mediumBuffer[cIDX]; + double pMedium = conditions.mediumBuffer[pIDX]; + double p2Medium = conditions.mediumBuffer[p2IDX]; + + // + double cMediumState = conditions.mediumStateBuffer[cIDX]; + double pMediumState = conditions.mediumStateBuffer[pIDX]; + double p2MediumState = conditions.mediumStateBuffer[p2IDX]; + + // + // FAST ... + + // + double cSlow = conditions.slowBuffer[cIDX]; + double pSlow = conditions.slowBuffer[pIDX]; + double p2Slow = conditions.slowBuffer[p2IDX]; + + // + double cSlowState = conditions.slowStateBuffer[cIDX]; + double pSlowState = conditions.slowStateBuffer[pIDX]; + double p2SlowState = conditions.slowStateBuffer[p2IDX]; + + // + // Conditions ... + + // + bool isFastOverMedium = cFast > cMedium; + bool isFastOverMediumPrev = pFast > pMedium; + bool isFastCrossedOverMedium = isFastOverMedium && + !isFastOverMediumPrev; + + // + bool isFastUnderMedium = cFast < cMedium; + bool isFastUnderMediumPrev = pFast < pMedium; + bool isFastCrossedUnderMedium = isFastUnderMedium && + !isFastUnderMediumPrev; + + // + bool isFastOverSlow = cFast > cSlow; + bool isFastOverSlowPrev = pFast > pSlow; + bool isFastCrossedOverSlow = isFastOverSlow && + !isFastOverSlowPrev; + + // + bool isFastUnderSlow = cFast < cSlow; + bool isFastUnderSlowPrev = pFast < pSlow; + bool isFastCrossedUnderSlow = isFastUnderSlow && + !isFastUnderSlowPrev; + + // + bool isMediumOverSlow = cMedium > cSlow; + bool isMediumOverSlowPrev = pMedium > pSlow; + bool isMediumCrossedOverSlow = isMediumOverSlow && + !isMediumOverSlowPrev; + + // + bool isMediumUnderSlow = cMedium < cSlow; + bool isMediumUnderSlowPrev = pMedium < pSlow; + bool isMediumCrossedUnderSlow = isMediumUnderSlow && + !isMediumUnderSlowPrev; + + // + bool is3MaBullishOrdered = + isFastOverMedium && + isMediumOverSlow; + bool is3MaBullishOrderedPrev = + isFastOverMediumPrev && + isMediumOverSlowPrev; + + // + bool is3MaBearishOrdered = + isFastUnderMedium && + isMediumUnderSlow; + bool is3MaBearishOrderedPrev = + isFastUnderMediumPrev && + isMediumUnderSlowPrev; + + // + bool is3MaSwitchedToBullishOrdered = is3MaBullishOrdered && + !is3MaBullishOrderedPrev; + bool is3MaSwitchedToBearishOrdered = is3MaBearishOrdered && + !is3MaBearishOrderedPrev; + + // + bool is3MaBullishState = + cFastState > 0 && + cMediumState > 0 && + cSlowState > 0; + bool is3MaBullishStatePrev = + pFastState > 0 && + pMediumState > 0 && + pSlowState > 0; + + // + bool is3MaBearishState = + cFastState < 0 && + cMediumState < 0 && + cSlowState < 0; + bool is3MaBearishStatePrev = + pFastState < 0 && + pMediumState < 0 && + pSlowState < 0; + + // + bool is3MaSwitchedToBullishState = is3MaBullishState && + !is3MaBullishStatePrev; + bool is3MaSwitchedToBearishState = is3MaBearishState && + !is3MaBearishStatePrev; + + // + bool is3MaBullish = + is3MaBullishState && + is3MaBullishOrdered; + bool is3MaBullishPrev = + is3MaBullishStatePrev && + is3MaBullishOrderedPrev; + + // + bool is3MaBearish = + is3MaBearishState && + is3MaBearishOrdered; + bool is3MaBearishPrev = + is3MaBearishStatePrev && + is3MaBearishOrderedPrev; + + // + bool is3MaSwitchedToBullish = is3MaBullish && + !is3MaBullishPrev; + bool is3MaSwitchedToBearish = is3MaBearish && + !is3MaBearishPrev; + + // + bool is3MaFinishedFromBullish = !is3MaBullish && + is3MaBullishPrev; + bool is3MaFinishedFromBearish = !is3MaBearish && + is3MaBearishPrev; + + // + conditions.is3MaBullish = is3MaBullish; + conditions.is3MaBearish = is3MaBearish; + conditions.isFastOverSlow = isFastOverSlow; + conditions.isFastUnderSlow = isFastUnderSlow; + conditions.isFastOverMedium = isFastOverMedium; + conditions.isMediumOverSlow = isMediumOverSlow; + conditions.isFastUnderMedium = isFastUnderMedium; + conditions.isMediumUnderSlow = isMediumUnderSlow; + conditions.is3MaBullishState = is3MaBullishState; + conditions.is3MaBearishState = is3MaBearishState; + conditions.is3MaBullishOrdered = is3MaBullishOrdered; + conditions.is3MaBearishOrdered = is3MaBearishOrdered; + conditions.isFastCrossedOverSlow = isFastCrossedOverSlow; + conditions.is3MaSwitchedToBullish = is3MaSwitchedToBullish; + conditions.is3MaSwitchedToBearish = is3MaSwitchedToBearish; + conditions.isFastCrossedUnderSlow = isFastCrossedUnderSlow; + conditions.isFastCrossedOverMedium = isFastCrossedOverMedium; + conditions.isMediumCrossedOverSlow = isMediumCrossedOverSlow; + conditions.is3MaFinishedFromBullish = is3MaFinishedFromBullish; + conditions.is3MaFinishedFromBearish = is3MaFinishedFromBearish; + conditions.isFastCrossedUnderMedium = isFastCrossedUnderMedium; + conditions.isMediumCrossedUnderSlow = isMediumCrossedUnderSlow; + conditions.is3MaSwitchedToBullishState = is3MaSwitchedToBullishState; + conditions.is3MaSwitchedToBearishState = is3MaSwitchedToBearishState; + conditions.is3MaSwitchedToBullishOrdered = is3MaSwitchedToBullishOrdered; + conditions.is3MaSwitchedToBearishOrdered = is3MaSwitchedToBearishOrdered; + + // + Cleanup(); + + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + + // + return result; + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + X121X3MAInputs mInputs; // Inputs ... + + // + // Buffers ... + double fastBuffer[]; + double mediumBuffer[]; + double slowBuffer[]; + double fastStateBuffer[]; + double mediumStateBuffer[]; + double slowStateBuffer[]; + + // + void Calculate( + int barIndex = 0, + int maxRequiredBars = 100 // + ) + { + // + // Buffers ... + if (barIndex < 0) + { + barIndex = 0; + } + + // + // FAST ... + + // + CopyBuffer( + mHandler, + X121_X3MA_FAST, + barIndex, + maxRequiredBars, + fastBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_X3MA_FAST_STATE, + barIndex, + maxRequiredBars, + fastStateBuffer // + ); + + // + // MEDIUM ... + + // + CopyBuffer( + mHandler, + X121_X3MA_MEDIUM, + barIndex, + maxRequiredBars, + mediumBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_X3MA_MEDIUM_STATE, + barIndex, + maxRequiredBars, + mediumStateBuffer // + ); + + // + // SLOW ... + + // + CopyBuffer( + mHandler, + X121_X3MA_SLOW, + barIndex, + maxRequiredBars, + slowBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_X3MA_SLOW_STATE, + barIndex, + maxRequiredBars, + slowStateBuffer // + ); + } + + // + void Cleanup( + int maxAllowed = 100 // + ) + { + // + CleanupArray( + fastBuffer, + maxAllowed // + ); + + // + CleanupArray( + mediumBuffer, + maxAllowed // + ); + + // + CleanupArray( + slowBuffer, + maxAllowed // + ); + + // + CleanupArray( + fastStateBuffer, + maxAllowed // + ); + + // + CleanupArray( + mediumStateBuffer, + maxAllowed // + ); + + // + CleanupArray( + slowStateBuffer, + maxAllowed // + ); + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14040316/Documents/Helpers/x-saherelm.x121.xca.helper.mq5 b/BKPS/14040316/Documents/Helpers/x-saherelm.x121.xca.helper.mq5 new file mode 100644 index 0000000..f7f1edb --- /dev/null +++ b/BKPS/14040316/Documents/Helpers/x-saherelm.x121.xca.helper.mq5 @@ -0,0 +1,5275 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XCX121XCAHelper +// 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.x-helper.class.mq5" + +// +// Definitions ... + +// +// Buffers ... +enum ENUM_X121_XCA_BUFFERS +{ + // + X121_XCA_S_HH_LINE = 0, + X121_XCA_S_LL_LINE = 1, + X121_XCA_M_HH_LINE = 2, + X121_XCA_M_LL_LINE = 3, + X121_XCA_L_HH_LINE = 4, + X121_XCA_L_LL_LINE = 5, + X121_XCA_H_HH_LINE = 6, + X121_XCA_H_LL_LINE = 7, + X121_XCA_SUPPORT_LINE = 8, + X121_XCA_RESISTANCE_LINE = 9, + X121_XCA_PEAK_LINE = 10, + X121_XCA_PEAK_GOLDEN_LINE = 11, + X121_XCA_VALE_LINE = 12, + X121_XCA_VALE_GOLDEN_LINE = 13, + X121_XCA_FIBO_L1_LINE = 14, + X121_XCA_FIBO_L2_LINE = 15, + X121_XCA_FIBO_L3_LINE = 16, + X121_XCA_FIBO_L4_LINE = 17, + X121_XCA_FIBO_L5_LINE = 18, + X121_XCA_SAR_LINE = 19, + X121_XCA_TREND_LINE = 20, + X121_XCA_KI_LINE = 22, + X121_XCA_SWING_LOW_LINE = 24, + X121_XCA_SWING_HIGH_LINE = 25, + X121_XCA_TKI_LINE = 26, + X121_XCA_VIDYA_LINE = 28, + X121_XCA_MAH_LINE = 30, + X121_XCA_MAL_LINE = 31, + X121_XCA_MAC_LINE = 32, + X121_XCA_TREND_STATE_LINE = 33, + X121_XCA_KI_STATE_LINE = 34, + X121_XCA_TKI_STATE_LINE = 35, + X121_XCA_VIDYA_STATE_LINE = 36, +}; + +// +// Input Models ... +struct X121XCAInputs +{ + // + // Props ... + + // + // Market ... + + // + // 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 + + // + // Boundary Detection ... + ENUM_SERIESMODE hhMode; // Highest High Calculation Method + ENUM_SERIESMODE llMode; // Lowest Low Calculation Method + ENUM_X_FIBO_LEVELS goldenZoneLevel; // Golden Zone Detection + + // + // Fibo Levels ... + ENUM_X_FIBO_LEVELS fiboLevel1; // Fibo Level 1 + ENUM_X_FIBO_LEVELS fiboLevel2; // Fibo Level 2 + ENUM_X_FIBO_LEVELS fiboLevel3; // Fibo Level 3 + ENUM_X_FIBO_LEVELS fiboLevel4; // Fibo Level 4 + ENUM_X_FIBO_LEVELS fiboLevel5; // Fibo Level 5 + + // + // Sar Detection ... + double sarStep; // Step + double sarMax; // Maximum + + // + // KI ... + int kiLength; // KI Length + + // + // VIDYA ... + int vidyaCMOLength; // CMO (Candle Momentum) Length + int vidyaEMALength; // EMA Length + ENUM_APPLIED_PRICE vidyaAppliedTo; // Applied To + + // + // MANALYSER ... + int manalyserLength; // Length + ENUM_MA_METHOD manalyserMethod; // Method + + // + // Swing Detection ... + int swingLength; // Length + + // + // Support and Resistance ... + int supResSmoothingLength; // Smoothing Length + ENUM_X_MA_METHOD supResSmoothingMode; // Smoothing Method + + // + // Presentation ... + + // + int startCalculationForLastBars; // Calculate Last n Bars + + // + bool showSar; // Show Sar + bool showKI; // Show KI + bool showTKI; // Show TKI + bool showMAH; // Show MAH + bool showMAL; // Show MAL + bool showMAC; // Show MAC + bool showVidya; // Show Vidya + bool showTrend; // Show Trend + bool showSwings; // Show Swings + bool showFiboLevel1; // Show Fibo Level 1 + bool showFiboLevel2; // Show Fibo Level 2 + bool showFiboLevel3; // Show Fibo Level 3 + bool showFiboLevel4; // Show Fibo Level 4 + bool showFiboLevel5; // Show Fibo Level 5 + bool showPeaksAndVales; // Show Peaks And Vales + bool showPeakAndValeGolden; // Show Peak and Vale Golden + bool showSupportAndResistance; // Show Support and Resistance + + // + bool showShortCycle; // Show Short Cycle + bool showMediumCycle; // Show Medium Cycle + bool showLongCycle; // Show Long Cycle + bool showHindCycle; // Show Hind Cycle + + // + int sarArrowCode; // Parabolic Sar Arrow Code + int peakArrowCode; // Peaks Arrow Code + int valeArrowCode; // Vales Arrow Code + int swingLowArrowCode; // Swing Low Arrow Code + int swingHighArrowCode; // Swing High Arrow Code + + // + // Constructor(s) ... + X121XCAInputs() + { + // + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + // Market ... + + // + // Short ... + scMethod = X_PERIOD_AUTO; // How to Find Period + scPeriod = NULL; // Time Period + + // + // Medium ... + mcMethod = X_PERIOD_AUTO; // How to Find Period + mcPeriod = NULL; // Time Period + + // + // Long ... + lcMethod = X_PERIOD_AUTO; // How to Find Period + lcPeriod = NULL; // Time Period + + // + // Hind ... + hcMethod = X_PERIOD_AUTO; // How to Find Period + hcPeriod = NULL; // Time Period + + // + // Boundary Detection ... + hhMode = MODE_HIGH; // Highest High Calculation Method + llMode = MODE_LOW; // Lowest Low Calculation Method + + // + // Fibo Levels ... + fiboLevel1 = X_FIBO_LEVEL_236; // Fibo Level 1 + fiboLevel2 = X_FIBO_LEVEL_382; // Fibo Level 2 + fiboLevel3 = X_FIBO_LEVEL_500; // Fibo Level 3 + fiboLevel4 = X_FIBO_LEVEL_618; // Fibo Level 4 + fiboLevel5 = X_FIBO_LEVEL_764; // Fibo Level 5 + + // + // Sar Detection ... + sarStep = 0; // Step + sarMax = 0; // Maximum + + // + // KI ... + kiLength = 0; // KI Length + + // + // VIDYA ... + vidyaCMOLength = 0; + vidyaEMALength = 0; + vidyaAppliedTo = PRICE_CLOSE; + + // + // MANALYSER ... + manalyserLength = 0; // Length + manalyserMethod = MODE_SMA; // Method + + // + // Swing Detection ... + swingLength = 0; // Length + + // + // Support and Resistance ... + supResSmoothingLength = 0; // Smoothing Length + supResSmoothingMode = X_MA_MODE_NONE; // Smoothing Method + + // + // Presentation ... + + // + startCalculationForLastBars = 0; // Calculate Last n Bars + + // + showSar = false; // Show Sar + showKI = false; // Show KI + showTKI = false; // Show TKI + showMAH = false; // Show MAH + showMAL = false; // Show MAL + showMAC = false; // Show MAC + showVidya = false; // Show Vidya + showTrend = false; // Show Trend + showSwings = false; // Show Swings + showFiboLevel1 = false; // Show Fibo Level 1 + showFiboLevel2 = false; // Show Fibo Level 2 + showFiboLevel3 = false; // Show Fibo Level 3 + showFiboLevel4 = false; // Show Fibo Level 4 + showFiboLevel5 = false; // Show Fibo Level 5 + showPeaksAndVales = false; // Show Peaks And Vales + showPeakAndValeGolden = false; // Show Peak and Vale Golden + showSupportAndResistance = false; // Show Support and Resistance + + // + showShortCycle = false; // Show Short Cycle + showMediumCycle = false; // Show Medium Cycle + showLongCycle = false; // Show Long Cycle + showHindCycle = false; // Show Hind Cycle + + // + sarArrowCode = 0; // Parabolic Sar Arrow Code + peakArrowCode = 0; // Peaks Arrow Code + valeArrowCode = 0; // Vales Arrow Code + swingLowArrowCode = 0; // Swing Low Arrow Code + swingHighArrowCode = 0; // Swing High Arrow Code + + // + ZeroMemory(this); + } + + // + // Default ... + void Default() + { + // + // Market ... + + // + // Short ... + scMethod = X_PERIOD_AUTO; // How to Find Period + scPeriod = NULL; // Time Period + + // + // Medium ... + mcMethod = X_PERIOD_AUTO; // How to Find Period + mcPeriod = NULL; // Time Period + + // + // Long ... + lcMethod = X_PERIOD_AUTO; // How to Find Period + lcPeriod = NULL; // Time Period + + // + // Hind ... + hcMethod = X_PERIOD_AUTO; // How to Find Period + hcPeriod = NULL; // Time Period + + // + // Boundary Detection ... + hhMode = MODE_HIGH; // Highest High Calculation Method + llMode = MODE_LOW; // Lowest Low Calculation Method + + // + // Fibo Levels ... + fiboLevel1 = X_FIBO_LEVEL_236; // Fibo Level 1 + fiboLevel2 = X_FIBO_LEVEL_382; // Fibo Level 2 + fiboLevel3 = X_FIBO_LEVEL_500; // Fibo Level 3 + fiboLevel4 = X_FIBO_LEVEL_618; // Fibo Level 4 + fiboLevel5 = X_FIBO_LEVEL_764; // Fibo Level 5 + + // + // Sar Detection ... + sarStep = 0.02; // Step + sarMax = 0.2; // Maximum + + // + // KI ... + kiLength = 26; // KI Length + + // + // VIDYA ... + vidyaCMOLength = 20; + vidyaEMALength = 14; + vidyaAppliedTo = PRICE_CLOSE; + + // + // MANALYSER ... + manalyserLength = 14; // Length + manalyserMethod = MODE_SMA; // Method + + // + // Swing Detection ... + swingLength = 5; // Length + + // + // Presentation ... + + // + startCalculationForLastBars = 1000; // Calculate Last n Bars + + // + showSar = true; // Show Sar + showKI = true; // Show KI + showTKI = true; // Show TKI + showMAH = true; // Show MAH + showMAL = true; // Show MAL + showMAC = true; // Show MAC + showVidya = true; // Show Vidya + showTrend = true; // Show Trend + showSwings = true; // Show Swings + showFiboLevel1 = true; // Show Fibo Level 1 + showFiboLevel2 = true; // Show Fibo Level 2 + showFiboLevel3 = true; // Show Fibo Level 3 + showFiboLevel4 = true; // Show Fibo Level 4 + showFiboLevel5 = true; // Show Fibo Level 5 + showPeaksAndVales = true; // Show Peaks And Vales + showPeakAndValeGolden = true; // Show Peak and Vale Golden + showSupportAndResistance = true; // Show Support and Resistance + + // + showShortCycle = true; // Show Short Cycle + showMediumCycle = true; // Show Medium Cycle + showLongCycle = true; // Show Long Cycle + showHindCycle = true; // Show Hind Cycle + + // + sarArrowCode = 159; // Parabolic Sar Arrow Code + peakArrowCode = 159; // Peaks Arrow Code + valeArrowCode = 159; // Vales Arrow Code + swingLowArrowCode = 225; // Swing Low Arrow Code + swingHighArrowCode = 226; // Swing High Arrow Code + } + + // + // Hide all Visible Buffers ... + void Hide() + { + // + showSar = false; // Show Sar + showKI = false; // Show KI + showTKI = false; // Show TKI + showMAH = false; // Show MAH + showMAL = false; // Show MAL + showMAC = false; // Show MAC + showVidya = false; // Show Vidya + showTrend = false; // Show Trend + showSwings = false; // Show Swings + showFiboLevel1 = false; // Show Fibo Level 1 + showFiboLevel2 = false; // Show Fibo Level 2 + showFiboLevel3 = false; // Show Fibo Level 3 + showFiboLevel4 = false; // Show Fibo Level 4 + showFiboLevel5 = false; // Show Fibo Level 5 + showPeaksAndVales = false; // Show Peaks And Vales + showPeakAndValeGolden = false; // Show Peak and Vale Golden + showSupportAndResistance = false; // Show Support and Resistance + + // + showShortCycle = false; // Show Short Cycle + showMediumCycle = false; // Show Medium Cycle + showLongCycle = false; // Show Long Cycle + showHindCycle = false; // Show Hind Cycle + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + // SAR ... + sarMax > 0 && + sarStep > 0 && + kiLength > 0 && + swingLength > 0 && + sarMax > sarStep && + vidyaCMOLength > 0 && + vidyaEMALength > 0 && + manalyserLength > 0 && + // + // XCA ... + (IsValid(scMethod, scPeriod) && + IsValid(mcMethod, mcPeriod) && + IsValid(lcMethod, lcPeriod) && + IsValid(hcMethod, hcPeriod)) + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(kiLength, swingLength); + result = MathMax(result, vidyaCMOLength); + result = MathMax(result, vidyaEMALength); + result = MathMax(result, manalyserLength); + + // + return result; + } +}; + +// +// Conditions ... +struct X121XCAConditions +{ + // + // Common ... + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + // Buffers ... + double kiBuffer[]; + double tkiBuffer[]; + double sHHBuffer[]; + double sLLBuffer[]; + double mHHBuffer[]; + double mLLBuffer[]; + double lHHBuffer[]; + double lLLBuffer[]; + double hHHBuffer[]; + double hLLBuffer[]; + double sarBuffer[]; + double mahBuffer[]; + double malBuffer[]; + double macBuffer[]; + double peakBuffer[]; + double valeBuffer[]; + double vidyaBuffer[]; + double trendBuffer[]; + double kiStateBuffer[]; + double supportBuffer[]; + double tkiStateBuffer[]; + double swingLowBuffer[]; + double swingHighBuffer[]; + double vidyaStateBuffer[]; + double resistanceBuffer[]; + double peakGoldenBuffer[]; + double valeGoldenBuffer[]; + double fiboLevel1Buffer[]; + double fiboLevel2Buffer[]; + double fiboLevel3Buffer[]; + double fiboLevel4Buffer[]; + double fiboLevel5Buffer[]; + double trendStateBuffer[]; + + // + // Conditions ... + + // + // KI ... + + // + bool isKIRejectUp; + bool isKIRejectDown; + + // + bool isKIBullish; + bool isKIBearish; + + // + bool isKISwitchedToBullish; + bool isKISwitchedToBearish; + + // + bool isKIFinishedFromBullish; + bool isKIFinishedFromBearish; + + // + // TKI ... + + // + bool isTKIRejectUp; + bool isTKIRejectDown; + + // + bool isTKIBullish; + bool isTKIBearish; + + // + bool isTKISwitchedToBullish; + bool isTKISwitchedToBearish; + + // + bool isTKIFinishedFromBullish; + bool isTKIFinishedFromBearish; + + // + // VIDYA ... + + // + bool isVidyaRejectUp; + bool isVidyaRejectDown; + + // + bool isVidyaBullish; + bool isVidyaBearish; + + // + bool isVidyaSwitchedToBullish; + bool isVidyaSwitchedToBearish; + + // + bool isVidyaFinishedFromBullish; + bool isVidyaFinishedFromBearish; + + // + // SAR ... + + // + bool isSarBullish; + bool isSarBearish; + + // + bool isSarSwitchedToBullish; + bool isSarSwitchedToBearish; + + // + bool isSarFinishedFromBullish; + bool isSarFinishedFromBearish; + + // + // MANALYSER ... + + // + // MAH ... + + // + bool isOverMah; + bool isUnderMah; + bool isCrossedOverMah; + bool isCrossedUnderMah; + + // + bool isCloseOverMah; + bool isCloseUnderMah; + bool isCloseCrossedOverMah; + bool isCloseCrossedUnderMah; + + // + bool isMahBullishRejected; + bool isMahBearishRejected; + + // + // MAL ... + + // + bool isOverMal; + bool isUnderMal; + bool isCrossedOverMal; + bool isCrossedUnderMal; + + // + bool isCloseOverMal; + bool isCloseUnderMal; + bool isCloseCrossedOverMal; + bool isCloseCrossedUnderMal; + + // + bool isMalBullishRejected; + bool isMalBearishRejected; + + // + // MAC ... + + // + bool isOverMac; + bool isUnderMac; + bool isCrossedOverMac; + bool isCrossedUnderMac; + + // + bool isCloseOverMac; + bool isCloseUnderMac; + bool isCloseCrossedOverMac; + bool isCloseCrossedUnderMac; + + // + bool isMacBullishRejected; + bool isMacBearishRejected; + + // + // PEAK ... + + // + bool isPeakSameLast; + bool isPeakOverLast; + bool isPeakUnderLast; + + // + // VALE ... + + // + bool isValeSameLast; + bool isValeOverLast; + bool isValeUnderLast; + + // + // TREND ... + + // + bool isTrendRejectUp; + bool isTrendRejectDown; + + // + bool isTrendBullish; + bool isTrendBearish; + + // + bool isTrendSwitchedToBullish; + bool isTrendSwitchedToBearish; + + // + bool isTrendFinishedFromBullish; + bool isTrendFinishedFromBearish; + + // + // SUPPORT ... + + // + bool isSupportSameLast; + bool isSupportOverLast; + bool isSupportUnderLast; + + // + bool isLastSupportBreaked; + bool isLastSupportRejected; + + // + // RESISTANCE ... + + // + bool isResistanceSameLast; + bool isResistanceOverLast; + bool isResistanceUnderLast; + + // + bool isLastResistanceBreaked; + bool isLastResistanceRejected; + + // + // SWING Low ... + + // + bool isSwingLowSameLast; + bool isSwingLowOverLast; + bool isSwingLowUnderLast; + + // + bool isLastSwingLowBreaked; + bool isLastSwingLowRejected; + + // + // SWING High ... + + // + bool isSwingHighSameLast; + bool isSwingHighOverLast; + bool isSwingHighUnderLast; + + // + bool isLastSwingHighBreaked; + bool isLastSwingHighRejected; + + // + // COMPLEX Conditions ... + + // + bool isPeakIsPivot; + bool isValeIsPivot; + + // + bool isPeakSwitchedToPivot; + bool isValeSwitchedToPivot; + + // + bool isPeakFinishedFromPivot; + bool isValeFinishedFromPivot; + + // + bool isSwingLowSameAsVale; + bool isSwingHighSameAsPeak; + + // + bool isSupportSameAsVale; + bool isResistanceSameAsPeak; + + // + bool isSupportSameAsSwingLow; + bool isResistanceSameAsSwingHigh; + + // + // Constructor ... + X121XCAConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + // Commons ... + symbol = NULL; + period = NULL; + time = NULL; + + // + // Buffers ... + + // + Clean(kiBuffer); + Clean(tkiBuffer); + Clean(sHHBuffer); + Clean(sLLBuffer); + Clean(mHHBuffer); + Clean(mLLBuffer); + Clean(lHHBuffer); + Clean(lLLBuffer); + Clean(hHHBuffer); + Clean(hLLBuffer); + Clean(sarBuffer); + Clean(mahBuffer); + Clean(malBuffer); + Clean(macBuffer); + Clean(peakBuffer); + Clean(valeBuffer); + Clean(vidyaBuffer); + Clean(trendBuffer); + Clean(kiStateBuffer); + Clean(supportBuffer); + Clean(tkiStateBuffer); + Clean(swingLowBuffer); + Clean(swingHighBuffer); + Clean(resistanceBuffer); + Clean(peakGoldenBuffer); + Clean(valeGoldenBuffer); + Clean(fiboLevel1Buffer); + Clean(fiboLevel2Buffer); + Clean(fiboLevel3Buffer); + Clean(fiboLevel4Buffer); + Clean(fiboLevel5Buffer); + Clean(vidyaStateBuffer); + Clean(trendStateBuffer); + + // + ArraySetAsSeries(kiBuffer, true); + ArraySetAsSeries(tkiBuffer, true); + ArraySetAsSeries(sHHBuffer, true); + ArraySetAsSeries(sLLBuffer, true); + ArraySetAsSeries(mHHBuffer, true); + ArraySetAsSeries(mLLBuffer, true); + ArraySetAsSeries(lHHBuffer, true); + ArraySetAsSeries(lLLBuffer, true); + ArraySetAsSeries(hHHBuffer, true); + ArraySetAsSeries(hLLBuffer, true); + ArraySetAsSeries(sarBuffer, true); + ArraySetAsSeries(mahBuffer, true); + ArraySetAsSeries(malBuffer, true); + ArraySetAsSeries(macBuffer, true); + ArraySetAsSeries(peakBuffer, true); + ArraySetAsSeries(valeBuffer, true); + ArraySetAsSeries(vidyaBuffer, true); + ArraySetAsSeries(trendBuffer, true); + ArraySetAsSeries(kiStateBuffer, true); + ArraySetAsSeries(supportBuffer, true); + ArraySetAsSeries(tkiStateBuffer, true); + ArraySetAsSeries(swingLowBuffer, true); + ArraySetAsSeries(swingHighBuffer, true); + ArraySetAsSeries(resistanceBuffer, true); + ArraySetAsSeries(peakGoldenBuffer, true); + ArraySetAsSeries(valeGoldenBuffer, true); + ArraySetAsSeries(fiboLevel1Buffer, true); + ArraySetAsSeries(fiboLevel2Buffer, true); + ArraySetAsSeries(fiboLevel3Buffer, true); + ArraySetAsSeries(fiboLevel4Buffer, true); + ArraySetAsSeries(fiboLevel5Buffer, true); + ArraySetAsSeries(vidyaStateBuffer, true); + ArraySetAsSeries(trendStateBuffer, true); + + // + // Conditions ... + + // + // KI ... + + // + isKIRejectUp = false; + isKIRejectDown = false; + + // + isKIBullish = false; + isKIBearish = false; + + // + isKISwitchedToBullish = false; + isKISwitchedToBearish = false; + + // + isKIFinishedFromBullish = false; + isKIFinishedFromBearish = false; + + // + // TKI ... + + // + isTKIRejectUp = false; + isTKIRejectDown = false; + + // + isTKIBullish = false; + isTKIBearish = false; + + // + isTKISwitchedToBullish = false; + isTKISwitchedToBearish = false; + + // + isTKIFinishedFromBullish = false; + isTKIFinishedFromBearish = false; + + // + // VIDYA ... + + // + isVidyaRejectUp = false; + isVidyaRejectDown = false; + + // + isVidyaBullish = false; + isVidyaBearish = false; + + // + isVidyaSwitchedToBullish = false; + isVidyaSwitchedToBearish = false; + + // + isVidyaFinishedFromBullish = false; + isVidyaFinishedFromBearish = false; + + // + // SAR ... + + // + isSarBullish = false; + isSarBearish = false; + + // + isSarSwitchedToBullish = false; + isSarSwitchedToBearish = false; + + // + isSarFinishedFromBullish = false; + isSarFinishedFromBearish = false; + + // + // MANALYSER ... + + // + // MAH ... + + // + isOverMah = false; + isUnderMah = false; + isCrossedOverMah = false; + isCrossedUnderMah = false; + + // + isCloseOverMah = false; + isCloseUnderMah = false; + isCloseCrossedOverMah = false; + isCloseCrossedUnderMah = false; + + // + isMahBullishRejected = false; + isMahBearishRejected = false; + + // + // MAL ... + + // + isOverMal = false; + isUnderMal = false; + isCrossedOverMal = false; + isCrossedUnderMal = false; + + // + isCloseOverMal = false; + isCloseUnderMal = false; + isCloseCrossedOverMal = false; + isCloseCrossedUnderMal = false; + + // + isMalBullishRejected = false; + isMalBearishRejected = false; + + // + // MAC ... + + // + isOverMac = false; + isUnderMac = false; + isCrossedOverMac = false; + isCrossedUnderMac = false; + + // + isCloseOverMac = false; + isCloseUnderMac = false; + isCloseCrossedOverMac = false; + isCloseCrossedUnderMac = false; + + // + isMacBullishRejected = false; + isMacBearishRejected = false; + + // + // PEAK ... + + // + isPeakSameLast = false; + isPeakOverLast = false; + isPeakUnderLast = false; + + // + // VALE ... + + // + isValeSameLast = false; + isValeOverLast = false; + isValeUnderLast = false; + + // + // TREND ... + + // + isTrendRejectUp = false; + isTrendRejectDown = false; + + // + isTrendBullish = false; + isTrendBearish = false; + + // + isTrendSwitchedToBullish = false; + isTrendSwitchedToBearish = false; + + // + isTrendFinishedFromBullish = false; + isTrendFinishedFromBearish = false; + + // + // SUPPORT ... + + // + isSupportSameLast = false; + isSupportOverLast = false; + isSupportUnderLast = false; + + // + isLastSupportBreaked = false; + isLastSupportRejected = false; + + // + // RESISTANCE ... + + // + isResistanceSameLast = false; + isResistanceOverLast = false; + isResistanceUnderLast = false; + + // + isLastResistanceBreaked = false; + isLastResistanceRejected = false; + + // + // SWING Low ... + + // + isSwingLowSameLast = false; + isSwingLowOverLast = false; + isSwingLowUnderLast = false; + + // + isLastSwingLowBreaked = false; + isLastSwingLowRejected = false; + + // + // SWING High ... + + // + isSwingHighSameLast = false; + isSwingHighOverLast = false; + isSwingHighUnderLast = false; + + // + isLastSwingHighBreaked = false; + isLastSwingHighRejected = false; + + // + // COMPLEX Conditions ... + + // + isPeakIsPivot = false; + isValeIsPivot = false; + + // + isPeakSwitchedToPivot = false; + isValeSwitchedToPivot = false; + + // + isPeakFinishedFromPivot = false; + isValeFinishedFromPivot = false; + + // + isSwingLowSameAsVale = false; + isSwingHighSameAsPeak = false; + + // + isSupportSameAsVale = false; + isResistanceSameAsPeak = false; + + // + isSupportSameAsSwingLow = false; + isResistanceSameAsSwingHigh = false; + + // + ZeroMemory(this); + } + + /** + * Generate Conditions Scores ... + * + * @param bullishScore: Double, Directional Scores Reference ... + * @param bearishScore: Double, Directional Scores Reference ... + */ + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + // + bullishScore = 0; + bearishScore = 0; + + // + double score = 1; + double minScore = 0.5; + double highScore = 1.5; + + // + // KI ... + + // + if (isKIBullish) + { + bullishScore += minScore; + } + if (isKIRejectUp) + { + bullishScore += minScore; + } + if (isKISwitchedToBullish) + { + bullishScore += minScore; + } + + // + if (isKIBearish) + { + bearishScore += minScore; + } + if (isKIRejectDown) + { + bearishScore += minScore; + } + if (isKISwitchedToBearish) + { + bearishScore += minScore; + } + + // + // TKI ... + + // + if (isTKIBullish) + { + bullishScore += minScore; + } + if (isTKIRejectUp) + { + bullishScore += minScore; + } + if (isTKISwitchedToBullish) + { + bullishScore += minScore; + } + + // + if (isTKIBearish) + { + bearishScore += minScore; + } + if (isTKIRejectDown) + { + bearishScore += minScore; + } + if (isTKISwitchedToBearish) + { + bearishScore += minScore; + } + + // + // VIDYA ... + + // + if (isVidyaBullish) + { + bullishScore += minScore; + } + if (isVidyaRejectUp) + { + bullishScore += minScore; + } + if (isVidyaSwitchedToBullish) + { + bullishScore += minScore; + } + + // + if (isVidyaBearish) + { + bearishScore += minScore; + } + if (isVidyaRejectDown) + { + bearishScore += minScore; + } + if (isVidyaSwitchedToBearish) + { + bearishScore += minScore; + } + + // + // SAR ... + + // + if (isSarBullish) + { + bullishScore += minScore; + } + if (isSarSwitchedToBullish) + { + bullishScore += minScore; + } + + // + if (isSarBearish) + { + bearishScore += minScore; + } + if (isSarSwitchedToBearish) + { + bearishScore += minScore; + } + + // + // MANALYSER ... + + // + // MAH ... + + // + if (isUnderMah) + { + bullishScore += minScore; + } + if (isCloseUnderMah) + { + bullishScore += minScore; + } + if (isCrossedUnderMah) + { + bullishScore += minScore; + } + if (isMahBullishRejected) + { + bullishScore += minScore; + } + if (isCloseCrossedUnderMah) + { + bullishScore += minScore; + } + + // + if (isOverMah) + { + bearishScore += minScore; + } + if (isCloseOverMah) + { + bearishScore += minScore; + } + if (isCrossedOverMah) + { + bearishScore += minScore; + } + if (isMahBearishRejected) + { + bearishScore += minScore; + } + if (isCloseCrossedOverMah) + { + bearishScore += minScore; + } + + // + + // + // MAL ... + + // + if (isOverMal) + { + bullishScore += minScore; + } + if (isCloseOverMal) + { + bullishScore += minScore; + } + if (isCrossedOverMal) + { + bullishScore += minScore; + } + if (isMalBullishRejected) + { + bullishScore += minScore; + } + if (isCloseCrossedOverMal) + { + bullishScore += minScore; + } + + // + if (isUnderMal) + { + bearishScore += minScore; + } + if (isCloseUnderMal) + { + bearishScore += minScore; + } + if (isCrossedUnderMal) + { + bearishScore += minScore; + } + if (isMalBearishRejected) + { + bearishScore += minScore; + } + if (isCloseCrossedUnderMal) + { + bearishScore += minScore; + } + + // + // MAC ... + + // + if (isOverMac) + { + bullishScore += minScore; + } + if (isCloseOverMac) + { + bullishScore += minScore; + } + if (isCrossedOverMac) + { + bullishScore += minScore; + } + if (isMacBullishRejected) + { + bullishScore += minScore; + } + if (isCloseCrossedOverMac) + { + bullishScore += minScore; + } + + // + if (isUnderMac) + { + bearishScore += minScore; + } + if (isCloseUnderMac) + { + bearishScore += minScore; + } + if (isCrossedUnderMac) + { + bearishScore += minScore; + } + if (isMacBearishRejected) + { + bearishScore += minScore; + } + if (isCloseCrossedUnderMac) + { + bearishScore += minScore; + } + + // + // TREND ... + + // + if (isTrendBullish) + { + bullishScore += minScore; + } + if (isTrendRejectUp) + { + bullishScore += minScore; + } + if (isTrendSwitchedToBullish) + { + bullishScore += minScore; + } + + // + if (isTrendBearish) + { + bearishScore += minScore; + } + if (isTrendRejectDown) + { + bearishScore += minScore; + } + if (isTrendSwitchedToBearish) + { + bearishScore += minScore; + } + + // + // SUPPORT ... + + // + if (isSupportSameLast) + { + bullishScore += minScore; + } + if (isSupportOverLast) + { + bullishScore += minScore; + } + if (isLastSupportRejected) + { + bullishScore += minScore; + } + + // + if (isSupportUnderLast) + { + bearishScore += minScore; + } + if (isLastSupportBreaked) + { + bearishScore += minScore; + } + + // + // RESISTANCE ... + + // + if (isResistanceOverLast) + { + bullishScore += minScore; + } + if (isLastResistanceBreaked) + { + bullishScore += minScore; + } + + // + if (isResistanceSameLast) + { + bearishScore += minScore; + } + if (isResistanceUnderLast) + { + bearishScore += minScore; + } + if (isLastResistanceRejected) + { + bearishScore += minScore; + } + + // + // SWING Low ... + + // + if (isSwingLowSameLast) + { + bullishScore += minScore; + } + if (isSwingLowOverLast) + { + bullishScore += minScore; + } + if (isLastSwingLowRejected) + { + bullishScore += minScore; + } + + // + if (isSwingLowUnderLast) + { + bearishScore += minScore; + } + if (isLastSwingLowBreaked) + { + bearishScore += minScore; + } + + // + // SWING High ... + + // + if (isSwingHighOverLast) + { + bullishScore += minScore; + } + if (isLastSwingHighBreaked) + { + bullishScore += minScore; + } + + // + if (isSwingHighSameLast) + { + bearishScore += minScore; + } + if (isSwingHighUnderLast) + { + bearishScore += minScore; + } + if (isLastSwingHighRejected) + { + bearishScore += minScore; + } + + // + // COMPLEX Conditions ... + + // + if (isValeIsPivot) + { + bullishScore += score; + } + if (isSupportSameAsVale) + { + bullishScore += score; + } + if (isSwingLowSameAsVale) + { + bullishScore += score; + } + if (isSupportSameAsSwingLow) + { + bullishScore += score; + } + + // + if (isPeakIsPivot) + { + bearishScore += score; + } + if (isSwingHighSameAsPeak) + { + bearishScore += score; + } + if (isResistanceSameAsPeak) + { + bearishScore += score; + } + if (isResistanceSameAsSwingHigh) + { + bearishScore += score; + } + + // + } + + /** + * Generate Summary String for Represent Conditions State ... + * + * @param onlyCommons: Boolean, Just Generate Only Commons Conditions ... + * @param onlyConditions: Boolean, Just Generate Only Conditions ... + * @param includeScores: Boolean, Attach Scores Representations on Result ... + * @param ignoreFalseConditions: Boolean, Ignore False Conditions on Result ... + * @param separator: String, Separate Lines ... + * + * @return ( string ) + */ + string GenerateSummary( + bool onlyCommons = false, + bool onlyConditions = false, + bool includeScores = true, + bool ignoreFalseConditions = true, + string separator = "\n" // + ) + { + // + string result = NULL; + + // + double bullishScore = 0; + double bearishScore = 0; + GenerateScore( + bullishScore, + bearishScore // + ); + + // + string scoresStr = + // + "Scores: " + separator + + "---------------" + separator + + "Bullish: " + ToString(bullishScore) + separator + + "Bearish: " + ToString(bearishScore) + separator + + "" + // + ; + + // + string commonStr = GenerateSpecifiedCommonSummary( + this, + separator, + includeScores // + ); + + // + string conditionsStr = + // + "-----------------------" + separator + + "XCA: " + separator + + "-----------------------" + separator + + ToString("isKIRejectUp", isKIRejectUp, ignoreFalseConditions, separator) + + ToString("isKIRejectDown", isKIRejectDown, ignoreFalseConditions, separator) + + ToString("isKIBullish", isKIBullish, ignoreFalseConditions, separator) + + ToString("isKIBearish", isKIBearish, ignoreFalseConditions, separator) + + ToString("isKISwitchedToBullish", isKISwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isKIFinishedFromBullish", isKIFinishedFromBullish, ignoreFalseConditions, separator) + + ToString("isKISwitchedToBearish", isKISwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isKIFinishedFromBearish", isKIFinishedFromBearish, ignoreFalseConditions, separator) + + ToString("isTKIRejectUp", isTKIRejectUp, ignoreFalseConditions, separator) + + ToString("isTKIRejectDown", isTKIRejectDown, ignoreFalseConditions, separator) + + ToString("isTKIBullish", isTKIBullish, ignoreFalseConditions, separator) + + ToString("isTKIBearish", isTKIBearish, ignoreFalseConditions, separator) + + ToString("isTKISwitchedToBullish", isTKISwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isTKIFinishedFromBullish", isTKIFinishedFromBullish, ignoreFalseConditions, separator) + + ToString("isTKISwitchedToBearish", isTKISwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isTKIFinishedFromBearish", isTKIFinishedFromBearish, ignoreFalseConditions, separator) + + ToString("isVidyaRejectUp", isVidyaRejectUp, ignoreFalseConditions, separator) + + ToString("isVidyaRejectDown", isVidyaRejectDown, ignoreFalseConditions, separator) + + ToString("isVidyaBullish", isVidyaBullish, ignoreFalseConditions, separator) + + ToString("isVidyaBearish", isVidyaBearish, ignoreFalseConditions, separator) + + ToString("isVidyaSwitchedToBullish", isVidyaSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isVidyaFinishedFromBullish", isVidyaFinishedFromBullish, ignoreFalseConditions, separator) + + ToString("isVidyaSwitchedToBearish", isVidyaSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isVidyaFinishedFromBearish", isVidyaFinishedFromBearish, ignoreFalseConditions, separator) + + ToString("isSarBullish", isSarBullish, ignoreFalseConditions, separator) + + ToString("isSarBearish", isSarBearish, ignoreFalseConditions, separator) + + ToString("isSarSwitchedToBullish", isSarSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isSarFinishedFromBullish", isSarFinishedFromBullish, ignoreFalseConditions, separator) + + ToString("isSarSwitchedToBearish", isSarSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isSarFinishedFromBearish", isSarFinishedFromBearish, ignoreFalseConditions, separator) + + ToString("isOverMah", isOverMah, ignoreFalseConditions, separator) + + ToString("isUnderMah", isUnderMah, ignoreFalseConditions, separator) + + ToString("isCrossedOverMah", isCrossedOverMah, ignoreFalseConditions, separator) + + ToString("isCrossedUnderMah", isCrossedUnderMah, ignoreFalseConditions, separator) + + ToString("isCloseOverMah", isCloseOverMah, ignoreFalseConditions, separator) + + ToString("isCloseUnderMah", isCloseUnderMah, ignoreFalseConditions, separator) + + ToString("isCloseCrossedOverMah", isCloseCrossedOverMah, ignoreFalseConditions, separator) + + ToString("isCloseCrossedUnderMah", isCloseCrossedUnderMah, ignoreFalseConditions, separator) + + ToString("isMahBullishRejected", isMahBullishRejected, ignoreFalseConditions, separator) + + ToString("isMahBearishRejected", isMahBearishRejected, ignoreFalseConditions, separator) + + ToString("isOverMal", isOverMal, ignoreFalseConditions, separator) + + ToString("isUnderMal", isUnderMal, ignoreFalseConditions, separator) + + ToString("isCrossedOverMal", isCrossedOverMal, ignoreFalseConditions, separator) + + ToString("isCrossedUnderMal", isCrossedUnderMal, ignoreFalseConditions, separator) + + ToString("isCloseOverMal", isCloseOverMal, ignoreFalseConditions, separator) + + ToString("isCloseUnderMal", isCloseUnderMal, ignoreFalseConditions, separator) + + ToString("isCloseCrossedOverMal", isCloseCrossedOverMal, ignoreFalseConditions, separator) + + ToString("isCloseCrossedUnderMal", isCloseCrossedUnderMal, ignoreFalseConditions, separator) + + ToString("isMalBullishRejected", isMalBullishRejected, ignoreFalseConditions, separator) + + ToString("isMalBearishRejected", isMalBearishRejected, ignoreFalseConditions, separator) + + ToString("isOverMac", isOverMac, ignoreFalseConditions, separator) + + ToString("isUnderMac", isUnderMac, ignoreFalseConditions, separator) + + ToString("isCrossedOverMac", isCrossedOverMac, ignoreFalseConditions, separator) + + ToString("isCrossedUnderMac", isCrossedUnderMac, ignoreFalseConditions, separator) + + ToString("isCloseOverMac", isCloseOverMac, ignoreFalseConditions, separator) + + ToString("isCloseUnderMac", isCloseUnderMac, ignoreFalseConditions, separator) + + ToString("isCloseCrossedOverMac", isCloseCrossedOverMac, ignoreFalseConditions, separator) + + ToString("isCloseCrossedUnderMac", isCloseCrossedUnderMac, ignoreFalseConditions, separator) + + ToString("isMacBullishRejected", isMacBullishRejected, ignoreFalseConditions, separator) + + ToString("isMacBearishRejected", isMacBearishRejected, ignoreFalseConditions, separator) + + ToString("isPeakSameLast", isPeakSameLast, ignoreFalseConditions, separator) + + ToString("isPeakOverLast", isPeakOverLast, ignoreFalseConditions, separator) + + ToString("isPeakUnderLast", isPeakUnderLast, ignoreFalseConditions, separator) + + ToString("isValeSameLast", isValeSameLast, ignoreFalseConditions, separator) + + ToString("isValeOverLast", isValeOverLast, ignoreFalseConditions, separator) + + ToString("isValeUnderLast", isValeUnderLast, ignoreFalseConditions, separator) + + ToString("isTrendRejectUp", isTrendRejectUp, ignoreFalseConditions, separator) + + ToString("isTrendRejectDown", isTrendRejectDown, ignoreFalseConditions, separator) + + ToString("isTrendBullish", isTrendBullish, ignoreFalseConditions, separator) + + ToString("isTrendBearish", isTrendBearish, ignoreFalseConditions, separator) + + ToString("isTrendSwitchedToBullish", isTrendSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isTrendFinishedFromBullish", isTrendFinishedFromBullish, ignoreFalseConditions, separator) + + ToString("isTrendSwitchedToBearish", isTrendSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isTrendFinishedFromBearish", isTrendFinishedFromBearish, ignoreFalseConditions, separator) + + ToString("isSupportSameLast", isSupportSameLast, ignoreFalseConditions, separator) + + ToString("isSupportOverLast", isSupportOverLast, ignoreFalseConditions, separator) + + ToString("isSupportUnderLast", isSupportUnderLast, ignoreFalseConditions, separator) + + ToString("isLastSupportBreaked", isLastSupportBreaked, ignoreFalseConditions, separator) + + ToString("isLastSupportRejected", isLastSupportRejected, ignoreFalseConditions, separator) + + ToString("isResistanceSameLast", isResistanceSameLast, ignoreFalseConditions, separator) + + ToString("isResistanceOverLast", isResistanceOverLast, ignoreFalseConditions, separator) + + ToString("isResistanceUnderLast", isResistanceUnderLast, ignoreFalseConditions, separator) + + ToString("isLastResistanceBreaked", isLastResistanceBreaked, ignoreFalseConditions, separator) + + ToString("isLastResistanceRejected", isLastResistanceRejected, ignoreFalseConditions, separator) + + ToString("isSwingLowSameLast", isSwingLowSameLast, ignoreFalseConditions, separator) + + ToString("isSwingLowOverLast", isSwingLowOverLast, ignoreFalseConditions, separator) + + ToString("isSwingLowUnderLast", isSwingLowUnderLast, ignoreFalseConditions, separator) + + ToString("isLastSwingLowBreaked", isLastSwingLowBreaked, ignoreFalseConditions, separator) + + ToString("isLastSwingLowRejected", isLastSwingLowRejected, ignoreFalseConditions, separator) + + ToString("isSwingHighSameLast", isSwingHighSameLast, ignoreFalseConditions, separator) + + ToString("isSwingHighOverLast", isSwingHighOverLast, ignoreFalseConditions, separator) + + ToString("isSwingHighUnderLast", isSwingHighUnderLast, ignoreFalseConditions, separator) + + ToString("isLastSwingHighBreaked", isLastSwingHighBreaked, ignoreFalseConditions, separator) + + ToString("isLastSwingHighRejected", isLastSwingHighRejected, ignoreFalseConditions, separator) + + ToString("isPeakIsPivot", isPeakIsPivot, ignoreFalseConditions, separator) + + ToString("isValeIsPivot", isValeIsPivot, ignoreFalseConditions, separator) + + ToString("isPeakSwitchedToPivot", isPeakSwitchedToPivot, ignoreFalseConditions, separator) + + ToString("isPeakFinishedFromPivot", isPeakFinishedFromPivot, ignoreFalseConditions, separator) + + ToString("isValeSwitchedToPivot", isValeSwitchedToPivot, ignoreFalseConditions, separator) + + ToString("isValeFinishedFromPivot", isValeFinishedFromPivot, ignoreFalseConditions, separator) + + ToString("isSwingLowSameAsVale", isSwingLowSameAsVale, ignoreFalseConditions, separator) + + ToString("isSwingHighSameAsPeak", isSwingHighSameAsPeak, ignoreFalseConditions, separator) + + ToString("isSupportSameAsVale", isSupportSameAsVale, ignoreFalseConditions, separator) + + ToString("isResistanceSameAsPeak", isResistanceSameAsPeak, ignoreFalseConditions, separator) + + ToString("isSupportSameAsSwingLow", isSupportSameAsSwingLow, ignoreFalseConditions, separator) + + ToString("isResistanceSameAsSwingHigh", isResistanceSameAsSwingHigh, ignoreFalseConditions, separator) + + // + "" + // + ; + + // + result = + // + "[" + GetTag() + "]" + separator + + (onlyConditions + ? "" + : commonStr) + + (!includeScores + ? "" + : scoresStr) + + " " + separator + + (onlyCommons + ? "" + : conditionsStr) + + "" + // + ; + + // + return result; + } + + /** + * Retrieve nique Tag Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + return GetTypeName(this); + } + + // +}; + +// +// Class ... +class XCX121XCAHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructors ... + XCX121XCAHelper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCX121XCAHelper() + { + // + mInputs.Clean(); + + // + Clean(kiBuffer); + Clean(tkiBuffer); + Clean(sHHBuffer); + Clean(sLLBuffer); + Clean(mHHBuffer); + Clean(mLLBuffer); + Clean(lHHBuffer); + Clean(lLLBuffer); + Clean(hHHBuffer); + Clean(hLLBuffer); + Clean(sarBuffer); + Clean(mahBuffer); + Clean(malBuffer); + Clean(macBuffer); + Clean(peakBuffer); + Clean(valeBuffer); + Clean(vidyaBuffer); + Clean(trendBuffer); + Clean(kiStateBuffer); + Clean(supportBuffer); + Clean(tkiStateBuffer); + Clean(swingLowBuffer); + Clean(swingHighBuffer); + Clean(resistanceBuffer); + Clean(peakGoldenBuffer); + Clean(valeGoldenBuffer); + Clean(fiboLevel1Buffer); + Clean(fiboLevel2Buffer); + Clean(fiboLevel3Buffer); + Clean(fiboLevel4Buffer); + Clean(fiboLevel5Buffer); + Clean(trendStateBuffer); + Clean(vidyaStateBuffer); + } + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + X121XCAInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + ArraySetAsSeries(kiBuffer, true); + ArraySetAsSeries(tkiBuffer, true); + ArraySetAsSeries(sHHBuffer, true); + ArraySetAsSeries(sLLBuffer, true); + ArraySetAsSeries(mHHBuffer, true); + ArraySetAsSeries(mLLBuffer, true); + ArraySetAsSeries(lHHBuffer, true); + ArraySetAsSeries(lLLBuffer, true); + ArraySetAsSeries(hHHBuffer, true); + ArraySetAsSeries(hLLBuffer, true); + ArraySetAsSeries(sarBuffer, true); + ArraySetAsSeries(mahBuffer, true); + ArraySetAsSeries(malBuffer, true); + ArraySetAsSeries(macBuffer, true); + ArraySetAsSeries(peakBuffer, true); + ArraySetAsSeries(valeBuffer, true); + ArraySetAsSeries(vidyaBuffer, true); + ArraySetAsSeries(trendBuffer, true); + ArraySetAsSeries(kiStateBuffer, true); + ArraySetAsSeries(supportBuffer, true); + ArraySetAsSeries(tkiStateBuffer, true); + ArraySetAsSeries(swingLowBuffer, true); + ArraySetAsSeries(swingHighBuffer, true); + ArraySetAsSeries(resistanceBuffer, true); + ArraySetAsSeries(peakGoldenBuffer, true); + ArraySetAsSeries(valeGoldenBuffer, true); + ArraySetAsSeries(fiboLevel1Buffer, true); + ArraySetAsSeries(fiboLevel2Buffer, true); + ArraySetAsSeries(fiboLevel3Buffer, true); + ArraySetAsSeries(fiboLevel4Buffer, true); + ArraySetAsSeries(fiboLevel5Buffer, true); + ArraySetAsSeries(vidyaStateBuffer, true); + ArraySetAsSeries(trendStateBuffer, true); + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.xca", + "", // Market ... + "", // Short ... + mInputs.scMethod, + mInputs.scPeriod, + "", // Medium ... + mInputs.mcMethod, + mInputs.mcPeriod, + "", // Long ... + mInputs.lcMethod, + mInputs.lcPeriod, + "", // Hind ... + mInputs.hcMethod, + mInputs.hcPeriod, + "", // Boundary Detection ... + mInputs.hhMode, + mInputs.llMode, + "", // Fibo Levels ... + mInputs.fiboLevel1, + mInputs.fiboLevel2, + mInputs.fiboLevel3, + mInputs.fiboLevel4, + mInputs.fiboLevel5, + "", // Sar Detection ... + mInputs.sarStep, + mInputs.sarMax, + "", // KI ... + mInputs.kiLength, + "", // VIDYA ... + mInputs.vidyaCMOLength, + mInputs.vidyaEMALength, + mInputs.vidyaAppliedTo, + "", // MANALYSER ... + mInputs.manalyserLength, + mInputs.manalyserMethod, + "", // Swing Detection ... + mInputs.swingLength, + "", // Support and Resistance ... + mInputs.supResSmoothingLength, + mInputs.supResSmoothingMode, + "", // Presentation ... + mInputs.startCalculationForLastBars, + mInputs.showSar, + mInputs.showKI, + mInputs.showTKI, + mInputs.showMAH, + mInputs.showMAL, + mInputs.showMAC, + mInputs.showVidya, + mInputs.showTrend, + mInputs.showSwings, + mInputs.showFiboLevel1, + mInputs.showFiboLevel2, + mInputs.showFiboLevel3, + mInputs.showFiboLevel4, + mInputs.showFiboLevel5, + mInputs.showPeaksAndVales, + mInputs.showPeakAndValeGolden, + mInputs.showSupportAndResistance // + // mInputs.showShortCycle, + // mInputs.showMediumCycle, + // mInputs.showLongCycle, + // mInputs.showHindCycle // , + // + // mInputs.sarArrowCode, + // mInputs.peakArrowCode, + // mInputs.valeArrowCode, + // mInputs.swingLowArrowCode, + // mInputs.swingHighArrowCode + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + X121XCAInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + X121XCAInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Readers ... + + // + // KI ... + + // + double GetKI( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(kiBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return kiBuffer[barIndex]; + } + + // + int CopyKI( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + kiBuffer, + buffer, + forceClean + // + ); + } + + // + // KI STATE ... + + // + double GetKIState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(kiStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return kiStateBuffer[barIndex]; + } + + // + int CopyKIState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + kiStateBuffer, + buffer, + forceClean + // + ); + } + + // + // TKI ... + + // + double GetTKI( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(tkiBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return tkiBuffer[barIndex]; + } + + // + int CopyTKI( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + tkiBuffer, + buffer, + forceClean + // + ); + } + + // + // TKI STATE ... + + // + double GetTKIState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(tkiStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return tkiStateBuffer[barIndex]; + } + + // + int CopyTKIState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + tkiStateBuffer, + buffer, + forceClean + // + ); + } + + // + // VIDYA ... + + // + double GetVidya( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(vidyaBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return vidyaBuffer[barIndex]; + } + + // + int CopyVidya( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + vidyaBuffer, + buffer, + forceClean + // + ); + } + + // + // VIDYA STATE ... + + // + double GetVidyaState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(vidyaStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return vidyaStateBuffer[barIndex]; + } + + // + int CopyVidyaState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + vidyaStateBuffer, + buffer, + forceClean + // + ); + } + + // + // SHORT ... + + // + // HH ... + + // + double GetSHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(sHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return sHHBuffer[barIndex]; + } + + // + int CopySHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + sHHBuffer, + buffer, + forceClean + // + ); + } + + // + // LL ... + + // + double GetSLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(sLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return sLLBuffer[barIndex]; + } + + // + int CopySLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + sLLBuffer, + buffer, + forceClean + // + ); + } + + // + // MEDIUM ... + + // + // HH ... + + // + double GetMHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(mHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return mHHBuffer[barIndex]; + } + + // + int CopyMHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + mHHBuffer, + buffer, + forceClean + // + ); + } + + // + // LL ... + + // + double GetMLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(mLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return mLLBuffer[barIndex]; + } + + // + int CopyMLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + mLLBuffer, + buffer, + forceClean + // + ); + } + + // + // LONG ... + + // + // HH ... + + // + double GetLHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(lHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return lHHBuffer[barIndex]; + } + + // + int CopyLHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + lHHBuffer, + buffer, + forceClean + // + ); + } + + // + // LL ... + + // + double GetLLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(lLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return lLLBuffer[barIndex]; + } + + // + int CopyLLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + lLLBuffer, + buffer, + forceClean + // + ); + } + + // + // HIND ... + + // + // HH ... + + // + double GetHHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hHHBuffer[barIndex]; + } + + // + int CopyHHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hHHBuffer, + buffer, + forceClean + // + ); + } + + // + // LL ... + + // + double GetHLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hLLBuffer[barIndex]; + } + + // + int CopyHLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hLLBuffer, + buffer, + forceClean + // + ); + } + + // + // SAR ... + + // + double GetSar( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(sarBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return sarBuffer[barIndex]; + } + + // + 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(start); + + // + // Copy Items ... + return Copy( + 0, + count, + sarBuffer, + buffer, + forceClean + // + ); + } + + // + // MANALYSER ... + + // + // MAH ... + + // + double GetMah( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(mahBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return mahBuffer[barIndex]; + } + + // + int CopyMah( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + mahBuffer, + buffer, + forceClean + // + ); + } + + // + // MAL ,,, + + // + double GetMal( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(malBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return malBuffer[barIndex]; + } + + // + int CopyMal( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + malBuffer, + buffer, + forceClean + // + ); + } + + // + // MAC ... + + // + double GetMac( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(macBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return macBuffer[barIndex]; + } + + // + int CopyMac( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + macBuffer, + buffer, + forceClean + // + ); + } + + // + // PEAK ... + + // + double GetPeak( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(peakBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return peakBuffer[barIndex]; + } + + // + 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(start); + + // + // Copy Items ... + return Copy( + 0, + count, + peakBuffer, + buffer, + forceClean + // + ); + } + + // + // PEAK Golden ... + + // + double GetPeakGolden( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(peakGoldenBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return peakGoldenBuffer[barIndex]; + } + + // + int CopyPeakGolden( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + peakGoldenBuffer, + buffer, + forceClean + // + ); + } + + // + // VALE ... + + // + double GetVale( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(valeBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return valeBuffer[barIndex]; + } + + // + 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(start); + + // + // Copy Items ... + return Copy( + 0, + count, + valeBuffer, + buffer, + forceClean + // + ); + } + + // + // VALE Golden ... + + // + double GetValeGolden( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(valeGoldenBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return valeGoldenBuffer[barIndex]; + } + + // + int CopyValeGolden( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + valeGoldenBuffer, + buffer, + forceClean + // + ); + } + + // + // TREND ... + + // + double GetTrend( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(trendBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return trendBuffer[barIndex]; + } + + // + 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(start); + + // + // Copy Items ... + return Copy( + 0, + count, + trendBuffer, + buffer, + forceClean + // + ); + } + + // + // TREND ... + + // + double GetTrendState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(trendStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return trendStateBuffer[barIndex]; + } + + // + int CopyTrendState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + trendStateBuffer, + buffer, + forceClean + // + ); + } + + // + // SUPPORT ... + + // + double GetSupport( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(supportBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return supportBuffer[barIndex]; + } + + // + 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(start); + + // + // Copy Items ... + return Copy( + 0, + count, + supportBuffer, + buffer, + forceClean + // + ); + } + + // + // RESISTANCE ... + + // + double GetResistance( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(resistanceBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return resistanceBuffer[barIndex]; + } + + // + 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(start); + + // + // Copy Items ... + return Copy( + 0, + count, + resistanceBuffer, + buffer, + forceClean + // + ); + } + + // + // SWING Low ... + + // + double GetSwingLow( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(swingLowBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return swingLowBuffer[barIndex]; + } + + // + int CopySwingLow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + swingLowBuffer, + buffer, + forceClean + // + ); + } + + // + // SWING High ... + + // + double GetSwingHigh( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(swingHighBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return swingHighBuffer[barIndex]; + } + + // + int CopySwingHigh( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + swingHighBuffer, + buffer, + forceClean + // + ); + } + + // + // FIBO Level 1 ... + + // + double GetFiboLevel1( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(fiboLevel1Buffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fiboLevel1Buffer[barIndex]; + } + + // + int CopyFiboLevel1( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + fiboLevel1Buffer, + buffer, + forceClean + // + ); + } + + // + // FIBO Level 2 ... + + // + double GetFiboLevel2( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(fiboLevel2Buffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fiboLevel2Buffer[barIndex]; + } + + // + int CopyFiboLevel2( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + fiboLevel2Buffer, + buffer, + forceClean + // + ); + } + + // + // FIBO Level 3 ... + + // + double GetFiboLevel3( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(fiboLevel3Buffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fiboLevel3Buffer[barIndex]; + } + + // + int CopyFiboLevel3( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + fiboLevel3Buffer, + buffer, + forceClean + // + ); + } + + // + // FIBO Level 4 ... + + // + double GetFiboLevel4( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(fiboLevel4Buffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fiboLevel4Buffer[barIndex]; + } + + // + int CopyFiboLevel4( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + fiboLevel4Buffer, + buffer, + forceClean + // + ); + } + + // + // FIBO Level 5 ... + + // + double GetFiboLevel5( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(fiboLevel5Buffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fiboLevel5Buffer[barIndex]; + } + + // + int CopyFiboLevel5( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + fiboLevel5Buffer, + buffer, + forceClean + // + ); + } + + // + void Free() override + { + Cleanup(10); + } + + // + bool GetConditions( + X121XCAConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = true; + + // + if (loopback < 5) + { + loopback = 5; + } + + // + conditions.Clean(); + + // + conditions.symbol = mSymbol; + conditions.period = mPeriod; + conditions.time = TimeCurrent(); + + // + int zIndex = barIndex; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + XOHCL zBar; + result = zBar.Init( + mSymbol, + mPeriod, + zIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL cBar; + result = cBar.Init( + mSymbol, + mPeriod, + cIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL pBar; + result = pBar.Init( + mSymbol, + mPeriod, + pIndex // + ); + if (!result) + { + return result; + } + + // + // Buffers ... + + // + CopyKI( + zIndex, + loopback, + conditions.kiBuffer // + ); + + // + CopyKIState( + zIndex, + loopback, + conditions.kiStateBuffer // + ); + + // + CopyTKI( + zIndex, + loopback, + conditions.tkiBuffer // + ); + + // + CopyTKIState( + zIndex, + loopback, + conditions.tkiStateBuffer // + ); + + // + CopyVidya( + zIndex, + loopback, + conditions.vidyaBuffer // + ); + + // + CopyVidyaState( + zIndex, + loopback, + conditions.vidyaStateBuffer // + ); + + // + CopySHH( + zIndex, + loopback, + conditions.sHHBuffer // + ); + + // + CopySLL( + zIndex, + loopback, + conditions.sLLBuffer // + ); + + // + CopyMHH( + zIndex, + loopback, + conditions.mHHBuffer // + ); + + // + CopyMLL( + zIndex, + loopback, + conditions.mLLBuffer // + ); + + // + CopyLHH( + zIndex, + loopback, + conditions.lHHBuffer // + ); + + // + CopyLLL( + zIndex, + loopback, + conditions.lLLBuffer // + ); + + // + CopyHHH( + zIndex, + loopback, + conditions.hHHBuffer // + ); + + // + CopyHLL( + zIndex, + loopback, + conditions.hLLBuffer // + ); + + // + CopySar( + zIndex, + loopback, + conditions.sarBuffer // + ); + + // + CopyMah( + zIndex, + loopback, + conditions.mahBuffer // + ); + + // + CopyMal( + zIndex, + loopback, + conditions.malBuffer // + ); + + // + CopyMac( + zIndex, + loopback, + conditions.macBuffer // + ); + + // + CopyPeak( + zIndex, + loopback, + conditions.peakBuffer // + ); + + // + CopyPeakGolden( + zIndex, + loopback, + conditions.peakGoldenBuffer // + ); + + // + CopyVale( + zIndex, + loopback, + conditions.valeBuffer // + ); + + // + CopyValeGolden( + zIndex, + loopback, + conditions.valeGoldenBuffer // + ); + + // + CopyTrend( + zIndex, + loopback, + conditions.trendBuffer // + ); + + // + CopyTrendState( + zIndex, + loopback, + conditions.trendStateBuffer // + ); + + // + CopySupport( + zIndex, + loopback, + conditions.supportBuffer // + ); + + // + CopyResistance( + zIndex, + loopback, + conditions.resistanceBuffer // + ); + + // + CopySwingLow( + zIndex, + loopback, + conditions.swingLowBuffer // + ); + + // + CopySwingHigh( + zIndex, + loopback, + conditions.swingHighBuffer // + ); + + // + CopyFiboLevel1( + zIndex, + loopback, + conditions.fiboLevel1Buffer // + ); + + // + CopyFiboLevel2( + zIndex, + loopback, + conditions.fiboLevel2Buffer // + ); + + // + CopyFiboLevel3( + zIndex, + loopback, + conditions.fiboLevel3Buffer // + ); + + // + CopyFiboLevel4( + zIndex, + loopback, + conditions.fiboLevel4Buffer // + ); + + // + CopyFiboLevel5( + zIndex, + loopback, + conditions.fiboLevel5Buffer // + ); + + // + // Conditions ... + + // + int zIDX = 0; + int cIDX = 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + int p3IDX = p2IDX + 1; + int p4IDX = p3IDX + 1; + + // + // Calculate ... + + // + // KI ... + + // + double cKI = conditions.kiBuffer[cIDX]; + double pKI = conditions.kiBuffer[pIDX]; + double p2KI = conditions.kiBuffer[p2IDX]; + + // + double cKIState = conditions.kiStateBuffer[cIDX]; + double pKIState = conditions.kiStateBuffer[pIDX]; + double p2KIState = conditions.kiStateBuffer[p2IDX]; + + // + bool isKIRejectUp = cBar.IsRejected( + cKI, + X_DIRECTION_BULLISH, + false, + false // + ); + bool isKIRejectDown = cBar.IsRejected( + cKI, + X_DIRECTION_BEARISH, + false, + false // + ); + + // + bool isKIBullish = cKIState > 0; + bool isKIBullishPrev = pKIState > 0; + + // + bool isKIBearish = cKIState < 0; + bool isKIBearishPrev = pKIState < 0; + + // + bool isKISwitchedToBullish = isKIBullish && + !isKIBullishPrev; + bool isKIFinishedFromBullish = !isKIBullish && + isKIBullishPrev; + + // + bool isKISwitchedToBearish = isKIBearish && + !isKIBearishPrev; + bool isKIFinishedFromBearish = !isKIBearish && + isKIBearishPrev; + + // + // TKI ... + + // + double cTKI = conditions.tkiBuffer[cIDX]; + double pTKI = conditions.tkiBuffer[pIDX]; + double p2TKI = conditions.tkiBuffer[p2IDX]; + + // + double cTKIState = conditions.tkiStateBuffer[cIDX]; + double pTKIState = conditions.tkiStateBuffer[pIDX]; + double p2TKIState = conditions.tkiStateBuffer[p2IDX]; + + // + bool isTKIRejectUp = cBar.IsRejected( + cTKI, + X_DIRECTION_BULLISH, + false, + false // + ); + bool isTKIRejectDown = cBar.IsRejected( + cTKI, + X_DIRECTION_BEARISH, + false, + false // + ); + + // + bool isTKIBullish = cTKIState > 0; + bool isTKIBullishPrev = pTKIState > 0; + + // + bool isTKIBearish = cTKIState < 0; + bool isTKIBearishPrev = pTKIState < 0; + + // + bool isTKISwitchedToBullish = isTKIBullish && + !isTKIBullishPrev; + bool isTKIFinishedFromBullish = !isTKIBullish && + isTKIBullishPrev; + + // + bool isTKISwitchedToBearish = isTKIBearish && + !isTKIBearishPrev; + bool isTKIFinishedFromBearish = !isTKIBearish && + isTKIBearishPrev; + + // + // VIDYA ... + + // + double cVidya = conditions.vidyaBuffer[cIDX]; + double pVidya = conditions.vidyaBuffer[pIDX]; + double p2Vidya = conditions.vidyaBuffer[p2IDX]; + + // + double cVidyaState = conditions.vidyaStateBuffer[cIDX]; + double pVidyaState = conditions.vidyaStateBuffer[pIDX]; + double p2VidyaState = conditions.vidyaStateBuffer[p2IDX]; + + // + bool isVidyaRejectUp = cBar.IsRejected( + cVidya, + X_DIRECTION_BULLISH, + false, + false // + ); + bool isVidyaRejectDown = cBar.IsRejected( + cVidya, + X_DIRECTION_BEARISH, + false, + false // + ); + + // + bool isVidyaBullish = cVidyaState > 0; + bool isVidyaBullishPrev = pVidyaState > 0; + + // + bool isVidyaBearish = cVidyaState < 0; + bool isVidyaBearishPrev = pVidyaState < 0; + + // + bool isVidyaSwitchedToBullish = isVidyaBullish && + !isVidyaBullishPrev; + bool isVidyaFinishedFromBullish = !isVidyaBullish && + isVidyaBullishPrev; + + // + bool isVidyaSwitchedToBearish = isVidyaBearish && + !isVidyaBearishPrev; + bool isVidyaFinishedFromBearish = !isVidyaBearish && + isVidyaBearishPrev; + + // + // SAR ... + + // + double cSar = conditions.sarBuffer[cIDX]; + double pSar = conditions.sarBuffer[pIDX]; + + // + bool isSarBullish = cBar.low > cSar; + bool isSarBullishPrev = pBar.low > pSar; + + // + bool isSarBearish = cBar.high < cSar; + bool isSarBearishPrev = pBar.high < pSar; + + // + bool isSarSwitchedToBullish = isSarBullish && + !isSarBullishPrev; + bool isSarFinishedFromBullish = !isSarBullish && + isSarBullishPrev; + + // + bool isSarSwitchedToBearish = isSarBearish && + !isSarBearishPrev; + bool isSarFinishedFromBearish = !isSarBearish && + isSarBearishPrev; + + // + // MANALYSER ... + + // + // MAH ... + + // + bool isOverMah = cBar.low > conditions.mahBuffer[cIDX]; + bool isOverMahPrev = pBar.low > conditions.mahBuffer[pIDX]; + + // + bool isUnderMah = cBar.high < conditions.mahBuffer[cIDX]; + bool isUnderMahPrev = pBar.high < conditions.mahBuffer[pIDX]; + + // + bool isCrossedOverMah = isOverMah && + !isOverMahPrev; + bool isCrossedUnderMah = isUnderMah && + !isUnderMahPrev; + + // + bool isCloseOverMah = cBar.close > conditions.mahBuffer[cIDX]; + bool isCloseOverMahPrev = pBar.close > conditions.mahBuffer[pIDX]; + + bool isCloseUnderMah = cBar.close < conditions.mahBuffer[cIDX]; + bool isCloseUnderMahPrev = pBar.close < conditions.mahBuffer[pIDX]; + + // + bool isCloseCrossedOverMah = isCloseOverMah && + !isCloseOverMahPrev; + bool isCloseCrossedUnderMah = isCloseUnderMah && + !isCloseUnderMahPrev; + + // + bool isMahBullishRejected = cBar.IsRejected( + conditions.mahBuffer[cIDX], + X_DIRECTION_BULLISH, + false, + false // + ); + bool isMahBearishRejected = cBar.IsRejected( + conditions.mahBuffer[cIDX], + X_DIRECTION_BEARISH, + false, + false // + ); + + // + // MAL ... + + // + bool isOverMal = cBar.low > conditions.malBuffer[cIDX]; + bool isOverMalPrev = pBar.low > conditions.malBuffer[pIDX]; + + // + bool isUnderMal = cBar.high < conditions.malBuffer[cIDX]; + bool isUnderMalPrev = pBar.high < conditions.malBuffer[pIDX]; + + // + bool isCrossedOverMal = isOverMal && + !isOverMalPrev; + bool isCrossedUnderMal = isUnderMal && + !isUnderMalPrev; + + // + bool isCloseOverMal = cBar.close > conditions.malBuffer[cIDX]; + bool isCloseOverMalPrev = pBar.close > conditions.malBuffer[pIDX]; + + bool isCloseUnderMal = cBar.close < conditions.malBuffer[cIDX]; + bool isCloseUnderMalPrev = pBar.close < conditions.malBuffer[pIDX]; + + // + bool isCloseCrossedOverMal = isCloseOverMal && + !isCloseOverMalPrev; + bool isCloseCrossedUnderMal = isCloseUnderMal && + !isCloseUnderMalPrev; + + // + bool isMalBullishRejected = cBar.IsRejected( + conditions.malBuffer[cIDX], + X_DIRECTION_BULLISH, + false, + false // + ); + bool isMalBearishRejected = cBar.IsRejected( + conditions.malBuffer[cIDX], + X_DIRECTION_BEARISH, + false, + false // + ); + + // + // MAC ... + + // + bool isOverMac = cBar.low > conditions.macBuffer[cIDX]; + bool isOverMacPrev = pBar.low > conditions.macBuffer[pIDX]; + + // + bool isUnderMac = cBar.high < conditions.macBuffer[cIDX]; + bool isUnderMacPrev = pBar.high < conditions.macBuffer[pIDX]; + + // + bool isCrossedOverMac = isOverMac && + !isOverMacPrev; + bool isCrossedUnderMac = isUnderMac && + !isUnderMacPrev; + + // + bool isCloseOverMac = cBar.close > conditions.macBuffer[cIDX]; + bool isCloseOverMacPrev = pBar.close > conditions.macBuffer[pIDX]; + + bool isCloseUnderMac = cBar.close < conditions.macBuffer[cIDX]; + bool isCloseUnderMacPrev = pBar.close < conditions.macBuffer[pIDX]; + + // + bool isCloseCrossedOverMac = isCloseOverMac && + !isCloseOverMacPrev; + bool isCloseCrossedUnderMac = isCloseUnderMac && + !isCloseUnderMacPrev; + + // + bool isMacBullishRejected = cBar.IsRejected( + conditions.macBuffer[cIDX], + X_DIRECTION_BULLISH, + false, + false // + ); + bool isMacBearishRejected = cBar.IsRejected( + conditions.macBuffer[cIDX], + X_DIRECTION_BEARISH, + false, + false // + ); + + // + // PEAK ... + + // + double cPeak = conditions.peakBuffer[cIDX]; + double pPeak = conditions.peakBuffer[pIDX]; + + // + bool isPeakSameLast = cPeak == pPeak; + bool isPeakOverLast = cPeak > pPeak; + bool isPeakUnderLast = cPeak < pPeak; + + // + // VALE ... + + // + double cVale = conditions.valeBuffer[cIDX]; + double pVale = conditions.valeBuffer[pIDX]; + + // + bool isValeSameLast = cVale == pVale; + bool isValeOverLast = cVale > pVale; + bool isValeUnderLast = cVale < pVale; + + // + // TREND ... + + // + double cTrend = conditions.trendBuffer[cIDX]; + double pTrend = conditions.trendBuffer[pIDX]; + + // + double cTrendState = conditions.trendStateBuffer[cIDX]; + double pTrendState = conditions.trendStateBuffer[pIDX]; + + // + bool isTrendRejectUp = cBar.IsRejected( + cTrend, + X_DIRECTION_BULLISH, + false, + false // + ); + bool isTrendRejectDown = cBar.IsRejected( + cTrend, + X_DIRECTION_BEARISH, + false, + false // + ); + + // + bool isTrendBullish = cTrendState > 0; + bool isTrendBullishPrev = pTrendState > 0; + + // + bool isTrendBearish = cTrendState < 0; + bool isTrendBearishPrev = pTrendState < 0; + + // + bool isTrendSwitchedToBullish = isTrendBullish && + !isTrendBullishPrev; + bool isTrendFinishedFromBullish = !isTrendBullish && + isTrendBullishPrev; + + // + bool isTrendSwitchedToBearish = isTrendBearish && + !isTrendBearishPrev; + bool isTrendFinishedFromBearish = !isTrendBearish && + isTrendBearishPrev; + + // + // SUPPORT ... + + // + double cSupport = conditions.supportBuffer[cIDX]; + double pSupport = conditions.supportBuffer[pIDX]; + + // + bool isSupportSameLast = cSupport == pSupport; + bool isSupportOverLast = cSupport > pSupport; + bool isSupportUnderLast = cSupport < pSupport; + + // + bool isLastSupportBreaked = cBar.IsBreaked( + pSupport, + X_DIRECTION_BEARISH // + ); + bool isLastSupportRejected = cBar.IsRejected( + pSupport, + X_DIRECTION_BULLISH, + false, + false // + ); + + // + // RESISTANCE ... + + // + double cResistance = conditions.resistanceBuffer[cIDX]; + double pResistance = conditions.resistanceBuffer[pIDX]; + + // + bool isResistanceSameLast = cResistance == pResistance; + bool isResistanceOverLast = cResistance > pResistance; + bool isResistanceUnderLast = cResistance < pResistance; + + // + bool isLastResistanceBreaked = cBar.IsBreaked( + pResistance, + X_DIRECTION_BULLISH // + ); + bool isLastResistanceRejected = cBar.IsRejected( + pResistance, + X_DIRECTION_BEARISH, + false, + false // + ); + + // + // SWING Low ... + + // + double cSwingLow = conditions.swingLowBuffer[cIDX]; + double pSwingLow = conditions.swingLowBuffer[pIDX]; + + // + bool isSwingLowSameLast = cSwingLow == pSwingLow; + bool isSwingLowOverLast = cSwingLow > pSwingLow; + bool isSwingLowUnderLast = cSwingLow < pSwingLow; + + // + bool isLastSwingLowBreaked = cBar.IsBreaked( + pSwingLow, + X_DIRECTION_BEARISH // + ); + bool isLastSwingLowRejected = cBar.IsRejected( + pSwingLow, + X_DIRECTION_BULLISH, + false, + false // + ); + + // + // SWING High ... + + // + double cSwingHigh = conditions.swingHighBuffer[cIDX]; + double pSwingHigh = conditions.swingHighBuffer[pIDX]; + + // + bool isSwingHighSameLast = cSwingHigh == pSwingHigh; + bool isSwingHighOverLast = cSwingHigh > pSwingHigh; + bool isSwingHighUnderLast = cSwingHigh < pSwingHigh; + + // + bool isLastSwingHighBreaked = cBar.IsBreaked( + pSwingHigh, + X_DIRECTION_BULLISH // + ); + bool isLastSwingHighRejected = cBar.IsRejected( + pSwingHigh, + X_DIRECTION_BEARISH, + false, + false // + ); + + // + // COMPLEX Conditions ... + + // + bool isSwingLowSameAsVale = cSwingLow == cVale; + bool isSwingLowSameAsValePrev = pSwingLow == pVale; + + // + bool isSwingHighSameAsPeak = cSwingHigh == cPeak; + bool isSwingHighSameAsPeakPrev = pSwingHigh == pPeak; + + // + bool isSupportSameAsVale = cSupport == cVale; + bool isSupportSameAsValePrev = pSupport == pVale; + + // + bool isResistanceSameAsPeak = cResistance == cPeak; + bool isResistanceSameAsPeakPrev = pResistance == pPeak; + + // + bool isSupportSameAsSwingLow = cSupport == cSwingLow; + bool isSupportSameAsSwingLowPrev = pSupport == pSwingLow; + + // + bool isResistanceSameAsSwingHigh = cResistance == cSwingHigh; + bool isResistanceSameAsSwingHighPrev = pResistance == pSwingHigh; + + // + bool isPeakIsPivot = isSwingHighSameAsPeak && + isResistanceSameAsPeak && + isResistanceSameAsSwingHigh; + bool isPeakIsPivotPrev = isSwingHighSameAsPeakPrev && + isResistanceSameAsPeakPrev && + isResistanceSameAsSwingHighPrev; + + // + bool isPeakSwitchedToPivot = isPeakIsPivot && + !isPeakIsPivotPrev; + + // + bool isPeakFinishedFromPivot = !isPeakIsPivot && + isPeakIsPivotPrev; + + // + bool isValeIsPivot = isSwingLowSameAsVale && + isSupportSameAsVale && + isSupportSameAsSwingLow; + bool isValeIsPivotPrev = isSwingLowSameAsValePrev && + isSupportSameAsValePrev && + isSupportSameAsSwingLowPrev; + + // + bool isValeSwitchedToPivot = isValeIsPivot && + !isValeIsPivotPrev; + bool isValeFinishedFromPivot = !isValeIsPivot && + isValeIsPivotPrev; + // + // Attached ... + + // + conditions.isOverMah = isOverMah; + conditions.isOverMal = isOverMal; + conditions.isOverMac = isOverMac; + conditions.isUnderMah = isUnderMah; + conditions.isUnderMal = isUnderMal; + conditions.isUnderMac = isUnderMac; + conditions.isKIBullish = isKIBullish; + conditions.isKIBearish = isKIBearish; + conditions.isKIRejectUp = isKIRejectUp; + conditions.isTKIBullish = isTKIBullish; + conditions.isTKIBearish = isTKIBearish; + conditions.isSarBullish = isSarBullish; + conditions.isSarBearish = isSarBearish; + conditions.isTKIRejectUp = isTKIRejectUp; + conditions.isPeakIsPivot = isPeakIsPivot; + conditions.isValeIsPivot = isValeIsPivot; + conditions.isCloseOverMah = isCloseOverMah; + conditions.isCloseOverMal = isCloseOverMal; + conditions.isCloseOverMac = isCloseOverMac; + conditions.isVidyaBullish = isVidyaBullish; + conditions.isVidyaBearish = isVidyaBearish; + conditions.isKIRejectDown = isKIRejectDown; + conditions.isPeakSameLast = isPeakSameLast; + conditions.isPeakOverLast = isPeakOverLast; + conditions.isValeSameLast = isValeSameLast; + conditions.isValeOverLast = isValeOverLast; + conditions.isTrendBullish = isTrendBullish; + conditions.isTrendBearish = isTrendBearish; + conditions.isCloseUnderMah = isCloseUnderMah; + conditions.isCloseUnderMal = isCloseUnderMal; + conditions.isCloseUnderMac = isCloseUnderMac; + conditions.isTKIRejectDown = isTKIRejectDown; + conditions.isPeakUnderLast = isPeakUnderLast; + conditions.isValeUnderLast = isValeUnderLast; + conditions.isTrendRejectUp = isTrendRejectUp; + conditions.isCrossedOverMah = isCrossedOverMah; + conditions.isCrossedOverMal = isCrossedOverMal; + conditions.isCrossedOverMac = isCrossedOverMac; + conditions.isCrossedUnderMah = isCrossedUnderMah; + conditions.isCrossedUnderMal = isCrossedUnderMal; + conditions.isCrossedUnderMac = isCrossedUnderMac; + conditions.isTrendRejectDown = isTrendRejectDown; + conditions.isSupportSameLast = isSupportSameLast; + conditions.isSupportOverLast = isSupportOverLast; + conditions.isSupportUnderLast = isSupportUnderLast; + conditions.isSwingLowSameLast = isSwingLowSameLast; + conditions.isSwingLowOverLast = isSwingLowOverLast; + conditions.isSwingLowUnderLast = isSwingLowUnderLast; + conditions.isSwingHighSameLast = isSwingHighSameLast; + conditions.isSwingHighOverLast = isSwingHighOverLast; + conditions.isSupportSameAsVale = isSupportSameAsVale; + conditions.isMahBullishRejected = isMahBullishRejected; + conditions.isMahBearishRejected = isMahBearishRejected; + conditions.isMalBullishRejected = isMalBullishRejected; + conditions.isMalBearishRejected = isMalBearishRejected; + conditions.isMacBullishRejected = isMacBullishRejected; + conditions.isMacBearishRejected = isMacBearishRejected; + conditions.isLastSupportBreaked = isLastSupportBreaked; + conditions.isResistanceSameLast = isResistanceSameLast; + conditions.isResistanceOverLast = isResistanceOverLast; + conditions.isSwingHighUnderLast = isSwingHighUnderLast; + conditions.isSwingLowSameAsVale = isSwingLowSameAsVale; + conditions.isCloseCrossedOverMah = isCloseCrossedOverMah; + conditions.isCloseCrossedOverMal = isCloseCrossedOverMal; + conditions.isCloseCrossedOverMac = isCloseCrossedOverMac; + conditions.isLastSupportRejected = isLastSupportRejected; + conditions.isResistanceUnderLast = isResistanceUnderLast; + conditions.isKISwitchedToBullish = isKISwitchedToBullish; + conditions.isKISwitchedToBearish = isKISwitchedToBearish; + conditions.isLastSwingLowBreaked = isLastSwingLowBreaked; + conditions.isSwingHighSameAsPeak = isSwingHighSameAsPeak; + conditions.isPeakSwitchedToPivot = isPeakSwitchedToPivot; + conditions.isValeSwitchedToPivot = isValeSwitchedToPivot; + conditions.isCloseCrossedUnderMah = isCloseCrossedUnderMah; + conditions.isCloseCrossedUnderMal = isCloseCrossedUnderMal; + conditions.isCloseCrossedUnderMac = isCloseCrossedUnderMac; + conditions.isTKISwitchedToBullish = isTKISwitchedToBullish; + conditions.isTKISwitchedToBearish = isTKISwitchedToBearish; + conditions.isLastSwingLowRejected = isLastSwingLowRejected; + conditions.isSarSwitchedToBullish = isSarSwitchedToBullish; + conditions.isSarSwitchedToBearish = isSarSwitchedToBearish; + conditions.isLastSwingHighBreaked = isLastSwingHighBreaked; + conditions.isResistanceSameAsPeak = isResistanceSameAsPeak; + conditions.isPeakFinishedFromPivot = isPeakFinishedFromPivot; + conditions.isValeFinishedFromPivot = isValeFinishedFromPivot; + conditions.isLastSwingHighRejected = isLastSwingHighRejected; + conditions.isLastResistanceBreaked = isLastResistanceBreaked; + conditions.isSupportSameAsSwingLow = isSupportSameAsSwingLow; + conditions.isKIFinishedFromBullish = isKIFinishedFromBullish; + conditions.isKIFinishedFromBearish = isKIFinishedFromBearish; + conditions.isTKIFinishedFromBullish = isTKIFinishedFromBullish; + conditions.isTKIFinishedFromBearish = isTKIFinishedFromBearish; + conditions.isSarFinishedFromBullish = isSarFinishedFromBullish; + conditions.isSarFinishedFromBearish = isSarFinishedFromBearish; + conditions.isVidyaSwitchedToBullish = isVidyaSwitchedToBullish; + conditions.isVidyaSwitchedToBearish = isVidyaSwitchedToBearish; + conditions.isLastResistanceRejected = isLastResistanceRejected; + conditions.isTrendSwitchedToBullish = isTrendSwitchedToBullish; + conditions.isTrendSwitchedToBearish = isTrendSwitchedToBearish; + conditions.isVidyaFinishedFromBullish = isVidyaFinishedFromBullish; + conditions.isVidyaFinishedFromBearish = isVidyaFinishedFromBearish; + conditions.isTrendFinishedFromBullish = isTrendFinishedFromBullish; + conditions.isTrendFinishedFromBearish = isTrendFinishedFromBearish; + conditions.isResistanceSameAsSwingHigh = isResistanceSameAsSwingHigh; + + // + Cleanup(); + + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + + // + return result; + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + X121XCAInputs mInputs; // Inputs ... + + // + // Buffers ... + double kiBuffer[]; + double tkiBuffer[]; + double sHHBuffer[]; + double sLLBuffer[]; + double mHHBuffer[]; + double mLLBuffer[]; + double lHHBuffer[]; + double lLLBuffer[]; + double hHHBuffer[]; + double hLLBuffer[]; + double sarBuffer[]; + double mahBuffer[]; + double malBuffer[]; + double macBuffer[]; + double peakBuffer[]; + double valeBuffer[]; + double vidyaBuffer[]; + double trendBuffer[]; + double kiStateBuffer[]; + double supportBuffer[]; + double tkiStateBuffer[]; + double swingLowBuffer[]; + double swingHighBuffer[]; + double resistanceBuffer[]; + double peakGoldenBuffer[]; + double valeGoldenBuffer[]; + double fiboLevel1Buffer[]; + double fiboLevel2Buffer[]; + double fiboLevel3Buffer[]; + double fiboLevel4Buffer[]; + double fiboLevel5Buffer[]; + double vidyaStateBuffer[]; + double trendStateBuffer[]; + + // + void Calculate( + int barIndex = 0, + int maxRequiredBars = 100 // + ) + { + // + // Buffers ... + if (barIndex < 0) + { + barIndex = 0; + } + + // + CopyBuffer( + mHandler, + X121_XCA_KI_LINE, + barIndex, + maxRequiredBars, + kiBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_TKI_LINE, + barIndex, + maxRequiredBars, + tkiBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_VIDYA_LINE, + barIndex, + maxRequiredBars, + vidyaBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_S_HH_LINE, + barIndex, + maxRequiredBars, + sHHBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_S_LL_LINE, + barIndex, + maxRequiredBars, + sLLBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_M_HH_LINE, + barIndex, + maxRequiredBars, + mHHBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_M_LL_LINE, + barIndex, + maxRequiredBars, + mLLBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_L_HH_LINE, + barIndex, + maxRequiredBars, + lHHBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_L_LL_LINE, + barIndex, + maxRequiredBars, + lLLBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_H_HH_LINE, + barIndex, + maxRequiredBars, + hHHBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_H_LL_LINE, + barIndex, + maxRequiredBars, + hLLBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_SAR_LINE, + barIndex, + maxRequiredBars, + sarBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_MAH_LINE, + barIndex, + maxRequiredBars, + mahBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_MAL_LINE, + barIndex, + maxRequiredBars, + malBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_MAC_LINE, + barIndex, + maxRequiredBars, + macBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_PEAK_LINE, + barIndex, + maxRequiredBars, + peakBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_VALE_LINE, + barIndex, + maxRequiredBars, + valeBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_TREND_LINE, + barIndex, + maxRequiredBars, + trendBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_KI_STATE_LINE, + barIndex, + maxRequiredBars, + kiStateBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_TKI_STATE_LINE, + barIndex, + maxRequiredBars, + tkiStateBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_VIDYA_STATE_LINE, + barIndex, + maxRequiredBars, + vidyaStateBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_SUPPORT_LINE, + barIndex, + maxRequiredBars, + supportBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_SWING_LOW_LINE, + barIndex, + maxRequiredBars, + swingLowBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_SWING_HIGH_LINE, + barIndex, + maxRequiredBars, + swingHighBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_RESISTANCE_LINE, + barIndex, + maxRequiredBars, + resistanceBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_PEAK_GOLDEN_LINE, + barIndex, + maxRequiredBars, + peakGoldenBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_VALE_GOLDEN_LINE, + barIndex, + maxRequiredBars, + valeGoldenBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_FIBO_L1_LINE, + barIndex, + maxRequiredBars, + fiboLevel1Buffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_FIBO_L2_LINE, + barIndex, + maxRequiredBars, + fiboLevel2Buffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_FIBO_L3_LINE, + barIndex, + maxRequiredBars, + fiboLevel3Buffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_FIBO_L4_LINE, + barIndex, + maxRequiredBars, + fiboLevel4Buffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_FIBO_L5_LINE, + barIndex, + maxRequiredBars, + fiboLevel5Buffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCA_TREND_STATE_LINE, + barIndex, + maxRequiredBars, + trendStateBuffer // + ); + } + + // + void Cleanup( + int maxAllowed = 100 // + ) + { + // + CleanupArray( + kiBuffer, + maxAllowed // + ); + + // + CleanupArray( + tkiBuffer, + maxAllowed // + ); + + // + CleanupArray( + vidyaBuffer, + maxAllowed // + ); + + // + CleanupArray( + sHHBuffer, + maxAllowed // + ); + + // + CleanupArray( + sLLBuffer, + maxAllowed // + ); + + // + CleanupArray( + mHHBuffer, + maxAllowed // + ); + + // + CleanupArray( + mLLBuffer, + maxAllowed // + ); + + // + CleanupArray( + lHHBuffer, + maxAllowed // + ); + + // + CleanupArray( + lLLBuffer, + maxAllowed // + ); + + // + CleanupArray( + hHHBuffer, + maxAllowed // + ); + + // + CleanupArray( + hLLBuffer, + maxAllowed // + ); + + // + CleanupArray( + sarBuffer, + maxAllowed // + ); + + // + CleanupArray( + mahBuffer, + maxAllowed // + ); + + // + CleanupArray( + malBuffer, + maxAllowed // + ); + + // + CleanupArray( + macBuffer, + maxAllowed // + ); + + // + CleanupArray( + peakBuffer, + maxAllowed // + ); + + // + CleanupArray( + valeBuffer, + maxAllowed // + ); + + // + CleanupArray( + trendBuffer, + maxAllowed // + ); + + // + CleanupArray( + kiStateBuffer, + maxAllowed // + ); + + // + CleanupArray( + tkiStateBuffer, + maxAllowed // + ); + + // + CleanupArray( + vidyaStateBuffer, + maxAllowed // + ); + + // + CleanupArray( + supportBuffer, + maxAllowed // + ); + + // + CleanupArray( + swingLowBuffer, + maxAllowed // + ); + + // + CleanupArray( + swingHighBuffer, + maxAllowed // + ); + + // + CleanupArray( + resistanceBuffer, + maxAllowed // + ); + + // + CleanupArray( + peakGoldenBuffer, + maxAllowed // + ); + + // + CleanupArray( + valeGoldenBuffer, + maxAllowed // + ); + + // + CleanupArray( + fiboLevel1Buffer, + maxAllowed // + ); + + // + CleanupArray( + fiboLevel2Buffer, + maxAllowed // + ); + + // + CleanupArray( + fiboLevel3Buffer, + maxAllowed // + ); + + // + CleanupArray( + fiboLevel4Buffer, + maxAllowed // + ); + + // + CleanupArray( + fiboLevel5Buffer, + maxAllowed // + ); + + // + CleanupArray( + trendStateBuffer, + maxAllowed // + ); + } + + // +}; + +// +// Tools ... \ No newline at end of file diff --git a/BKPS/14040316/Documents/Helpers/x-saherelm.x121.xcatb.helper.mq5 b/BKPS/14040316/Documents/Helpers/x-saherelm.x121.xcatb.helper.mq5 new file mode 100644 index 0000000..6bfab82 --- /dev/null +++ b/BKPS/14040316/Documents/Helpers/x-saherelm.x121.xcatb.helper.mq5 @@ -0,0 +1,5548 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XCX121XCatbHelper +// 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.x-helper.class.mq5" +#include "../Libraries/x-saherelm.x-poi.lib.mq5" + +// +// Definitions ... + +// +// Buffers ... +enum ENUM_X121_XCATB_BUFFERS +{ + X121_XCATB_SAR_LINE = 0, + X121_XCATB_SAR_STATE_LINE = 28, + X121_XCATB_PEAK_LINE = 2, + X121_XCATB_VALE_LINE = 3, + X121_XCATB_PEAK_GOLDEN_LINE = 4, + X121_XCATB_VALE_GOLDEN_LINE = 5, + X121_XCATB_ATR_BAND_UPPER_LINE = 6, + X121_XCATB_ATR_BAND_LOWER_LINE = 7, + X121_XCATB_TREND_LINE = 8, + X121_XCATB_TREND_STATE_LINE = 29, + X121_XCATB_SBAR_O_LINE = 10, + X121_XCATB_SBAR_H_LINE = 11, + X121_XCATB_SBAR_L_LINE = 12, + X121_XCATB_SBAR_C_LINE = 13, + X121_XCATB_HK_SBAR_O_LINE = 15, + X121_XCATB_HK_SBAR_H_LINE = 16, + X121_XCATB_HK_SBAR_L_LINE = 17, + X121_XCATB_HK_SBAR_C_LINE = 18, + X121_XCATB_S_HH_LINE = 20, + X121_XCATB_S_LL_LINE = 21, + X121_XCATB_M_HH_LINE = 22, + X121_XCATB_M_LL_LINE = 23, + X121_XCATB_L_HH_LINE = 24, + X121_XCATB_L_LL_LINE = 25, + X121_XCATB_H_HH_LINE = 26, + X121_XCATB_H_LL_LINE = 27, + X121_XCATB_RSI_LINE = 30, + X121_XCATB_ADX_LINE = 31, + X121_XCATB_ADXP_LINE = 32, + X121_XCATB_ADXN_LINE = 33, + X121_XCATB_DELTA_LINE = 34, + X121_XCATB_DELTA_SIGNAL_LINE = 35, + X121_XCATB_VOLUME_BULLISH_LINE = 36, + X121_XCATB_VOLUME_BEARISH_LINE = 37, + X121_XCATB_VOLUME_VOLUME_BULLISH_SIGNAL_LINE = 38, + X121_XCATB_VOLUME_VOLUME_BEARISH_SIGNAL_LINE = 39, + X121_XCATB_ATR_LINE = 40, + X121_XCATB_ATR_BAND_RAW_UPPER_LINE = 41, + X121_XCATB_ATR_BAND_RAW_LOWER_LINE = 42, + X121_XCATB_HK_BAR_O_LINE = 43, + X121_XCATB_HK_BAR_H_LINE = 44, + X121_XCATB_HK_BAR_L_LINE = 45, + X121_XCATB_HK_BAR_C_LINE = 46, +}; + +// +// Input Models ... +struct X121XCatbInputs +{ + // + // Props ... + + // + // Market ... + ENUM_X_PERIOD_METHOD scMethod; // How to Find Short Period + ENUM_TIMEFRAMES scPeriod; // Short Period + ENUM_X_PERIOD_METHOD mcMethod; // How to Find Medium Period + ENUM_TIMEFRAMES mcPeriod; // Medium Period + ENUM_X_PERIOD_METHOD lcMethod; // How to Find Long Period + ENUM_TIMEFRAMES lcPeriod; // Long Period + ENUM_X_PERIOD_METHOD hcMethod; // How to Find Hind Period + ENUM_TIMEFRAMES hcPeriod; // Hind Period + ENUM_X_MARKET_CYCLES appliedCycle; // Applied Cycle + + // + // Signal ... + int signalR2R; // Risk Reward Ratio + bool drawSignals; // Draw Signal + bool drawTriggerBlock; // Draw Trigger Block + double slAtrMultiplier; // ATR Multiplier for SL + + // + // Validating ... + bool forceHasSwing; // Force Blocks to Have Swing + bool forceOBBarType; // Force Block Has Reversal Bar + bool forceOBFVGBarType; // Force FVG Has Same Bars + bool forceHasFLiquidity; // Force Blocks to Have Following Liquidity + bool forceHasRLiquidity; // Force Blocks to Have Reversal Liquidity + bool validateGapSequence; // Validate Block's Gap Sequence + bool validateBlockEdgeBreakout; // Validate Block's Edge Breakout + + // + // Filtering ... + bool filterBasedOnPV; // Filter Based on Peak and Vale + bool filterBasedOnSar; // Filter Based on Sar + bool filterBasedOnRSI; // Filter Based on RSI + bool filterBasedOnADX; // Filter Based on ADX + bool filterBasedOnATR; // Filter Based on ATR + bool filterBasedOnTrend; // Filter Based on Trend + bool filterBasedOnDelta; // Filter Based on Delta + bool filterBasedOnVolume; // Filter Based on Volume + bool filterBasedOnSignalBar; // Filter Based on Signal Bar + bool filterBasedOnHKSignalBar; // Filter Based on Hiken Ashi Signal Bar + + // + // Alert ... + string alertPrefix; // Alert Prefix + bool logAlerts; // Log Alerts + bool pushAlerts; // Push Alerts + bool mailAlerts; // Mail Alerts + bool terminalAlerts; // Terminal Alerts + + // + // Presentation ... + bool showBars; // Show Bars + bool showPV; // Show PV + bool showPVGolden; // Show PV Golden + bool showSar; // Show Sar + bool showTrend; // Show Trend + bool showATRBand; // Show ATR Band + bool showSignalBars; // Show Signal Bars + bool showHKSignalBars; // Show Hiken Ashi Signal Bars + + // + double rsiOBLevel; // RSI OB Level + double rsiOSLevel; // RSI OS Level + double adxThreshold; // ADX Threshold + + // + int startCalculationForLastBars; // Calculate Last n Bars + + // + // Constructor(s) ... + X121XCatbInputs() + { + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + // Market ... + scMethod = X_PERIOD_AUTO; // How to Find Short Period + scPeriod = NULL; // Short Period + mcMethod = X_PERIOD_AUTO; // How to Find Medium Period + mcPeriod = NULL; // Medium Period + lcMethod = X_PERIOD_AUTO; // How to Find Long Period + lcPeriod = NULL; // Long Period + hcMethod = X_PERIOD_AUTO; // How to Find Hind Period + hcPeriod = NULL; // Hind Period + appliedCycle = X_MARKET_CYCLE_HIND; // Applied Cycle + + // + // Signal ... + signalR2R = 0; // Risk Reward Ratio + drawSignals = false; // Draw Signal + drawTriggerBlock = false; // Draw Trigger Block + slAtrMultiplier = 0; // ATR Multiplier for SL + + // + // Validating ... + forceHasSwing = false; // Force Blocks to Have Swing + forceOBBarType = false; // Force Block Has Reversal Bar + forceOBFVGBarType = false; // Force FVG Has Same Bars + forceHasFLiquidity = false; // Force Blocks to Have Following Liquidity + forceHasRLiquidity = false; // Force Blocks to Have Reversal Liquidity + validateGapSequence = false; // Validate Block's Gap Sequence + validateBlockEdgeBreakout = false; // Validate Block's Edge Breakout + + // + // Filtering ... + filterBasedOnPV = false; // Filter Based on Peak and Vale + filterBasedOnSar = false; // Filter Based on Sar + filterBasedOnRSI = false; // Filter Based on RSI + filterBasedOnADX = false; // Filter Based on ADX + filterBasedOnATR = false; // Filter Based on ATR + filterBasedOnTrend = false; // Filter Based on Trend + filterBasedOnDelta = false; // Filter Based on Delta + filterBasedOnVolume = false; // Filter Based on Volume + filterBasedOnSignalBar = false; // Filter Based on Signal Bar + filterBasedOnHKSignalBar = false; // Filter Based on Hiken Ashi Signal Bar + + // + // Alert ... + alertPrefix = ""; // Alert Prefix + logAlerts = false; // Log Alerts + pushAlerts = false; // Push Alerts + mailAlerts = false; // Mail Alerts + terminalAlerts = false; // Terminal Alerts + + // + // Presentation ... + showBars = false; // Show Bars + showPV = false; // Show PV + showPVGolden = false; // Show PV Golden + showSar = false; // Show Sar + showTrend = false; // Show Trend + showATRBand = false; // Show ATR Band + showSignalBars = false; // Show Signal Bars + showHKSignalBars = false; // Show Hiken Ashi Signal Bars + + // + startCalculationForLastBars = 0; // Calculate Last n Bars + + // + rsiOBLevel = 70.0; // RSI OB Level + rsiOSLevel = 30.0; // RSI OS Level + adxThreshold = 25.0; // ADX Threshold + + // + ZeroMemory(this); + } + + // + // Default ... + void Default() + { + // + // Market ... + scMethod = X_PERIOD_AUTO; // How to Find Short Period + scPeriod = NULL; // Short Period + mcMethod = X_PERIOD_AUTO; // How to Find Medium Period + mcPeriod = NULL; // Medium Period + lcMethod = X_PERIOD_AUTO; // How to Find Long Period + lcPeriod = NULL; // Long Period + hcMethod = X_PERIOD_AUTO; // How to Find Hind Period + hcPeriod = NULL; // Hind Period + appliedCycle = X_MARKET_CYCLE_HIND; // Applied Cycle + + // + // Signal ... + signalR2R = 4; // Risk Reward Ratio + drawSignals = false; // Draw Signal + drawTriggerBlock = false; // Draw Trigger Block + slAtrMultiplier = 1.0; // ATR Multiplier for SL + + // + // Validating ... + forceHasSwing = false; // Force Blocks to Have Swing + forceOBBarType = false; // Force Block Has Reversal Bar + forceOBFVGBarType = false; // Force FVG Has Same Bars + forceHasFLiquidity = false; // Force Blocks to Have Following Liquidity + forceHasRLiquidity = false; // Force Blocks to Have Reversal Liquidity + validateGapSequence = false; // Validate Block's Gap Sequence + validateBlockEdgeBreakout = false; // Validate Block's Edge Breakout + + // + // Filtering ... + filterBasedOnPV = false; // Filter Based on Peak and Vale + filterBasedOnSar = false; // Filter Based on Sar + filterBasedOnRSI = false; // Filter Based on RSI + filterBasedOnADX = false; // Filter Based on ADX + filterBasedOnATR = false; // Filter Based on ATR + filterBasedOnTrend = false; // Filter Based on Trend + filterBasedOnDelta = false; // Filter Based on Delta + filterBasedOnVolume = false; // Filter Based on Volume + filterBasedOnSignalBar = false; // Filter Based on Signal Bar + filterBasedOnHKSignalBar = false; // Filter Based on Hiken Ashi Signal Bar + + // + // Alert ... + alertPrefix = ""; // Alert Prefix + logAlerts = false; // Log Alerts + pushAlerts = false; // Push Alerts + mailAlerts = false; // Mail Alerts + terminalAlerts = false; // Terminal Alerts + + // + // Presentation ... + showBars = true; // Show Bars + showPV = false; // Show PV + showPVGolden = false; // Show PV Golden + showSar = false; // Show Sar + showTrend = false; // Show Trend + showATRBand = false; // Show ATR Band + showSignalBars = false; // Show Signal Bars + showHKSignalBars = false; // Show Hiken Ashi Signal Bars + + // + startCalculationForLastBars = 1500; // Calculate Last n Bars + + // + rsiOBLevel = 70.0; // RSI OB Level + rsiOSLevel = 30.0; // RSI OS Level + adxThreshold = 25.0; // ADX Threshold + } + + // + // Hide all Visible Buffers ... + void Hide() + { + // + showPV = false; + showPVGolden = false; + showSar = false; + showTrend = false; + showATRBand = false; + showSignalBars = false; + showHKSignalBars = false; + + // + drawSignals = false; + drawTriggerBlock = false; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsValid(appliedCycle) && + // + // CYCLES ... + (IsValid(scMethod, scPeriod) && + IsValid(mcMethod, mcPeriod) && + IsValid(lcMethod, lcPeriod) && + IsValid(hcMethod, hcPeriod)) + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + return result; + } + + // +}; + +// +// Conditions ... +struct X121XCatbConditions +{ + // + // Common ... + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + datetime to; + datetime from; + XOHCL bars[]; + + // + // Buffers ... + double sarBuffer[]; + double atrBuffer[]; + double rsiBuffer[]; + double adxBuffer[]; + double sHHBuffer[]; + double sLLBuffer[]; + double mHHBuffer[]; + double mLLBuffer[]; + double lHHBuffer[]; + double lLLBuffer[]; + double hHHBuffer[]; + double hLLBuffer[]; + double adxpBuffer[]; + double adxnBuffer[]; + double peakBuffer[]; + double valeBuffer[]; + double deltaBuffer[]; + double trendBuffer[]; + double hkLowBuffer[]; + double hkOpenBuffer[]; + double hkHighBuffer[]; + double hkCloseBuffer[]; + double sarStateBuffer[]; + double atrUpperBuffer[]; + double atrLowerBuffer[]; + double sBarOpenBuffer[]; + double sBarCloseBuffer[]; + double trendStateBuffer[]; + double hkSBarOpenBuffer[]; + double peakGoldenBuffer[]; + double valeGoldenBuffer[]; + double hkSBarCloseBuffer[]; + double deltaSignalBuffer[]; + double bullishVolumeBuffer[]; + double bearishVolumeBuffer[]; + double bullishVolumeSignalBuffer[]; + double bearishVolumeSignalBuffer[]; + + // + double rsiOBLevel; // Over Bought Level + double rsiOSLevel; // Over Sold Level + double adxThreshold; // Big Movement Threshold + + // + // Conditions ... + + // + // ATR Band ... + + // + bool isATRUp; + bool isATRDown; + + // + bool isClosedOverATRUpper; + bool isClosedUnderATRLower; + + // + // SAR ... + + // + bool isSarBullish; + bool isSarBearish; + + // + bool isSarSwitchedToBullish; + bool isSarSwitchedToBearish; + + // + // ADX ... + + // + bool isADXBiggerLast; + bool isADXLesserLast; + + // + bool isADXOverThreshold; + bool isADXUnderThreshold; + + // + bool isDXPBiggerThanDXN; + bool isDXNBiggerThanDXP; + + // + bool isADXBullish; + bool isADXBearish; + + // + bool isADXSwitchedToBullish; + bool isADXSwitchedToBearish; + + // + // RSI ... + + // + bool isRSIBullish; + bool isRSIBearish; + + // + bool isRSISwitchedToBullish; + bool isRSISwitchedToBearish; + + // + bool isRSIOB; + bool isRSIOS; + + // + bool isRSICrossedOverOB; + bool isRSICrossedOverOS; + + // + bool isRSICrossedUnderOB; + bool isRSICrossedUnderOS; + + // + // DELTA ... + + // + bool isDeltaUp; + bool isDeltaDown; + + // + bool isDeltaBullish; + bool isDeltaBearish; + + // + bool isDeltaSwitchedToBullish; + bool isDeltaSwitchedToBearish; + + // + // VOLUME ... + + // + bool isVolumeBullish; + bool isVolumeBearish; + + // + bool isVolumeSwitchedToBullish; + bool isVolumeSwitchedToBearish; + + // + // SIGNAL Bar ... + + // + bool isSBarBullish; + bool isSBarBearish; + + // + bool isSBarSwitchedToBullish; + bool isSBarSwitchedToBearish; + + // + // XHK Signal Bar ... + + // + bool isHKSBarBullish; + bool isHKSBarBearish; + + // + bool isHKSBarSwitchedToBullish; + bool isHKSBarSwitchedToBearish; + + // + // TREND ... + + // + bool isTrendUp; + bool isTrendDown; + + // + bool isTrendBullish; + bool isTrendBearish; + + // + bool isTrendSwitchedToBullish; + bool isTrendSwitchedToBearish; + + // + // PEAK ... + + // + bool isPeakSameLast; + bool isPeakOverLast; + bool isPeakUnderLast; + + // + // VALE ... + + // + bool isValeSameLast; + bool isValeOverLast; + bool isValeUnderLast; + + // + // Constructor ... + X121XCatbConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + // Commons ... + to = NULL; + from = NULL; + time = NULL; + symbol = NULL; + period = NULL; + + // + // Buffers ... + + // + Clean(bars); + Clean(sarBuffer); + Clean(atrBuffer); + Clean(rsiBuffer); + Clean(adxBuffer); + Clean(sHHBuffer); + Clean(sLLBuffer); + Clean(mHHBuffer); + Clean(mLLBuffer); + Clean(lHHBuffer); + Clean(lLLBuffer); + Clean(hHHBuffer); + Clean(hLLBuffer); + Clean(adxpBuffer); + Clean(adxnBuffer); + Clean(peakBuffer); + Clean(valeBuffer); + Clean(deltaBuffer); + Clean(trendBuffer); + Clean(hkLowBuffer); + Clean(hkOpenBuffer); + Clean(hkHighBuffer); + Clean(hkCloseBuffer); + Clean(sarStateBuffer); + Clean(atrUpperBuffer); + Clean(atrLowerBuffer); + Clean(sBarOpenBuffer); + Clean(sBarCloseBuffer); + Clean(trendStateBuffer); + Clean(hkSBarOpenBuffer); + Clean(peakGoldenBuffer); + Clean(valeGoldenBuffer); + Clean(hkSBarCloseBuffer); + Clean(deltaSignalBuffer); + Clean(bullishVolumeBuffer); + Clean(bearishVolumeBuffer); + Clean(bullishVolumeSignalBuffer); + Clean(bearishVolumeSignalBuffer); + + // + ArraySetAsSeries(bars, true); + ArraySetAsSeries(sarBuffer, true); + ArraySetAsSeries(atrBuffer, true); + ArraySetAsSeries(rsiBuffer, true); + ArraySetAsSeries(adxBuffer, true); + ArraySetAsSeries(sHHBuffer, true); + ArraySetAsSeries(sLLBuffer, true); + ArraySetAsSeries(mHHBuffer, true); + ArraySetAsSeries(mLLBuffer, true); + ArraySetAsSeries(lHHBuffer, true); + ArraySetAsSeries(lLLBuffer, true); + ArraySetAsSeries(hHHBuffer, true); + ArraySetAsSeries(hLLBuffer, true); + ArraySetAsSeries(adxpBuffer, true); + ArraySetAsSeries(adxnBuffer, true); + ArraySetAsSeries(peakBuffer, true); + ArraySetAsSeries(valeBuffer, true); + ArraySetAsSeries(deltaBuffer, true); + ArraySetAsSeries(trendBuffer, true); + ArraySetAsSeries(hkLowBuffer, true); + ArraySetAsSeries(hkOpenBuffer, true); + ArraySetAsSeries(hkHighBuffer, true); + ArraySetAsSeries(hkCloseBuffer, true); + ArraySetAsSeries(sarStateBuffer, true); + ArraySetAsSeries(atrUpperBuffer, true); + ArraySetAsSeries(atrLowerBuffer, true); + ArraySetAsSeries(sBarOpenBuffer, true); + ArraySetAsSeries(sBarCloseBuffer, true); + ArraySetAsSeries(trendStateBuffer, true); + ArraySetAsSeries(hkSBarOpenBuffer, true); + ArraySetAsSeries(peakGoldenBuffer, true); + ArraySetAsSeries(valeGoldenBuffer, true); + ArraySetAsSeries(hkSBarCloseBuffer, true); + ArraySetAsSeries(deltaSignalBuffer, true); + ArraySetAsSeries(bullishVolumeBuffer, true); + ArraySetAsSeries(bearishVolumeBuffer, true); + ArraySetAsSeries(bullishVolumeSignalBuffer, true); + ArraySetAsSeries(bearishVolumeSignalBuffer, true); + + // + rsiOBLevel = 0; // Over Bought Level + rsiOSLevel = 0; // Over Sold Level + adxThreshold = 0; // Big Movement Threshold + + // + // Conditions ... + + // + // Conditions ... + + // + // ATR Band ... + + // + isATRUp = false; + isATRDown = false; + + // + isClosedOverATRUpper = false; + isClosedUnderATRLower = false; + + // + // SAR ... + + // + isSarBullish = false; + isSarBearish = false; + + // + isSarSwitchedToBullish = false; + isSarSwitchedToBearish = false; + + // + // ADX ... + + // + isADXBiggerLast = false; + isADXLesserLast = false; + + // + isADXOverThreshold = false; + isADXUnderThreshold = false; + + // + isDXPBiggerThanDXN = false; + isDXNBiggerThanDXP = false; + + // + isADXBullish = false; + isADXBearish = false; + + // + isADXSwitchedToBullish = false; + isADXSwitchedToBearish = false; + + // + // RSI ... + + // + isRSIBullish = false; + isRSIBearish = false; + + // + isRSISwitchedToBullish = false; + isRSISwitchedToBearish = false; + + // + isRSIOB = false; + isRSIOS = false; + + // + isRSICrossedOverOB = false; + isRSICrossedOverOS = false; + + // + isRSICrossedUnderOB = false; + isRSICrossedUnderOS = false; + + // + // DELTA ... + + // + isDeltaUp = false; + isDeltaDown = false; + + // + isDeltaBullish = false; + isDeltaBearish = false; + + // + isDeltaSwitchedToBullish = false; + isDeltaSwitchedToBearish = false; + + // + // VOLUME ... + + // + isVolumeBullish = false; + isVolumeBearish = false; + + // + isVolumeSwitchedToBullish = false; + isVolumeSwitchedToBearish = false; + // + // SIGNAL Bar ... + + // + isSBarBullish = false; + isSBarBearish = false; + + // + isSBarSwitchedToBullish = false; + isSBarSwitchedToBearish = false; + + // + // XHK Signal Bar ... + + // + isHKSBarBullish = false; + isHKSBarBearish = false; + + // + isHKSBarSwitchedToBullish = false; + isHKSBarSwitchedToBearish = false; + + // + // TREND ... + + // + isTrendUp = false; + isTrendDown = false; + + // + isTrendBullish = false; + isTrendBearish = false; + + // + isTrendSwitchedToBullish = false; + isTrendSwitchedToBearish = false; + + // + // PEAK ... + + // + isPeakSameLast = false; + isPeakOverLast = false; + isPeakUnderLast = false; + + // + // VALE ... + + // + isValeSameLast = false; + isValeOverLast = false; + isValeUnderLast = false; + + // + ZeroMemory(this); + } + + /** + * Generate Conditions Scores ... + * + * @param bullishScore: Double, Directional Scores Reference ... + * @param bearishScore: Double, Directional Scores Reference ... + */ + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + // + bullishScore = 0; + bearishScore = 0; + + // + double score = 1; + double minScore = 0.5; + double highScore = 1.5; + + // + // ATR Band ... + + // + if (isATRUp) + { + bullishScore += score; + } + if (isClosedOverATRUpper) + { + bullishScore += score; + } + + // + if (isATRDown) + { + bearishScore += score; + } + if (isClosedUnderATRLower) + { + bearishScore += score; + } + + // + // SAR ... + + // + if (isSarBullish) + { + bullishScore += score; + } + if (isSarSwitchedToBullish) + { + bullishScore += score; + } + + // + if (isSarBearish) + { + bearishScore += score; + } + if (isSarSwitchedToBearish) + { + bearishScore += score; + } + + // + // ADX ... + + // + if (isADXBullish) + { + bullishScore += score; + } + if (isADXBiggerLast) + { + bullishScore += score; + } + if (isDXPBiggerThanDXN) + { + bullishScore += score; + } + if (isADXOverThreshold) + { + bullishScore += score; + } + if (isADXSwitchedToBullish) + { + bullishScore += score; + } + + // + if (isADXBearish) + { + bearishScore += score; + } + if (isADXLesserLast) + { + bearishScore += score; + } + if (isDXNBiggerThanDXP) + { + bearishScore += score; + } + if (isADXUnderThreshold) + { + bearishScore += score; + } + if (isADXSwitchedToBearish) + { + bearishScore += score; + } + + // + // RSI ... + + // + if (isRSIOS) + { + bullishScore += score; + } + if (isRSIBullish) + { + bullishScore += score; + } + if (isRSICrossedOverOS) + { + bullishScore += score; + } + if (isRSICrossedOverOB) + { + bullishScore += score; + } + if (isRSISwitchedToBullish) + { + bullishScore += score; + } + + // + if (isRSIOB) + { + bearishScore += score; + } + if (isRSIBearish) + { + bearishScore += score; + } + if (isRSICrossedUnderOB) + { + bearishScore += score; + } + if (isRSICrossedUnderOS) + { + bearishScore += score; + } + if (isRSISwitchedToBearish) + { + bearishScore += score; + } + + // + // DELTA ... + + // + if (isDeltaUp) + { + bullishScore += score; + } + if (isDeltaBullish) + { + bullishScore += score; + } + if (isDeltaSwitchedToBullish) + { + bullishScore += score; + } + + // + if (isDeltaDown) + { + bearishScore += score; + } + if (isDeltaBearish) + { + bearishScore += score; + } + if (isDeltaSwitchedToBearish) + { + bearishScore += score; + } + + // + // VOLUME ... + + // + if (isVolumeBullish) + { + bullishScore += score; + } + if (isVolumeSwitchedToBullish) + { + bullishScore += score; + } + + // + if (isVolumeBearish) + { + bearishScore += score; + } + if (isVolumeSwitchedToBearish) + { + bearishScore += score; + } + + // + // SIGNAL Bar ... + + // + if (isSBarBullish) + { + bullishScore += score; + } + if (isSBarSwitchedToBullish) + { + bullishScore += score; + } + + // + if (isSBarBearish) + { + bearishScore += score; + } + if (isSBarSwitchedToBearish) + { + bearishScore += score; + } + + // + // XHK Signal Bar ... + + // + if (isHKSBarBullish) + { + bullishScore += score; + } + if (isHKSBarSwitchedToBullish) + { + bullishScore += score; + } + + // + if (isHKSBarBearish) + { + bearishScore += score; + } + if (isHKSBarSwitchedToBearish) + { + bearishScore += score; + } + + // + // TREND ... + + // + if (isTrendUp) + { + bullishScore += score; + } + if (isTrendBullish) + { + bullishScore += score; + } + if (isTrendSwitchedToBullish) + { + bullishScore += score; + } + + // + if (isTrendDown) + { + bearishScore += score; + } + if (isTrendBearish) + { + bearishScore += score; + } + if (isTrendSwitchedToBearish) + { + bearishScore += score; + } + + // + // PEAK and VALE ... + + // + if (isValeSameLast) + { + bullishScore += score; + } + if (isValeOverLast) + { + bullishScore += score; + } + if (isPeakOverLast) + { + bullishScore += score; + } + + // + if (isPeakSameLast) + { + bearishScore += score; + } + if (isPeakUnderLast) + { + bearishScore += score; + } + if (isValeUnderLast) + { + bearishScore += score; + } + } + + /** + * Generate Summary String for Represent Conditions State ... + * + * @param onlyCommons: Boolean, Just Generate Only Commons Conditions ... + * @param onlyConditions: Boolean, Just Generate Only Conditions ... + * @param includeScores: Boolean, Attach Scores Representations on Result ... + * @param ignoreFalseConditions: Boolean, Ignore False Conditions on Result ... + * @param separator: String, Separate Lines ... + * + * @return ( string ) + */ + string GenerateSummary( + bool onlyCommons = false, + bool onlyConditions = false, + bool includeScores = true, + bool ignoreFalseConditions = true, + string separator = "\n" // + ) + { + // + string result = NULL; + + // + double bullishScore = 0; + double bearishScore = 0; + GenerateScore( + bullishScore, + bearishScore // + ); + + // + string scoresStr = + // + "Scores: " + separator + + "---------------" + separator + + "Bullish: " + ToString(bullishScore) + separator + + "Bearish: " + ToString(bearishScore) + separator + + "" + // + ; + + // + string commonStr = GenerateSpecifiedCommonSummary( + this, + separator, + includeScores // + ); + + // + string conditionsStr = + // + "-----------------------" + separator + + "XCATB: " + separator + + "-----------------------" + separator + + "" + separator + + // + "-----------------------" + separator + + "ATR Band: " + separator + + "-----------------------" + separator + + ToString("isATRUp", isATRUp, ignoreFalseConditions, separator) + + ToString("isATRDown", isATRDown, ignoreFalseConditions, separator) + + ToString("isClosedOverATRUpper", isClosedOverATRUpper, ignoreFalseConditions, separator) + + ToString("isClosedUnderATRLower", isClosedUnderATRLower, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "SAR: " + separator + + "-----------------------" + separator + + ToString("isSarBullish", isSarBullish, ignoreFalseConditions, separator) + + ToString("isSarBearish", isSarBearish, ignoreFalseConditions, separator) + + ToString("isSarSwitchedToBullish", isSarSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isSarSwitchedToBearish", isSarSwitchedToBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "ADX: " + separator + + "-----------------------" + separator + + ToString("isADXBiggerLast", isADXBiggerLast, ignoreFalseConditions, separator) + + ToString("isADXLesserLast", isADXLesserLast, ignoreFalseConditions, separator) + + ToString("isADXOverThreshold", isADXOverThreshold, ignoreFalseConditions, separator) + + ToString("isADXUnderThreshold", isADXUnderThreshold, ignoreFalseConditions, separator) + + ToString("isDXPBiggerThanDXN", isDXPBiggerThanDXN, ignoreFalseConditions, separator) + + ToString("isDXNBiggerThanDXP", isDXNBiggerThanDXP, ignoreFalseConditions, separator) + + ToString("isADXBullish", isADXBullish, ignoreFalseConditions, separator) + + ToString("isADXBearish", isADXBearish, ignoreFalseConditions, separator) + + ToString("isADXSwitchedToBullish", isADXSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isADXSwitchedToBearish", isADXSwitchedToBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "RSI: " + separator + + "-----------------------" + separator + + ToString("isRSIBullish", isRSIBullish, ignoreFalseConditions, separator) + + ToString("isRSIBearish", isRSIBearish, ignoreFalseConditions, separator) + + ToString("isRSISwitchedToBullish", isRSISwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isRSISwitchedToBearish", isRSISwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isRSIOB", isRSIOB, ignoreFalseConditions, separator) + + ToString("isRSIOS", isRSIOS, ignoreFalseConditions, separator) + + ToString("isRSICrossedOverOB", isRSICrossedOverOB, ignoreFalseConditions, separator) + + ToString("isRSICrossedOverOS", isRSICrossedOverOS, ignoreFalseConditions, separator) + + ToString("isRSICrossedUnderOB", isRSICrossedUnderOB, ignoreFalseConditions, separator) + + ToString("isRSICrossedUnderOS", isRSICrossedUnderOS, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "DELTA: " + separator + + "-----------------------" + separator + + ToString("isDeltaUp", isDeltaUp, ignoreFalseConditions, separator) + + ToString("isDeltaDown", isDeltaDown, ignoreFalseConditions, separator) + + ToString("isDeltaBullish", isDeltaBullish, ignoreFalseConditions, separator) + + ToString("isDeltaBearish", isDeltaBearish, ignoreFalseConditions, separator) + + ToString("isDeltaSwitchedToBullish", isDeltaSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isDeltaSwitchedToBearish", isDeltaSwitchedToBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "VOLUME: " + separator + + "-----------------------" + separator + + ToString("isVolumeBullish", isVolumeBullish, ignoreFalseConditions, separator) + + ToString("isVolumeBearish", isVolumeBearish, ignoreFalseConditions, separator) + + ToString("isVolumeSwitchedToBullish", isVolumeSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isVolumeSwitchedToBearish", isVolumeSwitchedToBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "SIGNAL Bar: " + separator + + "-----------------------" + separator + + ToString("isSBarBullish", isSBarBullish, ignoreFalseConditions, separator) + + ToString("isSBarBearish", isSBarBearish, ignoreFalseConditions, separator) + + ToString("isSBarSwitchedToBullish", isSBarSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isSBarSwitchedToBearish", isSBarSwitchedToBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "XHK Signal Bar: " + separator + + "-----------------------" + separator + + ToString("isHKSBarBullish", isHKSBarBullish, ignoreFalseConditions, separator) + + ToString("isHKSBarBearish", isHKSBarBearish, ignoreFalseConditions, separator) + + ToString("isHKSBarSwitchedToBullish", isHKSBarSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isHKSBarSwitchedToBearish", isHKSBarSwitchedToBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "Trend: " + separator + + "-----------------------" + separator + + ToString("isTrendUp", isTrendUp, ignoreFalseConditions, separator) + + ToString("isTrendDown", isTrendDown, ignoreFalseConditions, separator) + + ToString("isTrendBullish", isTrendBullish, ignoreFalseConditions, separator) + + ToString("isTrendBearish", isTrendBearish, ignoreFalseConditions, separator) + + ToString("isTrendSwitchedToBullish", isTrendSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isTrendSwitchedToBearish", isTrendSwitchedToBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "Peak: " + separator + + "-----------------------" + separator + + ToString("isPeakSameLast", isPeakSameLast, ignoreFalseConditions, separator) + + ToString("isPeakOverLast", isPeakOverLast, ignoreFalseConditions, separator) + + ToString("isPeakUnderLast", isPeakUnderLast, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "Vale: " + separator + + "-----------------------" + separator + + ToString("isValeSameLast", isValeSameLast, ignoreFalseConditions, separator) + + ToString("isValeOverLast", isValeOverLast, ignoreFalseConditions, separator) + + ToString("isValeUnderLast", isValeUnderLast, ignoreFalseConditions, separator) + + "" + // + ; + + // + result = + // + "[" + GetTag() + "]" + separator + + (onlyConditions + ? "" + : commonStr) + + (!includeScores + ? "" + : scoresStr) + + " " + separator + + (onlyCommons + ? "" + : conditionsStr) + + "" + // + ; + + // + return result; + } + + /** + * Retrieve nique Tag Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + return GetTypeName(this); + } + + // +}; + +// +// Class ... +class XCX121XCatbHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + + // + // Buffers ... + double sarBuffer[]; + double atrBuffer[]; + double rsiBuffer[]; + double adxBuffer[]; + double sHHBuffer[]; + double sLLBuffer[]; + double mHHBuffer[]; + double mLLBuffer[]; + double lHHBuffer[]; + double lLLBuffer[]; + double hHHBuffer[]; + double hLLBuffer[]; + double adxpBuffer[]; + double adxnBuffer[]; + double peakBuffer[]; + double valeBuffer[]; + double deltaBuffer[]; + double trendBuffer[]; + double hkLowBuffer[]; + double hkOpenBuffer[]; + double hkHighBuffer[]; + double hkCloseBuffer[]; + double sarStateBuffer[]; + double atrUpperBuffer[]; + double atrLowerBuffer[]; + double sBarOpenBuffer[]; + double sBarCloseBuffer[]; + double trendStateBuffer[]; + double hkSBarOpenBuffer[]; + double peakGoldenBuffer[]; + double valeGoldenBuffer[]; + double hkSBarCloseBuffer[]; + double deltaSignalBuffer[]; + double bullishVolumeBuffer[]; + double bearishVolumeBuffer[]; + double bullishVolumeSignalBuffer[]; + double bearishVolumeSignalBuffer[]; + + // + // Market Shift ... + + // + // SAR ... + XDirectionShift lastSarBullish; + XDirectionShift lastSarBearish; + + // + // TREND ... + XDirectionShift lastTrendBullish; + XDirectionShift lastTrendBearish; + + // + // DELTA ... + XDirectionShift lastDeltaBullish; + XDirectionShift lastDeltaBearish; + + // + // VOLUME ... + XDirectionShift lastVolumeBullish; + XDirectionShift lastVolumeBearish; + + // + // SIGNAL Bar ... + XDirectionShift lastSignalBarBullish; + XDirectionShift lastSignalBarBearish; + + // + // XHK SIGNAL Bar ... + XDirectionShift lastHKSignalBarBullish; + XDirectionShift lastHKSignalBarBearish; + + // + // Constructors ... + XCX121XCatbHelper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCX121XCatbHelper() + { + // + mInputs.Clean(); + + // + Clean(sarBuffer); + Clean(atrBuffer); + Clean(rsiBuffer); + Clean(adxBuffer); + Clean(sHHBuffer); + Clean(sLLBuffer); + Clean(mHHBuffer); + Clean(mLLBuffer); + Clean(lHHBuffer); + Clean(lLLBuffer); + Clean(hHHBuffer); + Clean(hLLBuffer); + Clean(adxpBuffer); + Clean(adxnBuffer); + Clean(peakBuffer); + Clean(valeBuffer); + Clean(deltaBuffer); + Clean(trendBuffer); + Clean(hkLowBuffer); + Clean(hkOpenBuffer); + Clean(hkHighBuffer); + Clean(hkCloseBuffer); + Clean(sarStateBuffer); + Clean(atrUpperBuffer); + Clean(atrLowerBuffer); + Clean(sBarOpenBuffer); + Clean(sBarCloseBuffer); + Clean(trendStateBuffer); + Clean(hkSBarOpenBuffer); + Clean(peakGoldenBuffer); + Clean(valeGoldenBuffer); + Clean(hkSBarCloseBuffer); + Clean(deltaSignalBuffer); + Clean(bullishVolumeBuffer); + Clean(bearishVolumeBuffer); + Clean(bullishVolumeSignalBuffer); + Clean(bearishVolumeSignalBuffer); + } + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + X121XCatbInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + ArraySetAsSeries(sarBuffer, true); + ArraySetAsSeries(atrBuffer, true); + ArraySetAsSeries(rsiBuffer, true); + ArraySetAsSeries(adxBuffer, true); + ArraySetAsSeries(sHHBuffer, true); + ArraySetAsSeries(sLLBuffer, true); + ArraySetAsSeries(mHHBuffer, true); + ArraySetAsSeries(mLLBuffer, true); + ArraySetAsSeries(lHHBuffer, true); + ArraySetAsSeries(lLLBuffer, true); + ArraySetAsSeries(hHHBuffer, true); + ArraySetAsSeries(hLLBuffer, true); + ArraySetAsSeries(adxpBuffer, true); + ArraySetAsSeries(adxnBuffer, true); + ArraySetAsSeries(peakBuffer, true); + ArraySetAsSeries(valeBuffer, true); + ArraySetAsSeries(deltaBuffer, true); + ArraySetAsSeries(trendBuffer, true); + ArraySetAsSeries(hkLowBuffer, true); + ArraySetAsSeries(hkOpenBuffer, true); + ArraySetAsSeries(hkHighBuffer, true); + ArraySetAsSeries(hkCloseBuffer, true); + ArraySetAsSeries(sarStateBuffer, true); + ArraySetAsSeries(atrUpperBuffer, true); + ArraySetAsSeries(atrLowerBuffer, true); + ArraySetAsSeries(sBarOpenBuffer, true); + ArraySetAsSeries(sBarCloseBuffer, true); + ArraySetAsSeries(trendStateBuffer, true); + ArraySetAsSeries(hkSBarOpenBuffer, true); + ArraySetAsSeries(peakGoldenBuffer, true); + ArraySetAsSeries(valeGoldenBuffer, true); + ArraySetAsSeries(hkSBarCloseBuffer, true); + ArraySetAsSeries(deltaSignalBuffer, true); + ArraySetAsSeries(bullishVolumeBuffer, true); + ArraySetAsSeries(bearishVolumeBuffer, true); + ArraySetAsSeries(bullishVolumeSignalBuffer, true); + ArraySetAsSeries(bearishVolumeSignalBuffer, true); + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.xcatb", + "", // Market ... + mInputs.scMethod, + mInputs.scPeriod, + mInputs.mcMethod, + mInputs.mcPeriod, + mInputs.lcMethod, + mInputs.lcPeriod, + mInputs.hcMethod, + mInputs.hcPeriod, + mInputs.appliedCycle, + "", // Signal ... + mInputs.signalR2R, + mInputs.drawSignals, + mInputs.drawTriggerBlock, + mInputs.slAtrMultiplier, + "", // Validating ... + mInputs.forceHasSwing, + mInputs.forceOBBarType, + mInputs.forceOBFVGBarType, + mInputs.forceHasFLiquidity, + mInputs.forceHasRLiquidity, + mInputs.validateGapSequence, + mInputs.validateBlockEdgeBreakout, + "", // Filtering ... + mInputs.filterBasedOnPV, + mInputs.filterBasedOnSar, + mInputs.filterBasedOnRSI, + mInputs.filterBasedOnADX, + mInputs.filterBasedOnATR, + mInputs.filterBasedOnTrend, + mInputs.filterBasedOnDelta, + mInputs.filterBasedOnVolume, + mInputs.filterBasedOnSignalBar, + mInputs.filterBasedOnHKSignalBar, + "", // Alerts ... + mInputs.alertPrefix, + mInputs.logAlerts, + mInputs.pushAlerts, + mInputs.mailAlerts, + mInputs.terminalAlerts, + "", // Presentation ... + mInputs.showBars, + mInputs.showPV, + mInputs.showPVGolden, + mInputs.showSar, + mInputs.showTrend, + mInputs.showATRBand, + mInputs.showSignalBars, + mInputs.showHKSignalBars, + mInputs.startCalculationForLastBars + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + void Check(int barIndex = 0) + { + // + bool has = false; + + // + bool isBullish = false; + bool isBearish = false; + + // + barIndex = NormalizeInt(barIndex, 0); + + // + X121XCatbConditions conditions; + has = GetConditions( + conditions, + barIndex, + 4 // + ); + if (!has) + { + // + conditions.Clean(); + return; + } + + // + // Checking Shifts ... + + // + // SAR ... + + // + isBullish = conditions.isSarSwitchedToBullish; + isBearish = conditions.isSarSwitchedToBearish; + + // + has = isBullish || + isBearish; + if (has) + { + // + // Bullish ... + has = + isBullish && + (!lastSarBullish.IsValid() + ? true + : lastSarBullish.at < conditions.bars[1].time); + if (has) + { + // + lastSarBullish.Clean(); + + // + lastSarBullish.type = "SAR"; + lastSarBullish.symbol = conditions.symbol; + lastSarBullish.period = conditions.period; + lastSarBullish.at = conditions.bars[1].time; + lastSarBullish.shiftTo = X_DIRECTION_BULLISH; + lastSarBullish.after = conditions.sarBuffer[1]; + lastSarBullish.before = conditions.sarBuffer[2]; + } + + // + // Bearish ... + has = + isBearish && + (!lastSarBearish.IsValid() + ? true + : lastSarBearish.at < conditions.bars[1].time); + if (has) + { + // + lastSarBearish.Clean(); + + // + lastSarBearish.type = "SAR"; + lastSarBearish.symbol = conditions.symbol; + lastSarBearish.period = conditions.period; + lastSarBearish.at = conditions.bars[1].time; + lastSarBearish.shiftTo = X_DIRECTION_BEARISH; + lastSarBearish.after = conditions.sarBuffer[1]; + lastSarBearish.before = conditions.sarBuffer[2]; + } + } + + // + // TREND ... + + // + isBullish = conditions.isTrendSwitchedToBullish; + isBearish = conditions.isTrendSwitchedToBearish; + + // + has = isBullish || + isBearish; + if (has) + { + // + // Bullish ... + has = + isBullish && + (!lastTrendBullish.IsValid() + ? true + : lastTrendBullish.at < conditions.bars[1].time); + if (has) + { + // + lastTrendBullish.Clean(); + + // + lastTrendBullish.type = "TREND"; + lastTrendBullish.symbol = conditions.symbol; + lastTrendBullish.period = conditions.period; + lastTrendBullish.at = conditions.bars[1].time; + lastTrendBullish.shiftTo = X_DIRECTION_BULLISH; + lastTrendBullish.after = conditions.trendBuffer[1]; + lastTrendBullish.before = conditions.trendBuffer[2]; + } + + // + // Bearish ... + has = + isBearish && + (!lastTrendBearish.IsValid() + ? true + : lastTrendBearish.at < conditions.bars[1].time); + if (has) + { + // + lastTrendBearish.Clean(); + + // + lastTrendBearish.type = "TREND"; + lastTrendBearish.symbol = conditions.symbol; + lastTrendBearish.period = conditions.period; + lastTrendBearish.at = conditions.bars[1].time; + lastTrendBearish.shiftTo = X_DIRECTION_BEARISH; + lastTrendBearish.after = conditions.trendBuffer[1]; + lastTrendBearish.before = conditions.trendBuffer[2]; + } + } + + // + // DELTA ... + + // + isBullish = + // + ( + // + // Delta is Up ... + conditions.deltaBuffer[1] > conditions.deltaBuffer[2] && + // + // Delta Signal is Up ... + conditions.deltaSignalBuffer[1] > conditions.deltaSignalBuffer[2] && + // + // Delta Crossed Over Delta ... + conditions.deltaBuffer[1] > conditions.deltaSignalBuffer[1] && + conditions.deltaBuffer[2] <= conditions.deltaSignalBuffer[2] + // + ) + // + ; + + // + isBearish = + // + ( + // + // Delta is Down ... + conditions.deltaBuffer[1] < conditions.deltaBuffer[2] && + // + // Delta Signal is Down ... + conditions.deltaSignalBuffer[1] < conditions.deltaSignalBuffer[2] && + // + // Delta Crossed Under Delta Signal ... + conditions.deltaBuffer[1] < conditions.deltaSignalBuffer[1] && + conditions.deltaBuffer[2] >= conditions.deltaSignalBuffer[2] + // + ) + // + ; + + // + has = isBullish || + isBearish; + if (has) + { + // + // Bullish ... + has = + isBullish && + (!lastDeltaBullish.IsValid() + ? true + : lastDeltaBullish.at < conditions.bars[1].time); + if (has) + { + // + lastDeltaBullish.Clean(); + + // + lastDeltaBullish.type = "DELTA"; + lastDeltaBullish.symbol = conditions.symbol; + lastDeltaBullish.period = conditions.period; + lastDeltaBullish.at = conditions.bars[1].time; + lastDeltaBullish.shiftTo = X_DIRECTION_BULLISH; + lastDeltaBullish.after = conditions.bars[1].close; + lastDeltaBullish.before = conditions.bars[2].close; + } + + // + // Bearish ... + has = + isBearish && + (!lastDeltaBearish.IsValid() + ? true + : lastDeltaBearish.at < conditions.bars[1].time); + if (has) + { + // + lastDeltaBearish.Clean(); + + // + lastDeltaBearish.type = "DELTA"; + lastDeltaBearish.symbol = conditions.symbol; + lastDeltaBearish.period = conditions.period; + lastDeltaBearish.at = conditions.bars[1].time; + lastDeltaBearish.shiftTo = X_DIRECTION_BEARISH; + lastDeltaBearish.after = conditions.bars[1].close; + lastDeltaBearish.before = conditions.bars[2].close; + } + } + + // + // VOLUME ... + + // + isBullish = + // + ( + // + // Volume is Up ... + conditions.bullishVolumeBuffer[1] > conditions.bullishVolumeBuffer[2] && + // + // Volume Signal is Up ... + conditions.bullishVolumeSignalBuffer[1] > conditions.bullishVolumeSignalBuffer[2] && + // + // Volume Signals Crossed Over ... + conditions.bullishVolumeSignalBuffer[1] > conditions.bearishVolumeSignalBuffer[1] && + conditions.bullishVolumeSignalBuffer[2] <= conditions.bearishVolumeSignalBuffer[2] + // + ) + // + ; + + // + isBullish = + // + ( + // + // Volume is Up ... + conditions.bearishVolumeBuffer[1] > conditions.bearishVolumeBuffer[2] && + // + // Volume Signal is Up ... + conditions.bearishVolumeSignalBuffer[1] > conditions.bearishVolumeSignalBuffer[2] && + // + // Volume Signals Crossed Over ... + conditions.bearishVolumeSignalBuffer[1] > conditions.bullishVolumeSignalBuffer[1] && + conditions.bearishVolumeSignalBuffer[2] <= conditions.bullishVolumeSignalBuffer[2] + // + ) + // + ; + + // + has = isBullish || + isBearish; + if (has) + { + // + // Bullish ... + has = + isBullish && + (!lastVolumeBullish.IsValid() + ? true + : lastVolumeBullish.at < conditions.bars[1].time); + if (has) + { + // + lastVolumeBullish.Clean(); + + // + lastVolumeBullish.type = "VOLUME"; + lastVolumeBullish.symbol = conditions.symbol; + lastVolumeBullish.period = conditions.period; + lastVolumeBullish.at = conditions.bars[1].time; + lastVolumeBullish.shiftTo = X_DIRECTION_BULLISH; + lastVolumeBullish.after = conditions.bars[1].close; + lastVolumeBullish.before = conditions.bars[2].close; + } + + // + // Bearish ... + has = + isBearish && + (!lastVolumeBearish.IsValid() + ? true + : lastVolumeBearish.at < conditions.bars[1].time); + if (has) + { + // + lastVolumeBearish.Clean(); + + // + lastVolumeBearish.type = "VOLUME"; + lastVolumeBearish.symbol = conditions.symbol; + lastVolumeBearish.period = conditions.period; + lastVolumeBearish.at = conditions.bars[1].time; + lastVolumeBearish.shiftTo = X_DIRECTION_BEARISH; + lastVolumeBearish.after = conditions.bars[1].close; + lastVolumeBearish.before = conditions.bars[2].close; + } + } + + // + // SIGNAL Bar ... + + // + isBullish = conditions.isSBarSwitchedToBullish; + isBearish = conditions.isSBarSwitchedToBearish; + + // + has = isBullish || + isBearish; + if (has) + { + // + // Bullish ... + has = + isBullish && + (!lastSignalBarBullish.IsValid() + ? true + : lastSignalBarBullish.at < conditions.bars[1].time); + if (has) + { + // + lastSignalBarBullish.Clean(); + + // + lastSignalBarBullish.type = "SIGNALBAR"; + lastSignalBarBullish.symbol = conditions.symbol; + lastSignalBarBullish.period = conditions.period; + lastSignalBarBullish.at = conditions.bars[1].time; + lastSignalBarBullish.shiftTo = X_DIRECTION_BULLISH; + lastSignalBarBullish.after = conditions.sBarCloseBuffer[1]; + lastSignalBarBullish.before = conditions.sBarCloseBuffer[2]; + } + + // + // Bearish ... + has = + isBearish && + (!lastSignalBarBearish.IsValid() + ? true + : lastSignalBarBearish.at < conditions.bars[1].time); + if (has) + { + // + lastSignalBarBearish.Clean(); + + // + lastSignalBarBearish.type = "SIGNALBAR"; + lastSignalBarBearish.symbol = conditions.symbol; + lastSignalBarBearish.period = conditions.period; + lastSignalBarBearish.at = conditions.bars[1].time; + lastSignalBarBearish.shiftTo = X_DIRECTION_BEARISH; + lastSignalBarBearish.after = conditions.sBarCloseBuffer[1]; + lastSignalBarBearish.before = conditions.sBarCloseBuffer[2]; + } + } + + // + // HKSIGNAL Bar ... + + // + isBullish = conditions.isHKSBarSwitchedToBullish; + isBearish = conditions.isHKSBarSwitchedToBearish; + + // + has = isBullish || + isBearish; + if (has) + { + // + // Bullish ... + has = + isBullish && + (!lastHKSignalBarBullish.IsValid() + ? true + : lastHKSignalBarBullish.at < conditions.bars[1].time); + if (has) + { + // + lastHKSignalBarBullish.Clean(); + + // + lastHKSignalBarBullish.type = "HKSIGNALBAR"; + lastHKSignalBarBullish.symbol = conditions.symbol; + lastHKSignalBarBullish.period = conditions.period; + lastHKSignalBarBullish.at = conditions.bars[1].time; + lastHKSignalBarBullish.shiftTo = X_DIRECTION_BULLISH; + lastHKSignalBarBullish.after = conditions.hkSBarCloseBuffer[1]; + lastHKSignalBarBullish.before = conditions.hkSBarCloseBuffer[2]; + } + + // + // Bearish ... + has = + isBearish && + (!lastHKSignalBarBearish.IsValid() + ? true + : lastHKSignalBarBearish.at < conditions.bars[1].time); + if (has) + { + // + lastHKSignalBarBearish.Clean(); + + // + lastHKSignalBarBearish.type = "HKSIGNALBAR"; + lastHKSignalBarBearish.symbol = conditions.symbol; + lastHKSignalBarBearish.period = conditions.period; + lastHKSignalBarBearish.at = conditions.bars[1].time; + lastHKSignalBarBearish.shiftTo = X_DIRECTION_BEARISH; + lastHKSignalBarBearish.after = conditions.hkSBarCloseBuffer[1]; + lastHKSignalBarBearish.before = conditions.hkSBarCloseBuffer[2]; + } + } + + // + // Cleanup Resources ... + + // + conditions.Clean(); + } + + // + // Inputs ... + + // + X121XCatbInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + X121XCatbInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Readers ... + + // + // SAR ... + + // + double GetSar( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(sarBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return sarBuffer[barIndex]; + } + + // + 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(start); + + // + // Copy Items ... + return Copy( + 0, + count, + sarBuffer, + buffer, + forceClean + // + ); + } + + // + // SAR State ... + + // + double GetSarState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(sarStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return sarStateBuffer[barIndex]; + } + + // + int CopySarState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + sarStateBuffer, + buffer, + forceClean + // + ); + } + + // + // PEAK ... + + // + double GetPeak( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(peakBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return peakBuffer[barIndex]; + } + + // + 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(start); + + // + // Copy Items ... + return Copy( + 0, + count, + peakBuffer, + buffer, + forceClean + // + ); + } + + // + // VALE ... + + // + double GetVale( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(valeBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return valeBuffer[barIndex]; + } + + // + 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(start); + + // + // Copy Items ... + return Copy( + 0, + count, + valeBuffer, + buffer, + forceClean + // + ); + } + + // + // PEAK Golden ... + + // + double GetPeakGolden( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(peakGoldenBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return peakGoldenBuffer[barIndex]; + } + + // + int CopyPeakGolden( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + peakGoldenBuffer, + buffer, + forceClean + // + ); + } + + // + // VALE Golden ... + + // + double GetValeGolden( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(valeGoldenBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return valeGoldenBuffer[barIndex]; + } + + // + int CopyValeGolden( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + valeGoldenBuffer, + buffer, + forceClean + // + ); + } + + // + // ATR ... + + // + double GetATR( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(atrBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return atrBuffer[barIndex]; + } + + // + 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(start); + + // + // Copy Items ... + return Copy( + 0, + count, + atrBuffer, + buffer, + forceClean + // + ); + } + + // + // ATR Band Upper ... + + // + double GetATRUpper( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(atrUpperBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return atrUpperBuffer[barIndex]; + } + + // + int CopyATRUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + atrUpperBuffer, + buffer, + forceClean + // + ); + } + + // + // ATR Band Lower ... + + // + double GetATRLower( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(atrLowerBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return atrLowerBuffer[barIndex]; + } + + // + int CopyATRLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + atrLowerBuffer, + buffer, + forceClean + // + ); + } + + // + // TREND ... + + // + double GetTrend( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(trendBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return trendBuffer[barIndex]; + } + + // + 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(start); + + // + // Copy Items ... + return Copy( + 0, + count, + trendBuffer, + buffer, + forceClean + // + ); + } + + // + // TREND State ... + + // + double GetTrendState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(trendStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return trendStateBuffer[barIndex]; + } + + // + int CopyTrendState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + trendStateBuffer, + buffer, + forceClean + // + ); + } + + // + // SIGNAL Bar ... + + // + // OPEN ... + + // + double GetSBarOpen( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(sBarOpenBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return sBarOpenBuffer[barIndex]; + } + + // + int CopySBarOpen( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + sBarOpenBuffer, + buffer, + forceClean + // + ); + } + + // + // CLOSE ... + + // + double GetSBarClose( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(sBarCloseBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return sBarCloseBuffer[barIndex]; + } + + // + int CopySBarClose( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + sBarCloseBuffer, + buffer, + forceClean + // + ); + } + + // + // XHK SIGNAL Bar ... + + // + // OPEN ... + + // + double GetHKSBarOpen( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hkSBarOpenBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hkSBarOpenBuffer[barIndex]; + } + + // + int CopyHKSBarOpen( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hkSBarOpenBuffer, + buffer, + forceClean + // + ); + } + + // + // CLOSE ... + + // + double GetHKSBarClose( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hkSBarCloseBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hkSBarCloseBuffer[barIndex]; + } + + // + int CopyHKSBarClose( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hkSBarCloseBuffer, + buffer, + forceClean + // + ); + } + + // + // CYCLES Range ... + + // + // SHORT ... + + // + // HH ... + + // + double GetSHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(sHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return sHHBuffer[barIndex]; + } + + // + int CopySHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + sHHBuffer, + buffer, + forceClean + // + ); + } + + // + // LL ... + + // + double GetSLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(sLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return sLLBuffer[barIndex]; + } + + // + int CopySLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + sLLBuffer, + buffer, + forceClean + // + ); + } + + // + // MEDIUM ... + + // + // HH ... + + // + double GetMHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(mHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return mHHBuffer[barIndex]; + } + + // + int CopyMHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + mHHBuffer, + buffer, + forceClean + // + ); + } + + // + // LL ... + + // + double GetMLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(mLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return mLLBuffer[barIndex]; + } + + // + int CopyMLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + mLLBuffer, + buffer, + forceClean + // + ); + } + + // + // LONG ... + + // + // HH ... + + // + double GetLHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(lHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return lHHBuffer[barIndex]; + } + + // + int CopyLHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + lHHBuffer, + buffer, + forceClean + // + ); + } + + // + // LL ... + + // + double GetLLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(lLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return lLLBuffer[barIndex]; + } + + // + int CopyLLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + lLLBuffer, + buffer, + forceClean + // + ); + } + + // + // HIND ... + + // + // HH ... + + // + double GetHHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hHHBuffer[barIndex]; + } + + // + int CopyHHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hHHBuffer, + buffer, + forceClean + // + ); + } + + // + // LL ... + + // + double GetHLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hLLBuffer[barIndex]; + } + + // + int CopyHLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hLLBuffer, + buffer, + forceClean + // + ); + } + + // + // ADX ... + + // + double GetADX( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(adxBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return adxBuffer[barIndex]; + } + + // + int CopyADX( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + adxBuffer, + buffer, + forceClean + // + ); + } + + // + // ADXP ... + + // + double GetADXP( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(adxpBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return adxpBuffer[barIndex]; + } + + // + int CopyADXP( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + adxpBuffer, + buffer, + forceClean + // + ); + } + + // + // ADXN ... + + // + double GetADXN( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(adxnBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return adxnBuffer[barIndex]; + } + + // + int CopyADXN( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + adxnBuffer, + buffer, + forceClean + // + ); + } + + // + // DELTA ... + + // + double GetDelta( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(deltaBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return deltaBuffer[barIndex]; + } + + // + int CopyDelta( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + deltaBuffer, + buffer, + forceClean + // + ); + } + + // + // DELTA Signal ... + + // + double GetDeltaSignal( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(deltaSignalBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return deltaSignalBuffer[barIndex]; + } + + // + int CopyDeltaSignal( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + deltaSignalBuffer, + buffer, + forceClean + // + ); + } + + // + // VOLUME ... + + // + // Bullish ... + + // + double GetBullishVolume( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(bullishVolumeBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return bullishVolumeBuffer[barIndex]; + } + + // + int CopyBullishVolume( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + bullishVolumeBuffer, + buffer, + forceClean + // + ); + } + + // + // Bearish ... + + // + double GetBearishVolume( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(bearishVolumeBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return bearishVolumeBuffer[barIndex]; + } + + // + int CopyBearishVolume( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + bearishVolumeBuffer, + buffer, + forceClean + // + ); + } + + // + // VOLUME Signal ... + + // + // Bullish ... + + // + double GetBullishVolumeSignal( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(bullishVolumeSignalBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return bullishVolumeSignalBuffer[barIndex]; + } + + // + int CopyBullishVolumeSignal( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + bullishVolumeSignalBuffer, + buffer, + forceClean + // + ); + } + + // + // Bearish ... + + // + double GetBearishVolumeSignal( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(bearishVolumeSignalBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return bearishVolumeSignalBuffer[barIndex]; + } + + // + int CopyBearishVolumeSignal( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + bearishVolumeSignalBuffer, + buffer, + forceClean + // + ); + } + + // + // XHK ... + + // + // Open ... + + // + double GetHKOpen( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hkOpenBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hkOpenBuffer[barIndex]; + } + + // + int CopyHKOpen( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hkOpenBuffer, + buffer, + forceClean + // + ); + } + + // + // High ... + + // + double GetHKHigh( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hkHighBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hkHighBuffer[barIndex]; + } + + // + int CopyHKHigh( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hkHighBuffer, + buffer, + forceClean + // + ); + } + + // + // Low ... + + // + double GetHKLow( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hkLowBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hkLowBuffer[barIndex]; + } + + // + int CopyHKLow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hkLowBuffer, + buffer, + forceClean + // + ); + } + + // + // Close ... + + // + double GetHKClose( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hkCloseBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hkCloseBuffer[barIndex]; + } + + // + int CopyHKClose( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hkCloseBuffer, + buffer, + forceClean + // + ); + } + + // + // RSI ... + + // + double GetRSI( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(rsiBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return rsiBuffer[barIndex]; + } + + // + 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(start); + + // + // Copy Items ... + return Copy( + 0, + count, + rsiBuffer, + buffer, + forceClean + // + ); + } + + // + // Tools ... + + // + void Update( + int barIndex // Bar Index + ) + { + // + Calculate(barIndex); + } + + // + void Free() override + { + Cleanup(10); + } + + // + bool GetConditions( + X121XCatbConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = true; + + // + if (loopback < 5) + { + loopback = 5; + } + + // + conditions.Clean(); + + // + conditions.symbol = mSymbol; + conditions.period = mPeriod; + conditions.time = TimeCurrent(); + + // + // Filling Bars ... + int barsCount = GetBars( + conditions.bars, + mSymbol, + mPeriod, + barIndex, + loopback // + ); + result = barsCount == loopback; + if (!result) + { + // + conditions.Clean(); + + // + return result; + } + + // + int zIDX = 0; + int cIDX = 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + int p3IDX = p2IDX + 1; + int p4IDX = p3IDX + 1; + + // + conditions.to = conditions.bars[0].time; + conditions.from = conditions.bars[ArraySize(conditions.bars) - 1].time; + + // + int zIndex = barIndex; + + // + // Buffers ... + + CopySar( + zIndex, + loopback, + conditions.sarBuffer // + ); + + // + CopySarState( + zIndex, + loopback, + conditions.sarStateBuffer // + ); + + // + CopyPeak( + zIndex, + loopback, + conditions.peakBuffer // + ); + + // + CopyVale( + zIndex, + loopback, + conditions.valeBuffer // + ); + + // + CopyPeakGolden( + zIndex, + loopback, + conditions.peakGoldenBuffer // + ); + + // + CopyValeGolden( + zIndex, + loopback, + conditions.valeGoldenBuffer // + ); + + // + CopyATR( + zIndex, + loopback, + conditions.atrBuffer // + ); + + // + CopyATRUpper( + zIndex, + loopback, + conditions.atrUpperBuffer // + ); + + // + CopyATRLower( + zIndex, + loopback, + conditions.atrLowerBuffer // + ); + + // + CopyTrend( + zIndex, + loopback, + conditions.trendBuffer // + ); + + // + CopyTrendState( + zIndex, + loopback, + conditions.trendStateBuffer // + ); + + // + CopySBarOpen( + zIndex, + loopback, + conditions.sBarOpenBuffer // + ); + + // + CopySBarClose( + zIndex, + loopback, + conditions.sBarCloseBuffer // + ); + + // + CopyHKSBarOpen( + zIndex, + loopback, + conditions.hkSBarOpenBuffer // + ); + + // + CopyHKSBarClose( + zIndex, + loopback, + conditions.hkSBarCloseBuffer // + ); + + // + CopySHH( + zIndex, + loopback, + conditions.sHHBuffer // + ); + + // + CopySLL( + zIndex, + loopback, + conditions.sLLBuffer // + ); + + // + CopyMHH( + zIndex, + loopback, + conditions.mHHBuffer // + ); + + // + CopyMLL( + zIndex, + loopback, + conditions.mLLBuffer // + ); + + // + CopyLHH( + zIndex, + loopback, + conditions.lHHBuffer // + ); + + // + CopyLLL( + zIndex, + loopback, + conditions.lLLBuffer // + ); + + // + CopyHHH( + zIndex, + loopback, + conditions.hHHBuffer // + ); + + // + CopyHLL( + zIndex, + loopback, + conditions.hLLBuffer // + ); + + // + CopyADX( + zIndex, + loopback, + conditions.adxBuffer // + ); + + // + CopyADXP( + zIndex, + loopback, + conditions.adxpBuffer // + ); + + // + CopyADXN( + zIndex, + loopback, + conditions.adxnBuffer // + ); + + // + CopyDelta( + zIndex, + loopback, + conditions.deltaBuffer // + ); + + // + CopyDeltaSignal( + zIndex, + loopback, + conditions.deltaSignalBuffer // + ); + + // + CopyBullishVolume( + zIndex, + loopback, + conditions.bullishVolumeBuffer // + ); + + // + CopyBearishVolume( + zIndex, + loopback, + conditions.bearishVolumeBuffer // + ); + + // + CopyBullishVolumeSignal( + zIndex, + loopback, + conditions.bullishVolumeSignalBuffer // + ); + + // + CopyBearishVolumeSignal( + zIndex, + loopback, + conditions.bearishVolumeSignalBuffer // + ); + + // + CopyHKOpen( + zIndex, + loopback, + conditions.hkOpenBuffer // + ); + + // + CopyHKHigh( + zIndex, + loopback, + conditions.hkHighBuffer // + ); + + // + CopyHKLow( + zIndex, + loopback, + conditions.hkLowBuffer // + ); + + // + CopyHKClose( + zIndex, + loopback, + conditions.hkCloseBuffer // + ); + + // + CopyRSI( + zIndex, + loopback, + conditions.rsiBuffer // + ); + + // + // Calculate ... + + // + double _rsiOBLevel = mInputs.rsiOBLevel; // Over Bought Level + double _rsiOSLevel = mInputs.rsiOSLevel; // Over Sold Level + double _adxThreshold = mInputs.adxThreshold; // Big Movement Threshold + + // + // Reading Values ... + + // + // ATR Upper ... + double zATRUpper = conditions.atrUpperBuffer[zIDX]; + double cATRUpper = conditions.atrUpperBuffer[cIDX]; + double pATRUpper = conditions.atrUpperBuffer[pIDX]; + double p2ATRUpper = conditions.atrUpperBuffer[p2IDX]; + double p3ATRUpper = conditions.atrUpperBuffer[p3IDX]; + + // + // ATR Lower ... + double zATRLower = conditions.atrLowerBuffer[zIDX]; + double cATRLower = conditions.atrLowerBuffer[cIDX]; + double pATRLower = conditions.atrLowerBuffer[pIDX]; + double p2ATRLower = conditions.atrLowerBuffer[p2IDX]; + double p3ATRLower = conditions.atrLowerBuffer[p3IDX]; + + // + // SAR ... + + // + double zSAR = conditions.sarBuffer[zIDX]; + double cSar = conditions.sarBuffer[cIDX]; + double pSAR = conditions.sarBuffer[pIDX]; + double p2SAR = conditions.sarBuffer[p2IDX]; + double p3SAR = conditions.sarBuffer[p3IDX]; + + // + double zSarState = conditions.sarStateBuffer[zIDX]; + double cSarState = conditions.sarStateBuffer[cIDX]; + double pSarState = conditions.sarStateBuffer[pIDX]; + double p2SarState = conditions.sarStateBuffer[p2IDX]; + double p3SarState = conditions.sarStateBuffer[p3IDX]; + + // + // ADX ... + + // + double zADX = conditions.adxBuffer[zIDX]; + double cADX = conditions.adxBuffer[cIDX]; + double pADX = conditions.adxBuffer[pIDX]; + double p2ADX = conditions.adxBuffer[p2IDX]; + double p3ADX = conditions.adxBuffer[p3IDX]; + + // + // ADX P ... + + // + double zADXP = conditions.adxpBuffer[zIDX]; + double cADXP = conditions.adxpBuffer[cIDX]; + double pADXP = conditions.adxpBuffer[pIDX]; + double p2ADXP = conditions.adxpBuffer[p2IDX]; + double p3ADXP = conditions.adxpBuffer[p3IDX]; + + // + // ADX N ... + + // + double zADXN = conditions.adxnBuffer[zIDX]; + double cADXN = conditions.adxnBuffer[cIDX]; + double pADXN = conditions.adxnBuffer[pIDX]; + double p2ADXN = conditions.adxnBuffer[p2IDX]; + double p3ADXN = conditions.adxnBuffer[p3IDX]; + + // + // RSI ... + + // + double zRSI = conditions.rsiBuffer[zIDX]; + double cRSI = conditions.rsiBuffer[cIDX]; + double pRSI = conditions.rsiBuffer[pIDX]; + double p2RSI = conditions.rsiBuffer[p2IDX]; + double p3RSI = conditions.rsiBuffer[p3IDX]; + + // + // SIGNAL Bar ... + + // + double zSBarO = conditions.sBarOpenBuffer[zIDX]; + double cSBarO = conditions.sBarOpenBuffer[cIDX]; + double pSBarO = conditions.sBarOpenBuffer[pIDX]; + double p2SBarO = conditions.sBarOpenBuffer[p2IDX]; + double p3SBarO = conditions.sBarOpenBuffer[p3IDX]; + + // + double zSBarC = conditions.sBarCloseBuffer[zIDX]; + double cSBarC = conditions.sBarCloseBuffer[cIDX]; + double pSBarC = conditions.sBarCloseBuffer[pIDX]; + double p2SBarC = conditions.sBarCloseBuffer[p2IDX]; + double p3SBarC = conditions.sBarCloseBuffer[p3IDX]; + + // + // XHK SIGNAL Bar ... + + // + double zHKSBarO = conditions.hkSBarOpenBuffer[zIDX]; + double cHKSBarO = conditions.hkSBarOpenBuffer[cIDX]; + double pHKSBarO = conditions.hkSBarOpenBuffer[pIDX]; + double p2HKSBarO = conditions.hkSBarOpenBuffer[p2IDX]; + double p3HKSBarO = conditions.hkSBarOpenBuffer[p3IDX]; + + // + double zHKSBarC = conditions.hkSBarCloseBuffer[zIDX]; + double cHKSBarC = conditions.hkSBarCloseBuffer[cIDX]; + double pHKSBarC = conditions.hkSBarCloseBuffer[pIDX]; + double p2HKSBarC = conditions.hkSBarCloseBuffer[p2IDX]; + double p3HKSBarC = conditions.hkSBarCloseBuffer[p3IDX]; + + // + // TREND ... + + // + double zTrend = conditions.trendBuffer[zIDX]; + double cTrend = conditions.trendBuffer[cIDX]; + double pTrend = conditions.trendBuffer[pIDX]; + double p2Trend = conditions.trendBuffer[p2IDX]; + double p3Trend = conditions.trendBuffer[p3IDX]; + + // + double zTrendState = conditions.trendStateBuffer[zIDX]; + double cTrendState = conditions.trendStateBuffer[cIDX]; + double pTrendState = conditions.trendStateBuffer[pIDX]; + double p2TrendState = conditions.trendStateBuffer[p2IDX]; + double p3TrendState = conditions.trendStateBuffer[p3IDX]; + + // + // XPV ... + + // + double zPEAK = conditions.peakBuffer[zIDX]; + double cPEAK = conditions.peakBuffer[cIDX]; + double pPEAK = conditions.peakBuffer[pIDX]; + double p2PEAK = conditions.peakBuffer[p2IDX]; + double p3PEAK = conditions.peakBuffer[p3IDX]; + + // + double zVALE = conditions.valeBuffer[zIDX]; + double cVALE = conditions.valeBuffer[cIDX]; + double pVALE = conditions.valeBuffer[pIDX]; + double p2VALE = conditions.valeBuffer[p2IDX]; + double p3VALE = conditions.valeBuffer[p3IDX]; + + // + // DELTA ... + + // + double zDelta = conditions.deltaBuffer[zIDX]; + double cDelta = conditions.deltaBuffer[cIDX]; + double pDelta = conditions.deltaBuffer[pIDX]; + double p2Delta = conditions.deltaBuffer[p2IDX]; + double p3Delta = conditions.deltaBuffer[p3IDX]; + + // + double zDeltaSignal = conditions.deltaSignalBuffer[zIDX]; + double cDeltaSignal = conditions.deltaSignalBuffer[cIDX]; + double pDeltaSignal = conditions.deltaSignalBuffer[pIDX]; + double p2DeltaSignal = conditions.deltaSignalBuffer[p2IDX]; + double p3DeltaSignal = conditions.deltaSignalBuffer[p3IDX]; + + // + // VOLUME ... + + // + double zBullishVolume = conditions.bullishVolumeBuffer[zIDX]; + double cBullishVolume = conditions.bullishVolumeBuffer[cIDX]; + double pBullishVolume = conditions.bullishVolumeBuffer[pIDX]; + double p2BullishVolume = conditions.bullishVolumeBuffer[p2IDX]; + double p3BullishVolume = conditions.bullishVolumeBuffer[p3IDX]; + + // + double zBearishVolume = conditions.bearishVolumeBuffer[zIDX]; + double cBearishVolume = conditions.bearishVolumeBuffer[cIDX]; + double pBearishVolume = conditions.bearishVolumeBuffer[pIDX]; + double p2BearishVolume = conditions.bearishVolumeBuffer[p2IDX]; + double p3BearishVolume = conditions.bearishVolumeBuffer[p3IDX]; + + // + double zBullishVolumeSignal = conditions.bullishVolumeSignalBuffer[zIDX]; + double cBullishVolumeSignal = conditions.bullishVolumeSignalBuffer[cIDX]; + double pBullishVolumeSignal = conditions.bullishVolumeSignalBuffer[pIDX]; + double p2BullishVolumeSignal = conditions.bullishVolumeSignalBuffer[p2IDX]; + double p3BullishVolumeSignal = conditions.bullishVolumeSignalBuffer[p3IDX]; + + // + double zBearishVolumeSignal = conditions.bearishVolumeSignalBuffer[zIDX]; + double cBearishVolumeSignal = conditions.bearishVolumeSignalBuffer[cIDX]; + double pBearishVolumeSignal = conditions.bearishVolumeSignalBuffer[pIDX]; + double p2BearishVolumeSignal = conditions.bearishVolumeSignalBuffer[p2IDX]; + double p3BearishVolumeSignal = conditions.bearishVolumeSignalBuffer[p3IDX]; + + // + // ATR Band ... + + // + bool isATRUp = + cATRUpper > pATRUpper && + cATRLower > pATRLower; + bool isATRDown = + cATRUpper < pATRUpper && + cATRLower < pATRLower; + + // + bool isClosedOverATRUpper = + conditions.bars[cIDX].close > cATRUpper; + bool isClosedUnderATRLower = + conditions.bars[cIDX].close < cATRLower; + + // + // SAR ... + + // + bool isSarBullish = cSarState > 0; + bool isSarBearish = cSarState < 0; + + // + bool isSarSwitchedToBullish = + cSarState > 0 && + pSarState <= 0; + bool isSarSwitchedToBearish = + cSarState < 0 && + pSarState >= 0; + + // + // ADX ... + + // + bool isADXBiggerLast = + cADX > pADX; + bool isADXLesserLast = + cADX < pADX; + + // + bool isPADXBiggerLast = + pADX > p2ADX; + bool isPADXLesserLast = + pADX < p2ADX; + + // + bool isADXOverThreshold = + cADX > _adxThreshold; + bool isADXUnderThreshold = + cADX < _adxThreshold; + + // + bool isPADXOverThreshold = + pADX > _adxThreshold; + bool isPADXUnderThreshold = + pADX < _adxThreshold; + + // + bool isDXPBiggerThanDXN = + cADXP > cADXN; + bool isDXNBiggerThanDXP = + cADXN > cADXP; + + // + bool isPDXPBiggerThanDXN = + pADXP > pADXN; + bool isPDXNBiggerThanDXP = + pADXN > pADXP; + + // + bool isADXBullish = + isADXBiggerLast && + isADXOverThreshold; + bool isADXBearish = + isADXLesserLast && + isADXUnderThreshold; + + // + bool isPADXBullish = + isPADXBiggerLast && + isPADXOverThreshold; + bool isPADXBearish = + isPADXLesserLast && + isPADXUnderThreshold; + + // + bool isADXSwitchedToBullish = + isADXBullish && + !isPADXBullish; + bool isADXSwitchedToBearish = + isADXBearish && + !isPADXBearish; + + // + // RSI ... + + // + bool isRSIBullish = + cRSI > pRSI; + bool isRSIBearish = + cRSI < pRSI; + + // + bool isRSISwitchedToBullish = + cRSI > pRSI && + pRSI <= cRSI; + bool isRSISwitchedToBearish = + cRSI < pRSI && + pRSI >= cRSI; + + // + bool isRSIOB = + cRSI > _rsiOBLevel; + bool isRSIOS = + cRSI < _rsiOSLevel; + + // + bool isRSICrossedOverOB = + cRSI > _rsiOBLevel && + pRSI <= _rsiOBLevel; + bool isRSICrossedOverOS = + cRSI > _rsiOSLevel && + pRSI <= _rsiOSLevel; + + // + bool isRSICrossedUnderOB = + cRSI < _rsiOBLevel && + pRSI >= _rsiOBLevel; + bool isRSICrossedUnderOS = + cRSI < _rsiOSLevel && + pRSI >= _rsiOSLevel; + + // + // DELTA ... + + // + bool isDeltaUp = + cDelta > pDelta; + bool isDeltaDown = + cDelta < pDelta; + + // + bool isDeltaBullish = + cDelta > pDelta && + cDeltaSignal > cDelta && + cDeltaSignal > pDeltaSignal; + bool isPDeltaBullish = + pDelta > p2Delta && + pDeltaSignal > pDelta && + pDeltaSignal > p2DeltaSignal; + + // + bool isDeltaBearish = + cDelta < pDelta && + cDeltaSignal < cDelta && + cDeltaSignal < pDeltaSignal; + bool isPDeltaBearish = + pDelta < p2Delta && + pDeltaSignal < pDelta && + pDeltaSignal < p2DeltaSignal; + + // + bool isDeltaSwitchedToBullish = + isDeltaBullish && + !isPDeltaBullish; + bool isDeltaSwitchedToBearish = + isDeltaBearish && + !isPDeltaBearish; + + // + // VOLUME ... + + // + bool isVolumeBullish = + cBullishVolume > pBullishVolume && + cBullishVolume > cBearishVolume; + bool isVolumeBearish = + cBearishVolume > pBearishVolume && + cBearishVolume > cBullishVolume; + + // + bool isVolumeSwitchedToBullish = + isVolumeBullish && + cBullishVolumeSignal > cBearishVolumeSignal && + pBullishVolumeSignal <= pBearishVolumeSignal; + bool isVolumeSwitchedToBearish = + isVolumeBearish && + cBearishVolumeSignal > cBullishVolumeSignal && + pBearishVolumeSignal <= pBullishVolumeSignal; + + // + // SIGNAL Bar ... + + // + bool isSBarBullish = + cSBarO < cSBarC; + bool isSBarBearish = + cSBarO > cSBarC; + + // + bool isSBarSwitchedToBullish = + cSBarO < cSBarC && + pSBarO >= pSBarC; + bool isSBarSwitchedToBearish = + cSBarO > cSBarC && + pSBarO <= pSBarC; + + // + // XHK Signal Bar ... + + // + bool isHKSBarBullish = + cHKSBarO < cHKSBarC; + bool isHKSBarBearish = + cHKSBarO > cHKSBarC; + + // + bool isHKSBarSwitchedToBullish = + cHKSBarO < cHKSBarC && + pHKSBarO >= pHKSBarC; + bool isHKSBarSwitchedToBearish = + cHKSBarO > cHKSBarC && + pHKSBarO <= pHKSBarC; + + // + // TREND ... + + // + bool isTrendUp = + cTrend > pTrend; + bool isTrendDown = + cTrend < pTrend; + + // + bool isTrendBullish = + cTrendState > 0; + bool isTrendBearish = + cTrendState < 0; + + // + bool isTrendSwitchedToBullish = + isTrendUp && + cTrendState > 0 && + pTrendState <= 0; + bool isTrendSwitchedToBearish = + isTrendDown && + cTrendState < 0 && + pTrendState >= 0; + + // + // PEAK ... + + // + bool isPeakSameLast = + cPEAK > 0 && + cPEAK == pPEAK; + bool isPeakOverLast = + pPEAK > 0 && + cPEAK > pPEAK; + bool isPeakUnderLast = + cPEAK > 0 && + cPEAK < pPEAK; + + // + // VALE ... + + // + bool isValeSameLast = + cVALE > 0 && + cVALE == pVALE; + bool isValeOverLast = + pVALE > 0 && + cVALE > pVALE; + bool isValeUnderLast = + cVALE > 0 && + cVALE < pVALE; + + // + // Attached ... + + // + conditions.isATRUp = isATRUp; + conditions.isRSIOB = isRSIOB; + conditions.isRSIOS = isRSIOS; + conditions.isDeltaUp = isDeltaUp; + conditions.isATRDown = isATRDown; + conditions.isTrendUp = isTrendUp; + conditions.rsiOBLevel = _rsiOBLevel; + conditions.rsiOSLevel = _rsiOSLevel; + conditions.isDeltaDown = isDeltaDown; + conditions.isTrendDown = isTrendDown; + conditions.adxThreshold = _adxThreshold; + conditions.isSarBullish = isSarBullish; + conditions.isSarBearish = isSarBearish; + conditions.isADXBullish = isADXBullish; + conditions.isADXBearish = isADXBearish; + conditions.isRSIBullish = isRSIBullish; + conditions.isRSIBearish = isRSIBearish; + conditions.isSBarBullish = isSBarBullish; + conditions.isSBarBearish = isSBarBearish; + conditions.isDeltaBullish = isDeltaBullish; + conditions.isDeltaBearish = isDeltaBearish; + conditions.isTrendBullish = isTrendBullish; + conditions.isTrendBearish = isTrendBearish; + conditions.isPeakSameLast = isPeakSameLast; + conditions.isPeakOverLast = isPeakOverLast; + conditions.isValeSameLast = isValeSameLast; + conditions.isValeOverLast = isValeOverLast; + conditions.isVolumeBullish = isVolumeBullish; + conditions.isVolumeBearish = isVolumeBearish; + conditions.isADXBiggerLast = isADXBiggerLast; + conditions.isADXLesserLast = isADXLesserLast; + conditions.isHKSBarBullish = isHKSBarBullish; + conditions.isHKSBarBearish = isHKSBarBearish; + conditions.isPeakUnderLast = isPeakUnderLast; + conditions.isValeUnderLast = isValeUnderLast; + conditions.isRSICrossedOverOB = isRSICrossedOverOB; + conditions.isRSICrossedOverOS = isRSICrossedOverOS; + conditions.isADXOverThreshold = isADXOverThreshold; + conditions.isDXPBiggerThanDXN = isDXPBiggerThanDXN; + conditions.isDXNBiggerThanDXP = isDXNBiggerThanDXP; + conditions.isRSICrossedUnderOB = isRSICrossedUnderOB; + conditions.isRSICrossedUnderOS = isRSICrossedUnderOS; + conditions.isADXUnderThreshold = isADXUnderThreshold; + conditions.isClosedOverATRUpper = isClosedOverATRUpper; + conditions.isClosedUnderATRLower = isClosedUnderATRLower; + conditions.isSarSwitchedToBullish = isSarSwitchedToBullish; + conditions.isSarSwitchedToBearish = isSarSwitchedToBearish; + conditions.isADXSwitchedToBullish = isADXSwitchedToBullish; + conditions.isADXSwitchedToBearish = isADXSwitchedToBearish; + conditions.isRSISwitchedToBullish = isRSISwitchedToBullish; + conditions.isRSISwitchedToBearish = isRSISwitchedToBearish; + conditions.isSBarSwitchedToBullish = isSBarSwitchedToBullish; + conditions.isSBarSwitchedToBearish = isSBarSwitchedToBearish; + conditions.isTrendSwitchedToBullish = isTrendSwitchedToBullish; + conditions.isTrendSwitchedToBearish = isTrendSwitchedToBearish; + conditions.isDeltaSwitchedToBullish = isDeltaSwitchedToBullish; + conditions.isDeltaSwitchedToBearish = isDeltaSwitchedToBearish; + conditions.isVolumeSwitchedToBullish = isVolumeSwitchedToBullish; + conditions.isVolumeSwitchedToBearish = isVolumeSwitchedToBearish; + conditions.isHKSBarSwitchedToBullish = isHKSBarSwitchedToBullish; + conditions.isHKSBarSwitchedToBearish = isHKSBarSwitchedToBearish; + + // + // Cleanup Resources ... + + // + Cleanup(); + + // + return result; + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + X121XCatbInputs mInputs; // Inputs ... + + // + // Buffers ... + // Define in Public ... + + // + void Calculate( + int barIndex = 0, + int maxRequiredBars = 100 // + ) + { + // + // Buffers ... + if (barIndex < 0) + { + barIndex = 0; + } + + // + CopyBuffer( + mHandler, + X121_XCATB_SAR_LINE, + barIndex, + maxRequiredBars, + sarBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_SAR_STATE_LINE, + barIndex, + maxRequiredBars, + sarStateBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_PEAK_LINE, + barIndex, + maxRequiredBars, + peakBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_VALE_LINE, + barIndex, + maxRequiredBars, + valeBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_PEAK_GOLDEN_LINE, + barIndex, + maxRequiredBars, + peakGoldenBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_VALE_GOLDEN_LINE, + barIndex, + maxRequiredBars, + valeGoldenBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_ATR_BAND_UPPER_LINE, + barIndex, + maxRequiredBars, + atrUpperBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_ATR_BAND_LOWER_LINE, + barIndex, + maxRequiredBars, + atrLowerBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_TREND_LINE, + barIndex, + maxRequiredBars, + trendBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_TREND_STATE_LINE, + barIndex, + maxRequiredBars, + trendStateBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_SBAR_O_LINE, + barIndex, + maxRequiredBars, + sBarOpenBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_SBAR_C_LINE, + barIndex, + maxRequiredBars, + sBarCloseBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_HK_SBAR_O_LINE, + barIndex, + maxRequiredBars, + hkSBarOpenBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_HK_SBAR_C_LINE, + barIndex, + maxRequiredBars, + hkSBarCloseBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_S_HH_LINE, + barIndex, + maxRequiredBars, + sHHBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_S_LL_LINE, + barIndex, + maxRequiredBars, + sLLBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_M_HH_LINE, + barIndex, + maxRequiredBars, + mHHBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_M_LL_LINE, + barIndex, + maxRequiredBars, + mLLBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_L_HH_LINE, + barIndex, + maxRequiredBars, + lHHBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_L_LL_LINE, + barIndex, + maxRequiredBars, + lLLBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_H_HH_LINE, + barIndex, + maxRequiredBars, + hHHBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_H_LL_LINE, + barIndex, + maxRequiredBars, + hLLBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_RSI_LINE, + barIndex, + maxRequiredBars, + rsiBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_ADX_LINE, + barIndex, + maxRequiredBars, + adxBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_ADXP_LINE, + barIndex, + maxRequiredBars, + adxpBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_ADXN_LINE, + barIndex, + maxRequiredBars, + adxnBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_DELTA_LINE, + barIndex, + maxRequiredBars, + deltaBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_DELTA_SIGNAL_LINE, + barIndex, + maxRequiredBars, + deltaSignalBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_VOLUME_BULLISH_LINE, + barIndex, + maxRequiredBars, + bullishVolumeBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_VOLUME_BEARISH_LINE, + barIndex, + maxRequiredBars, + bearishVolumeBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_VOLUME_VOLUME_BULLISH_SIGNAL_LINE, + barIndex, + maxRequiredBars, + bullishVolumeSignalBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_VOLUME_VOLUME_BEARISH_SIGNAL_LINE, + barIndex, + maxRequiredBars, + bearishVolumeSignalBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_ATR_LINE, + barIndex, + maxRequiredBars, + atrBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_HK_BAR_O_LINE, + barIndex, + maxRequiredBars, + hkOpenBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_HK_BAR_H_LINE, + barIndex, + maxRequiredBars, + hkHighBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_HK_BAR_L_LINE, + barIndex, + maxRequiredBars, + hkLowBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_HK_BAR_C_LINE, + barIndex, + maxRequiredBars, + hkCloseBuffer // + ); + } + + // + void Cleanup( + int maxAllowed = 100 // + ) + { + // + CleanupArray( + sarBuffer, + maxAllowed // + ); + + // + CleanupArray( + sarStateBuffer, + maxAllowed // + ); + + // + CleanupArray( + peakBuffer, + maxAllowed // + ); + + // + CleanupArray( + valeBuffer, + maxAllowed // + ); + + // + CleanupArray( + peakGoldenBuffer, + maxAllowed // + ); + + // + CleanupArray( + valeGoldenBuffer, + maxAllowed // + ); + + // + CleanupArray( + atrUpperBuffer, + maxAllowed // + ); + + // + CleanupArray( + atrLowerBuffer, + maxAllowed // + ); + + // + CleanupArray( + trendBuffer, + maxAllowed // + ); + + // + CleanupArray( + trendStateBuffer, + maxAllowed // + ); + + // + CleanupArray( + sBarOpenBuffer, + maxAllowed // + ); + + // + CleanupArray( + sBarCloseBuffer, + maxAllowed // + ); + + // + CleanupArray( + hkSBarOpenBuffer, + maxAllowed // + ); + + // + CleanupArray( + hkSBarCloseBuffer, + maxAllowed // + ); + + // + CleanupArray( + sHHBuffer, + maxAllowed // + ); + + // + CleanupArray( + sLLBuffer, + maxAllowed // + ); + + // + CleanupArray( + mHHBuffer, + maxAllowed // + ); + + // + CleanupArray( + mLLBuffer, + maxAllowed // + ); + + // + CleanupArray( + lHHBuffer, + maxAllowed // + ); + + // + CleanupArray( + lLLBuffer, + maxAllowed // + ); + + // + CleanupArray( + hHHBuffer, + maxAllowed // + ); + + // + CleanupArray( + hLLBuffer, + maxAllowed // + ); + + // + CleanupArray( + rsiBuffer, + maxAllowed // + ); + + // + CleanupArray( + adxBuffer, + maxAllowed // + ); + + // + CleanupArray( + adxpBuffer, + maxAllowed // + ); + + // + CleanupArray( + adxnBuffer, + maxAllowed // + ); + + // + CleanupArray( + deltaBuffer, + maxAllowed // + ); + + // + CleanupArray( + deltaSignalBuffer, + maxAllowed // + ); + + // + CleanupArray( + bullishVolumeBuffer, + maxAllowed // + ); + + // + CleanupArray( + bearishVolumeBuffer, + maxAllowed // + ); + + // + CleanupArray( + bullishVolumeSignalBuffer, + maxAllowed // + ); + + // + CleanupArray( + bearishVolumeSignalBuffer, + maxAllowed // + ); + + // + CleanupArray( + atrBuffer, + maxAllowed // + ); + + // + CleanupArray( + hkOpenBuffer, + maxAllowed // + ); + + // + CleanupArray( + hkHighBuffer, + maxAllowed // + ); + + // + CleanupArray( + hkLowBuffer, + maxAllowed // + ); + + // + CleanupArray( + hkCloseBuffer, + maxAllowed // + ); + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14040316/Documents/Helpers/x-saherelm.x121.xcc.helper.mq5 b/BKPS/14040316/Documents/Helpers/x-saherelm.x121.xcc.helper.mq5 new file mode 100644 index 0000000..6771036 --- /dev/null +++ b/BKPS/14040316/Documents/Helpers/x-saherelm.x121.xcc.helper.mq5 @@ -0,0 +1,259 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCX121XCCHelper +// 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.x-helper.class.mq5" + +// +// Definitions ... + +// +// Input Models ... +struct X121XCCInputs +{ + // + // Props ... + + // + // Chart Style ... + ENUM_CHART_MODE mode; // Mode + color upColor; // Up Color + color downColor; // Down Color + color lineColor; // Line mode and Doji candlestick Color + color bearishColor; // Bullish Color + color bullishColor; // Bearish Color + color volumesColor; // Volumes Color + + // + // Presentation ... + bool showCandles; // Show Candles + + // + // Constructor(s) ... + X121XCCInputs() + { + // + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + mode = CHART_CANDLES; + + // + upColor = CLR_NONE; + downColor = CLR_NONE; + lineColor = CLR_NONE; + bearishColor = CLR_NONE; + bullishColor = CLR_NONE; + volumesColor = CLR_NONE; + + // + showCandles = false; + + // + ZeroMemory(this); + } + + // + // Default ... + void Default() + { + // + mode = CHART_CANDLES; + + // + upColor = clrLime; + downColor = clrRed; + lineColor = clrLime; + bearishColor = clrRed; + bullishColor = clrLime; + volumesColor = clrGreen; + // + showCandles = true; + } + + // + // Hide all Visible Buffers ... + void Hide() + { + showCandles = 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 XCX121XCCHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructors ... + XCX121XCCHelper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCX121XCCHelper() + { + mInputs.Clean(); + } + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + X121XCCInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.xcc", + // + // Inputs ... + // + // Chart Style ... + "", + mInputs.mode, // Mode + mInputs.upColor, // Up Color + mInputs.downColor, // Down Color + mInputs.lineColor, // Line mode and Doji candlestick Color + mInputs.bullishColor, // Bearish Color + mInputs.bearishColor, // Bullish Color + mInputs.volumesColor, // Volumes Color + // + // Presentation ... + "", + mInputs.showCandles // Show Candles + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + X121XCCInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + X121XCCInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + X121XCCInputs mInputs; // Inputs ... +}; + +// +// Tools ... \ No newline at end of file diff --git a/BKPS/14040316/Documents/Helpers/x-saherelm.x121.xct.helper.mq5 b/BKPS/14040316/Documents/Helpers/x-saherelm.x121.xct.helper.mq5 new file mode 100644 index 0000000..6c5284e --- /dev/null +++ b/BKPS/14040316/Documents/Helpers/x-saherelm.x121.xct.helper.mq5 @@ -0,0 +1,241 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCX121XCTHelper +// 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.x-helper.class.mq5" + +// +// Definitions ... + +// +// Input Models ... +struct X121XCTInputs +{ + // + // Props ... + + // + string font; // Font + int fontSize; // Font Size; + color clr; // Text Color + ENUM_BASE_CORNER corner; // Text Position + + // + // Presentation ... + bool showCandleTime; // Show Candle Time + + // + // Constructor(s) ... + X121XCTInputs() + { + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + font = NULL; + fontSize = 15; + clr = CLR_NONE; + corner = CORNER_RIGHT_LOWER; + + // + // Presentation ... + showCandleTime = false; + + // + ZeroMemory(this); + } + + // + // Default ... + void Default() + { + // + font = "Arial"; + fontSize = 15; + clr = clrYellow; + corner = CORNER_RIGHT_LOWER; + + // + // Presentation ... + showCandleTime = true; + } + + // + // Hide all Visible Buffers ... + void Hide() + { + 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 XCX121XCTHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructors ... + XCX121XCTHelper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCX121XCTHelper() + { + mInputs.Clean(); + } + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + X121XCTInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.xct", + // + // Inputs ... + mInputs.fontSize, // Font Size ... + mInputs.font, // Font ... + 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 ... + + // + X121XCTInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + X121XCTInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + X121XCTInputs mInputs; // Inputs ... +}; + +// +// Tools ... \ No newline at end of file diff --git a/BKPS/14040316/Documents/Helpers/x-saherelm.x121.xoscs.helper.mq5 b/BKPS/14040316/Documents/Helpers/x-saherelm.x121.xoscs.helper.mq5 new file mode 100644 index 0000000..720c8d3 --- /dev/null +++ b/BKPS/14040316/Documents/Helpers/x-saherelm.x121.xoscs.helper.mq5 @@ -0,0 +1,3498 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XCX121XOCSHelper +// 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.x-helper.class.mq5" + +// +// Buffers ... +enum ENUM_X121_XOSCS_BUFFERS +{ + // + // https://www.mql5.com/en/articles/11467 ... + X121_XOSCS_XAC_LINE = 0, + // https://www.mql5.com/en/articles/10993 ... + X121_XOSCS_XAD_LINE = 1, + // https://www.mql5.com/en/articles/10715 ... + X121_XOSCS_XADX_LINE = 2, + X121_XOSCS_XADX_P_LINE = 3, + X121_XOSCS_XADX_N_LINE = 4, + // https://www.mql5.com/en/articles/10748 ... + X121_XOSCS_XATR_LINE = 5, + // https://www.mql5.com/en/articles/10592 ... + X121_XOSCS_XCCI_LINE = 6, + // https://www.mql5.com/en/articles/10528 ... + X121_XOSCS_XRSI_LINE = 7, + // https://www.mql5.com/en/articles/11037 ... + X121_XOSCS_XMFI_LINE = 8, + // https://www.mql5.com/en/articles/11425 ... + X121_XOSCS_XRVI_LINE = 9, + X121_XOSCS_XRVI_S_LINE = 10, + // https://www.mql5.com/en/articles/10674 ... + X121_XOSCS_XMACD_LINE = 11, + X121_XOSCS_XMACD_S_LINE = 12, + // https://www.mql5.com/en/articles/10547 ... + X121_XOSCS_XMOMENTUM_LINE = 13, + // https://www.mql5.com/en/articles/10692 .. + X121_XOSCS_XSTOCHASTIC_LINE = 14, + X121_XOSCS_XSTOCHASTIC_S_LINE = 15, +}; + +// +// Inputs ... +struct X121XOCSInputs +{ + // + // Props ... + + // + // Accumulation/Distribution ... + ENUM_APPLIED_VOLUME adAppliedTo; // Applied To + + // + // AC ... + int acBullishLevel; // Bullish Level + int acBearishLevel; // Bearish Level + + // + // ADX ... + int adxLength; // Length + int adxThreshold; // Big Movement Threshold + + // + // ATR ... + int atrLength; // Length + + // + // CCI ... + int cciLength; // Length + ENUM_APPLIED_PRICE cciAppliedTo; // Applied To + int cciOBLevel; // Over Bought Level + int cciOSLevel; // Over Sold Level + int cciReversalLevel; // Reversal Level + + // + // RSI ... + int rsiLength; // Length + ENUM_APPLIED_PRICE rsiAppliedTo; // Applied To + int rsiOBLevel; // Over Bought Level + int rsiOSLevel; // Over Sold Level + int rsiReversalLevel; // Reversal Level + + // + // MFI ... + int mfiLength; // Length + ENUM_APPLIED_VOLUME mfiAppliedTo; // Applied To + int mfiOBLevel; // Over Bought Level + int mfiOSLevel; // Over Sold Level + int mfiReversalLevel; // Reversal Level + + // + // RVI ... + int rviLength; // Length + int rviBullishLevel; // Bullish Level + int rviBearishLevel; // Bearish Level + + // + // MACD ... + int macdFastLength; // Fast EMA Length + int macdSlowLength; // Slow EMA Length + int macdSignalLength; // Signal Length + ENUM_APPLIED_PRICE macdAppliedTo; // Applied To + int macdBullishLevel; // Bullish Level + int macdBearishLevel; // Bearish Level + + // + // Momentum ... + int momentumLength; // Length + ENUM_APPLIED_PRICE momentumAppliedTo; // Applied To + int momentumBullishLevel; // Bullish Level + int momentumBearishLevel; // Bearish Level + + // + // Stochastic ... + int stochasticKLength; // K Length (Bars for Calculation) + int stochasticDLength; // D Length (first Smoothing) + int stochasticSmoothingLength; // Smoothing Length + ENUM_MA_METHOD stochasticSmoothingMethod; // Smoothing Method + ENUM_STO_PRICE stochasticAppliedTo; // Applied To + int stochasticOBLevel; // Over Bought Level + int stochasticOSLevel; // Over Sold Level + int stochasticReversalLevel; // Reversal Level + + // + // Presentation ... + int startCalculationForLastBars; // Calculate Last n Bars + + // + // Constructor(s) ... + X121XOCSInputs() + { + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + // Accumulation/Distribution ... + adAppliedTo = VOLUME_TICK; // Applied To + + // + // AC ... + acBullishLevel = 0; + acBearishLevel = 0; + + // + // ADX ... + adxLength = 0; // Length + adxThreshold = 0; // Big Movement Threshold + + // + // ATR ... + atrLength = 0; // Length + + // + // CCI ... + cciLength = 0; // Length + cciAppliedTo = PRICE_TYPICAL; // Applied To + cciOBLevel = 100; // Over Bought Level + cciOSLevel = -100; // Over Sold Level + cciReversalLevel = 0; // Reversal Level + + // + // RSI ... + rsiLength = 0; // Length + rsiAppliedTo = PRICE_CLOSE; // Applied To + rsiOBLevel = 0; // Over Bought Level + rsiOSLevel = 0; // Over Sold Level + rsiReversalLevel = 0; // Reversal Level + + // + // MFI ... + mfiLength = 0; // Length + mfiAppliedTo = VOLUME_TICK; // Applied To + mfiOBLevel = 0; // Over Bought Level + mfiOSLevel = 0; // Over Sold Level + mfiReversalLevel = 0; // Reversal Level + + // + // RVI ... + rviLength = 0; // Length + rviBullishLevel = 0; // Bullish Level + rviBearishLevel = 0; // Bearish Level + + // + // MACD ... + macdFastLength = 0; // Fast EMA Length + macdSlowLength = 0; // Slow EMA Length + macdSignalLength = 0; // Signal Length + macdAppliedTo = PRICE_CLOSE; // Applied To + macdBullishLevel = 0; // Bullish Level + macdBearishLevel = 0; // Bearish Level + + // + // Momentum ... + momentumLength = 0; // Length + momentumAppliedTo = PRICE_CLOSE; // Applied To + momentumBullishLevel = 0; // Bullish Level + momentumBearishLevel = 0; // Bearish Level + + // + // Stochastic ... + stochasticKLength = 0; // K Length (Bars for Calculation) + stochasticDLength = 0; // D Length (first Smoothing) + stochasticSmoothingLength = 0; // Smoothing Length + stochasticSmoothingMethod = MODE_SMA; // Smoothing Method + stochasticAppliedTo = STO_LOWHIGH; // Applied To + stochasticOBLevel = 0; // Over Bought Level + stochasticOSLevel = 0; // Over Sold Level + stochasticReversalLevel = 0; // Reversal Level + + // + // Presentation ... + startCalculationForLastBars = 0; // Calculate Last n Bars + + // + ZeroMemory(this); + } + + // + // Default ... + void Default() + { + // + // Accumulation/Distribution ... + adAppliedTo = VOLUME_TICK; // Applied To + + // + // AC ... + acBullishLevel = 0; + acBearishLevel = 0; + + // + // ADX ... + adxLength = 14; // Length + adxThreshold = 25; // Big Movement Threshold + + // + // ATR ... + atrLength = 14; // Length + + // + // CCI ... + cciLength = 14; // Length + cciAppliedTo = PRICE_TYPICAL; // Applied To + cciOBLevel = 100; // Over Bought Level + cciOSLevel = -100; // Over Sold Level + cciReversalLevel = 0; // Reversal Level + + // + // RSI ... + rsiLength = 14; // Length + rsiAppliedTo = PRICE_CLOSE; // Applied To + rsiOBLevel = 70; // Over Bought Level + rsiOSLevel = 30; // Over Sold Level + rsiReversalLevel = 50; // Reversal Level + + // + // MFI ... + mfiLength = 14; // Length + mfiAppliedTo = VOLUME_TICK; // Applied To + mfiOBLevel = 80; // Over Bought Level + mfiOSLevel = 20; // Over Sold Level + mfiReversalLevel = 50; // Reversal Level + + // + // RVI ... + rviLength = 14; // Length + rviBullishLevel = 0; // Bullish Level + rviBearishLevel = 0; // Bearish Level + + // + // MACD ... + macdFastLength = 12; // Fast EMA Length + macdSlowLength = 26; // Slow EMA Length + macdSignalLength = 9; // Signal Length + macdAppliedTo = PRICE_CLOSE; // Applied To + macdBullishLevel = 0; // Bullish Level + macdBearishLevel = 0; // Bearish Level + + // + // Momentum ... + momentumLength = 14; // Length + momentumAppliedTo = PRICE_CLOSE; // Applied To + momentumBullishLevel = 100; // Bullish Level + momentumBearishLevel = 100; // Bearish Level + + // + // Stochastic ... + stochasticKLength = 5; // K Length (Bars for Calculation) + stochasticDLength = 3; // D Length (first Smoothing) + stochasticSmoothingLength = 3; // Smoothing Length + stochasticSmoothingMethod = MODE_SMA; // Smoothing Method + stochasticAppliedTo = STO_LOWHIGH; // Applied To + stochasticOBLevel = 80; // Over Bought Level + stochasticOSLevel = 20; // Over Sold Level + stochasticReversalLevel = 50; // Reversal Level + + // + // Presentation ... + startCalculationForLastBars = 1000; // Calculate Last n Bars + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + adxLength > 0 && + adxThreshold > 0 && + // + atrLength > 0 && + // + cciLength > 0 && + cciOBLevel > 0 && + cciOSLevel != 0 && + cciOBLevel > cciReversalLevel && + cciOSLevel < cciReversalLevel && + // + rsiLength > 0 && + rsiOBLevel > 0 && + rsiOSLevel > 0 && + rsiReversalLevel > 0 && + rsiOBLevel > rsiReversalLevel && + rsiOSLevel < rsiReversalLevel && + // + mfiLength > 0 && + mfiOBLevel > 0 && + mfiOSLevel > 0 && + mfiReversalLevel > 0 && + mfiOBLevel > mfiReversalLevel && + mfiOSLevel < mfiReversalLevel && + // + rviLength > 0 && + // + macdFastLength > 0 && + macdSlowLength > 0 && + macdSignalLength > 0 && + macdFastLength < macdSlowLength && + // + stochasticKLength > 0 && + stochasticDLength > 0 && + stochasticSmoothingLength > 0 && + stochasticOBLevel > 0 && + stochasticOSLevel > 0 && + stochasticReversalLevel > 0 && + stochasticOBLevel > stochasticReversalLevel && + stochasticOSLevel < stochasticReversalLevel && + // + momentumLength > 0 + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(adxLength, atrLength); + result = MathMax(result, cciLength); + result = MathMax(result, rsiLength); + result = MathMax(result, mfiLength); + result = MathMax(result, rviLength); + result = MathMax(result, momentumLength); + result = MathMax(result, macdFastLength); + result = MathMax(result, macdSlowLength); + result = MathMax(result, macdSignalLength); + result = MathMax(result, stochasticKLength); + result = MathMax(result, stochasticDLength); + result = MathMax(result, stochasticSmoothingLength); + + // + return result; + } +}; + +// +// Conditions ... +struct X121XOCSConditions +{ + // + // Common ... + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + // Buffers ... + double acBuffer[]; + double adBuffer[]; + double atrBuffer[]; + double cciBuffer[]; + double rsiBuffer[]; + double mfiBuffer[]; + double rviBuffer[]; + double adxBuffer[]; + double adxpBuffer[]; + double adxnBuffer[]; + double macdBuffer[]; + double momentumBuffer[]; + double rviSignalBuffer[]; + double macdSignalBuffer[]; + double stochasticBuffer[]; + double stochasticSignalBuffer[]; + + // + // Values ... + + // + double adxThreshold; // Big Movement Threshold + double cciOBLevel; // Over Bought Level + double cciOSLevel; // Over Sold Level + double cciReversalLevel; // Reversal Level + double rsiOBLevel; // Over Bought Level + double rsiOSLevel; // Over Sold Level + double rsiReversalLevel; // Reversal Level + double mfiOBLevel; // Over Bought Level + double mfiOSLevel; // Over Sold Level + double mfiReversalLevel; // Reversal Level + double rviBullishLevel; // Bullish Level + double rviBearishLevel; // Bearish Level + double macdBullishLevel; // Bullish Level + double macdBearishLevel; // Bearish Level + double momentumBullishLevel; // Bullish Level + double momentumBearishLevel; // Bearish Level + double stochasticOBLevel; // Over Bought Level + double stochasticOSLevel; // Over Sold Level + double stochasticReversalLevel; // Reversal Level + + // + // Conditions ... + + // + // AC ... + + // + bool isACBullish; + bool isACBearish; + + // + bool isACSwitchedToBullish; + bool isACSwitchedToBearish; + + // + bool isACOverMax; + bool isACUnderMin; + + // + // AD ... + + // + bool isADBiggerLast; + bool isADLesserLast; + + // + bool isADOverMax; + bool isADUnderMin; + + // + // ADX ... + + // + bool isADXBiggerLast; + bool isADXLesserLast; + + // + bool isADXOverThreshold; + bool isADXUnderThreshold; + + // + bool isDXPBiggerThanDXN; + bool isDXNBiggerThanDXP; + + // + bool isADXBullish; + bool isADXBearish; + + // + bool isADXSwitchedToBullish; + bool isADXSwitchedToBearish; + + // + // ATR ... + + bool isATROverLast; + bool isATRUnderLast; + + // + // CCI ... + + // + bool isCCIBullish; + bool isCCIBearish; + + // + bool isCCISwitchedToBullish; + bool isCCISwitchedToBearish; + + // + bool isCCIOB; + bool isCCIOS; + + // + bool isCCICrossedOverOB; + bool isCCICrossedOverOS; + + // + bool isCCICrossedUnderOB; + bool isCCICrossedUnderOS; + + // + // RSI ... + + // + bool isRSIBullish; + bool isRSIBearish; + + // + bool isRSISwitchedToBullish; + bool isRSISwitchedToBearish; + + // + bool isRSIOB; + bool isRSIOS; + + // + bool isRSICrossedOverOB; + bool isRSICrossedOverOS; + + // + bool isRSICrossedUnderOB; + bool isRSICrossedUnderOS; + + // + // MFI ... + + // + bool isMFIBullish; + bool isMFIBearish; + + // + bool isMFISwitchedToBullish; + bool isMFISwitchedToBearish; + + // + bool isMFIOB; + bool isMFIOS; + + // + bool isMFICrossedOverOB; + bool isMFICrossedOverOS; + + // + bool isMFICrossedUnderOB; + bool isMFICrossedUnderOS; + + // + // RVI ... + + // + bool isRVIBullish; + bool isRVIBearish; + + // + bool isRVISwitchedToBullish; + bool isRVISwitchedToBearish; + + // + bool isRVIOverSignal; + bool isRVIUnderSignal; + + // + bool isRVICrossedOverSignal; + bool isRVICrossedUnderSignal; + + // + // MACD ... + + // + bool isMACDBullish; + bool isMACDBearish; + + // + bool isMACDSwitchedToBullish; + bool isMACDSwitchedToBearish; + + // + bool isMACDOverSignal; + bool isMACDUnderSignal; + + // + bool isMACDCrossedOverSignal; + bool isMACDCrossedUnderSignal; + + // + // MOMENTUM ... + + // + bool isMomentumBullish; + bool isMomentumBearish; + + // + bool isMomentumSwitchedToBullish; + bool isMomentumSwitchedToBearish; + + // + // STOCHASTIC ... + + // + bool isStochasticBullish; + bool isStochasticBearish; + + // + bool isStochasticSwitchedToBullish; + bool isStochasticSwitchedToBearish; + + // + bool isStochasticOverSignal; + bool isStochasticUnderSignal; + + // + bool isStochasticCrossedOverSignal; + bool isStochasticCrossedUnderSignal; + + // + bool isStochasticOB; + bool isStochasticOS; + + // + bool isStochasticCrossedOverOB; + bool isStochasticCrossedOverOS; + + // + bool isStochasticCrossedUnderOB; + bool isStochasticCrossedUnderOS; + + // + // Constructor ... + X121XOCSConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + // Commons ... + symbol = NULL; + period = NULL; + time = NULL; + + // + // Buffers ... + + // + Clean(acBuffer); + Clean(adBuffer); + Clean(atrBuffer); + Clean(cciBuffer); + Clean(rsiBuffer); + Clean(mfiBuffer); + Clean(rviBuffer); + Clean(adxBuffer); + Clean(adxpBuffer); + Clean(adxnBuffer); + Clean(macdBuffer); + Clean(momentumBuffer); + Clean(rviSignalBuffer); + Clean(macdSignalBuffer); + Clean(stochasticBuffer); + Clean(stochasticSignalBuffer); + + // + ArraySetAsSeries(acBuffer, true); + ArraySetAsSeries(adBuffer, true); + ArraySetAsSeries(atrBuffer, true); + ArraySetAsSeries(cciBuffer, true); + ArraySetAsSeries(rsiBuffer, true); + ArraySetAsSeries(mfiBuffer, true); + ArraySetAsSeries(rviBuffer, true); + ArraySetAsSeries(adxBuffer, true); + ArraySetAsSeries(adxpBuffer, true); + ArraySetAsSeries(adxnBuffer, true); + ArraySetAsSeries(macdBuffer, true); + ArraySetAsSeries(momentumBuffer, true); + ArraySetAsSeries(rviSignalBuffer, true); + ArraySetAsSeries(macdSignalBuffer, true); + ArraySetAsSeries(stochasticBuffer, true); + ArraySetAsSeries(stochasticSignalBuffer, true); + + // + // Values ... + + // + adxThreshold = 0.0; + cciOBLevel = 0.0; + cciOSLevel = 0.0; + cciReversalLevel = 0.0; + rsiOBLevel = 0.0; + rsiOSLevel = 0.0; + rsiReversalLevel = 0.0; + mfiOBLevel = 0.0; + mfiOSLevel = 0.0; + mfiReversalLevel = 0.0; + rviBullishLevel = 0.0; + rviBearishLevel = 0.0; + macdBullishLevel = 0.0; + macdBearishLevel = 0.0; + momentumBullishLevel = 0.0; + momentumBearishLevel = 0.0; + stochasticOBLevel = 0.0; + stochasticOSLevel = 0.0; + stochasticReversalLevel = 0.0; + + // + // Conditions ... + + // + // AC ... + + // + isACBullish = false; + isACBearish = false; + isACSwitchedToBullish = false; + isACSwitchedToBearish = false; + isACOverMax = false; + isACUnderMin = false; + + // + // AD ... + + // + isADBiggerLast = false; + isADLesserLast = false; + isADOverMax = false; + isADUnderMin = false; + + // + // ADX ... + + // + isADXBiggerLast = false; + isADXLesserLast = false; + isADXOverThreshold = false; + isADXUnderThreshold = false; + isDXPBiggerThanDXN = false; + isDXNBiggerThanDXP = false; + isADXBullish = false; + isADXBearish = false; + isADXSwitchedToBullish = false; + isADXSwitchedToBearish = false; + + // + // ATR ... + + // + isATROverLast = false; + isATRUnderLast = false; + + // + // CCI ... + + // + isCCIBullish = false; + isCCIBearish = false; + isCCISwitchedToBullish = false; + isCCISwitchedToBearish = false; + isCCIOB = false; + isCCIOS = false; + isCCICrossedOverOB = false; + isCCICrossedOverOS = false; + isCCICrossedUnderOB = false; + isCCICrossedUnderOS = false; + + // + // RSI ... + + // + isRSIBullish = false; + isRSIBearish = false; + isRSISwitchedToBullish = false; + isRSISwitchedToBearish = false; + isRSIOB = false; + isRSIOS = false; + isRSICrossedOverOB = false; + isRSICrossedOverOS = false; + isRSICrossedUnderOB = false; + isRSICrossedUnderOS = false; + + // + // MFI ... + + // + isMFIBullish = false; + isMFIBearish = false; + isMFISwitchedToBullish = false; + isMFISwitchedToBearish = false; + isMFIOB = false; + isMFIOS = false; + isMFICrossedOverOB = false; + isMFICrossedOverOS = false; + isMFICrossedUnderOB = false; + isMFICrossedUnderOS = false; + + // + // RVI ... + + // + isRVIBullish = false; + isRVIBearish = false; + isRVISwitchedToBullish = false; + isRVISwitchedToBearish = false; + isRVIOverSignal = false; + isRVIUnderSignal = false; + isRVICrossedOverSignal = false; + isRVICrossedUnderSignal = false; + + // + // MACD ... + + // + isMACDBullish = false; + isMACDBearish = false; + isMACDSwitchedToBullish = false; + isMACDSwitchedToBearish = false; + isMACDOverSignal = false; + isMACDUnderSignal = false; + isMACDCrossedOverSignal = false; + isMACDCrossedUnderSignal = false; + + // + // MOMENTUM ... + + // + isMomentumBullish = false; + isMomentumBearish = false; + isMomentumSwitchedToBullish = false; + isMomentumSwitchedToBearish = false; + + // + // STOCHASTIC ... + + // + isStochasticBullish = false; + isStochasticBearish = false; + isStochasticSwitchedToBullish = false; + isStochasticSwitchedToBearish = false; + isStochasticOverSignal = false; + isStochasticUnderSignal = false; + isStochasticCrossedOverSignal = false; + isStochasticCrossedUnderSignal = false; + isStochasticOB = false; + isStochasticOS = false; + isStochasticCrossedOverOB = false; + isStochasticCrossedOverOS = false; + isStochasticCrossedUnderOB = false; + isStochasticCrossedUnderOS = false; + + // + ZeroMemory(this); + } + + /** + * Generate Conditions Scores ... + * + * @param bullishScore: Double, Directional Scores Reference ... + * @param bearishScore: Double, Directional Scores Reference ... + */ + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + // + bullishScore = 0; + bearishScore = 0; + + // + double score = 1; + double minScore = 0.5; + double highScore = 1.5; + + // + + // + // AC ... + + // + if (isACBullish) + { + bullishScore += minScore; + } + if (isACOverMax) + { + bullishScore += minScore; + } + if (isACSwitchedToBullish) + { + bullishScore += minScore; + } + + // + if (isACBearish) + { + bearishScore += minScore; + } + if (isACUnderMin) + { + bearishScore += minScore; + } + if (isACSwitchedToBearish) + { + bearishScore += minScore; + } + + // + // AD ... + + // + if (isADOverMax) + { + bullishScore += minScore; + } + if (isADBiggerLast) + { + bullishScore += minScore; + } + + // + if (isADUnderMin) + { + bearishScore += minScore; + } + if (isADLesserLast) + { + bearishScore += minScore; + } + + // + // ADX ... + + // + if (isADXBullish) + { + bullishScore += minScore; + } + if (isADXBiggerLast) + { + bullishScore += minScore; + } + if (isADXOverThreshold) + { + bullishScore += minScore; + } + if (isDXPBiggerThanDXN) + { + bullishScore += minScore; + } + if (isADXSwitchedToBullish) + { + bullishScore += minScore; + } + + // + if (isADXBearish) + { + bearishScore += minScore; + } + if (isADXLesserLast) + { + bearishScore += minScore; + } + if (isDXNBiggerThanDXP) + { + bearishScore += minScore; + } + if (isADXUnderThreshold) + { + bearishScore += minScore; + } + if (isADXSwitchedToBearish) + { + bearishScore += minScore; + } + + // + // ATR ... + + // + if (isATROverLast) + { + bullishScore += minScore; + } + + // + if (isATRUnderLast) + { + bearishScore += minScore; + } + + // + // CCI ... + + // + if (isCCIOS) + { + bullishScore += minScore; + } + if (isCCIBullish) + { + bullishScore += minScore; + } + if (isCCICrossedOverOS) + { + bullishScore += minScore; + } + if (isCCICrossedOverOB) + { + bullishScore += minScore; + } + if (isCCISwitchedToBullish) + { + bullishScore += minScore; + } + + // + if (isCCIOB) + { + bearishScore += minScore; + } + if (isCCIBearish) + { + bearishScore += minScore; + } + if (isCCICrossedUnderOS) + { + bearishScore += minScore; + } + if (isCCICrossedUnderOB) + { + bearishScore += minScore; + } + if (isCCISwitchedToBearish) + { + bearishScore += minScore; + } + + // + // RSI ... + + // + if (isRSIOS) + { + bullishScore += minScore; + } + if (isRSIBullish) + { + bullishScore += minScore; + } + if (isRSICrossedOverOB) + { + bullishScore += minScore; + } + if (isRSICrossedOverOS) + { + bullishScore += minScore; + } + if (isRSISwitchedToBullish) + { + bullishScore += minScore; + } + + // + if (isRSIOB) + { + bearishScore += minScore; + } + if (isRSIBearish) + { + bearishScore += minScore; + } + if (isRSICrossedUnderOB) + { + bearishScore += minScore; + } + if (isRSICrossedUnderOS) + { + bearishScore += minScore; + } + if (isRSISwitchedToBearish) + { + bearishScore += minScore; + } + + // + // MFI ... + + // + if (isMFIOS) + { + bullishScore += minScore; + } + if (isMFIBullish) + { + bullishScore += minScore; + } + if (isMFICrossedOverOB) + { + bullishScore += minScore; + } + if (isMFICrossedOverOS) + { + bullishScore += minScore; + } + if (isMFISwitchedToBullish) + { + bullishScore += minScore; + } + + // + if (isMFIOB) + { + bearishScore += minScore; + } + if (isMFIBearish) + { + bearishScore += minScore; + } + if (isMFICrossedUnderOB) + { + bearishScore += minScore; + } + if (isMFICrossedUnderOS) + { + bearishScore += minScore; + } + if (isMFISwitchedToBearish) + { + bearishScore += minScore; + } + + // + // RVI ... + + // + if (isRVIBullish) + { + bullishScore += minScore; + } + if (isRVIOverSignal) + { + bullishScore += minScore; + } + if (isRVISwitchedToBullish) + { + bullishScore += minScore; + } + if (isRVICrossedOverSignal) + { + bullishScore += minScore; + } + + // + if (isRVIBearish) + { + bearishScore += minScore; + } + if (isRVIUnderSignal) + { + bearishScore += minScore; + } + if (isRVISwitchedToBearish) + { + bearishScore += minScore; + } + if (isRVICrossedUnderSignal) + { + bearishScore += minScore; + } + + // + // MACD ... + + // + if (isMACDBullish) + { + bullishScore += minScore; + } + if (isMACDOverSignal) + { + bullishScore += minScore; + } + if (isMACDSwitchedToBullish) + { + bullishScore += minScore; + } + if (isMACDCrossedOverSignal) + { + bullishScore += minScore; + } + + // + if (isMACDBearish) + { + bearishScore += minScore; + } + if (isMACDUnderSignal) + { + bearishScore += minScore; + } + if (isMACDSwitchedToBearish) + { + bearishScore += minScore; + } + if (isMACDCrossedUnderSignal) + { + bearishScore += minScore; + } + + // + // MOMENTUM ... + + // + if (isMomentumBullish) + { + bullishScore += minScore; + } + if (isMomentumSwitchedToBullish) + { + bullishScore += minScore; + } + + // + if (isMomentumBearish) + { + bearishScore += minScore; + } + if (isMomentumSwitchedToBearish) + { + bearishScore += minScore; + } + + // + // STOCHASTIC ... + + // + if (isStochasticOS) + { + bullishScore += minScore; + } + if (isStochasticOverSignal) + { + bullishScore += minScore; + } + if (isStochasticBullish) + { + bullishScore += minScore; + } + if (isStochasticCrossedOverSignal) + { + bullishScore += minScore; + } + if (isStochasticCrossedOverOB) + { + bullishScore += minScore; + } + if (isStochasticCrossedOverOS) + { + bullishScore += minScore; + } + if (isStochasticSwitchedToBullish) + { + bullishScore += minScore; + } + + // + if (isStochasticOB) + { + bearishScore += minScore; + } + if (isStochasticUnderSignal) + { + bearishScore += minScore; + } + if (isStochasticBearish) + { + bearishScore += minScore; + } + if (isStochasticCrossedUnderSignal) + { + bearishScore += minScore; + } + if (isStochasticCrossedUnderOB) + { + bearishScore += minScore; + } + if (isStochasticCrossedUnderOS) + { + bearishScore += minScore; + } + if (isStochasticSwitchedToBearish) + { + bearishScore += minScore; + } + + // + } + + /** + * Generate Summary String for Represent Conditions State ... + * + * @param onlyCommons: Boolean, Just Generate Only Commons Conditions ... + * @param onlyConditions: Boolean, Just Generate Only Conditions ... + * @param includeScores: Boolean, Attach Scores Representations on Result ... + * @param ignoreFalseConditions: Boolean, Ignore False Conditions on Result ... + * @param separator: String, Separate Lines ... + * + * @return ( string ) + */ + string GenerateSummary( + bool onlyCommons = false, + bool onlyConditions = false, + bool includeScores = true, + bool ignoreFalseConditions = true, + string separator = "\n" // + ) + { + // + string result = NULL; + + // + double bullishScore = 0; + double bearishScore = 0; + GenerateScore( + bullishScore, + bearishScore // + ); + + // + string scoresStr = + // + "Scores: " + separator + + "---------------" + separator + + "Bullish: " + ToString(bullishScore) + separator + + "Bearish: " + ToString(bearishScore) + separator + + "" + // + ; + + // + string commonStr = GenerateSpecifiedCommonSummary( + this, + separator, + includeScores // + ); + + // + string conditionsStr = + // + "-----------------------" + separator + + "XOSCS: " + separator + + "-----------------------" + separator + + ToString("isACBullish", isACBullish, ignoreFalseConditions, separator) + + ToString("isACBearish", isACBearish, ignoreFalseConditions, separator) + + ToString("isACSwitchedToBullish", isACSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isACSwitchedToBearish", isACSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isACOverMax", isACOverMax, ignoreFalseConditions, separator) + + ToString("isACUnderMin", isACUnderMin, ignoreFalseConditions, separator) + + ToString("isADBiggerLast", isADBiggerLast, ignoreFalseConditions, separator) + + ToString("isADLesserLast", isADLesserLast, ignoreFalseConditions, separator) + + ToString("isADOverMax", isADOverMax, ignoreFalseConditions, separator) + + ToString("isADUnderMin", isADUnderMin, ignoreFalseConditions, separator) + + ToString("isADXBiggerLast", isADXBiggerLast, ignoreFalseConditions, separator) + + ToString("isADXLesserLast", isADXLesserLast, ignoreFalseConditions, separator) + + ToString("isADXOverThreshold", isADXOverThreshold, ignoreFalseConditions, separator) + + ToString("isADXUnderThreshold", isADXUnderThreshold, ignoreFalseConditions, separator) + + ToString("isDXPBiggerThanDXN", isDXPBiggerThanDXN, ignoreFalseConditions, separator) + + ToString("isDXNBiggerThanDXP", isDXNBiggerThanDXP, ignoreFalseConditions, separator) + + ToString("isADXBullish", isADXBullish, ignoreFalseConditions, separator) + + ToString("isADXBearish", isADXBearish, ignoreFalseConditions, separator) + + ToString("isADXSwitchedToBullish", isADXSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isADXSwitchedToBearish", isADXSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isATROverLast", isATROverLast, ignoreFalseConditions, separator) + + ToString("isATRUnderLast", isATRUnderLast, ignoreFalseConditions, separator) + + ToString("isCCIBullish", isCCIBullish, ignoreFalseConditions, separator) + + ToString("isCCIBearish", isCCIBearish, ignoreFalseConditions, separator) + + ToString("isCCISwitchedToBullish", isCCISwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isCCISwitchedToBearish", isCCISwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isCCIOB", isCCIOB, ignoreFalseConditions, separator) + + ToString("isCCIOS", isCCIOS, ignoreFalseConditions, separator) + + ToString("isCCICrossedOverOB", isCCICrossedOverOB, ignoreFalseConditions, separator) + + ToString("isCCICrossedOverOS", isCCICrossedOverOS, ignoreFalseConditions, separator) + + ToString("isCCICrossedUnderOB", isCCICrossedUnderOB, ignoreFalseConditions, separator) + + ToString("isCCICrossedUnderOS", isCCICrossedUnderOS, ignoreFalseConditions, separator) + + ToString("isRSIBullish", isRSIBullish, ignoreFalseConditions, separator) + + ToString("isRSIBearish", isRSIBearish, ignoreFalseConditions, separator) + + ToString("isRSISwitchedToBullish", isRSISwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isRSISwitchedToBearish", isRSISwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isRSIOB", isRSIOB, ignoreFalseConditions, separator) + + ToString("isRSIOS", isRSIOS, ignoreFalseConditions, separator) + + ToString("isRSICrossedOverOB", isRSICrossedOverOB, ignoreFalseConditions, separator) + + ToString("isRSICrossedOverOS", isRSICrossedOverOS, ignoreFalseConditions, separator) + + ToString("isRSICrossedUnderOB", isRSICrossedUnderOB, ignoreFalseConditions, separator) + + ToString("isRSICrossedUnderOS", isRSICrossedUnderOS, ignoreFalseConditions, separator) + + ToString("isMFIBullish", isMFIBullish, ignoreFalseConditions, separator) + + ToString("isMFIBearish", isMFIBearish, ignoreFalseConditions, separator) + + ToString("isMFISwitchedToBullish", isMFISwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isMFISwitchedToBearish", isMFISwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isMFIOB", isMFIOB, ignoreFalseConditions, separator) + + ToString("isMFIOS", isMFIOS, ignoreFalseConditions, separator) + + ToString("isMFICrossedOverOB", isMFICrossedOverOB, ignoreFalseConditions, separator) + + ToString("isMFICrossedOverOS", isMFICrossedOverOS, ignoreFalseConditions, separator) + + ToString("isMFICrossedUnderOB", isMFICrossedUnderOB, ignoreFalseConditions, separator) + + ToString("isMFICrossedUnderOS", isMFICrossedUnderOS, ignoreFalseConditions, separator) + + ToString("isRVIBullish", isRVIBullish, ignoreFalseConditions, separator) + + ToString("isRVIBearish", isRVIBearish, ignoreFalseConditions, separator) + + ToString("isRVISwitchedToBullish", isRVISwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isRVISwitchedToBearish", isRVISwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isRVIOverSignal", isRVIOverSignal, ignoreFalseConditions, separator) + + ToString("isRVIUnderSignal", isRVIUnderSignal, ignoreFalseConditions, separator) + + ToString("isRVICrossedOverSignal", isRVICrossedOverSignal, ignoreFalseConditions, separator) + + ToString("isRVICrossedUnderSignal", isRVICrossedUnderSignal, ignoreFalseConditions, separator) + + ToString("isMACDBullish", isMACDBullish, ignoreFalseConditions, separator) + + ToString("isMACDBearish", isMACDBearish, ignoreFalseConditions, separator) + + ToString("isMACDSwitchedToBullish", isMACDSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isMACDSwitchedToBearish", isMACDSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isMACDOverSignal", isMACDOverSignal, ignoreFalseConditions, separator) + + ToString("isMACDUnderSignal", isMACDUnderSignal, ignoreFalseConditions, separator) + + ToString("isMACDCrossedOverSignal", isMACDCrossedOverSignal, ignoreFalseConditions, separator) + + ToString("isMACDCrossedUnderSignal", isMACDCrossedUnderSignal, ignoreFalseConditions, separator) + + ToString("isMomentumBullish", isMomentumBullish, ignoreFalseConditions, separator) + + ToString("isMomentumBearish", isMomentumBearish, ignoreFalseConditions, separator) + + ToString("isMomentumSwitchedToBullish", isMomentumSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isMomentumSwitchedToBearish", isMomentumSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isStochasticBullish", isStochasticBullish, ignoreFalseConditions, separator) + + ToString("isStochasticBearish", isStochasticBearish, ignoreFalseConditions, separator) + + ToString("isStochasticSwitchedToBullish", isStochasticSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isStochasticSwitchedToBearish", isStochasticSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isStochasticOverSignal", isStochasticOverSignal, ignoreFalseConditions, separator) + + ToString("isStochasticUnderSignal", isStochasticUnderSignal, ignoreFalseConditions, separator) + + ToString("isStochasticCrossedOverSignal", isStochasticCrossedOverSignal, ignoreFalseConditions, separator) + + ToString("isStochasticCrossedUnderSignal", isStochasticCrossedUnderSignal, ignoreFalseConditions, separator) + + ToString("isStochasticOB", isStochasticOB, ignoreFalseConditions, separator) + + ToString("isStochasticOS", isStochasticOS, ignoreFalseConditions, separator) + + ToString("isStochasticCrossedOverOB", isStochasticCrossedOverOB, ignoreFalseConditions, separator) + + ToString("isStochasticCrossedOverOS", isStochasticCrossedOverOS, ignoreFalseConditions, separator) + + ToString("isStochasticCrossedUnderOB", isStochasticCrossedUnderOB, ignoreFalseConditions, separator) + + ToString("isStochasticCrossedUnderOS", isStochasticCrossedUnderOS, ignoreFalseConditions, separator) + + // + "" + // + ; + + // + result = + // + "[" + GetTag() + "]" + separator + + (onlyConditions + ? "" + : commonStr) + + (!includeScores + ? "" + : scoresStr) + + " " + separator + + (onlyCommons + ? "" + : conditionsStr) + + "" + // + ; + + // + return result; + } + + /** + * Retrieve nique Tag Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + return GetTypeName(this); + } +}; + +// +// Helper Class Implementation ... +class XCX121XOCSHelper : XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructors ... + XCX121XOCSHelper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCX121XOCSHelper() + { + // + mInputs.Clean(); + + // + Clean(acBuffer); + Clean(adBuffer); + Clean(atrBuffer); + Clean(cciBuffer); + Clean(rsiBuffer); + Clean(mfiBuffer); + Clean(rviBuffer); + Clean(adxBuffer); + Clean(adxpBuffer); + Clean(adxnBuffer); + Clean(macdBuffer); + Clean(momentumBuffer); + Clean(rviSignalBuffer); + Clean(macdSignalBuffer); + Clean(stochasticBuffer); + Clean(stochasticSignalBuffer); + } + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + X121XOCSInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + ArraySetAsSeries(acBuffer, true); + ArraySetAsSeries(adBuffer, true); + ArraySetAsSeries(atrBuffer, true); + ArraySetAsSeries(cciBuffer, true); + ArraySetAsSeries(rsiBuffer, true); + ArraySetAsSeries(mfiBuffer, true); + ArraySetAsSeries(rviBuffer, true); + ArraySetAsSeries(adxBuffer, true); + ArraySetAsSeries(adxpBuffer, true); + ArraySetAsSeries(adxnBuffer, true); + ArraySetAsSeries(macdBuffer, true); + ArraySetAsSeries(momentumBuffer, true); + ArraySetAsSeries(rviSignalBuffer, true); + ArraySetAsSeries(macdSignalBuffer, true); + ArraySetAsSeries(stochasticBuffer, true); + ArraySetAsSeries(stochasticSignalBuffer, true); + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.xoscs", + // + // Inputs ... + // + // AD ... + "", + mInputs.adAppliedTo, + // + // ADX ... + "", + mInputs.adxLength, + // + // ATR ... + "", + mInputs.atrLength, + // + // CCI ... + "", + mInputs.cciLength, + mInputs.cciAppliedTo, + // + // RSI ... + "", + mInputs.rsiLength, + mInputs.rsiAppliedTo, + // + // MFI ... + "", + mInputs.mfiLength, + mInputs.mfiAppliedTo, + // + // RVI ... + "", + mInputs.rviLength, + // + // MACD ... + "", + mInputs.macdFastLength, + mInputs.macdSlowLength, + mInputs.macdSignalLength, + mInputs.macdAppliedTo, + // + // MOMENTUM ... + "", + mInputs.momentumLength, + mInputs.momentumAppliedTo, + // + // STOCHASTIC ... + "", + mInputs.stochasticKLength, + mInputs.stochasticDLength, + mInputs.stochasticSmoothingLength, + mInputs.stochasticSmoothingMethod, + mInputs.stochasticAppliedTo, + // + // Presentation ... + "", + // + mInputs.startCalculationForLastBars + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + X121XOCSInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + X121XOCSInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Readers ... + + // + // AC ... + + // + double GetAC( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(acBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return acBuffer[barIndex]; + } + + // + int CopyAC( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + acBuffer, + buffer, + forceClean + // + ); + } + + // + // AD ... + + // + double GetAD( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(adBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return adBuffer[barIndex]; + } + + // + int CopyAD( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + adBuffer, + buffer, + forceClean + // + ); + } + + // + // ADX ... + + // + double GetADX( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(adxBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return adxBuffer[barIndex]; + } + + // + int CopyADX( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + adxBuffer, + buffer, + forceClean + // + ); + } + + // + // ADXP ... + + // + double GetADXP( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(adxpBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return adxpBuffer[barIndex]; + } + + // + int CopyADXP( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + adxpBuffer, + buffer, + forceClean + // + ); + } + + // + // ADXN ... + + // + double GetADXN( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(adxnBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return adxnBuffer[barIndex]; + } + + // + int CopyADXN( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + adxnBuffer, + buffer, + forceClean + // + ); + } + + // + // ATR ... + + // + double GetATR( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(atrBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return atrBuffer[barIndex]; + } + + // + 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(start); + + // + // Copy Items ... + return Copy( + 0, + count, + atrBuffer, + buffer, + forceClean + // + ); + } + + // + // CCI ... + + // + double GetCCI( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(cciBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return cciBuffer[barIndex]; + } + + // + 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(start); + + // + // Copy Items ... + return Copy( + 0, + count, + cciBuffer, + buffer, + forceClean + // + ); + } + + // + // RSI ... + + // + double GetRSI( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(rsiBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return rsiBuffer[barIndex]; + } + + // + 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(start); + + // + // Copy Items ... + return Copy( + 0, + count, + rsiBuffer, + buffer, + forceClean + // + ); + } + + // + // MFI ... + + // + double GetMFI( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(mfiBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return mfiBuffer[barIndex]; + } + + // + int CopyMFI( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + mfiBuffer, + buffer, + forceClean + // + ); + } + + // + // Momentum ... + + // + double GetMomentum( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(momentumBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return momentumBuffer[barIndex]; + } + + // + 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(start); + + // + // Copy Items ... + return Copy( + 0, + count, + momentumBuffer, + buffer, + forceClean + // + ); + } + + // + // RVI ... + + // + double GetRVI( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(rviBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return rviBuffer[barIndex]; + } + + // + 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(start); + + // + // Copy Items ... + return Copy( + 0, + count, + rviBuffer, + buffer, + forceClean + // + ); + } + + // + // RVI Signal ... + + // + double GetRVISignal( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(rviSignalBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return rviSignalBuffer[barIndex]; + } + + // + 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(start); + + // + // Copy Items ... + return Copy( + 0, + count, + rviSignalBuffer, + buffer, + forceClean + // + ); + } + + // + // MACD ... + + // + double GetMACD( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(macdBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return macdBuffer[barIndex]; + } + + // + 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(start); + + // + // Copy Items ... + return Copy( + 0, + count, + macdBuffer, + buffer, + forceClean + // + ); + } + + // + // MACD Signal ... + + // + double GetMACDSignal( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(macdSignalBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return macdSignalBuffer[barIndex]; + } + + // + 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(start); + + // + // Copy Items ... + return Copy( + 0, + count, + macdSignalBuffer, + buffer, + forceClean + // + ); + } + + // + // Stochastic ... + + // + double GetStochastic( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(stochasticBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return stochasticBuffer[barIndex]; + } + + // + int CopyStochastic( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + stochasticBuffer, + buffer, + forceClean + // + ); + } + + // + // Stochastic Signal ... + + // + double GetStochasticSignal( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(stochasticSignalBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return stochasticSignalBuffer[barIndex]; + } + + // + int CopyStochasticSignal( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + stochasticSignalBuffer, + buffer, + forceClean + // + ); + } + + // + void Free() override + { + Cleanup(10); + } + + // + bool GetConditions( + X121XOCSConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = true; + + // + if (loopback < 5) + { + loopback = 5; + } + + // + conditions.Clean(); + + // + conditions.symbol = mSymbol; + conditions.period = mPeriod; + conditions.time = TimeCurrent(); + + // + int zIndex = barIndex; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + XOHCL zBar; + result = zBar.Init( + mSymbol, + mPeriod, + zIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL cBar; + result = cBar.Init( + mSymbol, + mPeriod, + cIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL pBar; + result = pBar.Init( + mSymbol, + mPeriod, + pIndex // + ); + if (!result) + { + return result; + } + + // + // Buffers ... + + // + CopyAC( + zIndex, + loopback, + conditions.acBuffer // + ); + + // + CopyAD( + zIndex, + loopback, + conditions.adBuffer // + ); + + // + CopyADX( + zIndex, + loopback, + conditions.adxBuffer // + ); + + // + CopyADXP( + zIndex, + loopback, + conditions.adxpBuffer // + ); + + // + CopyADXN( + zIndex, + loopback, + conditions.adxnBuffer // + ); + + // + CopyATR( + zIndex, + loopback, + conditions.atrBuffer // + ); + + // + CopyCCI( + zIndex, + loopback, + conditions.cciBuffer // + ); + + // + CopyRSI( + zIndex, + loopback, + conditions.rsiBuffer // + ); + + // + CopyMFI( + zIndex, + loopback, + conditions.mfiBuffer // + ); + + // + CopyMomentum( + zIndex, + loopback, + conditions.momentumBuffer // + ); + + // + CopyRVI( + zIndex, + loopback, + conditions.rviBuffer // + ); + + // + CopyRVISignal( + zIndex, + loopback, + conditions.rviSignalBuffer // + ); + + // + CopyMACD( + zIndex, + loopback, + conditions.macdBuffer // + ); + + // + CopyMACDSignal( + zIndex, + loopback, + conditions.macdSignalBuffer // + ); + + // + CopyStochastic( + zIndex, + loopback, + conditions.stochasticBuffer // + ); + + // + CopyStochasticSignal( + zIndex, + loopback, + conditions.stochasticSignalBuffer // + ); + + // + // Values ... + + // + conditions.adxThreshold = mInputs.adxThreshold; + conditions.cciOBLevel = mInputs.cciOBLevel; + conditions.cciOSLevel = mInputs.cciOSLevel; + conditions.cciReversalLevel = mInputs.cciReversalLevel; + conditions.rsiOBLevel = mInputs.rsiOBLevel; + conditions.rsiOSLevel = mInputs.rsiOSLevel; + conditions.rsiReversalLevel = mInputs.rsiReversalLevel; + conditions.mfiOBLevel = mInputs.mfiOBLevel; + conditions.mfiOSLevel = mInputs.mfiOSLevel; + conditions.mfiReversalLevel = mInputs.mfiReversalLevel; + conditions.rviBullishLevel = mInputs.rviBullishLevel; + conditions.rviBearishLevel = mInputs.rviBearishLevel; + conditions.macdBullishLevel = mInputs.macdBullishLevel; + conditions.macdBearishLevel = mInputs.macdBearishLevel; + conditions.momentumBullishLevel = mInputs.momentumBullishLevel; + conditions.momentumBearishLevel = mInputs.momentumBearishLevel; + conditions.stochasticOBLevel = mInputs.stochasticOBLevel; + conditions.stochasticOSLevel = mInputs.stochasticOSLevel; + conditions.stochasticReversalLevel = mInputs.stochasticReversalLevel; + + // + // Conditions ... + + // + int cIDX = 1; + int pIDX = cIDX + 1; + int ppIDX = pIDX + 1; + + // + // AC ... + + // + bool isACBullish = conditions.acBuffer[cIDX] > mInputs.acBullishLevel; + bool isACBullishPrev = conditions.acBuffer[pIDX] > mInputs.acBullishLevel; + bool isACSwitchedToBullish = isACBullish && + !isACBullishPrev; + + // + bool isACBearish = conditions.acBuffer[cIDX] < mInputs.acBearishLevel; + bool isACBearishPrev = conditions.acBuffer[pIDX] < mInputs.acBearishLevel; + bool isACSwitchedToBearish = isACBearish && + !isACBearishPrev; + + // + bool isACOverMax = conditions.acBuffer[cIDX] >= GetMax(conditions.acBuffer); + bool isACUnderMin = conditions.acBuffer[cIDX] <= GetMin(conditions.acBuffer); + + // + // AD ... + + // + bool isADBiggerLast = conditions.adBuffer[cIDX] > conditions.adBuffer[pIDX]; + bool isADLesserLast = conditions.adBuffer[cIDX] < conditions.adBuffer[pIDX]; + + // + bool isADOverMax = conditions.adBuffer[cIDX] >= GetMax(conditions.adBuffer); + bool isADUnderMin = conditions.adBuffer[cIDX] <= GetMin(conditions.adBuffer); + + // + // ADX ... + + // + bool isADXBiggerLast = conditions.adxBuffer[cIDX] > conditions.adxBuffer[pIDX]; + bool isADXBiggerLastPrev = conditions.adxBuffer[pIDX] > conditions.adxBuffer[ppIDX]; + + // + bool isADXLesserLast = conditions.adxBuffer[cIDX] < conditions.adxBuffer[pIDX]; + bool isADXLesserLastPrev = conditions.adxBuffer[pIDX] < conditions.adxBuffer[ppIDX]; + + // + bool isADXOverThreshold = conditions.adxBuffer[cIDX] > mInputs.adxThreshold; + bool isADXOverThresholdPrev = conditions.adxBuffer[pIDX] > mInputs.adxThreshold; + + // + bool isADXUnderThreshold = conditions.adxBuffer[cIDX] < mInputs.adxThreshold; + bool isADXUnderThresholdPrev = conditions.adxBuffer[pIDX] < mInputs.adxThreshold; + + // + bool isDXPBiggerThanDXN = conditions.adxpBuffer[cIDX] > conditions.adxnBuffer[cIDX]; + bool isDXPBiggerThanDXNPrev = conditions.adxpBuffer[pIDX] > conditions.adxnBuffer[pIDX]; + + // + bool isDXNBiggerThanDXP = conditions.adxnBuffer[cIDX] > conditions.adxpBuffer[cIDX]; + bool isDXNBiggerThanDXPPrev = conditions.adxnBuffer[pIDX] > conditions.adxpBuffer[pIDX]; + + // + bool isADXBullish = isADXBiggerLast && + isDXPBiggerThanDXN && + isADXOverThreshold; + bool isADXBullishPrev = isADXBiggerLastPrev && + isDXPBiggerThanDXNPrev && + isADXOverThresholdPrev; + bool isADXSwitchedToBullish = isADXBullish && + !isADXBullishPrev; + + // + bool isADXBearish = isADXLesserLast && + isDXNBiggerThanDXP && + isADXUnderThreshold; + bool isADXBearishPrev = isADXLesserLastPrev && + isDXNBiggerThanDXP && + isADXUnderThresholdPrev; + bool isADXSwitchedToBearish = isADXBearish && + !isADXBearishPrev; + + // + // ATR ... + + // + bool isATROverLast = conditions.atrBuffer[cIDX] > conditions.atrBuffer[pIDX]; + bool isATRUnderLast = conditions.atrBuffer[cIDX] < conditions.atrBuffer[pIDX]; + + // + // CCI ... + + // + bool isCCIBullish = conditions.cciBuffer[cIDX] > mInputs.cciReversalLevel; + bool isCCIBullishPrev = conditions.cciBuffer[pIDX] > mInputs.cciReversalLevel; + bool isCCISwitchedToBullish = isCCIBullish && + !isCCIBullishPrev; + + // + bool isCCIBearish = conditions.cciBuffer[cIDX] < mInputs.cciReversalLevel; + bool isCCIBearishPrev = conditions.cciBuffer[pIDX] < mInputs.cciReversalLevel; + bool isCCISwitchedToBearish = isCCIBearish && + !isCCIBearishPrev; + + // + bool isCCIOB = conditions.cciBuffer[cIDX] > mInputs.cciOBLevel; + bool isCCIOBPrev = conditions.cciBuffer[pIDX] > mInputs.cciOBLevel; + bool isCCICrossedOverOB = isCCIOB && + !isCCIOBPrev; + + // + bool isCCIUnderOB = conditions.cciBuffer[cIDX] < mInputs.cciOBLevel; + bool isCCIUnderOBPrev = conditions.cciBuffer[pIDX] < mInputs.cciOBLevel; + bool isCCICrossedUnderOB = isCCIUnderOB && + !isCCIUnderOBPrev; + + // + bool isCCIOS = conditions.cciBuffer[cIDX] < mInputs.cciOSLevel; + bool isCCIOSPrev = conditions.cciBuffer[pIDX] < mInputs.cciOSLevel; + bool isCCICrossedUnderOS = isCCIOS && + !isCCIOSPrev; + + // + bool isCCIOverOS = conditions.cciBuffer[cIDX] > mInputs.cciOSLevel; + bool isCCIOverOSPrev = conditions.cciBuffer[pIDX] > mInputs.cciOSLevel; + bool isCCICrossedOverOS = isCCIOverOS && + !isCCIOverOSPrev; + + // + // RSI ... + + // + bool isRSIBullish = conditions.rsiBuffer[cIDX] > mInputs.rsiReversalLevel; + bool isRSIBullishPrev = conditions.rsiBuffer[pIDX] > mInputs.rsiReversalLevel; + bool isRSISwitchedToBullish = isRSIBullish && + !isRSIBullishPrev; + + // + bool isRSIBearish = conditions.rsiBuffer[cIDX] < mInputs.rsiReversalLevel; + bool isRSIBearishPrev = conditions.rsiBuffer[pIDX] < mInputs.rsiReversalLevel; + bool isRSISwitchedToBearish = isRSIBearish && + !isRSIBearishPrev; + + // + bool isRSIOB = conditions.rsiBuffer[cIDX] > mInputs.rsiOBLevel; + bool isRSIOBPrev = conditions.rsiBuffer[pIDX] > mInputs.rsiOBLevel; + bool isRSICrossedOverOB = isRSIOB && + !isRSIOBPrev; + + // + bool isRSIUnderOB = conditions.rsiBuffer[cIDX] < mInputs.rsiOBLevel; + bool isRSIUnderOBPrev = conditions.rsiBuffer[pIDX] < mInputs.rsiOBLevel; + bool isRSICrossedUnderOB = isRSIUnderOB && + !isRSIUnderOBPrev; + + // + bool isRSIOS = conditions.rsiBuffer[cIDX] < mInputs.rsiOSLevel; + bool isRSIOSPrev = conditions.rsiBuffer[pIDX] < mInputs.rsiOSLevel; + bool isRSICrossedUnderOS = isRSIOS && + !isRSIOSPrev; + + // + bool isRSIOverOS = conditions.rsiBuffer[cIDX] > mInputs.rsiOSLevel; + bool isRSIOverOSPrev = conditions.rsiBuffer[pIDX] > mInputs.rsiOSLevel; + bool isRSICrossedOverOS = isRSIOverOS && + !isRSIOverOSPrev; + + // + // MFI ... + + // + bool isMFIBullish = conditions.mfiBuffer[cIDX] > mInputs.mfiReversalLevel; + bool isMFIBullishPrev = conditions.mfiBuffer[pIDX] > mInputs.mfiReversalLevel; + bool isMFISwitchedToBullish = isMFIBullish && + !isMFIBullishPrev; + + // + bool isMFIBearish = conditions.mfiBuffer[cIDX] < mInputs.mfiReversalLevel; + bool isMFIBearishPrev = conditions.mfiBuffer[pIDX] < mInputs.mfiReversalLevel; + bool isMFISwitchedToBearish = isMFIBearish && + !isMFIBearishPrev; + + // + bool isMFIOB = conditions.mfiBuffer[cIDX] > mInputs.mfiOBLevel; + bool isMFIOBPrev = conditions.mfiBuffer[pIDX] > mInputs.mfiOBLevel; + bool isMFICrossedOverOB = isMFIOB && + !isMFIOBPrev; + + // + bool isMFIUnderOB = conditions.mfiBuffer[cIDX] < mInputs.mfiOBLevel; + bool isMFIUnderOBPrev = conditions.mfiBuffer[pIDX] < mInputs.mfiOBLevel; + bool isMFICrossedUnderOB = isMFIUnderOB && + !isMFIUnderOBPrev; + + // + bool isMFIOS = conditions.mfiBuffer[cIDX] < mInputs.mfiOSLevel; + bool isMFIOSPrev = conditions.mfiBuffer[pIDX] < mInputs.mfiOSLevel; + bool isMFICrossedUnderOS = isMFIOS && + !isMFIOSPrev; + + // + bool isMFIOverOS = conditions.mfiBuffer[cIDX] > mInputs.mfiOSLevel; + bool isMFIOverOSPrev = conditions.mfiBuffer[pIDX] > mInputs.mfiOSLevel; + bool isMFICrossedOverOS = isMFIOverOS && + !isMFIOverOSPrev; + + // + // RVI ... + + // + bool isRVIBullish = conditions.rviBuffer[cIDX] > mInputs.rviBullishLevel; + bool isRVIBullishPrev = conditions.rviBuffer[pIDX] > mInputs.rviBullishLevel; + bool isRVISwitchedToBullish = isRVIBullish && + !isRVIBullishPrev; + + // + bool isRVIBearish = conditions.rviBuffer[cIDX] < mInputs.rviBearishLevel; + bool isRVIBearishPrev = conditions.rviBuffer[pIDX] < mInputs.rviBearishLevel; + bool isRVISwitchedToBearish = isRVIBearish && + !isRVIBearishPrev; + + // + bool isRVIOverSignal = conditions.rviBuffer[cIDX] > conditions.rviSignalBuffer[cIDX]; + bool isRVIOverSignalPrev = conditions.rviBuffer[pIDX] > conditions.rviSignalBuffer[pIDX]; + bool isRVICrossedOverSignal = isRVIOverSignal && + !isRVIOverSignalPrev; + + // + bool isRVIUnderSignal = conditions.rviBuffer[cIDX] < conditions.rviSignalBuffer[cIDX]; + bool isRVIUnderSignalPrev = conditions.rviBuffer[pIDX] < conditions.rviSignalBuffer[pIDX]; + bool isRVICrossedUnderSignal = isRVIUnderSignal && + !isRVIUnderSignalPrev; + + // + // MACD ... + + // + bool isMACDBullish = conditions.macdBuffer[cIDX] > mInputs.macdBullishLevel; + bool isMACDBullishPrev = conditions.macdBuffer[pIDX] > mInputs.macdBullishLevel; + bool isMACDSwitchedToBullish = isMACDBullish && + !isMACDBullishPrev; + + // + bool isMACDBearish = conditions.macdBuffer[cIDX] < mInputs.macdBearishLevel; + bool isMACDBearishPrev = conditions.macdBuffer[pIDX] < mInputs.macdBearishLevel; + bool isMACDSwitchedToBearish = isMACDBearish && + !isMACDBearishPrev; + + // + bool isMACDOverSignal = conditions.macdBuffer[cIDX] > conditions.macdSignalBuffer[cIDX]; + bool isMACDOverSignalPrev = conditions.macdBuffer[pIDX] > conditions.macdSignalBuffer[pIDX]; + bool isMACDCrossedOverSignal = isMACDOverSignal && + !isMACDOverSignalPrev; + + // + bool isMACDUnderSignal = conditions.macdBuffer[cIDX] < conditions.macdSignalBuffer[cIDX]; + bool isMACDUnderSignalPrev = conditions.macdBuffer[pIDX] < conditions.macdSignalBuffer[pIDX]; + bool isMACDCrossedUnderSignal = isMACDUnderSignal && + !isMACDUnderSignalPrev; + + // + // MOMENTUM ... + + // + bool isMomentumBullish = conditions.momentumBuffer[cIDX] > mInputs.momentumBullishLevel; + bool isMomentumBullishPrev = conditions.momentumBuffer[pIDX] > mInputs.momentumBullishLevel; + bool isMomentumSwitchedToBullish = isMomentumBullish && + !isMomentumBullishPrev; + + // + bool isMomentumBearish = conditions.momentumBuffer[cIDX] < mInputs.momentumBearishLevel; + bool isMomentumBearishPrev = conditions.momentumBuffer[pIDX] < mInputs.momentumBearishLevel; + bool isMomentumSwitchedToBearish = isMomentumBearish && + !isMomentumBearishPrev; + + // + // STOCHASTIC ... + + // + bool isStochasticBullish = conditions.stochasticBuffer[cIDX] > mInputs.stochasticReversalLevel; + bool isStochasticBullishPrev = conditions.stochasticBuffer[pIDX] > mInputs.stochasticReversalLevel; + bool isStochasticSwitchedToBullish = isStochasticBullish && + !isStochasticBullishPrev; + + // + bool isStochasticBearish = conditions.stochasticBuffer[cIDX] < mInputs.stochasticReversalLevel; + bool isStochasticBearishPrev = conditions.stochasticBuffer[pIDX] < mInputs.stochasticReversalLevel; + bool isStochasticSwitchedToBearish = isStochasticBearish && + !isStochasticBearishPrev; + + // + bool isStochasticOverSignal = conditions.stochasticBuffer[cIDX] > conditions.stochasticSignalBuffer[cIDX]; + bool isStochasticOverSignalPrev = conditions.stochasticBuffer[pIDX] > conditions.stochasticSignalBuffer[pIDX]; + bool isStochasticCrossedOverSignal = isStochasticOverSignal && + !isStochasticOverSignalPrev; + + // + bool isStochasticUnderSignal = conditions.stochasticBuffer[cIDX] < conditions.stochasticSignalBuffer[cIDX]; + bool isStochasticUnderSignalPrev = conditions.stochasticBuffer[pIDX] < conditions.stochasticSignalBuffer[pIDX]; + bool isStochasticCrossedUnderSignal = isStochasticUnderSignal && + !isStochasticUnderSignalPrev; + + // + bool isStochasticOB = conditions.stochasticBuffer[cIDX] > mInputs.stochasticOBLevel; + bool isStochasticOBPrev = conditions.stochasticBuffer[pIDX] > mInputs.stochasticOBLevel; + bool isStochasticCrossedOverOB = isStochasticOB && + !isStochasticOBPrev; + + // + bool isStochasticUnderOB = conditions.stochasticBuffer[cIDX] < mInputs.stochasticOBLevel; + bool isStochasticUnderOBPrev = conditions.stochasticBuffer[pIDX] < mInputs.stochasticOBLevel; + bool isStochasticCrossedUnderOB = isStochasticUnderOB && + !isStochasticUnderOBPrev; + + // + bool isStochasticOS = conditions.stochasticBuffer[cIDX] < mInputs.stochasticOSLevel; + bool isStochasticOSPrev = conditions.stochasticBuffer[pIDX] < mInputs.stochasticOSLevel; + bool isStochasticCrossedUnderOS = isStochasticOS && + !isStochasticOSPrev; + + // + bool isStochasticOverOS = conditions.stochasticBuffer[cIDX] > mInputs.stochasticOSLevel; + bool isStochasticOverOSPrev = conditions.stochasticBuffer[pIDX] > mInputs.stochasticOSLevel; + bool isStochasticCrossedOverOS = isStochasticOverOS && + !isStochasticOverOSPrev; + + // + // + // + + // + conditions.isCCIOB = isCCIOB; + conditions.isCCIOS = isCCIOS; + conditions.isRSIOB = isRSIOB; + conditions.isRSIOS = isRSIOS; + conditions.isMFIOB = isMFIOB; + conditions.isMFIOS = isMFIOS; + conditions.isACBullish = isACBullish; + conditions.isACBearish = isACBearish; + conditions.isACOverMax = isACOverMax; + conditions.isADOverMax = isADOverMax; + conditions.isACUnderMin = isACUnderMin; + conditions.isADUnderMin = isADUnderMin; + conditions.isADXBullish = isADXBullish; + conditions.isADXBearish = isADXBearish; + conditions.isCCIBullish = isCCIBullish; + conditions.isCCIBearish = isCCIBearish; + conditions.isRSIBullish = isRSIBullish; + conditions.isRSIBearish = isRSIBearish; + conditions.isMFIBullish = isMFIBullish; + conditions.isMFIBearish = isMFIBearish; + conditions.isRVIBullish = isRVIBullish; + conditions.isRVIBearish = isRVIBearish; + conditions.isATROverLast = isATROverLast; + conditions.isMACDBullish = isMACDBullish; + conditions.isMACDBearish = isMACDBearish; + conditions.isATRUnderLast = isATRUnderLast; + conditions.isADBiggerLast = isADBiggerLast; + conditions.isADLesserLast = isADLesserLast; + conditions.isStochasticOB = isStochasticOB; + conditions.isStochasticOS = isStochasticOS; + conditions.isADXBiggerLast = isADXBiggerLast; + conditions.isADXLesserLast = isADXLesserLast; + conditions.isRVIOverSignal = isRVIOverSignal; + conditions.isRVIUnderSignal = isRVIUnderSignal; + conditions.isMACDOverSignal = isMACDOverSignal; + conditions.isMACDUnderSignal = isMACDUnderSignal; + conditions.isMomentumBullish = isMomentumBullish; + conditions.isMomentumBearish = isMomentumBearish; + conditions.isADXOverThreshold = isADXOverThreshold; + conditions.isDXPBiggerThanDXN = isDXPBiggerThanDXN; + conditions.isDXNBiggerThanDXP = isDXNBiggerThanDXP; + conditions.isCCICrossedOverOB = isCCICrossedOverOB; + conditions.isCCICrossedOverOS = isCCICrossedOverOS; + conditions.isRSICrossedOverOB = isRSICrossedOverOB; + conditions.isRSICrossedOverOS = isRSICrossedOverOS; + conditions.isMFICrossedOverOB = isMFICrossedOverOB; + conditions.isMFICrossedOverOS = isMFICrossedOverOS; + conditions.isADXUnderThreshold = isADXUnderThreshold; + conditions.isCCICrossedUnderOB = isCCICrossedUnderOB; + conditions.isCCICrossedUnderOS = isCCICrossedUnderOS; + conditions.isRSICrossedUnderOB = isRSICrossedUnderOB; + conditions.isRSICrossedUnderOS = isRSICrossedUnderOS; + conditions.isMFICrossedUnderOB = isMFICrossedUnderOB; + conditions.isMFICrossedUnderOS = isMFICrossedUnderOS; + conditions.isStochasticBullish = isStochasticBullish; + conditions.isStochasticBearish = isStochasticBearish; + conditions.isACSwitchedToBullish = isACSwitchedToBullish; + conditions.isACSwitchedToBearish = isACSwitchedToBearish; + conditions.isADXSwitchedToBullish = isADXSwitchedToBullish; + conditions.isADXSwitchedToBearish = isADXSwitchedToBearish; + conditions.isCCISwitchedToBullish = isCCISwitchedToBullish; + conditions.isCCISwitchedToBearish = isCCISwitchedToBearish; + conditions.isRSISwitchedToBullish = isRSISwitchedToBullish; + conditions.isRSISwitchedToBearish = isRSISwitchedToBearish; + conditions.isMFISwitchedToBullish = isMFISwitchedToBullish; + conditions.isMFISwitchedToBearish = isMFISwitchedToBearish; + conditions.isRVISwitchedToBullish = isRVISwitchedToBullish; + conditions.isRVISwitchedToBearish = isRVISwitchedToBearish; + conditions.isRVICrossedOverSignal = isRVICrossedOverSignal; + conditions.isStochasticOverSignal = isStochasticOverSignal; + conditions.isStochasticUnderSignal = isStochasticUnderSignal; + conditions.isRVICrossedUnderSignal = isRVICrossedUnderSignal; + conditions.isMACDSwitchedToBullish = isMACDSwitchedToBullish; + conditions.isMACDSwitchedToBearish = isMACDSwitchedToBearish; + conditions.isMACDCrossedOverSignal = isMACDCrossedOverSignal; + conditions.isMACDCrossedUnderSignal = isMACDCrossedUnderSignal; + conditions.isStochasticCrossedOverOB = isStochasticCrossedOverOB; + conditions.isStochasticCrossedOverOS = isStochasticCrossedOverOS; + conditions.isStochasticCrossedUnderOB = isStochasticCrossedUnderOB; + conditions.isStochasticCrossedUnderOS = isStochasticCrossedUnderOS; + conditions.isMomentumSwitchedToBullish = isMomentumSwitchedToBullish; + conditions.isMomentumSwitchedToBearish = isMomentumSwitchedToBearish; + conditions.isStochasticSwitchedToBullish = isStochasticSwitchedToBullish; + conditions.isStochasticSwitchedToBearish = isStochasticSwitchedToBearish; + conditions.isStochasticCrossedOverSignal = isStochasticCrossedOverSignal; + conditions.isStochasticCrossedUnderSignal = isStochasticCrossedUnderSignal; + + // + Cleanup(); + + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + + // + return result; + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + X121XOCSInputs mInputs; // Inputs ... + + // + // Buffers ... + double acBuffer[]; + double adBuffer[]; + double atrBuffer[]; + double cciBuffer[]; + double rsiBuffer[]; + double mfiBuffer[]; + double rviBuffer[]; + double adxBuffer[]; + double adxpBuffer[]; + double adxnBuffer[]; + double macdBuffer[]; + double momentumBuffer[]; + double rviSignalBuffer[]; + double macdSignalBuffer[]; + double stochasticBuffer[]; + double stochasticSignalBuffer[]; + + // + void Calculate( + int barIndex = 0, + int maxRequiredBars = 100 // + ) + { + // + // Buffers ... + if (barIndex < 0) + { + barIndex = 0; + } + + // + // AC ... + CopyBuffer( + mHandler, + X121_XOSCS_XAC_LINE, + barIndex, + maxRequiredBars, + acBuffer // + ); + + // + // AD ... + CopyBuffer( + mHandler, + X121_XOSCS_XAD_LINE, + barIndex, + maxRequiredBars, + adBuffer // + ); + + // + // ADX ... + CopyBuffer( + mHandler, + X121_XOSCS_XADX_LINE, + barIndex, + maxRequiredBars, + adxBuffer // + ); + + // + // ADX P ... + CopyBuffer( + mHandler, + X121_XOSCS_XADX_P_LINE, + barIndex, + maxRequiredBars, + adxpBuffer // + ); + + // + // ADX N ... + CopyBuffer( + mHandler, + X121_XOSCS_XADX_N_LINE, + barIndex, + maxRequiredBars, + adxnBuffer // + ); + + // + // ATR ... + CopyBuffer( + mHandler, + X121_XOSCS_XATR_LINE, + barIndex, + maxRequiredBars, + atrBuffer // + ); + + // + // CCI ... + CopyBuffer( + mHandler, + X121_XOSCS_XCCI_LINE, + barIndex, + maxRequiredBars, + cciBuffer // + ); + + // + // RSI ... + CopyBuffer( + mHandler, + X121_XOSCS_XRSI_LINE, + barIndex, + maxRequiredBars, + rsiBuffer // + ); + + // + // MFI ... + CopyBuffer( + mHandler, + X121_XOSCS_XMFI_LINE, + barIndex, + maxRequiredBars, + mfiBuffer // + ); + + // + // MOMENTUM ... + CopyBuffer( + mHandler, + X121_XOSCS_XMOMENTUM_LINE, + barIndex, + maxRequiredBars, + momentumBuffer // + ); + + // + // RVI ... + CopyBuffer( + mHandler, + X121_XOSCS_XRVI_LINE, + barIndex, + maxRequiredBars, + rviBuffer // + ); + + // + // RVI Signal ... + CopyBuffer( + mHandler, + X121_XOSCS_XRVI_S_LINE, + barIndex, + maxRequiredBars, + rviSignalBuffer // + ); + + // + // MACD ... + CopyBuffer( + mHandler, + X121_XOSCS_XMACD_LINE, + barIndex, + maxRequiredBars, + macdBuffer // + ); + + // + // MACD Signal ... + CopyBuffer( + mHandler, + X121_XOSCS_XMACD_S_LINE, + barIndex, + maxRequiredBars, + macdSignalBuffer // + ); + + // + // STOCHASTIC ... + CopyBuffer( + mHandler, + X121_XOSCS_XSTOCHASTIC_LINE, + barIndex, + maxRequiredBars, + stochasticBuffer // + ); + + // + // STOCHASTIC Signal ... + CopyBuffer( + mHandler, + X121_XOSCS_XSTOCHASTIC_S_LINE, + barIndex, + maxRequiredBars, + stochasticSignalBuffer // + ); + } + + // + void Cleanup( + int maxAllowed = 100 // + ) + { + // + CleanupArray( + acBuffer, + maxAllowed // + ); + + // + CleanupArray( + adBuffer, + maxAllowed // + ); + + // + CleanupArray( + atrBuffer, + maxAllowed // + ); + + // + CleanupArray( + cciBuffer, + maxAllowed // + ); + + // + CleanupArray( + rsiBuffer, + maxAllowed // + ); + + // + CleanupArray( + mfiBuffer, + maxAllowed // + ); + + // + CleanupArray( + rviBuffer, + maxAllowed // + ); + + // + CleanupArray( + adxBuffer, + maxAllowed // + ); + + // + CleanupArray( + adxpBuffer, + maxAllowed // + ); + + // + CleanupArray( + adxnBuffer, + maxAllowed // + ); + + // + CleanupArray( + macdBuffer, + maxAllowed // + ); + + // + CleanupArray( + momentumBuffer, + maxAllowed // + ); + + // + CleanupArray( + rviSignalBuffer, + maxAllowed // + ); + + // + CleanupArray( + macdSignalBuffer, + maxAllowed // + ); + + // + CleanupArray( + stochasticBuffer, + maxAllowed // + ); + + // + CleanupArray( + stochasticSignalBuffer, + maxAllowed // + ); + } + + // +}; diff --git a/BKPS/14040316/Documents/Indicators/x-saherelm.x121.x3ma.mq5 b/BKPS/14040316/Documents/Indicators/x-saherelm.x121.x3ma.mq5 new file mode 100644 index 0000000..e535571 --- /dev/null +++ b/BKPS/14040316/Documents/Indicators/x-saherelm.x121.x3ma.mq5 @@ -0,0 +1,788 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 X3MA +// Description: X3MA ... +// +// +// 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 X3MA Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121 X3MA" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +// Fast ... +input group "Fast"; +input int fastLength = 6; // Length +input ENUM_MA_METHOD fastMethod = MODE_SMA; // Method +input ENUM_APPLIED_PRICE fastAppliedTo = PRICE_CLOSE; // Applied To + +// +// Medium ... +input group "Medium"; +input int mediumLength = 21; // Length +input ENUM_MA_METHOD mediumMethod = MODE_SMA; // Method +input ENUM_APPLIED_PRICE mediumAppliedTo = PRICE_CLOSE; // Applied To + +// +// Slow ... +input group "Slow"; +input int slowLength = 34; // Length +input ENUM_MA_METHOD slowMethod = MODE_SMA; // Method +input ENUM_APPLIED_PRICE slowAppliedTo = PRICE_CLOSE; // Applied To + +// +// Presentation ... +input group "Presentation"; + +// +input int startCalculationForLastBars = 1000; // Calculate Last n Bars + +// +input bool applyColor = false; + +// +input bool showFast = true; // Show Fast +input bool showMedium = true; // Show Medium +input bool showSlow = true; // Show Slow + +// +// Buffers ... + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#define bullishState 1 +#define neuturalState 0 +#define bearishState -1 + +// +#define emptyValue 0.0 + +// +#property indicator_chart_window + +// +#property indicator_buffers 9 +#property indicator_plots 3 + +// +// Plot Buffers ... + +// +// FAST ... + +// +#define fastBufferIndex 0 +double fastBuffer[]; + +// +#define fastColorBufferIndex 1 +double fastColorBuffer[]; + +// +#property indicator_label1 "X121 X3MA Fast" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 CLR_NONE, clrYellow, clrChocolate, clrGray +#property indicator_style1 STYLE_SOLID +#property indicator_width1 2 + +// +// MEDIUM ... + +// +#define mediumBufferIndex 2 +double mediumBuffer[]; + +// +#define mediumColorBufferIndex 3 +double mediumColorBuffer[]; + +// +#property indicator_label2 "X121 X3MA Medium" +#property indicator_type2 DRAW_COLOR_LINE +#property indicator_color2 CLR_NONE, clrAqua, clrMagenta, clrGray +#property indicator_style2 STYLE_DASHDOTDOT +#property indicator_width2 2 + +// +// SLOW ... + +// +#define slowBufferIndex 4 +double slowBuffer[]; + +// +#define slowColorBufferIndex 5 +double slowColorBuffer[]; + +// +#property indicator_label3 "X121 X3MA Slow" +#property indicator_type3 DRAW_COLOR_LINE +#property indicator_color3 CLR_NONE, clrLime, clrRed, clrGray +#property indicator_style3 STYLE_DASH +#property indicator_width3 2 + +// +// Data Buffers ... + +#define mLastBufferIndex 5 + +// +#define fastStateBufferIndex mLastBufferIndex + 1 +double fastStateBuffer[]; + +// +#define mediumStateBufferIndex mLastBufferIndex + 2 +double mediumStateBuffer[]; + +// +#define slowStateBufferIndex mLastBufferIndex + 3 +double slowStateBuffer[]; + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +int fastHandler = INVALID_HANDLE; +int mediumHandler = INVALID_HANDLE; +int slowHandler = INVALID_HANDLE; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + + // + // FAST ... + fastHandler = iMA( + _Symbol, + _Period, + fastLength, + 0, + fastMethod, + fastAppliedTo // + ); + bool isInited = fastHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // MEDIUM ... + mediumHandler = iMA( + _Symbol, + _Period, + mediumLength, + 0, + mediumMethod, + mediumAppliedTo // + ); + isInited = mediumHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // SLOW ... + slowHandler = iMA( + _Symbol, + _Period, + slowLength, + 0, + slowMethod, + slowAppliedTo // + ); + isInited = slowHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // 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; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +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(fastHandler); + IndicatorRelease(mediumHandler); + IndicatorRelease(slowHandler); +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // 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); + + // + // Validate Calculated Bars ... + + // + // FAST ... + int fastCalculatedBars = BarsCalculated(fastHandler); + + // + // MEDIUM ... + int mediumCalculatedBars = BarsCalculated(mediumHandler); + + // + // SLOW ... + int slowCalculatedBars = BarsCalculated(slowHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // FAST ... + fastCalculatedBars >= maxLength && + // + // MEDIUM ... + mediumCalculatedBars >= maxLength && + // + // SLOW ... + slowCalculatedBars >= maxLength + // + ; + if (!isPassedRequiredCalculatedBars) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + + // + // FAST ... + int copiedFasts = CopyBuffer(fastHandler, 0, 0, limit, fastBuffer); + + // + // MEDIUM ... + int copiedMediumss = CopyBuffer(mediumHandler, 0, 0, limit, mediumBuffer); + + // + // SLOW ... + int copiedSlows = CopyBuffer(slowHandler, 0, 0, limit, slowBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // FAST ... + copiedFasts >= limit && + // + // MEDIUM ... + copiedMediumss >= limit && + // + // SLOW ... + copiedSlows >= limit + // + ; + if (!isPassedRequiredCopiedItems) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + result = + // + fastLength > 2 && + mediumLength > 2 && + slowLength > 2 && + mediumLength > fastLength && + mediumLength < slowLength + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(fastLength, mediumLength); + result = MathMax(result, slowLength); + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + + // + // FAST ... + + // + ArraySetAsSeries(fastBuffer, true); + SetIndexBuffer(fastBufferIndex, fastBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(fastBufferIndex, PLOT_SHOW_DATA, showFast); + + // + PlotIndexSetDouble(fastBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(fastColorBuffer, true); + SetIndexBuffer(fastColorBufferIndex, fastColorBuffer, INDICATOR_COLOR_INDEX); + + // + // MEDIUM ... + + // + ArraySetAsSeries(mediumBuffer, true); + SetIndexBuffer(mediumBufferIndex, mediumBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(mediumBufferIndex, PLOT_SHOW_DATA, showMedium); + + // + PlotIndexSetDouble(mediumBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(mediumColorBuffer, true); + SetIndexBuffer(mediumColorBufferIndex, mediumColorBuffer, INDICATOR_COLOR_INDEX); + + // + // SLOW ... + + // + ArraySetAsSeries(slowBuffer, true); + SetIndexBuffer(slowBufferIndex, slowBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(slowBufferIndex, PLOT_SHOW_DATA, showSlow); + + // + PlotIndexSetDouble(slowBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(slowColorBuffer, true); + SetIndexBuffer(slowColorBufferIndex, slowColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Data Buffers ... + + // + // FAST State ... + ArraySetAsSeries(fastStateBuffer, true); + SetIndexBuffer(fastStateBufferIndex, fastStateBuffer, INDICATOR_CALCULATIONS); + + // + // MEDIUM State ... + ArraySetAsSeries(mediumStateBuffer, true); + SetIndexBuffer(mediumStateBufferIndex, mediumStateBuffer, INDICATOR_CALCULATIONS); + + // + // SLOW State ... + ArraySetAsSeries(slowStateBuffer, true); + SetIndexBuffer(slowStateBufferIndex, slowStateBuffer, INDICATOR_CALCULATIONS); +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + // + IndicatorSetInteger(INDICATOR_DIGITS, _Digits); + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +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[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + // + // bool canCalculate = true; + bool canCalculate = + barsLimit == 0 || + bar_index <= barsLimit; + if (canCalculate) + { + // + // Calculate Values ... + CalculateValues( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + else + { + FillBuffersZero(bar_index); + } +} + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + // FAST ... + fastBuffer[barIndex] = emptyValue; + fastColorBuffer[barIndex] = hideColorIDX; + fastStateBuffer[barIndex] = neuturalState; + + // + // MEDIUM ... + mediumBuffer[barIndex] = emptyValue; + mediumColorBuffer[barIndex] = hideColorIDX; + mediumStateBuffer[barIndex] = neuturalState; + + // + // SLOW ... + slowBuffer[barIndex] = emptyValue; + slowColorBuffer[barIndex] = hideColorIDX; + slowStateBuffer[barIndex] = neuturalState; +} + +/** + * Calculate Values ... + * + * @param bar_index: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void CalculateValues( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // Check Prev Bar ... + + // + int lastBarIndex = bar_index + 1; + bool isFirstBar = + startCalculationForLastBars > 0 + ? bar_index == startCalculationForLastBars + : bar_index == ratesTotal; + + // + double iLow = low[bar_index]; + double iHigh = high[bar_index]; + double iClose = close[bar_index]; + + // + // FAST ... + + // + double iFast = fastBuffer[bar_index]; + + // + double iFastState = + iLow > iFast + ? bullishState + : iHigh < iFast + ? bearishState + : neuturalState; + double iFastColor = hideColorIDX; + if (showFast) + { + // + if (applyColor) + { + // + iFastColor = + iFastState == bullishState + ? bullishColorIDX + : iFastState == bearishState + ? bearishColorIDX + : neuturalColorIDX; + } + else + { + iFastColor = bullishColorIDX; + } + } + fastColorBuffer[bar_index] = iFastColor; + fastStateBuffer[bar_index] = iFastState; + + // + // MEDIUM ... + + // + double iMedium = mediumBuffer[bar_index]; + + // + double iMediumState = + iLow > iMedium + ? bullishState + : iHigh < iMedium + ? bearishState + : neuturalState; + double iMediumColor = hideColorIDX; + if (showMedium) + { + // + if (applyColor) + { + // + iMediumColor = + iMediumState == bullishState + ? bullishColorIDX + : iMediumState == bearishState + ? bearishColorIDX + : neuturalColorIDX; + } + else + { + iMediumColor = bullishColorIDX; + } + } + mediumColorBuffer[bar_index] = iMediumColor; + mediumStateBuffer[bar_index] = iMediumState; + + // + // SLOW ... + + // + double iSlow = slowBuffer[bar_index]; + + // + double iSlowState = + iLow > iSlow + ? bullishState + : iHigh < iSlow + ? bearishState + : neuturalState; + double iSlowColor = hideColorIDX; + if (showSlow) + { + // + if (applyColor) + { + // + iSlowColor = + iSlowState == bullishState + ? bullishColorIDX + : iSlowState == bearishState + ? bearishColorIDX + : neuturalColorIDX; + } + else + { + iSlowColor = bullishColorIDX; + } + } + slowColorBuffer[bar_index] = iSlowColor; + slowStateBuffer[bar_index] = iSlowState; +} + +// \ No newline at end of file diff --git a/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xatr.mq5 b/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xatr.mq5 new file mode 100644 index 0000000..08dbc82 --- /dev/null +++ b/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xatr.mq5 @@ -0,0 +1,882 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XATR +// Description: XATR ... +// +// +// 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 XATR Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121 XATR" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +// Market ... +input group "Market"; + +// +input group "RSI Detection"; +input int rsiLength = 14; // Length +input ENUM_X_PRICE rsiPriceType = X_PRICE_CLOSE; // Applied To +input ENUM_X_MA_METHOD rsiSmoothingMethod = X_MA_MODE_SMA; // Smoothing Method; + +// +input group "ATR Detection"; +input int atrLength = 14; // Length +input double atrMultiplier = 1; // Multiplier +input ENUM_X_PRICE atrUpperPriceType = X_PRICE_HIGH; // Upper Zone Applied To +input ENUM_X_PRICE atrLowerPriceType = X_PRICE_LOW; // Lower Zone Applied To +input ENUM_X_MA_METHOD atrSmoothingMethod = X_MA_MODE_SMA; // Smoothing Method + +// +input group "Price Change"; +input int priceChangeSmoothingLength = 14; // Length +input ENUM_X_PRICE priceChangeType = X_PRICE_CLOSE; // Price Type +input ENUM_X_MA_METHOD priceChangeSmoothingMethod = X_MA_MODE_SMA; // Moving Average Moethod + +// +input group "Presentation"; + +// +input int startCalculationForLastBars = 1000; // Calculate Last n Bars + +// +input bool showAtrUpper = true; // Show Upper Zone +input bool showAtrLower = true; // Show Lower Zone +input bool showSmoothedAtrUpper = true; // Show Smoothed Upper Zone +input bool showSmoothedAtrLower = true; // Show Smoothed Lower Zone +input bool showRSIChange = true; // Show RSI Change +input bool showSmoothedRSIChange = true; // ShowSmoothed RSI Change +input bool showPriceChange = true; // Show Price Change +input bool showSmoothedPriceChange = true; // ShowSmoothed Price Change + +// +// Buffers ... + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#property indicator_chart_window + +// +#property indicator_buffers 10 +#property indicator_plots 8 + +// +// ATR ... + +// +// Upper ... + +// +#define atrUpperBufferIndex 0 +double atrUpperBuffer[]; + +#property indicator_label1 "X121 ATRU" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrYellow +#property indicator_style1 STYLE_SOLID +#property indicator_width1 1 + +// +// Lower ... + +// +#define atrLowerBufferIndex 1 +double atrLowerBuffer[]; + +#property indicator_label2 "X121 ATRL" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrYellow +#property indicator_style2 STYLE_SOLID +#property indicator_width2 1 + +// +// ATR Smoothed ... + +// +// Upper ... + +// +#define atrSmoothedUpperBufferIndex 2 +double atrSmoothedUpperBuffer[]; + +#property indicator_label3 "X121 ATRUSM" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrYellow +#property indicator_style3 STYLE_DASH +#property indicator_width3 1 + +// +// Lower ... + +// +#define atrSmoothedLowerBufferIndex 3 +double atrSmoothedLowerBuffer[]; + +#property indicator_label4 "X121 ATRLSM" +#property indicator_type4 DRAW_LINE +#property indicator_color4 clrYellow +#property indicator_style4 STYLE_DASH +#property indicator_width4 1 + +// +// Price Change ... + +// +#define priceChangeBufferIndex 4 +double priceChangeBuffer[]; + +#property indicator_label5 "X121 PCH" +#property indicator_type5 DRAW_LINE +#property indicator_color5 clrOrchid +#property indicator_style5 STYLE_SOLID +#property indicator_width5 1 + +// +// Price Change Smoothed ... + +// +#define priceChangeSmoothedBufferIndex 5 +double priceChangeSmoothedBuffer[]; + +#property indicator_label6 "X121 PCHSM" +#property indicator_type6 DRAW_LINE +#property indicator_color6 clrOrchid +#property indicator_style6 STYLE_SOLID +#property indicator_width6 1 + +// +// RSI Change ... + +// +#define rsiChangeBufferIndex 6 +double rsiChangeBuffer[]; + +#property indicator_label7 "X121 RSICH" +#property indicator_type7 DRAW_LINE +#property indicator_color7 clrCornflowerBlue +#property indicator_style7 STYLE_SOLID +#property indicator_width7 1 + +// +// RSI Change Smoothed ... + +// +#define rsiChangeSmoothedBufferIndex 7 +double rsiChangeSmoothedBuffer[]; + +#property indicator_label8 "X121 RSICHSM" +#property indicator_type8 DRAW_LINE +#property indicator_color8 clrCornflowerBlue +#property indicator_style8 STYLE_SOLID +#property indicator_width8 1 + +// +// Data Buffers ... + +// +int mLastBufferIndex = 7; + +// +// ATR ... + +#define atrBufferIndex mLastBufferIndex + 1 +double atrBuffer[]; + +// +// RSI ... +#define rsiBufferIndex mLastBufferIndex + 2 +double rsiBuffer[]; + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +// RSI Handler ... +int rsiHandler = INVALID_HANDLE; + +// +// ATR Handler ... +int atrHandler = INVALID_HANDLE; + +// +ENUM_APPLIED_PRICE rsiAppliedTo = ToAppliedPrice(rsiPriceType); + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + + // + // RSI ... + rsiHandler = iRSI( + _Symbol, + _Period, + rsiLength, + rsiAppliedTo // + ); + bool isInited = rsiHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // ATR ... + atrHandler = iATR( + _Symbol, + _Period, + atrLength // + ); + isInited = atrHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // 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; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +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(rsiHandler); + IndicatorRelease(atrHandler); +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // 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); + + // + // Fill All Buffers by Zero ... + if (prev_calculated == 0) + { + } + + // + // Validate Calculated Bars ... + + // + // RSI ... + int rsiCalculatedBars = BarsCalculated(rsiHandler); + + // + // ATR ... + int atrCalculatedBars = BarsCalculated(atrHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // RSI ... + rsiCalculatedBars >= maxLength && + // + // ATR ... + atrCalculatedBars >= maxLength + // + ; + if (!isPassedRequiredCalculatedBars) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + + // + // RSI ... + int copiedRsis = CopyBuffer(rsiHandler, 0, 0, limit, rsiBuffer); + + // + // ATR ... + int copiedAtrs = CopyBuffer(atrHandler, 0, 0, limit, atrBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // + // RSI ... + copiedRsis > 0 && + // + // ATR ... + copiedAtrs > 0 + // + ; + if (!isPassedRequiredCopiedItems) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = + // + // RSI ... + rsiLength > 0 && + // + // ATR ... + atrLength > 0 && + atrMultiplier > 0 && + // + priceChangeSmoothingLength > 0 && + // + IsValid(rsiPriceType) && + IsValid(priceChangeType) && + IsValid(atrUpperPriceType) && + IsValid(atrLowerPriceType) + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(rsiLength, atrLength); + result = MathMax(result, priceChangeSmoothingLength); + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // ATR ... + + // + // UPPER ... + ENUM_DRAW_TYPE atrUpperDrawType = showAtrUpper ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(atrUpperBuffer, true); + SetIndexBuffer(atrUpperBufferIndex, atrUpperBuffer, INDICATOR_DATA); + PlotIndexSetDouble(atrUpperBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(atrUpperBufferIndex, PLOT_SHOW_DATA, showAtrUpper); + PlotIndexSetInteger(atrUpperBufferIndex, PLOT_DRAW_TYPE, atrUpperDrawType); + + // + // LOWER ... + ENUM_DRAW_TYPE atrLowerDrawType = showAtrLower ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(atrLowerBuffer, true); + SetIndexBuffer(atrLowerBufferIndex, atrLowerBuffer, INDICATOR_DATA); + PlotIndexSetDouble(atrLowerBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(atrLowerBufferIndex, PLOT_SHOW_DATA, showAtrLower); + PlotIndexSetInteger(atrLowerBufferIndex, PLOT_DRAW_TYPE, atrLowerDrawType); + + // + // ATR Smoothed ... + + // + // UPPER ... + ENUM_DRAW_TYPE atrSmoothedUpperDrawType = showSmoothedAtrUpper ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(atrSmoothedUpperBuffer, true); + SetIndexBuffer(atrSmoothedUpperBufferIndex, atrSmoothedUpperBuffer, INDICATOR_DATA); + PlotIndexSetDouble(atrSmoothedUpperBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(atrSmoothedUpperBufferIndex, PLOT_SHOW_DATA, showSmoothedAtrUpper); + PlotIndexSetInteger(atrSmoothedUpperBufferIndex, PLOT_DRAW_TYPE, atrSmoothedUpperDrawType); + + // + // LOWER ... + ENUM_DRAW_TYPE atrSmoothedLowerDrawType = showSmoothedAtrLower ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(atrSmoothedLowerBuffer, true); + SetIndexBuffer(atrSmoothedLowerBufferIndex, atrSmoothedLowerBuffer, INDICATOR_DATA); + PlotIndexSetDouble(atrSmoothedLowerBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(atrSmoothedLowerBufferIndex, PLOT_SHOW_DATA, showSmoothedAtrLower); + PlotIndexSetInteger(atrSmoothedLowerBufferIndex, PLOT_DRAW_TYPE, atrSmoothedLowerDrawType); + + // + // PriceChange ... + ENUM_DRAW_TYPE priceChangeDrawType = showPriceChange ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(priceChangeBuffer, true); + SetIndexBuffer(priceChangeBufferIndex, priceChangeBuffer, INDICATOR_DATA); + PlotIndexSetDouble(priceChangeBufferIndex, PLOT_EMPTY_VALUE, 0.0); + PlotIndexSetInteger(priceChangeBufferIndex, PLOT_SHOW_DATA, showPriceChange); + PlotIndexSetInteger(priceChangeBufferIndex, PLOT_DRAW_TYPE, priceChangeDrawType); + + // + // PriceChange Smoothed ... + ENUM_DRAW_TYPE priceChangeSmoothedaDrawType = showSmoothedPriceChange ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(priceChangeSmoothedBuffer, true); + SetIndexBuffer(priceChangeSmoothedBufferIndex, priceChangeSmoothedBuffer, INDICATOR_DATA); + PlotIndexSetDouble(priceChangeSmoothedBufferIndex, PLOT_EMPTY_VALUE, 0.0); + PlotIndexSetInteger(priceChangeSmoothedBufferIndex, PLOT_SHOW_DATA, showSmoothedPriceChange); + PlotIndexSetInteger(priceChangeSmoothedBufferIndex, PLOT_DRAW_TYPE, priceChangeSmoothedaDrawType); + + // + // RSIChange ... + ENUM_DRAW_TYPE rsiChangeDrawType = showRSIChange ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(rsiChangeBuffer, true); + SetIndexBuffer(rsiChangeBufferIndex, rsiChangeBuffer, INDICATOR_DATA); + PlotIndexSetDouble(rsiChangeBufferIndex, PLOT_EMPTY_VALUE, 0.0); + PlotIndexSetInteger(rsiChangeBufferIndex, PLOT_SHOW_DATA, showRSIChange); + PlotIndexSetInteger(rsiChangeBufferIndex, PLOT_DRAW_TYPE, rsiChangeDrawType); + + // + // RSIChangeMa ... + ENUM_DRAW_TYPE rsiChangeMaDrawType = showSmoothedRSIChange ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(rsiChangeSmoothedBuffer, true); + SetIndexBuffer(rsiChangeSmoothedBufferIndex, rsiChangeSmoothedBuffer, INDICATOR_DATA); + PlotIndexSetDouble(rsiChangeSmoothedBufferIndex, PLOT_EMPTY_VALUE, 0.0); + PlotIndexSetInteger(rsiChangeSmoothedBufferIndex, PLOT_SHOW_DATA, showSmoothedRSIChange); + PlotIndexSetInteger(rsiChangeSmoothedBufferIndex, PLOT_DRAW_TYPE, rsiChangeMaDrawType); + + // + // Data Buffers ... + + // + // ATR ... + ArraySetAsSeries(atrBuffer, true); + SetIndexBuffer(atrBufferIndex, atrBuffer, INDICATOR_CALCULATIONS); + + // + // RSI ... + ArraySetAsSeries(rsiBuffer, true); + SetIndexBuffer(rsiBufferIndex, rsiBuffer, INDICATOR_CALCULATIONS); +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + // + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); + IndicatorSetInteger(INDICATOR_DIGITS, 2); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +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[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + // + // bool canCalculate = true; + bool canCalculate = + barsLimit == 0 || + bar_index <= barsLimit; + if (canCalculate) + { + // + CalculateAtrZones( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low // + ); + } + else + { + FillBuffersZero(bar_index); + } +} + +// +// Custom ... + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + rsiBuffer[barIndex] = 0; + atrBuffer[barIndex] = 0; + atrUpperBuffer[barIndex] = 0; + atrLowerBuffer[barIndex] = 0; + rsiChangeBuffer[barIndex] = 0; + priceChangeBuffer[barIndex] = 0; + atrSmoothedUpperBuffer[barIndex] = 0; + atrSmoothedLowerBuffer[barIndex] = 0; + rsiChangeSmoothedBuffer[barIndex] = 0; + priceChangeSmoothedBuffer[barIndex] = 0; +} + +/** + * Calculate ATR Zones ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + */ +void CalculateAtrZones( + 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 points = GetPoints(_Symbol); + + // + // ATR Calculations ... + double iAtr = atrBuffer[bar_index]; + double iMultiPliedAtr = iAtr * atrMultiplier; + + // + // Select Upper Price ... + double iUpperPrice = GetAppliedPrice( + atrUpperPriceType, + open, + high, + low, + close, + bar_index // + ); + + // + // Select Lower Price ... + double iLowerPrice = GetAppliedPrice( + atrLowerPriceType, + open, + high, + low, + close, + bar_index // + ); + + // + // Calculate Atrs ... + + // + double iAtrUpper = iUpperPrice + iMultiPliedAtr; + double iAtrLower = iLowerPrice - iMultiPliedAtr; + + // + atrUpperBuffer[bar_index] = iAtrUpper; + atrLowerBuffer[bar_index] = iAtrLower; + + // + bool canSmoothAtr = atrSmoothingMethod != X_MA_MODE_NONE; + if (canSmoothAtr) + { + // + // Upper ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + atrLength, + atrUpperBuffer, + atrSmoothedUpperBuffer, + atrSmoothingMethod // + ); + + // + // Lower ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + atrLength, + atrLowerBuffer, + atrSmoothedLowerBuffer, + atrSmoothingMethod // + ); + } + else + { + // + atrSmoothedUpperBuffer[bar_index] = iAtrUpper; + atrSmoothedLowerBuffer[bar_index] = iAtrLower; + } + + // + // RSI Change Calculations ... + + // + double iRsi = rsiBuffer[bar_index]; + double iRsiP = rsiBuffer[bar_index + 1]; + double iRsiPrice = GetAppliedPrice( + rsiPriceType, + open, + high, + low, + close, + bar_index // + ); + + // + double iRsiChanged = iRsi - iRsiP; + double iRsiPointsChanged = iRsiChanged / points; + + // + double iRChange = iRsiPrice + (iRsiChanged * points); + rsiChangeBuffer[bar_index] = iRChange; + + // + bool canSmoothRsi = rsiSmoothingMethod != X_MA_MODE_NONE; + if (canSmoothRsi) + { + // + // Upper ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + atrLength, + rsiChangeBuffer, + rsiChangeSmoothedBuffer, + rsiSmoothingMethod // + ); + } + else + { + rsiChangeSmoothedBuffer[bar_index] = iRChange; + } + + // + // PRICE Change Calculation ... + + // + double iPChangePrice = GetAppliedPrice( + priceChangeType, + open, + high, + low, + close, + bar_index // + ); + double iPPChangePrice = GetAppliedPrice( + priceChangeType, + open, + high, + low, + close, + bar_index + 1 // + ); + + // + double iPriceChange = iPChangePrice - iPPChangePrice; + double iPricePointsChanged = iPriceChange / points; + double iVolatilityChange = iPriceChange / iAtr; + + // + double iPChange = iPChangePrice + (iPricePointsChanged * points); + priceChangeBuffer[bar_index] = iPChange; + + // + bool canSmoothPriceChange = priceChangeSmoothingMethod != X_MA_MODE_NONE; + if (canSmoothPriceChange) + { + // + // Upper ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + atrLength, + priceChangeBuffer, + priceChangeSmoothedBuffer, + priceChangeSmoothingMethod // + ); + } + else + { + priceChangeSmoothedBuffer[bar_index] = iPChange; + } +} + +// \ No newline at end of file diff --git a/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xca.mq5 b/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xca.mq5 new file mode 100644 index 0000000..7e1ec60 --- /dev/null +++ b/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xca.mq5 @@ -0,0 +1,2601 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XCA +// Description: XCA ... +// +// +// 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 XCA Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121 XCA" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +input group "Market"; + +// +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 "Boundary Detection"; +input ENUM_SERIESMODE hhMode = MODE_HIGH; // Highest High Calculation Method +input ENUM_SERIESMODE llMode = MODE_LOW; // Lowest Low Calculation Method + +// +input group "Fibo Levels"; +input ENUM_X_FIBO_LEVELS fiboLevel1 = X_FIBO_LEVEL_236; // Fibo Level 1 +input ENUM_X_FIBO_LEVELS fiboLevel2 = X_FIBO_LEVEL_382; // Fibo Level 2 +input ENUM_X_FIBO_LEVELS fiboLevel3 = X_FIBO_LEVEL_500; // Fibo Level 3 +input ENUM_X_FIBO_LEVELS fiboLevel4 = X_FIBO_LEVEL_618; // Fibo Level 4 +input ENUM_X_FIBO_LEVELS fiboLevel5 = X_FIBO_LEVEL_764; // Fibo Level 5 + +// +input group "Sar Detection"; +input double sarStep = 0.02; // Step +input double sarMax = 0.2; // Maximum + +// +// KI ... +input group "KI"; +input int kiLength = 26; // KI Length + +// +// VIDYA ... +// Variable Index Dynamic Average ... +input group "VIDYA"; +input int vidyaCMOLength = 20; // CMO (Candle Momentum) Length +input int vidyaEMALength = 14; // EMA Length +input ENUM_APPLIED_PRICE vidyaAppliedTo = PRICE_CLOSE; // Applied To + +// +// Manalyser ... +input group "Manalyser"; +input int manalyserLength = 14; // Length +input ENUM_MA_METHOD manalyserMethod = MODE_SMA; // Method + +// +input group "Swing Detection"; +input int swingLength = 5; // Length + +// +input group "Support and Resistance"; +input int supResSmoothingLength = 7; // Smoothing Length +input ENUM_X_MA_METHOD supResSmoothingMode = X_MA_MODE_NONE; // Smoothing Method + +// +// Presentation ... +input group "Presentation"; + +// +input int startCalculationForLastBars = 1000; // Calculate Last n Bars + +// +input bool showSar = true; // Show Sar +input bool showKI = true; // Show KI +input bool showTKI = true; // Show KI Trend +input bool showMAH = true; // Show MAH +input bool showMAL = true; // Show MAL +input bool showMAC = true; // Show MAC +input bool showVidya = true; // Show Vidya +input bool showTrend = true; // Show Trend +input bool showSwings = true; // Show Swings +input bool showFiboLevel1 = true; // Show Fibo Level 1 +input bool showFiboLevel2 = true; // Show Fibo Level 2 +input bool showFiboLevel3 = true; // Show Fibo Level 3 +input bool showFiboLevel4 = true; // Show Fibo Level 4 +input bool showFiboLevel5 = true; // Show Fibo Level 5 +input bool showPeaksAndVales = true; // Show Peaks And Vales +input bool showPeakAndValeGolden = true; // Show Peak and Vale Golden +input bool showSupportAndResistance = true; // Show Support and Resistance + +// +bool showShortCycle = false; // Show Short Cycle +bool showMediumCycle = false; // Show Medium Cycle +bool showLongCycle = false; // Show Long Cycle +bool showHindCycle = false; // Show Hind Cycle + +// +int sarArrowCode = 159; // Parabolic Sar Arrow Code +int peakArrowCode = 159; // Peaks Arrow Code +int valeArrowCode = 159; // Vales Arrow Code +int swingLowArrowCode = 225; // Swing Low Arrow Code +int swingHighArrowCode = 226; // Swing High Arrow Code + +// +// Buffers ... + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#define bullishState 1 +#define neuturalState 0 +#define bearishState -1 + +// +#define emptyValue 0.0 + +// +#property indicator_chart_window + +// +#property indicator_buffers 39 +#property indicator_plots 29 + +// +// Plot Buffers ... + +// +// SHORT ... + +// +#define sHHBufferIndex 0 +double sHHBuffer[]; + +// +#property indicator_label1 "SH" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrGray +#property indicator_style1 STYLE_DOT +#property indicator_width1 1 + +// +#define sLLBufferIndex 1 +double sLLBuffer[]; + +// +#property indicator_label2 "SL" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrGray +#property indicator_style2 STYLE_DOT +#property indicator_width2 1 + +// +// MEDIUM ... + +// +#define mHHBufferIndex 2 +double mHHBuffer[]; + +// +#property indicator_label3 "MH" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrIndigo +#property indicator_style3 STYLE_DOT +#property indicator_width3 1 + +// +#define mLLBufferIndex 3 +double mLLBuffer[]; + +// +#property indicator_label4 "ML" +#property indicator_type4 DRAW_LINE +#property indicator_color4 clrIndigo +#property indicator_style4 STYLE_DOT +#property indicator_width4 1 + +// +// LONG ... + +// +#define lHHBufferIndex 4 +double lHHBuffer[]; + +// +#property indicator_label5 "LH" +#property indicator_type5 DRAW_LINE +#property indicator_color5 clrGoldenrod +#property indicator_style5 STYLE_DOT +#property indicator_width5 1 + +// +#define lLLBufferIndex 5 +double lLLBuffer[]; + +// +#property indicator_label6 "LL" +#property indicator_type6 DRAW_LINE +#property indicator_color6 clrGoldenrod +#property indicator_style6 STYLE_DOT +#property indicator_width6 1 + +// +// HIND ... + +// +#define hHHBufferIndex 6 +double hHHBuffer[]; + +// +#property indicator_label7 "HH" +#property indicator_type7 DRAW_LINE +#property indicator_color7 clrBrown +#property indicator_style7 STYLE_DOT +#property indicator_width7 1 + +// +#define hLLBufferIndex 7 +double hLLBuffer[]; + +// +#property indicator_label8 "HL" +#property indicator_type8 DRAW_LINE +#property indicator_color8 clrBrown +#property indicator_style8 STYLE_DOT +#property indicator_width8 1 + +// +// SUPPORT ... + +// +#define supportBufferIndex 8 +double supportBuffer[]; + +// +#property indicator_label9 "SUPPORT" +#property indicator_type9 DRAW_LINE +#property indicator_color9 clrLime +#property indicator_style9 STYLE_SOLID +#property indicator_width9 1 + +// +// RESISTANCE ... + +// +#define resistanceBufferIndex 9 +double resistanceBuffer[]; + +// +#property indicator_label10 "RESISTANCE" +#property indicator_type10 DRAW_LINE +#property indicator_color10 clrRed +#property indicator_style10 STYLE_SOLID +#property indicator_width10 1 + +// +// PEAKS ... + +// +#define peakBufferIndex 10 +double peakBuffer[]; + +// +#property indicator_label11 "PEAK" +#property indicator_type11 DRAW_ARROW +#property indicator_color11 clrMagenta +#property indicator_width11 1 + +// +// PEAKS Golden ... + +// +#define peakGoldenBufferIndex 11 +double peakGoldenBuffer[]; + +// +#property indicator_label12 "PEAK Golden" +#property indicator_type12 DRAW_LINE +#property indicator_color12 clrMagenta +#property indicator_style2 STYLE_DOT +#property indicator_width12 1 + +// +// VALES ... + +// +#define valeBufferIndex 12 +double valeBuffer[]; + +// +#property indicator_label13 "VALE" +#property indicator_type13 DRAW_ARROW +#property indicator_color13 clrAqua +#property indicator_width13 1 + +// +// VALE Golden ... + +// +#define valeGoldenBufferIndex 13 +double valeGoldenBuffer[]; + +// +#property indicator_label14 "VALES Golden" +#property indicator_type14 DRAW_LINE +#property indicator_color14 clrAqua +#property indicator_style4 STYLE_DOT +#property indicator_width14 1 + +// +// FIBO Level 1 + +// +#define fiboLevel1BufferIndex 14 +double fiboLevel1Buffer[]; + +// +#property indicator_label15 "Fibo L1" +#property indicator_type15 DRAW_LINE +#property indicator_color15 clrGold +#property indicator_style15 STYLE_DOT +#property indicator_width15 1 + +// +// FIBO Level 2 + +// +#define fiboLevel2BufferIndex 15 +double fiboLevel2Buffer[]; + +// +#property indicator_label16 "Fibo L2" +#property indicator_type16 DRAW_LINE +#property indicator_color16 clrGold +#property indicator_style16 STYLE_DOT +#property indicator_width16 1 + +// +// FIBO Level 3 + +// +#define fiboLevel3BufferIndex 16 +double fiboLevel3Buffer[]; + +// +#property indicator_label17 "Fibo L3" +#property indicator_type17 DRAW_LINE +#property indicator_color17 clrYellow +#property indicator_style17 STYLE_DASH +#property indicator_width17 1 + +// +// FIBO Level 4 + +// +#define fiboLevel4BufferIndex 17 +double fiboLevel4Buffer[]; + +// +#property indicator_label18 "Fibo L4" +#property indicator_type18 DRAW_LINE +#property indicator_color18 clrGold +#property indicator_style18 STYLE_DOT +#property indicator_width18 1 + +// +// FIBO Level 5 + +// +#define fiboLevel5BufferIndex 18 +double fiboLevel5Buffer[]; + +// +#property indicator_label19 "Fibo L5" +#property indicator_type19 DRAW_LINE +#property indicator_color19 clrGold +#property indicator_style19 STYLE_DOT +#property indicator_width19 1 + +// +// SAR ... + +// +#define sarBufferIndex 19 +double sarBuffer[]; + +// +#property indicator_label20 "SAR" +#property indicator_type20 DRAW_ARROW +#property indicator_color20 clrYellow +#property indicator_width20 1 + +// +// TREND ... + +// +#define trendBufferIndex 20 +#define trendBufferPlotIndex 20 +double trendBuffer[]; + +// +#define trendColorBufferIndex 21 +double trendColorBuffer[]; + +// +#property indicator_label21 "TRND" +#property indicator_type21 DRAW_COLOR_LINE +#property indicator_color21 CLR_NONE, clrAqua, clrMagenta, clrGray +#property indicator_style21 STYLE_DASH +#property indicator_width21 2 + +// +// KI ... + +// +#define kiBufferIndex 22 +#define kiBufferPlotIndex 21 +double kiBuffer[]; + +// +#define kiColorBufferIndex 23 +double kiColorBuffer[]; + +// +#property indicator_label22 "KI" +#property indicator_type22 DRAW_COLOR_LINE +#property indicator_color22 CLR_NONE, clrGreen, clrRed, clrGray +#property indicator_style22 STYLE_DASHDOTDOT +#property indicator_width22 2 + +// +// SWING Low ... + +// +#define swingLowBufferIndex 24 +#define swingLowBufferPlotIndex 22 +double swingLowBuffer[]; + +// +#property indicator_label23 "SWL" +#property indicator_type23 DRAW_ARROW +#property indicator_color23 clrGreen +#property indicator_width23 1 + +// +// SWING High ... + +// +#define swingHighBufferIndex 25 +#define swingHighBufferPlotIndex 23 +double swingHighBuffer[]; + +// +#property indicator_label24 "SWH" +#property indicator_type24 DRAW_ARROW +#property indicator_color24 clrRed +#property indicator_width24 1 + +// +// TKI ... + +// +#define tkiBufferIndex 26 +#define tkiBufferPlotIndex 24 +double tkiBuffer[]; + +// +#define tkiColorBufferIndex 27 +double tkiColorBuffer[]; + +// +#property indicator_label25 "TKI" +#property indicator_type25 DRAW_COLOR_LINE +#property indicator_color25 CLR_NONE, clrGreen, clrRed, clrGray +#property indicator_style25 STYLE_DASHDOTDOT +#property indicator_width25 2 + +// +// VIDYA ... + +// +#define vidyaBufferIndex 28 +#define vidyaBufferPlotIndex 25 +double vidyaBuffer[]; + +// +#define vidyaColorBufferIndex 29 +double vidyaColorBuffer[]; + +// +#property indicator_label26 "VIDYA" +#property indicator_type26 DRAW_COLOR_LINE +#property indicator_color26 CLR_NONE, clrAqua, clrMagenta, clrGray +#property indicator_style26 STYLE_SOLID +#property indicator_width26 1 + +// +// MAH ... + +// +#define mahBufferIndex 30 +#define mahBufferPlotIndex 26 +double mahBuffer[]; + +// +#property indicator_label27 "MAH" +#property indicator_type27 DRAW_LINE +#property indicator_color27 clrMagenta +#property indicator_style27 STYLE_SOLID +#property indicator_width27 1 + +// +// MAL ... + +// +#define malBufferIndex 31 +#define malBufferPlotIndex 27 +double malBuffer[]; + +// +#property indicator_label28 "MAL" +#property indicator_type28 DRAW_LINE +#property indicator_color28 clrAqua +#property indicator_style28 STYLE_SOLID +#property indicator_width28 1 + +// +// MAC ... + +// +#define macBufferIndex 32 +#define macBufferPlotIndex 28 +double macBuffer[]; + +// +#property indicator_label29 "MAC" +#property indicator_type29 DRAW_LINE +#property indicator_color29 clrYellow +#property indicator_style29 STYLE_SOLID +#property indicator_width29 1 + +// +// Data Buffers ... + +#define mLastBufferIndex 32 + +// +#define trendStateBufferIndex mLastBufferIndex + 1 +double trendStateBuffer[]; + +// +#define kiStateBufferIndex mLastBufferIndex + 2 +double kiStateBuffer[]; + +// +#define tkiStateBufferIndex mLastBufferIndex + 3 +double tkiStateBuffer[]; + +// +#define vidyaStateBufferIndex mLastBufferIndex + 4 +double vidyaStateBuffer[]; + +// +#define supBufferIndex mLastBufferIndex + 5 +double supBuffer[]; + +// +#define resBufferIndex mLastBufferIndex + 6 +double resBuffer[]; + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int firstBarIndex; + +// +int maxLength; + +// +// SAR Handler ... +int sarHandler = INVALID_HANDLE; + +// +// TREND Handler ... +int tkiHandler = INVALID_HANDLE; +int vidyaHandler = INVALID_HANDLE; +int trendHandler = INVALID_HANDLE; + +// +// Manalyser Handlers ... +int mahHandler = INVALID_HANDLE; +int malHandler = INVALID_HANDLE; +int macHandler = INVALID_HANDLE; + +// +// XMarketCycle sc; +int mSCLength = 0; +ENUM_TIMEFRAMES mSCPeriod = NULL; + +// +// XMarketCycle mc; +int mMCLength = 0; +ENUM_TIMEFRAMES mMCPeriod = NULL; + +// +// XMarketCycle lc; +int mLCLength = 0; +ENUM_TIMEFRAMES mLCPeriod = NULL; + +// +// XMarketCycle hc; +int mHCLength = 0; +ENUM_TIMEFRAMES mHCPeriod = NULL; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + if (!InitMarketCycles()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + + // + // SAR ... + sarHandler = iSAR( + _Symbol, + _Period, + sarStep, + sarMax // + ); + bool isInited = sarHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // TKI ... + tkiHandler = iMA( + _Symbol, + _Period, + kiLength, + 0, + MODE_SMA, + PRICE_MEDIAN // + ); + isInited = tkiHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // VIDYA ... + vidyaHandler = iVIDyA( + _Symbol, + _Period, + vidyaCMOLength, + vidyaEMALength, + 0, + vidyaAppliedTo // + ); + isInited = vidyaHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // TREND ... + trendHandler = iMA( + _Symbol, + _Period, + mHCLength, + 0, + MODE_SMA, + PRICE_CLOSE // + ); + isInited = trendHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // MANALYSE ... + + // + // MAH ... + mahHandler = iMA( + _Symbol, + _Period, + manalyserLength, + 0, + manalyserMethod, + PRICE_HIGH // + ); + isInited = mahHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // MAL ... + malHandler = iMA( + _Symbol, + _Period, + manalyserLength, + 0, + manalyserMethod, + PRICE_LOW // + ); + isInited = malHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // MAC ... + macHandler = iMA( + _Symbol, + _Period, + manalyserLength, + 0, + manalyserMethod, + PRICE_CLOSE // + ); + isInited = macHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // 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; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +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(sarHandler); + IndicatorRelease(tkiHandler); + IndicatorRelease(vidyaHandler); + IndicatorRelease(trendHandler); +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // 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); + + // + // Validate Calculated Bars ... + + // + // SAR ... + int sarCalculatedBars = BarsCalculated(sarHandler); + + // + // TKI ... + int tkiCalculatedBars = BarsCalculated(tkiHandler); + + // + // VIDYA ... + int vidyaCalculatedBars = BarsCalculated(vidyaHandler); + + // + // TREND ... + int trendCalculatedBars = BarsCalculated(trendHandler); + + // + // MANALYSER ... + + // + // MAH ... + int mahCalculatedBars = BarsCalculated(mahHandler); + + // + // MAL ... + int malCalculatedBars = BarsCalculated(malHandler); + + // + // MAC ... + int macCalculatedBars = BarsCalculated(macHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // SAR ... + sarCalculatedBars >= maxLength && + // + // TKI ... + tkiCalculatedBars >= maxLength && + // + // VIDYA ... + vidyaCalculatedBars >= maxLength && + // + // TREND ... + trendCalculatedBars >= maxLength && + // + // MANALYSER ... + // MAH ... + mahCalculatedBars >= maxLength && + // MAL ... + malCalculatedBars >= maxLength && + // MAC ... + macCalculatedBars >= maxLength + // + ; + if (!isPassedRequiredCalculatedBars) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + + // + // SAR ... + int copiedSars = CopyBuffer(sarHandler, 0, 0, limit, sarBuffer); + + // + // TKI ... + int copiedTKIs = CopyBuffer(tkiHandler, 0, 0, limit, tkiBuffer); + + // + // TKI ... + int copiedVidyas = CopyBuffer(vidyaHandler, 0, 0, limit, vidyaBuffer); + + // + // TREND ... + int copiedTrends = CopyBuffer(trendHandler, MAIN_LINE, 0, limit + 1, trendBuffer); + + // + // MANALYSER ... + + // + // MAH ... + int copiedMahs = CopyBuffer(mahHandler, 0, 0, limit, mahBuffer); + + // + // MAL ... + int copiedMals = CopyBuffer(malHandler, 0, 0, limit, malBuffer); + + // + // MAC ... + int copiedMacs = CopyBuffer(macHandler, 0, 0, limit, macBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // SAR ... + copiedSars >= limit && + // + // TKI ... + copiedTKIs >= limit && + // + // VIDYA ... + copiedVidyas >= limit && + // + // TREND ... + copiedTrends >= limit && + // + // MANALYSER ... + // MAH ... + copiedMahs >= limit && + // MAL ... + copiedMals >= limit && + // MAC ... + copiedMacs >= limit + // + ; + if (!isPassedRequiredCopiedItems) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + result = + // + // SAR ... + sarMax > 0 && + sarStep > 0 && + kiLength > 0 && + swingLength > 0 && + sarMax > sarStep && + vidyaEMALength > 0 && + vidyaCMOLength > 0 && + manalyserLength > 0 && + // + // XCA ... + (IsValid(scMethod, scPeriod) && + IsValid(mcMethod, mcPeriod) && + IsValid(lcMethod, lcPeriod) && + IsValid(hcMethod, hcPeriod)) + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(kiLength, swingLength); + result = MathMax(result, vidyaCMOLength); + result = MathMax(result, vidyaEMALength); + result = MathMax(result, manalyserLength); + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + + // + // SHORT ... + + // + ENUM_DRAW_TYPE sDrawType = showShortCycle ? DRAW_LINE : DRAW_NONE; + + // + // HH ... + + // + ArraySetAsSeries(sHHBuffer, true); + SetIndexBuffer(sHHBufferIndex, sHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(sHHBufferIndex, PLOT_SHOW_DATA, showShortCycle); + PlotIndexSetInteger(sHHBufferIndex, PLOT_DRAW_TYPE, sDrawType); + + // + PlotIndexSetDouble(sHHBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LL ... + + // + ArraySetAsSeries(sLLBuffer, true); + SetIndexBuffer(sLLBufferIndex, sLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(sLLBufferIndex, PLOT_SHOW_DATA, showShortCycle); + PlotIndexSetInteger(sLLBufferIndex, PLOT_DRAW_TYPE, sDrawType); + + // + PlotIndexSetDouble(sLLBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // MEDIUM ... + + // + ENUM_DRAW_TYPE mDrawType = showMediumCycle ? DRAW_LINE : DRAW_NONE; + + // + // HH ... + + // + ArraySetAsSeries(mHHBuffer, true); + SetIndexBuffer(mHHBufferIndex, mHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(mHHBufferIndex, PLOT_SHOW_DATA, showMediumCycle); + PlotIndexSetInteger(mHHBufferIndex, PLOT_DRAW_TYPE, mDrawType); + + // + PlotIndexSetDouble(mHHBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LL ... + + // + ArraySetAsSeries(mLLBuffer, true); + SetIndexBuffer(mLLBufferIndex, mLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(mLLBufferIndex, PLOT_SHOW_DATA, showMediumCycle); + PlotIndexSetInteger(mLLBufferIndex, PLOT_DRAW_TYPE, mDrawType); + + // + PlotIndexSetDouble(mLLBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LONG ... + + // + ENUM_DRAW_TYPE lDrawType = showLongCycle ? DRAW_LINE : DRAW_NONE; + + // + // HH ... + + // + ArraySetAsSeries(lHHBuffer, true); + SetIndexBuffer(lHHBufferIndex, lHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(lHHBufferIndex, PLOT_SHOW_DATA, showLongCycle); + PlotIndexSetInteger(lHHBufferIndex, PLOT_DRAW_TYPE, lDrawType); + + // + PlotIndexSetDouble(lHHBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LL ... + + // + ArraySetAsSeries(lLLBuffer, true); + SetIndexBuffer(lLLBufferIndex, lLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(lLLBufferIndex, PLOT_SHOW_DATA, showLongCycle); + PlotIndexSetInteger(lLLBufferIndex, PLOT_DRAW_TYPE, lDrawType); + + // + PlotIndexSetDouble(lLLBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // HIND ... + + // + ENUM_DRAW_TYPE hDrawType = showHindCycle ? DRAW_LINE : DRAW_NONE; + + // + // HH ... + + // + ArraySetAsSeries(hHHBuffer, true); + SetIndexBuffer(hHHBufferIndex, hHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(hHHBufferIndex, PLOT_SHOW_DATA, showHindCycle); + PlotIndexSetInteger(hHHBufferIndex, PLOT_DRAW_TYPE, hDrawType); + + // + PlotIndexSetDouble(hHHBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LL ... + + // + ArraySetAsSeries(hLLBuffer, true); + SetIndexBuffer(hLLBufferIndex, hLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(hLLBufferIndex, PLOT_SHOW_DATA, showHindCycle); + PlotIndexSetInteger(hLLBufferIndex, PLOT_DRAW_TYPE, hDrawType); + + // + PlotIndexSetDouble(hLLBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // SUPPORT / RESISTANCE ... + + // + ENUM_DRAW_TYPE supResDrawType = showSupportAndResistance ? DRAW_LINE : DRAW_NONE; + + // + // SUPPORT ... + + // + ArraySetAsSeries(supportBuffer, true); + SetIndexBuffer(supportBufferIndex, supportBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(supportBufferIndex, PLOT_SHOW_DATA, showSupportAndResistance); + PlotIndexSetInteger(supportBufferIndex, PLOT_DRAW_TYPE, supResDrawType); + + // + PlotIndexSetDouble(supportBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // RESISTANCE ... + + // + ArraySetAsSeries(resistanceBuffer, true); + SetIndexBuffer(resistanceBufferIndex, resistanceBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(resistanceBufferIndex, PLOT_SHOW_DATA, showSupportAndResistance); + PlotIndexSetInteger(resistanceBufferIndex, PLOT_DRAW_TYPE, supResDrawType); + + // + PlotIndexSetDouble(resistanceBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // PEAK / VALE ... + + // + ENUM_DRAW_TYPE pvDrawType = showPeaksAndVales ? DRAW_ARROW : DRAW_NONE; + + // + // PEAK ... + + // + ArraySetAsSeries(peakBuffer, true); + SetIndexBuffer(peakBufferIndex, peakBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(peakBufferIndex, PLOT_SHOW_DATA, showPeaksAndVales); + PlotIndexSetInteger(peakBufferIndex, PLOT_DRAW_TYPE, pvDrawType); + + // + PlotIndexSetDouble(peakBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(peakBufferIndex, PLOT_ARROW, peakArrowCode); + + // + // VALE ... + + // + ArraySetAsSeries(valeBuffer, true); + SetIndexBuffer(valeBufferIndex, valeBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(valeBufferIndex, PLOT_SHOW_DATA, showPeaksAndVales); + PlotIndexSetInteger(valeBufferIndex, PLOT_DRAW_TYPE, pvDrawType); + + // + PlotIndexSetDouble(valeBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(valeBufferIndex, PLOT_ARROW, valeArrowCode); + + // + // PV GOLDEN ... + + // + ENUM_DRAW_TYPE pvGoldenDrawType = showPeakAndValeGolden ? DRAW_LINE : DRAW_NONE; + + // + // PEAK Golden ... + + // + ArraySetAsSeries(peakGoldenBuffer, true); + SetIndexBuffer(peakGoldenBufferIndex, peakGoldenBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(peakGoldenBufferIndex, PLOT_SHOW_DATA, showPeakAndValeGolden); + PlotIndexSetInteger(peakGoldenBufferIndex, PLOT_DRAW_TYPE, pvGoldenDrawType); + + // + PlotIndexSetDouble(peakGoldenBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // VALE Golden ... + + // + ArraySetAsSeries(valeGoldenBuffer, true); + SetIndexBuffer(valeGoldenBufferIndex, valeGoldenBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(valeGoldenBufferIndex, PLOT_SHOW_DATA, showPeakAndValeGolden); + PlotIndexSetInteger(valeGoldenBufferIndex, PLOT_DRAW_TYPE, pvGoldenDrawType); + + // + PlotIndexSetDouble(valeGoldenBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // FIBO L1 ... + + // + ENUM_DRAW_TYPE fiboL1DrawType = showFiboLevel1 ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(fiboLevel1Buffer, true); + SetIndexBuffer(fiboLevel1BufferIndex, fiboLevel1Buffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(fiboLevel1BufferIndex, PLOT_SHOW_DATA, showFiboLevel1); + PlotIndexSetInteger(fiboLevel1BufferIndex, PLOT_DRAW_TYPE, fiboL1DrawType); + + // + PlotIndexSetDouble(fiboLevel1BufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // FIBO L2 ... + + // + ENUM_DRAW_TYPE fiboL2DrawType = showFiboLevel2 ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(fiboLevel2Buffer, true); + SetIndexBuffer(fiboLevel2BufferIndex, fiboLevel2Buffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(fiboLevel2BufferIndex, PLOT_SHOW_DATA, showFiboLevel2); + PlotIndexSetInteger(fiboLevel2BufferIndex, PLOT_DRAW_TYPE, fiboL2DrawType); + + // + PlotIndexSetDouble(fiboLevel2BufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // FIBO L3 ... + + // + ENUM_DRAW_TYPE fiboL3DrawType = showFiboLevel3 ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(fiboLevel3Buffer, true); + SetIndexBuffer(fiboLevel3BufferIndex, fiboLevel3Buffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(fiboLevel3BufferIndex, PLOT_SHOW_DATA, showFiboLevel3); + PlotIndexSetInteger(fiboLevel3BufferIndex, PLOT_DRAW_TYPE, fiboL3DrawType); + + // + PlotIndexSetDouble(fiboLevel3BufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // FIBO L4 ... + + // + ENUM_DRAW_TYPE fiboL4DrawType = showFiboLevel4 ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(fiboLevel4Buffer, true); + SetIndexBuffer(fiboLevel4BufferIndex, fiboLevel4Buffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(fiboLevel4BufferIndex, PLOT_SHOW_DATA, showFiboLevel4); + PlotIndexSetInteger(fiboLevel4BufferIndex, PLOT_DRAW_TYPE, fiboL4DrawType); + + // + PlotIndexSetDouble(fiboLevel4BufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // FIBO L5 ... + + // + ENUM_DRAW_TYPE fiboL5DrawType = showFiboLevel5 ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(fiboLevel5Buffer, true); + SetIndexBuffer(fiboLevel5BufferIndex, fiboLevel5Buffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(fiboLevel5BufferIndex, PLOT_SHOW_DATA, showFiboLevel5); + PlotIndexSetInteger(fiboLevel5BufferIndex, PLOT_DRAW_TYPE, fiboL5DrawType); + + // + PlotIndexSetDouble(fiboLevel5BufferIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // SAR ... + + // + ENUM_DRAW_TYPE sarDrawType = showSar ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(sarBuffer, true); + SetIndexBuffer(sarBufferIndex, sarBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(sarBufferIndex, PLOT_SHOW_DATA, showSar); + PlotIndexSetInteger(sarBufferIndex, PLOT_DRAW_TYPE, sarDrawType); + + // + PlotIndexSetDouble(sarBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(sarBufferIndex, PLOT_ARROW, sarArrowCode); + + // + // TREND ... + + // + ENUM_DRAW_TYPE trendDrawType = showTrend ? DRAW_COLOR_LINE : DRAW_NONE; + + // + ArraySetAsSeries(trendBuffer, true); + SetIndexBuffer(trendBufferIndex, trendBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(trendBufferPlotIndex, PLOT_SHOW_DATA, showTrend); + // PlotIndexSetInteger(trendBufferPlotIndex, PLOT_DRAW_TYPE, trendDrawType); + + // + PlotIndexSetDouble(trendBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(trendColorBuffer, true); + SetIndexBuffer(trendColorBufferIndex, trendColorBuffer, INDICATOR_COLOR_INDEX); + + // + // KI ... + + // + ENUM_DRAW_TYPE kiDrawType = showKI ? DRAW_COLOR_LINE : DRAW_NONE; + + // + ArraySetAsSeries(kiBuffer, true); + SetIndexBuffer(kiBufferIndex, kiBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(kiBufferPlotIndex, PLOT_SHOW_DATA, showKI); + // PlotIndexSetInteger(kiBufferPlotIndex, PLOT_DRAW_TYPE, kiDrawType); + + // + PlotIndexSetDouble(kiBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(kiColorBuffer, true); + SetIndexBuffer(kiColorBufferIndex, kiColorBuffer, INDICATOR_COLOR_INDEX); + + // + // TKI ... + + // + ENUM_DRAW_TYPE tkiDrawType = showTKI ? DRAW_COLOR_LINE : DRAW_NONE; + + // + ArraySetAsSeries(tkiBuffer, true); + SetIndexBuffer(tkiBufferIndex, tkiBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(tkiBufferPlotIndex, PLOT_SHOW_DATA, showKI); + // PlotIndexSetInteger(tkiBufferPlotIndex, PLOT_DRAW_TYPE, kiDrawType); + + // + PlotIndexSetDouble(tkiBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(tkiColorBuffer, true); + SetIndexBuffer(tkiColorBufferIndex, tkiColorBuffer, INDICATOR_COLOR_INDEX); + + // + // VIDYA ... + + // + ENUM_DRAW_TYPE vidyaDrawType = showVidya ? DRAW_COLOR_LINE : DRAW_NONE; + + // + ArraySetAsSeries(vidyaBuffer, true); + SetIndexBuffer(vidyaBufferIndex, vidyaBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(vidyaBufferPlotIndex, PLOT_SHOW_DATA, showKI); + // PlotIndexSetInteger(vidyaBufferPlotIndex, PLOT_DRAW_TYPE, vidyaDrawType); + + // + PlotIndexSetDouble(vidyaBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(vidyaColorBuffer, true); + SetIndexBuffer(vidyaColorBufferIndex, vidyaColorBuffer, INDICATOR_COLOR_INDEX); + + // + // SWINGS ... + + // + ENUM_DRAW_TYPE swingDrawType = showSwings ? DRAW_ARROW : DRAW_NONE; + + // + // SWING Low ... + + // + ArraySetAsSeries(swingLowBuffer, true); + SetIndexBuffer(swingLowBufferIndex, swingLowBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(swingLowBufferPlotIndex, PLOT_SHOW_DATA, showSwings); + PlotIndexSetInteger(swingLowBufferPlotIndex, PLOT_DRAW_TYPE, swingDrawType); + + // + PlotIndexSetDouble(swingLowBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(swingLowBufferPlotIndex, PLOT_ARROW, swingLowArrowCode); + + // + // SWING High ... + + // + ArraySetAsSeries(swingHighBuffer, true); + SetIndexBuffer(swingHighBufferIndex, swingHighBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(swingHighBufferPlotIndex, PLOT_SHOW_DATA, showSwings); + PlotIndexSetInteger(swingHighBufferPlotIndex, PLOT_DRAW_TYPE, swingDrawType); + + // + PlotIndexSetDouble(swingHighBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(swingHighBufferPlotIndex, PLOT_ARROW, swingHighArrowCode); + + // + // MANALYSER ... + + // + // MAH ... + + // + ENUM_DRAW_TYPE mahDrawType = showMAH ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(mahBuffer, true); + SetIndexBuffer(mahBufferIndex, mahBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(mahBufferPlotIndex, PLOT_SHOW_DATA, showMAH); + PlotIndexSetInteger(mahBufferPlotIndex, PLOT_DRAW_TYPE, mahDrawType); + + // + PlotIndexSetDouble(mahBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // MAL ... + + // + ENUM_DRAW_TYPE malDrawType = showMAL ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(malBuffer, true); + SetIndexBuffer(malBufferIndex, malBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(malBufferPlotIndex, PLOT_SHOW_DATA, showMAL); + PlotIndexSetInteger(malBufferPlotIndex, PLOT_DRAW_TYPE, malDrawType); + + // + PlotIndexSetDouble(malBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // MAC ... + + // + ENUM_DRAW_TYPE macDrawType = showMAC ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(macBuffer, true); + SetIndexBuffer(macBufferIndex, macBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(macBufferPlotIndex, PLOT_SHOW_DATA, showMAC); + PlotIndexSetInteger(macBufferPlotIndex, PLOT_DRAW_TYPE, mahDrawType); + + // + PlotIndexSetDouble(macBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // Data Buffers ... + + // + ArraySetAsSeries(trendStateBuffer, true); + SetIndexBuffer(trendStateBufferIndex, trendStateBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(kiStateBuffer, true); + SetIndexBuffer(kiStateBufferIndex, kiStateBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(tkiStateBuffer, true); + SetIndexBuffer(tkiStateBufferIndex, tkiStateBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(vidyaStateBuffer, true); + SetIndexBuffer(vidyaStateBufferIndex, vidyaStateBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(supBuffer, true); + SetIndexBuffer(supBufferIndex, supBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(resBuffer, true); + SetIndexBuffer(resBufferIndex, resBuffer, INDICATOR_CALCULATIONS); + + // +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + // + IndicatorSetInteger(INDICATOR_DIGITS, _Digits); + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +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[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + if (barsLimit == 0) + { + // + barsLimit = ratesTotal; + firstBarIndex = barsLimit - 1; + } + else + { + // + firstBarIndex = startCalculationForLastBars; + } + + // + // bool canCalculate = true; + bool canCalculate = + bar_index <= barsLimit; + if (canCalculate) + { + // + // Calculate Cycles ... + CalculateCycles(bar_index); + + // + // Calculate Support nad Resistance ... + CalculateValues( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + else + { + FillBuffersZero(bar_index); + } +} + +// +// Custom ... + +/** + * Initial Market Cycles ... + * + * @return ( bool ) + */ +bool InitMarketCycles() +{ + // + bool result = false; + + // + int cPeriodSeconds = PeriodSeconds(_Period); + + // + // Find Cycle Period ... + if (scMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mSCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_SHORT, + _Period // + ); + } + else + { + mSCPeriod = scPeriod; + } + + // + if (IsValid(mSCPeriod)) + { + mSCLength = PeriodSeconds(mSCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (mcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mMCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_MEDIUM, + _Period // + ); + } + else + { + mMCPeriod = mcPeriod; + } + + // + if (IsValid(mMCPeriod)) + { + mMCLength = PeriodSeconds(mMCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (lcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mLCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_LONG, + _Period // + ); + } + else + { + mLCPeriod = lcPeriod; + } + + // + if (IsValid(mLCPeriod)) + { + mLCLength = PeriodSeconds(mLCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (hcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mHCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_HIND, + _Period // + ); + } + else + { + mHCPeriod = hcPeriod; + } + + // + if (IsValid(mHCPeriod)) + { + mHCLength = PeriodSeconds(mHCPeriod) / cPeriodSeconds; + } + + // + result = mSCLength > 0 && + mMCLength > mSCLength && + mLCLength > mMCLength && + mHCLength > mLCLength; + + // + return result; +} + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + // SHORT ... + sHHBuffer[barIndex] = emptyValue; + sLLBuffer[barIndex] = emptyValue; + + // + // MEDIUM ... + mHHBuffer[barIndex] = emptyValue; + mLLBuffer[barIndex] = emptyValue; + + // + // LONG ... + lHHBuffer[barIndex] = emptyValue; + lLLBuffer[barIndex] = emptyValue; + + // + // HIND ... + hHHBuffer[barIndex] = emptyValue; + hLLBuffer[barIndex] = emptyValue; + + // + // SUPPORT / RESISTANCE ... + supBuffer[barIndex] = emptyValue; + resBuffer[barIndex] = emptyValue; + supportBuffer[barIndex] = emptyValue; + resistanceBuffer[barIndex] = emptyValue; + + // + // PEAKS ... + peakBuffer[barIndex] = emptyValue; + peakGoldenBuffer[barIndex] = emptyValue; + + // + // VALES ... + valeBuffer[barIndex] = emptyValue; + valeGoldenBuffer[barIndex] = emptyValue; + + // + // FiBo ... + fiboLevel1Buffer[barIndex] = emptyValue; + fiboLevel2Buffer[barIndex] = emptyValue; + fiboLevel3Buffer[barIndex] = emptyValue; + fiboLevel4Buffer[barIndex] = emptyValue; + fiboLevel5Buffer[barIndex] = emptyValue; + + // + // SAR ... + sarBuffer[barIndex] = emptyValue; + + // + // TREND ... + trendBuffer[barIndex] = emptyValue; + trendColorBuffer[barIndex] = hideColorIDX; + trendStateBuffer[barIndex] = neuturalState; + + // + // KI ... + kiBuffer[barIndex] = emptyValue; + kiColorBuffer[barIndex] = hideColorIDX; + kiStateBuffer[barIndex] = neuturalState; + + // + // TKI ... + tkiBuffer[barIndex] = emptyValue; + tkiColorBuffer[barIndex] = hideColorIDX; + tkiStateBuffer[barIndex] = neuturalState; + + // + // VIDYA ... + vidyaBuffer[barIndex] = emptyValue; + vidyaColorBuffer[barIndex] = hideColorIDX; + vidyaStateBuffer[barIndex] = neuturalState; + + // + // SWINGS ... + swingLowBuffer[barIndex] = emptyValue; + swingHighBuffer[barIndex] = emptyValue; +} + +/** + * Calculate Specified Market Cycle Info ... + * + * @param barIndex: Integer, Bar Index ... + * @param cycle: ENUM_X_MARKET_CYCLES member, Specified Cycle ... + * @param hhBuffer: Highest High Buffer Reference ... + * @param llBuffer: Lowest Low Buffer Reference ... + */ +void CalculateCycle( + int barIndex, + ENUM_X_MARKET_CYCLES cycle, + double &hhBuffer[], + double &llBuffer[] // +) +{ + // + XOHCL bar; + bool isBarInited = bar.Init( + _Symbol, + _Period, + barIndex + // + ); + if (!isBarInited) + { + return; + } + + // + int mLength = 0; + switch (cycle) + { + // + case X_MARKET_CYCLE_SHORT: + mLength = mSCLength; + break; + + // + case X_MARKET_CYCLE_MEDIUM: + mLength = mMCLength; + break; + + // + case X_MARKET_CYCLE_LONG: + mLength = mLCLength; + break; + + // + case X_MARKET_CYCLE_HIND: + mLength = mHCLength; + break; + } + + // + if (mLength == 0) + { + return; + } + + // + // Find Highest High ... + double hhValue = bar.FindHighest( + mLength, + hhMode + // + ); + hhBuffer[barIndex] = hhValue; + + // + // Find Lowest Low ... + double llValue = bar.FindLowest( + mLength, + llMode + // + ); + llBuffer[barIndex] = llValue; +} + +/** + * Claculate Cycles ... + * + * @param barIndex: Integer, Bar Index ... + */ +void CalculateCycles(int barIndex) +{ + // + // SHORT ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_SHORT, + sHHBuffer, + sLLBuffer // + ); + + // + // MEDIUM ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_MEDIUM, + mHHBuffer, + mLLBuffer // + ); + + // + // LONG ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_LONG, + lHHBuffer, + lLLBuffer // + ); + + // + // HIND ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_HIND, + hHHBuffer, + hLLBuffer // + ); +} + +/** + * Calculate Values ... + * + * @param bar_index: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void CalculateValues( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // Check Prev Bar ... + // + int lastBarIndex = bar_index + 1; + bool isFirstBar = + startCalculationForLastBars > 0 + ? bar_index == startCalculationForLastBars + : bar_index == firstBarIndex; + + XOHCL iBar; + bool isInited = iBar.Init( + _Symbol, + _Period, + bar_index // + ); + + // + double iSHH = sHHBuffer[bar_index]; + double iSLL = sLLBuffer[bar_index]; + + // + double iMHH = mHHBuffer[bar_index]; + double iMLL = mLLBuffer[bar_index]; + + // + double iLHH = lHHBuffer[bar_index]; + double iLLL = lLLBuffer[bar_index]; + + // + double iHHH = hHHBuffer[bar_index]; + double iHLL = hLLBuffer[bar_index]; + + // + // Calculate Support ... + double lastSupport = + isFirstBar + ? emptyValue + : supBuffer[lastBarIndex]; + bool isSupport = iSLL == iMLL; + double iSupport = + isSupport + ? iSLL + : lastSupport; + supBuffer[bar_index] = iSupport; + + // + // Calculate Vale ... + double lastVale = + isFirstBar + ? emptyValue + : valeBuffer[lastBarIndex]; + bool isVale = + isSupport && + iMLL == iLLL && + iLLL == iHLL; + double iVale = + isVale + ? iMLL + : lastVale; + valeBuffer[bar_index] = iVale; + + // + // Calculate Resistance ... + double lastResistance = + isFirstBar + ? emptyValue + : resBuffer[lastBarIndex]; + bool isResistance = iSHH == iMHH; + double iResistance = + isResistance + ? iSHH + : lastResistance; + resBuffer[bar_index] = iResistance; + + // + // Calculate Peak ... + double lastPeak = + isFirstBar + ? emptyValue + : peakBuffer[lastBarIndex]; + bool isPeak = + isResistance && + iMHH == iLHH && + iLHH == iHHH; + double iPeak = + isPeak + ? iMHH + : lastPeak; + peakBuffer[bar_index] = iPeak; + + // + bool canSmooth = + supResSmoothingLength > 0 && + supResSmoothingMode != X_MA_MODE_NONE; + if (!canSmooth) + { + // + supportBuffer[bar_index] = iSupport; + resistanceBuffer[bar_index] = iResistance; + } + else + { + // + // Support ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + supResSmoothingLength, + supBuffer, + supportBuffer, + supResSmoothingMode // + ); + + // + // Resistance ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + supResSmoothingLength, + resBuffer, + resistanceBuffer, + supResSmoothingMode // + ); + } + + // + // Calculate Swings ... + + // + double lastSwingLow = + isFirstBar + ? emptyValue + : swingLowBuffer[lastBarIndex]; + double lastSwingHigh = + isFirstBar + ? emptyValue + : swingHighBuffer[lastBarIndex]; + + // + bool isSwingLow = IsSwingLow( + high, + low, + bar_index, + swingLength // + ); + bool isSwingHigh = IsSwingHigh( + high, + low, + bar_index, + swingLength // + ); + bool hasSwing = isSwingLow || + isSwingHigh; + double iSwingLow = emptyValue; + double iSwingHigh = emptyValue; + if (!hasSwing) + { + // + // FillBuffersZero(bar_index); + + // + iSwingLow = lastSwingLow; + iSwingHigh = lastSwingHigh; + + // + swingLowBuffer[bar_index] = lastSwingLow; + swingHighBuffer[bar_index] = lastSwingHigh; + } + else + { + // + iSwingLow = low[bar_index]; + double iSwingHigh = high[bar_index]; + + // + if (isSwingLow && !isSwingHigh) + { + iSwingHigh = lastSwingHigh; + } + else if (isSwingHigh && !isSwingLow) + { + iSwingLow = lastSwingLow; + } + + // + if (iSwingLow > lastSwingLow && + iSwingHigh == lastSwingHigh) + { + iSwingLow = lastSwingLow; + } + + // + if (iSwingHigh < lastSwingHigh && + iSwingLow == lastSwingLow) + { + iSwingHigh = lastSwingHigh; + } + + // + swingLowBuffer[bar_index] = iSwingLow; + swingHighBuffer[bar_index] = iSwingHigh; + } + + // + // Calculate Fibo Levels ... + + // + double iFiboValues[] = { + peakBuffer[bar_index], + valeBuffer[bar_index], + supBuffer[bar_index], + swingLowBuffer[bar_index], + swingHighBuffer[bar_index], + resBuffer[bar_index], // + }; + + // + double iFiboUpper = GetMax(iFiboValues); + double iFiboLower = GetMin(iFiboValues); + + // + // Fibo Level 1 ... + double iFiboLevel1 = emptyValue; + iFiboLevel1 = GetFibonacciLevel( + iFiboUpper, + iFiboLower, + fiboLevel1, + X_DIRECTION_BEARISH // + ); + fiboLevel1Buffer[bar_index] = iFiboLevel1; + + // + // Fibo Level 2 ... + double iFiboLevel2 = emptyValue; + iFiboLevel2 = GetFibonacciLevel( + iFiboUpper, + iFiboLower, + fiboLevel2, + X_DIRECTION_BEARISH // + ); + fiboLevel2Buffer[bar_index] = iFiboLevel2; + + // + // Fibo Level 3 ... + double iFiboLevel3 = emptyValue; + iFiboLevel3 = GetFibonacciLevel( + iFiboUpper, + iFiboLower, + fiboLevel3, + X_DIRECTION_BEARISH // + ); + fiboLevel3Buffer[bar_index] = iFiboLevel3; + + // + // Fibo Level 4 ... + double iFiboLevel4 = emptyValue; + iFiboLevel4 = GetFibonacciLevel( + iFiboUpper, + iFiboLower, + fiboLevel4, + X_DIRECTION_BEARISH // + ); + fiboLevel4Buffer[bar_index] = iFiboLevel4; + + // + // Fibo Level 5 ... + double iFiboLevel5 = emptyValue; + iFiboLevel5 = GetFibonacciLevel( + iFiboUpper, + iFiboLower, + fiboLevel5, + X_DIRECTION_BEARISH // + ); + fiboLevel5Buffer[bar_index] = iFiboLevel5; + + // + // Calculate Trend Color Buffer ... + double iClose = close[bar_index]; + double iTrend = trendBuffer[bar_index]; + + // + double iTrendState = neuturalState; + double iTrendColor = neuturalColorIDX; + if (iClose > iTrend) + { + // + iTrendState = bullishState; + iTrendColor = !showTrend + ? hideColorIDX + : bullishColorIDX; + } + else if (iClose < iTrend) + { + // + iTrendState = bearishState; + iTrendColor = !showTrend + ? hideColorIDX + : bearishColorIDX; + } + trendStateBuffer[bar_index] = iTrendState; + trendColorBuffer[bar_index] = iTrendColor; + + // + // Calculate KI / Color ... + double lastKI = + isFirstBar + ? emptyValue + : kiBuffer[lastBarIndex]; + double iKI = lastKI; + if (isInited) + { + // + double iLLKI = iBar.FindLowest(kiLength, MODE_LOW); + double iHHKI = iBar.FindHighest(kiLength, MODE_HIGH); + + // + iKI = (iHHKI + iLLKI) / 2; + if (iLLKI == 0 || iHHKI == 0) + { + iKI = lastKI; + } + } + else + { + iKI = lastKI; + } + kiBuffer[bar_index] = iKI; + + // + double iKIState = neuturalState; + double iKIColor = neuturalColorIDX; + if (iClose > iKI) + { + // + iKIState = bullishState; + iKIColor = + !showKI + ? hideColorIDX + : bullishColorIDX; + } + else if (iClose < iKI) + { + // + iKIState = bearishState; + iKIColor = + !showKI + ? hideColorIDX + : bearishColorIDX; + } + kiStateBuffer[bar_index] = iKIState; + kiColorBuffer[bar_index] = iKIColor; + + // + // Calculate PV Gold ... + double lastPeakGold = + isFirstBar + ? emptyValue + : peakGoldenBuffer[lastBarIndex]; + double lastValeGold = + isFirstBar + ? emptyValue + : valeGoldenBuffer[lastBarIndex]; + double iPeakGold = lastPeakGold; + double iValeGold = lastValeGold; + if (isInited) + { + // + iPeakGold = iBar.FindHighest(mHCLength, MODE_CLOSE); + if (iPeakGold == 0) + { + iPeakGold = lastPeakGold; + } + + // + iValeGold = iBar.FindLowest(mHCLength, MODE_CLOSE); + if (iValeGold == 0) + { + iValeGold = lastValeGold; + } + } + else + { + // + iPeakGold = lastPeakGold; + iValeGold = lastValeGold; + } + peakGoldenBuffer[bar_index] = iPeakGold; + valeGoldenBuffer[bar_index] = iValeGold; + + // + // TKI State and Color ... + + // + double iTKI = tkiBuffer[bar_index]; + + // + double iTKIState = neuturalState; + double iTKIColor = neuturalColorIDX; + if (iClose > iTKI) + { + // + iTKIState = bullishState; + iTKIColor = + !showTKI + ? hideColorIDX + : bullishColorIDX; + } + else if (iClose < iTKI) + { + // + iTKIState = bearishState; + iTKIColor = + !showTKI + ? hideColorIDX + : bearishColorIDX; + } + tkiStateBuffer[bar_index] = iTKIState; + tkiColorBuffer[bar_index] = iTKIColor; + + // + // VIDYA Color ... + + // + double iVIDYA = vidyaBuffer[bar_index]; + + // + double iVIDYAState = neuturalState; + double iVIDYAColor = neuturalColorIDX; + if (iClose > iVIDYA) + { + // + iVIDYAState = bullishState; + iVIDYAColor = + !showVidya + ? hideColorIDX + : bullishColorIDX; + } + else if (iClose < iVIDYA) + { + // + iVIDYAState = bearishState; + iVIDYAColor = + !showVidya + ? hideColorIDX + : bearishColorIDX; + } + vidyaStateBuffer[bar_index] = iVIDYAState; + vidyaColorBuffer[bar_index] = iVIDYAColor; + + // + // Cleanup Resources ... + + // + iBar.Clean(); +} + +// +bool IsSwingLow( + const double &high[], + const double &low[], + int index, + int length // +) +{ + // + bool result = false; + + // + result = index + 1 + length <= firstBarIndex; + if (!result) + { + return result; + } + + // + for (int i = index + 1; i <= index + length; i++) + { + // + result = low[index] < low[i]; + if (!result) + { + break; + } + } + + // + return result; +} + +// +bool IsSwingHigh( + const double &high[], + const double &low[], + int index, + int length // +) +{ + // + bool result = false; + + // + result = index + 1 + length <= firstBarIndex; + if (!result) + { + return result; + } + + // + for (int i = index + 1; i <= index + length; i++) + { + // + result = high[index] > high[i]; + if (!result) + { + break; + } + } + + // + return result; +} + +// \ No newline at end of file diff --git a/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xcatb.mq5 b/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xcatb.mq5 new file mode 100644 index 0000000..8fb1e13 --- /dev/null +++ b/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xcatb.mq5 @@ -0,0 +1,2777 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XCATB +// Description: Integrates All Requirements inside +// this indicator for analyse Markets to +// Detect Trigger Blocks ... +// +// - HK Bars; +// - ATR Band; +// - Signal Bars; +// - Parabolic Sar; +// - HK Signal Bars; +// - Peaks and Vales; +// - Peaks and Vales Goldens; +// - Trending Average Prices; +// +// - ATR; +// - RSI; +// - ADX; +// - DELTA; +// - VOLUME; +// +// 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 XCATB Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121 XCATB" + +// +// Imports ... +#include "../Classes/x-saherelm.x-alert.class.mq5" +#include "../Classes/x-saherelm.x-bar.analyser.class.mq5" +#include "../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" +#include "../Libraries/x-saherelm.x121.xcatb.lib.mq5" + +// +// Inputs ... + +// +input group "Market"; + +// +// Short ... +input ENUM_X_PERIOD_METHOD scMethod = X_PERIOD_AUTO; // How to Find Short Period +input ENUM_TIMEFRAMES scPeriod = NULL; // Short Period + +// +// Medium ... +input ENUM_X_PERIOD_METHOD mcMethod = X_PERIOD_AUTO; // How to Find Medium Period +input ENUM_TIMEFRAMES mcPeriod = NULL; // Medium Period + +// +// Long ... +input ENUM_X_PERIOD_METHOD lcMethod = X_PERIOD_AUTO; // How to Find Long Period +input ENUM_TIMEFRAMES lcPeriod = NULL; // Long Period + +// +// Hind ... +input ENUM_X_PERIOD_METHOD hcMethod = X_PERIOD_AUTO; // How to Find Hind Period +input ENUM_TIMEFRAMES hcPeriod = NULL; // Hind Period + +// +// Select Trending Cycle ... +// this Cycle Used for All Calculations ... +input ENUM_X_MARKET_CYCLES appliedCycle = X_MARKET_CYCLE_HIND; // Applied Cycle + +// +// Signal ... +input group "Signal"; +input int signalR2R = 4; // Risk Reward Ratio +input bool drawSignals = true; // Draw Signal +input bool drawTriggerBlock = true; // Draw Trigger Block +input double slAtrMultiplier = 1.0; // ATR Multiplier for SL + +// +// Validating ... +input group "Validating"; +input bool forceHasSwing = false; // Force Blocks to Have Swing +input bool forceObBarType = false; // Force Block Has Reversal Bar +input bool forceOBFVGBarType = false; // Force FVG Has Same Bars +input bool forceHasFLiquidity = false; // Force Blocks to Have Following Liquidity +input bool forceHasRLiquidity = false; // Force Blocks to Have Reversal Liquidity +input bool validateGapSequence = false; // Validate Block's Gap Sequence +input bool validateBlockEdgeBreakout = false; // Validate Block's Edge Breakout + +// +// Filtering ... +input group "Filtering"; +input bool filterBasedOnPV = false; // Filter Based on Peak and Vale +input bool filterBasedOnSar = false; // Filter Based on Sar +input bool filterBasedOnRSI = false; // Filter Based on RSI +input bool filterBasedOnADX = false; // Filter Based on ADX +input bool filterBasedOnATR = false; // Filter Based on ATR +input bool filterBasedOnTrend = false; // Filter Based on Trend +input bool filterBasedOnDelta = false; // Filter Based on Delta +input bool filterBasedOnVolume = false; // Filter Based on Volume +input bool filterBasedOnSignalBar = false; // Filter Based on Signal Bar +input bool filterBasedOnHKSignalBar = false; // Filter Based on Hiken Ashi Signal Bar + +// +// Alert ... +input group "Alerts"; +input string mAlertPrefix = ""; // Alert Prefix +input bool _logAlerts = false; // Log Alerts +input bool _pushAlerts = false; // Push Alerts +input bool _mailAlerts = false; // Mail Alerts +input bool _terminalAlerts = false; // Terminal Alerts + +// +// Presentation ... +input group "Presentation"; +input bool showBars = true; // Show Bars +input bool showPV = false; // Show PV +input bool showPVGolden = false; // Show PV Golden +input bool showSar = false; // Show Sar +input bool showTrend = false; // Show Trend +input bool showATRBand = false; // Show ATR Band +input bool showSignalBars = false; // Show Signal Bars +input bool showHKSignalBars = false; // Show Hiken Ashi Signal Bars + +// +input int startCalculationForLastBars = 1500; // Calculate Last n Bars + +// +// Non Inputs ... +double sarStep = 0.02; // Step +double sarMax = 0.2; // Maximum +double rsiOBLevel = 70.0; // RSI OB Level +double rsiOSLevel = 30.0; // RSI OS Level +double adxThreshold = 25.0; // ADX Threshold +int sarArrowCode = 159; // Parabolic Sar Arrow Code +int peakArrowCode = 159; // Peaks Arrow Code +int valeArrowCode = 159; // Vales Arrow Code +double atrMultiplier = 1.5; // ATR Band Multiplier +bool showShortCycle = false; // Show Short Cycle Range +bool showMediumCycle = false; // Show Medium Cycle Range +bool showLongCycle = false; // Show Long Cycle Range +bool showHindCycle = false; // Show Hind Cycle Range +ENUM_MA_METHOD trendMode = MODE_SMA; // Trend Mode +ENUM_SERIESMODE upperMode = MODE_HIGH; // Peak Method +ENUM_SERIESMODE lowerMode = MODE_LOW; // Vale Method +ENUM_X_PRICE atrUpperPriceType = X_PRICE_HIGH; // ATR Upper Zone Applied To +ENUM_X_PRICE atrLowerPriceType = X_PRICE_LOW; // ATR Lower Zone Applied To +ENUM_APPLIED_PRICE rsiAppliedTo = PRICE_CLOSE; // RSI Applied To +ENUM_APPLIED_PRICE trendAppliedTo = PRICE_MEDIAN; // Trend Applied To +ENUM_X_MA_METHOD atrSignalMethod = X_MA_MODE_EMA; // ATR Signalling Method +ENUM_X_MA_METHOD barsSignalMethod = X_MA_MODE_EMA; // Bars Signalling Method +ENUM_X_MA_METHOD deltaSignalMethod = X_MA_MODE_EMA; // Delta Signalling Method +ENUM_X_MA_METHOD hkSignalBarMethod = X_MA_MODE_EMA; // Hiken Ashi Signal Method +ENUM_X_MA_METHOD volumeSignalMethod = X_MA_MODE_EMA; // Volume Signalling Method + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#define bullishState 1 +#define neuturalState 0 +#define bearishState -1 + +// +#define emptyValue 0.0 + +// +// Buffers ... + +// +#property indicator_chart_window + +// +// Plot: 18 +// Color: 4 +// Bar: 8 +// Data Buffer: 19 +#property indicator_buffers 49 +#property indicator_plots 18 + +// +// Plot Buffers ... + +// +// SAR ... + +// +#define sarBufferIndex 0 +#define sarBufferPlotIndex 0 +double sarBuffer[]; + +// +#define sarColorBufferIndex 1 +double sarColorBuffer[]; + +// +#property indicator_label1 "SAR" +#property indicator_type1 DRAW_COLOR_ARROW +#property indicator_color1 CLR_NONE, clrLime, clrRed, clrGray +#property indicator_width1 2 + +// +// PEAKS ... + +// +#define peakBufferIndex 2 +#define peakBufferPlotIndex 1 +double peakBuffer[]; + +// +#property indicator_label2 "PEAK" +#property indicator_type2 DRAW_ARROW +#property indicator_color2 clrMagenta +#property indicator_width2 1 + +// +// VALES ... + +// +#define valeBufferIndex 3 +#define valeBufferPlotIndex 2 +double valeBuffer[]; + +// +#property indicator_label3 "VALE" +#property indicator_type3 DRAW_ARROW +#property indicator_color3 clrAqua +#property indicator_width3 1 + +// +// PEAKS Golden ... + +// +#define peakGoldenBufferIndex 4 +#define peakGoldenBufferPlotIndex 3 +double peakGoldenBuffer[]; + +// +#property indicator_label4 "PEAK Golden" +#property indicator_type4 DRAW_LINE +#property indicator_color4 clrMagenta +#property indicator_style4 STYLE_DOT +#property indicator_width4 1 + +// +// VALE Golden ... + +// +#define valeGoldenBufferIndex 5 +#define valeGoldenBufferPlotIndex 4 +double valeGoldenBuffer[]; + +// +#property indicator_label5 "VALES Golden" +#property indicator_type5 DRAW_LINE +#property indicator_color5 clrAqua +#property indicator_style5 STYLE_DOT +#property indicator_width5 1 + +// +// ATR ... + +// +// Upper ... + +// +#define atrUpperBufferIndex 6 +#define atrUpperBufferPlotIndex 5 +double atrUpperBuffer[]; + +// +#property indicator_label6 "XATRU" +#property indicator_type6 DRAW_LINE +#property indicator_color6 clrYellow +#property indicator_style6 STYLE_SOLID +#property indicator_width6 1 + +// +// Lower ... + +// +#define atrLowerBufferIndex 7 +#define atrLowerBufferPlotIndex 6 +double atrLowerBuffer[]; + +// +#property indicator_label7 "XATRL" +#property indicator_type7 DRAW_LINE +#property indicator_color7 clrYellow +#property indicator_style7 STYLE_SOLID +#property indicator_width7 1 + +// +// TREND ... + +// +#define trendBufferIndex 8 +#define trendBufferPlotIndex 7 +double trendBuffer[]; + +// +#define trendColorBufferIndex 9 +double trendColorBuffer[]; + +// +#property indicator_label8 "Trend" +#property indicator_type8 DRAW_COLOR_LINE +#property indicator_color8 CLR_NONE, clrAqua, clrMagenta, clrGray +#property indicator_style8 STYLE_SOLID +#property indicator_width8 2 + +// +// Signal Bar ... + +// +#define sBarOpenBufferIndex 10 +double sBarOpenBuffer[]; + +// +#define sBarHighBufferIndex 11 +double sBarHighBuffer[]; + +// +#define sBarLowBufferIndex 12 +double sBarLowBuffer[]; + +// +#define sBarCloseBufferIndex 13 +double sBarCloseBuffer[]; + +// +#define sBarColorBufferIndex 14 +double sBarColorBuffer[]; + +// +#define sBarBufferPlotIndex 8 +#property indicator_label9 "XSGB Open;XSGB High;XSGB Low;XSGB Close" +#property indicator_type9 DRAW_COLOR_CANDLES +#property indicator_color9 CLR_NONE, clrLime, clrRed + +// +// XHK SIGNAL ... + +// +#define hkSBarOpenBufferIndex 15 +double hkSBarOpenBuffer[]; + +// +#define hkSBarHighBufferIndex 16 +double hkSBarHighBuffer[]; + +// +#define hkSBarLowBufferIndex 17 +double hkSBarLowBuffer[]; + +// +#define hkSBarCloseBufferIndex 18 +double hkSBarCloseBuffer[]; + +// +#define hkSBarColorBufferIndex 19 +double hkSBarColorBuffer[]; + +// +#define hkSBarBufferPlotIndex 9 +#property indicator_label10 "XHKSGB Open;XHKSGB High;XHKSGB Low;XHKSGB Close" +#property indicator_type10 DRAW_COLOR_CANDLES +#property indicator_color10 CLR_NONE, clrAqua, clrMagenta + +// +// CYCLES Range ... + +// +// SHORT ... + +// +#define sHHBufferIndex 20 +#define sHHBufferPlotIndex 10 +double sHHBuffer[]; + +// +#property indicator_label11 "SH" +#property indicator_type11 DRAW_LINE +#property indicator_color11 clrGray +#property indicator_style11 STYLE_DOT +#property indicator_width11 1 + +// +#define sLLBufferIndex 21 +#define sLLBufferPlotIndex 11 +double sLLBuffer[]; + +// +#property indicator_label12 "SL" +#property indicator_type12 DRAW_LINE +#property indicator_color12 clrGray +#property indicator_style12 STYLE_DOT +#property indicator_width12 1 + +// +// MEDIUM ... + +// +#define mHHBufferIndex 22 +#define mHHBufferPlotIndex 12 +double mHHBuffer[]; + +// +#property indicator_label13 "MH" +#property indicator_type13 DRAW_LINE +#property indicator_color13 clrIndigo +#property indicator_style13 STYLE_DOT +#property indicator_width13 1 + +// +#define mLLBufferIndex 23 +#define mLLBufferPlotIndex 13 +double mLLBuffer[]; + +// +#property indicator_label14 "ML" +#property indicator_type14 DRAW_LINE +#property indicator_color14 clrIndigo +#property indicator_style14 STYLE_DOT +#property indicator_width14 1 + +// +// LONG ... + +// +#define lHHBufferIndex 24 +#define lHHBufferPlotIndex 14 +double lHHBuffer[]; + +// +#property indicator_label15 "LH" +#property indicator_type15 DRAW_LINE +#property indicator_color15 clrGoldenrod +#property indicator_style15 STYLE_DOT +#property indicator_width15 1 + +// +#define lLLBufferIndex 25 +#define lLLBufferPlotIndex 15 +double lLLBuffer[]; + +// +#property indicator_label16 "LL" +#property indicator_type16 DRAW_LINE +#property indicator_color16 clrGoldenrod +#property indicator_style16 STYLE_DOT +#property indicator_width16 1 + +// +// HIND ... + +// +#define hHHBufferIndex 26 +#define hHHBufferPlotIndex 16 +double hHHBuffer[]; + +// +#property indicator_label17 "HH" +#property indicator_type17 DRAW_LINE +#property indicator_color17 clrBrown +#property indicator_style17 STYLE_DOT +#property indicator_width17 1 + +// +#define hLLBufferIndex 27 +#define hLLBufferPlotIndex 17 +double hLLBuffer[]; + +// +#property indicator_label18 "HL" +#property indicator_type18 DRAW_LINE +#property indicator_color18 clrBrown +#property indicator_style18 STYLE_DOT +#property indicator_width18 1 + +// +// Data Buffers ... + +// +#define mLastBufferIndex 27 + +// +// SAR ... + +// +#define sarStateBufferIndex mLastBufferIndex + 1 +double sarStateBuffer[]; + +// +// TREND State ... + +// +#define trendStateBufferIndex mLastBufferIndex + 2 +double trendStateBuffer[]; + +// +// RSI ... + +// +#define rsiBufferIndex mLastBufferIndex + 3 +double rsiBuffer[]; + +// +// ADX ... + +// +#define adxBufferIndex mLastBufferIndex + 4 +double adxBuffer[]; + +// +#define adxpBufferIndex mLastBufferIndex + 5 +double adxpBuffer[]; + +// +#define adxnBufferIndex mLastBufferIndex + 6 +double adxnBuffer[]; + +// +// DELTA ... + +// +#define deltaBufferIndex mLastBufferIndex + 7 +double deltaBuffer[]; + +// +#define deltaSignalBufferIndex mLastBufferIndex + 8 +double deltaSignalBuffer[]; + +// +// VOLUMES ... + +// +#define bullishVolumeBufferIndex mLastBufferIndex + 9 +double bullishVolumeBuffer[]; + +// +#define bearishVolumeBufferIndex mLastBufferIndex + 10 +double bearishVolumeBuffer[]; + +// +#define bullishVolumeSignalBufferIndex mLastBufferIndex + 11 +double bullishVolumeSignalBuffer[]; + +// +#define bearishVolumeSignalBufferIndex mLastBufferIndex + 12 +double bearishVolumeSignalBuffer[]; + +// +// ATR ... + +// +#define atrBufferIndex mLastBufferIndex + 13 +double atrBuffer[]; + +// +#define atrUpperRawBufferIndex mLastBufferIndex + 14 +double atrUpperRawBuffer[]; + +// +#define atrLowerRawBufferIndex mLastBufferIndex + 15 +double atrLowerRawBuffer[]; + +// +// HK ... + +// +#define openHKBufferIndex mLastBufferIndex + 16 +double openHKBuffer[]; + +// +#define highHKBufferIndex mLastBufferIndex + 17 +double highHKBuffer[]; + +// +#define lowHKBufferIndex mLastBufferIndex + 18 +double lowHKBuffer[]; + +// +#define closeHKBufferIndex mLastBufferIndex + 19 +double closeHKBuffer[]; + +// +// Variables, Properties and etc ... + +// +int limit; + +// +int maxLength; + +// +int firstBarIndex; + +// +// Bars Color Variables ... +color _upColor = clrLime; +color _downColor = clrRed; +color _lineColor = clrLime; +color _bullishColor = clrLime; +color _bearishColor = clrRed; + +// +// XMarketCycle sc; +int mSCLength = 0; +ENUM_TIMEFRAMES mSCPeriod = NULL; + +// +// XMarketCycle mc; +int mMCLength = 0; +ENUM_TIMEFRAMES mMCPeriod = NULL; + +// +// XMarketCycle lc; +int mLCLength = 0; +ENUM_TIMEFRAMES mLCPeriod = NULL; + +// +// XMarketCycle hc; +int mHCLength = 0; +ENUM_TIMEFRAMES mHCPeriod = NULL; + +// +// Applied Cycle ... +int mAppliedLength; +ENUM_TIMEFRAMES mAppliedPeriod = NULL; + +// +// Handlers ... +int atrHandler = INVALID_HANDLE; +int sarHandler = INVALID_HANDLE; +int rsiHandler = INVALID_HANDLE; +int adxHandler = INVALID_HANDLE; +int trendHandler = INVALID_HANDLE; + +// +XCAlert *mAlert; +CArrayObj mObjects; +XCPOIDrawer *mDrawer; +bool mEnableAlerts = false; +XCBarAnalyser *mBarAnalyser; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + bool has = false; + + // + ReadBarStyle(); + + // + // Validate Inputs ... + has = ValidateInputs(); + if (!has) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + has = InitCycles(); + if (!has) + { + return INIT_FAILED; + } + + // + // 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(); + + // + // Initial Requirements ... + has = InitRequirements(); + if (!has) + { + return INIT_FAILED; + } + + // + if (showBars) + { + ShowBars(); + } + else + { + HideBars(); + } + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; + + // +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +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 + + // + ShowBars(); + + // + mObjects.Clear(); + + // + delete mAlert; + ZeroMemory(mAlert); + + // + delete mDrawer; + ZeroMemory(mDrawer); + + // + delete mBarAnalyser; + ZeroMemory(mBarAnalyser); + + // + // De Initialize all Handlers and etc ... + IndicatorRelease(atrHandler); + IndicatorRelease(sarHandler); + IndicatorRelease(rsiHandler); + IndicatorRelease(adxHandler); + IndicatorRelease(trendHandler); +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // 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); + + // + // Validate Calculated Bars ... + + // + // ATR ... + int atrCalculatedBars = BarsCalculated(atrHandler); + + // + // SAR ... + int sarCalculatedBars = BarsCalculated(sarHandler); + + // + // RSI ... + int rsiCalculatedBars = BarsCalculated(rsiHandler); + + // + // ADX ... + int adxCalculatedBars = BarsCalculated(adxHandler); + + // + // TREND ... + int trendCalculatedBars = BarsCalculated(trendHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // ATR ... + atrCalculatedBars >= maxLength && + // + // SAR ... + sarCalculatedBars >= maxLength && + // + // RSI ... + rsiCalculatedBars >= maxLength && + // + // ADX ... + adxCalculatedBars >= maxLength && + // + // TREND ... + trendCalculatedBars >= maxLength + // + ; + if (!isPassedRequiredCalculatedBars) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + + // + // ATR ... + int copiedAtrs = CopyBuffer(atrHandler, MAIN_LINE, 0, limit, atrBuffer); + + // + // SAR ... + int copiedSars = CopyBuffer(sarHandler, MAIN_LINE, 0, limit, sarBuffer); + + // + // RSI ... + int copiedRSIs = CopyBuffer(rsiHandler, MAIN_LINE, 0, limit, rsiBuffer); + + // + // ADX ... + int copiedADXs = CopyBuffer(adxHandler, MAIN_LINE, 0, limit, adxBuffer); + + // + // ADX Plus ... + int copiedADXPs = CopyBuffer(adxHandler, PLUSDI_LINE, 0, limit, adxpBuffer); + + // + // ADX Negative ... + int copiedADXNs = CopyBuffer(adxHandler, MINUSDI_LINE, 0, limit, adxnBuffer); + + // + // TREND ... + int copiedTrends = CopyBuffer(trendHandler, MAIN_LINE, 0, limit, trendBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // ATR ... + copiedAtrs >= limit && + // + // SAR ... + copiedSars >= limit && + // + // RSI ... + copiedRSIs >= limit && + // + // TREND ... + copiedTrends >= limit + // + ; + if (!isPassedRequiredCopiedItems) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + if (prev_calculated == 0) + { + // + string message = "History Finished ..."; + Print(message); + } + + // + return rates_total; +} + +// +// Custom Functions ... + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + // + IndicatorSetInteger(INDICATOR_DIGITS, _Digits); + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + result = + // + sarMax > 0 && + sarStep > 0 && + rsiOBLevel > 0 && + rsiOSLevel > 0 && + adxThreshold > 0 && + sarMax > sarStep && + atrMultiplier > 0 && + // + IsValid(appliedCycle) && + // + IsValid(atrUpperPriceType) && + IsValid(atrLowerPriceType) && + // + // CYCLES ... + (IsValid(scMethod, scPeriod) && + IsValid(mcMethod, mcPeriod) && + IsValid(lcMethod, lcPeriod) && + IsValid(hcMethod, hcPeriod)) + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(mSCLength, mMCLength); + result = MathMax(result, mLCLength); + result = MathMax(result, mHCLength); + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + + // + // SAR ... + + // + ArraySetAsSeries(sarBuffer, true); + SetIndexBuffer(sarBufferIndex, sarBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(sarBufferPlotIndex, PLOT_SHOW_DATA, showSar); + PlotIndexSetDouble(sarBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(sarBufferPlotIndex, PLOT_ARROW, sarArrowCode); + + // + ArraySetAsSeries(sarColorBuffer, true); + SetIndexBuffer(sarColorBufferIndex, sarColorBuffer, INDICATOR_COLOR_INDEX); + + // + ArraySetAsSeries(sarStateBuffer, true); + SetIndexBuffer(sarStateBufferIndex, sarStateBuffer, INDICATOR_CALCULATIONS); + + // + // PEAK / VALE ... + + // + ENUM_DRAW_TYPE pvDrawType = showPV ? DRAW_ARROW : DRAW_NONE; + + // + // PEAK ... + + // + ArraySetAsSeries(peakBuffer, true); + SetIndexBuffer(peakBufferIndex, peakBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(peakBufferPlotIndex, PLOT_SHOW_DATA, showPV); + PlotIndexSetInteger(peakBufferPlotIndex, PLOT_DRAW_TYPE, pvDrawType); + + // + PlotIndexSetDouble(peakBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(peakBufferPlotIndex, PLOT_ARROW, peakArrowCode); + + // + // VALE ... + + // + ArraySetAsSeries(valeBuffer, true); + SetIndexBuffer(valeBufferIndex, valeBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(valeBufferPlotIndex, PLOT_SHOW_DATA, showPV); + PlotIndexSetInteger(valeBufferPlotIndex, PLOT_DRAW_TYPE, pvDrawType); + + // + PlotIndexSetDouble(valeBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(valeBufferPlotIndex, PLOT_ARROW, valeArrowCode); + + // + // PV GOLDEN ... + + // + ENUM_DRAW_TYPE pvGoldenDrawType = showPVGolden ? DRAW_LINE : DRAW_NONE; + + // + // PEAK Golden ... + + // + ArraySetAsSeries(peakGoldenBuffer, true); + SetIndexBuffer(peakGoldenBufferIndex, peakGoldenBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(peakGoldenBufferPlotIndex, PLOT_SHOW_DATA, showPVGolden); + PlotIndexSetInteger(peakGoldenBufferPlotIndex, PLOT_DRAW_TYPE, pvGoldenDrawType); + + // + PlotIndexSetDouble(peakGoldenBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // VALE Golden ... + + // + ArraySetAsSeries(valeGoldenBuffer, true); + SetIndexBuffer(valeGoldenBufferIndex, valeGoldenBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(valeGoldenBufferPlotIndex, PLOT_SHOW_DATA, showPVGolden); + PlotIndexSetInteger(valeGoldenBufferPlotIndex, PLOT_DRAW_TYPE, pvGoldenDrawType); + + // + PlotIndexSetDouble(valeGoldenBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // ATR Band ... + + // + // UPPER ... + ENUM_DRAW_TYPE atrUpperDrawType = showATRBand ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(atrUpperBuffer, true); + SetIndexBuffer(atrUpperBufferIndex, atrUpperBuffer, INDICATOR_DATA); + + // + PlotIndexSetDouble(atrUpperBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(atrUpperBufferPlotIndex, PLOT_SHOW_DATA, showATRBand); + PlotIndexSetInteger(atrUpperBufferPlotIndex, PLOT_DRAW_TYPE, atrUpperDrawType); + + // + // LOWER ... + ENUM_DRAW_TYPE atrLowerDrawType = showATRBand ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(atrLowerBuffer, true); + SetIndexBuffer(atrLowerBufferIndex, atrLowerBuffer, INDICATOR_DATA); + + // + PlotIndexSetDouble(atrLowerBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(atrLowerBufferPlotIndex, PLOT_SHOW_DATA, showATRBand); + PlotIndexSetInteger(atrLowerBufferPlotIndex, PLOT_DRAW_TYPE, atrLowerDrawType); + + // + // TREND ... + + // + ArraySetAsSeries(trendBuffer, true); + SetIndexBuffer(trendBufferIndex, trendBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(trendBufferPlotIndex, PLOT_SHOW_DATA, showTrend); + PlotIndexSetDouble(trendBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(trendColorBuffer, true); + SetIndexBuffer(trendColorBufferIndex, trendColorBuffer, INDICATOR_COLOR_INDEX); + + // + ArraySetAsSeries(trendStateBuffer, true); + SetIndexBuffer(trendStateBufferIndex, trendStateBuffer, INDICATOR_CALCULATIONS); + + // + // SIGNAL Bar ... + + // + // Signal Bars Color ... + ArraySetAsSeries(sBarColorBuffer, true); + SetIndexBuffer(sBarColorBufferIndex, sBarColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Set EMPTY_VALUE on XHK Bar Buffer ... + PlotIndexSetDouble(sBarBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(sBarBufferPlotIndex, PLOT_SHOW_DATA, false); + + // + // Open ... + ArraySetAsSeries(sBarOpenBuffer, true); + SetIndexBuffer(sBarOpenBufferIndex, sBarOpenBuffer, INDICATOR_DATA); + + // + // High ... + ArraySetAsSeries(sBarHighBuffer, true); + SetIndexBuffer(sBarHighBufferIndex, sBarHighBuffer, INDICATOR_DATA); + + // + // Low ... + ArraySetAsSeries(sBarLowBuffer, true); + SetIndexBuffer(sBarLowBufferIndex, sBarLowBuffer, INDICATOR_DATA); + + // + // Close ... + ArraySetAsSeries(sBarCloseBuffer, true); + SetIndexBuffer(sBarCloseBufferIndex, sBarCloseBuffer, INDICATOR_DATA); + + // + // XHK SIGNAL Bar ... + + // + // HK Bars Color ... + ArraySetAsSeries(hkSBarColorBuffer, true); + SetIndexBuffer(hkSBarColorBufferIndex, hkSBarColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Set EMPTY_VALUE on XHK Bar Buffer ... + PlotIndexSetDouble(hkSBarBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(hkSBarBufferPlotIndex, PLOT_SHOW_DATA, false); + + // + // Open ... + ArraySetAsSeries(hkSBarOpenBuffer, true); + SetIndexBuffer(hkSBarOpenBufferIndex, hkSBarOpenBuffer, INDICATOR_DATA); + + // + // High ... + ArraySetAsSeries(hkSBarHighBuffer, true); + SetIndexBuffer(hkSBarHighBufferIndex, hkSBarHighBuffer, INDICATOR_DATA); + + // + // Low ... + ArraySetAsSeries(hkSBarLowBuffer, true); + SetIndexBuffer(hkSBarLowBufferIndex, hkSBarLowBuffer, INDICATOR_DATA); + + // + // Close ... + ArraySetAsSeries(hkSBarCloseBuffer, true); + SetIndexBuffer(hkSBarCloseBufferIndex, hkSBarCloseBuffer, INDICATOR_DATA); + + // + // CYCLES ... + + // + // SHORT ... + + // + ENUM_DRAW_TYPE sDrawType = showShortCycle ? DRAW_LINE : DRAW_NONE; + + // + // HH ... + + // + ArraySetAsSeries(sHHBuffer, true); + SetIndexBuffer(sHHBufferIndex, sHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(sHHBufferPlotIndex, PLOT_SHOW_DATA, showShortCycle); + PlotIndexSetInteger(sHHBufferPlotIndex, PLOT_DRAW_TYPE, sDrawType); + PlotIndexSetDouble(sHHBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LL ... + + // + ArraySetAsSeries(sLLBuffer, true); + SetIndexBuffer(sLLBufferIndex, sLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(sLLBufferPlotIndex, PLOT_SHOW_DATA, showShortCycle); + PlotIndexSetInteger(sLLBufferPlotIndex, PLOT_DRAW_TYPE, sDrawType); + PlotIndexSetDouble(sLLBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // MEDIUM ... + + // + ENUM_DRAW_TYPE mDrawType = showMediumCycle ? DRAW_LINE : DRAW_NONE; + + // + // HH ... + + // + ArraySetAsSeries(mHHBuffer, true); + SetIndexBuffer(mHHBufferIndex, mHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(mHHBufferPlotIndex, PLOT_SHOW_DATA, showMediumCycle); + PlotIndexSetInteger(mHHBufferPlotIndex, PLOT_DRAW_TYPE, mDrawType); + PlotIndexSetDouble(mHHBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LL ... + + // + ArraySetAsSeries(mLLBuffer, true); + SetIndexBuffer(mLLBufferIndex, mLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(mLLBufferPlotIndex, PLOT_SHOW_DATA, showMediumCycle); + PlotIndexSetInteger(mLLBufferPlotIndex, PLOT_DRAW_TYPE, mDrawType); + PlotIndexSetDouble(mLLBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LONG ... + + // + ENUM_DRAW_TYPE lDrawType = showLongCycle ? DRAW_LINE : DRAW_NONE; + + // + // HH ... + + // + ArraySetAsSeries(lHHBuffer, true); + SetIndexBuffer(lHHBufferIndex, lHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(lHHBufferPlotIndex, PLOT_SHOW_DATA, showLongCycle); + PlotIndexSetInteger(lHHBufferPlotIndex, PLOT_DRAW_TYPE, lDrawType); + PlotIndexSetDouble(lHHBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LL ... + + // + ArraySetAsSeries(lLLBuffer, true); + SetIndexBuffer(lLLBufferIndex, lLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(lLLBufferPlotIndex, PLOT_SHOW_DATA, showLongCycle); + PlotIndexSetInteger(lLLBufferPlotIndex, PLOT_DRAW_TYPE, lDrawType); + PlotIndexSetDouble(lLLBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // HIND ... + + // + ENUM_DRAW_TYPE hDrawType = showHindCycle ? DRAW_LINE : DRAW_NONE; + + // + // HH ... + + // + ArraySetAsSeries(hHHBuffer, true); + SetIndexBuffer(hHHBufferIndex, hHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(hHHBufferPlotIndex, PLOT_SHOW_DATA, showHindCycle); + PlotIndexSetInteger(hHHBufferPlotIndex, PLOT_DRAW_TYPE, hDrawType); + PlotIndexSetDouble(hHHBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LL ... + + // + ArraySetAsSeries(hLLBuffer, true); + SetIndexBuffer(hLLBufferIndex, hLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(hLLBufferPlotIndex, PLOT_SHOW_DATA, showHindCycle); + PlotIndexSetInteger(hLLBufferPlotIndex, PLOT_DRAW_TYPE, hDrawType); + PlotIndexSetDouble(hLLBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // Data Buffers ... + + // + // RSI ... + ArraySetAsSeries(rsiBuffer, true); + SetIndexBuffer(rsiBufferIndex, rsiBuffer, INDICATOR_CALCULATIONS); + + // + // ADX ... + + // + ArraySetAsSeries(adxBuffer, true); + SetIndexBuffer(adxBufferIndex, adxBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(adxpBuffer, true); + SetIndexBuffer(adxpBufferIndex, adxpBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(adxnBuffer, true); + SetIndexBuffer(adxnBufferIndex, adxnBuffer, INDICATOR_CALCULATIONS); + + // + // DELTA ... + + // + ArraySetAsSeries(deltaBuffer, true); + SetIndexBuffer(deltaBufferIndex, deltaBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(deltaSignalBuffer, true); + SetIndexBuffer(deltaSignalBufferIndex, deltaSignalBuffer, INDICATOR_CALCULATIONS); + + // + // VOLUME ... + + // + ArraySetAsSeries(bullishVolumeBuffer, true); + SetIndexBuffer(bullishVolumeBufferIndex, bullishVolumeBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(bearishVolumeBuffer, true); + SetIndexBuffer(bearishVolumeBufferIndex, bearishVolumeBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(bullishVolumeSignalBuffer, true); + SetIndexBuffer(bullishVolumeSignalBufferIndex, bullishVolumeSignalBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(bearishVolumeSignalBuffer, true); + SetIndexBuffer(bearishVolumeSignalBufferIndex, bearishVolumeSignalBuffer, INDICATOR_CALCULATIONS); + + // + // ATR ... + + ArraySetAsSeries(atrBuffer, true); + SetIndexBuffer(atrBufferIndex, atrBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(atrUpperRawBuffer, true); + SetIndexBuffer(atrUpperRawBufferIndex, atrUpperRawBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(atrLowerRawBuffer, true); + SetIndexBuffer(atrLowerRawBufferIndex, atrLowerRawBuffer, INDICATOR_CALCULATIONS); + + // + // XHK ... + + // + ArraySetAsSeries(openHKBuffer, true); + SetIndexBuffer(openHKBufferIndex, openHKBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(highHKBuffer, true); + SetIndexBuffer(highHKBufferIndex, highHKBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(lowHKBuffer, true); + SetIndexBuffer(lowHKBufferIndex, lowHKBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(closeHKBuffer, true); + SetIndexBuffer(closeHKBufferIndex, closeHKBuffer, INDICATOR_CALCULATIONS); + + // +} + +/** + * Initial Market Cycles ... + * + * @return ( bool ) + */ +bool InitCycles() +{ + // + bool result = false; + + // + int cPeriodSeconds = PeriodSeconds(_Period); + + // + // Find Cycle Period ... + if (scMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mSCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_SHORT, + _Period // + ); + } + else + { + mSCPeriod = scPeriod; + } + + // + if (IsValid(mSCPeriod)) + { + mSCLength = PeriodSeconds(mSCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (mcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mMCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_MEDIUM, + _Period // + ); + } + else + { + mMCPeriod = mcPeriod; + } + + // + if (IsValid(mMCPeriod)) + { + mMCLength = PeriodSeconds(mMCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (lcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mLCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_LONG, + _Period // + ); + } + else + { + mLCPeriod = lcPeriod; + } + + // + if (IsValid(mLCPeriod)) + { + mLCLength = PeriodSeconds(mLCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (hcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mHCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_HIND, + _Period // + ); + } + else + { + mHCPeriod = hcPeriod; + } + + // + if (IsValid(mHCPeriod)) + { + mHCLength = PeriodSeconds(mHCPeriod) / cPeriodSeconds; + } + + // + result = mSCLength > 0 && + mMCLength > mSCLength && + mLCLength > mMCLength && + mHCLength > mLCLength; + + // + // Selecte Applied Cycle ... + if (result) + { + // + switch (appliedCycle) + { + // + case X_MARKET_CYCLE_SHORT: + // + mAppliedLength = mSCLength; + mAppliedPeriod = mSCPeriod; + break; + + // + case X_MARKET_CYCLE_MEDIUM: + // + mAppliedLength = mMCLength; + mAppliedPeriod = mMCPeriod; + break; + + // + case X_MARKET_CYCLE_LONG: + // + mAppliedLength = mLCLength; + mAppliedPeriod = mLCPeriod; + break; + + // + case X_MARKET_CYCLE_HIND: + // + mAppliedLength = mHCLength; + mAppliedPeriod = mHCPeriod; + break; + } + } + + // + return result; +} + +/** + * Initial all Indicator Requirements ... + * + * @return ( false ) + * + */ +bool InitRequirements() +{ + // + bool result = false; + + // + // Handlers ... + + // + // SAR ... + sarHandler = iSAR( + _Symbol, + _Period, + sarStep, + sarMax // + ); + result = sarHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // ATR ... + atrHandler = iATR( + _Symbol, + _Period, + mAppliedLength // + ); + result = atrHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // RSI ... + rsiHandler = iRSI( + _Symbol, + _Period, + mAppliedLength, + rsiAppliedTo // + ); + result = rsiHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // ADX ... + adxHandler = iADX( + _Symbol, + _Period, + mAppliedLength // + ); + result = adxHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // TREND ... + trendHandler = iMA( + _Symbol, + _Period, + mAppliedLength, + 0, + trendMode, + trendAppliedTo // + ); + result = trendHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // Initial Class Instances ... + + // + mDrawer = new XCPOIDrawer(); + mBarAnalyser = new XCBarAnalyser(); + + // + // Initialize and Configure Alert ... + mAlert = new XCAlert(); + mEnableAlerts = + _logAlerts || + _pushAlerts || + _mailAlerts || + _terminalAlerts; + string mPrefix = ShortName + + (!IsValid(mAlertPrefix) + ? "" + : "[" + mAlertPrefix + "]"); + mAlert.SetPrefix(mPrefix); + mAlert.SetLogAlerts(_logAlerts); + mAlert.SetMailAlerts(_mailAlerts); + mAlert.SetPushAlerts(_pushAlerts); + mAlert.SetEnableAlerts(mEnableAlerts); + mAlert.SetTerminalAlerts(_terminalAlerts); + + // + return result; +} + +/** + * Calculate Custom Buffers ... + * + * @param barIndex: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateBuffers( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + if (barsLimit == 0) + { + // + barsLimit = ratesTotal; + firstBarIndex = barsLimit - 1; + } + else + { + firstBarIndex = startCalculationForLastBars; + } + + // + // bool canCalculate = true; + bool canCalculate = + barIndex <= barsLimit; + if (canCalculate) + { + // + // Calculate Values ... + CalculateValues( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + else + { + FillBuffersZero(barIndex); + } +} + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + sarColorBuffer[barIndex] = hideColorIDX; + trendColorBuffer[barIndex] = hideColorIDX; + + // + atrUpperRawBuffer[barIndex] = emptyValue; + atrLowerRawBuffer[barIndex] = emptyValue; +} + +// +// Custom Handlers ... + +/** + * Calculate Values ... + * + * @param barIndex: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void CalculateValues( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = barIndex + 1; + int maxBarIndex = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : ratesTotal; + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + // Cycle Ranges ... + CalculateCycleRanges( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // PV ... + CalculatePV( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // SAR ... + CalculateSAR( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // SBAR ... + CalculateSBar( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // HKBAR ... + CalculateHKBar( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // DELTA ... + CalculateDelta( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // TREND ... + CalculateTrend( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // VOLUME ... + CalculateVolume( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // ATR Band ... + CalculateATRBand( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // Try To Detect Trigger Block ... + + // + // Prevent Calculation ... + if (maxBarIndex - barIndex < maxLength) + { + return; + } + + // + XTriggerBlock tb; + bool has = DetectTriggerBlock( + // + _Symbol, + _Period, + // + tb, + // + mBarAnalyser, + // + // Required Buffers ... + atrBuffer, + rsiBuffer, + adxBuffer, + adxpBuffer, + adxnBuffer, + peakBuffer, + valeBuffer, + deltaBuffer, + sarBuffer, + sarStateBuffer, + trendBuffer, + trendStateBuffer, + atrUpperBuffer, + atrLowerBuffer, + sBarOpenBuffer, + sBarCloseBuffer, + hkSBarOpenBuffer, + hkSBarCloseBuffer, + peakGoldenBuffer, + valeGoldenBuffer, + deltaSignalBuffer, + bullishVolumeSignalBuffer, + bearishVolumeSignalBuffer, + // + barIndex, + // + // Signalling ... + signalR2R, + slAtrMultiplier, + // + // Configs ... + rsiOBLevel, + rsiOSLevel, + adxThreshold, + // + // Validators ... + forceObBarType, + forceOBFVGBarType, + forceHasSwing, + forceHasFLiquidity, + forceHasRLiquidity, + validateGapSequence, + validateBlockEdgeBreakout, + // + // Filters ... + filterBasedOnPV, + filterBasedOnSar, + filterBasedOnRSI, + filterBasedOnADX, + filterBasedOnATR, + filterBasedOnTrend, + filterBasedOnDelta, + filterBasedOnVolume, + filterBasedOnSignalBar, + filterBasedOnHKSignalBar // + ); + if (has) + { + // + // Draw ... + if (drawTriggerBlock) + { + // + has = DrawTriggerBlock( + tb, + mDrawer, + mObjects, + NULL, + drawSignals // + ); + } + + // + // Alert ... + bool canAlert = + mEnableAlerts && + prevCalculated > 0; + bool canLogOnly = + mEnableAlerts && + prevCalculated == 0; + if (has && + (canAlert || + canLogOnly)) + { + // + string message = + tb.trigger.symbol + "," + + ToString(tb.trigger.period) + "> " + + ToString(tb.trigger.dir) + + " Zone Detected at: " + ToString(tb.trigger.to); + + // + if (canLogOnly) + { + mAlert.LogAlert(message); + } + else if (canAlert) + { + mAlert.SendAlert(message); + } + } + } +} + +// +void CalculateCycleRanges( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // SHORT ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_SHORT, + sHHBuffer, + sLLBuffer // + ); + + // + // MEDIUM ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_MEDIUM, + mHHBuffer, + mLLBuffer // + ); + + // + // LONG ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_LONG, + lHHBuffer, + lLLBuffer // + ); + + // + // HIND ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_HIND, + hHHBuffer, + hLLBuffer // + ); +} + +// +void CalculatePV( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = barIndex + 1; + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + double iSHH = sHHBuffer[barIndex]; + double iSLL = sLLBuffer[barIndex]; + + // + double iMHH = mHHBuffer[barIndex]; + double iMLL = mLLBuffer[barIndex]; + + // + double iLHH = lHHBuffer[barIndex]; + double iLLL = lLLBuffer[barIndex]; + + // + double iHHH = hHHBuffer[barIndex]; + double iHLL = hLLBuffer[barIndex]; + + // + // Calculate VALE ... + bool isVale = iSLL == iMLL && + iMLL == iLLL && + iLLL == iHLL; + double iPVale = + isFirstBar + ? emptyValue + : valeBuffer[lastBarIndex]; + double iVale = + isVale + ? iSLL + : iPVale; + valeBuffer[barIndex] = iVale; + + // + // Calculate PEAK ... + bool isPeak = iSHH == iMHH && + iMHH == iLHH && + iLHH == iHHH; + double iPPeak = + isFirstBar + ? emptyValue + : peakBuffer[lastBarIndex]; + double iPeak = + isPeak + ? iSHH + : iPPeak; + peakBuffer[barIndex] = iPeak; + + // + // GOLDEN ... + + XOHCL iBar; + bool isInited = iBar.Init( + _Symbol, + _Period, + barIndex // + ); + + // + // Calculate PV Gold ... + double lastPeakGold = + isFirstBar + ? emptyValue + : peakGoldenBuffer[lastBarIndex]; + double lastValeGold = + isFirstBar + ? emptyValue + : valeGoldenBuffer[lastBarIndex]; + double iPeakGold = lastPeakGold; + double iValeGold = lastValeGold; + if (isInited) + { + // + iPeakGold = iBar.FindHighest(mHCLength, MODE_CLOSE); + if (iPeakGold == 0) + { + iPeakGold = lastPeakGold; + } + + // + iValeGold = iBar.FindLowest(mHCLength, MODE_CLOSE); + if (iValeGold == 0) + { + iValeGold = lastValeGold; + } + } + else + { + // + iPeakGold = lastPeakGold; + iValeGold = lastValeGold; + } + + // + peakGoldenBuffer[barIndex] = iPeakGold; + valeGoldenBuffer[barIndex] = iValeGold; + + // + iBar.Clean(); +} + +// +void CalculateSAR( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + double iLow = low[barIndex]; + double iHigh = low[barIndex]; + double iSar = sarBuffer[barIndex]; + + // + bool isBullish = iSar < iLow; + bool isBearish = iSar > iHigh; + + // + double iSarState = isBullish + ? 1 + : isBearish + ? -1 + : 0; + double iSarColor = iSarState > 0 + ? bullishColorIDX + : iSarState < 0 + ? bearishColorIDX + : neuturalColorIDX; + sarStateBuffer[barIndex] = iSarState; + sarColorBuffer[barIndex] = showSar + ? iSarColor + : hideColorIDX; +} + +// +void CalculateSBar( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // Open ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + open, + sBarOpenBuffer, + barsSignalMethod // + ); + + // + // Close ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + close, + sBarCloseBuffer, + barsSignalMethod // + ); + + // + double min = MathMin(sBarCloseBuffer[barIndex], sBarOpenBuffer[barIndex]); + double max = MathMin(sBarCloseBuffer[barIndex], sBarOpenBuffer[barIndex]); + + // + sBarLowBuffer[barIndex] = min; + sBarHighBuffer[barIndex] = max; + + // + // Calculate HK Signal Color ... + double iSignalColorValue = + sBarOpenBuffer[barIndex] < sBarCloseBuffer[barIndex] + ? bullishColorIDX + : bearishColorIDX; + sBarColorBuffer[barIndex] = + showSignalBars + ? iSignalColorValue + : hideColorIDX; +} + +// +void CalculateHKBar( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = barIndex + 1; + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + double lastHKOpen = + isFirstBar + ? emptyValue + : openHKBuffer[lastBarIndex]; + double lastHKClose = + isFirstBar + ? emptyValue + : closeHKBuffer[lastBarIndex]; + + // + double iHKOpenValue = (lastHKOpen + lastHKClose) / 2; + double iHKCloseValue = (open[barIndex] + high[barIndex] + close[barIndex] + low[barIndex]) / 4; + double iHKHighValue = MathMax(high[barIndex], MathMax(iHKOpenValue, iHKCloseValue)); + double iHKLowValue = MathMin(low[barIndex], MathMin(iHKOpenValue, iHKCloseValue)); + + // + // Raw HK Buffers ... + openHKBuffer[barIndex] = iHKOpenValue; + highHKBuffer[barIndex] = iHKHighValue; + lowHKBuffer[barIndex] = iHKLowValue; + closeHKBuffer[barIndex] = iHKCloseValue; + + // + // XHK Signal ... + + // + // Open ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + openHKBuffer, + hkSBarOpenBuffer, + hkSignalBarMethod // + ); + + // + // Close ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + closeHKBuffer, + hkSBarCloseBuffer, + hkSignalBarMethod // + ); + + // + double min = MathMin(hkSBarCloseBuffer[barIndex], hkSBarOpenBuffer[barIndex]); + double max = MathMin(hkSBarCloseBuffer[barIndex], hkSBarOpenBuffer[barIndex]); + + // + hkSBarLowBuffer[barIndex] = min; + hkSBarHighBuffer[barIndex] = max; + + // + // Calculate HK Signal Color ... + double iHKSignalColorValue = + hkSBarOpenBuffer[barIndex] < hkSBarCloseBuffer[barIndex] + ? bullishColorIDX + : bearishColorIDX; + hkSBarColorBuffer[barIndex] = + showHKSignalBars + ? iHKSignalColorValue + : hideColorIDX; +} + +// +void CalculateDelta( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = barIndex + 1; + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + double iClose = close[barIndex]; + double iOpen = open[barIndex]; + double iVolume = (double)iVolume(_Symbol, _Period, barIndex); + + // + bool isBullish = iClose > iOpen; + bool isBearish = iClose < iOpen; + + // + // DELTA ... + double lastDelta = + isFirstBar + ? emptyValue + : deltaBuffer[lastBarIndex]; + double iAppliedVolume = + isBullish + ? iVolume + : -1 * iVolume; + double iDelta = + lastDelta + iAppliedVolume; + deltaBuffer[barIndex] = iDelta; + + // + // Calculate Delta Signal ... + int deltaSignalsCount = iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + deltaBuffer, + deltaSignalBuffer, + deltaSignalMethod // + ); +} + +// +void CalculateTrend( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + double iLow = low[barIndex]; + double iHigh = high[barIndex]; + double iClose = close[barIndex]; + double iTrend = trendBuffer[barIndex]; + + // + bool isBullish = iTrend < iLow; + bool isBearish = iTrend > iHigh; + + // + double iTrendState = + isBullish + ? 1 + : isBearish + ? -1 + : 0; + double iTrendColor = + iTrendState > 0 + ? bullishColorIDX + : iTrendState < 0 + ? bearishColorIDX + : neuturalColorIDX; + trendStateBuffer[barIndex] = iTrendState; + trendColorBuffer[barIndex] = showTrend + ? iTrendColor + : hideColorIDX; +} + +// +void CalculateVolume( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + double iClose = close[barIndex]; + double iOpen = open[barIndex]; + double iVolume = (double)iVolume(_Symbol, _Period, barIndex); + + // + bool isBullish = iClose > iOpen; + bool isBearish = iClose < iOpen; + + // + double iBullishVolume = emptyValue; + double iBearishVolume = emptyValue; + if (isBullish) + { + iBullishVolume = iVolume; + } + else if (isBearish) + { + iBearishVolume = iVolume; + } + else + { + // + double iHalfVolume = iVolume / 2; + + // + iBullishVolume = iHalfVolume; + iBearishVolume = iHalfVolume; + } + bullishVolumeBuffer[barIndex] = iBullishVolume; + bearishVolumeBuffer[barIndex] = iBearishVolume; + + // + // Calculate Volume Signals ... + + // + int bullishVolumeSignalsCount = iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + bullishVolumeBuffer, + bullishVolumeSignalBuffer, + volumeSignalMethod // + ); + + // + int bearishVolumeSignalsCount = iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + bearishVolumeBuffer, + bearishVolumeSignalBuffer, + volumeSignalMethod // + ); +} + +// +void CalculateATRBand( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + double iATR = atrBuffer[barIndex]; + double iAppliedATR = atrMultiplier * iATR; + double iATRUpperPrice = GetAppliedPrice( + atrUpperPriceType, + open, + high, + low, + close, + barIndex // + ); + double iATRLowerPrice = GetAppliedPrice( + atrLowerPriceType, + open, + high, + low, + close, + barIndex // + ); + double iATRUpper = iATRUpperPrice + iAppliedATR; + double iATRLower = iATRLowerPrice - iAppliedATR; + atrUpperRawBuffer[barIndex] = iATRUpper; + atrLowerRawBuffer[barIndex] = iATRLower; + + // + bool canSignalATR = IsValid(atrSignalMethod); + if (canSignalATR) + { + // + // Upper ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + atrUpperRawBuffer, + atrUpperBuffer, + atrSignalMethod // + ); + + // + // Lower ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + atrLowerRawBuffer, + atrLowerBuffer, + atrSignalMethod // + ); + } + else + { + // + atrUpperBuffer[barIndex] = iATRUpper; + atrLowerBuffer[barIndex] = iATRLower; + } +} + +/** + * Calculate Specified Market Cycle Info ... + * + * @param barIndex: Integer, Bar Index ... + * @param cycle: ENUM_X_MARKET_CYCLES member, Specified Cycle ... + * @param hhBuffer: Highest High Buffer Reference ... + * @param llBuffer: Lowest Low Buffer Reference ... + */ +void CalculateCycle( + int barIndex, + ENUM_X_MARKET_CYCLES cycle, + double &hhBuffer[], + double &llBuffer[] // +) +{ + // + XOHCL bar; + bool isBarInited = bar.Init( + _Symbol, + _Period, + barIndex + // + ); + if (!isBarInited) + { + return; + } + + // + int mLength = 0; + switch (cycle) + { + // + case X_MARKET_CYCLE_SHORT: + mLength = mSCLength; + break; + + // + case X_MARKET_CYCLE_MEDIUM: + mLength = mMCLength; + break; + + // + case X_MARKET_CYCLE_LONG: + mLength = mLCLength; + break; + + // + case X_MARKET_CYCLE_HIND: + mLength = mHCLength; + break; + } + + // + if (mLength == 0) + { + return; + } + + // + // Find Highest High ... + double hhValue = bar.FindHighest( + mLength, + upperMode // + ); + hhBuffer[barIndex] = hhValue; + + // + // Find Lowest Low ... + double llValue = bar.FindLowest( + mLength, + lowerMode // + ); + llBuffer[barIndex] = llValue; + + // + bar.Clean(); +} + +// +void ReadBarStyle() +{ + // + long chartId = ChartID(); + + // + _upColor = GetChartUpColor(chartId); + _downColor = GetChartDownColor(chartId); + _lineColor = GetChartLineColor(chartId); + _bullishColor = GetChartBullishColor(chartId); + _bearishColor = GetChartBearishColor(chartId); +} + +// +void ShowBars() +{ + // + long chartId = ChartID(); + + // + SetChartUpColor(_upColor, chartId); + SetChartDownColor(_downColor, chartId); + SetChartLineColor(_lineColor, chartId); + SetChartBullishColor(_bullishColor, chartId); + SetChartBearishColor(_bearishColor, chartId); +} + +// +void HideBars() +{ + // + long chartId = ChartID(); + + // + SetChartUpColor(CLR_NONE, chartId); + SetChartDownColor(CLR_NONE, chartId); + SetChartLineColor(CLR_NONE, chartId); + SetChartBullishColor(CLR_NONE, chartId); + SetChartBearishColor(CLR_NONE, chartId); +} + +// \ No newline at end of file diff --git a/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xcc.mq5 b/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xcc.mq5 new file mode 100644 index 0000000..2f45b84 --- /dev/null +++ b/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xcc.mq5 @@ -0,0 +1,437 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Candle Styles +// --------------------------------------------------- +// Name: X121 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 X121 XCC Indicator" +#property strict + +// +// START Constants ... +// + +// +// Indicator Short Name ... +#define ShortName "X121 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 = clrGreen; // Up Color +input color downColor = clrRed; // Down Color +input color lineColor = clrGreen; // Line mode and Doji candlestick Color +input color bullishColor = clrGreen; // Bullish Color +input color bearishColor = clrRed; // 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( + 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; +} + +// +// 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/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xche.mq5 b/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xche.mq5 new file mode 100644 index 0000000..d8ed104 --- /dev/null +++ b/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xche.mq5 @@ -0,0 +1,624 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XCHE +// Description: XCHE ... +// +// +// 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 XCHE Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121 XCHE" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +// Market ... +input group "Market"; +input int cheLength = 35; // Length +input int cheLoopback = 26; // Loopback +input double cheMultiplier1 = 3.0; // 1st Multiplier +input double cheMultiplier2 = 3.5; // 2nd Multiplier +input ENUM_APPLIED_PRICE cheUpperAppliedTo = PRICE_HIGH; // Upper Zone Applied to +input ENUM_APPLIED_PRICE cheLowerAppliedTo = PRICE_LOW; // Lower Zone Applied to + +// +input group "Presentation"; + +// +input int cheArrowCode = 159; // CHE Arrow Code + +// +input bool showLE1 = true; // Show 1st Long Exit +input bool showSE1 = true; // Show 1st Short Exit +input bool showLE2 = true; // Show 2st Long Exit +input bool showSE2 = true; // Show 2st Short Exit + +// +// Buffers ... + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#property indicator_chart_window + +// +#property indicator_buffers 8 +#property indicator_plots 8 + +// +// Exit 1 ... + +// +// LONG ... + +// +#define le1BufferIndex 0 +double le1Buffer[]; + +#property indicator_label1 "X121 LE1" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrAqua +#property indicator_style1 STYLE_DOT +#property indicator_width1 1 + +// +// SHORT ... + +// +#define se1BufferIndex 1 +double se1Buffer[]; + +#property indicator_label2 "X121 SE1" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrMagenta +#property indicator_style2 STYLE_DOT +#property indicator_width2 1 + +// +// Exit 2 ... + +// +// LONG ... + +// +#define le2BufferIndex 2 +double le2Buffer[]; + +#property indicator_label3 "X121 LE2" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrAqua +#property indicator_style3 STYLE_SOLID +#property indicator_width3 1 + +// +// SHORT ... + +// +#define se2BufferIndex 3 +double se2Buffer[]; + +#property indicator_label4 "X121 SE2" +#property indicator_type4 DRAW_LINE +#property indicator_color4 clrMagenta +#property indicator_style4 STYLE_SOLID +#property indicator_width4 1 + +// +// Start Buffers ... + +// +#define le1StartBufferIndex 4 +double le1StartBuffer[]; + +// +#property indicator_label5 "X121 LE1 S" +#property indicator_type5 DRAW_ARROW +#property indicator_color5 clrLime + +// +#define se1StartBufferIndex 5 +double se1StartBuffer[]; + +// +#property indicator_label6 "X121 SE1 S" +#property indicator_type6 DRAW_ARROW +#property indicator_color6 clrRed + +// +#define le2StartBufferIndex 6 +double le2StartBuffer[]; + +// +#property indicator_label7 "X121 LE2 S" +#property indicator_type7 DRAW_ARROW +#property indicator_color7 clrLime + +// +#define se2StartBufferIndex 7 +double se2StartBuffer[]; + +// +#property indicator_label8 "X121 SE2 S" +#property indicator_type8 DRAW_ARROW +#property indicator_color8 clrRed + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +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 + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +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 cheLength, here we get max Input cheLength + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +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 +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + if (Bars(_Symbol, _Period) < rates_total) + { + return (prev_calculated); + } + + // + if (ArrayRange(work, 0) != rates_total) + { + ArrayResize(work, rates_total); + } + + // + // this counts Available Bars ... + + // + 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; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = true; + + // + result = + cheLength >= 9 && + cheLoopback >= 0; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(cheLength, cheLoopback); + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // LEVEL 1 ... + + // + // Long Exit 1 ... + + // + // Draw Type ... + ENUM_DRAW_TYPE le1DrawType = showLE1 ? DRAW_LINE : DRAW_NONE; + ENUM_DRAW_TYPE le1StartDrawType = showLE1 ? DRAW_ARROW : DRAW_NONE; + + // + // Buffer ... + SetIndexBuffer(le1BufferIndex, le1Buffer, INDICATOR_DATA); + PlotIndexSetInteger(le1BufferIndex, PLOT_SHOW_DATA, showLE1); + PlotIndexSetInteger(le1BufferIndex, PLOT_DRAW_TYPE, le1DrawType); + + // + // Start Buffer ... + SetIndexBuffer(le1StartBufferIndex, le1StartBuffer, INDICATOR_DATA); + PlotIndexSetInteger(le1StartBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(le1StartBufferIndex, PLOT_DRAW_TYPE, le1StartDrawType); + PlotIndexSetInteger(le1StartBufferIndex, PLOT_ARROW, cheArrowCode); + + // + // Short Exit 1 ... + + // + // Draw Type ... + ENUM_DRAW_TYPE se1DrawType = showSE1 ? DRAW_LINE : DRAW_NONE; + ENUM_DRAW_TYPE se1StartDrawType = showSE1 ? DRAW_ARROW : DRAW_NONE; + + // + // Buffer ... + SetIndexBuffer(se1BufferIndex, se1Buffer, INDICATOR_DATA); + PlotIndexSetInteger(se1BufferIndex, PLOT_SHOW_DATA, showSE1); + PlotIndexSetInteger(se1BufferIndex, PLOT_DRAW_TYPE, se1DrawType); + + // + // Start Buffer ... + SetIndexBuffer(se1StartBufferIndex, se1StartBuffer, INDICATOR_DATA); + PlotIndexSetInteger(se1StartBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(se1StartBufferIndex, PLOT_DRAW_TYPE, se1StartDrawType); + PlotIndexSetInteger(se1StartBufferIndex, PLOT_ARROW, cheArrowCode); + + // + // LEVEL 2 ... + + // + // Long Exit 2 ... + + // + // Draw Type ... + ENUM_DRAW_TYPE le2DrawType = showLE2 ? DRAW_LINE : DRAW_NONE; + ENUM_DRAW_TYPE le2StartDrawType = showLE2 ? DRAW_ARROW : DRAW_NONE; + + // + // Buffer ... + SetIndexBuffer(le2BufferIndex, le2Buffer, INDICATOR_DATA); + PlotIndexSetInteger(le2BufferIndex, PLOT_SHOW_DATA, showLE2); + PlotIndexSetInteger(le2BufferIndex, PLOT_DRAW_TYPE, le2DrawType); + + // + // Start Buffer ... + SetIndexBuffer(le2StartBufferIndex, le2StartBuffer, INDICATOR_DATA); + PlotIndexSetInteger(le2StartBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(le2StartBufferIndex, PLOT_DRAW_TYPE, le2StartDrawType); + PlotIndexSetInteger(le2StartBufferIndex, PLOT_ARROW, cheArrowCode); + + // + // Short Exit 2 ... + + // + // Draw Type ... + ENUM_DRAW_TYPE se2DrawType = showSE2 ? DRAW_LINE : DRAW_NONE; + ENUM_DRAW_TYPE se2StartDrawType = showSE2 ? DRAW_ARROW : DRAW_NONE; + + // + // Buffer ... + SetIndexBuffer(se2BufferIndex, se2Buffer, INDICATOR_DATA); + PlotIndexSetInteger(se2BufferIndex, PLOT_SHOW_DATA, showSE2); + PlotIndexSetInteger(se2BufferIndex, PLOT_DRAW_TYPE, se2DrawType); + + // + // Start Buffer ... + SetIndexBuffer(se2StartBufferIndex, se2StartBuffer, INDICATOR_DATA); + PlotIndexSetInteger(se2StartBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(se2StartBufferIndex, PLOT_DRAW_TYPE, se2StartDrawType); + PlotIndexSetInteger(se2StartBufferIndex, PLOT_ARROW, cheArrowCode); +} + +/** + * 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 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 ... + le1Buffer[bar_index] = le1StartBuffer[bar_index] = se1Buffer[bar_index] = se1StartBuffer[bar_index] = EMPTY_VALUE; + le2Buffer[bar_index] = le2StartBuffer[bar_index] = se2Buffer[bar_index] = se2StartBuffer[bar_index] = EMPTY_VALUE; + + // + int start = MathMax(bar_index - cheLoopback, 0); + + // + // Calculate ATR Value ... + double atrValue = 0; + for (int k = 1; k <= cheLength && (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)cheLength; + + // + // Retrieve Highest High and Lowest Lows ... + double cheLoopbackMax = high[ArrayMaximum(high, start, cheLoopback)]; + double cheLoopbackMin = low[ArrayMinimum(low, start, cheLoopback)]; + + // + // Fill Multi Dimesional Working Array ... + work[bar_index][hi1Idx] = cheLoopbackMax - cheMultiplier1 * atrValue; + work[bar_index][lo1Idx] = cheLoopbackMin + cheMultiplier1 * atrValue; + work[bar_index][hi2Idx] = cheLoopbackMax - cheMultiplier2 * atrValue; + work[bar_index][lo2Idx] = cheLoopbackMin + cheMultiplier2 * 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 (cheMultiplier1 > 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]; + } + + // + le1Buffer[bar_index] = work[bar_index][hi1Idx]; + + // + if (le1Buffer[bar_index - 1] == EMPTY_VALUE) + { + le1StartBuffer[bar_index] = le1Buffer[bar_index]; + } + } + + // + // Short ... + if (cheMultiplier1 > 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]; + } + + // + se1Buffer[bar_index] = work[bar_index][lo1Idx]; + + // + if (se1Buffer[bar_index - 1] == EMPTY_VALUE) + { + se1StartBuffer[bar_index] = se1Buffer[bar_index]; + } + } + + // + // Exit 2 ... + + // + // Long ... + if (cheMultiplier2 > 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]; + } + + // + le2Buffer[bar_index] = work[bar_index][hi2Idx]; + + // + if (le2Buffer[bar_index - 1] == EMPTY_VALUE) + { + le2StartBuffer[bar_index] = le2Buffer[bar_index]; + } + } + + // + // Short ... + if (cheMultiplier2 > 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]; + } + + // + se2Buffer[bar_index] = work[bar_index][lo2Idx]; + + // + if (se2Buffer[bar_index - 1] == EMPTY_VALUE) + { + se2StartBuffer[bar_index] = se2Buffer[bar_index]; + } + } + } +} + +// \ No newline at end of file diff --git a/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xct.mq5 b/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xct.mq5 new file mode 100644 index 0000000..286882a --- /dev/null +++ b/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xct.mq5 @@ -0,0 +1,262 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// --------------------------------------------- +// Name: X121 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 X121 XCT Indicator" +#property strict + +// +// START Constants ... +// + +// +#define ShortName "X121 XCT" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input int fontSize = 15; // Font Size +input string font = "Arial"; // Font +input color clr = clrYellow; // Text Color +input ENUM_BASE_CORNER corner = CORNER_RIGHT_LOWER; // Text Position + +// +input group "Presentation"; +input bool showTimer = 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 ... +// +bool isCreatedObject; +string tag; +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + + // + tag = ShortName + _Symbol + ToString(_Period); + + // + // 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 + + // + // Delete Object ... + ObjectDelete(0, tag); + + // + 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 ... +) +{ + // + if (!showTimer) + { + return rates_total; + } + + // + 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; + + // + if (IsValid(tag) && !isCreatedObject) + { + CreateIndicatorObject(); + } + + // + if (isCreatedObject) + { + ObjectSetString(0, tag, OBJPROP_TEXT, objText); + } + + // + 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 (!showTimer || + !IsValid(tag)) + { + return; + } + + // + isCreatedObject = ObjectCreate(0, tag, OBJ_LABEL, 0, 0, 0); + ObjectSetInteger(0, tag, OBJPROP_CORNER, corner); + ObjectSetInteger(0, tag, OBJPROP_XDISTANCE, 10); + ObjectSetInteger(0, tag, 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; + } + + // + int mFontSize = fontSize > 0 + ? fontSize + : 10; + + // + string mFont = IsValid(font) + ? font + : "Arial"; + + // + ObjectSetString(0, tag, OBJPROP_FONT, mFont); + ObjectSetInteger(0, tag, OBJPROP_COLOR, clr); + ObjectSetInteger(0, tag, OBJPROP_ANCHOR, Anchor); + ObjectSetInteger(0, tag, OBJPROP_FONTSIZE, mFontSize); +} + +// +// END Functions ... +// diff --git a/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xczone.mq5 b/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xczone.mq5 new file mode 100644 index 0000000..f6d56a4 --- /dev/null +++ b/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xczone.mq5 @@ -0,0 +1,2452 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 X3MA +// Description: X3MA ... +// +// +// 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 XCZone Indicator" +#property strict + +// +// Definitions ... +// +#define ShortName "X121 XCZone" + +// +// Includes Common Library ... +#include "../Classes/x-saherelm.x-alert.class.mq5" +#include "../Classes/x-saherelm.x-bar.analyser.class.mq5" +#include "../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" +#include "../Libraries/x-saherelm.x-poi.lib.mq5" + +// +// Inputs ... +input group "Market"; +input ENUM_X_PERIOD_METHOD trendPeriodMethod = X_PERIOD_AUTO; // How to Find Trend Period +input ENUM_TIMEFRAMES trendPeriod = NULL; // Trend Time Period +input ENUM_MA_METHOD trendMode = MODE_SMA; // Trend Mode +input ENUM_APPLIED_PRICE trendAppliedTo = PRICE_CLOSE; // Trend Applied To +input double sarStep = 0.02; // Sar Step +input double sarMax = 0.2; // Sar Maximum +input int adxLength = 14; // ADX Length +input double adxThreshold = 25.0; // ADX Threshold +input int rsiLength = 14; // RSI Length +input double rsiOBLevel = 70.0; // RSI OB Level +input double rsiOSLevel = 30.0; // RSI OS Level +input ENUM_APPLIED_PRICE rsiAppliedTo = PRICE_CLOSE; // RSI Applied To +input int deltaSignalLength = 14; // Delta Signal Length +input ENUM_X_MA_METHOD deltaSignalMethod = X_MA_MODE_EMA; // Delta Signalling Method +input int volumeSignalLength = 14; // Volume Signal Length +input ENUM_X_MA_METHOD volumeSignalMethod = X_MA_MODE_EMA; // Volume Signalling Method + +// +// Validating ... +input group "Validating"; +input int minZoneLength = 7; // Minimum Length of Consolidation Zone +input double maxZoneRangeInPoints = 70; // Max Zone Range in Point +input double maxAllowedEntryDistance = 30; // Max Allowed Entry Distance +input bool forceGapBarsBreakout = true; // Force Zone's Gap Bar's Breakes Out +input bool forceHasSwing = true; // Force Zone's Has Propper Swing +input bool forceHasPinBarEntry = true; // Force Zone's Ends with a Pin Bar + +// +// Filtering ... +input group "Filtering"; +input bool filterBasedOnSar = false; // Filter Pivots Based on Sar +input bool filterBasedOnRSI = false; // Filter Pivots Based on RSI +input bool filterBasedOnADX = false; // Filter Pivots Based on ADX +input bool filterBasedOnTrend = false; // Filter Pivots Based on Trend + +// +// Presentation ... +input group "Presentation"; +input bool showSar = false; // Show Sar +input bool showTrend = false; // Show Trend +input bool rayLeft = false; // Ray to Left +input bool drawZones = true; // Draw Detected Zones +input bool drawRRofZones = true; // Draw Zone's Risk Reward Ratios +input int boxWidth = 2; // Box Width +input color bullishColor = clrLime; // Bullish Color +input color bearishColor = clrRed; // Bearish Color +input ENUM_LINE_STYLE boxStyle = STYLE_SOLID; // Box Style + +// +input int startCalculationForLastBars = 5000; // Calculate Last n Bars +int sarArrowCode = 159; // Sar Arrow Code +int rrZoneLength = 7; // Draw Risk Reward Ratio till n Bars + +// +// Alert ... +input group "Alerts"; +input string alertPrefix = ""; // Alert Prefix +input bool _logAlerts = true; // Log Alerts +input bool _pushAlerts = true; // Push Alerts +input bool _mailAlerts = false; // Mail Alerts +input bool _terminalAlerts = true; // Terminal Alerts + +// +// Buffers ... + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#define bullishState 1 +#define neuturalState 0 +#define bearishState -1 + +// +#define emptyValue 0.0 + +// +#property indicator_chart_window + +// +#property indicator_buffers 16 +#property indicator_plots 2 + +// +// Plot Buffers ... + +// +// TREND ... + +// +#define trendBufferIndex 0 +#define trendBufferPlotIndex 0 +double trendBuffer[]; + +// +#define trendColorBufferIndex 1 +double trendColorBuffer[]; + +// +#property indicator_label1 "X121 Trend" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 CLR_NONE, clrAqua, clrMagenta, clrGray +#property indicator_style1 STYLE_DASH +#property indicator_width1 2 + +// +// SAR ... + +// +#define sarBufferIndex 2 +#define sarBufferPlotIndex 2 +double sarBuffer[]; + +// +#define sarColorBufferIndex 3 +double sarColorBuffer[]; + +// +#property indicator_label2 "X121 SAR" +#property indicator_type2 DRAW_COLOR_ARROW +#property indicator_color2 CLR_NONE, clrAqua, clrMagenta, clrGray +#property indicator_width2 2 + +// +// Data Buffers ... + +#define mLastBufferIndex 3 + +// +// TREND State ... + +// +#define trendStateBufferIndex mLastBufferIndex + 1 +double trendStateBuffer[]; + +// +// SAR ... + +// +#define sarStateBufferIndex mLastBufferIndex + 2 +double sarStateBuffer[]; + +// +// RSI ... + +// +#define rsiBufferIndex mLastBufferIndex + 3 +double rsiBuffer[]; + +// +// ADX ... + +// +#define adxBufferIndex mLastBufferIndex + 4 +double adxBuffer[]; + +// +#define adxpBufferIndex mLastBufferIndex + 5 +double adxpBuffer[]; + +// +#define adxnBufferIndex mLastBufferIndex + 6 +double adxnBuffer[]; + +// +// DELTA ... + +// +#define deltaBufferIndex mLastBufferIndex + 7 +double deltaBuffer[]; + +// +#define deltaSignalBufferIndex mLastBufferIndex + 8 +double deltaSignalBuffer[]; + +// +// VOLUMES ... + +// +#define bullishVolumeBufferIndex mLastBufferIndex + 9 +double bullishVolumeBuffer[]; + +// +#define bearishVolumeBufferIndex mLastBufferIndex + 10 +double bearishVolumeBuffer[]; + +// +#define bullishVolumeSignalBufferIndex mLastBufferIndex + 11 +double bullishVolumeSignalBuffer[]; + +// +#define bearishVolumeSignalBufferIndex mLastBufferIndex + 12 +double bearishVolumeSignalBuffer[]; + +// +// Variables, Properties and etc ... + +// +int limit; + +// +int maxLength; + +// +int firstBarIndex; + +// +XCAlert *alert; +double mPoints = 0; +CArrayObj mObjects; +XCPOIDrawer *drawer; +bool mEnableAlerts = false; +XCBarAnalyser *barAnalyser; +int mTrendPeriodLength = 0; +int sarHandler = INVALID_HANDLE; +int rsiHandler = INVALID_HANDLE; +int adxHandler = INVALID_HANDLE; +int trendHandler = INVALID_HANDLE; +ENUM_TIMEFRAMES mTrendPeriod = NULL; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + + // + // Configure Alert ... + alert = new XCAlert(); + mEnableAlerts = + _logAlerts || + _pushAlerts || + _mailAlerts || + _terminalAlerts; + string mPrefix = ShortName + + (!IsValid(alertPrefix) + ? "" + : "[" + alertPrefix + "]"); + alert.SetPrefix(mPrefix); + alert.SetLogAlerts(_logAlerts); + alert.SetMailAlerts(_mailAlerts); + alert.SetPushAlerts(_pushAlerts); + alert.SetEnableAlerts(mEnableAlerts); + alert.SetTerminalAlerts(_terminalAlerts); + + // + drawer = new XCPOIDrawer(); + barAnalyser = new XCBarAnalyser(); + + // + // Initializing TrendPeriod ... + int cPeriodSeconds = PeriodSeconds(_Period); + if (trendPeriodMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mTrendPeriod = GetCyclePeriod( + X_MARKET_CYCLE_HIND, + _Period // + ); + } + else + { + mTrendPeriod = trendPeriod; + } + if (IsValid(mTrendPeriod)) + { + mTrendPeriodLength = PeriodSeconds(mTrendPeriod) / cPeriodSeconds; + } + + // + // SAR ... + sarHandler = iSAR( + _Symbol, + _Period, + sarStep, + sarMax // + ); + bool isInited = sarHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // RSI ... + rsiHandler = iRSI( + _Symbol, + _Period, + rsiLength, + rsiAppliedTo // + ); + isInited = rsiHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // ADX ... + adxHandler = iADX( + _Symbol, + _Period, + adxLength // + ); + isInited = adxHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // TREND ... + trendHandler = iMA( + _Symbol, + _Period, + mTrendPeriodLength, + 0, + trendMode, + trendAppliedTo // + ); + isInited = trendHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + mPoints = GetPoints(_Symbol); + + // + // 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; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +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 + + // + mObjects.Clear(); + + // + delete alert; + delete drawer; + + // + ZeroMemory(alert); + ZeroMemory(drawer); + ZeroMemory(barAnalyser); + + // + IndicatorRelease(sarHandler); + IndicatorRelease(rsiHandler); + IndicatorRelease(adxHandler); + IndicatorRelease(trendHandler); +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // 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); + + // + // Validate Calculated Bars ... + + // + // SAR ... + int sarCalculatedBars = BarsCalculated(sarHandler); + + // + // RSI ... + int rsiCalculatedBars = BarsCalculated(rsiHandler); + + // + // ADX ... + int adxCalculatedBars = BarsCalculated(adxHandler); + + // + // TREND ... + int trendCalculatedBars = BarsCalculated(trendHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // SAR ... + sarCalculatedBars >= maxLength && + // + // RSI ... + rsiCalculatedBars >= maxLength && + // + // ADX ... + adxCalculatedBars >= maxLength && + // + // TREND ... + trendCalculatedBars >= maxLength + // + ; + if (!isPassedRequiredCalculatedBars) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + + // + // SAR ... + int copiedSars = CopyBuffer(sarHandler, MAIN_LINE, 0, limit, sarBuffer); + + // + // RSI ... + int copiedRSIs = CopyBuffer(rsiHandler, MAIN_LINE, 0, limit, rsiBuffer); + + // + // ADX ... + int copiedADXs = CopyBuffer(adxHandler, MAIN_LINE, 0, limit, adxBuffer); + + // + // ADX Plus ... + int copiedADXPs = CopyBuffer(adxHandler, PLUSDI_LINE, 0, limit, adxpBuffer); + + // + // ADX Negative ... + int copiedADXNs = CopyBuffer(adxHandler, MINUSDI_LINE, 0, limit, adxnBuffer); + + // + // TREND ... + int copiedTrends = CopyBuffer(trendHandler, MAIN_LINE, 0, limit, trendBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // SAR ... + copiedSars >= limit && + // + // RSI ... + copiedRSIs >= limit && + // + // TREND ... + copiedTrends >= limit + // + ; + if (!isPassedRequiredCopiedItems) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + result = + // + sarMax > 0 && + sarStep > 0 && + adxLength > 0 && + rsiLength > 0 && + rsiOBLevel > 0 && + rsiOSLevel > 0 && + sarMax > sarStep && + minZoneLength > 2 && + deltaSignalLength > 2 && + volumeSignalLength > 2 && + deltaSignalMethod != X_MA_MODE_NONE && + volumeSignalMethod != X_MA_MODE_NONE && + IsValid(trendPeriodMethod, trendPeriod) + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(minZoneLength, rsiLength); + result = MathMax(result, adxLength); + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + + // + // TREND ... + + // + ArraySetAsSeries(trendBuffer, true); + SetIndexBuffer(trendBufferIndex, trendBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(trendBufferPlotIndex, PLOT_SHOW_DATA, showTrend); + + // + PlotIndexSetDouble(trendBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(trendColorBuffer, true); + SetIndexBuffer(trendColorBufferIndex, trendColorBuffer, INDICATOR_COLOR_INDEX); + + // + // SAR ... + + // + ArraySetAsSeries(sarBuffer, true); + SetIndexBuffer(sarBufferIndex, sarBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(sarBufferPlotIndex, PLOT_SHOW_DATA, showSar); + + // + PlotIndexSetDouble(sarBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(sarBufferPlotIndex, PLOT_ARROW, sarArrowCode); + + // + ArraySetAsSeries(sarColorBuffer, true); + SetIndexBuffer(sarColorBufferIndex, sarColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Data Buffers ... + + // + ArraySetAsSeries(trendStateBuffer, true); + SetIndexBuffer(trendStateBufferIndex, trendStateBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(sarStateBuffer, true); + SetIndexBuffer(sarStateBufferIndex, sarStateBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(rsiBuffer, true); + SetIndexBuffer(rsiBufferIndex, rsiBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(adxBuffer, true); + SetIndexBuffer(adxBufferIndex, adxBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(adxpBuffer, true); + SetIndexBuffer(adxpBufferIndex, adxpBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(adxnBuffer, true); + SetIndexBuffer(adxnBufferIndex, adxnBuffer, INDICATOR_CALCULATIONS); + + // + // DELTA ... + + // + ArraySetAsSeries(deltaBuffer, true); + SetIndexBuffer(deltaBufferIndex, deltaBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(deltaSignalBuffer, true); + SetIndexBuffer(deltaSignalBufferIndex, deltaSignalBuffer, INDICATOR_CALCULATIONS); + + // + // VOLUME ... + + // + ArraySetAsSeries(bullishVolumeBuffer, true); + SetIndexBuffer(bullishVolumeBufferIndex, bullishVolumeBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(bearishVolumeBuffer, true); + SetIndexBuffer(bearishVolumeBufferIndex, bearishVolumeBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(bullishVolumeSignalBuffer, true); + SetIndexBuffer(bullishVolumeSignalBufferIndex, bullishVolumeSignalBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(bearishVolumeSignalBuffer, true); + SetIndexBuffer(bearishVolumeSignalBufferIndex, bearishVolumeSignalBuffer, INDICATOR_CALCULATIONS); +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + // + IndicatorSetInteger(INDICATOR_DIGITS, _Digits); + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +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[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + if (barsLimit == 0) + { + // + barsLimit = ratesTotal; + firstBarIndex = barsLimit - 1; + } + else + { + // + firstBarIndex = startCalculationForLastBars; + } + + // + // bool canCalculate = true; + bool canCalculate = + bar_index <= barsLimit; + if (canCalculate) + { + // + // Calculate Values ... + CalculateValues( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + else + { + FillBuffersZero(bar_index); + } +} + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ +} + +/** + * Calculate Values ... + * + * @param bar_index: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void CalculateValues( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = bar_index + 1; + bool isFirstBar = + startCalculationForLastBars > 0 + ? bar_index == startCalculationForLastBars + : bar_index == firstBarIndex; + + // + // Bar Info ... + double iLow = high[bar_index]; + double iHigh = high[bar_index]; + double iClose = close[bar_index]; + double iOpen = open[bar_index]; + double iVolume = (double)iVolume(_Symbol, _Period, bar_index); + + // + bool isBullish = iClose > iOpen; + bool isBearish = iClose < iOpen; + + // + double points = GetPoints(_Symbol); + + // + // Calculate Sar Color Buffer ... + double iSar = sarBuffer[bar_index]; + + // + double iSarState = neuturalState; + double iSarColor = neuturalColorIDX; + if (iLow > iSar) + { + // + iSarState = bullishState; + iSarColor = !showSar + ? hideColorIDX + : bullishColorIDX; + } + else if (iHigh < iSar) + { + // + iSarState = bearishState; + iSarColor = !showSar + ? hideColorIDX + : bearishColorIDX; + } + sarStateBuffer[bar_index] = iSarState; + sarColorBuffer[bar_index] = iSarColor; + + // + // Calculate Trend Color Buffer ... + double iTrend = trendBuffer[bar_index]; + + // + double iTrendState = neuturalState; + double iTrendColor = neuturalColorIDX; + if (iClose > iTrend) + { + // + iTrendState = bullishState; + iTrendColor = !showTrend + ? hideColorIDX + : bullishColorIDX; + } + else if (iClose < iTrend) + { + // + iTrendState = bearishState; + iTrendColor = !showTrend + ? hideColorIDX + : bearishColorIDX; + } + trendStateBuffer[bar_index] = iTrendState; + trendColorBuffer[bar_index] = iTrendColor; + + // + // DELTA ... + double lastDelta = + isFirstBar + ? emptyValue + : deltaBuffer[lastBarIndex]; + double iAppliedVolume = + isBullish + ? iVolume + : -1 * iVolume; + double iDelta = + lastDelta + iAppliedVolume; + deltaBuffer[bar_index] = iDelta; + + // + // Calculate Delta Signal ... + int deltaSignalsCount = iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + deltaSignalLength, + deltaBuffer, + deltaSignalBuffer, + deltaSignalMethod // + ); + + // + // VOLUME ... + + // + double iBullishVolume = emptyValue; + double iBearishVolume = emptyValue; + if (isBullish) + { + iBullishVolume = iVolume; + } + else if (isBearish) + { + iBearishVolume = iVolume; + } + else + { + // + double iHalfVolume = iVolume / 2; + + // + iBullishVolume = iHalfVolume; + iBearishVolume = iHalfVolume; + } + bullishVolumeBuffer[bar_index] = iBullishVolume; + bearishVolumeBuffer[bar_index] = iBearishVolume; + + // + // Calculate Volume Signals ... + + // + int bullishVolumeSignalsCount = iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + volumeSignalLength, + bullishVolumeBuffer, + bullishVolumeSignalBuffer, + volumeSignalMethod // + ); + + // + int bearishVolumeSignalsCount = iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + volumeSignalLength, + bearishVolumeBuffer, + bearishVolumeSignalBuffer, + volumeSignalMethod // + ); + + // + // Detect Trigger Zone ... + DetectTriggerZone( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); +} + +// +void DetectTriggerZone( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // Check Prev Bar ... + + // + int lastBarIndex = bar_index + 1; + int maxBarIndex = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : ratesTotal; + bool isFirstBar = + bar_index == maxBarIndex; + + // + // Prevent Calculation ... + if (maxBarIndex - bar_index < minZoneLength) + { + return; + } + + // + int zIDX = 0; + int cIDX = 0; + int pIDX = 0; + int p2IDX = 0; + int p3IDX = 0; + int p4IDX = 0; + double ll = 0; + double hh = 0; + bool has = false; + ENUM_X_DIRECTION iDir; + + // + // Retrieve Required Bars ... + + // + XOHCL zBar; // Current Start Checking Bar (Usually Used for Triggering) ... + XOHCL cBar; // Current Finished Bar which Start Detecting Structures based on it ( End of Block and FVG Bar ) ... + XOHCL pBar; // Determines Block Gap Bar (all Filtering must applied and Check using this Bar and it's Next Bar) ... + XOHCL p2Bar; // Determines FVG's Start Bar in a Block ... + XOHCL p3Bar; // First Verification of Block ... + XOHCL p4Bar; // Seccond Verification of Block ... + + // + has = zBar.Init( + _Symbol, + _Period, + bar_index // + ); + has = + has && + zBar.GetPreviousBar(cBar); + has = + has && + cBar.GetPreviousBar(pBar); + has = + has && + pBar.GetPreviousBar(p2Bar); + has = + has && + p2Bar.GetPreviousBar(p3Bar); + has = + has && + p3Bar.GetPreviousBar(p4Bar); + if (!has) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + + // + // Define Zone Structure ... + XBoxZone zone; + + // + // Detect Based Order Block using CBar ... + has = barAnalyser.IsOB( + cBar, + zone, + true, // Force FVG Bar Type ... + true // Force Block Two Bar Checking ... + ); + + // + // Ensure a Block is Detected ... + if (!has) + { + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + + // + zIDX = zBar.Index(); + cIDX = cBar.Index(); + pIDX = pBar.Index(); + p2IDX = p2Bar.Index(); + p3IDX = p3Bar.Index(); + p4IDX = p4Bar.Index(); + + // + bool isBullish = + has && + zone.IsBullish(); + + // + bool isBearish = + has && + zone.IsBearish(); + + // + int toIDX = zone.ToIndex(); + int fromIDX = zone.FromIndex(); + + // + // Validating p2Bar and p3Bar Direction ... + if (has) + { + // + iDir = Opposit(zone.dir); + + // + has = + iDir == p3Bar.GetDirection() || + iDir == p4Bar.GetDirection(); + if (!has) + { + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + } + + // + // Start Validating Block based on + // Detected One ... + + // + // Validating Using Max Range ... + has = maxZoneRangeInPoints > 0; + if (has) + { + // + double range = zone.GetRange(); + has = range <= maxZoneRangeInPoints * mPoints; + if (!has) + { + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + } + + // + // Validate Gap Endup with PinBar ... + has = forceHasPinBarEntry; + if (has) + { + // + bool isBullishRejected = + isBullish && + cBar.IsBullish() && + cBar.GetLowShadow() > cBar.GetHighShadow(); + + // + bool isBearishRejected = + isBearish && + cBar.IsBearish() && + cBar.GetLowShadow() < cBar.GetHighShadow(); + + // + has = isBullishRejected || + isBearishRejected; + if (!has) + { + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + } + + // + // Validating Gap Bar must a Momentum Bar and + // Breakes out Zone's Directional Edge ... + // for Bullish: Upper + // for Bearish: Lower + has = forceGapBarsBreakout; + if (has) + { + // + // Gap Bar is PBar ... + + // + // Check Gap Bar is Momentum Bar ... + has = barAnalyser.IsMomentum( + pBar, + iDir // + ); + bool isBullishMomentum = + has && + IsBullish(iDir); + bool isBearishMomentum = + has && + IsBearish(iDir); + + // + // Check Gap Bar's Breakout ... + + // + bool isBullishBreakedout = + isBullish && + pBar.IsBullish() && + isBullishMomentum && + pBar.GetUp() > zone.upper && + pBar.GetDown() < zone.upper; + + // + bool isBearishBreakedout = + isBearish && + pBar.IsBearish() && + isBearishMomentum && + pBar.GetUp() > zone.lower && + pBar.GetDown() < zone.lower; + + // + has = isBullishBreakedout || + isBearishBreakedout; + if (!has) + { + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + } + + // + // Validate Zone Has Propper Swing ... + // for Bullish: p2Bar or p3Bar must be a Swing Low ... + // for Bearish: p2Bar or p3Bar must be a Swing High ... + has = forceHasSwing; + if (has) + { + // + // p2Bar ... + bool isP2BarSwing = + barAnalyser + .IsSimpleSwing( + p2Bar, + iDir // + ); + bool isP2BarSwingLow = + isP2BarSwing && + IsBullish(iDir); + bool isP2BarSwingHigh = + isP2BarSwing && + IsBearish(iDir); + + // + // p3Bar ... + bool isP3BarSwing = + barAnalyser + .IsSimpleSwing( + p3Bar, + iDir // + ); + bool isP3BarSwingLow = + isP3BarSwing && + IsBullish(iDir); + bool isP3BarSwingHigh = + isP3BarSwing && + IsBearish(iDir); + + // + bool hasSwingLow = + isBullish && + (isP2BarSwingLow || + isP3BarSwingLow); + + // + bool hasSwingHigh = + isBearish && + (isP2BarSwingHigh || + isP3BarSwingHigh); + + // + has = + hasSwingLow || + hasSwingHigh; + if (!has) + { + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + } + + // + // Validating Using Swing Length ... + has = minZoneLength > 0; + if (has) + { + // + XOHCL fromBar; + has = zone.FromBar(fromBar); + if (has) + { + // + // Retrieve HH and LL ... + ll = fromBar.FindLowest(minZoneLength, MODE_LOW); + hh = fromBar.FindHighest(minZoneLength, MODE_HIGH); + + // + // Validate Using HH and LL ... + + // + bool isBullishValid = + isBullish && + ll >= zone.lower; + + // + bool isBearishValid = + isBearish && + hh <= zone.upper; + + // + has = isBullishValid || + isBearishValid; + if (!has) + { + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + + // + // Update Zone's From Time ... + zone.from = GetBarTime( + zone.symbol, + zone.period, + fromBar.Index() + minZoneLength // + ); + } + + // + fromBar.Clean(); + } + + // + // Validate Max Allowed Entry Distance ... + has = maxAllowedEntryDistance > 0; + if (has) + { + // + double base = + isBullish + ? zone.upper + : zone.lower; + double entryDistance = MathAbs(zBar.open - base); + has = entryDistance <= maxAllowedEntryDistance * mPoints; + if (!has) + { + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + } + + // + // Here we Ensure which have a Valid Zone using Different Applied Validations ... + // from now we are Going to Filtered Validate Zones ... + + // + // Check Exists Filters or not ... + has = filterBasedOnSar || + filterBasedOnRSI || + filterBasedOnADX || + filterBasedOnTrend; + if (has) + { + // + // Do Apply Several Exists Filters ... + + // + // SAR Filter ... + if (filterBasedOnSar) + { + // + // Reading Conditions Values ... + + // + double zSar = sarBuffer[zIDX]; + double cSar = sarBuffer[cIDX]; + double pSar = sarBuffer[pIDX]; + double p2Sar = sarBuffer[p2IDX]; + double p3Sar = sarBuffer[p3IDX]; + double p4Sar = sarBuffer[p4IDX]; + + // + // Create Required Conditions ... + + // + bool isZSarBullish = zSar < zBar.low; + bool isZSarBearish = zSar > zBar.high; + + // + bool isCSarBullish = cSar < cBar.low; + bool isCSarBearish = cSar > cBar.high; + + // + bool isPSarBullish = pSar < pBar.low; + bool isPSarBearish = pSar > pBar.high; + + // + bool isP2SarBullish = p2Sar < p2Bar.low; + bool isP2SarBearish = p2Sar > p2Bar.high; + + // + bool isCSarSwitchedToBullish = + isZSarBullish && + isCSarBullish && + !isPSarBullish && + cBar.IsBullish() && + cBar.GetUp() > pSar; + + // + bool isCSarSwitchedToBearish = + isZSarBearish && + isCSarBearish && + !isPSarBearish && + cBar.IsBearish() && + cBar.GetDown() < pSar; + + // + bool isPSarSwitchedToBullish = + isZSarBullish && + isCSarBullish && + isPSarBullish && + !isP2SarBullish && + pBar.IsBullish() && + pBar.GetUp() > p2Sar; + + // + bool isPSarSwitchedToBearish = + isZSarBearish && + isCSarBearish && + isPSarBearish && + !isP2SarBearish && + pBar.IsBearish() && + pBar.GetDown() < p2Sar; + + // + // Summarize Filtering ... + + // + bool isBullishFiltered = + isBullish && + (isCSarSwitchedToBullish || + isPSarSwitchedToBullish); + + // + bool isBearishFiltered = + isBearish && + (isCSarSwitchedToBearish || + isPSarSwitchedToBearish); + + // + has = + isBullishFiltered || + isBearishFiltered; + if (!has) + { + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + } + + // + // RSI Filter ... + if (filterBasedOnRSI) + { + // + // Reading Conditions Values ... + + // + double rsiTrend = (rsiOBLevel + rsiOSLevel) / 2; + + // + double zRSI = rsiBuffer[zIDX]; + double cRSI = rsiBuffer[cIDX]; + double pRSI = rsiBuffer[pIDX]; + double p2RSI = rsiBuffer[p2IDX]; + double p3RSI = rsiBuffer[p3IDX]; + double p4RSI = rsiBuffer[p4IDX]; + + // + // Create Required Conditions ... + + // + bool isZRSIBullish = zRSI > rsiTrend; + bool isZRSIBearish = zRSI < rsiTrend; + + // + bool isCRSIBullish = cRSI > rsiTrend; + bool isCRSIBearish = cRSI < rsiTrend; + + // + bool isPRSIBullish = pRSI > rsiTrend; + bool isPRSIBearish = pRSI < rsiTrend; + + // + bool isP2RSIBullish = p2RSI > rsiTrend; + bool isP2RSIBearish = p2RSI < rsiTrend; + + // + bool isP3RSIBullish = p3RSI > rsiTrend; + bool isP3RSIBearish = p3RSI < rsiTrend; + + // + // Trending Conditions ... + + // + bool isCRSISwitchedToBullish = + isZRSIBullish && + isCRSIBullish && + !isPRSIBullish; + + // + bool isCRSISwitchedToBearish = + isZRSIBearish && + isCRSIBearish && + !isPRSIBearish; + + // + bool isPRSISwitchedToBullish = + isZRSIBullish && + isCRSIBullish && + isPRSIBullish && + !isP2RSIBullish; + + // + bool isPRSISwitchedToBearish = + isZRSIBearish && + isCRSIBearish && + isPRSIBearish && + !isP2RSIBearish; + + // + bool isP2RSISwitchedToBullish = + isZRSIBullish && + isCRSIBullish && + isPRSIBullish && + isP2RSIBullish && + !isP3RSIBullish; + + // + bool isP2RSISwitchedToBearish = + isZRSIBearish && + isCRSIBearish && + isPRSIBearish && + isP2RSIBearish && + !isP3RSIBearish; + + // + // Crosses Conditions ... + + // + bool isCBarCrossedOverOS = + zRSI > rsiOSLevel && + cRSI > rsiOSLevel && + pRSI <= rsiOSLevel; + + // + bool isCBarCrossedUnderOB = + zRSI < rsiOBLevel && + cRSI < rsiOBLevel && + pRSI >= rsiOBLevel; + + // + bool isPBarCrossedOverOS = + zRSI > rsiOSLevel && + cRSI > rsiOSLevel && + pRSI > rsiOSLevel && + p2RSI <= rsiOSLevel; + + // + bool isPBarCrossedUnderOB = + zRSI < rsiOBLevel && + cRSI < rsiOBLevel && + pRSI < rsiOBLevel && + p2RSI >= rsiOBLevel; + + // + // V Pattern Conditions ... + + // + bool isCRSIHasVBullishPattern = + zRSI >= cRSI && + cRSI > pRSI && + p2RSI > pRSI && + cRSI >= p2RSI; + + // + bool isCRSIHasVBearishPattern = + zRSI <= cRSI && + cRSI < pRSI && + p2RSI < pRSI && + cRSI <= p2RSI; + + // + // Continuation Conditions ... + + // + bool isRSIUp = + zRSI >= cRSI && + (cRSI >= pRSI || + pRSI >= p2RSI || + p2RSI >= p3RSI); + + // + bool isRSIDown = + zRSI <= cRSI && + (cRSI <= pRSI || + pRSI <= p2RSI || + p2RSI <= p3RSI); + + // + // Summarize Filtering ... + + // + bool isBullishFiltered = + isBullish && + ( + // + // Grows ... + isRSIUp + // + || + // + // Crosses ... + (isCBarCrossedOverOS || + isPBarCrossedOverOS) + // + || + // + // V Pattern ... + isCRSIHasVBullishPattern + // + || + // + // Trending ... + (isCRSISwitchedToBullish || + isPRSISwitchedToBullish || + isP2RSISwitchedToBullish) + // + ); + + // + bool isBearishFiltered = + isBearish && + ( + // + // Grows ... + isRSIDown + // + || + // + // Crosses ... + (isCBarCrossedUnderOB || + isPBarCrossedUnderOB) + // + || + // + // V Pattern ... + isCRSIHasVBearishPattern + // + || + // + // Trending ... + (isCRSISwitchedToBearish || + isPRSISwitchedToBearish || + isP2RSISwitchedToBearish) + // + ); + + // + has = + isBullishFiltered || + isBearishFiltered; + if (!has) + { + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + } + + // + // ADX Filter ... + if (filterBasedOnADX) + { + // + // Reading Conditions Values ... + + // + // ADX ... + double zADX = adxBuffer[zIDX]; + double cADX = adxBuffer[cIDX]; + double pADX = adxBuffer[pIDX]; + double p2ADX = adxBuffer[p2IDX]; + double p3ADX = adxBuffer[p3IDX]; + double p4ADX = adxBuffer[p4IDX]; + + // + // ADX +DI ... + double zADXP = adxpBuffer[zIDX]; + double cADXP = adxpBuffer[cIDX]; + double pADXP = adxpBuffer[pIDX]; + double p2ADXP = adxpBuffer[p2IDX]; + double p3ADXP = adxpBuffer[p3IDX]; + double p4ADXP = adxpBuffer[p4IDX]; + + // + // ADX -DI ... + double zADXN = adxnBuffer[zIDX]; + double cADXN = adxnBuffer[cIDX]; + double pADXN = adxnBuffer[pIDX]; + double p2ADXN = adxnBuffer[p2IDX]; + double p3ADXN = adxnBuffer[p3IDX]; + double p4ADXN = adxnBuffer[p4IDX]; + + // + // Create Required Conditions ... + + // + // Grows ... + + // + bool isADXUp = + zADX >= cADX && + (cADX >= pADX || + pADX >= p2ADX); + + // + bool isADXDown = + zADX <= cADX && + (cADX <= pADX || + pADX <= p2ADX); + + // + // Trending ... + + // + bool isZADXBullish = zADX > adxThreshold; + bool isZADXBearish = zADX < adxThreshold; + + // + bool isCADXBullish = cADX > adxThreshold; + bool isCADXBearish = cADX < adxThreshold; + + // + bool isPADXBullish = pADX > adxThreshold; + bool isPADXBearish = pADX < adxThreshold; + + // + bool isP2ADXBullish = p2ADX > adxThreshold; + bool isP2ADXBearish = p2ADX < adxThreshold; + + // + bool isP3ADXBullish = p3ADX > adxThreshold; + bool isP3ADXBearish = p3ADX < adxThreshold; + + // + bool isP4ADXBullish = p4ADX > adxThreshold; + bool isP4ADXBearish = p4ADX < adxThreshold; + + // + bool isCADXSwitchedToBullish = + isZADXBullish && + isCADXBullish && + !isPADXBullish; + + // + bool isCADXSwitchedToBearish = + isZADXBearish && + isCADXBearish && + !isPADXBearish; + + // + bool isPADXSwitchedToBullish = + isZADXBullish && + isCADXBullish && + isPADXBullish && + !isP2ADXBullish; + + // + bool isPADXSwitchedToBearish = + isZADXBearish && + isCADXBearish && + isPADXBearish && + !isP2ADXBearish; + + // + // Powering ... + + // + bool isZADXHasBullishPower = zADXP > zADXN; + bool isZADXHasBearishPower = zADXN > zADXP; + + // + bool isCADXHasBullishPower = cADXP > cADXN; + bool isCADXHasBearishPower = cADXN > cADXP; + + // + bool isPADXHasBullishPower = pADXP > pADXN; + bool isPADXHasBearishPower = pADXN > pADXP; + + // + bool isP2ADXHasBullishPower = p2ADXP > p2ADXN; + bool isP2ADXHasBearishPower = p2ADXN > p2ADXP; + + // + bool isP3ADXHasBullishPower = p3ADXP > p3ADXN; + bool isP3ADXHasBearishPower = p3ADXN > p3ADXP; + + // + bool isP4ADXHasBullishPower = p4ADXP > p4ADXN; + bool isP4ADXHasBearishPower = p4ADXN > p4ADXP; + + // + bool isCADXSwitchedToBullishPower = + isZADXHasBullishPower && + isCADXHasBullishPower && + !isPADXHasBullishPower; + + // + bool isCADXSwitchedToBearishPower = + isZADXHasBearishPower && + isCADXHasBearishPower && + !isPADXHasBearishPower; + + // + bool isPADXSwitchedToBullishPower = + isZADXHasBullishPower && + isCADXHasBullishPower && + isPADXHasBullishPower && + !isP2ADXHasBullishPower; + + // + bool isPADXSwitchedToBearishPower = + isZADXHasBearishPower && + isCADXHasBearishPower && + isPADXHasBearishPower && + !isP2ADXHasBearishPower; + + // + // Summarize Filtering ... + + // + bool isBullishFiltered = + isBullish && + ( + // + // Grows ... + isADXUp + // + || + // + // Trending ... + (isCADXSwitchedToBullish || + isPADXSwitchedToBullish) + // + || + // + // Powering ... + (isCADXSwitchedToBullishPower || + isPADXSwitchedToBullishPower) + // + ); + + // + bool isBearishFiltered = + isBearish && + ( + // + // Grows ... + isADXDown + // + || + // + // Trending ... + (isCADXSwitchedToBearish || + isPADXSwitchedToBearish) + // + || + // + // Powering ... + (isCADXSwitchedToBearishPower || + isPADXSwitchedToBearishPower) + // + ); + + // + has = + isBullishFiltered || + isBearishFiltered; + if (!has) + { + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + } + + // + // TREND Filter ... + if (filterBasedOnTrend) + { + // + // Reading Conditions Values ... + + // + double zTrend = trendBuffer[zIDX]; + double cTrend = trendBuffer[cIDX]; + double pTrend = trendBuffer[pIDX]; + double p2Trend = trendBuffer[p2IDX]; + double p3Trend = trendBuffer[p3IDX]; + double p4Trend = trendBuffer[p4IDX]; + + // + double trends[] = { + zTrend, + cTrend, + pTrend, + p2Trend, + p3Trend, + p4Trend // + }; + double trendsMin = GetMin(trends); + double trendsMax = GetMax(trends); + double trendsAVG = GetAverage(trends); + + // + double zTrendState = trendStateBuffer[zIDX]; + double cTrendState = trendStateBuffer[cIDX]; + double pTrendState = trendStateBuffer[pIDX]; + double p2TrendState = trendStateBuffer[p2IDX]; + double p3TrendState = trendStateBuffer[p3IDX]; + double p4TrendState = trendStateBuffer[p4IDX]; + + // + // Create Required Conditions ... + + // + // Grows ... + + // + bool isTrendUp = + zTrend >= cTrend && + cTrend >= trendsAVG && + cTrend > trendsMin; + + // + bool isTrendDown = + zTrend <= cTrend && + cTrend <= trendsAVG && + cTrend < trendsMax; + + // + // Stating ... + + // + bool isCTrendBullish = + zTrendState > 0 && + cTrendState > 0; + + // + bool isCTrendBearish = + zTrendState < 0 && + cTrendState < 0; + + // + bool isPTrendBullish = + zTrendState > 0 && + cTrendState > 0 && + pTrendState > 0; + + // + bool isPTrendBearish = + zTrendState < 0 && + cTrendState < 0 && + pTrendState < 0; + + // + bool isP2TrendBullish = + zTrendState > 0 && + cTrendState > 0 && + pTrendState > 0 && + p2TrendState > 0; + + // + bool isP2TrendBearish = + zTrendState < 0 && + cTrendState < 0 && + pTrendState < 0 && + p2TrendState < 0; + + // + bool isCTrendSwitchedToBullish = + isCTrendBullish && + !isPTrendBullish; + + // + bool isCTrendSwitchedToBearish = + isCTrendBearish && + !isPTrendBearish; + + // + bool isPTrendSwitchedToBullish = + isCTrendBullish && + isPTrendBullish && + !isP2TrendBullish; + + // + bool isPTrendSwitchedToBearish = + isCTrendBearish && + isPTrendBearish && + !isP2TrendBearish; + + // + // Summarize Filtering ... + + // + bool isBullishFiltered = + isBullish && + ( + // + // Grows ... + isTrendUp + // + || + // + // Trend Stating ... + (isCTrendBullish && + isPTrendBullish) + // + || + // + // Switching ... + (isCTrendSwitchedToBullish || + isPTrendSwitchedToBullish) + // + ); + + // + bool isBearishFiltered = + isBearish && + ( + // + // Grows ... + isTrendDown + // + || + // + // Trend Stating ... + (isCTrendBearish && + isPTrendBearish) + // + || + // + // Switching ... + (isCTrendSwitchedToBearish || + isPTrendSwitchedToBearish) + // + ); + + // + has = + isBullishFiltered || + isBearishFiltered; + if (!has) + { + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + } + + // + // SCORE Filter ... + + // + // VOLUME Filter ... + } + + // + // Detect Left Side of Box ... + XOHCL zoneLeftBar; + int idx = fromIDX + 1; + bool isBaseValid = true; + while (isBaseValid) + { + // + // Retrieve iteration Bar ... + has = zoneLeftBar.Init( + _Symbol, + _Period, + idx // + ); + if (!has) + { + // + zoneLeftBar.Clean(); + break; + } + + // + // Check Bar's Validation ... + + // + bool isBullishPassed = + isBullish && + zoneLeftBar.low >= zone.lower; + + // + bool isBearishPassed = + isBearish && + zoneLeftBar.high <= zone.upper; + + // + // Summarize Conditions ... + has = + isBullishPassed || + isBearishPassed; + if (!has) + { + break; + } + + // + idx++; + } + + // + // Ray to Left Side Zone, if Provided ... + if (rayLeft) + { + // + // Update Value ... + fromIDX = zone.FromIndex(); + + // + // Check Last Iteration Bar is Valid Bar ... + // then Update Zone from Time ... + has = zoneLeftBar.IsValid(); + if (has) + { + // + zone.from = zoneLeftBar.time; + fromIDX = zone.FromIndex(); + } + } + + // + // Draw Detected Zone ... + if (drawZones) + { + // + XCBoxObject *iZoneObj; + has = drawer.DrawBox( + zone, + iZoneObj // + ); + if (has) + { + // + ApplyStyle(iZoneObj, zone.dir); + + // + mObjects.Add(iZoneObj); + + // + // TODO: Enable This for Debugging ... + // string message = ToString(zone.dir) + " Zone Detected (" + cBar.time + ") ..."; + // Print(message); + } + ZeroMemory(iZoneObj); + } + + // + // Draw RR Tool ... + if (drawRRofZones) + { + // + double rr[]{ + 1, + 1.5, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10 // + }; + XCRRObject *iRRObj; + iRRObj = new XCRRObject(); + has = iRRObj.CreateBoxRR( + drawer.ChartIdentification(), + drawer.SubWindowIdentification(), + zone, + rr, + rrZoneLength // + ); + if (has) + { + // + int iWidth = 2; + ENUM_LINE_STYLE iStyle = STYLE_SOLID; + + // + iRRObj.TPWidth(iWidth); + iRRObj.SLWidth(iWidth); + iRRObj.EntryWidth(iWidth); + iRRObj.TargetWidth(iWidth); + + // + iRRObj.TPStyle(iStyle); + iRRObj.SLStyle(iStyle); + iRRObj.EntryStyle(iStyle); + iRRObj.TargetStyle(iStyle); + + // + iRRObj.TPColor(clrLime); + iRRObj.SLColor(clrRed); + iRRObj.EntryColor(clrYellow); + iRRObj.TargetColor(clrLightBlue); + + // + mObjects.Add(iRRObj); + } + ZeroMemory(iRRObj); + } + + // + // Handle Alerst ... + bool canAlert = + mEnableAlerts && + prevCalculated > 0; + bool canLogOnly = + mEnableAlerts && + prevCalculated == 0; + if (canAlert || canLogOnly) + { + // + string message = + zone.symbol + "," + + ToString(zone.period) + "> " + + ToString(zone.dir) + + " Zone Detected at: " + ToString(zone.to); + + // + if (canLogOnly) + { + alert.LogAlert(message); + } + else if (canAlert) + { + alert.SendAlert(message); + } + } + + // + // Cleanup Resources ... + + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + zoneLeftBar.Clean(); +} + +// +void ApplyStyle( + XCBoxObject *iObj, + ENUM_X_DIRECTION dir // +) +{ + // + if (!HasDirection(dir) || iObj == NULL) + { + return; + } + + // + int width = boxWidth > 0 + ? boxWidth + : 1; + int clr = IsBullish(dir) + ? bullishColor + : bearishColor; + + // + iObj.BoxColor(clr); + iObj.BoxWidth(width); + iObj.BoxStyle(boxStyle); + + // +} + +// \ No newline at end of file diff --git a/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xdelta.mq5 b/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xdelta.mq5 new file mode 100644 index 0000000..9cadee6 --- /dev/null +++ b/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xdelta.mq5 @@ -0,0 +1,550 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Ocillator +// ------------------------------------------------- +// Name: X121 XDelta +// Description: Detect Comulative Volumes Delta ... +// +// +// 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 XDelta Ocillator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121_XDELTA" + +// +// Imports ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +// Makret ... +input group "Market"; +input int maLength = 14; // Moving Averge Length +input ENUM_X_MA_METHOD maMethod = X_MA_MODE_EMA; // Moving Averge Method + +// +// Presentation ... +input group "Presentation"; +input int startCalculationForLastBars = 1000; // Calculate Last n Bars +input bool showDeltaLine = true; // Show Delta Line +input bool showDeltaHistogram = true; // Show Delta Histogram +input bool showDeltaMa = true; // Show Delta Moving Average + +// +// Buffers Props ... + +// +#property indicator_separate_window + +// +#property indicator_buffers 6 +#property indicator_plots 3 + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 + +// +// Buffers ... + +// +#define deltaLineBufferIndex 0 +double deltaLineBuffer[]; + +#property indicator_label1 "Delta Line" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrYellow +#property indicator_style1 STYLE_SOLID +#property indicator_width1 1 + +// +#define deltaHistogramBufferIndex 1 +double deltaHistogramBuffer[]; + +// +#define deltaHistogramColorBufferIndex 2 +double deltaHistogramColorBuffer[]; + +#property indicator_label2 "Delta Histogram" +#property indicator_type2 DRAW_COLOR_HISTOGRAM +#property indicator_color2 CLR_NONE, clrGreen, clrDarkRed +#property indicator_style2 STYLE_DOT +#property indicator_width2 1 + +// +#define deltaMaBufferIndex 3 +double deltaMaBuffer[]; + +#property indicator_label3 "Delta MA" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrOrchid +#property indicator_style3 STYLE_SOLID +#property indicator_width3 1 + +// +// Data Buffers ... + +#define mLastBufferIndex 3 + +// +#define rawDeltaBufferIndex mLastBufferIndex + 1 +double rawDeltaBuffer[]; + +// +#define deltaStateBufferIndex mLastBufferIndex + 2 +double deltaStateBuffer[]; + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +int firstBarIndex; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + + // + // 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(); + IndicatorSetInteger(INDICATOR_DIGITS, 2); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +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 +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // 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); + + // + 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, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + result = maLength > 0 && + IsValid(maMethod); + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(0, maLength); + + // + return result; +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + + // + // Delta Line ... + ENUM_DRAW_TYPE deltaLineDrawType = showDeltaLine ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(deltaLineBuffer, true); + SetIndexBuffer(deltaLineBufferIndex, deltaLineBuffer, INDICATOR_DATA); + PlotIndexSetDouble(deltaLineBufferIndex, PLOT_EMPTY_VALUE, 0.0); + PlotIndexSetInteger(deltaLineBufferIndex, PLOT_SHOW_DATA, showDeltaLine); + PlotIndexSetInteger(deltaLineBufferIndex, PLOT_DRAW_TYPE, deltaLineDrawType); + + // + // Delta Histogram ... + ENUM_DRAW_TYPE deltaHistogramDrawType = showDeltaHistogram ? DRAW_COLOR_HISTOGRAM : DRAW_NONE; + + // + ArraySetAsSeries(deltaHistogramBuffer, true); + SetIndexBuffer(deltaHistogramBufferIndex, deltaHistogramBuffer, INDICATOR_DATA); + PlotIndexSetDouble(deltaHistogramBufferIndex, PLOT_EMPTY_VALUE, 0.0); + PlotIndexSetInteger(deltaHistogramBufferIndex, PLOT_SHOW_DATA, showDeltaHistogram); + PlotIndexSetInteger(deltaHistogramBufferIndex, PLOT_DRAW_TYPE, deltaHistogramDrawType); + + // + ArraySetAsSeries(deltaHistogramColorBuffer, true); + SetIndexBuffer(deltaHistogramColorBufferIndex, deltaHistogramColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Delta Ma ... + ENUM_DRAW_TYPE deltaMaDrawType = showDeltaMa ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(deltaMaBuffer, true); + SetIndexBuffer(deltaMaBufferIndex, deltaMaBuffer, INDICATOR_DATA); + PlotIndexSetDouble(deltaMaBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(deltaMaBufferIndex, PLOT_SHOW_DATA, showDeltaMa); + PlotIndexSetInteger(deltaMaBufferIndex, PLOT_DRAW_TYPE, deltaMaDrawType); + + // + // Data Buffers ... + + // + ArraySetAsSeries(rawDeltaBuffer, true); + SetIndexBuffer(rawDeltaBufferIndex, rawDeltaBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(deltaStateBuffer, true); + SetIndexBuffer(deltaStateBufferIndex, deltaStateBuffer, INDICATOR_CALCULATIONS); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +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[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + if (barsLimit == 0) + { + // + barsLimit = ratesTotal; + firstBarIndex = barsLimit - 1; + } + else + { + // + firstBarIndex = startCalculationForLastBars; + } + + // + // bool canCalculate = true; + bool canCalculate = + bar_index <= barsLimit; + if (canCalculate) + { + // + CalculateValues( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + else + { + FillBuffersZero(bar_index); + } +} + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + rawDeltaBuffer[barIndex] = 0.0; + deltaLineBuffer[barIndex] = 0.0; + deltaStateBuffer[barIndex] = 0.0; + deltaHistogramBuffer[barIndex] = 0.0; + deltaMaBuffer[barIndex] = 0.0; + deltaHistogramColorBuffer[barIndex] = hideColorIDX; +} + +/** + * Calculate Vales ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateValues( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // Check Prev Bar ... + int lastBarIndex = bar_index + 1; + bool isFirstBar = + startCalculationForLastBars > 0 + ? bar_index == startCalculationForLastBars + : bar_index == firstBarIndex; + + // + XOHCL bar; + bool has = bar.Init( + _Symbol, + _Period, + bar_index // + ); + if (!has) + { + return; + } + + // + double iDelta = 0.0; + + // + // Detecting Delta Volume ... + if (bar.IsBullish()) + { + iDelta = (double)bar.volume; + } + else if (bar.IsBearish()) + { + iDelta = -(double)bar.volume; + } + + // + // Setting iDelta Value ... + if (isFirstBar) + { + // + rawDeltaBuffer[bar_index] = iDelta; + deltaLineBuffer[bar_index] = iDelta; + deltaHistogramBuffer[bar_index] = iDelta; + } + else + { + // + iDelta += deltaLineBuffer[bar_index + 1]; + + // + rawDeltaBuffer[bar_index] = iDelta; + deltaLineBuffer[bar_index] = iDelta; + deltaHistogramBuffer[bar_index] = iDelta; + } + + // + // Setting iDelta State ... + double iState = iDelta > 0 + ? bullishColorIDX + : iDelta < 0 + ? bearishColorIDX + : hideColorIDX; + // + // Setting iDelta Color ... + double iDeltaColor = iDelta > 0 + ? bullishColorIDX + : iDelta < 0 + ? bearishColorIDX + : hideColorIDX; + + // + deltaStateBuffer[bar_index] = iState; + deltaHistogramColorBuffer[bar_index] = iDeltaColor; + + // + // Calculate Moving Averages ... + int deltaMAsCount = iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + maLength, + rawDeltaBuffer, + deltaMaBuffer, + maMethod // + ); + + // + bar.Clean(); +} + +// diff --git a/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xdon.mq5 b/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xdon.mq5 new file mode 100644 index 0000000..49785d4 --- /dev/null +++ b/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xdon.mq5 @@ -0,0 +1,692 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XDON +// Description: XDON ... +// +// +// 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 XDON Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121 XDON" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +// Market ... +input group "Market"; +input int donchainLength = 40; // Donchain Length + +// +// Presentation ... +input group "Presentation"; + +// +input int startCalculationForLastBars = 1000; // Calculate Last n Bars + +// +input bool showUpper = true; // Show Upper Band +input bool showLower = true; // Show Lower Band + +// +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 ... + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#property indicator_chart_window + +// +#property indicator_buffers 8 +#property indicator_plots 8 + +// +// Plot Buffers ... + +// +// Open ... + +// +#define donOpenUpperBufferIndex 0 +double donOpenUpperBuffer[]; + +// +#define donOpenUpperPlotBufferIndex 0 +#property indicator_label1 "X121 O U" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrCornflowerBlue +#property indicator_width1 1 + +// +#define donOpenLowerBufferIndex 1 +double donOpenLowerBuffer[]; + +// +#define donOpenLowerPlotBufferIndex 1 +#property indicator_label2 "X121 O L" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrCornflowerBlue +#property indicator_width2 1 + +// +// High ... + +// +#define donHighUpperBufferIndex 2 +double donHighUpperBuffer[]; + +// +#define donHighUpperPlotBufferIndex 2 +#property indicator_label3 "X121 H U" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrAquamarine +#property indicator_width3 1 + +// +#define donHighLowerBufferIndex 3 +double donHighLowerBuffer[]; + +// +#define donHighLowerPlotBufferIndex 3 +#property indicator_label4 "X121 H L" +#property indicator_type4 DRAW_LINE +#property indicator_color4 clrAquamarine +#property indicator_width4 1 + +// +// Low ... + +// +#define donLowUpperBufferIndex 4 +double donLowUpperBuffer[]; + +// +#define donLowUpperPlotBufferIndex 4 +#property indicator_label5 "X121 L U" +#property indicator_type5 DRAW_LINE +#property indicator_color5 clrDarkOrchid +#property indicator_width5 1 + +// +#define donLowLowerBufferIndex 5 +double donLowLowerBuffer[]; + +// +#define donLowLowerPlotBufferIndex 5 +#property indicator_label6 "X121 L L" +#property indicator_type6 DRAW_LINE +#property indicator_color6 clrDarkOrchid +#property indicator_width6 1 + +// +// Close ... + +// +#define donCloseUpperBufferIndex 6 +double donCloseUpperBuffer[]; + +// +#define donCloseUpperPlotBufferIndex 6 +#property indicator_label7 "X121 C U" +#property indicator_type7 DRAW_LINE +#property indicator_color7 clrCoral +#property indicator_width7 1 + +// +#define donCloseLowerBufferIndex 7 +double donCloseLowerBuffer[]; + +// +#define donCloseLowerPlotBufferIndex 7 +#property indicator_label8 "X121 C L" +#property indicator_type8 DRAW_LINE +#property indicator_color8 clrCoral +#property indicator_width8 1 + +// +// Data Buffers ... + +// +int mLastBufferIndex = 7; + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + + // + // 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; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +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 +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // 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); + + // + // Validate Calculated Bars ... + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + result = + // + donchainLength > 0 + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + // + // Open ... + + // + // UPPER ... + bool canShowCOpenUpper = showUpper && showOpen; + ENUM_DRAW_TYPE donOpenUpperDrawType = canShowCOpenUpper ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donOpenUpperBuffer, true); + SetIndexBuffer(donOpenUpperBufferIndex, donOpenUpperBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donOpenUpperPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donOpenUpperPlotBufferIndex, PLOT_SHOW_DATA, canShowCOpenUpper); + PlotIndexSetInteger(donOpenUpperPlotBufferIndex, PLOT_DRAW_TYPE, donOpenUpperDrawType); + + // + // LOWER ... + bool canShowCOpenLower = showLower && showOpen; + ENUM_DRAW_TYPE donOpenLowerDrawType = canShowCOpenLower ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donOpenLowerBuffer, true); + SetIndexBuffer(donOpenLowerBufferIndex, donOpenLowerBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donOpenLowerPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donOpenLowerPlotBufferIndex, PLOT_SHOW_DATA, canShowCOpenLower); + PlotIndexSetInteger(donOpenLowerPlotBufferIndex, PLOT_DRAW_TYPE, donOpenLowerDrawType); + + // + // Close ... + + // + // UPPER ... + bool canShowCCloseUpper = showUpper && showClose; + ENUM_DRAW_TYPE donCloseUpperDrawType = canShowCCloseUpper ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donCloseUpperBuffer, true); + SetIndexBuffer(donCloseUpperBufferIndex, donCloseUpperBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donCloseUpperPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donCloseUpperPlotBufferIndex, PLOT_SHOW_DATA, canShowCCloseUpper); + PlotIndexSetInteger(donCloseUpperPlotBufferIndex, PLOT_DRAW_TYPE, donCloseUpperDrawType); + + // + // LOWER ... + bool canShowCCloseLower = showLower && showClose; + ENUM_DRAW_TYPE donCloseLowerDrawType = canShowCCloseLower ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donCloseLowerBuffer, true); + SetIndexBuffer(donCloseLowerBufferIndex, donCloseLowerBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donCloseLowerPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donCloseLowerPlotBufferIndex, PLOT_SHOW_DATA, canShowCCloseLower); + PlotIndexSetInteger(donCloseLowerPlotBufferIndex, PLOT_DRAW_TYPE, donCloseLowerDrawType); + + // + // High ... + + // + // UPPER ... + bool canShowCHighUpper = showUpper && showHigh; + ENUM_DRAW_TYPE donHighUpperDrawType = canShowCHighUpper ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donHighUpperBuffer, true); + SetIndexBuffer(donHighUpperBufferIndex, donHighUpperBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donHighUpperPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donHighUpperPlotBufferIndex, PLOT_SHOW_DATA, canShowCHighUpper); + PlotIndexSetInteger(donHighUpperPlotBufferIndex, PLOT_DRAW_TYPE, donHighUpperDrawType); + + // + // LOWER ... + bool canShowCHighLower = showLower && showHigh; + ENUM_DRAW_TYPE donHighLowerDrawType = canShowCHighLower ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donHighLowerBuffer, true); + SetIndexBuffer(donHighLowerBufferIndex, donHighLowerBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donHighLowerPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donHighLowerPlotBufferIndex, PLOT_SHOW_DATA, canShowCHighLower); + PlotIndexSetInteger(donHighLowerPlotBufferIndex, PLOT_DRAW_TYPE, donHighLowerDrawType); + + // + // Low ... + + // + // UPPER ... + bool canShowCLowUpper = showUpper && showLow; + ENUM_DRAW_TYPE donLowUpperDrawType = canShowCLowUpper ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donLowUpperBuffer, true); + SetIndexBuffer(donLowUpperBufferIndex, donLowUpperBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donLowUpperPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donLowUpperPlotBufferIndex, PLOT_SHOW_DATA, canShowCLowUpper); + PlotIndexSetInteger(donLowUpperPlotBufferIndex, PLOT_DRAW_TYPE, donLowUpperDrawType); + + // + // LOWER ... + bool canShowCLowLower = showLower && showLow; + ENUM_DRAW_TYPE donLowLowerDrawType = canShowCLowLower ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donLowLowerBuffer, true); + SetIndexBuffer(donLowLowerBufferIndex, donLowLowerBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donLowLowerPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donLowLowerPlotBufferIndex, PLOT_SHOW_DATA, canShowCLowLower); + PlotIndexSetInteger(donLowLowerPlotBufferIndex, PLOT_DRAW_TYPE, donLowLowerDrawType); + + // + // Data Buffers ... +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +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[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + // + // bool canCalculate = true; + bool canCalculate = + barsLimit == 0 || + bar_index <= barsLimit; + if (canCalculate) + { + // + CalculateDonchains( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + else + { + FillBuffersZero(bar_index); + } +} + +// +// Custom ... + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + donOpenUpperBuffer[barIndex] = EMPTY_VALUE; + donOpenLowerBuffer[barIndex] = EMPTY_VALUE; + donCloseUpperBuffer[barIndex] = EMPTY_VALUE; + donCloseLowerBuffer[barIndex] = EMPTY_VALUE; + donHighUpperBuffer[barIndex] = EMPTY_VALUE; + donHighLowerBuffer[barIndex] = EMPTY_VALUE; + donLowUpperBuffer[barIndex] = EMPTY_VALUE; + donLowLowerBuffer[barIndex] = EMPTY_VALUE; +} + +/** + * Calculate Donchain ... + * + * @param bar_index: Integer, Bar Index ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + * @param _length: Integer, Donchain Length ... + * @param _ouBuffer: Double Array Reference ... + * @param _olBuffer: Double Array Reference ... + * @param _huBuffer: Double Array Reference ... + * @param _hlBuffer: Double Array Reference ... + * @param _luBuffer: Double Array Reference ... + * @param _llBuffer: Double Array Reference ... + * @param _cuBuffer: Double Array Reference ... + * @param _clBuffer: Double Array Reference ... + */ +void CalculateDonchain( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + // + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[], + // + int _length, + // + double &_ouBuffer[], + double &_olBuffer[], + double &_huBuffer[], + double &_hlBuffer[], + double &_luBuffer[], + double &_llBuffer[], + double &_cuBuffer[], + double &_clBuffer[] // +) +{ + // + double iUpper = 0; + double iLower = 0; + + // + // OPEN ... + + // + int from = bar_index; + + // + iUpper = open[ArrayMaximum(open, from, _length)]; + iLower = open[ArrayMinimum(open, from, _length)]; + + // + _ouBuffer[bar_index] = iUpper; + _olBuffer[bar_index] = iLower; + + // + // HIGH ... + + // + iUpper = high[ArrayMaximum(high, from, _length)]; + iLower = high[ArrayMinimum(high, from, _length)]; + + // + _huBuffer[bar_index] = iUpper; + _hlBuffer[bar_index] = iLower; + + // + // LOW ... + + // + iUpper = low[ArrayMaximum(low, from, _length)]; + iLower = low[ArrayMinimum(low, from, _length)]; + + // + _luBuffer[bar_index] = iUpper; + _llBuffer[bar_index] = iLower; + + // + // CLOSE ... + + // + iUpper = close[ArrayMaximum(close, from, _length)]; + iLower = close[ArrayMinimum(close, from, _length)]; + + // + _cuBuffer[bar_index] = iUpper; + _clBuffer[bar_index] = iLower; +} + +/** + * Calculate Different VWaps ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateDonchains( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + CalculateDonchain( + // + bar_index, + prevCalculated, + ratesTotal, + // + open, + high, + close, + low, + tickVolume, + // + donchainLength, + // + donOpenUpperBuffer, + donOpenLowerBuffer, + donHighUpperBuffer, + donHighLowerBuffer, + donLowUpperBuffer, + donLowLowerBuffer, + donCloseUpperBuffer, + donCloseLowerBuffer // + ); +} + +// \ No newline at end of file diff --git a/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xhk.mq5 b/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xhk.mq5 new file mode 100644 index 0000000..8e23e94 --- /dev/null +++ b/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xhk.mq5 @@ -0,0 +1,636 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XHK +// Description: XHK ... +// +// +// 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 XHK Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121 XHK" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +// Market ... +input group "Market"; +input int xhkSmoothingLength = 14; // Length +input ENUM_X_MA_METHOD xhkSmoothingMode = X_MA_MODE_EMA; // Smoothing Method +input bool xhkIgnoreSmoothingShadows = false; // Ignore Smoothed Bar Shadows + +// +input group "Presentation"; + +// +input int startCalculationForLastBars = 1000; // Calculate Last n Bars + +// +input bool drawRawXHKCandles = true; // Draw Raw Candle +input bool drawSmoothedXHKCandles = true; // Draw Smoothed Candle + +// +// Buffers ... + +// +#property indicator_chart_window + +// +#property indicator_buffers 10 +#property indicator_plots 2 + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +// PLOTTED Buffers ... + +// +#define openHKBufferIndex 0 +double openHKBuffer[]; + +// +#define highHKBufferIndex 1 +double highHKBuffer[]; + +// +#define lowHKBufferIndex 2 +double lowHKBuffer[]; + +// +#define closeHKBufferIndex 3 +double closeHKBuffer[]; + +// +#define rawHKColorBufferIndex 4 +double rawHKColorBuffer[]; + +// +#define rawHKBufferIndex 0 +#property indicator_label1 "X121 XHK Open;X121 XHK High;X121 XHK Low;X121 XHK Close" +#property indicator_type1 DRAW_COLOR_CANDLES +#property indicator_color1 CLR_NONE, clrDodgerBlue, clrDarkGoldenrod + +// +// Open ... +#define openBufferIndex 5 +double openBuffer[]; + +// +// High ... +#define highBufferIndex 6 +double highBuffer[]; + +// +// Low ... +#define lowBufferIndex 7 +double lowBuffer[]; + +// +// Close ... +#define closeBufferIndex 8 +double closeBuffer[]; + +// +// Candle Color ... +#define candleColorBufferIndex 9 +double candleColorBuffer[]; + +// +#define candlesBufferIndex 1 +#property indicator_label2 "X121 XHKSM Open;X121 XHKSM High;X121 XHKSM Low;X121 XHKSM Close" +#property indicator_type2 DRAW_COLOR_CANDLES +#property indicator_color2 CLR_NONE, clrAqua, clrMagenta + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +int firstBarIndex; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + + // + // 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; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +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 + + // +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // 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); + + // + // Fill All Buffers by Zero ... + if (prev_calculated == 0) + { + } + + // + 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, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = + // + true + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(0, xhkSmoothingLength); + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + + // + // RAW ... + + // + // Raw Candles Color ... + ArraySetAsSeries(rawHKColorBuffer, true); + SetIndexBuffer(rawHKColorBufferIndex, rawHKColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Set EMPTY_VALUE on Candles Buffer ... + PlotIndexSetDouble(rawHKBufferIndex, PLOT_EMPTY_VALUE, 0.0); + PlotIndexSetInteger(rawHKBufferIndex, PLOT_SHOW_DATA, false); + + // + // Open ... + ArraySetAsSeries(openHKBuffer, true); + SetIndexBuffer(openHKBufferIndex, openHKBuffer, INDICATOR_DATA); + + // + // High ... + ArraySetAsSeries(highHKBuffer, true); + SetIndexBuffer(highHKBufferIndex, highHKBuffer, INDICATOR_DATA); + + // + // Close ... + ArraySetAsSeries(closeHKBuffer, true); + SetIndexBuffer(closeHKBufferIndex, closeHKBuffer, INDICATOR_DATA); + + // + // Low ... + ArraySetAsSeries(lowHKBuffer, true); + SetIndexBuffer(lowHKBufferIndex, lowHKBuffer, INDICATOR_DATA); + + // + // SMOOTHED ... + + // + // 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); + + // + // Open ... + ArraySetAsSeries(openBuffer, true); + SetIndexBuffer(openBufferIndex, openBuffer, INDICATOR_DATA); + + // + // High ... + ArraySetAsSeries(highBuffer, true); + SetIndexBuffer(highBufferIndex, highBuffer, INDICATOR_DATA); + + // + // Close ... + ArraySetAsSeries(closeBuffer, true); + SetIndexBuffer(closeBufferIndex, closeBuffer, INDICATOR_DATA); + + // + // Low ... + ArraySetAsSeries(lowBuffer, true); + SetIndexBuffer(lowBufferIndex, lowBuffer, INDICATOR_DATA); +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +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[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + if (barsLimit == 0) + { + // + barsLimit = ratesTotal; + firstBarIndex = barsLimit - 1; + } + else + { + // + firstBarIndex = startCalculationForLastBars; + } + + // + // bool canCalculate = true; + bool canCalculate = + bar_index <= barsLimit; + if (canCalculate) + { + // + CalculateXHK( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low // + ); + } + else + { + FillBuffersZero(bar_index); + } +} + +// +// Custom ... + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + lowHKBuffer[barIndex] = 0.0; + openHKBuffer[barIndex] = 0.0; + highHKBuffer[barIndex] = 0.0; + closeHKBuffer[barIndex] = 0.0; + rawHKColorBuffer[barIndex] = hideColorIDX; + + // + lowBuffer[barIndex] = 0.0; + openBuffer[barIndex] = 0.0; + highBuffer[barIndex] = 0.0; + closeBuffer[barIndex] = 0.0; + candleColorBuffer[barIndex] = hideColorIDX; +} + +/** + * Calculate ATR Zones ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + */ +void CalculateXHK( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[] // +) +{ + // + int lastBarIndex = bar_index + 1; + bool isFirstBar = + startCalculationForLastBars > 0 + ? bar_index == startCalculationForLastBars + : bar_index == firstBarIndex; + + // + double mPrevHKOpenValue; + double mPrevHKCloseValue; + + // + if (ArraySize(open) <= bar_index + 1) + { + // + mPrevHKOpenValue = 0; + mPrevHKCloseValue = 0; + } + else + { + // + mPrevHKOpenValue = openHKBuffer[bar_index + 1]; + mPrevHKCloseValue = closeHKBuffer[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)); + + // + double candleColorValue = + mHKOpenValue < mHKCloseValue ? bullishColorIDX : bearishColorIDX; + + // + // Raw HK Buffers ... + openHKBuffer[bar_index] = mHKOpenValue; + highHKBuffer[bar_index] = mHKHighValue; + lowHKBuffer[bar_index] = mHKLowValue; + closeHKBuffer[bar_index] = mHKCloseValue; + rawHKColorBuffer[bar_index] = drawRawXHKCandles ? candleColorValue : hideColorIDX; + + // + // Apply Smoothing ... + bool canSmooth = xhkSmoothingLength > 0 && + xhkSmoothingMode != X_MA_MODE_NONE; + if (!canSmooth) + { + // + double min = MathMin(mHKOpenValue, mHKCloseValue); + double max = MathMax(mHKOpenValue, mHKCloseValue); + + // + openBuffer[bar_index] = mHKOpenValue; + highBuffer[bar_index] = xhkIgnoreSmoothingShadows ? max : mHKHighValue; + lowBuffer[bar_index] = xhkIgnoreSmoothingShadows ? min : mHKLowValue; + closeBuffer[bar_index] = mHKCloseValue; + candleColorBuffer[bar_index] = drawSmoothedXHKCandles ? candleColorValue : hideColorIDX; + } + else + { + // + // Open ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + xhkSmoothingLength, + openHKBuffer, + openBuffer, + xhkSmoothingMode // + ); + + // + // Close ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + xhkSmoothingLength, + closeHKBuffer, + closeBuffer, + xhkSmoothingMode // + ); + + // + // Ignoring Shadows ... + if (!xhkIgnoreSmoothingShadows) + { + // + // High ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + xhkSmoothingLength, + highHKBuffer, + highBuffer, + xhkSmoothingMode // + ); + + // + // Low ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + xhkSmoothingLength, + lowHKBuffer, + lowBuffer, + xhkSmoothingMode // + ); + } + else + { + // + double min = MathMin(closeBuffer[bar_index], openBuffer[bar_index]); + double max = MathMin(closeBuffer[bar_index], openBuffer[bar_index]); + + // + lowBuffer[bar_index] = min; + highBuffer[bar_index] = max; + } + + // + // Calculate Smoothed Color ... + candleColorValue = + openBuffer[bar_index] < closeBuffer[bar_index] ? bullishColorIDX : bearishColorIDX; + candleColorBuffer[bar_index] = drawSmoothedXHKCandles ? candleColorValue : hideColorIDX; + } +} + +// \ No newline at end of file diff --git a/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xich.mq5 b/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xich.mq5 new file mode 100644 index 0000000..89b3fb8 --- /dev/null +++ b/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xich.mq5 @@ -0,0 +1,625 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XWZ +// Description: XWZ ... +// +// +// 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 XWZ Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121_XICH" + +// +// Imports ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +// Market ... +input group "Market"; +input ENUM_X_PRICE chikouSpanMode = X_PRICE_CLOSE; // ChikouSpan Mode +input int tenkanSenLength = 9; // TenkanSen Length +input ENUM_X_BOUNDARY_PRICE tenkanSenMode = X_BOUNDARY_PRICE_HIGH_LOW; // TencanSen Mode +input int kijunSenLength = 26; // KijunSen Length +input ENUM_X_BOUNDARY_PRICE kijunSenMode = X_BOUNDARY_PRICE_HIGH_LOW; // KijunSen Mode +input int senkouSpanBLength = 52; // SenkouSpan B Length +input ENUM_X_BOUNDARY_PRICE senkouSpanBMode = X_BOUNDARY_PRICE_HIGH_LOW; // SenkouSpan B Mode + +// +// Presentation ... +input group "Presentation"; + +// +input int startCalculationForLastBars = 1000; // Calculate Last n Bars +input bool shiftKumo = true; // Shift Kumo +input bool showTenkanSen = true; // Show TenkanSen +input bool showKijunSen = true; // Show KijunSen +input bool showChikouSpan = true; // Show ChikouSpan +input bool showSenkouSpanA = true; // Show Senkou Span A +input bool showSenkouSpanB = true; // Show Senkou Span B +input bool showKumo = true; // Show Kumo + +// +// Buffers ... + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#property indicator_chart_window + +// +#property indicator_buffers 8 +#property indicator_plots 6 + +// +// Plot Buffers ... + +// +#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 2 + +// +#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 2 + +// +#define chikouSpanBufferIndex 2 +double chikouSpanBuffer[]; + +// +#property indicator_label3 "XICH CS" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrDarkGreen +#property indicator_style3 STYLE_SOLID +#property indicator_width3 2 + +// +#define senkouSpanABufferIndex 3 +double senkouSpanABuffer[]; + +// +#property indicator_label4 "XICH SSA" +#property indicator_type4 DRAW_LINE +#property indicator_color4 clrLightGray +#property indicator_style4 STYLE_DASHDOTDOT +#property indicator_width4 2 + +// +#define senkouSpanBBufferIndex 4 +double senkouSpanBBuffer[]; + +// +#property indicator_label5 "XICH SSB" +#property indicator_type5 DRAW_LINE +#property indicator_color5 clrLightGray +#property indicator_style5 STYLE_DASHDOTDOT +#property indicator_width5 2 + +// +#define senkouABufferIndex 5 +double senkouABuffer[]; + +// +#define senkouBBufferIndex 6 +double senkouBBuffer[]; + +// +#define kumoBufferIndex 5 + +// +#property indicator_label6 "XICH Kumo" +#property indicator_type6 DRAW_FILLING +#property indicator_color6 clrAqua, clrMagenta +#property indicator_style6 STYLE_SOLID +#property indicator_width6 2 + +// +// Data Buffers ... + +// +int mLastBufferIndex = 6; + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +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(); + IndicatorSetInteger(INDICATOR_DIGITS, 2); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +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 +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // 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); + + // + 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, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + result = + // + kijunSenLength > 0 && + tenkanSenLength > 0 && + senkouSpanBLength > 0 && + IsValid(kijunSenMode) && + IsValid(tenkanSenMode) && + IsValid(chikouSpanMode) && + IsValid(senkouSpanBMode) + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(kijunSenLength, tenkanSenLength); + result = MathMax(result, senkouSpanBLength); + + // + return result; +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + 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); + + // + 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); + + // + 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); + + // + int shiftSize = shiftKumo ? kijunSenLength : 0; + + // + ENUM_DRAW_TYPE senkouSpanADrawType = showSenkouSpanA ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(senkouSpanABuffer, true); + SetIndexBuffer(senkouSpanABufferIndex, senkouSpanABuffer, INDICATOR_DATA); + PlotIndexSetInteger(senkouSpanABufferIndex, PLOT_SHIFT, shiftSize); + PlotIndexSetInteger(senkouSpanABufferIndex, PLOT_SHOW_DATA, showSenkouSpanA); + PlotIndexSetInteger(senkouSpanABufferIndex, PLOT_DRAW_TYPE, senkouSpanADrawType); + + // + ENUM_DRAW_TYPE senkouSpanBDrawType = showSenkouSpanB ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(senkouSpanBBuffer, true); + SetIndexBuffer(senkouSpanBBufferIndex, senkouSpanBBuffer, INDICATOR_DATA); + PlotIndexSetInteger(senkouSpanBBufferIndex, PLOT_SHIFT, shiftSize); + PlotIndexSetInteger(senkouSpanBBufferIndex, PLOT_SHOW_DATA, showSenkouSpanB); + PlotIndexSetInteger(senkouSpanBBufferIndex, PLOT_DRAW_TYPE, senkouSpanBDrawType); + + // + ArraySetAsSeries(senkouABuffer, true); + SetIndexBuffer(senkouABufferIndex, senkouABuffer, INDICATOR_DATA); + PlotIndexSetInteger(senkouABufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + ArraySetAsSeries(senkouBBuffer, true); + SetIndexBuffer(senkouBBufferIndex, senkouBBuffer, INDICATOR_DATA); + PlotIndexSetInteger(senkouBBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + 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); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +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[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + // + // bool canCalculate = true; + bool canCalculate = + barsLimit == 0 || + bar_index <= barsLimit; + if (canCalculate) + { + // + CalculateValues( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + else + { + FillBuffersZero(bar_index); + } +} + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + senkouABuffer[barIndex] = 0; + senkouBBuffer[barIndex] = 0; + kijunSenBuffer[barIndex] = 0; + tenkanSenBuffer[barIndex] = 0; + chikouSpanBuffer[barIndex] = 0; + senkouSpanABuffer[barIndex] = 0; + senkouSpanBBuffer[barIndex] = 0; +} + +/** + * Calculate Vales ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateValues( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + double uppers[]; + double lowers[]; + + // + double uppersMax = 0; + double uppersMin = 0; + + // + double lowersMax = 0; + double lowersMin = 0; + + // + // Calculate ChikouSpan ... + double iChikouSpan = GetAppliedPrice( + _Symbol, + _Period, + bar_index, + chikouSpanMode // + ); + + // + // Calculate TenkanSen ... + GetPriceBoundary( + uppers, + lowers, + _Symbol, + _Period, + tenkanSenMode, + tenkanSenLength, + bar_index // + ); + + // + uppersMax = uppers[ArrayMaximum(uppers)]; + uppersMin = uppers[ArrayMinimum(uppers)]; + + // + lowersMax = lowers[ArrayMaximum(lowers)]; + lowersMin = lowers[ArrayMinimum(lowers)]; + + // + double iTenkanSen = (uppersMax + lowersMin) / 2; + + // + // Calculate KijunSen ... + GetPriceBoundary( + uppers, + lowers, + _Symbol, + _Period, + kijunSenMode, + kijunSenLength, + bar_index // + ); + + // + uppersMax = uppers[ArrayMaximum(uppers)]; + uppersMin = uppers[ArrayMinimum(uppers)]; + + // + lowersMax = lowers[ArrayMaximum(lowers)]; + lowersMin = lowers[ArrayMinimum(lowers)]; + + // + double iKijunSen = (uppersMax + lowersMin) / 2; + + // + // Calculate SenkouSpanB ... + GetPriceBoundary( + uppers, + lowers, + _Symbol, + _Period, + senkouSpanBMode, + senkouSpanBLength, + bar_index // + ); + + // + uppersMax = uppers[ArrayMaximum(uppers)]; + uppersMin = uppers[ArrayMinimum(uppers)]; + + // + lowersMax = lowers[ArrayMaximum(lowers)]; + lowersMin = lowers[ArrayMinimum(lowers)]; + + // + double iSenkouSpanB = (uppersMax + lowersMin) / 2; + + // + // Calculate SenkouSpanA ... + double iSenkouSpanA = (iTenkanSen + iKijunSen) / 2; + + // + // Setting Buffers ... + kijunSenBuffer[bar_index] = iKijunSen; + senkouABuffer[bar_index] = iSenkouSpanA; + senkouBBuffer[bar_index] = iSenkouSpanB; + tenkanSenBuffer[bar_index] = iTenkanSen; + chikouSpanBuffer[bar_index] = iChikouSpan; + senkouSpanABuffer[bar_index] = iSenkouSpanA; + senkouSpanBBuffer[bar_index] = iSenkouSpanB; +} + +// diff --git a/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xoscs.mq5 b/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xoscs.mq5 new file mode 100644 index 0000000..4c32077 --- /dev/null +++ b/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xoscs.mq5 @@ -0,0 +1,1026 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XWZ +// Description: XWZ ... +// +// +// 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 XWZ Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121_X3MA" + +// +// Imports ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +input group "Accumulation/Distribution"; +input ENUM_APPLIED_VOLUME adAppliedTo = VOLUME_TICK; // Applied To + +// +input group "ADX"; +input int adxLength = 14; // Length + +// +input group "ATR"; +input int atrLength = 14; // Length + +// +input group "CCI"; +input int cciLength = 14; // Length +input ENUM_APPLIED_PRICE cciAppliedTo = PRICE_TYPICAL; // Applied To + +// +input group "RSI"; +input int rsiLength = 14; // Length +input ENUM_APPLIED_PRICE rsiAppliedTo = PRICE_CLOSE; // Applied To + +// +input group "MFI"; +input int mfiLength = 14; // Length +input ENUM_APPLIED_VOLUME mfiAppliedTo = VOLUME_TICK; // Applied To + +// +input group "RVI"; +input int rviLength = 14; // Length + +// +input group "MACD"; +input int macdFastLength = 12; // Fast EMA Length +input int macdSlowLength = 26; // Slow EMA Length +input int macdSignalLength = 9; // Signal Length +input ENUM_APPLIED_PRICE macdAppliedTo = PRICE_CLOSE; // Applied To + +// +input group "Momentum"; +input int momentumLength = 14; // Length +input ENUM_APPLIED_PRICE momentumAppliedTo = PRICE_CLOSE; // Applied To + +// +input group "Stochastic"; +input int stochasticKLength = 5; // K Length (Bars for Calculation) +input int stochasticDLength = 3; // D Length (first Smoothing) +input int stochasticSmoothingLength = 3; // Smoothing Length +input ENUM_MA_METHOD stochasticSmoothingMethod = MODE_SMA; // Smoothing Method +input ENUM_STO_PRICE stochasticAppliedTo = STO_LOWHIGH; // Applied To + +// +// Presentation ... +input group "Presentation"; + +// +input int startCalculationForLastBars = 1000; // Calculate Last n Bars + +// +// Buffers ... + +// +#define emptyValue 0.0 + +// +#property indicator_chart_window + +// +#property indicator_buffers 16 +#property indicator_plots 0 + +// +// Plot Buffers ... + +// +// Data Buffers ... + +// +int mLastBufferIndex = -1; + +// +// AC ... +#define acBufferIndex mLastBufferIndex + 1 +double acBuffer[]; + +// +// AD ... +#define adBufferIndex mLastBufferIndex + 2 +double adBuffer[]; + +// +// ADX ... +#define adxBufferIndex mLastBufferIndex + 3 +double adxBuffer[]; + +// +// ADX Plus ... +#define adxpBufferIndex mLastBufferIndex + 4 +double adxpBuffer[]; + +// +// ADX Negative ... +#define adxnBufferIndex mLastBufferIndex + 5 +double adxnBuffer[]; + +// +// ATR ... +#define atrBufferIndex mLastBufferIndex + 6 +double atrBuffer[]; + +// +// CCI ... +#define cciBufferIndex mLastBufferIndex + 7 +double cciBuffer[]; + +// +// RSI ... +#define rsiBufferIndex mLastBufferIndex + 8 +double rsiBuffer[]; + +// +// MFI ... +#define mfiBufferIndex mLastBufferIndex + 9 +double mfiBuffer[]; + +// +// RVI ... +#define rviBufferIndex mLastBufferIndex + 10 +double rviBuffer[]; + +// +// RVI Signal ... +#define rviSignalBufferIndex mLastBufferIndex + 11 +double rviSignalBuffer[]; + +// +// MACD ... +#define macdBufferIndex mLastBufferIndex + 12 +double macdBuffer[]; + +// +// MACD Signal ... +#define macdSignalBufferIndex mLastBufferIndex + 13 +double macdSignalBuffer[]; + +// +// Momentum ... +#define momentumBufferIndex mLastBufferIndex + 14 +double momentumBuffer[]; + +// +// Stochstic ... +#define stochasticBufferIndex mLastBufferIndex + 15 +double stochasticBuffer[]; + +// +// Stochstic Signal ... +#define stochasticSignalBufferIndex mLastBufferIndex + 16 +double stochasticSignalBuffer[]; + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +int acHandler = INVALID_HANDLE; +int adHandler = INVALID_HANDLE; +int adxHandler = INVALID_HANDLE; +int atrHandler = INVALID_HANDLE; +int cciHandler = INVALID_HANDLE; +int rsiHandler = INVALID_HANDLE; +int rviHandler = INVALID_HANDLE; +int mfiHandler = INVALID_HANDLE; +int macdHandler = INVALID_HANDLE; +int momentumHandler = INVALID_HANDLE; +int stochasticHandler = INVALID_HANDLE; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + if (!InitializeHandlres()) + { + return INIT_FAILED; + } + + // + // 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(); + IndicatorSetInteger(INDICATOR_DIGITS, 2); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +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 + + // + DeInitializeHandlres(); +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // 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); + + // + // Validate Calculated Bars ... + + // + // AC ... + int acCalculatedBars = BarsCalculated(acHandler); + + // + // AD ... + int adCalculatedBars = BarsCalculated(adHandler); + + // + // ADX ... + int adxCalculatedBars = BarsCalculated(adHandler); + + // + // ATR ... + int atrCalculatedBars = BarsCalculated(atrHandler); + + // + // CCI ... + int cciCalculatedBars = BarsCalculated(cciHandler); + + // + // RSI ... + int rsiCalculatedBars = BarsCalculated(rsiHandler); + + // + // MFI ... + int mfiCalculatedBars = BarsCalculated(mfiHandler); + + // + // RVI ... + int rviCalculatedBars = BarsCalculated(rviHandler); + + // + // MACD ... + int macdCalculatedBars = BarsCalculated(macdHandler); + + // + // Momentum ... + int momentumCalculatedBars = BarsCalculated(momentumHandler); + + // + // Stochastic ... + int stochasticCalculatedBars = BarsCalculated(stochasticHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // AC ... + acCalculatedBars >= maxLength && + // + // AD ... + adCalculatedBars >= maxLength && + // + // ADX ... + adxCalculatedBars >= maxLength && + // + // ATR ... + atrCalculatedBars >= maxLength && + // + // CCI ... + cciCalculatedBars >= maxLength && + // + // RSI ... + rsiCalculatedBars >= maxLength && + // + // MFI ... + mfiCalculatedBars >= maxLength && + // + // RVI ... + rviCalculatedBars >= maxLength && + // + // MACD ... + macdCalculatedBars >= maxLength && + // + // Momentum ... + momentumCalculatedBars >= maxLength && + // + // Stochastic ... + stochasticCalculatedBars >= maxLength + // + ; + if (!isPassedRequiredCalculatedBars) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + + // + // AC ... + int copiedACs = CopyBuffer(acHandler, MAIN_LINE, 0, limit, acBuffer); + + // + // AD ... + int copiedADs = CopyBuffer(adHandler, MAIN_LINE, 0, limit, adBuffer); + + // + // ADX ... + int copiedADXs = CopyBuffer(adxHandler, MAIN_LINE, 0, limit, adxBuffer); + + // + // ADX Plus ... + int copiedADXPs = CopyBuffer(adxHandler, PLUSDI_LINE, 0, limit, adxpBuffer); + + // + // ADX Negative ... + int copiedADXNs = CopyBuffer(adxHandler, MINUSDI_LINE, 0, limit, adxnBuffer); + + // + // ATR ... + int copiedATRs = CopyBuffer(atrHandler, MAIN_LINE, 0, limit, atrBuffer); + + // + // CCI ... + int copiedCCIs = CopyBuffer(cciHandler, MAIN_LINE, 0, limit, cciBuffer); + + // + // RSI ... + int copiedRSIs = CopyBuffer(rsiHandler, MAIN_LINE, 0, limit, rsiBuffer); + + // + // MFI ... + int copiedMFIs = CopyBuffer(mfiHandler, MAIN_LINE, 0, limit, mfiBuffer); + + // + // RVI ... + int copiedRVIs = CopyBuffer(rviHandler, MAIN_LINE, 0, limit, rviBuffer); + + // + // RVI ... + int copiedRVISignals = CopyBuffer(rviHandler, SIGNAL_LINE, 0, limit, rviSignalBuffer); + + // + // MACD ... + int copiedMACDs = CopyBuffer(macdHandler, MAIN_LINE, 0, limit, macdBuffer); + + // + // MACD Signal ... + int copiedMACDSignals = CopyBuffer(macdHandler, SIGNAL_LINE, 0, limit, macdSignalBuffer); + + // + // Momentum ... + int copiedMomentums = CopyBuffer(cciHandler, MAIN_LINE, 0, limit, momentumBuffer); + + // + // Stochastic ... + int copiedStochastics = CopyBuffer(stochasticHandler, MAIN_LINE, 0, limit, stochasticBuffer); + + // + // Stochastic Signal ... + int copiedStochasticSignals = CopyBuffer(stochasticHandler, SIGNAL_LINE, 0, limit, stochasticSignalBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // AC ... + copiedACs > 0 && + // + // AD ... + copiedADs > 0 && + // + // ADX ... + copiedADXs > 0 && + // + // ADX Plus ... + copiedADXPs > 0 && + // + // ADX Negative ... + copiedADXNs > 0 && + // + // ATR ... + copiedATRs > 0 && + // + // CCI ... + copiedCCIs > 0 && + // + // RSI ... + copiedRSIs > 0 && + // + // MFI ... + copiedMFIs > 0 && + // + // RVI ... + copiedRVIs > 0 && + // + // RVI Signal ... + copiedRVISignals > 0 && + // + // MACD ... + copiedMACDs > 0 && + // + // MACD Signal ... + copiedMACDSignals > 0 && + // + // Momentum ... + copiedMomentums > 0 && + // + // Stochastic ... + copiedStochastics > 0 && + // + // Stochastic Signal ... + copiedStochasticSignals > 0 + // + ; + if (!isPassedRequiredCopiedItems) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + // + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + result = + // + adxLength > 0 && + atrLength > 0 && + cciLength > 0 && + rsiLength > 0 && + mfiLength > 0 && + rviLength > 0 && + // + macdFastLength > 0 && + macdSlowLength > 0 && + macdSignalLength > 0 && + macdFastLength < macdSlowLength && + // + stochasticKLength > 0 && + stochasticDLength > 0 && + stochasticSmoothingLength > 0 && + // + momentumLength > 0 + // + ; + + // + return result; +} + +/** + * Initialize All Indicators Handlers ... + * + * @return ( bool ) + */ +bool InitializeHandlres() +{ + // + bool result = false; + + // + // AC ... + acHandler = iAC(_Symbol, _Period); + result = acHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // AD ... + adHandler = iAD( + _Symbol, + _Period, + adAppliedTo // + ); + result = adHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // ADX ... + adxHandler = iADX( + _Symbol, + _Period, + adxLength // + ); + result = adxHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // ATR ... + atrHandler = iATR( + _Symbol, + _Period, + atrLength // + ); + result = atrHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // CCI ... + cciHandler = iCCI( + _Symbol, + _Period, + cciLength, + cciAppliedTo // + ); + result = cciHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // RSI ... + rsiHandler = iRSI( + _Symbol, + _Period, + rsiLength, + rsiAppliedTo // + ); + result = rsiHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // MFI ... + mfiHandler = iMFI( + _Symbol, + _Period, + mfiLength, + mfiAppliedTo // + ); + result = mfiHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // RVI ... + rviHandler = iRVI( + _Symbol, + _Period, + rviLength // + ); + result = rviHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // MACD ... + macdHandler = iMACD( + _Symbol, + _Period, + macdFastLength, + macdSlowLength, + macdSignalLength, + macdAppliedTo // + ); + result = macdHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // Momentum ... + momentumHandler = iMomentum( + _Symbol, + _Period, + momentumLength, + momentumAppliedTo // + ); + result = momentumHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // Stochastic ... + stochasticHandler = iStochastic( + _Symbol, + _Period, + stochasticKLength, + stochasticDLength, + stochasticSmoothingLength, + stochasticSmoothingMethod, + stochasticAppliedTo // + ); + result = stochasticHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; +} + +/** + * Release All Indicators ... + */ +void DeInitializeHandlres() +{ + // + IndicatorRelease(acHandler); + IndicatorRelease(adHandler); + IndicatorRelease(adxHandler); + IndicatorRelease(atrHandler); + IndicatorRelease(cciHandler); + IndicatorRelease(rsiHandler); + IndicatorRelease(mfiHandler); + IndicatorRelease(rviHandler); + IndicatorRelease(macdHandler); + IndicatorRelease(momentumHandler); + IndicatorRelease(stochasticHandler); +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(adxLength, atrLength); + result = MathMax(result, cciLength); + result = MathMax(result, rsiLength); + result = MathMax(result, mfiLength); + result = MathMax(result, rviLength); + result = MathMax(result, momentumLength); + result = MathMax(result, macdFastLength); + result = MathMax(result, macdSlowLength); + result = MathMax(result, macdSignalLength); + result = MathMax(result, stochasticKLength); + result = MathMax(result, stochasticDLength); + result = MathMax(result, stochasticSmoothingLength); + + // + return result; +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + // + IndicatorSetInteger(INDICATOR_DIGITS, _Digits); + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + + // + // Data Buffers ... + + // + // AC ... + ArraySetAsSeries(acBuffer, true); + SetIndexBuffer(acBufferIndex, acBuffer, INDICATOR_CALCULATIONS); + + // + // AD ... + ArraySetAsSeries(adBuffer, true); + SetIndexBuffer(adBufferIndex, adBuffer, INDICATOR_CALCULATIONS); + + // + // ADX ... + ArraySetAsSeries(adxBuffer, true); + SetIndexBuffer(adxBufferIndex, adxBuffer, INDICATOR_CALCULATIONS); + + // + // ADX Plus ... + ArraySetAsSeries(adxpBuffer, true); + SetIndexBuffer(adxpBufferIndex, adxpBuffer, INDICATOR_CALCULATIONS); + + // + // ADX Negative ... + ArraySetAsSeries(adxnBuffer, true); + SetIndexBuffer(adxnBufferIndex, adxnBuffer, INDICATOR_CALCULATIONS); + + // + // ATR ... + ArraySetAsSeries(atrBuffer, true); + SetIndexBuffer(atrBufferIndex, atrBuffer, INDICATOR_CALCULATIONS); + + // + // CCI ... + ArraySetAsSeries(cciBuffer, true); + SetIndexBuffer(cciBufferIndex, cciBuffer, INDICATOR_CALCULATIONS); + + // + // RSI ... + ArraySetAsSeries(rsiBuffer, true); + SetIndexBuffer(rsiBufferIndex, rsiBuffer, INDICATOR_CALCULATIONS); + + // + // MFI ... + ArraySetAsSeries(mfiBuffer, true); + SetIndexBuffer(mfiBufferIndex, mfiBuffer, INDICATOR_CALCULATIONS); + + // + // RVI ... + ArraySetAsSeries(rviBuffer, true); + SetIndexBuffer(rviBufferIndex, rviBuffer, INDICATOR_CALCULATIONS); + + // + // RVI Signal ... + ArraySetAsSeries(rviSignalBuffer, true); + SetIndexBuffer(rviSignalBufferIndex, rviSignalBuffer, INDICATOR_CALCULATIONS); + + // + // MACD ... + ArraySetAsSeries(macdBuffer, true); + SetIndexBuffer(macdBufferIndex, macdBuffer, INDICATOR_CALCULATIONS); + + // + // MACD Signal ... + ArraySetAsSeries(macdSignalBuffer, true); + SetIndexBuffer(macdSignalBufferIndex, macdSignalBuffer, INDICATOR_CALCULATIONS); + + // + // Momentum ... + ArraySetAsSeries(momentumBuffer, true); + SetIndexBuffer(momentumBufferIndex, momentumBuffer, INDICATOR_CALCULATIONS); + + // + // Stochastics ... + ArraySetAsSeries(stochasticBuffer, true); + SetIndexBuffer(stochasticBufferIndex, stochasticBuffer, INDICATOR_CALCULATIONS); + + // + // Stochastics Signal ... + ArraySetAsSeries(stochasticSignalBuffer, true); + SetIndexBuffer(stochasticSignalBufferIndex, stochasticSignalBuffer, INDICATOR_CALCULATIONS); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +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[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + // + // bool canCalculate = true; + bool canCalculate = + barsLimit == 0 || + bar_index <= barsLimit; + if (canCalculate) + { + // + CalculateValues( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + else + { + FillBuffersZero(bar_index); + } +} + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + acBuffer[barIndex] = emptyValue; + adBuffer[barIndex] = emptyValue; + adxBuffer[barIndex] = emptyValue; + adxpBuffer[barIndex] = emptyValue; + adxnBuffer[barIndex] = emptyValue; + atrBuffer[barIndex] = emptyValue; + cciBuffer[barIndex] = emptyValue; + rsiBuffer[barIndex] = emptyValue; + mfiBuffer[barIndex] = emptyValue; + rviBuffer[barIndex] = emptyValue; + macdBuffer[barIndex] = emptyValue; + momentumBuffer[barIndex] = emptyValue; + rviSignalBuffer[barIndex] = emptyValue; + macdSignalBuffer[barIndex] = emptyValue; + stochasticBuffer[barIndex] = emptyValue; + stochasticSignalBuffer[barIndex] = emptyValue; +} + +/** + * Calculate Vales ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateValues( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // Implement Colorify Mechanism ... +} + +// diff --git a/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xstr.mq5 b/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xstr.mq5 new file mode 100644 index 0000000..3a95d4d --- /dev/null +++ b/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xstr.mq5 @@ -0,0 +1,812 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XSTR +// Description: XSTR ... +// +// +// 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 XSTR Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121 XSTR" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +// Market ... +input group "Market"; +input int strLength = 14; // Length +input double strMultiplier = 3; // Multiplier +input int vidyaLength = 14; // Smothing Length +input ENUM_MA_METHOD strBoundaryMode = MODE_SMA; // Boundary Mode +input ENUM_APPLIED_PRICE strAppliedTo = PRICE_MEDIAN; // Applied To +input ENUM_APPLIED_PRICE vidyaAppliedTo = PRICE_CLOSE; // Smoothing Applied To + +// +input group "Presentation"; +input bool showStr = true; // Show Str +input bool showVidya = true; // Show Vidya +input bool showStrUpper = true; // Show Str Upper +input bool showStrLower = true; // Show Str Lower +input bool showStrLowMa = true; // Show Low Smoothed Buffer +input bool showStrHighMa = true; // Show High Smoothed Buffer + +// +// Buffers ... + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#define emptyValue 0.0 + +// +#property indicator_chart_window + +// +#property indicator_buffers 10 +#property indicator_plots 6 + +// +// STR ... +#define strBufferIndex 0 +double strBuffer[]; + +#define strColorBufferIndex 1 +double strColorBuffer[]; + +// +#define strPlotBufferIndex 0 +#property indicator_label1 "X121 STR" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 CLR_NONE, clrLime, clrRed, clrGray +#property indicator_style1 STYLE_SOLID +#property indicator_width1 2 + +// +// Up ... +#define strUpBufferIndex 2 +double strUpBuffer[]; + +// +#define strUpPlotBufferIndex 1 +#property indicator_label2 "X121 STR U" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrBlueViolet +#property indicator_style2 STYLE_SOLID +#property indicator_width2 1 + +// +// Down ... +#define strDownBufferIndex 3 +double strDownBuffer[]; + +// +#define strDownPlotBufferIndex 2 +#property indicator_label3 "X121 STR D" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrBlueViolet +#property indicator_style3 STYLE_SOLID +#property indicator_width3 1 + +// +// High MA ... +#define strHighMaBufferIndex 4 +double strHighMaBuffer[]; + +// +#define strHighMaPlotBufferIndex 3 +#property indicator_label4 "X121 STR HSM" +#property indicator_type4 DRAW_LINE +#property indicator_color4 clrAqua +#property indicator_style4 STYLE_SOLID +#property indicator_width4 1 + +// +// Low Ma ... +#define strLowMaBufferIndex 5 +double strLowMaBuffer[]; + +// +#define strLowMaPlotBufferIndex 4 +#property indicator_label5 "X121 STR LSM" +#property indicator_type5 DRAW_LINE +#property indicator_color5 clrMagenta +#property indicator_style5 STYLE_SOLID +#property indicator_width5 1 + +// +// VIDYA ... +#define vidyaBufferIndex 6 +double vidyaBuffer[]; + +// +#define vidyaPlotBufferIndex 5 +#property indicator_label6 "X121 VIDYA" +#property indicator_type6 DRAW_LINE +#property indicator_color6 clrYellow +#property indicator_style6 STYLE_SOLID +#property indicator_width6 1 + +// +// Data Buffers ... + +// +int mLastBufferIndex = 6; + +// +// STR ... + +// +// Atr ... +#define atrBufferIndex mLastBufferIndex + 1 +double atrBuffer[]; + +// +// Price ... +#define strPriceBufferIndex mLastBufferIndex + 2 +double strPriceBuffer[]; + +// +// Trend ... +#define strStateBufferIndex mLastBufferIndex + 3 +double strStateBuffer[]; + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +// ATR Handler ... +int atrHandler = INVALID_HANDLE; + +// +// MA Handler ... +int lowMaHandler = INVALID_HANDLE; +int highMaHandler = INVALID_HANDLE; +int vidyaHandler = INVALID_HANDLE; + +// +bool isStrTrendChanged; +bool isStrStartBearishTrend; +bool isStrStartBullishTrend; + +// +int changeOfTrend; +int startBearishTrend; +int startBullishTrend; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + + // + // ATR ... + atrHandler = iATR( + _Symbol, + _Period, + strLength // + ); + bool isInited = atrHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // Low Ma ... + lowMaHandler = iMA( + _Symbol, + _Period, + strLength, + 0, + strBoundaryMode, + PRICE_LOW // + ); + isInited = lowMaHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // High Ma ... + highMaHandler = iMA( + _Symbol, + _Period, + strLength, + 0, + strBoundaryMode, + PRICE_HIGH // + ); + isInited = highMaHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // Vidya ... + vidyaHandler = iVIDyA( + _Symbol, + _Period, + strLength, + vidyaLength, + 0, // Shift ... + vidyaAppliedTo // + ); + isInited = vidyaHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // 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; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +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(atrHandler); + IndicatorRelease(vidyaHandler); + IndicatorRelease(lowMaHandler); + IndicatorRelease(highMaHandler); +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // Prepare Buffers ... + + // + // Validate Calculated Bars ... + + // + // ATR ... + int atrCalculatedBars = BarsCalculated(atrHandler); + + // + // VIDYA ... + int vidyaCalculatedBars = BarsCalculated(vidyaHandler); + + // + // Low Ma ... + int lowMaCalculatedBars = BarsCalculated(lowMaHandler); + + // + // High Ma ... + int highMaCalculatedBars = BarsCalculated(highMaHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // ATR ... + atrCalculatedBars >= 0 && + // + // VIDYA ... + vidyaCalculatedBars >= 0 && + // + // Low Ma ... + lowMaCalculatedBars >= 0 && + // + // High Ma ... + highMaCalculatedBars >= 0 + // + ; + if (!isPassedRequiredCalculatedBars) + { + return prev_calculated; + } + + // + // + // checking for the limit start of calculation of an indicator ... + limit = + (prev_calculated > rates_total || prev_calculated <= 0) + ? maxLength + : prev_calculated - 1; + + // + // Buffers Copy ... + + // + // ATR ... + int copiedAtrs = CopyBuffer(atrHandler, 0, 0, rates_total, atrBuffer); + + // + // VYDIA ... + int copiedVidyas = CopyBuffer(vidyaHandler, 0, 0, rates_total, vidyaBuffer); + + // + // Low Ma ... + int copiedLowMas = CopyBuffer(lowMaHandler, 0, 0, rates_total, strLowMaBuffer); + + // + // High Ma ... + int copiedHighMas = CopyBuffer(highMaHandler, 0, 0, rates_total, strHighMaBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // ATR ... + copiedAtrs >= 0 && + // + // VIDYA ... + copiedVidyas >= 0 && + // + // Low Ma ... + copiedLowMas >= 0 && + // + // Hig Ma ... + copiedHighMas >= 0 + // + ; + if (!isPassedRequiredCopiedItems) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit; i < rates_total && !IsStopped(); i++) + { + // + CalculateBuffers( + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = + // + // STR ... + strLength > 0 && + strMultiplier > 0 + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(1, strLength); + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // STR ... + SetIndexBuffer(strBufferIndex, strBuffer, INDICATOR_DATA); + SetIndexBuffer(strColorBufferIndex, strColorBuffer, INDICATOR_COLOR_INDEX); + + // + ENUM_DRAW_TYPE strUpDrawType = showStrUpper ? DRAW_LINE : DRAW_NONE; + SetIndexBuffer(strUpBufferIndex, strUpBuffer, INDICATOR_DATA); + PlotIndexSetDouble(strUpPlotBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(strUpPlotBufferIndex, PLOT_SHOW_DATA, showStrUpper); + PlotIndexSetInteger(strUpPlotBufferIndex, PLOT_DRAW_TYPE, strUpDrawType); + + // + ENUM_DRAW_TYPE strDownDrawType = showStrLower ? DRAW_LINE : DRAW_NONE; + SetIndexBuffer(strDownBufferIndex, strDownBuffer, INDICATOR_DATA); + PlotIndexSetDouble(strDownPlotBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(strDownPlotBufferIndex, PLOT_SHOW_DATA, showStrLower); + PlotIndexSetInteger(strDownPlotBufferIndex, PLOT_DRAW_TYPE, strDownDrawType); + + // + ENUM_DRAW_TYPE strLowMaDrawType = showStrLowMa ? DRAW_LINE : DRAW_NONE; + SetIndexBuffer(strLowMaBufferIndex, strLowMaBuffer, INDICATOR_DATA); + PlotIndexSetDouble(strLowMaPlotBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(strLowMaPlotBufferIndex, PLOT_SHOW_DATA, showStrLowMa); + PlotIndexSetInteger(strLowMaPlotBufferIndex, PLOT_DRAW_TYPE, strLowMaDrawType); + + // + ENUM_DRAW_TYPE strHighMaDrawType = showStrHighMa ? DRAW_LINE : DRAW_NONE; + SetIndexBuffer(strHighMaBufferIndex, strHighMaBuffer, INDICATOR_DATA); + PlotIndexSetDouble(strHighMaPlotBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(strHighMaPlotBufferIndex, PLOT_SHOW_DATA, showStrHighMa); + PlotIndexSetInteger(strHighMaPlotBufferIndex, PLOT_DRAW_TYPE, strHighMaDrawType); + + // + ENUM_DRAW_TYPE vidyaDrawType = showVidya ? DRAW_LINE : DRAW_NONE; + SetIndexBuffer(vidyaBufferIndex, vidyaBuffer, INDICATOR_DATA); + PlotIndexSetDouble(vidyaPlotBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(vidyaPlotBufferIndex, PLOT_SHOW_DATA, showVidya); + PlotIndexSetInteger(vidyaPlotBufferIndex, PLOT_DRAW_TYPE, vidyaDrawType); + + // + // Data Buffers ... + + // + SetIndexBuffer(strPriceBufferIndex, strPriceBuffer, INDICATOR_CALCULATIONS); + SetIndexBuffer(strStateBufferIndex, strStateBuffer, INDICATOR_CALCULATIONS); +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +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[], + const long &tickVolume[] // +) +{ + // + CalculateStr( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low // + ); +} + +// +// Custom ... + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + // STR ... + strBuffer[barIndex] = emptyValue; + strUpBuffer[barIndex] = emptyValue; + strDownBuffer[barIndex] = emptyValue; + strPriceBuffer[barIndex] = emptyValue; + strLowMaBuffer[barIndex] = emptyValue; + strHighMaBuffer[barIndex] = emptyValue; + + // + strColorBuffer[barIndex] = hideColorIDX; + strStateBuffer[barIndex] = hideColorIDX; +} + +/** + * Calculate STR ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + */ +void CalculateStr( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[] // +) +{ + // + // Calculated Price ... + ENUM_X_PRICE mPType = ToXPrice(strAppliedTo); + double price = GetAppliedPrice( + mPType, + open, + high, + low, + close, + bar_index // + ); + strPriceBuffer[bar_index] = price; + + // + double atr = atrBuffer[bar_index]; + + // + // Up ... + strUpBuffer[bar_index] = price + (strMultiplier * atr); + + // + // Down ... + strDownBuffer[bar_index] = price - (strMultiplier * atr); + + // + if (close[bar_index] > strUpBuffer[bar_index - 1]) + { + // + strStateBuffer[bar_index] = 1; + if (strStateBuffer[bar_index - 1] == -1) + { + changeOfTrend = 1; + } + } + else if (close[bar_index] < strDownBuffer[bar_index - 1]) + { + // + strStateBuffer[bar_index] = -1; + if (strStateBuffer[bar_index - 1] == 1) + { + changeOfTrend = 1; + } + } + else if (strStateBuffer[bar_index - 1] == 1) + { + // + strStateBuffer[bar_index] = 1; + changeOfTrend = 0; + } + else if (strStateBuffer[bar_index - 1] == -1) + { + // + strStateBuffer[bar_index] = -1; + changeOfTrend = 0; + } + + // + // Down Trend Starting ... + if (strStateBuffer[bar_index] < 0 && strStateBuffer[bar_index - 1] > 0) + { + startBearishTrend = 1; + } + else + { + startBearishTrend = 0; + } + + // + // Up Trend Starting ... + if (strStateBuffer[bar_index] > 0 && strStateBuffer[bar_index - 1] < 0) + { + startBullishTrend = 1; + } + else + { + startBullishTrend = 0; + } + + // + if (strStateBuffer[bar_index] > 0 && strDownBuffer[bar_index] < strDownBuffer[bar_index - 1]) + { + strDownBuffer[bar_index] = strDownBuffer[bar_index - 1]; + } + + // + if (strStateBuffer[bar_index] < 0 && strUpBuffer[bar_index] > strUpBuffer[bar_index - 1]) + { + strUpBuffer[bar_index] = strUpBuffer[bar_index - 1]; + } + + // + if (startBearishTrend == 1) + { + strUpBuffer[bar_index] = strPriceBuffer[bar_index] + (strMultiplier * atr); + } + + // + if (startBullishTrend == 1) + { + strDownBuffer[bar_index] = strPriceBuffer[bar_index] - (strMultiplier * atr); + } + + // + // Draw the indicator ... + + // + double colorIDX = hideColorIDX; + strColorBuffer[bar_index] = colorIDX; + + // + if (strStateBuffer[bar_index] == 1) + { + // + strBuffer[bar_index] = strDownBuffer[bar_index]; + if (changeOfTrend == 1) + { + strBuffer[bar_index - 1] = strBuffer[bar_index - 2]; + changeOfTrend = 0; + } + + // + colorIDX = bullishColorIDX; + } + else if (strStateBuffer[bar_index] == -1) + { + // + strBuffer[bar_index] = strUpBuffer[bar_index]; + if (changeOfTrend == 1) + { + // + strBuffer[bar_index - 1] = strBuffer[bar_index - 2]; + changeOfTrend = 0; + } + + // + colorIDX = bearishColorIDX; + } + + // + if (showStr) + { + strColorBuffer[bar_index] = colorIDX; + } + + // + // Str Mid ... + + // + double iStrMid = strDownBuffer[bar_index] + ((strUpBuffer[bar_index] - strDownBuffer[bar_index]) / 2); + + // +} + +// \ No newline at end of file diff --git a/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xtb.mq5 b/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xtb.mq5 new file mode 100644 index 0000000..f40cea9 --- /dev/null +++ b/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xtb.mq5 @@ -0,0 +1,2966 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 X3MA +// Description: X3MA ... +// +// +// 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 XTB Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121 XTB" + +// +// Includes Common Library ... +#include "../Classes/x-saherelm.x-alert.class.mq5" +#include "../Classes/x-saherelm.x-bar.analyser.class.mq5" +#include "../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" +#include "../Libraries/x-saherelm.x-poi.lib.mq5" + +// +enum ENUM_XCAEA_TIGGER_TYPE +{ + XCA_TRIGGER_NONE, // None + XCA_TRIGGER_BULL, // TriggerBull + XCA_TRIGGER_BEAR, // TriggerBear +}; + +// +bool IsValid(ENUM_XCAEA_TIGGER_TYPE value) +{ + return value != XCA_TRIGGER_NONE; +} + +// +string ToString(ENUM_XCAEA_TIGGER_TYPE value) +{ + return EnumToString(value); +} + +// +ENUM_XCAEA_TIGGER_TYPE GetType(string type) +{ + // + ENUM_XCAEA_TIGGER_TYPE result = XCA_TRIGGER_NONE; + + // + bool isTriggerBull = type == ToString(XCA_TRIGGER_BULL); + bool isTriggerBear = type == ToString(XCA_TRIGGER_BEAR); + + // + if (isTriggerBull) + { + result = XCA_TRIGGER_BULL; + } + else if (isTriggerBear) + { + result = XCA_TRIGGER_BEAR; + } + + // + return result; +} + +// +ENUM_X_DIRECTION GetDirection(ENUM_XCAEA_TIGGER_TYPE value) +{ + return value == XCA_TRIGGER_BULL + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; +} + +// +struct XTriggerBlock +{ + // + // Props ... + XBoxZone ob; // Order Block + XBoxZone fvg; // Fair Value Gap + XOHCL swingBar; // Swing of Trigger + XBoxZone trigger; // Trigger Block + XBoxZone rLiquidity; // Reversal Liquidity + XBoxZone fLiquidity; // Following Liquidity + + // + XSignal signal; // Pepared Signal + + // + // Constructor ... + XTriggerBlock() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + ob.Clean(); + fvg.Clean(); + signal.Clean(); + trigger.Clean(); + swingBar.Clean(); + rLiquidity.Clean(); + fLiquidity.Clean(); + + // + ZeroMemory(this); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = ob.IsValid() && + fvg.IsValid() && + trigger.IsValid(); + + // + return result; + } + + // + bool IsBullish() + { + return IsValid() && + ob.IsBullish(); + } + + // + bool IsBearish() + { + return IsValid() && + ob.IsBearish(); + } + + // + int ToIndex() + { + return trigger.ToIndex(); + } + + // + int FromIndex() + { + return trigger.FromIndex(); + } + + // + ENUM_X_DIRECTION GetDirection() + { + // + ENUM_X_DIRECTION result = X_DIRECTION_NONE; + + // + if (IsValid()) + { + result = ob.dir; + } + + // + return result; + } + + // +}; + +// +// Inputs ... +input group "Market"; +input ENUM_X_PERIOD_METHOD trendPeriodMethod = X_PERIOD_AUTO; // How to Find Trend Period +input ENUM_TIMEFRAMES trendPeriod = NULL; // Trend Time Period +input ENUM_MA_METHOD trendMode = MODE_SMA; // Trend Mode +input ENUM_APPLIED_PRICE trendAppliedTo = PRICE_CLOSE; // Trend Applied To +input double sarStep = 0.02; // Sar Step +input double sarMax = 0.2; // Sar Maximum +input int adxLength = 14; // ADX Length +input double adxThreshold = 25.0; // ADX Threshold +input int rsiLength = 14; // RSI Length +input double rsiOBLevel = 70.0; // RSI OB Level +input double rsiOSLevel = 30.0; // RSI OS Level +input ENUM_APPLIED_PRICE rsiAppliedTo = PRICE_CLOSE; // RSI Applied To +input int atrLength = 14; // ATR Length +input double atrMultiplier = 1.5; // ATR Band Multiplier +input ENUM_X_PRICE atrUpperPriceType = X_PRICE_HIGH; // ATR Upper Zone Applied To +input ENUM_X_PRICE atrLowerPriceType = X_PRICE_LOW; // ATR Lower Zone Applied To +input ENUM_X_MA_METHOD atrSignalMethod = X_MA_MODE_SMA; // ATR Signalling Method +input int barsSignalLength = 14; // Bars Signal Length +input ENUM_X_MA_METHOD barsSignalMethod = X_MA_MODE_EMA; // Bars Signalling Method +input int deltaSignalLength = 14; // Delta Signal Length +input ENUM_X_MA_METHOD deltaSignalMethod = X_MA_MODE_EMA; // Delta Signalling Method +input int volumeSignalLength = 14; // Volume Signal Length +input ENUM_X_MA_METHOD volumeSignalMethod = X_MA_MODE_EMA; // Volume Signalling Method +input int hkSignalBarLength = 14; // Hiken Ashi Signal Length +input ENUM_X_MA_METHOD hkSignalBarMethod = X_MA_MODE_EMA; // Hiken Ashi Signal Method + +// +// Validating ... +input group "Validating"; +input bool forceHasSwing = true; // Force Blocks to Have Swing +input bool forceHasFLiquidity = false; // Force Blocks to Have Following Liquidity +input bool forceHasRLiquidity = false; // Force Blocks to Have Reversal Liquidity +input bool validateGapSequence = false; // Validate Block's Gap Sequence +input bool validateBlockEdgeBreakout = false; // Validate Block's Edge Breakout + +// +// Filtering ... +input group "Filtering"; +input bool filterBasedOnSar = false; // Filter Based on Sar +input bool filterBasedOnRSI = false; // Filter Based on RSI +input bool filterBasedOnADX = false; // Filter Based on ADX +input bool filterBasedOnATR = false; // Filter Based on ATR +input bool filterBasedOnTrend = false; // Filter Based on Trend +input bool filterBasedOnDelta = false; // Filter Based on Delta +input bool filterBasedOnVolume = false; // Filter Based on Volume +input bool filterBasedOnSignalBar = false; // Filter Based on Signal Bar +input bool filterBasedOnTrendBars = false; // Filter Based on Trend Bars +input bool filterBasedOnHKSignalBar = false; // Filter Based on Hiken Ashi Signal Bar + +// +// Alert ... +input group "Alerts"; +input string alertPrefix = ""; // Alert Prefix +input bool _logAlerts = true; // Log Alerts +input bool _pushAlerts = false; // Push Alerts +input bool _mailAlerts = false; // Mail Alerts +input bool _terminalAlerts = true; // Terminal Alerts + +// +// Presentation ... +input group "Presentation"; +input bool showBars = true; // Show Bars +input bool showSar = false; // Show Sar +input bool showTrend = false; // Show Trend +input bool showHKBars = false; // Show Hiken Ashi Bars +input bool showATRBand = false; // Show ATR Band +input bool showTrendBars = false; // Show Trend Bars +input bool showSignalBars = false; // Show Signal Bars +input bool showHKSignalBars = false; // Show Hiken Ashi Signal Bars + +// +// Draws ... +input bool drawZones = false; // Draw Detected Zones +input bool drawSignals = false; // Draw Zone's Signal + +// +input int startCalculationForLastBars = 1000; // Calculate Last n Bars +input int sarArrowCode = 159; // Sar Arrow Code +input int rrZoneLength = 7; // Draw Risk Reward Ratio till n Bars +input int maxSignalR2R = 4; // Max Allowed Signal R2R +input double slAtrMultiplier = 0; // Additional SL ATR Multiplier + +// +// Styling ... + +// +// Trigger Block ... +input int tbWidth = 1; // Trigger Block Width +input color tbBullishColor = clrAqua; // Trigger Block Bullish Color +input color tbBearishColor = clrMagenta; // Trigger Block Bearish Color +input ENUM_LINE_STYLE tbStyle = STYLE_DASHDOTDOT; // Trigger Block Style + +// +// OB ... +input int obWidth = 1; // OB Width +input color obBullishColor = clrLime; // OB Bullish Color +input color obBearishColor = clrRed; // OB Bearish Color +input ENUM_LINE_STYLE obStyle = STYLE_DOT; // OB Style + +// +// FVG ... +input int fvgWidth = 2; // FVG Width +input color fvgBullishColor = clrLime; // FVG Bullish Color +input color fvgBearishColor = clrRed; // FVG Bearish Color +input ENUM_LINE_STYLE fvgStyle = STYLE_SOLID; // FVG Style + +// +// Buffers ... + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#define bullishState 1 +#define neuturalState 0 +#define bearishState -1 + +// +#define emptyValue 0.0 + +// +#property indicator_chart_window + +// +#property indicator_buffers 36 +#property indicator_plots 7 + +// +// Plot Buffers ... + +// +// TREND ... + +// +#define trendBufferIndex 0 +#define trendBufferPlotIndex 0 +double trendBuffer[]; + +// +#define trendColorBufferIndex 1 +double trendColorBuffer[]; + +// +#property indicator_label1 "X121 Trend" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 CLR_NONE, clrAqua, clrMagenta, clrGray +#property indicator_style1 STYLE_DASH +#property indicator_width1 2 + +// +// SAR ... + +// +#define sarBufferIndex 2 +#define sarBufferPlotIndex 2 +double sarBuffer[]; + +// +#define sarColorBufferIndex 3 +double sarColorBuffer[]; + +// +#property indicator_label2 "X121 SAR" +#property indicator_type2 DRAW_COLOR_ARROW +#property indicator_color2 CLR_NONE, clrAqua, clrMagenta, clrGray +#property indicator_width2 2 + +// +// Signal Bar ... + +// +#define openSignalBufferIndex 4 +double openSignalBuffer[]; + +// +#define highSignalBufferIndex 5 +double highSignalBuffer[]; + +// +#define lowSignalBufferIndex 6 +double lowSignalBuffer[]; + +// +#define closeSignalBufferIndex 7 +double closeSignalBuffer[]; + +// +#define signalBarColorBufferIndex 8 +double signalBarColorBuffer[]; + +// +#define signalBarBufferIndex 2 +#property indicator_label3 "X121 XSGB Open;X121 XSGB High;X121 XSGB Low;X121 XSGB Close" +#property indicator_type3 DRAW_COLOR_CANDLES +#property indicator_color3 CLR_NONE, clrLime, clrRed + +// +// XHK ... + +// +#define openHKBufferIndex 9 +double openHKBuffer[]; + +// +#define highHKBufferIndex 10 +double highHKBuffer[]; + +// +#define lowHKBufferIndex 11 +double lowHKBuffer[]; + +// +#define closeHKBufferIndex 12 +double closeHKBuffer[]; + +// +#define barHKColorBufferIndex 13 +double barHKColorBuffer[]; + +// +#define barHKBufferIndex 3 +#property indicator_label4 "X121 XHK Open;X121 XHK High;X121 XHK Low;X121 XHK Close" +#property indicator_type4 DRAW_COLOR_CANDLES +#property indicator_color4 CLR_NONE, clrDodgerBlue, clrDarkGoldenrod + +// +// XHK SIGNAL ... + +// +// Open ... +#define openHKSignalBufferIndex 14 +double openHKSignalBuffer[]; + +// +// High ... +#define highHKSignalBufferIndex 15 +double highHKSignalBuffer[]; + +// +// Low ... +#define lowHKSignalBufferIndex 16 +double lowHKSignalBuffer[]; + +// +// Close ... +#define closeHKSignalBufferIndex 17 +double closeHKSignalBuffer[]; + +// +// Candle Color ... +#define barHKSignalColorBufferIndex 18 +double barHKSignalColorBuffer[]; + +// +#define barHKSignalBufferIndex 4 +#property indicator_label5 "X121 XHKSM Open;X121 XHKSM High;X121 XHKSM Low;X121 XHKSM Close" +#property indicator_type5 DRAW_COLOR_CANDLES +#property indicator_color5 CLR_NONE, clrAqua, clrMagenta + +// +// ATR ... + +// +// Upper ... + +// +#define atrUpperBufferIndex 19 +#define atrUpperBufferPlotIndex 5 +double atrUpperBuffer[]; + +#property indicator_label6 "X121 XATRU" +#property indicator_type6 DRAW_LINE +#property indicator_color6 clrYellow +#property indicator_style6 STYLE_SOLID +#property indicator_width6 1 + +// +// Lower ... + +// +#define atrLowerBufferIndex 20 +#define atrLowerBufferPlotIndex 6 +double atrLowerBuffer[]; + +#property indicator_label7 "X121 XATRL" +#property indicator_type7 DRAW_LINE +#property indicator_color7 clrYellow +#property indicator_style7 STYLE_SOLID +#property indicator_width7 1 + +// +// Data Buffers ... + +#define mLastBufferIndex 20 + +// +// TREND State ... + +// +#define trendStateBufferIndex mLastBufferIndex + 1 +double trendStateBuffer[]; + +// +// SAR ... + +// +#define sarStateBufferIndex mLastBufferIndex + 2 +double sarStateBuffer[]; + +// +// RSI ... + +// +#define rsiBufferIndex mLastBufferIndex + 3 +double rsiBuffer[]; + +// +// ADX ... + +// +#define adxBufferIndex mLastBufferIndex + 4 +double adxBuffer[]; + +// +#define adxpBufferIndex mLastBufferIndex + 5 +double adxpBuffer[]; + +// +#define adxnBufferIndex mLastBufferIndex + 6 +double adxnBuffer[]; + +// +// DELTA ... + +// +#define deltaBufferIndex mLastBufferIndex + 7 +double deltaBuffer[]; + +// +#define deltaSignalBufferIndex mLastBufferIndex + 8 +double deltaSignalBuffer[]; + +// +// VOLUMES ... + +// +#define bullishVolumeBufferIndex mLastBufferIndex + 9 +double bullishVolumeBuffer[]; + +// +#define bearishVolumeBufferIndex mLastBufferIndex + 10 +double bearishVolumeBuffer[]; + +// +#define bullishVolumeSignalBufferIndex mLastBufferIndex + 11 +double bullishVolumeSignalBuffer[]; + +// +#define bearishVolumeSignalBufferIndex mLastBufferIndex + 12 +double bearishVolumeSignalBuffer[]; + +// +// ATR ... +#define atrBufferIndex mLastBufferIndex + 13 +double atrBuffer[]; + +#define atrUpperRawBufferIndex mLastBufferIndex + 14 +double atrUpperRawBuffer[]; + +#define atrLowerRawBufferIndex mLastBufferIndex + 15 +double atrLowerRawBuffer[]; + +// +// Variables, Properties and etc ... + +// +int limit; + +// +int maxLength; + +// +int firstBarIndex; + +// +// Bars Color Variables ... +color _upColor = clrLime; +color _downColor = clrRed; +color _lineColor = clrLime; +color _bullishColor = clrLime; +color _bearishColor = clrRed; + +// +XCAlert *alert; +double mPoints = 0; +CArrayObj mObjects; +XCPOIDrawer *drawer; +bool mEnableAlerts = false; +XCBarAnalyser *barAnalyser; +int mTrendPeriodLength = 0; +int atrHandler = INVALID_HANDLE; +int sarHandler = INVALID_HANDLE; +int rsiHandler = INVALID_HANDLE; +int adxHandler = INVALID_HANDLE; +int trendHandler = INVALID_HANDLE; +ENUM_TIMEFRAMES mTrendPeriod = NULL; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + + // + // Configure Alert ... + alert = new XCAlert(); + mEnableAlerts = + _logAlerts || + _pushAlerts || + _mailAlerts || + _terminalAlerts; + string mPrefix = ShortName + + (!IsValid(alertPrefix) + ? "" + : "[" + alertPrefix + "]"); + alert.SetPrefix(mPrefix); + alert.SetLogAlerts(_logAlerts); + alert.SetMailAlerts(_mailAlerts); + alert.SetPushAlerts(_pushAlerts); + alert.SetEnableAlerts(mEnableAlerts); + alert.SetTerminalAlerts(_terminalAlerts); + + // + drawer = new XCPOIDrawer(); + barAnalyser = new XCBarAnalyser(); + + // + // Initializing TrendPeriod ... + int cPeriodSeconds = PeriodSeconds(_Period); + if (trendPeriodMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mTrendPeriod = GetCyclePeriod( + X_MARKET_CYCLE_HIND, + _Period // + ); + } + else + { + mTrendPeriod = trendPeriod; + } + if (IsValid(mTrendPeriod)) + { + mTrendPeriodLength = PeriodSeconds(mTrendPeriod) / cPeriodSeconds; + } + + // + // ATR ... + atrHandler = iATR( + _Symbol, + _Period, + atrLength // + ); + bool isInited = atrHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // SAR ... + sarHandler = iSAR( + _Symbol, + _Period, + sarStep, + sarMax // + ); + isInited = sarHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // RSI ... + rsiHandler = iRSI( + _Symbol, + _Period, + rsiLength, + rsiAppliedTo // + ); + isInited = rsiHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // ADX ... + adxHandler = iADX( + _Symbol, + _Period, + adxLength // + ); + isInited = adxHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // TREND ... + trendHandler = iMA( + _Symbol, + _Period, + mTrendPeriodLength, + 0, + trendMode, + trendAppliedTo // + ); + isInited = trendHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + mPoints = GetPoints(_Symbol); + + // + // 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(); + + // + ReadBarStyle(); + + // + if (showBars) + { + ShowBars(); + } + else + { + HideBars(); + } + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +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 + + // + mObjects.Clear(); + + // + delete alert; + delete drawer; + + // + ZeroMemory(alert); + ZeroMemory(drawer); + ZeroMemory(barAnalyser); + + // + ShowBars(); + + // + IndicatorRelease(atrHandler); + IndicatorRelease(sarHandler); + IndicatorRelease(rsiHandler); + IndicatorRelease(adxHandler); + IndicatorRelease(trendHandler); +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // 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); + + // + // Validate Calculated Bars ... + + // + // ATR ... + int atrCalculatedBars = BarsCalculated(atrHandler); + + // + // SAR ... + int sarCalculatedBars = BarsCalculated(sarHandler); + + // + // RSI ... + int rsiCalculatedBars = BarsCalculated(rsiHandler); + + // + // ADX ... + int adxCalculatedBars = BarsCalculated(adxHandler); + + // + // TREND ... + int trendCalculatedBars = BarsCalculated(trendHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // ATR ... + atrCalculatedBars >= maxLength && + // + // SAR ... + sarCalculatedBars >= maxLength && + // + // RSI ... + rsiCalculatedBars >= maxLength && + // + // ADX ... + adxCalculatedBars >= maxLength && + // + // TREND ... + trendCalculatedBars >= maxLength + // + ; + if (!isPassedRequiredCalculatedBars) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + + // + // ATR ... + int copiedAtrs = CopyBuffer(atrHandler, MAIN_LINE, 0, limit, atrBuffer); + + // + // SAR ... + int copiedSars = CopyBuffer(sarHandler, MAIN_LINE, 0, limit, sarBuffer); + + // + // RSI ... + int copiedRSIs = CopyBuffer(rsiHandler, MAIN_LINE, 0, limit, rsiBuffer); + + // + // ADX ... + int copiedADXs = CopyBuffer(adxHandler, MAIN_LINE, 0, limit, adxBuffer); + + // + // ADX Plus ... + int copiedADXPs = CopyBuffer(adxHandler, PLUSDI_LINE, 0, limit, adxpBuffer); + + // + // ADX Negative ... + int copiedADXNs = CopyBuffer(adxHandler, MINUSDI_LINE, 0, limit, adxnBuffer); + + // + // TREND ... + int copiedTrends = CopyBuffer(trendHandler, MAIN_LINE, 0, limit, trendBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // ATR ... + copiedAtrs >= limit && + // + // SAR ... + copiedSars >= limit && + // + // RSI ... + copiedRSIs >= limit && + // + // TREND ... + copiedTrends >= limit + // + ; + if (!isPassedRequiredCopiedItems) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + if (prev_calculated == 0) + { + // + string message = "History Finished ..."; + Print(message); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + result = + // + sarMax > 0 && + sarStep > 0 && + adxLength > 0 && + atrLength > 0 && + rsiLength > 0 && + rsiOBLevel > 0 && + rsiOSLevel > 0 && + sarMax > sarStep && + atrMultiplier > 0 && + barsSignalLength > 2 && + deltaSignalLength > 2 && + hkSignalBarLength > 2 && + volumeSignalLength > 2 && + IsValid(atrUpperPriceType) && + IsValid(atrLowerPriceType) && + barsSignalMethod != X_MA_MODE_NONE && + deltaSignalMethod != X_MA_MODE_NONE && + hkSignalBarMethod != X_MA_MODE_NONE && + volumeSignalMethod != X_MA_MODE_NONE && + IsValid(trendPeriodMethod, trendPeriod) + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(adxLength, rsiLength); + result = MathMax(result, barsSignalLength); + result = MathMax(result, deltaSignalLength); + result = MathMax(result, volumeSignalLength); + result = MathMax(result, hkSignalBarLength); + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + + // + // TREND ... + + // + ArraySetAsSeries(trendBuffer, true); + SetIndexBuffer(trendBufferIndex, trendBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(trendBufferPlotIndex, PLOT_SHOW_DATA, showTrend); + + // + PlotIndexSetDouble(trendBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(trendColorBuffer, true); + SetIndexBuffer(trendColorBufferIndex, trendColorBuffer, INDICATOR_COLOR_INDEX); + + // + // SAR ... + + // + ArraySetAsSeries(sarBuffer, true); + SetIndexBuffer(sarBufferIndex, sarBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(sarBufferPlotIndex, PLOT_SHOW_DATA, showSar); + + // + PlotIndexSetDouble(sarBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(sarBufferPlotIndex, PLOT_ARROW, sarArrowCode); + + // + ArraySetAsSeries(sarColorBuffer, true); + SetIndexBuffer(sarColorBufferIndex, sarColorBuffer, INDICATOR_COLOR_INDEX); + + // + // SIGNAL Bar ... + + // + // Signal Bars Color ... + ArraySetAsSeries(signalBarColorBuffer, true); + SetIndexBuffer(signalBarColorBufferIndex, signalBarColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Set EMPTY_VALUE on XHK Bar Buffer ... + PlotIndexSetDouble(signalBarBufferIndex, PLOT_EMPTY_VALUE, 0.0); + PlotIndexSetInteger(signalBarBufferIndex, PLOT_SHOW_DATA, false); + + // + // Open ... + ArraySetAsSeries(openSignalBuffer, true); + SetIndexBuffer(openSignalBufferIndex, openSignalBuffer, INDICATOR_DATA); + + // + // High ... + ArraySetAsSeries(highSignalBuffer, true); + SetIndexBuffer(highSignalBufferIndex, highSignalBuffer, INDICATOR_DATA); + + // + // Close ... + ArraySetAsSeries(closeSignalBuffer, true); + SetIndexBuffer(closeSignalBufferIndex, closeSignalBuffer, INDICATOR_DATA); + + // + // Low ... + ArraySetAsSeries(lowSignalBuffer, true); + SetIndexBuffer(lowSignalBufferIndex, lowSignalBuffer, INDICATOR_DATA); + + // + // XHK ... + + // + // HK Bars Color ... + ArraySetAsSeries(barHKColorBuffer, true); + SetIndexBuffer(barHKColorBufferIndex, barHKColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Set EMPTY_VALUE on XHK Bar Buffer ... + PlotIndexSetDouble(barHKBufferIndex, PLOT_EMPTY_VALUE, 0.0); + PlotIndexSetInteger(barHKBufferIndex, PLOT_SHOW_DATA, false); + + // + // Open ... + ArraySetAsSeries(openHKBuffer, true); + SetIndexBuffer(openHKBufferIndex, openHKBuffer, INDICATOR_DATA); + + // + // High ... + ArraySetAsSeries(highHKBuffer, true); + SetIndexBuffer(highHKBufferIndex, highHKBuffer, INDICATOR_DATA); + + // + // Close ... + ArraySetAsSeries(closeHKBuffer, true); + SetIndexBuffer(closeHKBufferIndex, closeHKBuffer, INDICATOR_DATA); + + // + // Low ... + ArraySetAsSeries(lowHKBuffer, true); + SetIndexBuffer(lowHKBufferIndex, lowHKBuffer, INDICATOR_DATA); + + // + // XHK SIGNAL ... + + // + // HK Bars Color ... + ArraySetAsSeries(barHKSignalColorBuffer, true); + SetIndexBuffer(barHKSignalColorBufferIndex, barHKSignalColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Set EMPTY_VALUE on XHK Bar Buffer ... + PlotIndexSetDouble(barHKSignalBufferIndex, PLOT_EMPTY_VALUE, 0.0); + PlotIndexSetInteger(barHKSignalBufferIndex, PLOT_SHOW_DATA, false); + + // + // Open ... + ArraySetAsSeries(openHKSignalBuffer, true); + SetIndexBuffer(openHKSignalBufferIndex, openHKSignalBuffer, INDICATOR_DATA); + + // + // High ... + ArraySetAsSeries(highHKSignalBuffer, true); + SetIndexBuffer(highHKSignalBufferIndex, highHKSignalBuffer, INDICATOR_DATA); + + // + // Close ... + ArraySetAsSeries(closeHKSignalBuffer, true); + SetIndexBuffer(closeHKSignalBufferIndex, closeHKSignalBuffer, INDICATOR_DATA); + + // + // Low ... + ArraySetAsSeries(lowHKSignalBuffer, true); + SetIndexBuffer(lowHKSignalBufferIndex, lowHKSignalBuffer, INDICATOR_DATA); + + // + // ATR ... + + // + // UPPER ... + ENUM_DRAW_TYPE atrUpperDrawType = showATRBand ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(atrUpperBuffer, true); + SetIndexBuffer(atrUpperBufferIndex, atrUpperBuffer, INDICATOR_DATA); + PlotIndexSetDouble(atrUpperBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(atrUpperBufferPlotIndex, PLOT_SHOW_DATA, showATRBand); + PlotIndexSetInteger(atrUpperBufferPlotIndex, PLOT_DRAW_TYPE, atrUpperDrawType); + + // + // LOWER ... + ENUM_DRAW_TYPE atrLowerDrawType = showATRBand ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(atrLowerBuffer, true); + SetIndexBuffer(atrLowerBufferIndex, atrLowerBuffer, INDICATOR_DATA); + PlotIndexSetDouble(atrLowerBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(atrLowerBufferPlotIndex, PLOT_SHOW_DATA, showATRBand); + PlotIndexSetInteger(atrLowerBufferPlotIndex, PLOT_DRAW_TYPE, atrLowerDrawType); + + // + // Data Buffers ... + + // + ArraySetAsSeries(trendStateBuffer, true); + SetIndexBuffer(trendStateBufferIndex, trendStateBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(sarStateBuffer, true); + SetIndexBuffer(sarStateBufferIndex, sarStateBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(rsiBuffer, true); + SetIndexBuffer(rsiBufferIndex, rsiBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(adxBuffer, true); + SetIndexBuffer(adxBufferIndex, adxBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(adxpBuffer, true); + SetIndexBuffer(adxpBufferIndex, adxpBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(adxnBuffer, true); + SetIndexBuffer(adxnBufferIndex, adxnBuffer, INDICATOR_CALCULATIONS); + + // + // DELTA ... + + // + ArraySetAsSeries(deltaBuffer, true); + SetIndexBuffer(deltaBufferIndex, deltaBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(deltaSignalBuffer, true); + SetIndexBuffer(deltaSignalBufferIndex, deltaSignalBuffer, INDICATOR_CALCULATIONS); + + // + // VOLUME ... + + // + ArraySetAsSeries(bullishVolumeBuffer, true); + SetIndexBuffer(bullishVolumeBufferIndex, bullishVolumeBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(bearishVolumeBuffer, true); + SetIndexBuffer(bearishVolumeBufferIndex, bearishVolumeBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(bullishVolumeSignalBuffer, true); + SetIndexBuffer(bullishVolumeSignalBufferIndex, bullishVolumeSignalBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(bearishVolumeSignalBuffer, true); + SetIndexBuffer(bearishVolumeSignalBufferIndex, bearishVolumeSignalBuffer, INDICATOR_CALCULATIONS); + + // + // ATR ... + ArraySetAsSeries(atrBuffer, true); + SetIndexBuffer(atrBufferIndex, atrBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(atrUpperRawBuffer, true); + SetIndexBuffer(atrUpperRawBufferIndex, atrUpperRawBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(atrLowerRawBuffer, true); + SetIndexBuffer(atrLowerRawBufferIndex, atrLowerRawBuffer, INDICATOR_CALCULATIONS); +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + // + IndicatorSetInteger(INDICATOR_DIGITS, _Digits); + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +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[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + if (barsLimit == 0) + { + // + barsLimit = ratesTotal; + firstBarIndex = barsLimit - 1; + } + else + { + // + firstBarIndex = startCalculationForLastBars; + } + + // + // bool canCalculate = true; + bool canCalculate = + bar_index <= barsLimit; + if (canCalculate) + { + // + // Calculate Values ... + CalculateValues( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + else + { + FillBuffersZero(bar_index); + } +} + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int bar_index) +{ + // + sarColorBuffer[bar_index] = hideColorIDX; + trendColorBuffer[bar_index] = hideColorIDX; +} + +/** + * Calculate Values ... + * + * @param bar_index: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void CalculateValues( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = bar_index + 1; + bool isFirstBar = + startCalculationForLastBars > 0 + ? bar_index == startCalculationForLastBars + : bar_index == firstBarIndex; + + // + // Bar Info ... + double iLow = high[bar_index]; + double iHigh = high[bar_index]; + double iClose = close[bar_index]; + double iOpen = open[bar_index]; + double iVolume = (double)iVolume(_Symbol, _Period, bar_index); + + // + bool isBullish = iClose > iOpen; + bool isBearish = iClose < iOpen; + + // + double points = GetPoints(_Symbol); + + // + // Calculate Sar Color Buffer ... + double iSar = sarBuffer[bar_index]; + + // + double iSarState = neuturalState; + double iSarColor = neuturalColorIDX; + if (iLow > iSar) + { + // + iSarState = bullishState; + iSarColor = !showSar + ? hideColorIDX + : bullishColorIDX; + } + else if (iHigh < iSar) + { + // + iSarState = bearishState; + iSarColor = !showSar + ? hideColorIDX + : bearishColorIDX; + } + sarStateBuffer[bar_index] = iSarState; + sarColorBuffer[bar_index] = iSarColor; + + // + // Calculate Trend Color Buffer ... + double iTrend = trendBuffer[bar_index]; + + // + double iTrendState = neuturalState; + double iTrendColor = neuturalColorIDX; + if (iClose > iTrend) + { + // + iTrendState = bullishState; + iTrendColor = !showTrend + ? hideColorIDX + : bullishColorIDX; + } + else if (iClose < iTrend) + { + // + iTrendState = bearishState; + iTrendColor = !showTrend + ? hideColorIDX + : bearishColorIDX; + } + trendStateBuffer[bar_index] = iTrendState; + trendColorBuffer[bar_index] = iTrendColor; + + // + // DELTA ... + double lastDelta = + isFirstBar + ? emptyValue + : deltaBuffer[lastBarIndex]; + double iAppliedVolume = + isBullish + ? iVolume + : -1 * iVolume; + double iDelta = + lastDelta + iAppliedVolume; + deltaBuffer[bar_index] = iDelta; + + // + // Calculate Delta Signal ... + int deltaSignalsCount = iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + deltaSignalLength, + deltaBuffer, + deltaSignalBuffer, + deltaSignalMethod // + ); + + // + // VOLUME ... + + // + double iBullishVolume = emptyValue; + double iBearishVolume = emptyValue; + if (isBullish) + { + iBullishVolume = iVolume; + } + else if (isBearish) + { + iBearishVolume = iVolume; + } + else + { + // + double iHalfVolume = iVolume / 2; + + // + iBullishVolume = iHalfVolume; + iBearishVolume = iHalfVolume; + } + bullishVolumeBuffer[bar_index] = iBullishVolume; + bearishVolumeBuffer[bar_index] = iBearishVolume; + + // + // Calculate Volume Signals ... + + // + int bullishVolumeSignalsCount = iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + volumeSignalLength, + bullishVolumeBuffer, + bullishVolumeSignalBuffer, + volumeSignalMethod // + ); + + // + int bearishVolumeSignalsCount = iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + volumeSignalLength, + bearishVolumeBuffer, + bearishVolumeSignalBuffer, + volumeSignalMethod // + ); + + // + // SIGNAL Bar ... + + // + // Open ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + barsSignalLength, + open, + openSignalBuffer, + barsSignalMethod // + ); + + // + // Close ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + barsSignalLength, + close, + closeSignalBuffer, + barsSignalMethod // + ); + + // + double min = MathMin(closeSignalBuffer[bar_index], openSignalBuffer[bar_index]); + double max = MathMin(closeSignalBuffer[bar_index], openSignalBuffer[bar_index]); + + // + lowSignalBuffer[bar_index] = min; + highSignalBuffer[bar_index] = max; + + // + // Calculate HK Signal Color ... + double iSignalColorValue = + openSignalBuffer[bar_index] < closeSignalBuffer[bar_index] + ? bullishColorIDX + : bearishColorIDX; + signalBarColorBuffer[bar_index] = + showSignalBars + ? iSignalColorValue + : hideColorIDX; + + // + // XHK ... + + // + double lastHKOpen = + isFirstBar + ? emptyValue + : openHKBuffer[lastBarIndex]; + double lastHKClose = + isFirstBar + ? emptyValue + : closeHKBuffer[lastBarIndex]; + + // + double iHKOpenValue = (lastHKOpen + lastHKClose) / 2; + double iHKCloseValue = (open[bar_index] + high[bar_index] + close[bar_index] + low[bar_index]) / 4; + double iHKHighValue = MathMax(high[bar_index], MathMax(iHKOpenValue, iHKCloseValue)); + double iHKLowValue = MathMin(low[bar_index], MathMin(iHKOpenValue, iHKCloseValue)); + + // + double iHKColorValue = + iHKOpenValue < iHKCloseValue + ? bullishColorIDX + : bearishColorIDX; + + // + // Raw HK Buffers ... + openHKBuffer[bar_index] = iHKOpenValue; + highHKBuffer[bar_index] = iHKHighValue; + lowHKBuffer[bar_index] = iHKLowValue; + closeHKBuffer[bar_index] = iHKCloseValue; + barHKColorBuffer[bar_index] = showHKBars ? iHKColorValue + : hideColorIDX; + + // + // XHK Signal ... + + // + // Open ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + hkSignalBarLength, + openHKBuffer, + openHKSignalBuffer, + hkSignalBarMethod // + ); + + // + // Close ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + hkSignalBarLength, + closeHKBuffer, + closeHKSignalBuffer, + hkSignalBarMethod // + ); + + // + min = MathMin(closeHKSignalBuffer[bar_index], openHKSignalBuffer[bar_index]); + max = MathMin(closeHKSignalBuffer[bar_index], openHKSignalBuffer[bar_index]); + + // + lowHKSignalBuffer[bar_index] = min; + highHKSignalBuffer[bar_index] = max; + + // + // Calculate HK Signal Color ... + double iHKSignalColorValue = + openHKSignalBuffer[bar_index] < closeHKSignalBuffer[bar_index] + ? bullishColorIDX + : bearishColorIDX; + barHKSignalColorBuffer[bar_index] = + showHKSignalBars + ? iHKSignalColorValue + : hideColorIDX; + + // + // Calculate ATR Band ... + double iATR = atrBuffer[bar_index]; + double iAppliedATR = atrMultiplier * iATR; + double iATRUpperPrice = GetAppliedPrice( + atrUpperPriceType, + open, + high, + low, + close, + bar_index // + ); + double iATRLowerPrice = GetAppliedPrice( + atrLowerPriceType, + open, + high, + low, + close, + bar_index // + ); + double iATRUpper = iATRUpperPrice + iAppliedATR; + double iATRLower = iATRLowerPrice - iAppliedATR; + atrUpperRawBuffer[bar_index] = iATRUpper; + atrLowerRawBuffer[bar_index] = iATRLower; + + // + bool canSignalATR = IsValid(atrSignalMethod); + if (canSignalATR) + { + // + // Upper ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + atrLength, + atrUpperRawBuffer, + atrUpperBuffer, + atrSignalMethod // + ); + + // + // Lower ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + atrLength, + atrLowerRawBuffer, + atrLowerBuffer, + atrSignalMethod // + ); + } + else + { + // + atrUpperBuffer[bar_index] = iATRUpper; + atrLowerBuffer[bar_index] = iATRLower; + } + + // + // Trigger Block ... + + // + DetectTriggerBlock( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); +} + +/** + * Detect Trigger Block ... + * + * @param bar_index: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void DetectTriggerBlock( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = bar_index + 1; + int maxBarIndex = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : ratesTotal; + bool isFirstBar = + bar_index == maxBarIndex; + + // + // Prevent Calculation ... + if (maxBarIndex - bar_index < maxLength) + { + return; + } + + // + int zIDX = 0; + bool has = false; + bool isDone = false; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + + // + // Retrieve Required Bars ... + + // + XOHCL iBar; + XOHCL zBar; // Current Start Checking Bar (Usually Used for Triggering) ... + has = zBar.Init( + _Symbol, + _Period, + bar_index // + ); + + // + // Detect Trend Bar ... + XOHCL zTrendBar; + int zTrendIDX = iBarShift( + _Symbol, + mTrendPeriod, + zBar.time // + ); + has = + has && + zTrendBar.Init( + _Symbol, + mTrendPeriod, + zTrendIDX + 1 // + ); + + // + // Define Zone Structure ... + XTriggerBlock tb; + + // + bool validateObBarType = true; + bool validateFVGBarType = true; + + // + // Detect Based Order Block ... + has = + has && + barAnalyser.IsOB( + zBar, + tb.ob, + validateFVGBarType, // Force FVG Bar Type ... + validateObBarType // Force Block Two Bar Checking ... + ); + + // + // Detect Based Fair Value Gap ... + has = + has && + barAnalyser.IsFVG( + zBar, + tb.fvg, + validateFVGBarType // Force FVG Bar Type ... + ); + + // + // Clone Trigger Block ... + if (has) + { + tb.trigger = tb.ob; + } + + // + bool isBullish = + has && + tb.IsBullish(); + + // + bool isBearish = + has && + tb.IsBearish(); + + // + int toIDX = tb.ToIndex(); + int fromIDX = tb.FromIndex(); + + // + // Verifications and Filters ... + + // + int loopback = 144; + + // + // Forces ... + + // + // Force Has Proper Swing ... + if (has && + forceHasSwing) + { + // + toIDX = tb.ToIndex(); + fromIDX = tb.FromIndex(); + for (int i = toIDX; i < fromIDX; i++) + { + // + // Initialize iBar ... + isDone = iBar.Init( + zBar.symbol, + zBar.period, + i // + ); + isDone = + isDone && + barAnalyser.IsSimpleSwing( + iBar, + iDir // + ) && + iDir == tb.GetDirection(); + if (isDone) + { + // + bool canSet = + !tb.swingBar.IsValid() + ? true + : (isBullish + ? tb.swingBar.low > iBar.low + : tb.swingBar.high < iBar.high); + if (canSet) + { + tb.swingBar = iBar; + } + } + + // + iBar.Clean(); + } + + // + has = tb.swingBar.IsValid(); + } + + // + // Force Has Liquidity ... + if (has && + (forceHasFLiquidity || + forceHasRLiquidity)) + { + // + toIDX = tb.ToIndex(); + fromIDX = tb.FromIndex(); + for (int i = toIDX; i < fromIDX + loopback; i++) + { + // + // Initialize iBar ... + isDone = iBar.Init( + zBar.symbol, + zBar.period, + i // + ); + + // + bool isRejected = + isDone && + barAnalyser.IsRejected( + iBar, + iDir, + false, // Force Bar Type ... + true // Force Fibo Pressure ... + ); + + // + // Following Liquidity ... + bool isFLiq = + isDone && + isRejected && + iDir == tb.GetDirection() && + (isBullish + ? iBar.low < tb.trigger.lower + : iBar.high > tb.trigger.upper); + if (isFLiq && + forceHasFLiquidity && + !tb.fLiquidity.IsValid()) + { + // + FillLiquidity( + iBar, + iDir, + tb.fLiquidity, + tb.trigger.to // + ); + } + + // + // Reversal Liquidity ... + bool isRLiq = + isDone && + isRejected && + Opposit(iDir) == tb.GetDirection() && + (isBullish + ? iBar.low > tb.trigger.upper + : iBar.high < tb.trigger.lower); + if (isRLiq && + forceHasRLiquidity && + !tb.rLiquidity.IsValid()) + { + // + FillLiquidity( + iBar, + iDir, + tb.rLiquidity, + tb.trigger.to // + ); + } + + // + // Checking Conditions ... + isDone = + (!forceHasFLiquidity + ? true + : tb.fLiquidity.IsValid()) && + (!forceHasRLiquidity + ? true + : tb.rLiquidity.IsValid()); + if (isDone) + { + // + iBar.Clean(); + break; + } + + // + iBar.Clean(); + } + + // + // Checking Conditions ... + has = + (!forceHasFLiquidity + ? true + : tb.fLiquidity.IsValid()) && + (!forceHasRLiquidity + ? true + : tb.rLiquidity.IsValid()); + } + + // + // Validations ... + + // + // Validating Gap Sequence means + // Gap Bars must Follow each Other ... + if (has && + validateGapSequence) + { + // + XOHCL iPBar; + toIDX = tb.fvg.ToIndex(); + fromIDX = tb.fvg.FromIndex(); + + // + for (int i = toIDX; i < fromIDX - 1; i++) + { + // + // Initialize iBar ... + has = iBar.Init( + zBar.symbol, + zBar.period, + i // + ); + has = + has && + iBar.GetPreviousBar(iPBar); + has = + has && + (isBullish + ? iBar.low > iPBar.low + : iBar.high < iPBar.high); + if (!has) + { + break; + } + } + + // + iBar.Clean(); + iPBar.Clean(); + } + + // + // Validate Block Edge Breakout ... + if (has && + validateBlockEdgeBreakout) + { + // + has = tb.fvg.ToBar(iBar); + has = + has && + (isBullish + ? (iBar.GetDown() < tb.ob.upper && + iBar.GetUp() > tb.ob.upper) + : (iBar.GetDown() < tb.ob.lower && + iBar.GetUp() > tb.ob.lower)); + + // + iBar.Clean(); + } + + // + // Filters ... + + // + // DELTA ... + if (has && + filterBasedOnDelta) + { + // + double iDelta = deltaBuffer[bar_index]; + double iPDelta = deltaBuffer[lastBarIndex]; + + // + bool isDeltaUp = iDelta > iPDelta; + bool isDeltaDown = iDelta < iPDelta; + + // + double iDeltaSignal = deltaSignalBuffer[bar_index]; + double iPDeltaSignal = deltaSignalBuffer[lastBarIndex]; + + // + bool isDeltaSignalUp = iDeltaSignal > iPDeltaSignal; + bool isDeltaSignalDown = iDeltaSignal < iPDeltaSignal; + + // + bool isDeltaSwitchedToBullish = + isDeltaUp && + isDeltaSignalUp && + iDelta > iDeltaSignal && + iPDelta < iPDeltaSignal; + + // + bool isDeltaSwitchedToBearish = + isDeltaDown && + isDeltaSignalDown && + iDelta < iDeltaSignal && + iPDelta > iPDeltaSignal; + + // + has = + has && + (isBullish + ? isDeltaSwitchedToBullish + : isDeltaSwitchedToBearish); + } + + // + // VOLUME ... + if (has && + filterBasedOnVolume) + { + // + double iBullishVolumeSignal = bullishVolumeSignalBuffer[bar_index]; + double iPBullishVolumeSignal = bullishVolumeSignalBuffer[lastBarIndex]; + + // + bool isBullishVolumeSignalUp = iBullishVolumeSignal > iPBullishVolumeSignal; + bool isBullishVolumeSignalDown = iBullishVolumeSignal < iPBullishVolumeSignal; + + // + double iBearishVolumeSignal = bearishVolumeSignalBuffer[bar_index]; + double iPBearishVolumeSignal = bearishVolumeSignalBuffer[lastBarIndex]; + + // + bool isBearishVolumeSignalUp = iBearishVolumeSignal > iPBearishVolumeSignal; + bool isBearishVolumeSignalDown = iBearishVolumeSignal < iPBearishVolumeSignal; + + // + bool isVolumeSwitchdToBullish = + isBullishVolumeSignalUp && + !isBearishVolumeSignalUp && + iBullishVolumeSignal > iBearishVolumeSignal && + iPBullishVolumeSignal < iPBearishVolumeSignal; + + // + bool isVolumeSwitchdToBearish = + isBearishVolumeSignalUp && + !isBullishVolumeSignalUp && + iBearishVolumeSignal > iBullishVolumeSignal && + iPBearishVolumeSignal < iPBullishVolumeSignal; + + // + has = + has && + (isBullish + ? isVolumeSwitchdToBullish + : isVolumeSwitchdToBearish); + } + + // + // SIGNAL Bar ... + if (has && + filterBasedOnSignalBar) + { + // + double iSignalOpen = openSignalBuffer[bar_index]; + double iPSignalOpen = openSignalBuffer[lastBarIndex]; + + // + double iSignalClose = closeSignalBuffer[bar_index]; + double iPSignalClose = closeSignalBuffer[lastBarIndex]; + + // + bool isSignalBarBullish = iSignalOpen < iSignalClose; + bool isPSignalBarBullish = iPSignalOpen < iPSignalClose; + + // + bool isSignalBarBearish = iSignalOpen > iSignalClose; + bool isPSignalBarBearish = iPSignalOpen > iPSignalClose; + + // + bool isSignalBarSwitchedToBullish = + isSignalBarBullish && + !isPSignalBarBullish; + + // + bool isSignalBarSwitchedToBearish = + isSignalBarBearish && + !isPSignalBarBearish; + + // + has = + has && + (isBullish + ? isSignalBarSwitchedToBullish + : isSignalBarSwitchedToBearish); + } + + // + // HK SIGNAL Bar ... + if (has && + filterBasedOnHKSignalBar) + { + // + double iHKSignalOpen = openHKSignalBuffer[bar_index]; + double iPHKSignalOpen = openHKSignalBuffer[lastBarIndex]; + + // + double iHKSignalClose = closeHKSignalBuffer[bar_index]; + double iPHKSignalClose = closeHKSignalBuffer[lastBarIndex]; + + // + bool isHKSignalBarBullish = iHKSignalOpen < iHKSignalClose; + bool isPHKSignalBarBullish = iPHKSignalOpen < iPHKSignalClose; + + // + bool isHKSignalBarBearish = iHKSignalOpen > iHKSignalClose; + bool isPHKSignalBarBearish = iPHKSignalOpen > iPHKSignalClose; + + // + bool isHKSignalBarSwitchedToBullish = + isHKSignalBarBullish && + !isPHKSignalBarBullish; + + // + bool isHKSignalBarSwitchedToBearish = + isHKSignalBarBearish && + !isPHKSignalBarBearish; + + // + has = + has && + (isBullish + ? isHKSignalBarSwitchedToBullish + : isHKSignalBarSwitchedToBearish); + } + + // + // ATR ... + if (has && + filterBasedOnATR) + { + // + fromIDX = tb.FromIndex(); + double iATRUpper = atrUpperBuffer[fromIDX]; + double iATRLower = atrLowerBuffer[fromIDX]; + + // + has = + has && + (isBullish + ? tb.trigger.lower < iATRLower + : tb.trigger.upper > iATRUpper); + } + + // + // SAR ... + if (has && + filterBasedOnSar) + { + // + double iSarState = sarStateBuffer[bar_index]; + double iPSarState = sarStateBuffer[lastBarIndex]; + double iP2SarState = sarStateBuffer[lastBarIndex + 1]; + + // + bool isSarBullish = iSarState > 0; + bool isPSarBullish = iPSarState > 0; + bool isP2SarBullish = iP2SarState > 0; + + // + bool isSarBearish = iSarState < 0; + bool isPSarBearish = iPSarState < 0; + bool isP2SarBearish = iP2SarState < 0; + + // + bool isSarSwitchedToBullish = + isSarBullish && + !isPSarBullish; + + // + bool isSarSwitchedToBearish = + isSarBearish && + !isPSarBearish; + + // + bool isSarPSwitchedToBullish = + isPSarBullish && + !isP2SarBullish; + + // + bool isSarPSwitchedToBearish = + isPSarBearish && + !isP2SarBearish; + + // + has = + has && + (isBullish + ? (isSarSwitchedToBullish || + isSarPSwitchedToBullish) + : (isSarSwitchedToBearish || + isSarPSwitchedToBearish)); + } + + // + // TREND ... + if (has && + filterBasedOnTrend) + { + // + double iTrendState = trendStateBuffer[bar_index]; + double iPTrendState = trendStateBuffer[lastBarIndex]; + + // + bool isTrendBullish = iTrendState > 0; + bool isPTrendBullish = iPTrendState > 0; + + // + bool isTrendBearish = iTrendState < 0; + bool isPTrendBearish = iPTrendState < 0; + + // + double trends[]; + int toIDX = tb.ToIndex(); + int fromIDX = tb.FromIndex(); + double iTrend = trendBuffer[toIDX]; + for (int i = toIDX; i <= fromIDX; i++) + { + // + Add( + trendBuffer[i], + trends // + ); + } + double trendsMin = GetMin(trends); + double trendsMax = GetMax(trends); + double trendsAVG = GetAverage(trends); + + // + bool isTrendUp = + iTrend > trendsMin && + iTrend >= trendsAVG; + + // + bool isTrendDown = + iTrend < trendsMax && + iTrend <= trendsAVG; + + // + bool isTrendSwitchedToBullish = + isTrendUp && + isTrendBullish && + !isPTrendBullish; + + // + bool isTrendSwitchedToBearish = + isTrendDown && + isTrendBearish && + !isPTrendBearish; + + // + has = + has && + (isBullish + ? isTrendSwitchedToBullish + : isTrendSwitchedToBearish); + } + + // + // TREND Bars ... + if (has && + zTrendBar.IsValid() && + filterBasedOnTrendBars) + { + // + // Calculate Trend Bar's Midd Range ... + double mid = zTrendBar.low + ((zTrendBar.high - zTrendBar.low) / 2); + + // + // Check zBar Close based on MID ... + has = + has && + (isBullish + ? zBar.close < mid + : zBar.close > mid); + + // + // Check Trigger Block ... + has = + has && + (isBullish + ? tb.trigger.lower < zTrendBar.GetDown() + : tb.trigger.upper > zTrendBar.GetUp()); + } + + // + // RSI ... + if (has && + filterBasedOnRSI) + { + // + double rsiTrend = (rsiOBLevel + rsiOSLevel) / 2; + + // + double iRSI = rsiBuffer[bar_index]; + double iPRSI = rsiBuffer[lastBarIndex]; + double iP2RSI = rsiBuffer[lastBarIndex + 1]; + + // + bool isRSICrossedOverOS = + iRSI > rsiOSLevel && + iPRSI <= rsiOSLevel; + + // + bool isRSICrossedUnderOB = + iRSI < rsiOBLevel && + iPRSI >= rsiOBLevel; + + // + bool isPRSICrossedOverOS = + iPRSI > rsiOSLevel && + iP2RSI <= rsiOSLevel; + + // + bool isPRSICrossedUnderOB = + iPRSI < rsiOBLevel && + iP2RSI >= rsiOBLevel; + + // + has = + has && + (isBullish + ? (isRSICrossedOverOS || + isPRSICrossedOverOS) + : (isRSICrossedUnderOB || + isPRSICrossedUnderOB)); + } + + // + // ADX ... + if (has && + filterBasedOnADX) + { + // + // ADX ... + double iADX = adxBuffer[bar_index]; + double iPADX = adxBuffer[lastBarIndex]; + double iP2ADX = adxBuffer[lastBarIndex + 1]; + + // + // ADX +DI ... + double iADXP = adxpBuffer[bar_index]; + double iPADXP = adxpBuffer[lastBarIndex]; + double iP2ADXP = adxpBuffer[lastBarIndex + 1]; + + // + // ADX -DI ... + double iADXN = adxnBuffer[bar_index]; + double iPADXN = adxnBuffer[lastBarIndex]; + double iP2ADXN = adxnBuffer[lastBarIndex + 1]; + + // + // Preparing Conditions ... + + // + bool isADXBullish = iADX > adxThreshold; + bool isADXBearish = iADX < adxThreshold; + + // + bool isPADXBullish = iPADX > adxThreshold; + bool isPADXBearish = iPADX < adxThreshold; + + // + bool isP2ADXBullish = iP2ADX > adxThreshold; + bool isP2ADXBearish = iP2ADX < adxThreshold; + + // + bool isADXSwitchedToBullish = + isADXBullish && + !isPADXBullish; + + // + bool isADXSwitchedToBearish = + isADXBearish && + !isPADXBearish; + + // + bool isPADXSwitchedToBullish = + isPADXBullish && + !isP2ADXBullish; + + // + bool isPADXSwitchedToBearish = + isPADXBearish && + !isP2ADXBearish; + + // + has = + has && + (isBullish + ? (isADXSwitchedToBullish || + isPADXSwitchedToBullish) + : (isADXSwitchedToBearish || + isPADXSwitchedToBearish)); + } + + // + // SIGNAL ... + if (has && + (drawSignals && + maxSignalR2R > 0)) + { + // + double targets[]; + for (int i = 1; i <= maxSignalR2R; i++) + { + // + Add( + (double)i, + targets // + ); + } + + // + double iATR = atrBuffer[bar_index]; + double slAdditional = slAtrMultiplier * iATR; + + // + has = ToSignal( + tb.trigger, + tb.signal, + targets, + slAdditional // + ); + } + + // + // Handle Draw ... + + // + // Draw Trend Bar ... + if (has && + showTrendBars) + { + // + XCOHCLObject *iObj; + isDone = drawer.CreateBar( + zTrendBar, + iObj, + zBar.time // + ); + if (isDone) + { + // + // Style Object ... + + // + // Store Object ... + mObjects.Add(iObj); + } + } + + // + // Draw Trigger Block ... + if (has && + drawZones) + { + DrawTB(tb); + } + + // + // Handle Alerst ... + bool canAlert = + mEnableAlerts && + prevCalculated > 0; + bool canLogOnly = + mEnableAlerts && + prevCalculated == 0; + if (has && + (canAlert || + canLogOnly)) + { + // + string message = + tb.trigger.symbol + "," + + ToString(tb.trigger.period) + "> " + + ToString(tb.trigger.dir) + + " Zone Detected at: " + ToString(tb.trigger.to); + + // + if (canLogOnly) + { + alert.LogAlert(message); + } + else if (canAlert) + { + alert.SendAlert(message); + } + } + + // + // Cleanup Resources ... + + // + tb.Clean(); + zBar.Clean(); + iBar.Clean(); + zTrendBar.Clean(); +} + +// +void ReadBarStyle() +{ + // + long chartId = ChartID(); + + // + _upColor = GetChartUpColor(chartId); + _downColor = GetChartDownColor(chartId); + _lineColor = GetChartLineColor(chartId); + _bullishColor = GetChartBullishColor(chartId); + _bearishColor = GetChartBearishColor(chartId); +} + +// +void ShowBars() +{ + // + long chartId = ChartID(); + + // + SetChartUpColor(_upColor, chartId); + SetChartDownColor(_downColor, chartId); + SetChartLineColor(_lineColor, chartId); + SetChartBullishColor(_bullishColor, chartId); + SetChartBearishColor(_bearishColor, chartId); +} + +// +void HideBars() +{ + // + long chartId = ChartID(); + + // + SetChartUpColor(CLR_NONE, chartId); + SetChartDownColor(CLR_NONE, chartId); + SetChartLineColor(CLR_NONE, chartId); + SetChartBullishColor(CLR_NONE, chartId); + SetChartBearishColor(CLR_NONE, chartId); +} + +// +// Draw Specific Trigger Block ... +bool DrawTB( + XTriggerBlock &trigger, + datetime to = NULL // +) +{ + // + bool result = false; + + // + // Validate Args ... + result = trigger.IsValid(); + if (!result) + { + return result; + } + + // + // Update To ... + bool canUpdateTo = IsValid(to); + if (canUpdateTo) + { + // + trigger.trigger.to = to; + trigger.rLiquidity.to = to; + trigger.fLiquidity.to = to; + } + + // + bool isBullish = trigger.IsBullish(); + + // + // Draw OB ... + if (trigger.ob.IsValid()) + { + // + XCBoxObject *iOBObj; + result = drawer.DrawBox( + trigger.ob, + iOBObj // + ); + if (result) + { + // + // Style Object ... + + // + color iClr = + isBullish + ? obBullishColor + : obBearishColor; + + // + iOBObj.BoxColor(iClr); + iOBObj.BoxWidth(obWidth); + iOBObj.BoxStyle(obStyle); + + // + // Store Object ... + mObjects.Add(iOBObj); + } + ZeroMemory(iOBObj); + + // + if (!result) + { + return result; + } + } + + // + // Draw FVG ... + if (trigger.fvg.IsValid()) + { + // + XCBoxObject *iFVGObj; + result = drawer.DrawBox( + trigger.fvg, + iFVGObj // + ); + if (result) + { + // + // Style Object ... + + // + color iClr = + isBullish + ? fvgBullishColor + : fvgBearishColor; + + // + iFVGObj.BoxColor(iClr); + iFVGObj.BoxWidth(fvgWidth); + iFVGObj.BoxStyle(fvgStyle); + + // + // Store Object ... + mObjects.Add(iFVGObj); + } + ZeroMemory(iFVGObj); + + // + if (!result) + { + return result; + } + } + + // + // Draw Trigger ... + if (trigger.trigger.IsValid()) + { + // + XCBoxObject *iTriggerObj; + result = drawer.DrawBox( + trigger.trigger, + iTriggerObj // + ); + if (result) + { + // + // Style Object ... + + // + color iClr = + isBullish + ? tbBullishColor + : tbBearishColor; + + // + iTriggerObj.BoxColor(iClr); + iTriggerObj.BoxWidth(tbWidth); + iTriggerObj.BoxStyle(tbStyle); + + // + // Store Object ... + mObjects.Add(iTriggerObj); + } + ZeroMemory(iTriggerObj); + + // + if (!result) + { + return result; + } + } + + // + // Draw Liquidities ... + + // + // Reversla Liquidity ... + if (trigger.rLiquidity.IsValid()) + { + // + XCBoxObject *iLiqObj; + result = drawer.DrawBox( + trigger.rLiquidity, + iLiqObj // + ); + if (result) + { + mObjects.Add(iLiqObj); + } + ZeroMemory(iLiqObj); + + // + if (!result) + { + return result; + } + } + + // + // Following Liquidity ... + if (trigger.fLiquidity.IsValid()) + { + // + XCBoxObject *iLiqObj; + result = drawer.DrawBox( + trigger.fLiquidity, + iLiqObj // + ); + if (result) + { + mObjects.Add(iLiqObj); + } + ZeroMemory(iLiqObj); + + // + if (!result) + { + return result; + } + } + + // + // Draw Swing Bar ... + if (trigger.swingBar.IsValid()) + { + // + color swingColor = + trigger.fvg.IsBullish() + ? clrAqua + : clrMagenta; + ENUM_X_PRICE swingPType = + trigger.fvg.IsBullish() + ? X_PRICE_LOW + : X_PRICE_HIGH; + + // + XCBarArrowObject *swingObj; + result = drawer.CreateBarArrow( + trigger.swingBar, + swingObj, + swingPType, + 159, + swingColor // + ); + if (result) + { + mObjects.Add(swingObj); + } + ZeroMemory(swingObj); + + // + if (!result) + { + return result; + } + } + + // + // Draw RR of Signal ... + if (trigger.signal.IsValid() && + rrZoneLength > 0) + { + // + XCRRObject *iRRObj; + iRRObj = new XCRRObject(); + result = iRRObj.Create( + drawer.ChartIdentification(), + drawer.SubWindowIdentification(), + trigger.signal, + rrZoneLength // + ); + if (result) + { + // + int iWidth = 2; + ENUM_LINE_STYLE iStyle = STYLE_SOLID; + + // + iRRObj.TPWidth(iWidth); + iRRObj.SLWidth(iWidth); + iRRObj.EntryWidth(iWidth); + iRRObj.TargetWidth(iWidth); + + // + iRRObj.TPStyle(iStyle); + iRRObj.SLStyle(iStyle); + iRRObj.EntryStyle(iStyle); + iRRObj.TargetStyle(iStyle); + + // + iRRObj.TPColor(clrLime); + iRRObj.SLColor(clrRed); + iRRObj.EntryColor(clrYellow); + iRRObj.TargetColor(clrLightBlue); + + // + mObjects.Add(iRRObj); + } + ZeroMemory(iRRObj); + + // + if (result) + { + return result; + } + } + + // + return result; +} + +// \ No newline at end of file diff --git a/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xvolume.mq5 b/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xvolume.mq5 new file mode 100644 index 0000000..657cb9a --- /dev/null +++ b/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xvolume.mq5 @@ -0,0 +1,567 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Ocillator +// ------------------------------------------------- +// Name: X121 XVolume +// Description: Detect Bullish/Bearish Volumes ... +// +// +// 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 XVolume Ocillator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121_XVOLUME" + +// +// Imports ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +// Makret ... +input group "Market"; +input int maLength = 14; // Moving Averge Length +input ENUM_X_MA_METHOD maMethod = X_MA_MODE_EMA; // Moving Averge Method + +// +// Presentation ... +input group "Presentation"; +input int startCalculationForLastBars = 1000; // Calculate Last n Bars +input bool showBullishVolume = true; // Show Bullish Volume +input bool showBullishVolumeMa = true; // Show Bullish Volume Moving Average +input bool showBearishVolume = true; // Show Bearish Volume +input bool showBearishVolumeMa = true; // Show Bearish Volume Moving Average + +// +// Buffers Props ... + +// +#property indicator_separate_window + +// +#property indicator_buffers 6 +#property indicator_plots 4 + +// +// Buffers ... + +// +#define bullishVolumeBufferIndex 0 +double bullishVolumeBuffer[]; + +#property indicator_label1 "Bullish Volume" +#property indicator_type1 DRAW_HISTOGRAM +#property indicator_color1 clrLime +#property indicator_style1 STYLE_DOT +#property indicator_width1 1 + +// +#define bullishVolumeMaBufferIndex 1 +double bullishVolumeMaBuffer[]; + +#property indicator_label2 "Bullish Volume MA" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrLime +#property indicator_style2 STYLE_SOLID +#property indicator_width2 1 + +// +#define bearishVolumeBufferIndex 2 +double bearishVolumeBuffer[]; + +#property indicator_label3 "Bearish Volume" +#property indicator_type3 DRAW_HISTOGRAM +#property indicator_color3 clrRed +#property indicator_style3 STYLE_DOT +#property indicator_width3 1 + +// +#define bearishVolumeMaBufferIndex 3 +double bearishVolumeMaBuffer[]; + +#property indicator_label4 "Bearish Volume MA" +#property indicator_type4 DRAW_LINE +#property indicator_color4 clrRed +#property indicator_style4 STYLE_SOLID +#property indicator_width4 1 + +// +// Data Buffers ... + +#define mLastBufferIndex 3 + +// +#define rawBullishVolumeBufferIndex mLastBufferIndex + 1 +double rawBullishVolumeBuffer[]; + +// +#define rawBearishVolumeBufferIndex mLastBufferIndex + 2 +double rawBearishVolumeBuffer[]; + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +int firstBarIndex; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + + // + // 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(); + IndicatorSetInteger(INDICATOR_DIGITS, 2); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +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 +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // 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); + + // + 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, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + result = maLength > 0 && + IsValid(maMethod); + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(0, maLength); + + // + return result; +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + + // + // Bullish ... + + // + // Volume ... + ENUM_DRAW_TYPE bullishVolumeDrawType = showBullishVolume ? DRAW_HISTOGRAM : DRAW_NONE; + + // + ArraySetAsSeries(bullishVolumeBuffer, true); + SetIndexBuffer(bullishVolumeBufferIndex, bullishVolumeBuffer, INDICATOR_DATA); + PlotIndexSetDouble(bullishVolumeBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(bullishVolumeBufferIndex, PLOT_SHOW_DATA, showBullishVolume); + PlotIndexSetInteger(bullishVolumeBufferIndex, PLOT_DRAW_TYPE, bullishVolumeDrawType); + + // + // Average ... + ENUM_DRAW_TYPE bullishVolumeMaDrawType = showBullishVolumeMa ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(bullishVolumeMaBuffer, true); + SetIndexBuffer(bullishVolumeMaBufferIndex, bullishVolumeMaBuffer, INDICATOR_DATA); + PlotIndexSetDouble(bullishVolumeMaBufferIndex, PLOT_EMPTY_VALUE, 0.0); + PlotIndexSetInteger(bullishVolumeMaBufferIndex, PLOT_SHOW_DATA, showBullishVolumeMa); + PlotIndexSetInteger(bullishVolumeMaBufferIndex, PLOT_DRAW_TYPE, bullishVolumeMaDrawType); + + // + // Bearish ... + + // + // Volume ... + ENUM_DRAW_TYPE bearishVolumeDrawType = showBearishVolume ? DRAW_HISTOGRAM : DRAW_NONE; + + // + ArraySetAsSeries(bearishVolumeBuffer, true); + SetIndexBuffer(bearishVolumeBufferIndex, bearishVolumeBuffer, INDICATOR_DATA); + PlotIndexSetDouble(bearishVolumeBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(bearishVolumeBufferIndex, PLOT_SHOW_DATA, showBearishVolume); + PlotIndexSetInteger(bearishVolumeBufferIndex, PLOT_DRAW_TYPE, bearishVolumeDrawType); + + // + // Average ... + ENUM_DRAW_TYPE bearishVolumeMaDrawType = showBearishVolumeMa ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(bearishVolumeMaBuffer, true); + SetIndexBuffer(bearishVolumeMaBufferIndex, bearishVolumeMaBuffer, INDICATOR_DATA); + PlotIndexSetDouble(bearishVolumeMaBufferIndex, PLOT_EMPTY_VALUE, 0.0); + PlotIndexSetInteger(bearishVolumeMaBufferIndex, PLOT_SHOW_DATA, showBearishVolumeMa); + PlotIndexSetInteger(bearishVolumeMaBufferIndex, PLOT_DRAW_TYPE, bearishVolumeMaDrawType); + + // + // Data Buffers ... + + // + ArraySetAsSeries(rawBullishVolumeBuffer, true); + SetIndexBuffer(rawBullishVolumeBufferIndex, rawBullishVolumeBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(rawBearishVolumeBuffer, true); + SetIndexBuffer(rawBearishVolumeBufferIndex, rawBearishVolumeBuffer, INDICATOR_CALCULATIONS); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +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[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + if (barsLimit == 0) + { + // + barsLimit = ratesTotal; + firstBarIndex = barsLimit - 1; + } + else + { + // + firstBarIndex = startCalculationForLastBars; + } + + // + // bool canCalculate = true; + bool canCalculate = + bar_index <= barsLimit; + if (canCalculate) + { + // + CalculateValues( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + else + { + FillBuffersZero(bar_index); + } +} + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + bullishVolumeBuffer[barIndex] = EMPTY_VALUE; + bullishVolumeMaBuffer[barIndex] = EMPTY_VALUE; + rawBullishVolumeBuffer[barIndex] = 0; + + // + bearishVolumeBuffer[barIndex] = EMPTY_VALUE; + bearishVolumeMaBuffer[barIndex] = EMPTY_VALUE; + rawBearishVolumeBuffer[barIndex] = 0; +} + +/** + * Calculate Vales ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateValues( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // Check Prev Bar ... + // + int lastBarIndex = bar_index + 1; + bool isFirstBar = + startCalculationForLastBars > 0 + ? bar_index == startCalculationForLastBars + : bar_index == firstBarIndex; + + // + XOHCL bar; + bool has = bar.Init( + _Symbol, + _Period, + bar_index // + ); + if (!has) + { + return; + } + + // + double iBullishVolume = 0; + double iBearishVolume = 0; + + // + if (bar.IsBullish()) + { + // + iBullishVolume = (double)bar.volume; + iBearishVolume = 0; + } + else if (bar.IsBearish()) + { + // + iBearishVolume = (double)bar.volume; + iBullishVolume = 0; + } + else + { + // + double volume = ((double)bar.volume) / 2.0; + iBullishVolume = volume; + iBearishVolume = volume; + } + + // + bullishVolumeBuffer[bar_index] = + iBullishVolume == 0 + ? EMPTY_VALUE + : iBullishVolume; + rawBullishVolumeBuffer[bar_index] = iBullishVolume; + + // + bearishVolumeBuffer[bar_index] = + iBearishVolume == 0 + ? EMPTY_VALUE + : iBearishVolume; + rawBearishVolumeBuffer[bar_index] = iBearishVolume; + + // + // Calculate Moving Averages ... + + // + int bullishMAsCount = iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + maLength, + rawBullishVolumeBuffer, + bullishVolumeMaBuffer, + maMethod // + ); + + // + int bearishMAsCount = iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + maLength, + rawBearishVolumeBuffer, + bearishVolumeMaBuffer, + maMethod // + ); + + // + bar.Clean(); +} + +// diff --git a/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xvwap.mq5 b/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xvwap.mq5 new file mode 100644 index 0000000..ca2a2c4 --- /dev/null +++ b/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xvwap.mq5 @@ -0,0 +1,712 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XVWAP +// Description: XVWAP ... +// +// +// 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 XVWAP Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121 XVWAP" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +// Market ... +input group "Market"; +input int vwapFastLength = 20; // Fast Length +input int vwapMidLength = 40; // Mid Length +input int vwapSlowLength = 60; // Slow Length +input ENUM_APPLIED_PRICE vwapAppliedTo = PRICE_CLOSE; // Applied To + +// +// Presentation ... +input group "Presentation"; + +// +input int startCalculationForLastBars = 1000; // Calculate Last n Bars + +// +input bool showVWapFast = true; // Show VWap Fast +input bool showVWapMedium = true; // Show VWap Medium +input bool showVWapSlow = true; // Show VWap Slow + +// +// Buffers ... + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#property indicator_chart_window + +// +#property indicator_buffers 11 +#property indicator_plots 3 + +// +// Plot Buffers ... + +// +// FAST ... +#define vwapFastBufferIndex 0 +double vwapFastBuffer[]; + +#define vwapFastColorBufferIndex 1 +double vwapFastColorBuffer[]; + +// +#define vwapFastPlotBufferIndex 0 +#property indicator_label1 "X121 VWF" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 CLR_NONE, clrAqua, clrMagenta, clrGray +#property indicator_style1 STYLE_SOLID +#property indicator_width1 2 + +// +// MID ... +#define vwapMidBufferIndex 2 +double vwapMidBuffer[]; + +#define vwapMidColorBufferIndex 3 +double vwapMidColorBuffer[]; + +// +#define vwapMidPlotBufferIndex 1 +#property indicator_label2 "X121 VWM" +#property indicator_type2 DRAW_COLOR_LINE +#property indicator_color2 CLR_NONE, clrGreen, clrRed, clrGray +#property indicator_style2 STYLE_SOLID +#property indicator_width2 2 + +// +// SLOW ... +#define vwapSlowBufferIndex 4 +double vwapSlowBuffer[]; + +#define vwapSlowColorBufferIndex 5 +double vwapSlowColorBuffer[]; + +// +#define vwapSlowPlotBufferIndex 2 +#property indicator_label3 "X121 VWS" +#property indicator_type3 DRAW_COLOR_LINE +#property indicator_color3 CLR_NONE, clrSteelBlue, clrDarkRed, clrGray +#property indicator_style3 STYLE_SOLID +#property indicator_width3 2 + +// +// Data Buffers ... + +// +int mLastBufferIndex = 5; + +// +// Volume ... +#define vwapVolumeBufferIndex mLastBufferIndex + 1 +double vwapVolumeBuffer[]; + +// +// Price ... +#define vwapPriceBufferIndex mLastBufferIndex + 2 +double vwapPriceBuffer[]; + +// +// Fast State ... +#define vwapFastStateBufferIndex mLastBufferIndex + 3 +double vwapFastStateBuffer[]; + +// +// Mid State ... +#define vwapMidStateBufferIndex mLastBufferIndex + 4 +double vwapMidStateBuffer[]; + +// +// Slow State ... +#define vwapSlowStateBufferIndex mLastBufferIndex + 5 +double vwapSlowStateBuffer[]; + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + + // + // 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; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +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 +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // 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); + + // + // Validate Calculated Bars ... + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + result = + // + vwapFastLength > 2 && + vwapMidLength > vwapFastLength && + vwapSlowLength > vwapMidLength + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + // XVWAP ... + result = MathMax(result, vwapFastLength); + result = MathMax(result, vwapMidLength); + result = MathMax(result, vwapSlowLength); + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + + // + // Fast ... + ArraySetAsSeries(vwapFastBuffer, true); + ArraySetAsSeries(vwapFastColorBuffer, true); + SetIndexBuffer(vwapFastBufferIndex, vwapFastBuffer, INDICATOR_DATA); + SetIndexBuffer(vwapFastColorBufferIndex, vwapFastColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Mid ... + ArraySetAsSeries(vwapMidBuffer, true); + ArraySetAsSeries(vwapMidColorBuffer, true); + SetIndexBuffer(vwapMidBufferIndex, vwapMidBuffer, INDICATOR_DATA); + SetIndexBuffer(vwapMidColorBufferIndex, vwapMidColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Slow ... + ArraySetAsSeries(vwapSlowBuffer, true); + ArraySetAsSeries(vwapSlowColorBuffer, true); + SetIndexBuffer(vwapSlowBufferIndex, vwapSlowBuffer, INDICATOR_DATA); + SetIndexBuffer(vwapSlowColorBufferIndex, vwapSlowColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Data Buffers ... + + // + // Volumes ... + ArraySetAsSeries(vwapVolumeBuffer, true); + SetIndexBuffer(vwapVolumeBufferIndex, vwapVolumeBuffer, INDICATOR_CALCULATIONS); + + // + // Price ... + ArraySetAsSeries(vwapPriceBuffer, true); + SetIndexBuffer(vwapPriceBufferIndex, vwapPriceBuffer, INDICATOR_CALCULATIONS); + + // + // Fast State ... + ArraySetAsSeries(vwapFastStateBuffer, true); + SetIndexBuffer(vwapFastStateBufferIndex, vwapFastStateBuffer, INDICATOR_CALCULATIONS); + + // + // Mid State ... + ArraySetAsSeries(vwapMidStateBuffer, true); + SetIndexBuffer(vwapMidStateBufferIndex, vwapMidStateBuffer, INDICATOR_CALCULATIONS); + + // + // Slow State ... + ArraySetAsSeries(vwapSlowStateBuffer, true); + SetIndexBuffer(vwapSlowStateBufferIndex, vwapSlowStateBuffer, INDICATOR_CALCULATIONS); +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +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[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + // + // bool canCalculate = true; + bool canCalculate = + barsLimit == 0 || + bar_index <= barsLimit; + if (canCalculate) + { + // + // Calculate Required VWAP Data Buffers ... + if (ratesTotal - bar_index <= maxLength) + { + // + CalculateVWAPDataBuffers( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // Prevent Moving Forward ... + } + else + { + // + CalculateVWAPDataBuffers( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + CalculateVWAPS( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + } + else + { + FillBuffersZero(bar_index); + } +} + +// +// Custom ... + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + vwapFastBuffer[barIndex] = EMPTY_VALUE; + vwapMidBuffer[barIndex] = EMPTY_VALUE; + vwapSlowBuffer[barIndex] = EMPTY_VALUE; + vwapVolumeBuffer[barIndex] = EMPTY_VALUE; + vwapPriceBuffer[barIndex] = EMPTY_VALUE; + + // + vwapFastColorBuffer[barIndex] = hideColorIDX; + vwapMidColorBuffer[barIndex] = hideColorIDX; + vwapSlowColorBuffer[barIndex] = hideColorIDX; + vwapFastStateBuffer[barIndex] = hideColorIDX; + vwapMidStateBuffer[barIndex] = hideColorIDX; + vwapSlowStateBuffer[barIndex] = hideColorIDX; +} + +/** + * Calculate VWAP Value for Specified Bar ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + * @param _length: Integer, Specified VWAP Length ... + * @param _show: Boolean, Specified Show Buffer or not ... + * @param _buffer: Double Array Reference, Points to Buffer ... + * @param _colorBuffer: Double Array Reference, Points to Color Buffer ... + * @param _stateBuffer: Double Array Reference, Points to State Buffer ... + */ +void CalculateVWAP( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[], + // + int _length, // Calculation Length + bool _show, + double &_buffer[], + double &_colorBuffer[], + double &_stateBuffer[] // +) +{ + // + double vSum = 0; + double pSum = 0; + double mSum = 0; + for (int x = 0; x < _length; x++) + { + // + pSum += vwapPriceBuffer[x + bar_index]; + vSum += vwapVolumeBuffer[x + bar_index]; + mSum += vwapPriceBuffer[x + bar_index] * vwapVolumeBuffer[x + bar_index]; + } + + // + double iValue = mSum / vSum; + iValue = NormalizeDouble(iValue, _Digits); + + // + _buffer[bar_index] = iValue; + + // + bool isBullish = low[bar_index] > iValue; + bool isBearish = high[bar_index] < iValue; + + // + double iColor = + isBullish + ? bullishColorIDX + : isBearish + ? bearishColorIDX + : neuturalColorIDX; + + // + _colorBuffer[bar_index] = hideColorIDX; + _stateBuffer[bar_index] = iColor; + if (_show) + { + _colorBuffer[bar_index] = iColor; + } +} + +/** + * Calculate VWAP Required Data Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateVWAPDataBuffers( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + ENUM_X_PRICE mPType = ToXPrice(vwapAppliedTo); + double price = GetAppliedPrice( + mPType, + open, + high, + low, + close, + bar_index // + ); + vwapPriceBuffer[bar_index] = price; + vwapVolumeBuffer[bar_index] = (double)tickVolume[bar_index]; +} + +/** + * Calculate Different VWaps ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateVWAPS( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // Fast ... + CalculateVWAP( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume, + // + vwapFastLength, + showVWapFast, + vwapFastBuffer, + vwapFastColorBuffer, + vwapFastStateBuffer // + ); + + // + // Mid ... + CalculateVWAP( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume, + // + vwapMidLength, + showVWapMedium, + vwapMidBuffer, + vwapMidColorBuffer, + vwapMidStateBuffer // + ); + + // + // Fast ... + CalculateVWAP( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume, + // + vwapSlowLength, + showVWapSlow, + vwapSlowBuffer, + vwapSlowColorBuffer, + vwapSlowStateBuffer // + ); +} + +// \ No newline at end of file diff --git a/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xwz.mq5 b/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xwz.mq5 new file mode 100644 index 0000000..626ee8e --- /dev/null +++ b/BKPS/14040316/Documents/Indicators/x-saherelm.x121.xwz.mq5 @@ -0,0 +1,2780 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XWZ +// Description: XWZ ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Glzoneal Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121 XWZ Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121_XWZ" + +// +// Includes Common Library ... +#include "../Classes/x-saherelm.x-alert.class.mq5" +#include "../Classes/x-saherelm.x-bar.analyser.class.mq5" +#include "../Classes/x-saherelm.x-poi.class.mq5" +#include "../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" +#include "../Libraries/x-saherelm.x-poi.extensions.lib.mq5" + +// +// Inputs ... + +// +// Market ... +input group "Market"; + +// +input group "Calculation"; +input ENUM_APPLIED_PRICE appliedTo = PRICE_CLOSE; // Detect Price Type + +// +input group "MA Detection"; +input int maLength = 20; // MA Length +input ENUM_MA_METHOD maMethod = MODE_EMA; // MA Method + +// +input group "ATR StopLoss"; +input int atrLength = 14; // ATR Length +input double atrMultiplier = 2; // ATR Multiplier + +// +input group "ADX Detection"; +input int adxLength = 14; // ADX Length +input double adxThreshold = 25; // ADX Threshold for Strong Trends + +// +input group "POI Detection"; +input ENUM_TIMEFRAMES orderBlockTF = PERIOD_H1; // Order Block Detection Time Frame +input ENUM_TIMEFRAMES fairValueGapTF = PERIOD_M15; // Fair Value Gap Detection Time Frame +input ENUM_TIMEFRAMES supDemTF = PERIOD_H4; // Supply and Demand Detection Time Frame + +// +input group "Alert"; +input bool mXWZEnableAlerts = true; // Enable Alerts +input bool mXWZPushAlerts = false; // Push Alerts +input bool mXWZMailAlerts = false; // Mail Alerts +input bool mXWZTerminalAlerts = false; // Terminal Alerts + +// +// Presentation ... +input group "Presentation"; + +// +input group "Buffer Presentation"; +input bool showMA = true; // Show Moving Average +input bool showPin = true; // Show Pin Bars +input bool showSwing = true; // Show Swing Bars +input bool showTrend = true; // Show Trend +input bool showEngulf = true; // Show Engulf Bars +input bool showLongSL = true; // Show Long SL +input bool showShortSL = true; // Show Short SL +input bool showMomentum = true; // Show Momentum Bars +input bool showRejection = true; // Show Rejection Bars + +// +input group "POI Presentation"; +input bool showPOIs = true; // Show POI(s) +input bool showOrderBlocks = true; // Show Order Blocks +input bool showFairValueGaps = true; // Show Fair Value Gaps +input bool showSupplyZones = true; // Show Supply Zones +input bool showDemandZones = true; // Show Demand Zones + +// +input group "Presentation Config"; +input int startCalculationForLastBars = 1000; // Calculate Last n Bars +input int upTrendArrowCode = 236; // Up Trend Arrow Code +input int downTrendArrowCode = 238; // Down Trend Arrow Code +input int swingLowArrowCode = 108; // Swing Low Arrow Code +input int swingHighArrowCode = 108; // Swing High Arrow Code +input int bullishPinArrowCode = 246; // Bullish Pin Arrow Code +input int bearishPinArrowCode = 248; // Bearish Pin Arrow Code +input int bullishEngulfArrowCode = 200; // Bullish Engulf Arrow Code +input int bearishEngulfArrowCode = 202; // Bearish Engulf Arrow Code +input int bullishMomentumArrowCode = 233; // Bullish Momentum Arrow Code +input int bearishMomentumArrowCode = 234; // Bearish Momentum Arrow Code +input int bullishRejectionArrowCode = 241; // Bullish Rejection Arrow Code +input int bearishRejectionArrowCode = 242; // Bearish Rejection Arrow Code + +// +#property indicator_chart_window + +// +#property indicator_buffers 17 +#property indicator_plots 15 + +// +// Plot Buffers ... + +// +#define maBufferIndex 0 +double maBuffer[]; + +// +#property indicator_label1 "X121-XWZ MA" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrLightSkyBlue +#property indicator_style1 STYLE_SOLID +#property indicator_width1 2 + +// +#define longSLBufferIndex 1 +double longSLBuffer[]; + +// +#property indicator_label2 "X121-XWZ Long SL" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrOrange +#property indicator_style2 STYLE_SOLID +#property indicator_width2 1 + +// +#define shortSLBufferIndex 2 +double shortSLBuffer[]; + +// +#property indicator_label3 "X121-XWZ Short SL" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrOrange +#property indicator_style3 STYLE_SOLID +#property indicator_width3 1 + +// +#define upTrendBufferIndex 3 +double upTrendBuffer[]; + +// +#property indicator_label4 "X121-XWZ Trend Up" +#property indicator_type4 DRAW_ARROW +#property indicator_color4 clrAqua +#property indicator_width4 3 + +// +#define downTrendBufferIndex 4 +double downTrendBuffer[]; + +// +#property indicator_label5 "X121-XWZ Trend Down" +#property indicator_type5 DRAW_ARROW +#property indicator_color5 clrMagenta +#property indicator_width5 3 + +// +#define bullishMomentumBufferIndex 5 +double bullishMomentumBuffer[]; + +// +#property indicator_label6 "X121-XWZ Bull Momentum" +#property indicator_type6 DRAW_ARROW +#property indicator_color6 clrAqua +#property indicator_width6 3 + +// +#define bearishMomentumBufferIndex 6 +double bearishMomentumBuffer[]; + +// +#property indicator_label7 "X121-XWZ Bear Momentum" +#property indicator_type7 DRAW_ARROW +#property indicator_color7 clrMagenta +#property indicator_width7 3 + +// +#define bullishRejectionBufferIndex 7 +double bullishRejectionBuffer[]; + +// +#property indicator_label8 "X121-XWZ Bull Rejection" +#property indicator_type8 DRAW_ARROW +#property indicator_color8 clrAqua +#property indicator_width8 3 + +// +#define bearishRejectionBufferIndex 8 +double bearishRejectionBuffer[]; + +// +#property indicator_label9 "X121-XWZ Bear Rejection" +#property indicator_type9 DRAW_ARROW +#property indicator_color9 clrMagenta +#property indicator_width9 3 + +// +#define bullishPinBufferIndex 9 +double bullishPinBuffer[]; + +// +#property indicator_label10 "X121-XWZ Bull Pin" +#property indicator_type10 DRAW_ARROW +#property indicator_color10 clrAqua +#property indicator_width10 3 + +// +#define bearishPinBufferIndex 10 +double bearishPinBuffer[]; + +// +#property indicator_label11 "X121-XWZ Bear Pin" +#property indicator_type11 DRAW_ARROW +#property indicator_color11 clrMagenta +#property indicator_width11 3 + +// +#define bullishEngulfBufferIndex 11 +double bullishEngulfBuffer[]; + +// +#property indicator_label12 "X121-XWZ Bull Engulf" +#property indicator_type12 DRAW_ARROW +#property indicator_color12 clrAqua +#property indicator_width12 3 + +// +#define bearishEngulfBufferIndex 12 +double bearishEngulfBuffer[]; + +// +#property indicator_label13 "X121-XWZ Bear Engulf" +#property indicator_type13 DRAW_ARROW +#property indicator_color13 clrMagenta +#property indicator_width13 3 + +// +#define swingLowBufferIndex 13 +double swingLowBuffer[]; + +// +#property indicator_label14 "X121-XWZ Swing Low" +#property indicator_type14 DRAW_ARROW +#property indicator_color14 clrAqua +#property indicator_width14 3 + +// +#define swingHighBufferIndex 14 +double swingHighBuffer[]; + +// +#property indicator_label15 "X121-XWZ Swing High" +#property indicator_type15 DRAW_ARROW +#property indicator_color15 clrMagenta +#property indicator_width15 3 + +// +// Data Buffers ... + +// +int mLastBufferIndex = 14; + +// +#define atrBufferIndex mLastBufferIndex + 1 +double atrBuffer[]; + +// +#define adxBufferIndex mLastBufferIndex + 2 +double adxBuffer[]; + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +// MA Handler ... +int maHandler = INVALID_HANDLE; + +// +// ATR Handler ... +int atrHandler = INVALID_HANDLE; + +// +// ADX Handler ... +int adxHandler = INVALID_HANDLE; + +// +XCAlert *mXWZAlert; +XBarTracker mXWZBarTracker; +CArrayObj mXWZDrawnObjects; +XCPOIDrawer *mXWZPOIDrawer; +XCBarAnalyser *mXWZBarAnalyser; + +// +// POI(s) ... + +// +bool mXWZDetectOrderBlocks = true; +bool mXWZDetectFairValueGaps = true; +bool mXWZDetectSupplyZones = true; +bool mXWZDetectDemandZones = true; + +// +bool mXWZIgnoreUnActivateds = true; + +// +bool mXWZForceStarteds = true; +bool mXWZForceUnBreaked = true; +bool mXWZForceActivation = true; + +// +int mXWZSuResRange = 21; +int mXWZOBFVGSameBars = 3; + +// +// Un Activated POI(s) ... +XCFVG *mXWZUnActivatedFVGs[]; +XCOrderBlock *mXWZUnActivatedOBs[]; +XCSupplyZone *mXWZUnActivatedSupplyZones[]; +XCDemandZone *mXWZUnActivatedDemandZones[]; + +// +// Activated POI(s) ... +XCFVG *mXWZActivatedFVGs[]; +XCOrderBlock *mXWZActivatedOBs[]; +XCSupplyZone *mXWZActivatedSupplyZones[]; +XCDemandZone *mXWZActivatedDemandZones[]; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + mXWZDrawnObjects.Clear(); + + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + + // + // MA ... + maHandler = iMA( + _Symbol, + _Period, + maLength, + 0, + maMethod, + appliedTo // + ); + bool isInited = maHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // ATR ... + atrHandler = iATR( + _Symbol, + _Period, + atrLength // + ); + isInited = maHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // ADX ... + adxHandler = iADX( + _Symbol, + _Period, + adxLength // + ); + isInited = maHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // 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(); + IndicatorSetInteger(INDICATOR_DIGITS, 2); + + // + // Initialize Bar Tracker ... + mXWZBarTracker.Init( + _Symbol, + _Period // + ); + + // + mXWZPOIDrawer = new XCPOIDrawer(); + ConfigurePOIDrawer(); + + // + mXWZAlert = new XCAlert(); + ConfigureAlert(); + + // + mXWZBarAnalyser = new XCBarAnalyser(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +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(maHandler); + IndicatorRelease(atrHandler); + IndicatorRelease(adxHandler); + + // + mXWZDrawnObjects.Clear(); + + // + ZeroMemory(mXWZAlert); + ZeroMemory(mXWZPOIDrawer); + ZeroMemory(mXWZBarAnalyser); + + // + Clean(mXWZActivatedOBs); + Clean(mXWZActivatedFVGs); + Clean(mXWZActivatedSupplyZones); + Clean(mXWZActivatedDemandZones); + + // + Clean(mXWZUnActivatedOBs); + Clean(mXWZUnActivatedFVGs); + Clean(mXWZUnActivatedSupplyZones); + Clean(mXWZUnActivatedDemandZones); +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // 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); + + // + // Validate Calculated Bars ... + + // + // MA ... + int maCalculatedBars = BarsCalculated(maHandler); + + // + // ATR ... + int atrCalculatedBars = BarsCalculated(atrHandler); + + // + // ADX ... + int adxCalculatedBars = BarsCalculated(adxHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // MA ... + maCalculatedBars >= maxLength && + // + // ATR ... + atrCalculatedBars >= maxLength && + // + // ADX ... + adxCalculatedBars >= maxLength + // + ; + if (!isPassedRequiredCalculatedBars) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + + // + // MA ... + int copiedMas = CopyBuffer(maHandler, 0, 0, limit, maBuffer); + + // + // ATR ... + int copiedAtr = CopyBuffer(atrHandler, MAIN_LINE, 0, limit, atrBuffer); + + // + // ADX ... + int copiedAdxs = CopyBuffer(adxHandler, MAIN_LINE, 0, limit, adxBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // MA ... + copiedMas > 0 && + // + // ATR ... + copiedAtr > 0 && + // + // ADX ... + copiedAdxs > 0 + // + ; + if (!isPassedRequiredCopiedItems) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + // + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + result = + // + // MA ... + maLength > 0 && + // + // ATR ... + atrLength > 0 && + atrMultiplier > 0 && + // + // ADX ... + adxLength > 0 && + adxThreshold > 0 + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(maLength, atrLength); + result = MathMax(result, adxLength); + + // + return result; +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + + // + // MA Buffer ... + + // + ENUM_DRAW_TYPE maDrawType = showMA ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(maBuffer, true); + SetIndexBuffer(maBufferIndex, maBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(maBufferIndex, PLOT_SHOW_DATA, showMA); + PlotIndexSetInteger(maBufferIndex, PLOT_DRAW_TYPE, maDrawType); + + // + PlotIndexSetDouble(maBufferIndex, PLOT_EMPTY_VALUE, 0); + + // + // LONG SL Buffer ... + + // + ENUM_DRAW_TYPE longSLDrawType = showLongSL ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(longSLBuffer, true); + SetIndexBuffer(longSLBufferIndex, longSLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(longSLBufferIndex, PLOT_SHOW_DATA, showLongSL); + PlotIndexSetInteger(longSLBufferIndex, PLOT_DRAW_TYPE, longSLDrawType); + + // + PlotIndexSetDouble(longSLBufferIndex, PLOT_EMPTY_VALUE, 0); + + // + // SHORT SL Buffer ... + + // + ENUM_DRAW_TYPE shortSLDrawType = showShortSL ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(shortSLBuffer, true); + SetIndexBuffer(shortSLBufferIndex, shortSLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(shortSLBufferIndex, PLOT_SHOW_DATA, showShortSL); + PlotIndexSetInteger(shortSLBufferIndex, PLOT_DRAW_TYPE, shortSLDrawType); + + // + PlotIndexSetDouble(shortSLBufferIndex, PLOT_EMPTY_VALUE, 0); + + // + // UP Trend ... + + // + ENUM_DRAW_TYPE upTrendDrawType = showTrend ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(upTrendBuffer, true); + SetIndexBuffer(upTrendBufferIndex, upTrendBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(upTrendBufferIndex, PLOT_SHOW_DATA, showTrend); + PlotIndexSetInteger(upTrendBufferIndex, PLOT_DRAW_TYPE, upTrendDrawType); + + // + PlotIndexSetDouble(upTrendBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(upTrendBufferIndex, PLOT_ARROW, upTrendArrowCode); + + // + // DOWN Trend ... + + // + ENUM_DRAW_TYPE downTrendDrawType = showTrend ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(downTrendBuffer, true); + SetIndexBuffer(downTrendBufferIndex, downTrendBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(downTrendBufferIndex, PLOT_SHOW_DATA, showTrend); + PlotIndexSetInteger(downTrendBufferIndex, PLOT_DRAW_TYPE, downTrendDrawType); + + // + PlotIndexSetDouble(downTrendBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(downTrendBufferIndex, PLOT_ARROW, downTrendArrowCode); + + // + // Bullish Momentum ... + + // + ENUM_DRAW_TYPE bullishMomentumDrawType = showMomentum ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(bullishMomentumBuffer, true); + SetIndexBuffer(bullishMomentumBufferIndex, bullishMomentumBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(bullishMomentumBufferIndex, PLOT_SHOW_DATA, showMomentum); + PlotIndexSetInteger(bullishMomentumBufferIndex, PLOT_DRAW_TYPE, bullishMomentumDrawType); + + // + PlotIndexSetDouble(bullishMomentumBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(bullishMomentumBufferIndex, PLOT_ARROW, bullishMomentumArrowCode); + + // + // Bearish Momentum ... + + // + ENUM_DRAW_TYPE bearishMomentumDrawType = showMomentum ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(bearishMomentumBuffer, true); + SetIndexBuffer(bearishMomentumBufferIndex, bearishMomentumBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(bearishMomentumBufferIndex, PLOT_SHOW_DATA, showMomentum); + PlotIndexSetInteger(bearishMomentumBufferIndex, PLOT_DRAW_TYPE, bearishMomentumDrawType); + + // + PlotIndexSetDouble(bearishMomentumBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(bearishMomentumBufferIndex, PLOT_ARROW, bearishMomentumArrowCode); + + // + // Bullish Rejection ... + + // + ENUM_DRAW_TYPE bullishRejectionDrawType = showRejection ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(bullishRejectionBuffer, true); + SetIndexBuffer(bullishRejectionBufferIndex, bullishRejectionBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(bullishRejectionBufferIndex, PLOT_SHOW_DATA, showRejection); + PlotIndexSetInteger(bullishRejectionBufferIndex, PLOT_DRAW_TYPE, bullishRejectionDrawType); + + // + PlotIndexSetDouble(bullishRejectionBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(bullishRejectionBufferIndex, PLOT_ARROW, bullishRejectionArrowCode); + + // + // Bearish Rejection ... + + // + ENUM_DRAW_TYPE bearishRejectionDrawType = showRejection ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(bearishRejectionBuffer, true); + SetIndexBuffer(bearishRejectionBufferIndex, bearishRejectionBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(bearishRejectionBufferIndex, PLOT_SHOW_DATA, showRejection); + PlotIndexSetInteger(bearishRejectionBufferIndex, PLOT_DRAW_TYPE, bearishRejectionDrawType); + + // + PlotIndexSetDouble(bearishRejectionBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(bearishRejectionBufferIndex, PLOT_ARROW, bearishRejectionArrowCode); + + // + // Bullish Pin ... + + // + ENUM_DRAW_TYPE bullishPinDrawType = showPin ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(bullishPinBuffer, true); + SetIndexBuffer(bullishPinBufferIndex, bullishPinBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(bullishPinBufferIndex, PLOT_SHOW_DATA, showPin); + PlotIndexSetInteger(bullishPinBufferIndex, PLOT_DRAW_TYPE, bullishPinDrawType); + + // + PlotIndexSetDouble(bullishPinBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(bullishPinBufferIndex, PLOT_ARROW, bullishPinArrowCode); + + // + // Bearish Pin ... + + // + ENUM_DRAW_TYPE bearishPinDrawType = showPin ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(bearishPinBuffer, true); + SetIndexBuffer(bearishPinBufferIndex, bearishPinBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(bearishPinBufferIndex, PLOT_SHOW_DATA, showPin); + PlotIndexSetInteger(bearishPinBufferIndex, PLOT_DRAW_TYPE, bearishPinDrawType); + + // + PlotIndexSetDouble(bearishPinBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(bearishPinBufferIndex, PLOT_ARROW, bearishPinArrowCode); + + // + // Bullish Engulf ... + + // + ENUM_DRAW_TYPE bullishEngulfDrawType = showEngulf ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(bullishEngulfBuffer, true); + SetIndexBuffer(bullishEngulfBufferIndex, bullishEngulfBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(bullishEngulfBufferIndex, PLOT_SHOW_DATA, showEngulf); + PlotIndexSetInteger(bullishEngulfBufferIndex, PLOT_DRAW_TYPE, bullishEngulfDrawType); + + // + PlotIndexSetDouble(bullishEngulfBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(bullishEngulfBufferIndex, PLOT_ARROW, bullishEngulfArrowCode); + + // + // Bearish Engulf ... + + // + ENUM_DRAW_TYPE bearishEngulfDrawType = showEngulf ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(bearishEngulfBuffer, true); + SetIndexBuffer(bearishEngulfBufferIndex, bearishEngulfBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(bearishEngulfBufferIndex, PLOT_SHOW_DATA, showEngulf); + PlotIndexSetInteger(bearishEngulfBufferIndex, PLOT_DRAW_TYPE, bearishEngulfDrawType); + + // + PlotIndexSetDouble(bearishEngulfBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(bearishEngulfBufferIndex, PLOT_ARROW, bearishEngulfArrowCode); + + // + // Swing Low ... + + // + ENUM_DRAW_TYPE swingLowDrawType = showSwing ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(swingLowBuffer, true); + SetIndexBuffer(swingLowBufferIndex, swingLowBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(swingLowBufferIndex, PLOT_SHOW_DATA, showSwing); + PlotIndexSetInteger(swingLowBufferIndex, PLOT_DRAW_TYPE, swingLowDrawType); + + // + PlotIndexSetDouble(swingLowBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(swingLowBufferIndex, PLOT_ARROW, swingLowArrowCode); + + // + // Swing High ... + + // + ENUM_DRAW_TYPE swingHighDrawType = showSwing ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(swingHighBuffer, true); + SetIndexBuffer(swingHighBufferIndex, swingHighBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(swingHighBufferIndex, PLOT_SHOW_DATA, showSwing); + PlotIndexSetInteger(swingHighBufferIndex, PLOT_DRAW_TYPE, swingHighDrawType); + + // + PlotIndexSetDouble(swingHighBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(swingHighBufferIndex, PLOT_ARROW, swingHighArrowCode); + + // + // DATA Buffers ... + + // + ArraySetAsSeries(atrBuffer, true); + SetIndexBuffer(atrBufferIndex, atrBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(adxBuffer, true); + SetIndexBuffer(adxBufferIndex, adxBuffer, INDICATOR_CALCULATIONS); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +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[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + // + // bool canCalculate = true; + bool canCalculate = + barsLimit == 0 || + bar_index <= barsLimit; + if (canCalculate) + { + // + CalculatedPOIs( + // + bar_index, + prevCalculated, + ratesTotal, + // + open, + high, + close, + low, + tickVolume // + ); + + // + CalculateValues( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + else + { + FillBuffersZero(bar_index); + } +} + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + maBuffer[barIndex] = 0; + atrBuffer[barIndex] = 0; + adxBuffer[barIndex] = 0; + longSLBuffer[barIndex] = 0; + shortSLBuffer[barIndex] = 0; + upTrendBuffer[barIndex] = 0; + swingLowBuffer[barIndex] = 0; + swingHighBuffer[barIndex] = 0; + downTrendBuffer[barIndex] = 0; + bullishPinBuffer[barIndex] = 0; + bearishPinBuffer[barIndex] = 0; + bullishEngulfBuffer[barIndex] = 0; + bearishEngulfBuffer[barIndex] = 0; + bullishMomentumBuffer[barIndex] = 0; + bearishMomentumBuffer[barIndex] = 0; + bullishRejectionBuffer[barIndex] = 0; + bearishRejectionBuffer[barIndex] = 0; +} + +/** + * Calculate Vales ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateValues( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // Prepare Requirements ... + + // + XOHCL iBar; + bool isInited = iBar.Init( + _Symbol, + _Period, + bar_index // + ); + if (!isInited) + { + // + iBar.Clean(); + return; + } + + // + XOHCL pBar; + isInited = iBar.GetPreviousBar(pBar); + if (!isInited) + { + // + iBar.Clean(); + pBar.Clean(); + return; + } + int pIndex = pBar.Index(); + + // + // Calculate Applied Price ... + double iPrice = GetAppliedPrice( + appliedTo, + open, + high, + low, + close, + bar_index // + ); + + // + double iMa = maBuffer[bar_index]; + double iMaPrev = maBuffer[pIndex]; + double iAtr = atrBuffer[bar_index]; + double iAdx = adxBuffer[bar_index]; + double iAppliedAtr = iAtr * atrMultiplier; + + // + double points = GetPoints(_Symbol); + double points10 = 10 * points; + + // + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + + // + // SL Buffers ... + + // + double iLongSL = iPrice - iAppliedAtr; + double iShortSL = iPrice + iAppliedAtr; + + // + longSLBuffer[bar_index] = iLongSL; + shortSLBuffer[bar_index] = iShortSL; + + // + // Trend Buffers ... + + // + bool isUpTrend = + // + iPrice > iMa && + iBar.low < iMa && + iAdx > adxThreshold + // + ; + + // + bool isDownTrend = + // + iPrice < iMa && + iBar.high > iMa && + iAdx > adxThreshold + // + ; + + // + double upTrendValue = 0; + double downTrendValue = 0; + if (isUpTrend) + { + upTrendValue = iBar.low; + } + if (isDownTrend) + { + downTrendValue = iBar.high; + } + + // + upTrendBuffer[bar_index] = upTrendValue; + downTrendBuffer[bar_index] = downTrendValue; + + // + // Momentum Buffers ... + + // + bool isMomentum = mXWZBarAnalyser + .IsMomentumBar( + iBar, + iDir, + 1, // Extends ... + 70 // Body Percent ... + ); + bool isBullishMomentum = + isMomentum && + IsBullish(iDir); + bool isBearishMomentum = + isMomentum && + IsBearish(iDir); + if (isMomentum) + { + // + double iBullMomentumValue = 0; + double iBearMomentumValue = 0; + + // + if (isBullishMomentum) + { + // + double selectedValue = iBar.low; + + // + iBullMomentumValue = selectedValue; + } + + // + if (isBearishMomentum) + { + // + double selectedValue = iBar.high; + + // + iBearMomentumValue = selectedValue; + } + + // + bullishMomentumBuffer[bar_index] = iBullMomentumValue; + bearishMomentumBuffer[bar_index] = iBearMomentumValue; + } + + // + // Rejection Buffers ... + + // + bool isRejection = mXWZBarAnalyser + .IsRejectionBar( + iBar, + iDir, + 1, // Extends ... + 70 // Body Percent ... + ); + bool isBullishRejection = + isRejection && + IsBullish(iDir); + bool isBearishRejection = + isRejection && + IsBearish(iDir); + if (isRejection) + { + // + double iBullRejectionValue = 0; + double iBearRejectionValue = 0; + + // + if (isBullishRejection) + { + // + double selectedValue = iBar.low; + + // + iBullRejectionValue = selectedValue; + } + + // + if (isBearishRejection) + { + // + double selectedValue = iBar.high; + + // + iBearRejectionValue = selectedValue; + } + + // + bullishRejectionBuffer[bar_index] = iBullRejectionValue; + bearishRejectionBuffer[bar_index] = iBearRejectionValue; + } + + // + // Pin Buffers ... + + // + bool isPin = mXWZBarAnalyser + .IsPinBar( + iBar, + iDir, + 0, // Extends ... + 50, // Shadow Percent ... + 25 // Body Percent ... + ); + bool isBullishPin = + isPin && + IsBullish(iDir); + bool isBearishPin = + isPin && + IsBearish(iDir); + if (isPin) + { + // + double iBullPinValue = 0; + double iBearPinValue = 0; + + // + if (isBullishPin) + { + // + double selectedValue = iBar.low; + + // + iBullPinValue = selectedValue; + } + + // + if (isBearishPin) + { + // + double selectedValue = iBar.high; + + // + iBearPinValue = selectedValue; + } + + // + bullishPinBuffer[bar_index] = iBullPinValue; + bearishPinBuffer[bar_index] = iBearPinValue; + } + + // + // Engulf Buffers ... + + // + bool isEngulf = mXWZBarAnalyser + .IsEngulfBar( + iBar, + iDir, + 1, // Extends ... + 70 // Body Percent ... + ); + bool isBullishEngulf = + isEngulf && + IsBullish(iDir); + bool isBearishEngulf = + isEngulf && + IsBearish(iDir); + if (isEngulf) + { + // + double iBullEngulfValue = 0; + double iBearEngulfValue = 0; + + // + if (isBullishEngulf) + { + // + double selectedValue = iBar.low; + + // + iBullEngulfValue = selectedValue; + } + + // + if (isBearishEngulf) + { + // + double selectedValue = iBar.high; + + // + iBearEngulfValue = selectedValue; + } + + // + bullishEngulfBuffer[bar_index] = iBullEngulfValue; + bearishEngulfBuffer[bar_index] = iBearEngulfValue; + } + + // + // Swing Buffers ... + + // + bool isSwing = mXWZBarAnalyser + .IsSwing( + iBar, + iDir, + 2 // Range ... + ); + bool isSwingLow = + isSwing && + IsBullish(iDir); + bool isSwingHigh = + isSwing && + IsBearish(iDir); + if (isSwing) + { + // + double iSwingLowValue = 0; + double iSwingHighValue = 0; + + // + if (isSwingLow) + { + // + double selectedValue = iBar.low; + + // + iSwingLowValue = selectedValue; + } + + // + if (isSwingHigh) + { + // + double selectedValue = iBar.high; + + // + iSwingHighValue = selectedValue; + } + + // + swingLowBuffer[bar_index] = iSwingLowValue; + swingHighBuffer[bar_index] = iSwingHighValue; + } + + // + // Cleanup Resources ... + + // + iBar.Clean(); + pBar.Clean(); +} + +// +// POIS Functions ... + +// +void ConfigurePOIDrawer() +{ + // + if (mXWZPOIDrawer == NULL) + { + return; + } + + // + mXWZPOIDrawer.Prefix(ShortName); + mXWZPOIDrawer.ChartIdentification(ChartID()); + mXWZPOIDrawer.SubWindowIdentification(0); + + // + mXWZPOIDrawer.BullishFVGWidth(2); + mXWZPOIDrawer.BullishFVGStyle(STYLE_DOT); + mXWZPOIDrawer.BullishFVGColor(clrAqua); + + // + mXWZPOIDrawer.BearishFVGWidth(2); + mXWZPOIDrawer.BearishFVGStyle(STYLE_DOT); + mXWZPOIDrawer.BearishFVGColor(clrMagenta); + + // + mXWZPOIDrawer.SupportZoneWidth(1); + mXWZPOIDrawer.SupportZoneStyle(STYLE_DASHDOTDOT); + mXWZPOIDrawer.SupportZoneColor(clrLime); + + // + mXWZPOIDrawer.ResistanceZoneWidth(1); + mXWZPOIDrawer.ResistanceZoneStyle(STYLE_DASHDOTDOT); + mXWZPOIDrawer.ResistanceZoneColor(clrRed); + + // + mXWZPOIDrawer.BullishOrderBlockWidth(3); + mXWZPOIDrawer.BullishOrderBlockStyle(STYLE_DASH); + mXWZPOIDrawer.BullishOrderBlockColor(clrAqua); + + // + mXWZPOIDrawer.BearishOrderBlockWidth(3); + mXWZPOIDrawer.BearishOrderBlockStyle(STYLE_DASH); + mXWZPOIDrawer.BearishOrderBlockColor(clrMagenta); +} + +// +void ConfigureAlert() +{ + // + mXWZAlert.SetPrefix(ShortName); + + // + mXWZAlert.SetPushAlerts(mXWZPushAlerts); + mXWZAlert.SetMailAlerts(mXWZMailAlerts); + mXWZAlert.SetEnableAlerts(mXWZEnableAlerts); + mXWZAlert.SetTerminalAlerts(mXWZTerminalAlerts); +} + +// +void CalculatedPOIs( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + XOHCL iBar; + bool isInited = iBar.Init( + _Symbol, + _Period, + bar_index // + ); + if (!isInited) + { + // + iBar.Clean(); + return; + } + + // + XOHCL pBar; + isInited = iBar.GetPreviousBar(pBar); + if (!isInited) + { + // + iBar.Clean(); + pBar.Clean(); + return; + } + + // + // POI ... + DetectPOIs(iBar); + UpdatePOIs(iBar); + DrawPOIs(); + + // + iBar.Clean(); + pBar.Clean(); +} + +// +bool CanDetectPOIs() +{ + // + bool result = false; + + // + result = + // + mXWZDetectOrderBlocks || + mXWZDetectFairValueGaps || + mXWZDetectSupplyZones || + mXWZDetectDemandZones + // + ; + + // + return result; +} + +// +void DetectPOIs( + XOHCL &bar // +) +{ + // + if (!CanDetectPOIs()) + { + return; + } + + // + int barIndex = bar.Index(); + + // + if (barIndex <= 0) + { + return; + } + + // + DetectOrderBlock(bar); + DetectSupplyZone(bar); + DetectDemandZone(bar); + DetectFairValueGap(bar); + + // +} + +// +void UpdatePOIs( + XOHCL &bar // +) +{ + // + int count = 0; + bool has = false; + + // + // OrderBlock(s) ... + + // + has = HasChild(mXWZUnActivatedOBs); + if (has) + { + // + SpecifiedUpdateTo( + mXWZUnActivatedOBs, + bar.time // + ); + } + + // + // Fair Value Gaps ... + + // + has = HasChild(mXWZUnActivatedFVGs); + if (has) + { + // + SpecifiedUpdateTo( + mXWZUnActivatedFVGs, + bar.time // + ); + + // + count = ArraySize(mXWZUnActivatedFVGs); + } + + // + // Supply Zones ... + + // + has = HasChild(mXWZUnActivatedSupplyZones); + if (has) + { + // + SpecifiedUpdateTo( + mXWZUnActivatedSupplyZones, + bar.time // + ); + + // + count = ArraySize(mXWZUnActivatedSupplyZones); + } + + // + // Demand Zones ... + + // + has = HasChild(mXWZUnActivatedDemandZones); + if (has) + { + // + SpecifiedUpdateTo( + mXWZUnActivatedDemandZones, + bar.time // + ); + + // + count = ArraySize(mXWZUnActivatedDemandZones); + } +} + +// +void DrawPOIs() +{ + // + int count = 0; + bool has = false; + bool isCreated = false; + + // + if (!showPOIs) + { + return; + } + + // + // Order Blocks ... + if (showOrderBlocks) + { + // + bool showBullishOrderBlocks = true; + bool showBearishOrderBlocks = true; + + // + // UnActivated ... + count = ArraySize(mXWZUnActivatedOBs); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + bool isBullish = mXWZUnActivatedOBs[i].IsBullish(); + + // + if ((isBullish && + showBullishOrderBlocks) || + (!isBullish && + showBearishOrderBlocks)) + { + // + XCBaseObject *iObj; + isCreated = mXWZPOIDrawer + .CreateOrderBlock( + mXWZUnActivatedOBs[i], + iObj // + ); + if (isCreated) + { + mXWZDrawnObjects.Add(iObj); + } + } + } + } + } + + // + // Fair Value Gaps ... + if (showFairValueGaps) + { + // + bool showBullishFairValueGaps = true; + bool showBearishFairValueGaps = true; + + // + // UnActivated ... + count = ArraySize(mXWZUnActivatedFVGs); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + bool isBullish = mXWZUnActivatedFVGs[i].IsBullish(); + + // + if ((isBullish && + showBullishFairValueGaps) || + (!isBullish && + showBearishFairValueGaps)) + { + // + XCBaseObject *iObj; + isCreated = mXWZPOIDrawer + .CreateFairValueGap( + mXWZUnActivatedFVGs[i], + iObj // + ); + if (isCreated) + { + mXWZDrawnObjects.Add(iObj); + } + } + } + } + } + + // + // Supply Zones ... + if (showSupplyZones) + { + // + // UnActivated ... + count = ArraySize(mXWZUnActivatedSupplyZones); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + XCSupplyZoneObject *iObj; + isCreated = mXWZPOIDrawer + .CreateSupplyZone( + mXWZUnActivatedSupplyZones[i], + iObj // + ); + if (isCreated) + { + mXWZDrawnObjects.Add(iObj); + } + } + } + + // + // Activated ... + count = ArraySize(mXWZActivatedSupplyZones); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + } + } + } + + // + // Demand Zones ... + if (showDemandZones) + { + // + // UnActivated ... + count = ArraySize(mXWZUnActivatedDemandZones); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + XCDemandZoneObject *iObj; + isCreated = mXWZPOIDrawer + .CreateDemandZone( + mXWZUnActivatedDemandZones[i], + iObj // + ); + if (isCreated) + { + mXWZDrawnObjects.Add(iObj); + } + } + } + + // + // Activated ... + count = ArraySize(mXWZActivatedDemandZones); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + } + } + } + + // + ChartRedraw(); + + // +} + +// +// +// + +// +// Detect Order Block ... +void DetectOrderBlock(XOHCL &bar) +{ + // + int idx = -1; + int count = 0; + bool has = false; + + // + if (!mXWZDetectOrderBlocks) + { + return; + } + + // + int iBarIndex = bar.Index(orderBlockTF); + + // + XOHCL iBar; + bool isInited = iBar.Init( + bar.symbol, + orderBlockTF, + iBarIndex // + ); + if (!isInited) + { + return; + } + + // + XOHCL zoneBar; + ENUM_X_DIRECTION zoneDir; + has = mXWZBarAnalyser.HasOrderBlock( + iBar, + zoneBar, + zoneDir, + mXWZOBFVGSameBars // + ); + + // + if (!has) + { + // + zoneBar.Clean(); + return; + } + + // + XCOrderBlock *zone; + zone = new XCOrderBlock(); + has = zone.Init( + zoneBar, + zoneDir // + ); + + // + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + + // + return; + } + + // + // Check Start ... + if (mXWZForceStarteds) + { + // + XOHCL startedBar; + bool isBodyOut = false; + bool isStarted = zone.IsStarted( + zoneDir, + startedBar, + isBodyOut, + iBar.period // + ); + + // + has = isStarted; + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + startedBar.Clean(); + + // + return; + } + + // + startedBar.Clean(); + } + + // + // Check Activation ... + if (mXWZForceActivation) + { + // + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = zone.IsActivated( + zoneDir, + activationBar, + isActivationBarBodyIn, + false, + iBar.period // + ); + + // + has = !isActivated; + if (!has) + { + // + if (!mXWZIgnoreUnActivateds) + { + // + zone.To(activationBar.time); + + // + Add( + zone, + mXWZActivatedOBs // + ); + } + + // + zoneBar.Clean(); + ZeroMemory(zone); + activationBar.Clean(); + + // + return; + } + + // + activationBar.Clean(); + } + + // + // Check Breaktion ... + if (mXWZForceUnBreaked) + { + // + XOHCL breakedBar; + bool isBodyOut = false; + bool isBreaked = zone.IsBreaked( + zoneDir, + breakedBar, + isBodyOut, + false, + iBar.period // + ); + + // + has = !isBreaked; + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + breakedBar.Clean(); + + // + return; + } + + // + breakedBar.Clean(); + } + + // + // Check Indexes ... + + // + // UnActivateds ... + idx = FindIndex( + zone, + mXWZUnActivatedOBs // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + + // + return; + } + + // + // Activateds ... + idx = FindIndex( + zone, + mXWZActivatedOBs // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + + // + return; + } + + // + has = zone != NULL && + zone.IsValid(); + if (has) + { + // + zone.To(bar.time); + + // + Add( + zone, + mXWZUnActivatedOBs // + ); + } + + // + iBar.Clean(); + zoneBar.Clean(); +} + +// +// Detect Fair Value Gap ... +void DetectFairValueGap(XOHCL &bar) +{ + // + int idx = -1; + int count = 0; + bool has = false; + + // + if (!mXWZDetectFairValueGaps) + { + return; + } + + // + int iBarIndex = bar.Index(fairValueGapTF); + + // + XOHCL iBar; + bool isInited = iBar.Init( + bar.symbol, + fairValueGapTF, + iBarIndex // + ); + if (!isInited) + { + return; + } + + // + XOHCL zoneEndBar; + XOHCL zoneStartBar; + ENUM_X_DIRECTION zoneDir; + has = mXWZBarAnalyser.HasFairValueGap( + iBar, + zoneStartBar, + zoneEndBar, + zoneDir, + mXWZOBFVGSameBars // + ); + + // + if (!has) + { + // + zoneEndBar.Clean(); + zoneStartBar.Clean(); + return; + } + + // + XCFVG *zone; + zone = new XCFVG(); + has = zone.Init( + zoneStartBar, + zoneEndBar, + zoneDir // + ); + + // + if (!has) + { + // + ZeroMemory(zone); + zoneEndBar.Clean(); + zoneStartBar.Clean(); + + // + return; + } + + // + // Check Start ... + if (mXWZForceStarteds) + { + // + XOHCL startedBar; + bool isBodyOut = false; + bool isStarted = zone.IsStarted( + zoneDir, + startedBar, + isBodyOut, + iBar.period // + ); + + // + has = isStarted; + if (!has) + { + // + ZeroMemory(zone); + startedBar.Clean(); + zoneEndBar.Clean(); + zoneStartBar.Clean(); + + // + return; + } + + // + startedBar.Clean(); + } + + // + // Check Activation ... + if (mXWZForceActivation) + { + // + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = zone.IsActivated( + zoneDir, + activationBar, + isActivationBarBodyIn, + false, + iBar.period // + ); + + // + has = !isActivated; + if (!has) + { + // + ZeroMemory(zone); + zoneEndBar.Clean(); + zoneStartBar.Clean(); + activationBar.Clean(); + + // + return; + } + + // + activationBar.Clean(); + } + + // + // Check Breaktion ... + if (mXWZForceUnBreaked) + { + // + XOHCL breakedBar; + bool isBodyOut = false; + bool isBreaked = zone.IsBreaked( + zoneDir, + breakedBar, + isBodyOut, + false, + iBar.period // + ); + + // + has = !isBreaked; + if (!has) + { + // + ZeroMemory(zone); + breakedBar.Clean(); + zoneEndBar.Clean(); + zoneStartBar.Clean(); + + // + return; + } + + // + breakedBar.Clean(); + } + + // + // Check Indexes ... + + // + // UnActivateds ... + idx = FindIndex( + zone, + mXWZUnActivatedFVGs // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + ZeroMemory(zone); + zoneEndBar.Clean(); + zoneStartBar.Clean(); + + // + return; + } + + // + // Activateds ... + idx = FindIndex( + zone, + mXWZActivatedFVGs // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + ZeroMemory(zone); + zoneEndBar.Clean(); + zoneStartBar.Clean(); + + // + return; + } + + // + has = zone != NULL && + zone.IsValid(); + if (has) + { + // + zone.To(bar.time); + + // + Add( + zone, + mXWZUnActivatedFVGs // + ); + } + + // + iBar.Clean(); + zoneEndBar.Clean(); + zoneStartBar.Clean(); +} + +// +// Supply Zone ... +void DetectSupplyZone(XOHCL &bar) +{ + // + int idx = -1; + int count = 0; + bool has = false; + + // + if (!mXWZDetectSupplyZones) + { + return; + } + + // + int iBarIndex = bar.Index(supDemTF); + + // + XOHCL iBar; + bool isInited = iBar.Init( + bar.symbol, + supDemTF, + iBarIndex // + ); + if (!isInited) + { + return; + } + + // + int range = mXWZSuResRange * 2; + + // + XOHCL zoneBar; + ENUM_X_DIRECTION zoneDir = X_DIRECTION_BEARISH; + has = mXWZBarAnalyser.HasResistance( + iBar, + zoneBar, + range // + ); + + // + if (!has) + { + // + zoneBar.Clean(); + return; + } + + // + XCSupplyZone *zone; + zone = new XCSupplyZone(); + has = zone.Init( + zoneBar, + range, + true // + ); + + // + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + + // + return; + } + + // + // Check Start ... + if (mXWZForceStarteds) + { + // + XOHCL startedBar; + bool isBodyOut = false; + bool isStarted = zone.IsStarted( + zoneDir, + startedBar, + isBodyOut, + iBar.period // + ); + + // + has = isStarted; + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + startedBar.Clean(); + + // + return; + } + + // + startedBar.Clean(); + } + + // + // Check Activation ... + if (mXWZForceActivation) + { + // + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = zone.IsActivated( + zoneDir, + activationBar, + isActivationBarBodyIn, + false, + iBar.period // + ); + + // + has = !isActivated; + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + activationBar.Clean(); + + // + return; + } + + // + activationBar.Clean(); + } + + // + // Check Breaktion ... + if (mXWZForceUnBreaked) + { + // + XOHCL breakedBar; + bool isBodyOut = false; + bool isBreaked = zone.IsBreaked( + zoneDir, + breakedBar, + isBodyOut, + false, + iBar.period // + ); + + // + has = !isBreaked; + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + breakedBar.Clean(); + + // + return; + } + + // + breakedBar.Clean(); + } + + // + // Check Indexes ... + + // + // UnActivateds ... + idx = FindIndex( + zone, + mXWZUnActivatedSupplyZones // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + + // + return; + } + + // + // Activateds ... + idx = FindIndex( + zone, + mXWZActivatedSupplyZones // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + + // + return; + } + + // + has = zone != NULL && + zone.IsValid(); + if (has) + { + // + zone.To(bar.time); + + // + Add( + zone, + mXWZUnActivatedSupplyZones // + ); + } + + // + iBar.Clean(); + zoneBar.Clean(); +} + +// +// Demand Zone ... +void DetectDemandZone(XOHCL &bar) +{ + // + int idx = -1; + int count = 0; + bool has = false; + + // + if (!mXWZDetectDemandZones) + { + return; + } + + // + int iBarIndex = bar.Index(supDemTF); + + // + XOHCL iBar; + bool isInited = iBar.Init( + bar.symbol, + supDemTF, + iBarIndex // + ); + if (!isInited) + { + return; + } + + // + int range = mXWZSuResRange * 2; + + // + XOHCL zoneBar; + ENUM_X_DIRECTION zoneDir = X_DIRECTION_BULLISH; + has = mXWZBarAnalyser.HasSupport( + iBar, + zoneBar, + range // + ); + + // + if (!has) + { + // + zoneBar.Clean(); + return; + } + + // + XCDemandZone *zone; + zone = new XCDemandZone(); + has = zone.Init( + zoneBar, + range, + true // + ); + + // + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + + // + return; + } + + // + // Check Start ... + if (mXWZForceStarteds) + { + // + XOHCL startedBar; + bool isBodyOut = false; + bool isStarted = zone.IsStarted( + zoneDir, + startedBar, + isBodyOut, + iBar.period // + ); + + // + has = isStarted; + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + startedBar.Clean(); + + // + return; + } + + // + startedBar.Clean(); + } + + // + // Check Activation ... + if (mXWZForceActivation) + { + // + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = zone.IsActivated( + zoneDir, + activationBar, + isActivationBarBodyIn, + false, + iBar.period // + ); + + // + has = !isActivated; + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + activationBar.Clean(); + + // + return; + } + + // + activationBar.Clean(); + } + + // + // Check Breaktion ... + if (mXWZForceUnBreaked) + { + // + XOHCL breakedBar; + bool isBodyOut = false; + bool isBreaked = zone.IsBreaked( + zoneDir, + breakedBar, + isBodyOut, + false, + iBar.period // + ); + + // + has = !isBreaked; + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + breakedBar.Clean(); + + // + return; + } + + // + breakedBar.Clean(); + } + + // + // Check Indexes ... + + // + // UnActivateds ... + idx = FindIndex( + zone, + mXWZUnActivatedDemandZones // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + + // + return; + } + + // + // Activateds ... + idx = FindIndex( + zone, + mXWZActivatedDemandZones // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + + // + return; + } + + // + has = zone != NULL && + zone.IsValid(); + if (has) + { + // + zone.To(bar.time); + + // + Add( + zone, + mXWZUnActivatedDemandZones // + ); + } + + // + iBar.Clean(); + zoneBar.Clean(); +} + +// \ No newline at end of file diff --git a/BKPS/14040316/Documents/JsModules/mqlHelper.js b/BKPS/14040316/Documents/JsModules/mqlHelper.js new file mode 100644 index 0000000..8fe4e41 --- /dev/null +++ b/BKPS/14040316/Documents/JsModules/mqlHelper.js @@ -0,0 +1,19 @@ +/** + * XMQL Helper CLI Tools ... + * a module for handle MQL5 Commands running ... + * + * Maintainer + * + * Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) + */ + +// +// Import Requirements ... +const XProjectTools = require("./x-mql-project.tools"); + +// +// Read Command Arguments ... +let cmdName = process.argv[2]; + +// +XProjectTools.runCommand(cmdName); diff --git a/BKPS/14040316/Documents/JsModules/prepareXCATBEA.js b/BKPS/14040316/Documents/JsModules/prepareXCATBEA.js new file mode 100644 index 0000000..797e213 --- /dev/null +++ b/BKPS/14040316/Documents/JsModules/prepareXCATBEA.js @@ -0,0 +1,35 @@ +// +// Import Requirements ... +const XProjectTools = require("./x-mql-project.tools"); + +// +// define constants ... +const projectName = "XCATBEA"; + +// +// Projects Resources ... +const projectResources = [ + "Libraries/*", // Required Libraries + "Classes/*", // Required Classes + "XCATBEA/*", // XCATBEA Projects ... + "Indicators/x-saherelm.x121.xcatb", // Required Indicators + "Helpers/x-saherelm.x121.xcatb.helper", // Indicator's Helpers Classes + "Experts/x-saherelm.x121.xcatb.ea", // Expert Advisers +]; + +// +run(); + +/** + * Main Project Function ... + */ +async function run() { + // + await XProjectTools.prepareProject( + projectName, + projectResources + ); +} + + + diff --git a/BKPS/14040316/Documents/JsModules/x-color.tools.js b/BKPS/14040316/Documents/JsModules/x-color.tools.js new file mode 100644 index 0000000..c3ac5f9 --- /dev/null +++ b/BKPS/14040316/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/BKPS/14040316/Documents/JsModules/x-file.tools.js b/BKPS/14040316/Documents/JsModules/x-file.tools.js new file mode 100644 index 0000000..2a3535d --- /dev/null +++ b/BKPS/14040316/Documents/JsModules/x-file.tools.js @@ -0,0 +1,887 @@ +/** + * 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; +} + +/** + * Extract Specific files from a folder and it's content ... + * + * @param {string} path Folder Path ... + * @returns + */ +async function extractFiles(path = "", ext = [], excludeWorkspaceFolders = []) { + // + const result = []; + + // + if (!ext || ext.length == 0) { + return result; + } + + // + const pathContent = await getDirectoryContents(path); + if (!pathContent || pathContent.length == 0) { + return result; + } + + // + // Loop through Content ... + for (const c of pathContent) { + // + // Prepare full path ... + const cPath = joinPath(path, c); + + // + // check content path is file or not ... + const isCFile = isFileExists(cPath); + const isCDirectory = isDirectoryExists(cPath); + if (isCFile) { + // + // Check it is MQL file or not ... + const cExt = getFileExtension(cPath); + if (ext.includes(cExt)) { + result.push(cPath); + } + } else if (isCDirectory) { + // + const destFolderName = basename(cPath); + const isExcluded = excludeWorkspaceFolders.includes(destFolderName); + if (isExcluded) { + continue; + } + + // + const cFiles = await extractFiles(cPath, ext); + if (cFiles && cFiles.length > 0) { + result.push(...cFiles); + } + } + } + + // + 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, + extractFiles, + + // + copyFolder, + createDirectory, + removeDirectory, + isDirectoryExists, + getDirectoryFiles, + getDirectoryFolders, + getDirectoryContents, +}; +//#endregion \ No newline at end of file diff --git a/BKPS/14040316/Documents/JsModules/x-mql-project.tools.js b/BKPS/14040316/Documents/JsModules/x-mql-project.tools.js new file mode 100644 index 0000000..4a507a4 --- /dev/null +++ b/BKPS/14040316/Documents/JsModules/x-mql-project.tools.js @@ -0,0 +1,494 @@ +/** + * XProject Tools Module ... + * a module for handle MQL5 Projects Compile and Packing ... + * + * Maintainer + * + * Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) + */ + +// +// Import Requirements ... +const execSync = require("child_process").execSync; +const XFileTools = require("./Documents/JsModules/x-file.tools"); +const XShellTools = require("./Documents/JsModules/x-shell.tools"); +const XColorTools = require("./Documents/JsModules/x-color.tools"); +const XTypeTools = require("./Documents/JsModules/x-type-detector.tools"); + +// +// Definitions ... +const packsPath = XFileTools.joinPath(".", "Packs"); +const workspacePaths = [ + "Classes", // Required Classes + "Experts", // Expert Advisers + "Helpers", // Indicator's Helpers Classes + "Indicators", // Required Indicators + "Libraries", // Required Libraries + "XCATBEA", // XCATBEA Projects ... +]; + +// +//#region Tools ... + +/** + * Handle Compile and Pack Projects ... + * + * @param {string} projectName + * @param {string[]} resources + * @param {boolean} forceCleanup + * @param {boolean} forceCompileIndicators + */ +async function prepareProject( + projectName = "", + resources = [], + forceCleanup = true, + forceCompileIndicators = true +) { + // + // Check Resources Has Child ... + let isValidArgs = + resources.length > 0 && + XTypeTools.isArray(resources); + if (!isValidArgs) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("Invalid Resource List ...", XColorTools.COLOR_NAMES.Red) + ); + } + + // + // Check Project Name is Valid ... + isValidArgs = + projectName.length > 0 && + XTypeTools.isString(projectName); + if (!isValidArgs) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("Empty Project Name ...", XColorTools.COLOR_NAMES.Red) + ); + } + + // + // Extract Required to Compile Resources List ... + let compileList = await extractResources(resources, true); + if (!compileList || compileList.length == 0) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("Resource List Extraction to Compile Failed ...", XColorTools.COLOR_NAMES.Red) + ); + + // + return; + } + + // + // Compile Resources Files ... + for (const f of compileList) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("try to Compile: ", XColorTools.COLOR_NAMES.Yellow), + XColorTools.applyForegroundColor(f, XColorTools.COLOR_NAMES.Blue) + ); + + // + await recursiveTriesToCompileFile(f, 0); + } + + // + // Extract Required to Pack Resources List ... + let packList = await extractResources(resources, false); + if (!packList || packList.length == 0) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("Resource List Extraction to Pack Failed ...", XColorTools.COLOR_NAMES.Red) + ); + + // + return; + } + + // + // Prepare Pack Folder Exists ... + let isExists = XFileTools.isDirectoryExists(packsPath); + if (!isExists) { + XFileTools.createDirectory(packsPath); + } + + // + // Check Folder Exists or not ... + // if Exists Remove it ... + // Create Project Folder on Packs ... + const prjFolderOnPacks = XFileTools.joinPath(packsPath, projectName); + isExists = XFileTools.isDirectoryExists(prjFolderOnPacks); + if (isExists) { + await XFileTools.removeDirectory(prjFolderOnPacks, true); + } + XFileTools.createDirectory(prjFolderOnPacks); + + // + // Loop through Files ... + for (const f of packList) { + // + // Prepare Destination Path ... + const fBasePath = XFileTools.basename(f); + let fDestPath = f.replace(fBasePath, ""); + fDestPath = fDestPath.substring(0, fDestPath.length - 1); + fDestPath = XFileTools.joinPath(prjFolderOnPacks, fDestPath); + + // + const isFDestPathExists = XFileTools.isDirectoryExists(fDestPath); + if (!isFDestPathExists) { + XFileTools.createDirectory(fDestPath); + } + + // + // Log ... + console.log( + XColorTools.applyForegroundColor("try to copy: ", XColorTools.COLOR_NAMES.Yellow), + XColorTools.applyForegroundColor(f, XColorTools.COLOR_NAMES.Blue), + XColorTools.applyForegroundColor(" to : ", XColorTools.COLOR_NAMES.Yellow), + XColorTools.applyForegroundColor(fDestPath, XColorTools.COLOR_NAMES.Magenta) + ); + + // + let result = await XFileTools.copyFile(f, fDestPath); + if (result) { + // + const msg = "copy successfully ..."; + console.log( + XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Green) + ); + } else { + // + const msg = "copy failed ..."; + console.log(XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Red)); + throw msg; + } + } + + // + // Log ... + console.log( + XColorTools.applyForegroundColor("Project: ", XColorTools.COLOR_NAMES.Green), + XColorTools.applyForegroundColor(projectName, XColorTools.COLOR_NAMES.Yellow), + XColorTools.applyForegroundColor(" Compiled and Packed Successfully ...", XColorTools.COLOR_NAMES.Green), + ); + + // + // Cleanup WorkSpace if Provided ... + if (forceCleanup) { + await cleanupWorkSpace(); + } + + // + // Compile Indicators ... + if (forceCompileIndicators) { + await compile("Indicators"); + } +} + +/** + * Extract required Files List ... + * + * @param {boolean} forCompile + * + * @returns Promise + */ +async function extractResources( + resources = [], + forCompile = true +) { + // + let result = []; + + // + // Loop Through Project Resources and Extract Files List to Compile ... + for (const resource of resources) { + // + // Prepare Normalized Resource Path ... + let resourcePath = XFileTools.joinPath(".", resource); + + // + // Handle Wild Card Resources ... + if (resourcePath.endsWith("//*") || + resourcePath.endsWith("\\*")) { + // + resourcePath = resourcePath.substring(0, resourcePath.length - 2); + const files = await XFileTools.extractFiles( + resourcePath, + forCompile ? [".mq5", ".mq4"] : [".ex5", ".ex4"] + ); + + // + result = result.concat(files); + } + // + // Handle Direct File Resources ... + else { + // + // Check MQL 5 Version ... + let fileResourcePath = resourcePath + (forCompile ? ".mq5" : ".ex5"); + + // + // Check File Exists ... + let isExists = XFileTools.isFileExists(fileResourcePath); + if (!isExists) { + // + // Check MQL 4 Version ... + fileResourcePath = resourcePath + (forCompile ? ".mq4" : ".ex4"); + isExists = XFileTools.isFileExists(fileResourcePath); + } + + // + // Add File Path to Files List if Exists ... + if (isExists) { + result.push(fileResourcePath); + } + } + } + + // + return result; +} + +/** + * try to compile a file ... + * @param {string} f + * @param {number} numberOfTries + */ +async function recursiveTriesToCompileFile(f = "", numberOfTries = 0) { + // + let result = await handleFileCompile(f); + if (result) { + // + const msg = "compiled successfully ..."; + console.log(XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Green)); + return result; + } else { + // + if (numberOfTries < 10) { + // + numberOfTries++; + + // + const msg = "retry (" + (numberOfTries + 1) + ") ..."; + console.log(XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.LightMagenta)); + await recursiveTriesToCompileFile(f, numberOfTries); + } else { + // + const msg = "failed ..."; + console.log(XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Red)); + throw msg; + + // + return false; + } + } +} + +/** + * execute compile task on Specific File ... + * @param {string} f file path to Execute Compile task ... + * @returns + */ +async function handleFileCompile(f = "") { + // + let result = false; + + // + let exResult = await compileMQLFile(f); + if (exResult.includes("0 errors")) { + result = true; + } else { + result = false; + } + + // + return result; +} + +/** + * Compile Specific MQL File ... + * + * @param {string} path MQL file path ... + * @returns + */ +async function compileMQLFile(path = "") { + // + // Check File Exists ... + const isExists = XFileTools.isFileExists(path); + if (!isExists) { + // + const msg = "file not found ..."; + console.log(XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Red)); + throw msg; + } + + // + const ext = XFileTools.getFileExtension(path); + if (ext !== ".mq5" && ext !== "mq4") { + // + const msg = "invalid file extension ..."; + console.log(XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Red)); + throw msg; + } + + // + const cwd = __dirname; + const cmd = "compile.cmd " + path; + + // + const result = await XShellTools.execute(cmd, cwd); + return result; +} + +/** + * Run Specified Command in workspace ... + * + * @param {string} cmd + * @returns + */ +async function runCommand(cmd = "") { + // + // Validate Args ... + let isValidArgs = cmd.length > 0 && + XTypeTools.isString(cmd); + + // + // Validate Commands ... + if (isValidArgs) { + // + // Check Available Commands ... + isValidArgs = + cmd === "*" || + cmd === "cleanup" || + workspacePaths.includes(cmd) || + workspacePaths.map(x => x.toLowerCase(x)).includes(cmd.toLowerCase()); + } + if (!isValidArgs) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("Invalid Command ...", XColorTools.COLOR_NAMES.Red) + ); + } + + // + // Compile ... + if (cmd == "*") { + await compileWorkSpace(); + } else if (cmd == "cleanup") { + await cleanupWorkSpace(); + } else { + // + // Select Workspace to Compile ... + const folder = workspacePaths + .find(x => x.toLowerCase() === cmd.toLowerCase()); + isValidArgs = + XTypeTools.isString(folder) && + folder.length > 0; + if (!isValidArgs) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("Invalid Command ...", XColorTools.COLOR_NAMES.Red) + ); + } + + // + // Extract Required to Compile Resources List ... + let compileList = await XFileTools.extractFiles( + folder, + [".mq5", ".mq4"] + ); + if (!compileList || compileList.length == 0) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("Extraction to Compile Failed ...", XColorTools.COLOR_NAMES.Red) + ); + + // + return; + } + + // + // Compile Resources Files ... + for (const f of compileList) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("try to Compile: ", XColorTools.COLOR_NAMES.Yellow), + XColorTools.applyForegroundColor(f, XColorTools.COLOR_NAMES.Blue) + ); + + // + await recursiveTriesToCompileFile(f, 0); + } + } +} + +/** + * Cleanup Workspace compiled files ... + */ +async function cleanupWorkSpace() { + // + for (const path of workspacePaths) { + // + const fSourcePath = XFileTools.joinPath(".", path); + const filesToRemove = await XFileTools.extractFiles(fSourcePath, [".ex5", ".ex4"]); + for (const f of filesToRemove) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("try to Remove: ", XColorTools.COLOR_NAMES.Yellow), + XColorTools.applyForegroundColor(f, XColorTools.COLOR_NAMES.Blue) + ); + + // + let result = await XFileTools.removeFile(f); + if (result) { + // + const msg = "removed successfully ..."; + console.log( + XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Green) + ); + } else { + // + const msg = "removed failed ..."; + console.log(XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Red)); + throw msg; + } + } + } +} + +/** + * Compile Workspace ... + */ +async function compileWorkSpace() { + // + for (const path of workspacePaths) { + await runCommand(path); + } +} +//#endregion + +// +//#region Module Exports ... +module.exports = { + extractResources, + recursiveTriesToCompileFile, + handleFileCompile, + compileMQLFile, + runCommand, + cleanupWorkSpace, + compileWorkSpace, + prepareProject +} +//#endregion \ No newline at end of file diff --git a/BKPS/14040316/Documents/JsModules/x-shell.tools.js b/BKPS/14040316/Documents/JsModules/x-shell.tools.js new file mode 100644 index 0000000..0ee13de --- /dev/null +++ b/BKPS/14040316/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/BKPS/14040316/Documents/JsModules/x-type-detector.tools.js b/BKPS/14040316/Documents/JsModules/x-type-detector.tools.js new file mode 100644 index 0000000..86ed3d8 --- /dev/null +++ b/BKPS/14040316/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/BKPS/14040316/Documents/JsModules/x-value.tools.js b/BKPS/14040316/Documents/JsModules/x-value.tools.js new file mode 100644 index 0000000..81cfcc4 --- /dev/null +++ b/BKPS/14040316/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/BKPS/14040316/Documents/MQL5 VSCode.7z b/BKPS/14040316/Documents/MQL5 VSCode.7z new file mode 100644 index 0000000000000000000000000000000000000000..a0e81380adb05238d088d401dffb1f8b062ac7fc GIT binary patch literal 1998962 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�kbUW=_mTu)r}J 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

HMN9l-FT{PbV~`1Ro1PhY{VEzyrn(N=hqZmha$ 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 z


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%0D$9;2o)76kOPFs5PbgZ01?OT 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�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%0A3yz>)_Vx6wA(K|*ehmxGEkY#_Q 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ΞPJ-#5w zI>qNvXaw!*269ky(TvfRM1`hT&;$32w@b`v;lKzDoeB*a2uyuxhoa;#H{VM7r z;0xA?f=dI0qPUu&Q3{Bn2kxG6^bZ7F+*_J{nTuKC3#ia9@bLdMIsdHoc@A_j& zwNZ&rYrIpQIob?RiouVS?4ZL(iZ`@&B*o|TKnE-yE}36JPito5t7z;Lhy>n7m12UuF*0S#isRrknuT}!D-(^D z*<4OZSl7^fc<0C`GhUCXSR=m~(@9|)!DTLYIh~S)DPhi@`eI!)ebpx2P{Zvnmz*oO z%$!2`ttQHnNIxKe>o%Sfd?#~mn3~kpAAaT6Lz!IKPTDVd5RoQ z&s3@ItJnz*!b}%u!gX#wM|qma(gGRDL8d=3L$~;P=WD*o=^bG>^DAyT6nA8v^LLUB zvmgMTQ3_Tjt)r$Op5+z8nJ5{&&2XzvF!WSX$~}DvGqZ+sdc7CV0sOXw2yT>h*BTfm znterx1Sc8-)Sv)H_L9rMm-GS~`1kp_%#m)ylf#;ndfA+{9H(;#tTc?=s0hECp5MkK z;?OQsLUlE>Cl%vBFD=Wg42>c0t9FQJ<>MJmb_OdBeypeP)5B5?DuaTFMKyZlB`UFE z$aDFMoR%mx)rtLZ+M@VMaFWP4i=)86+Dt$$l~3nHLZvI^8E43;U*d zEpYfnY~*$xiq0+O8<1AmzlRVFbIQY;h|){M+`TS1XbGh(#;B0h4-&i0gShgq zGg`3g_qu))29NjRnZK0MsfDFX84KU|tV*9Bzjze)Z}!E`1J5R>2`SchUz}0+3XcgJ z5>IuT(!-&%f(;oY2yrWu6$@*xpjWwqo@H~>as_*YaYOY36i4+MMC(%z6+_x-dQ`5? zigNOgJk#-+^tekktxKGMNVOJ$DHf8y1u6Ht#5f=lvepXLz2IOsQ6WX+A&j;ZOsH*( zF2nN=v!>WtqFe6E0`K_eWlFCMEBvG9cBU$jMo-4k2^S=&?$F4{RRK^r3%Y==GH< z4!JTo1EWn2_Y1S4<6Eczy&nPWut4%Gb22KA{!xt~w?2v_tr86DR zghp2(+5sNWjsD9dNExPr|AWG>%0D$H8VG7ec*rRF3xPJ}(E+Q~s9w9EKpFWRF{;IQ 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�Znt@y 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%0AEVl3s2_vfgu(c3h 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

FBO_QQ#ru?CG`wC+pf)RwT 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

^;hV*Y|*-w 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∈p37IFbAVu-T94 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%0D7rZfWkWdxKHi++#+1dexvuVX(#?iS&Mc+Fm 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

dnWfIZ6AOB{R}QaP)O&&8(#OPT3ax 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

b2e(d1!Qsh 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ÌZy_1Pm#}djCHk1(C@p0!D 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žqr850^$)Z3~m2ikQ9i9 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%0A0X7_0Cj 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 >Qgq&~Yy8smQt+C-Ju><-p|xV8Muh;_ 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 V1ziAO000cY-b4xk_x!8V0026rpoahe literal 0 HcmV?d00001 diff --git a/BKPS/14040316/Documents/Temlates/signalling.function.template.mq5 b/BKPS/14040316/Documents/Temlates/signalling.function.template.mq5 new file mode 100644 index 0000000..3cbd45a --- /dev/null +++ b/BKPS/14040316/Documents/Temlates/signalling.function.template.mq5 @@ -0,0 +1,221 @@ + +// +// Detect Signals Based On XPV Indicator Golden Zones ... +// +bool HasTMPConditions( + ENUM_X_CYCLES cycle, + XBoxZone &box, + ENUM_X_DIRECTION &dir, + X121SMCStrategySignalProviderData &provider, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + box.Clean(); + dir = X_DIRECTION_NONE; + + // + // Fil Selected Data ... + XPOIState cState; + X121Conditions cXConditions; + XPOIStateEvents cStateEvents; + XC121SMCCycleHelper *cHelper; + X121SMCCycleConditions cConditions; + result = provider.SelectCycle( + cycle, + cState, + cStateEvents, + cXConditions, + cHelper, + cConditions // + ); + if (!result) + { + // + cState.Clean(); + ZeroMemory(cHelper); + cConditions.Clean(); + cXConditions.Clean(); + cStateEvents.Clean(); + + // + return result; + } + + // + // Normalize Args ... + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int idx = -1; + int count = 0; + bool has = false; + + // + int zIDX = barIndex; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int ppIDX = pIDX + 1; + + // + bool isBullish = false; + bool isBearish = false; + + // + XOHCL zBar; + XOHCL cBar; + XOHCL pBar; + XOHCL pPBar; + + // + // Initial Bars ... + result = zBar.Init( + cState.symbol, + cState.period, + barIndex // + ); + result = + result && + zBar.GetPreviousBar(cBar); + result = + result && + cBar.GetPreviousBar(pBar); + result = + result && + pBar.GetPreviousBar(pPBar); + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + cState.Clean(); + ZeroMemory(cHelper); + cConditions.Clean(); + cXConditions.Clean(); + + // + return result; + } + + // + // Checking Conditions ... + + // + // Summarize Conditions ... + + // + isBullish = + // + false + // + ; + + // + isBearish = + // + false + // + ; + + // + // Filling Requirements ... + result = + isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + box.dir = dir; + box.from = pPBar.time; + box.to = TimeCurrent(); + box.symbol = cBar.symbol; + box.period = cBar.period; + + // + double points = GetPoints(box.symbol); + + // + // Usually is Preffered SL ... + double pivot = 0; + + // + // Usually is Current Price or Entry Price ... + double point = GetEntry( + cBar.symbol, + dir // + ); + + // + box.upper = + isBullish + ? point + : pivot; + + // + box.lower = + isBullish + ? pivot + : point; + + // + XCPOIDrawer *drawer = provider.visionCycleHelper.mPOIDrawer; + bool drawBoxes = true; + if (drawBoxes) + { + // + if (box.IsValid()) { + // + XCBoxObject *iObj; + bool isCreated = drawer.DrawBox( + box, + iObj // + ); + + // + if (isCreated) { + // + // TODO: ... + } + } + } + } + + // + // Check All Conditions ... + result = + box.IsValid() && + HasDirection(dir) && + (isBullish || + isBearish); + + // + // Cleanup Resources ... + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + pPBar.Clean(); + cState.Clean(); + cConditions.Clean(); + cConditions.Clean(); + ZeroMemory(cHelper); + cStateEvents.Clean(); + cXConditions.Clean(); + + // + return result; +} diff --git a/BKPS/14040316/Documents/Temlates/temp.pivot.detect.mq5 b/BKPS/14040316/Documents/Temlates/temp.pivot.detect.mq5 new file mode 100644 index 0000000..2104084 --- /dev/null +++ b/BKPS/14040316/Documents/Temlates/temp.pivot.detect.mq5 @@ -0,0 +1,83 @@ + + // + bool DetectPivot( + int barIndex, + XOHCL &zBar, + XOHCL &cBar, + XOHCL &pBar, + XOHCL &p2Bar, + XCAEAConditions &conditions // + ) + { + // + bool result = false; + + // + // Validate Args ... + result = + // + barIndex >= 0 && + zBar.IsValid() && + cBar.IsValid() && + pBar.IsValid() && + p2Bar.IsValid() && + // + ; + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + + // + XCAPviot pivot; + datetime cTime = zBar.time; + string symbol = zBar.symbol; + string period = zBar.period; + + // + // Reading Conditional Values ... + + // + // Prepare Conditinal Conditions ... + + // + bool hasStartCondition = false; + bool hasContinuationCondition = false; + bool hasEndCondition = false; + + // + // ReInstance Pivot ... + if (hasStartConditions) + { + // + } + + // + // Calculate and Fill Pivot Requirements ... + if (hasContinuationCondition) + { + // + } + + // + // End up Pivot and Store it ... + if (hasEndCondition) + { + // + } + + // + pivot.Clean(); + + // + return result; + } diff --git a/BKPS/14040316/Documents/Temlates/x-saherelm.x-ea.template.ea.mq5 b/BKPS/14040316/Documents/Temlates/x-saherelm.x-ea.template.ea.mq5 new file mode 100644 index 0000000..297e0b0 --- /dev/null +++ b/BKPS/14040316/Documents/Temlates/x-saherelm.x-ea.template.ea.mq5 @@ -0,0 +1,542 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center XTest MQL5 Expert Advisor +// ------------------------------------------------- +// Name: XEATemplate +// Description: a Template For Exper Advisors +// +// 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 XEATemplate" +#property strict + +// +#define ShortName "XEATemplate" + +// +// Imports ... +#include "../Classes/x-saherelm.xalert.class.mq5" +#include "../Classes/x-saherelm.xtrade.class.mq5" +#include "../Helpers/x-saherelm.xcc.helper.mq5" +#include "../Helpers/x-saherelm.xct.helper.mq5" + +// +// Inputs ... + +// +// Common ... +input group "Common"; +input long eaMagicNumber = 78692110; // Magic Number +input int eaSlippage = 10; // Slippgae +input string eaLogSuffix = ""; // Log Suffix + +// +// Alert ... +// Here we Provider All Requirements for +// Configuring Alert Provider ... +input group "Alert"; +input bool eAEnableAlerts = true; // Enable Alerts +input bool eALogAlerts = true; // Log Alerts +input bool eAMailAlerts = false; // Mail Alerts +input bool eAPushAlerts = false; // Push Alerts +input bool eATerminalAlerts = false; // Terminal Alerts + +// +// Time Report ... +input group "Reports"; +input bool eaReportNewMonths = false; // Report New Month +input bool eaReportNewWeeks = false; // Report New Weeks +input bool eaReportNewDays = false; // Report New Days +input bool eaReportNewHours = false; // Report New Hours + +// +// Define Local Variables ... + +// +string eaLogTag; // EA Log Prefix ... +XSCAlert *eaAlert; // Alert Provider for Expert Adviser ... +XSCTrade *eaTrader; // Trader of Expert Adviser ... +XTimeTracker eaTimeTracker; // Time Tracker for Providing Reports ... +XSCXCTHelper *eaCHelper; // Bar Timer Indicator Helper class ... +XSCXCCHelper *eaCCHelper; // Chart Styler Indicator Helper Class ... + +// +// Event Handlers ... + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs and Required Parameters + // for EA to Works fine ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Timer ... + if (!InitTimer()) { + return INIT_FAILED; + } + + // + // Initialize all Requirements ... + if (!InitEA()) + { + return INIT_FAILED; + } + + // + // Initialize all GUI Objects and Classes ... + if (!InitGUI()) + { + return INIT_FAILED; + } + + // + // Alert Initialization ... + string msg = "Initialized Successfully ..."; + eaAlert.SendAlert(msg); + + // + // 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 + + // + // Destroy Timer ... + DestroyTimer(); + + // + // Destroy all GUI Requirements ... + DestroyGUI(); + + // + // Alert De Initialization Succeeded ... + string msg = "De Initialized Successfully ..."; + eaAlert.SendAlert(msg); + + // + // Destroy all EA Requirements ... + DestroyEA(); +} + +// +// On Tick Handler ... +void OnTick() +{ + // + UpdateGUI(); + HandleReportTime(); + UpdatePositionsState(); + + // + // TODO: Implemetn Tick Processors Algorithm ... +} + +// +// Handle On Trade Event ... +void OnTrade() +{ + eaTrader.HandleOnTrade(); +} + +// +// On Timer ... +void OnTimer() +{ + // + // TODO: Implement Time Based Functionalities ... +} + +// +// Chart Event Handler ... +void OnChartEvent( + const int id, + const long &lparam, + const double &dparam, + const string &sparam // +) +{ + // + // Handle OnClick Event ... + if (id == CHARTEVENT_OBJECT_CLICK) + { + HandleOnClickEvent(sparam); + } +} + +// +// Custom Event Handlers ... + +/** + * Handle StopLoss Triggered Positions ... + * + * @param deal: XDeal ... + */ +void OnStopLossTriggered(const XDeal &deal) +{ + // + HandleReportBalance(); +} + +/** + * Handle Take Profit Triggered Positions ... + * + * @param deal: XDeal ... + */ +void OnTakeProfitTriggered(const XDeal &deal) +{ + // + HandleReportBalance(); +} + +/** + * Handle Force Close a Position ... + * + * @param ticket: Position Ticket ... + * @param position: XPosition ... + * @param comment: Closing Comment ... + */ +void OnPositionForceClosed( + const ulong ticket, + const XPosition &position, + const string comment // +) +{ + // + HandleReportBalance(); +} + +// +// Custom Functions ... + +/** + * Validate all Inputs of Expert Adviser ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + string errMessage = ""; + + // + bool isCommonValid = ( + // + eaSlippage > 0 && + eaMagicNumber > 0 + // + ); + if (!isCommonValid) + { + // + errMessage += "common configurations error;" + "\n"; + } + + // + result = + // + // Common ... + isCommonValid && + // + // Otere ... + true + // + ; + + // + if (!result) + { + // + // Since here Logger not Initiallized, we Use Raw Print Command ... + Print(ShortName + " Errors: \n", errMessage); + } + + // + return result; +} + +/** + * Initialize Timer ... + * + * @return ( bool ) + */ +bool InitTimer() { + // + bool result = false; + + // + // TODO: Initialize Timer if necessary ... + // result = EventSetTimer(1); + // result = EventSetMillisecondTimer(100); + result = true; + + // + return result; +} + +/** + * Destroy Timer ... + */ +void DestroyTimer() { + // + // TODO: Use This ... + // EventKillTimer(); +} + +/** + * Initialize all Requirements for Working Fine ... + * + * @return ( bool ) + */ +bool InitEA() +{ + // + bool result = false; + + // + // Locally Apply Changes on Prefix ... + eaLogTag = ShortName + ">" + eaLogSuffix; + + // + // Bar Timer ... + XCTInputs ctInputs; + ctInputs.Default(); // Default Configurations ... + eaCHelper = new XSCXCTHelper(); + result = eaCHelper.Init( + _Symbol, + _Period, + ctInputs // + ); + if (!result) + { + return result; + } + + // + // Bar Styles ... + XCCInputs ccInputs; + ccInputs.Default(); // Default Configurations ... + eaCCHelper = new XSCXCCHelper(); + result = eaCCHelper.Init( + _Symbol, + _Period, + ccInputs // + ); + if (!result) + { + return result; + } + + // + // Create Instance of Alert Class and Configure it ... + eaAlert = new XSCAlert(); + eaAlert.SetPrefix(eaLogTag); + eaAlert.SetLogAlerts(eALogAlerts); + eaAlert.SetMailAlerts(eAMailAlerts); + eaAlert.SetPushAlerts(eAPushAlerts); + eaAlert.SetEnableAlerts(eAEnableAlerts); + eaAlert.SetTerminalAlerts(eATerminalAlerts); + + // + // Create Trader Instance and Configure it ... + eaTrader = new XSCTrade( + eaSlippage, + eaMagicNumber // + ); + eaTrader.AddOnStopLossEventHandler(OnStopLossTriggered); + eaTrader.AddOnTakeProfitEventHandler(OnTakeProfitTriggered); + eaTrader.AddOnForceClosePositionEventHandler(OnPositionForceClosed); + + // + return result; +} + +/** + * Destroy all Initialized EA Requirements ... + */ +void DestroyEA() +{ + // + delete eaCHelper; + delete eaCCHelper; + + // + delete eaAlert; +} + +/** + * Initialize all GUI Requirements for EA ... + * + * @return ( bool ) + */ +bool InitGUI() +{ + // + bool result = false; + + // + // TODO: Fix This ... + result = true; + + // + return result; +} + +/** + * Update GUI based on Each Ticks ... + */ +void UpdateGUI() +{ + // + // TODO: Implement this ... +} + +/** + * Destroy all Initialized GUi Requirements ... + */ +void DestroyGUI() +{ + // + // TODO: Complete this ... +} + +// +// Others ... + +/** + * Update Positions States ... + */ +void UpdatePositionsState() +{ + // + // TODO: Implement this ... +} + +/** + * Handle On Click Event for GUI Components ... + * + * @param name: Object Name ... + */ +void HandleOnClickEvent(string name) +{ + // + if (!IsValid(name)) + { + return; + } + + // + bool isClicked = false; + + // + // TODO: Implement Chart Objects On Click ... + + // + if (isClicked) + { + UpdateGUI(); + } +} + +/** + * Report Account Balance ... + */ +void HandleReportBalance() +{ + // + if (!IsRunningOnTestMode()) + { + return; + } + + // + string msg = "Balance: " + ToString(eaTrader.mAccount.GetBalance()); + eaAlert.Log(msg); +} + +/** + * Time Reporting based on Inputs ... + */ +void HandleReportTime() +{ + // + // Monthly Report .... + if (eaReportNewMonths && + eaTimeTracker.IsNewMonth()) + { + // + string msg = "New Month ..."; + + // + eaAlert.SendAlert(msg); + } + + // + // Weekly Report .... + if (eaReportNewWeeks && + eaTimeTracker.IsNewWeek()) + { + // + string msg = "New Week ..."; + + // + eaAlert.SendAlert(msg); + } + + // + // Daily Report .... + if (eaReportNewDays && + eaTimeTracker.IsNewDay()) + { + // + string msg = "New Day ..."; + + // + eaAlert.SendAlert(msg); + } + + // + // Hourly Report .... + if (eaReportNewHours && + eaTimeTracker.IsNewHour()) + { + // + string msg = "New Hour ..."; + + // + eaAlert.SendAlert(msg); + } +} + +// diff --git a/BKPS/14040316/Documents/Temlates/x-saherelm.x-panel.ea.mq5 b/BKPS/14040316/Documents/Temlates/x-saherelm.x-panel.ea.mq5 new file mode 100644 index 0000000..08417d4 --- /dev/null +++ b/BKPS/14040316/Documents/Temlates/x-saherelm.x-panel.ea.mq5 @@ -0,0 +1,575 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center XTest MQL5 Expert Advisor +// ------------------------------------------------- +// Name: XPanelEA +// Description: an Exper Advisor which used Panels +// +// 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 XPanelEA" +#property strict + +// +#define ShortName "XPANELEA" + +// +// Imports ... +#include "../Classes/x-saherelm.x-app-dialog.class.mq5" +#include "../Classes/x-saherelm.xalert.class.mq5" +#include "../Classes/x-saherelm.xtrade.class.mq5" +#include "../Helpers/x-saherelm.xcc.helper.mq5" +#include "../Helpers/x-saherelm.xct.helper.mq5" + +// +// Inputs ... + +// +// Common ... +input group "Common"; +input long eaMagicNumber = 78692110; // Magic Number +input int eaSlippage = 10; // Slippgae +input string eaLogSuffix = ""; // Log Suffix + +// +// Alert ... +// Here we Provider All Requirements for +// Configuring Alert Provider ... +input group "Alert"; +input bool eAEnableAlerts = true; // Enable Alerts +input bool eALogAlerts = true; // Log Alerts +input bool eAMailAlerts = false; // Mail Alerts +input bool eAPushAlerts = false; // Push Alerts +input bool eATerminalAlerts = false; // Terminal Alerts + +// +// Time Report ... +input group "Reports"; +input bool eaReportNewMonths = false; // Report New Month +input bool eaReportNewWeeks = false; // Report New Weeks +input bool eaReportNewDays = false; // Report New Days +input bool eaReportNewHours = false; // Report New Hours + +// +// Define Local Variables ... + +// +string eaLogTag; // EA Log Prefix ... +XSCAlert *eaAlert; // Alert Provider for Expert Adviser ... +XSCTrade *eaTrader; // Trader of Expert Adviser ... +XTimeTracker eaTimeTracker; // Time Tracker for Providing Reports ... +XSCXCTHelper *eaCTHelper; // Bar Timer Indicator Helper class ... +XSCXCCHelper *eaCCHelper; // Chart Styler Indicator Helper Class ... + +// +XCAppDialog eaMainWindow; // EA Main Dialog ... + +// +// Event Handlers ... + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs and Required Parameters + // for EA to Works fine ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Timer ... + if (!InitTimer()) + { + return INIT_FAILED; + } + + // + // Initialize all Requirements ... + if (!InitEA()) + { + return INIT_FAILED; + } + + // + // Initialize all GUI Objects and Classes ... + if (!InitGUI()) + { + return INIT_FAILED; + } + + // + // Alert Initialization ... + string msg = "Initialized Successfully ..."; + eaAlert.SendAlert(msg); + + // + // 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 + + // + // Destroy Timer ... + DestroyTimer(); + + // + // Destroy all GUI Requirements ... + DestroyGUI(); + + // + // Alert De Initialization Succeeded ... + string msg = "De Initialized Successfully ..."; + eaAlert.SendAlert(msg); + + // + // Destroy all EA Requirements ... + DestroyEA(); +} + +// +// On Tick Handler ... +void OnTick() +{ + // + UpdateGUI(); + HandleReportTime(); + UpdatePositionsState(); + + // + // TODO: Implemetn Tick Processors Algorithm ... +} + +// +// Handle On Trade Event ... +void OnTrade() +{ + eaTrader.HandleOnTrade(); +} + +// +// On Timer ... +void OnTimer() +{ + // + // TODO: Implement Time Based Functionalities ... +} + +// +// Chart Event Handler ... +void OnChartEvent( + const int id, + const long &lparam, + const double &dparam, + const string &sparam // +) +{ + // + // Apply Chart Event on Main Window ... + eaMainWindow.ChartEvent(id, lparam, dparam, sparam); + + // + // Handle OnClick Event ... + if (id == CHARTEVENT_OBJECT_CLICK) + { + HandleOnClickEvent(sparam); + } +} + +// +// Custom Event Handlers ... + +/** + * Handle StopLoss Triggered Positions ... + * + * @param deal: XDeal ... + */ +void OnStopLossTriggered(const XDeal &deal) +{ + // + HandleReportBalance(); +} + +/** + * Handle Take Profit Triggered Positions ... + * + * @param deal: XDeal ... + */ +void OnTakeProfitTriggered(const XDeal &deal) +{ + // + HandleReportBalance(); +} + +/** + * Handle Force Close a Position ... + * + * @param ticket: Position Ticket ... + * @param position: XPosition ... + * @param comment: Closing Comment ... + */ +void OnPositionForceClosed( + const ulong ticket, + const XPosition &position, + const string comment // +) +{ + // + HandleReportBalance(); +} + +// +// Custom Functions ... + +/** + * Validate all Inputs of Expert Adviser ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + string errMessage = ""; + + // + bool isCommonValid = ( + // + eaSlippage > 0 && + eaMagicNumber > 0 + // + ); + if (!isCommonValid) + { + // + errMessage += "common configurations error;" + "\n"; + } + + // + result = + // + // Common ... + isCommonValid && + // + // Otere ... + true + // + ; + + // + if (!result) + { + // + // Since here Logger not Initiallized, we Use Raw Print Command ... + Print(ShortName + " Errors: \n", errMessage); + } + + // + return result; +} + +/** + * Initialize Timer ... + * + * @return ( bool ) + */ +bool InitTimer() +{ + // + bool result = false; + + // + // TODO: Initialize Timer if necessary ... + // result = EventSetTimer(1); + // result = EventSetMillisecondTimer(100); + result = true; + + // + return result; +} + +/** + * Destroy Timer ... + */ +void DestroyTimer() +{ + // + // TODO: Use This ... + // EventKillTimer(); +} + +/** + * Initialize all Requirements for Working Fine ... + * + * @return ( bool ) + */ +bool InitEA() +{ + // + bool result = false; + + // + // Locally Apply Changes on Prefix ... + eaLogTag = ShortName + ">" + eaLogSuffix; + + // + // Bar Timer ... + XCTInputs ctInputs; + ctInputs.Default(); // Default Configurations ... + eaCTHelper = new XSCXCTHelper(); + result = eaCTHelper.Init( + _Symbol, + _Period, + ctInputs // + ); + if (!result) + { + return result; + } + + // + // Bar Styles ... + XCCInputs ccInputs; + ccInputs.Default(); // Default Configurations ... + eaCCHelper = new XSCXCCHelper(); + result = eaCCHelper.Init( + _Symbol, + _Period, + ccInputs // + ); + if (!result) + { + return result; + } + + // + // Create Instance of Alert Class and Configure it ... + eaAlert = new XSCAlert(); + eaAlert.SetPrefix(eaLogTag); + eaAlert.SetLogAlerts(eALogAlerts); + eaAlert.SetMailAlerts(eAMailAlerts); + eaAlert.SetPushAlerts(eAPushAlerts); + eaAlert.SetEnableAlerts(eAEnableAlerts); + eaAlert.SetTerminalAlerts(eATerminalAlerts); + + // + // Create Trader Instance and Configure it ... + eaTrader = new XSCTrade( + eaSlippage, + eaMagicNumber // + ); + eaTrader.AddOnStopLossEventHandler(OnStopLossTriggered); + eaTrader.AddOnTakeProfitEventHandler(OnTakeProfitTriggered); + eaTrader.AddOnForceClosePositionEventHandler(OnPositionForceClosed); + + // + return result; +} + +/** + * Destroy all Initialized EA Requirements ... + */ +void DestroyEA() +{ + // + delete eaCTHelper; + delete eaCCHelper; + + // + delete eaAlert; +} + +/** + * Initialize all GUI Requirements for EA ... + * + * @return ( bool ) + */ +bool InitGUI() +{ + // + bool result = false; + + // + // Initialize Application Main Window ... + result = eaMainWindow.Create( + ChartID(), + ShortName, // Dialog Name ... + 0, // SubWindow ... + 10, // X1 ... + 35, // Y1 ... + 300, // X2 ... + 200 // Y2 ... + ); + + // + // Configuring Dialog ... + // eaMainWindow.MinimizeButton(false); // Hide Minimize Button ... + // eaMainWindow.CloseButton(false); // Hide Close Button ... + eaMainWindow.BackgroundColor(clrBlack); + // result = true; + + // + // Try To Run Main Window ... + if (result) + { + eaMainWindow.Run(); + } + + // + return result; +} + +/** + * Update GUI based on Each Ticks ... + */ +void UpdateGUI() +{ + // + // TODO: Implement this ... +} + +/** + * Destroy all Initialized GUi Requirements ... + */ +void DestroyGUI() +{ + // + eaMainWindow.Destroy(); +} + +// +// Others ... + +/** + * Update Positions States ... + */ +void UpdatePositionsState() +{ + // + // TODO: Implement this ... +} + +/** + * Handle On Click Event for GUI Components ... + * + * @param name: Object Name ... + */ +void HandleOnClickEvent(string name) +{ + // + if (!IsValid(name)) + { + return; + } + + // + bool isClicked = false; + + // + // TODO: Implement Chart Objects On Click ... + + // + if (isClicked) + { + UpdateGUI(); + } +} + +/** + * Report Account Balance ... + */ +void HandleReportBalance() +{ + // + if (!IsRunningOnTestMode()) + { + return; + } + + // + string msg = "Balance: " + ToString(eaTrader.mAccount.GetBalance()); + eaAlert.Log(msg); +} + +/** + * Time Reporting based on Inputs ... + */ +void HandleReportTime() +{ + // + // Monthly Report .... + if (eaReportNewMonths && + eaTimeTracker.IsNewMonth()) + { + // + string msg = "New Month ..."; + + // + eaAlert.SendAlert(msg); + } + + // + // Weekly Report .... + if (eaReportNewWeeks && + eaTimeTracker.IsNewWeek()) + { + // + string msg = "New Week ..."; + + // + eaAlert.SendAlert(msg); + } + + // + // Daily Report .... + if (eaReportNewDays && + eaTimeTracker.IsNewDay()) + { + // + string msg = "New Day ..."; + + // + eaAlert.SendAlert(msg); + } + + // + // Hourly Report .... + if (eaReportNewHours && + eaTimeTracker.IsNewHour()) + { + // + string msg = "New Hour ..."; + + // + eaAlert.SendAlert(msg); + } +} + +// diff --git a/BKPS/14040316/Documents/Temlates/xwz.signal.senario.template.mq5 b/BKPS/14040316/Documents/Temlates/xwz.signal.senario.template.mq5 new file mode 100644 index 0000000..f9f6052 --- /dev/null +++ b/BKPS/14040316/Documents/Temlates/xwz.signal.senario.template.mq5 @@ -0,0 +1,187 @@ + + // + // Senario 3: + // ---------- + bool useSenario3 = false; + bool isSenario3Happend = false; + bool isSenario3Bullish = false; + bool isSenario3Bearish = false; + if (useSenario3) + { + // + // Senario 3 Bullish Conditions ... + isSenario3Bullish = false; + + // + // Senario 3 Bearish Conditions ... + isSenario3Bearish = false; + + // + // Filling Requirements using Senario 3 ... + isSenario3Happend = + isSenario3Bullish || + isSenario3Bearish; + if (isSenario3Happend) + { + // + dir = + isSenario3Bullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + box.dir = dir; + box.to = TimeCurrent(); + box.symbol = provider + .decisionXConditions + .symbol; + box.period = provider + .decisionXConditions + .period; + + // + int fromIDX = -1; + if (isSenario3Bullish) + { + // + double vale = provider + .decisionXConditions + .valesBuffer[cIDX]; + + // + box.lower = vale; + + // + box.upper = provider + .decisionXConditions + .valesGoldenBuffer[cIDX]; + + // + int lowerValeIDX = -1; + double lowerVale = provider + .decisionCycleHelper + .mX121Helper + .xpvHelper + .GetLowerVale( + lowerValeIDX, + vale, + cBar.Index() // + ); + + // + int higherValeIDX = -1; + double higherVale = provider + .decisionCycleHelper + .mX121Helper + .xpvHelper + .GetHigherVale( + higherValeIDX, + vale, + cBar.Index() // + ); + + // + if (IsValidIndex(lowerValeIDX) && + IsValidIndex(higherValeIDX)) + { + // + fromIDX = + lowerValeIDX < higherValeIDX + ? lowerValeIDX + : higherValeIDX; + } + else if (IsValidIndex(lowerValeIDX) && + !IsValidIndex(higherValeIDX)) + { + // + fromIDX = lowerValeIDX; + } + else if (!IsValidIndex(lowerValeIDX) && + IsValidIndex(higherValeIDX)) + { + // + fromIDX = higherValeIDX; + } + } + else + { + // + double peak = provider + .decisionXConditions + .peaksBuffer[cIDX]; + + // + box.upper = peak; + + // + box.lower = provider + .decisionXConditions + .peaksGoldenBuffer[cIDX]; + + // + int lowerPeakIDX = -1; + double lowerPeak = provider + .decisionCycleHelper + .mX121Helper + .xpvHelper + .GetLowerPeak( + lowerPeakIDX, + peak, + cBar.Index() // + ); + + // + int higherPeakIDX = -1; + double higherPeak = provider + .decisionCycleHelper + .mX121Helper + .xpvHelper + .GetHigherPeak( + higherPeakIDX, + peak, + cBar.Index() // + ); + + // + if (IsValidIndex(lowerPeakIDX) && + IsValidIndex(higherPeakIDX)) + { + // + fromIDX = + lowerPeakIDX < higherPeakIDX + ? lowerPeakIDX + : higherPeakIDX; + } + else if (IsValidIndex(lowerPeakIDX) && + !IsValidIndex(higherPeakIDX)) + { + // + fromIDX = lowerPeakIDX; + } + else if (!IsValidIndex(lowerPeakIDX) && + IsValidIndex(higherPeakIDX)) + { + // + fromIDX = higherPeakIDX; + } + } + + // + if (IsValidIndex(fromIDX)) + { + // + box.from = iTime( + zBar.symbol, + zBar.period, + fromIDX // + ); + } + else + { + box.from = pBar.time; + } + + // + signalProvider = X121SMC_XWZ_PROVIDER_ACTIVATED_BOX; + } + } diff --git a/BKPS/14040316/Documents/XCATBEAInputs/X121XCATBEA_XAUUSDb_M5.x121.log.txt b/BKPS/14040316/Documents/XCATBEAInputs/X121XCATBEA_XAUUSDb_M5.x121.log.txt new file mode 100644 index 0000000..e141480 --- /dev/null +++ b/BKPS/14040316/Documents/XCATBEAInputs/X121XCATBEA_XAUUSDb_M5.x121.log.txt @@ -0,0 +1,43 @@ +----------------------- +Validating: +----------------------- +eaForceHasSwing: true +eaForceOBBarType: true +eaForceFVGBarType: true +eaForceHasFLiquidity: false +eaForceHasRLiquidity: false +eaValidateGapSequence: true +eaValidateBlockEdgeBreakout: false +----------------------- +Filtering: +----------------------- +eaFilterBasedOnKI: true +eaFilterBasedOnPV: false +eaFilterBasedOnSar: false +eaForceSarSwitched: false +eaForceSarOnBothSide: false +eaForceSarHasBreakout: false +eaForceSarHasReversalSide: false +eaFilterBasedOnRSI: false +eaForceHasRSITrending: false +eaForceHasRSIVPattern: false +eaForceHasRSICrossing: false +eaFilterBasedOnADX: false +eaForceHasADXTrending: false +eaForceHasADXCrossing: false +eaFilterBasedOnATR: false +eaForceHasATRTrending: false +eaForceHasATRBreakout: false +eaFilterBasedOnTrend: true +eaForceHasTrendDir: true +eaForceHasTrendPlace: true +eaForceHasTrendChange: false +eaForceHasTrendTrending: false +eaForceHasTrendRejection: false +eaForceHasTrendLineInside: false +eaForceHasTrendDirOnBothSide: false +eaFilterBasedOnDelta: false +eaFilterBasedOnVolume: true +eaFilterBasedOnSignalBar: false +eaFilterBasedOnHKSignalBar: false + diff --git a/BKPS/14040316/Documents/XCATBEAInputs/inputs.config.filepath.txt b/BKPS/14040316/Documents/XCATBEAInputs/inputs.config.filepath.txt new file mode 100644 index 0000000..34f0b61 --- /dev/null +++ b/BKPS/14040316/Documents/XCATBEAInputs/inputs.config.filepath.txt @@ -0,0 +1 @@ +X121XCATBEA\X121XCATBEA_XAUUSDb_M5.x121.log diff --git a/BKPS/14040316/Documents/XCATBEAInputs/x-saherelm.xcatb.ea.base.optimization.inputs.set b/BKPS/14040316/Documents/XCATBEAInputs/x-saherelm.xcatb.ea.base.optimization.inputs.set new file mode 100644 index 0000000000000000000000000000000000000000..fff3ec2bac42c39232cf78b288a3a2a8f832a919 GIT binary patch literal 9618 zcmc(lYjYw+6o&h=RsIKlfX3Ww)yjulHk&Q82?dz-D*=LWb2CgfiREus-=_~v_e?<9 zp@~H?%=C1>=YCFK`1`LPUBiuB*L`*a*Vp~6yU}&st?IkwR`k0)zBYW@4{pu9aa_N5 zU%Rgy;|uqzyA(>pUFi2pNDbHXNQICug~&U8@7#lWH}uY3hPtNl6==!8=?I-LrpV{DSSexfyWh(6E9yaw&>Ys9raSdKPi{h;sA^Kc@}YmI@o9qDCT zcH5LCw{-WXKGRxWwy*lWClma(m+;QpaVTt%txxzdog#D;KH=?p53XH^>@Kb&=jr_EvpHL8j^*-eRBlHndcI&~&+MD$x(j zw+^L~s+Q{eLlwQ16}=oa19?hUwrr2Rk99I9m_B74{g?wwCr>$l>dLm2KCx@qKmO*4BJ=SNXZ6U5W>9$xE$DSl!zmMRiR$Yb9v? zW~~n6x-jJvD$G#Ib8vQ0Z1xhOakPN#zl1Uw0e@g^b1$w~FSB;~|LLbW<5baRyKMD+ zl~t$hdG#e-S#EZ0j@{3b`4=k_X2V6LU(`>1K6d46c-ymPmBe7!QyR!8@qu(zL`H*e zb~MS<({-{uTTS!JwWWFHG-~UwN^Rp+scpV0wXIjBwq27NxjwCcA=jsEX+-R}4WH#L z$J=$&x5VAbwy)J>*4_krp!%9?AMil2Og-gvAX1=yLwTTRC)+b44f|brD$IY=O|=%J zwW??wr1z_S2c2pb>K!}j;X_;0s6{II5t#~AQcf{GElJKQwWf4xdjQZjxwa-;$2-m# zQvU5UDYR5)1yw5fZH8~NGmWoMZ|%gTn4BWC#5tOEMFp?(H*{H>p zT}>jQtDG06OLQl#vipcu!Gn&|9y@;`mkf`x{Gp!0X`bbZ zP%%~}wS!aU4SnqcZyWxED6~}N+*gF6A?9qv(y4Mh`;V#iccr~}u1G(;D@OZU_2(>= z_V^a7)r%f>blJttfkiA2vmjw1R-$FD%K4@IWV%ju5F@6k3^h`2D5Ir)=f~=Jdr-4& zEnLPd^n3VpEP`t2p^ zfoMH@PV4FVCE}6fe~^}PN#F5NPbI4#K`EE%nmrF9=+mlB-FQ#AZAyC1pyK})a-i 0 && + eaMagicNumber > 0 + // + ); + if (!isCommonValid) + { + // + errMessage += "common configurations error;" + "\n"; + } + + // + result = + // + // Common ... + isCommonValid && + // + // Otere ... + true + // + ; + + // + if (!result) + { + // + // Since here Logger not Initiallized, we Use Raw Print Command ... + Print(ShortName + " Errors: \n", errMessage); + } + + // + return result; +} + +/** + * Initialize Timer ... + * + * @return ( bool ) + */ +bool InitTimer() +{ + // + bool result = false; + + // + // TODO: Initialize Timer if necessary ... + // result = EventSetTimer(1); + // result = EventSetMillisecondTimer(100); + result = true; + + // + return result; +} + +/** + * Destroy Timer ... + */ +void DestroyTimer() +{ + // + // TODO: Use This ... + // EventKillTimer(); +} + +/** + * Initialize all Requirements for Working Fine ... + * + * @return ( bool ) + */ +bool InitEA() +{ + // + bool result = false; + + // + // Locally Apply Changes on Prefix ... + eaLogTag = ShortName + ">" + eaLogSuffix; + + // + // Bar Timer ... + X121XCTInputs ctInputs; + ctInputs.Default(); // Default Configurations ... + eaCTHelper = new XCX121XCTHelper(); + result = eaCTHelper.Init( + _Symbol, + _Period, + ctInputs // + ); + if (!result) + { + return result; + } + + // + // Bar Styles ... + X121XCCInputs ccInputs; + ccInputs.Default(); // Default Configurations ... + eaCCHelper = new XCX121XCCHelper(); + result = eaCCHelper.Init( + _Symbol, + _Period, + ccInputs // + ); + if (!result) + { + return result; + } + + // + // Create Instance of Alert Class and Configure it ... + eaAlert = new XCAlert(); + eaAlert.SetPrefix(eaLogTag); + eaAlert.SetLogAlerts(eALogAlerts); + eaAlert.SetMailAlerts(eAMailAlerts); + eaAlert.SetPushAlerts(eAPushAlerts); + eaAlert.SetEnableAlerts(eAEnableAlerts); + eaAlert.SetTerminalAlerts(eATerminalAlerts); + + // + // Create Trader Instance and Configure it ... + eaTrader = new XCTrade( + eaSlippage, + eaMagicNumber // + ); + eaTrader.AddOnStopLossEventHandler(OnStopLossTriggered); + eaTrader.AddOnTakeProfitEventHandler(OnTakeProfitTriggered); + eaTrader.AddOnForceClosePositionEventHandler(OnPositionForceClosed); + + // + return result; +} + +/** + * Destroy all Initialized EA Requirements ... + */ +void DestroyEA() +{ + // + delete eaCTHelper; + delete eaCCHelper; + + // + delete eaAlert; +} + +/** + * Initialize all GUI Requirements for EA ... + * + * @return ( bool ) + */ +bool InitGUI() +{ + // + bool result = false; + + // + // Initialize Application Main Window ... + result = eaMainWindow.Create( + ChartID(), + ShortName, // Dialog Name ... + 0, // SubWindow ... + 10, // X1 ... + 35, // Y1 ... + 300, // X2 ... + 200 // Y2 ... + ); + + // + // Try To Run Main Window ... + if (result) + { + eaMainWindow.Run(); + } + + // + return result; +} + +/** + * Update GUI based on Each Ticks ... + */ +void UpdateGUI() +{ + // + eaMainWindow.UpdateState(); +} + +/** + * Destroy all Initialized GUi Requirements ... + */ +void DestroyGUI() +{ + // + eaMainWindow.Destroy(); +} + +// diff --git a/BKPS/14040316/Experts/x-saherelm.x121.xcatb.ea.mq5 b/BKPS/14040316/Experts/x-saherelm.x121.xcatb.ea.mq5 new file mode 100644 index 0000000..107f2c0 --- /dev/null +++ b/BKPS/14040316/Experts/x-saherelm.x121.xcatb.ea.mq5 @@ -0,0 +1,635 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Expert Advisor +// ------------------------------------------------- +// Name: X121XCATB +// Description: X121XCATB base Expert Advisor ... +// +// 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 X121XCATB based Expert Advisor" +#property strict + +// +#define ShortName "X121XCATBEA" + +// +// Importts ... +#include "../XCATBEA/Classes/xcatbea.expert.class.mq5" + +// +// Inputs ... + +// +// Common ... +input group "Common"; +input long eaMagicNumber = 1694056; // Magic Number +input int eaSlippage = 10; // Slippgae +input string eaLogSuffix = ""; // Log Suffix + +// +// Detector ... +input group "Detector"; + +// +// Validating ... +input group "Validations"; +input bool eaForceHasSwing = false; // Force Block to Has Propper Swing +input bool eaForceOBBarType = false; // Force Order Block to Has InDirectional Bars +input int eaMinRequiredOBBar = 0; // Min Required OB Bar +input bool eaForceFVGBarType = false; // Force Fair Value Gaps Bars Type +input int eaLiquidityLoopback = 0; // Liquidity Detection Loopback +input double eaMaxAllowedRange = 0.0; // Max Allowed Order Block Range +input double eaMinAllowedRange = 0.0; // Min Allowed Order Block Range +input bool eaForceHasFLiquidity = false; // Force Order Block To Has Reversal Liquidity +input bool eaForceHasRLiquidity = false; // Force Order Block to Has Following Liquidity +input bool eaValidateGapSequence = false; // Validate Fair Value Gaps Bar Sequences +input int eaMinAllowedBlockLength = 0; // Min Allowed Block Length +input bool eaValidateBlockEdgeBreakout = false; // Validate Order Block Edge Breakeout + +// +// Filtering ... +input group "Filters"; +input bool eaFilterBasedOnKI = false; // Filter Based On KI Flats +input bool eaFilterBasedOnPV = false; // Filter Based On PV +input int eaBosLoopback = 0; // PV Based Filtering BOS Lookup +input bool eaFilterBasedOnSar = false; // Filter Based On SAR +input bool eaForceSarSwitched = false; // SAR Switched on Sides for Filtering +input bool eaForceSarOnBothSide = false; // SAR Check on Both Sides for Filtering +input bool eaForceSarHasBreakout = false; // SAR Must Breakout +input bool eaForceSarHasReversalSide = false; // SAR Must Has Reversal Direction +input bool eaFilterBasedOnRSI = false; // Filter Based On RSI +input bool eaForceHasRSITrending = false; // RSI Must Has Trending +input bool eaForceHasRSIVPattern = false; // RSI Must Has V Pattern +input bool eaForceHasRSICrossing = false; // RSI Must Has Crossing Levels +input bool eaFilterBasedOnADX = false; // Filter Based On ADX +input bool eaForceHasADXTrending = false; // ADX Must Has Trending +input bool eaForceHasADXCrossing = false; // ADX Must Has Crossing +DI/-DI +input bool eaFilterBasedOnATR = false; // Filter Based On ATR +input bool eaForceHasATRTrending = false; // ATR Must Has Trending +input bool eaForceHasATRBreakout = false; // ATR Must Has Breakout +input bool eaFilterBasedOnTrend = false; // Filter Based On Trend +input bool eaForceHasTrendDir = false; // TREND Must Has Following Direction +input bool eaForceHasTrendPlace = false; // TREND Place Based Filtering +input bool eaForceHasTrendChange = false; // TREND Change Filtering +input bool eaForceHasTrendTrending = false; // TREND Must Has Trending +input bool eaForceHasTrendRejection = false; // TREND Line Must Rejected +input bool eaForceHasTrendLineInside = false; // TREND Line has Inside +input bool eaForceHasTrendDirOnBothSide = false; // TREND Must Has Following Direction in Both Side +input bool eaFilterBasedOnDelta = false; // Filter Based On Delta +input bool eaFilterBasedOnVolume = false; // Filter Based On Volume +input bool eaFilterBasedOnSignalBar = false; // Filter Based on Signal Bar +input bool eaFilterBasedOnHKSignalBar = false; // Filter Based On HK Signal Bar + +// +// Signal ... +input group "Signal"; +input int eaSignalR2R = 2; // Risk Reward Ratio +input double eaSLATRMultiplier = 0; // ATR Multiplier for SL +input bool eaAllowSignallingBasedOnConditions; // Signalling Based on Market Conditions +input bool eaAllowSignallingBasedOnTriggerBlocks; // Signalling Based on Trigger Blocks +input bool eaAllowSignallingBasedOnTriggerBlocksInsideOther; // Signalling Based on Trigger Blocks Seccond inputs +input bool eaSecondsTriggersSLUsingFirstTriggerBlock; // Use First Trigger Block for SL of Seconds Trigger Block Signalss +input bool eaApplyValidateAndFilterOnSelectInsideOthers; // Select Trigger Blocks by Applying Validations and Filterss +input bool eaAllowSignallingConditions1; // Allow Market Conditions Signaller to Using Sar Signals +input bool eaAllowSignallingConditions2; // Allow Market Conditions Signaller to Using Trend Signals +input bool eaAllowSignallingConditions3; // Allow Market Conditions Signaller to Using Delta Signals +input bool eaAllowSignallingConditions4; // Allow Market Conditions Signaller to Using Volume Signals +input bool eaAllowSignallingConditions5; // Allow Market Conditions Signaller to Using Signal Bar Signals +input bool eaAllowSignallingConditions6; // Allow Market Conditions Signaller to Using HK Signal Bar Signals + +// +// Volume ... +input group "Volume"; +input ENUM_X_VOLUME_SELECT_TYPE eaVolumeSelect = X_VOLUME_EQUITY; // Volume Applying Type +input double eaStaticVoluem = 0.0; // Static Volume +input double eaDynamicVolumeStepBalance = 0.0; // Step of Balance for Increase Volume +input double eaDynamicVolumeStepVolume = X_MIN_VOLUME; // Step of Volume Increasing +input double eaConstantRiskBalance = 0.0; // Constant Risk Balance per Trade +input double eaConstantPercent = 0.5; // Constant Percent of Balance Per Trade +input double eaConstantBalance = 0.0; // Constant Balance for Calculations + +// +// Management ... +// eaSymbols => comma separated Symbols for Trading, use Default if not Provided ... +// eaSessions => (ST_04:00_08:30),(TL_10:30_12:00),(NY_16:00_20:00) +input group "Management"; +input string eaSymbols = ""; // Allowed Trading Symbols +input bool eaAllowGuards = false; // Allow Guards +input bool eaAllowTrade = true; // Allow Trade on Signals +input bool eaAllowLongs = true; // Allow Long Trades +input bool eaAllowShorts = true; // Allow Short Trades +input string eaSessions = ""; // Active Sessions +input ENUM_XCATBEA_TRADE_RESTRICTION_PERIOD eaRestrictionsPeriod = XCATBEA_TRADE_RESTRICATION_NONE; // Restrictions Period +input int eaMaxAllowedTPs = 0; // Max Allowed TP(s) in Restrictions Period +input int eaMaxAllowedSLs = 0; // Max Allowed SL(s) in Restrictions Period +input int eaMaxAllowedTrades = 0; // Max Allowed Trades in Restrictions Period +input int eaMaxAllowedPositions = 5; // Max Allowed Same Time Trades +input double eaMaxAllowedSpread = 25; // Max Allowed Spread For Trade +input double eaMaxAllowedDrawdownFactor = 0.3; // Max Allowed DrawDown for Trade +input string eaCloseAllOpenTradesAt = ""; // Close All Open Trades per Day At Specified Time + +// +// Alert ... +// Here we Provider All Requirements for +// Configuring Alert Provider ... +input group "Alert"; +input bool eaEnableAlerts = true; // Enable Alerts +input bool eaSaveAlerts = true; // Save Alerts +input bool eaLogAlerts = true; // Log Alerts +input bool eaMailAlerts = false; // Mail Alerts +input bool eaPushAlerts = true; // Push Alerts +input bool eaTerminalAlerts = false; // Terminal Alerts + +// +// Time Report ... +input group "Reports"; +input bool eaReportNewMonths = false; // Report New Month +input bool eaReportNewWeeks = false; // Report New Weeks +input bool eaReportNewDays = true; // Report New Days +input bool eaReportNewHours = false; // Report New Hours +input bool eaReportTrades = true; // Report Trades +input bool eaReportSignals = true; // Report Signals +input bool eaReportRestrictions = true; // Report Restrictions +input bool eaReportProtector = true; // Report Protector Actions +input bool eaReportAfterTradesBalance = true; // Report Balance after a Trade Finished + +// +// Collector ... +input group "Collector"; +input bool eaSaveTrades = false; // Save Trades +input bool eaSaveSignals = false; // Save Signals +input bool eaSaveWins = false; // Save Winning Conditions +input bool eaSaveLosts = false; // Save Lost Conditions +input bool eaSaveRestrictions = false; // Save Restriction Reports + +// +// Variables ... + +// +XCXCATBEAExpert *eaExpert; + +// +// Event Handlers ... + +// +// Initialization ... +int OnInit() +{ + // + // Preparing Tags ... + string eaTag = + (IsValid(eaLogSuffix) + ? eaLogSuffix + "_" + : "") + + ShortName; + + // + // Validate Inputs and Required Parameters + // for EA to Works fine ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Timer ... + if (!InitTimer()) + { + return INIT_FAILED; + } + + // + // Configure EA Expert Class ... + eaExpert = new XCXCATBEAExpert(); + + // + // Setting All Inputs to Expert Adviser Class ... + + // + // Common ... + eaExpert.eaLogSuffix = eaTag; + eaExpert.eaSlippage = eaSlippage; + eaExpert.eaMagicNumber = eaMagicNumber; + + // + // Detector ... + + // + // Validations ... + eaExpert.eaForceHasSwing = eaForceHasSwing; + eaExpert.eaForceOBBarType = eaForceOBBarType; + eaExpert.eaForceFVGBarType = eaForceFVGBarType; + eaExpert.eaMaxAllowedRange = eaMaxAllowedRange; + eaExpert.eaMinAllowedRange = eaMinAllowedRange; + eaExpert.eaMinRequiredOBBar = eaMinRequiredOBBar; + eaExpert.eaLiquidityLoopback = eaLiquidityLoopback; + eaExpert.eaForceHasFLiquidity = eaForceHasFLiquidity; + eaExpert.eaForceHasRLiquidity = eaForceHasRLiquidity; + eaExpert.eaValidateGapSequence = eaValidateGapSequence; + eaExpert.eaMinAllowedBlockLength = eaMinAllowedBlockLength; + eaExpert.eaValidateBlockEdgeBreakout = eaValidateBlockEdgeBreakout; + + // + // Filters ... + eaExpert.eaBosLoopback = eaBosLoopback; + eaExpert.eaFilterBasedOnKI = eaFilterBasedOnKI; + eaExpert.eaFilterBasedOnPV = eaFilterBasedOnPV; + eaExpert.eaFilterBasedOnSar = eaFilterBasedOnSar; + eaExpert.eaFilterBasedOnRSI = eaFilterBasedOnRSI; + eaExpert.eaForceSarSwitched = eaForceSarSwitched; + eaExpert.eaFilterBasedOnADX = eaFilterBasedOnADX; + eaExpert.eaFilterBasedOnATR = eaFilterBasedOnATR; + eaExpert.eaForceHasTrendDir = eaForceHasTrendDir; + eaExpert.eaForceSarOnBothSide = eaForceSarOnBothSide; + eaExpert.eaFilterBasedOnTrend = eaFilterBasedOnTrend; + eaExpert.eaForceHasTrendPlace = eaForceHasTrendPlace; + eaExpert.eaFilterBasedOnDelta = eaFilterBasedOnDelta; + eaExpert.eaForceSarHasBreakout = eaForceSarHasBreakout; + eaExpert.eaForceHasRSITrending = eaForceHasRSITrending; + eaExpert.eaForceHasRSIVPattern = eaForceHasRSIVPattern; + eaExpert.eaForceHasRSICrossing = eaForceHasRSICrossing; + eaExpert.eaForceHasADXTrending = eaForceHasADXTrending; + eaExpert.eaForceHasADXCrossing = eaForceHasADXCrossing; + eaExpert.eaForceHasATRTrending = eaForceHasATRTrending; + eaExpert.eaForceHasATRBreakout = eaForceHasATRBreakout; + eaExpert.eaForceHasTrendChange = eaForceHasTrendChange; + eaExpert.eaFilterBasedOnVolume = eaFilterBasedOnVolume; + eaExpert.eaForceHasTrendTrending = eaForceHasTrendTrending; + eaExpert.eaForceHasTrendRejection = eaForceHasTrendRejection; + eaExpert.eaFilterBasedOnSignalBar = eaFilterBasedOnSignalBar; + eaExpert.eaForceSarHasReversalSide = eaForceSarHasReversalSide; + eaExpert.eaForceHasTrendLineInside = eaForceHasTrendLineInside; + eaExpert.eaFilterBasedOnHKSignalBar = eaFilterBasedOnHKSignalBar; + eaExpert.eaForceHasTrendDirOnBothSide = eaForceHasTrendDirOnBothSide; + + // + // Signal ... + eaExpert.eaSignalR2R = eaSignalR2R; + eaExpert.eaSLATRMultiplier = eaSLATRMultiplier; + eaExpert.eaAllowSignallingBasedOnConditions = eaAllowSignallingBasedOnConditions; + eaExpert.eaAllowSignallingBasedOnTriggerBlocks = eaAllowSignallingBasedOnTriggerBlocks; + eaExpert.eaSecondsTriggersSLUsingFirstTriggerBlock = eaSecondsTriggersSLUsingFirstTriggerBlock; + eaExpert.eaApplyValidateAndFilterOnSelectInsideOthers = eaApplyValidateAndFilterOnSelectInsideOthers; + eaExpert.eaAllowSignallingBasedOnTriggerBlocksInsideOther = eaAllowSignallingBasedOnTriggerBlocksInsideOther; + eaExpert.eaAllowSignallingConditions1 = eaAllowSignallingConditions1; + eaExpert.eaAllowSignallingConditions2 = eaAllowSignallingConditions2; + eaExpert.eaAllowSignallingConditions3 = eaAllowSignallingConditions3; + eaExpert.eaAllowSignallingConditions4 = eaAllowSignallingConditions4; + eaExpert.eaAllowSignallingConditions5 = eaAllowSignallingConditions5; + eaExpert.eaAllowSignallingConditions6 = eaAllowSignallingConditions6; + + // + // Volume ... + eaExpert.eaVolumeSelect = eaVolumeSelect; + eaExpert.eaStaticVoluem = eaStaticVoluem; + eaExpert.eaConstantPercent = eaConstantPercent; + eaExpert.eaConstantBalance = eaConstantBalance; + eaExpert.eaConstantRiskBalance = eaConstantRiskBalance; + eaExpert.eaDynamicVolumeStepVolume = eaDynamicVolumeStepVolume; + eaExpert.eaDynamicVolumeStepBalance = eaDynamicVolumeStepBalance; + + // + // Management ... + eaExpert.eaSymbols = eaSymbols; + eaExpert.eaSessions = eaSessions; + eaExpert.eaAllowTrade = eaAllowTrade; + eaExpert.eaAllowLongs = eaAllowLongs; + eaExpert.eaAllowGuards = eaAllowGuards; + eaExpert.eaAllowShorts = eaAllowShorts; + eaExpert.eaMaxAllowedTPs = eaMaxAllowedTPs; + eaExpert.eaMaxAllowedSLs = eaMaxAllowedSLs; + eaExpert.eaMaxAllowedTrades = eaMaxAllowedTrades; + eaExpert.eaMaxAllowedSpread = eaMaxAllowedSpread; + eaExpert.eaRestrictionsPeriod = eaRestrictionsPeriod; + eaExpert.eaMaxAllowedPositions = eaMaxAllowedPositions; + eaExpert.eaCloseAllOpenTradesAt = eaCloseAllOpenTradesAt; + eaExpert.eaMaxAllowedDrawdownFactor = eaMaxAllowedDrawdownFactor; + + // + // Alert ... + eaExpert.eaLogAlerts = eaLogAlerts; + eaExpert.eaMailAlerts = eaMailAlerts; + eaExpert.eaPushAlerts = eaPushAlerts; + eaExpert.eaSaveAlerts = eaSaveAlerts; + eaExpert.eaEnableAlerts = eaEnableAlerts; + eaExpert.eaTerminalAlerts = eaTerminalAlerts; + + // + // Reports ... + eaExpert.eaReportTrades = eaReportTrades; + eaExpert.eaReportNewDays = eaReportNewDays; + eaExpert.eaReportSignals = eaReportSignals; + eaExpert.eaReportNewWeeks = eaReportNewWeeks; + eaExpert.eaReportNewHours = eaReportNewHours; + eaExpert.eaReportProtector = eaReportProtector; + eaExpert.eaReportNewMonths = eaReportNewMonths; + eaExpert.eaReportRestrictions = eaReportRestrictions; + eaExpert.eaReportAfterTradesBalance = eaReportAfterTradesBalance; + + // + // Collector ... + eaExpert.eaSaveWins = eaSaveWins; + eaExpert.eaSaveLosts = eaSaveLosts; + eaExpert.eaSaveTrades = eaSaveTrades; + eaExpert.eaSaveSignals = eaSaveSignals; + eaExpert.eaSaveRestrictions = eaSaveRestrictions; + + // + // Attach Event Handlers ... + eaExpert.AddOnDealsChangedEventHandler(OnDealsChanged); + eaExpert.AddOnStopLossEventHandler(OnStopLossTriggered); + eaExpert.AddOnOrdersChangedEventHandler(OnOrdersChanged); + eaExpert.AddOnTakeProfitEventHandler(OnTakeProfitTriggered); + eaExpert.AddOnModifyPositionEventHandler(OnPositionModified); + eaExpert.AddOnPositionsChangedEventHandler(OnPositionsChanged); + eaExpert.AddOnTradeStateChangedEventHandler(OnTradeStateChanged); + eaExpert.AddOnForceClosePositionEventHandler(OnPositionForceClosed); + eaExpert.AddOnPartialClosePositionEventHandler(OnPositionPartialClosed); + + // + bool isInited = eaExpert.HandleOnInit(); + if (!isInited) + { + return INIT_FAILED; + } + + // + 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 + + // + // Destroy Timer ... + eaExpert.HandleOnDeInit(); + + // + delete eaExpert; + ZeroMemory(eaExpert); +} + +// +// On Tick Handler ... +void OnTick() +{ + eaExpert.HandleOnTick(); +} + +// +// Handle On Trade Event ... +void OnTrade() +{ + eaExpert.HandleOnTrade(); +} + +// +// On Timer ... +void OnTimer() +{ + eaExpert.HandleOnTimer(); +} + +// +// Chart Event Handler ... +void OnChartEvent( + const int id, + const long &lparam, + const double &dparam, + const string &sparam // +) +{ + eaExpert.HandleOnChartEvent(id, lparam, dparam, sparam); +} + +// +// Event Listeners ... + +/** + * Handle StopLoss Triggered Positions ... + * + * @param deal: XDeal instance ... + */ +void OnStopLossTriggered(const XDeal &deal) +{ + eaExpert.HandleOnStopLossTriggered(deal); +} + +/** + * Handle Take Profit Triggered Positions ... + * + * @param deal: XDeal instance ... + */ +void OnTakeProfitTriggered(const XDeal &deal) +{ + eaExpert.HandleOnTakeProfitTriggered(deal); +} + +/** + * Handle Force Close a Position ... + * + * @param ticket: ULONG ... + * @param position: XPosition instance ... + * @param comment: String ... + */ +void OnPositionForceClosed( + const ulong ticket, + const XPosition &position, + const string comment // +) +{ + // + eaExpert.HandleOnPositionForceClosed( + ticket, + position, + comment // + ); +} + +/** + * Handle Deals Changes ... + * + * @param count: Integer, Number of Changes ... + */ +void OnDealsChanged(int count) +{ + eaExpert.HandleOnDealsChanged(count); +} + +/** + * Handle Orders Changes ... + * + * @param count: Integer, Number of Changes ... + */ +void OnOrdersChanged(int count) +{ + eaExpert.HandleOnOrdersChanged(count); +} + +/** + * Handle Positions Changes ... + * + * @param count: Integer, Number of Changes ... + */ +void OnPositionsChanged(int count) +{ + eaExpert.HandleOnPositionsChanged(count); +} + +/** + * Handle Position Modified ... + * + * @param ticket: ulong, Position Ticket ... + * @param profit: double, Position Profit ... + * @param comment: string, Comment ... + */ +void OnPositionModified( + const ulong ticket, + const double profit, + const string comment // +) +{ + // + eaExpert.HandleOnPositionModified( + ticket, + profit, + comment // + ); +} + +/** + * Handle Position Partial Closed ... + * + * @param ticket: ulong, Position Ticket ... + * @param profit: double, Position Profit ... + * @param comment: string, Comment ... + */ +void OnPositionPartialClosed( + const ulong ticket, + const double profit, + const string comment // +) +{ + // + eaExpert.HandleOnPositionPartialClosed( + ticket, + profit, + comment // + ); +} + +/** + * Handle Trade State Changed ... + * + * @param state: XOnTradeHandlerState instance ... + */ +void OnTradeStateChanged(const XOnTradeHandlerState &state) +{ + eaExpert.HandleOnTradeStateChanged(state); +} + +// +// Custom Functions ... + +/** + * Validate all Inputs of Expert Adviser ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + string errMessage = ""; + + // + bool isCommonValid = ( + // + eaSlippage > 0 && + eaMagicNumber > 0 + // + ); + if (!isCommonValid) + { + // + errMessage += "common configurations error;" + "\n"; + } + + // + result = + // + // Common ... + isCommonValid && + // + // Otere ... + true + // + ; + + // + if (!result) + { + // + // Since here Logger not Initiallized, we Use Raw Print Command ... + Print(ShortName + " Errors: \n", errMessage); + } + + // + return result; +} + +/** + * Initialize Timer ... + * + * @return ( bool ) + */ +bool InitTimer() +{ + // + bool result = false; + + // + // TODO: Initialize Timer if necessary ... + // result = EventSetTimer(1); + // result = EventSetMillisecondTimer(100); + result = true; + + // + return result; +} + +/** + * Destroy Timer ... + */ +void DestroyTimer() +{ + // + // TODO: Use This ... + // EventKillTimer(); +} + +// \ No newline at end of file diff --git a/BKPS/14040316/Helpers/x-saherelm.x121.xcatb.helper.mq5 b/BKPS/14040316/Helpers/x-saherelm.x121.xcatb.helper.mq5 new file mode 100644 index 0000000..2bff819 --- /dev/null +++ b/BKPS/14040316/Helpers/x-saherelm.x121.xcatb.helper.mq5 @@ -0,0 +1,6693 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XCX121XCatbHelper +// 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.x-helper.class.mq5" +#include "../Libraries/x-saherelm.x-poi.lib.mq5" + +// +// Definitions ... + +// +// Buffers ... +enum ENUM_X121_XCATB_BUFFERS +{ + X121_XCATB_SAR_LINE = 0, + X121_XCATB_SAR_COLOR_LINE = 1, + X121_XCATB_PEAK_LINE = 2, + X121_XCATB_VALE_LINE = 3, + X121_XCATB_PEAK_GOLDEN_LINE = 4, + X121_XCATB_VALE_GOLDEN_LINE = 5, + X121_XCATB_ATR_BAND_UPPER_LINE = 6, + X121_XCATB_ATR_BAND_LOWER_LINE = 7, + X121_XCATB_TREND_LINE = 8, + X121_XCATB_TREND_COLOR_LINE = 9, + X121_XCATB_SBAR_O_LINE = 10, + X121_XCATB_SBAR_H_LINE = 11, + X121_XCATB_SBAR_L_LINE = 12, + X121_XCATB_SBAR_C_LINE = 13, + X121_XCATB_SBAR_COLOR_LINE = 14, + X121_XCATB_HK_SBAR_O_LINE = 15, + X121_XCATB_HK_SBAR_H_LINE = 16, + X121_XCATB_HK_SBAR_L_LINE = 17, + X121_XCATB_HK_SBAR_C_LINE = 18, + X121_XCATB_HK_SBAR_COLOR_LINE = 19, + X121_XCATB_S_HH_LINE = 20, + X121_XCATB_S_LL_LINE = 21, + X121_XCATB_M_HH_LINE = 22, + X121_XCATB_M_LL_LINE = 23, + X121_XCATB_L_HH_LINE = 24, + X121_XCATB_L_LL_LINE = 25, + X121_XCATB_H_HH_LINE = 26, + X121_XCATB_H_LL_LINE = 27, + X121_XCATB_KI_LINE = 28, + X121_XCATB_KI_COLOR_LINE = 29, + X121_XCATB_SAR_STATE_LINE = 30, + X121_XCATB_TREND_STATE_LINE = 31, + X121_XCATB_RSI_LINE = 32, + X121_XCATB_ADX_LINE = 33, + X121_XCATB_ADXP_LINE = 34, + X121_XCATB_ADXN_LINE = 35, + X121_XCATB_DELTA_LINE = 36, + X121_XCATB_DELTA_SIGNAL_LINE = 37, + X121_XCATB_VOLUME_BULLISH_LINE = 38, + X121_XCATB_VOLUME_BEARISH_LINE = 39, + X121_XCATB_VOLUME_VOLUME_BULLISH_SIGNAL_LINE = 40, + X121_XCATB_VOLUME_VOLUME_BEARISH_SIGNAL_LINE = 41, + X121_XCATB_ATR_LINE = 42, + X121_XCATB_ATR_BAND_RAW_UPPER_LINE = 43, + X121_XCATB_ATR_BAND_RAW_LOWER_LINE = 44, + X121_XCATB_HK_BAR_O_LINE = 45, + X121_XCATB_HK_BAR_H_LINE = 46, + X121_XCATB_HK_BAR_L_LINE = 47, + X121_XCATB_HK_BAR_C_LINE = 48, + X121_XCATB_KI_STATE_LINE = 49, +}; + +// +// Input Models ... +struct X121XCatbInputs +{ + // + // Props ... + + // + // Market ... + ENUM_X_PERIOD_METHOD scMethod; // How to Find Short Period + ENUM_TIMEFRAMES scPeriod; // Short Period + ENUM_X_PERIOD_METHOD mcMethod; // How to Find Medium Period + ENUM_TIMEFRAMES mcPeriod; // Medium Period + ENUM_X_PERIOD_METHOD lcMethod; // How to Find Long Period + ENUM_TIMEFRAMES lcPeriod; // Long Period + ENUM_X_PERIOD_METHOD hcMethod; // How to Find Hind Period + ENUM_TIMEFRAMES hcPeriod; // Hind Period + ENUM_X_MARKET_CYCLES appliedCycle; // Applied Cycle + + // + // Presentation ... + bool showBars; // Show Bars + bool showKI; // Show KI + bool showPV; // Show PV + bool showPVGolden; // Show PV Golden + bool showSar; // Show Sar + bool showTrend; // Show Trend + bool showATRBand; // Show ATR Band + bool showSignalBars; // Show Signal Bars + bool showHKSignalBars; // Show Hiken Ashi Signal Bars + + // + double rsiOBLevel; // RSI OB Level + double rsiOSLevel; // RSI OS Level + double adxThreshold; // ADX Threshold + + // + int startCalculationForLastBars; // Calculate Last n Bars + + // + // Constructor(s) ... + X121XCatbInputs() + { + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + // Market ... + scMethod = X_PERIOD_AUTO; // How to Find Short Period + scPeriod = NULL; // Short Period + mcMethod = X_PERIOD_AUTO; // How to Find Medium Period + mcPeriod = NULL; // Medium Period + lcMethod = X_PERIOD_AUTO; // How to Find Long Period + lcPeriod = NULL; // Long Period + hcMethod = X_PERIOD_AUTO; // How to Find Hind Period + hcPeriod = NULL; // Hind Period + appliedCycle = X_MARKET_CYCLE_HIND; // Applied Cycle + + // + // Presentation ... + showBars = false; // Show Bars + showKI = false; // Show KI + showPV = false; // Show PV + showPVGolden = false; // Show PV Golden + showSar = false; // Show Sar + showTrend = false; // Show Trend + showATRBand = false; // Show ATR Band + showSignalBars = false; // Show Signal Bars + showHKSignalBars = false; // Show Hiken Ashi Signal Bars + + // + startCalculationForLastBars = 0; // Calculate Last n Bars + + // + rsiOBLevel = 70.0; // RSI OB Level + rsiOSLevel = 30.0; // RSI OS Level + adxThreshold = 25.0; // ADX Threshold + + // + ZeroMemory(this); + } + + // + // Default ... + void Default() + { + // + // Market ... + scMethod = X_PERIOD_AUTO; // How to Find Short Period + scPeriod = NULL; // Short Period + mcMethod = X_PERIOD_AUTO; // How to Find Medium Period + mcPeriod = NULL; // Medium Period + lcMethod = X_PERIOD_AUTO; // How to Find Long Period + lcPeriod = NULL; // Long Period + hcMethod = X_PERIOD_AUTO; // How to Find Hind Period + hcPeriod = NULL; // Hind Period + appliedCycle = X_MARKET_CYCLE_HIND; // Applied Cycle + + // + // Presentation ... + showBars = true; // Show Bars + showKI = false; // Show KI + showPV = false; // Show PV + showPVGolden = false; // Show PV Golden + showSar = false; // Show Sar + showTrend = false; // Show Trend + showATRBand = false; // Show ATR Band + showSignalBars = false; // Show Signal Bars + showHKSignalBars = false; // Show Hiken Ashi Signal Bars + + // + startCalculationForLastBars = 1500; // Calculate Last n Bars + + // + rsiOBLevel = 70.0; // RSI OB Level + rsiOSLevel = 30.0; // RSI OS Level + adxThreshold = 25.0; // ADX Threshold + } + + // + // Hide all Visible Buffers ... + void Hide() + { + // + showKI = false; + showPV = false; + showSar = false; + showTrend = false; + showATRBand = false; + showPVGolden = false; + showSignalBars = false; + showHKSignalBars = false; + + // + // drawSignals = false; + // drawTriggerBlock = false; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsValid(appliedCycle) && + // + // CYCLES ... + (IsValid(scMethod, scPeriod) && + IsValid(mcMethod, mcPeriod) && + IsValid(lcMethod, lcPeriod) && + IsValid(hcMethod, hcPeriod)) + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + return result; + } + + // +}; + +// +// Conditions ... +struct X121XCatbConditions +{ + // + // Common ... + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + datetime to; + datetime from; + XOHCL bars[]; + + // + // Buffers ... + double kiBuffer[]; + double sarBuffer[]; + double atrBuffer[]; + double rsiBuffer[]; + double adxBuffer[]; + double sHHBuffer[]; + double sLLBuffer[]; + double mHHBuffer[]; + double mLLBuffer[]; + double lHHBuffer[]; + double lLLBuffer[]; + double hHHBuffer[]; + double hLLBuffer[]; + double adxpBuffer[]; + double adxnBuffer[]; + double peakBuffer[]; + double valeBuffer[]; + double deltaBuffer[]; + double trendBuffer[]; + double hkLowBuffer[]; + double hkOpenBuffer[]; + double hkHighBuffer[]; + double hkCloseBuffer[]; + double kiStateBuffer[]; + double sarStateBuffer[]; + double atrUpperBuffer[]; + double atrLowerBuffer[]; + double sBarOpenBuffer[]; + double sBarCloseBuffer[]; + double trendStateBuffer[]; + double hkSBarOpenBuffer[]; + double peakGoldenBuffer[]; + double valeGoldenBuffer[]; + double hkSBarCloseBuffer[]; + double deltaSignalBuffer[]; + double bullishVolumeBuffer[]; + double bearishVolumeBuffer[]; + double bullishVolumeSignalBuffer[]; + double bearishVolumeSignalBuffer[]; + + // + double rsiOBLevel; // Over Bought Level + double rsiOSLevel; // Over Sold Level + double adxThreshold; // Big Movement Threshold + + // + // Conditions ... + + // + // ATR Band ... + + // + bool isATRUp; + bool isATRDown; + + // + bool isClosedOverATRUpper; + bool isClosedUnderATRLower; + + // + // SAR ... + + // + bool isSarBullish; + bool isSarBearish; + + // + bool isSarSwitchedToBullish; + bool isSarSwitchedToBearish; + + // + // KI ... + + // + bool isKIUp; + bool isKIDown; + + // + bool isKIBullish; + bool isKIBearish; + + // + bool isKISameAsLast; + + // + bool isKISwitchedToBullish; + bool isKISwitchedToBearish; + + // + // ADX ... + + // + bool isADXBiggerLast; + bool isADXLesserLast; + + // + bool isADXOverThreshold; + bool isADXUnderThreshold; + + // + bool isDXPBiggerThanDXN; + bool isDXNBiggerThanDXP; + + // + bool isADXBullish; + bool isADXBearish; + + // + bool isADXSwitchedToBullish; + bool isADXSwitchedToBearish; + + // + // RSI ... + + // + bool isRSIBullish; + bool isRSIBearish; + + // + bool isRSISwitchedToBullish; + bool isRSISwitchedToBearish; + + // + bool isRSIOB; + bool isRSIOS; + + // + bool isRSICrossedOverOB; + bool isRSICrossedOverOS; + + // + bool isRSICrossedUnderOB; + bool isRSICrossedUnderOS; + + // + // DELTA ... + + // + bool isDeltaUp; + bool isDeltaDown; + + // + bool isDeltaBullish; + bool isDeltaBearish; + + // + bool isDeltaSwitchedToBullish; + bool isDeltaSwitchedToBearish; + + // + // VOLUME ... + + // + bool isVolumeBullish; + bool isVolumeBearish; + + // + bool isVolumeSwitchedToBullish; + bool isVolumeSwitchedToBearish; + + // + // SIGNAL Bar ... + + // + bool isSBarBullish; + bool isSBarBearish; + + // + bool isSBarSwitchedToBullish; + bool isSBarSwitchedToBearish; + + // + // XHK Signal Bar ... + + // + bool isHKSBarBullish; + bool isHKSBarBearish; + + // + bool isHKSBarSwitchedToBullish; + bool isHKSBarSwitchedToBearish; + + // + // TREND ... + + // + bool isTrendUp; + bool isTrendDown; + + // + bool isTrendBullish; + bool isTrendBearish; + + // + bool isTrendSwitchedToBullish; + bool isTrendSwitchedToBearish; + + // + // PEAK ... + + // + bool isPeakSameLast; + bool isPeakOverLast; + bool isPeakUnderLast; + + // + // VALE ... + + // + bool isValeSameLast; + bool isValeOverLast; + bool isValeUnderLast; + + // + // Constructor ... + X121XCatbConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + // Commons ... + to = NULL; + from = NULL; + time = NULL; + symbol = NULL; + period = NULL; + + // + // Buffers ... + + // + Clean(bars); + Clean(kiBuffer); + Clean(sarBuffer); + Clean(atrBuffer); + Clean(rsiBuffer); + Clean(adxBuffer); + Clean(sHHBuffer); + Clean(sLLBuffer); + Clean(mHHBuffer); + Clean(mLLBuffer); + Clean(lHHBuffer); + Clean(lLLBuffer); + Clean(hHHBuffer); + Clean(hLLBuffer); + Clean(adxpBuffer); + Clean(adxnBuffer); + Clean(peakBuffer); + Clean(valeBuffer); + Clean(deltaBuffer); + Clean(trendBuffer); + Clean(hkLowBuffer); + Clean(hkOpenBuffer); + Clean(hkHighBuffer); + Clean(hkCloseBuffer); + Clean(kiStateBuffer); + Clean(sarStateBuffer); + Clean(atrUpperBuffer); + Clean(atrLowerBuffer); + Clean(sBarOpenBuffer); + Clean(sBarCloseBuffer); + Clean(trendStateBuffer); + Clean(hkSBarOpenBuffer); + Clean(peakGoldenBuffer); + Clean(valeGoldenBuffer); + Clean(hkSBarCloseBuffer); + Clean(deltaSignalBuffer); + Clean(bullishVolumeBuffer); + Clean(bearishVolumeBuffer); + Clean(bullishVolumeSignalBuffer); + Clean(bearishVolumeSignalBuffer); + + // + ArraySetAsSeries(bars, true); + ArraySetAsSeries(kiBuffer, true); + ArraySetAsSeries(sarBuffer, true); + ArraySetAsSeries(atrBuffer, true); + ArraySetAsSeries(rsiBuffer, true); + ArraySetAsSeries(adxBuffer, true); + ArraySetAsSeries(sHHBuffer, true); + ArraySetAsSeries(sLLBuffer, true); + ArraySetAsSeries(mHHBuffer, true); + ArraySetAsSeries(mLLBuffer, true); + ArraySetAsSeries(lHHBuffer, true); + ArraySetAsSeries(lLLBuffer, true); + ArraySetAsSeries(hHHBuffer, true); + ArraySetAsSeries(hLLBuffer, true); + ArraySetAsSeries(adxpBuffer, true); + ArraySetAsSeries(adxnBuffer, true); + ArraySetAsSeries(peakBuffer, true); + ArraySetAsSeries(valeBuffer, true); + ArraySetAsSeries(deltaBuffer, true); + ArraySetAsSeries(trendBuffer, true); + ArraySetAsSeries(hkLowBuffer, true); + ArraySetAsSeries(hkOpenBuffer, true); + ArraySetAsSeries(hkHighBuffer, true); + ArraySetAsSeries(hkCloseBuffer, true); + ArraySetAsSeries(kiStateBuffer, true); + ArraySetAsSeries(sarStateBuffer, true); + ArraySetAsSeries(atrUpperBuffer, true); + ArraySetAsSeries(atrLowerBuffer, true); + ArraySetAsSeries(sBarOpenBuffer, true); + ArraySetAsSeries(sBarCloseBuffer, true); + ArraySetAsSeries(trendStateBuffer, true); + ArraySetAsSeries(hkSBarOpenBuffer, true); + ArraySetAsSeries(peakGoldenBuffer, true); + ArraySetAsSeries(valeGoldenBuffer, true); + ArraySetAsSeries(hkSBarCloseBuffer, true); + ArraySetAsSeries(deltaSignalBuffer, true); + ArraySetAsSeries(bullishVolumeBuffer, true); + ArraySetAsSeries(bearishVolumeBuffer, true); + ArraySetAsSeries(bullishVolumeSignalBuffer, true); + ArraySetAsSeries(bearishVolumeSignalBuffer, true); + + // + rsiOBLevel = 0; // Over Bought Level + rsiOSLevel = 0; // Over Sold Level + adxThreshold = 0; // Big Movement Threshold + + // + // Conditions ... + + // + // Conditions ... + + // + // ATR Band ... + + // + isATRUp = false; + isATRDown = false; + + // + isClosedOverATRUpper = false; + isClosedUnderATRLower = false; + + // + // SAR ... + + // + isSarBullish = false; + isSarBearish = false; + + // + isSarSwitchedToBullish = false; + isSarSwitchedToBearish = false; + + // + // KI ... + + // + isKIUp = false; + isKIDown = false; + + // + isKIBullish = false; + isKIBearish = false; + + // + isKISameAsLast = false; + + // + isKISwitchedToBullish = false; + isKISwitchedToBearish = false; + + // + // ADX ... + + // + isADXBiggerLast = false; + isADXLesserLast = false; + + // + isADXOverThreshold = false; + isADXUnderThreshold = false; + + // + isDXPBiggerThanDXN = false; + isDXNBiggerThanDXP = false; + + // + isADXBullish = false; + isADXBearish = false; + + // + isADXSwitchedToBullish = false; + isADXSwitchedToBearish = false; + + // + // RSI ... + + // + isRSIBullish = false; + isRSIBearish = false; + + // + isRSISwitchedToBullish = false; + isRSISwitchedToBearish = false; + + // + isRSIOB = false; + isRSIOS = false; + + // + isRSICrossedOverOB = false; + isRSICrossedOverOS = false; + + // + isRSICrossedUnderOB = false; + isRSICrossedUnderOS = false; + + // + // DELTA ... + + // + isDeltaUp = false; + isDeltaDown = false; + + // + isDeltaBullish = false; + isDeltaBearish = false; + + // + isDeltaSwitchedToBullish = false; + isDeltaSwitchedToBearish = false; + + // + // VOLUME ... + + // + isVolumeBullish = false; + isVolumeBearish = false; + + // + isVolumeSwitchedToBullish = false; + isVolumeSwitchedToBearish = false; + // + // SIGNAL Bar ... + + // + isSBarBullish = false; + isSBarBearish = false; + + // + isSBarSwitchedToBullish = false; + isSBarSwitchedToBearish = false; + + // + // XHK Signal Bar ... + + // + isHKSBarBullish = false; + isHKSBarBearish = false; + + // + isHKSBarSwitchedToBullish = false; + isHKSBarSwitchedToBearish = false; + + // + // TREND ... + + // + isTrendUp = false; + isTrendDown = false; + + // + isTrendBullish = false; + isTrendBearish = false; + + // + isTrendSwitchedToBullish = false; + isTrendSwitchedToBearish = false; + + // + // PEAK ... + + // + isPeakSameLast = false; + isPeakOverLast = false; + isPeakUnderLast = false; + + // + // VALE ... + + // + isValeSameLast = false; + isValeOverLast = false; + isValeUnderLast = false; + + // + ZeroMemory(this); + } + + /** + * Generate Conditions Scores ... + * + * @param bullishScore: Double, Directional Scores Reference ... + * @param bearishScore: Double, Directional Scores Reference ... + */ + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + // + bullishScore = 0; + bearishScore = 0; + + // + double score = 1; + double minScore = 0.5; + double highScore = 1.5; + + // + // ATR Band ... + + // + if (isATRUp) + { + bullishScore += score; + } + if (isClosedOverATRUpper) + { + bullishScore += score; + } + + // + if (isATRDown) + { + bearishScore += score; + } + if (isClosedUnderATRLower) + { + bearishScore += score; + } + + // + // SAR ... + + // + if (isSarBullish) + { + bullishScore += score; + } + if (isSarSwitchedToBullish) + { + bullishScore += score; + } + + // + if (isSarBearish) + { + bearishScore += score; + } + if (isSarSwitchedToBearish) + { + bearishScore += score; + } + + // + // KI ... + + // + if (isKIUp) + { + bullishScore += score; + } + if (isKIBullish) + { + bullishScore += score; + } + if (isKISwitchedToBullish) + { + bullishScore += score; + } + + // + if (isKIDown) + { + bearishScore += score; + } + if (isKIBearish) + { + bearishScore += score; + } + if (isKISwitchedToBearish) + { + bearishScore += score; + } + + // + // ADX ... + + // + if (isADXBullish) + { + bullishScore += score; + } + if (isADXBiggerLast) + { + bullishScore += score; + } + if (isDXPBiggerThanDXN) + { + bullishScore += score; + } + if (isADXOverThreshold) + { + bullishScore += score; + } + if (isADXSwitchedToBullish) + { + bullishScore += score; + } + + // + if (isADXBearish) + { + bearishScore += score; + } + if (isADXLesserLast) + { + bearishScore += score; + } + if (isDXNBiggerThanDXP) + { + bearishScore += score; + } + if (isADXUnderThreshold) + { + bearishScore += score; + } + if (isADXSwitchedToBearish) + { + bearishScore += score; + } + + // + // RSI ... + + // + if (isRSIOS) + { + bullishScore += score; + } + if (isRSIBullish) + { + bullishScore += score; + } + if (isRSICrossedOverOS) + { + bullishScore += score; + } + if (isRSICrossedOverOB) + { + bullishScore += score; + } + if (isRSISwitchedToBullish) + { + bullishScore += score; + } + + // + if (isRSIOB) + { + bearishScore += score; + } + if (isRSIBearish) + { + bearishScore += score; + } + if (isRSICrossedUnderOB) + { + bearishScore += score; + } + if (isRSICrossedUnderOS) + { + bearishScore += score; + } + if (isRSISwitchedToBearish) + { + bearishScore += score; + } + + // + // DELTA ... + + // + if (isDeltaUp) + { + bullishScore += score; + } + if (isDeltaBullish) + { + bullishScore += score; + } + if (isDeltaSwitchedToBullish) + { + bullishScore += score; + } + + // + if (isDeltaDown) + { + bearishScore += score; + } + if (isDeltaBearish) + { + bearishScore += score; + } + if (isDeltaSwitchedToBearish) + { + bearishScore += score; + } + + // + // VOLUME ... + + // + if (isVolumeBullish) + { + bullishScore += score; + } + if (isVolumeSwitchedToBullish) + { + bullishScore += score; + } + + // + if (isVolumeBearish) + { + bearishScore += score; + } + if (isVolumeSwitchedToBearish) + { + bearishScore += score; + } + + // + // SIGNAL Bar ... + + // + if (isSBarBullish) + { + bullishScore += score; + } + if (isSBarSwitchedToBullish) + { + bullishScore += score; + } + + // + if (isSBarBearish) + { + bearishScore += score; + } + if (isSBarSwitchedToBearish) + { + bearishScore += score; + } + + // + // XHK Signal Bar ... + + // + if (isHKSBarBullish) + { + bullishScore += score; + } + if (isHKSBarSwitchedToBullish) + { + bullishScore += score; + } + + // + if (isHKSBarBearish) + { + bearishScore += score; + } + if (isHKSBarSwitchedToBearish) + { + bearishScore += score; + } + + // + // TREND ... + + // + if (isTrendUp) + { + bullishScore += score; + } + if (isTrendBullish) + { + bullishScore += score; + } + if (isTrendSwitchedToBullish) + { + bullishScore += score; + } + + // + if (isTrendDown) + { + bearishScore += score; + } + if (isTrendBearish) + { + bearishScore += score; + } + if (isTrendSwitchedToBearish) + { + bearishScore += score; + } + + // + // PEAK and VALE ... + + // + if (isValeSameLast) + { + bullishScore += score; + } + if (isValeOverLast) + { + bullishScore += score; + } + if (isPeakOverLast) + { + bullishScore += score; + } + + // + if (isPeakSameLast) + { + bearishScore += score; + } + if (isPeakUnderLast) + { + bearishScore += score; + } + if (isValeUnderLast) + { + bearishScore += score; + } + } + + /** + * Generate Summary String for Represent Conditions State ... + * + * @param onlyCommons: Boolean, Just Generate Only Commons Conditions ... + * @param onlyConditions: Boolean, Just Generate Only Conditions ... + * @param includeScores: Boolean, Attach Scores Representations on Result ... + * @param ignoreFalseConditions: Boolean, Ignore False Conditions on Result ... + * @param separator: String, Separate Lines ... + * + * @return ( string ) + */ + string GenerateSummary( + bool onlyCommons = false, + bool onlyConditions = false, + bool includeScores = true, + bool ignoreFalseConditions = true, + string separator = "\n" // + ) + { + // + string result = NULL; + + // + double bullishScore = 0; + double bearishScore = 0; + GenerateScore( + bullishScore, + bearishScore // + ); + + // + string scoresStr = + // + "Scores: " + separator + + "---------------" + separator + + "Bullish: " + ToString(bullishScore) + separator + + "Bearish: " + ToString(bearishScore) + separator + + "" + // + ; + + // + string commonStr = GenerateSpecifiedCommonSummary( + this, + separator, + includeScores // + ); + + // + string conditionsStr = + // + "-----------------------" + separator + + "XCATB: " + separator + + "-----------------------" + separator + + "" + separator + + // + "-----------------------" + separator + + "ATR Band: " + separator + + "-----------------------" + separator + + ToString("isATRUp", isATRUp, ignoreFalseConditions, separator) + + ToString("isATRDown", isATRDown, ignoreFalseConditions, separator) + + ToString("isClosedOverATRUpper", isClosedOverATRUpper, ignoreFalseConditions, separator) + + ToString("isClosedUnderATRLower", isClosedUnderATRLower, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "KI: " + separator + + "-----------------------" + separator + + ToString("isKIUp", isKIUp, ignoreFalseConditions, separator) + + ToString("isKIDown", isKIDown, ignoreFalseConditions, separator) + + ToString("isKIBullish", isKIBullish, ignoreFalseConditions, separator) + + ToString("isKIBearish", isKIBearish, ignoreFalseConditions, separator) + + ToString("isKISameAsLast", isKISameAsLast, ignoreFalseConditions, separator) + + ToString("isKISwitchedToBullish", isKISwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isKISwitchedToBearish", isKISwitchedToBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "SAR: " + separator + + "-----------------------" + separator + + ToString("isSarBullish", isSarBullish, ignoreFalseConditions, separator) + + ToString("isSarBearish", isSarBearish, ignoreFalseConditions, separator) + + ToString("isSarSwitchedToBullish", isSarSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isSarSwitchedToBearish", isSarSwitchedToBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "ADX: " + separator + + "-----------------------" + separator + + ToString("isADXBiggerLast", isADXBiggerLast, ignoreFalseConditions, separator) + + ToString("isADXLesserLast", isADXLesserLast, ignoreFalseConditions, separator) + + ToString("isADXOverThreshold", isADXOverThreshold, ignoreFalseConditions, separator) + + ToString("isADXUnderThreshold", isADXUnderThreshold, ignoreFalseConditions, separator) + + ToString("isDXPBiggerThanDXN", isDXPBiggerThanDXN, ignoreFalseConditions, separator) + + ToString("isDXNBiggerThanDXP", isDXNBiggerThanDXP, ignoreFalseConditions, separator) + + ToString("isADXBullish", isADXBullish, ignoreFalseConditions, separator) + + ToString("isADXBearish", isADXBearish, ignoreFalseConditions, separator) + + ToString("isADXSwitchedToBullish", isADXSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isADXSwitchedToBearish", isADXSwitchedToBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "RSI: " + separator + + "-----------------------" + separator + + ToString("isRSIBullish", isRSIBullish, ignoreFalseConditions, separator) + + ToString("isRSIBearish", isRSIBearish, ignoreFalseConditions, separator) + + ToString("isRSISwitchedToBullish", isRSISwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isRSISwitchedToBearish", isRSISwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isRSIOB", isRSIOB, ignoreFalseConditions, separator) + + ToString("isRSIOS", isRSIOS, ignoreFalseConditions, separator) + + ToString("isRSICrossedOverOB", isRSICrossedOverOB, ignoreFalseConditions, separator) + + ToString("isRSICrossedOverOS", isRSICrossedOverOS, ignoreFalseConditions, separator) + + ToString("isRSICrossedUnderOB", isRSICrossedUnderOB, ignoreFalseConditions, separator) + + ToString("isRSICrossedUnderOS", isRSICrossedUnderOS, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "DELTA: " + separator + + "-----------------------" + separator + + ToString("isDeltaUp", isDeltaUp, ignoreFalseConditions, separator) + + ToString("isDeltaDown", isDeltaDown, ignoreFalseConditions, separator) + + ToString("isDeltaBullish", isDeltaBullish, ignoreFalseConditions, separator) + + ToString("isDeltaBearish", isDeltaBearish, ignoreFalseConditions, separator) + + ToString("isDeltaSwitchedToBullish", isDeltaSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isDeltaSwitchedToBearish", isDeltaSwitchedToBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "VOLUME: " + separator + + "-----------------------" + separator + + ToString("isVolumeBullish", isVolumeBullish, ignoreFalseConditions, separator) + + ToString("isVolumeBearish", isVolumeBearish, ignoreFalseConditions, separator) + + ToString("isVolumeSwitchedToBullish", isVolumeSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isVolumeSwitchedToBearish", isVolumeSwitchedToBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "SIGNAL Bar: " + separator + + "-----------------------" + separator + + ToString("isSBarBullish", isSBarBullish, ignoreFalseConditions, separator) + + ToString("isSBarBearish", isSBarBearish, ignoreFalseConditions, separator) + + ToString("isSBarSwitchedToBullish", isSBarSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isSBarSwitchedToBearish", isSBarSwitchedToBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "XHK Signal Bar: " + separator + + "-----------------------" + separator + + ToString("isHKSBarBullish", isHKSBarBullish, ignoreFalseConditions, separator) + + ToString("isHKSBarBearish", isHKSBarBearish, ignoreFalseConditions, separator) + + ToString("isHKSBarSwitchedToBullish", isHKSBarSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isHKSBarSwitchedToBearish", isHKSBarSwitchedToBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "Trend: " + separator + + "-----------------------" + separator + + ToString("isTrendUp", isTrendUp, ignoreFalseConditions, separator) + + ToString("isTrendDown", isTrendDown, ignoreFalseConditions, separator) + + ToString("isTrendBullish", isTrendBullish, ignoreFalseConditions, separator) + + ToString("isTrendBearish", isTrendBearish, ignoreFalseConditions, separator) + + ToString("isTrendSwitchedToBullish", isTrendSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isTrendSwitchedToBearish", isTrendSwitchedToBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "Peak: " + separator + + "-----------------------" + separator + + ToString("isPeakSameLast", isPeakSameLast, ignoreFalseConditions, separator) + + ToString("isPeakOverLast", isPeakOverLast, ignoreFalseConditions, separator) + + ToString("isPeakUnderLast", isPeakUnderLast, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "Vale: " + separator + + "-----------------------" + separator + + ToString("isValeSameLast", isValeSameLast, ignoreFalseConditions, separator) + + ToString("isValeOverLast", isValeOverLast, ignoreFalseConditions, separator) + + ToString("isValeUnderLast", isValeUnderLast, ignoreFalseConditions, separator) + + "" + // + ; + + // + result = + // + "[" + GetTag() + "]" + separator + + (onlyConditions + ? "" + : commonStr) + + (!includeScores + ? "" + : scoresStr) + + " " + separator + + (onlyCommons + ? "" + : conditionsStr) + + "" + // + ; + + // + return result; + } + + /** + * Retrieve nique Tag Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + return GetTypeName(this); + } + + // +}; + +// +// Class ... +class XCX121XCatbHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + + // + // Buffers ... + double kiBuffer[]; + double sarBuffer[]; + double atrBuffer[]; + double rsiBuffer[]; + double adxBuffer[]; + double sHHBuffer[]; + double sLLBuffer[]; + double mHHBuffer[]; + double mLLBuffer[]; + double lHHBuffer[]; + double lLLBuffer[]; + double hHHBuffer[]; + double hLLBuffer[]; + double adxpBuffer[]; + double adxnBuffer[]; + double peakBuffer[]; + double valeBuffer[]; + double deltaBuffer[]; + double trendBuffer[]; + double hkLowBuffer[]; + double hkOpenBuffer[]; + double hkHighBuffer[]; + double hkCloseBuffer[]; + double kiStateBuffer[]; + double sarStateBuffer[]; + double atrUpperBuffer[]; + double atrLowerBuffer[]; + double sBarOpenBuffer[]; + double sBarCloseBuffer[]; + double trendStateBuffer[]; + double hkSBarOpenBuffer[]; + double peakGoldenBuffer[]; + double valeGoldenBuffer[]; + double hkSBarCloseBuffer[]; + double deltaSignalBuffer[]; + double bullishVolumeBuffer[]; + double bearishVolumeBuffer[]; + double bullishVolumeSignalBuffer[]; + double bearishVolumeSignalBuffer[]; + + // + // Market Shift ... + + // + // SAR ... + XDirectionShift lastSarBullish; + XDirectionShift lastSarBearish; + + // + // TREND ... + XDirectionShift lastTrendBullish; + XDirectionShift lastTrendBearish; + + // + // DELTA ... + XDirectionShift lastDeltaBullish; + XDirectionShift lastDeltaBearish; + + // + // VOLUME ... + XDirectionShift lastVolumeBullish; + XDirectionShift lastVolumeBearish; + + // + // SIGNAL Bar ... + XDirectionShift lastSignalBarBullish; + XDirectionShift lastSignalBarBearish; + + // + // XHK SIGNAL Bar ... + XDirectionShift lastHKSignalBarBullish; + XDirectionShift lastHKSignalBarBearish; + + // + // Constructors ... + XCX121XCatbHelper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCX121XCatbHelper() + { + // + mInputs.Clean(); + + // + Clean(sarBuffer); + Clean(atrBuffer); + Clean(rsiBuffer); + Clean(adxBuffer); + Clean(sHHBuffer); + Clean(sLLBuffer); + Clean(mHHBuffer); + Clean(mLLBuffer); + Clean(lHHBuffer); + Clean(lLLBuffer); + Clean(hHHBuffer); + Clean(hLLBuffer); + Clean(adxpBuffer); + Clean(adxnBuffer); + Clean(peakBuffer); + Clean(valeBuffer); + Clean(deltaBuffer); + Clean(trendBuffer); + Clean(hkLowBuffer); + Clean(hkOpenBuffer); + Clean(hkHighBuffer); + Clean(hkCloseBuffer); + Clean(sarStateBuffer); + Clean(atrUpperBuffer); + Clean(atrLowerBuffer); + Clean(sBarOpenBuffer); + Clean(sBarCloseBuffer); + Clean(trendStateBuffer); + Clean(hkSBarOpenBuffer); + Clean(peakGoldenBuffer); + Clean(valeGoldenBuffer); + Clean(hkSBarCloseBuffer); + Clean(deltaSignalBuffer); + Clean(bullishVolumeBuffer); + Clean(bearishVolumeBuffer); + Clean(bullishVolumeSignalBuffer); + Clean(bearishVolumeSignalBuffer); + } + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + X121XCatbInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + ArraySetAsSeries(kiBuffer, true); + ArraySetAsSeries(sarBuffer, true); + ArraySetAsSeries(atrBuffer, true); + ArraySetAsSeries(rsiBuffer, true); + ArraySetAsSeries(adxBuffer, true); + ArraySetAsSeries(sHHBuffer, true); + ArraySetAsSeries(sLLBuffer, true); + ArraySetAsSeries(mHHBuffer, true); + ArraySetAsSeries(mLLBuffer, true); + ArraySetAsSeries(lHHBuffer, true); + ArraySetAsSeries(lLLBuffer, true); + ArraySetAsSeries(hHHBuffer, true); + ArraySetAsSeries(hLLBuffer, true); + ArraySetAsSeries(adxpBuffer, true); + ArraySetAsSeries(adxnBuffer, true); + ArraySetAsSeries(peakBuffer, true); + ArraySetAsSeries(valeBuffer, true); + ArraySetAsSeries(deltaBuffer, true); + ArraySetAsSeries(trendBuffer, true); + ArraySetAsSeries(hkLowBuffer, true); + ArraySetAsSeries(hkOpenBuffer, true); + ArraySetAsSeries(hkHighBuffer, true); + ArraySetAsSeries(hkCloseBuffer, true); + ArraySetAsSeries(kiStateBuffer, true); + ArraySetAsSeries(sarStateBuffer, true); + ArraySetAsSeries(atrUpperBuffer, true); + ArraySetAsSeries(atrLowerBuffer, true); + ArraySetAsSeries(sBarOpenBuffer, true); + ArraySetAsSeries(sBarCloseBuffer, true); + ArraySetAsSeries(trendStateBuffer, true); + ArraySetAsSeries(hkSBarOpenBuffer, true); + ArraySetAsSeries(peakGoldenBuffer, true); + ArraySetAsSeries(valeGoldenBuffer, true); + ArraySetAsSeries(hkSBarCloseBuffer, true); + ArraySetAsSeries(deltaSignalBuffer, true); + ArraySetAsSeries(bullishVolumeBuffer, true); + ArraySetAsSeries(bearishVolumeBuffer, true); + ArraySetAsSeries(bullishVolumeSignalBuffer, true); + ArraySetAsSeries(bearishVolumeSignalBuffer, true); + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.xcatb", + "", // Market ... + mInputs.scMethod, + mInputs.scPeriod, + mInputs.mcMethod, + mInputs.mcPeriod, + mInputs.lcMethod, + mInputs.lcPeriod, + mInputs.hcMethod, + mInputs.hcPeriod, + mInputs.appliedCycle, + "", // Presentation ... + mInputs.showBars, + mInputs.showKI, + mInputs.showPV, + mInputs.showPVGolden, + mInputs.showSar, + mInputs.showTrend, + mInputs.showATRBand, + mInputs.showSignalBars, + mInputs.showHKSignalBars, + mInputs.startCalculationForLastBars + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + void Check(int barIndex = 0) + { + // + bool has = false; + + // + bool isBullish = false; + bool isBearish = false; + + // + barIndex = NormalizeInt(barIndex, 0); + + // + X121XCatbConditions conditions; + has = GetConditions( + conditions, + barIndex, + 4 // + ); + if (!has) + { + // + conditions.Clean(); + return; + } + + // + // Checking Shifts ... + + // + // SAR ... + + // + isBullish = conditions.isSarSwitchedToBullish; + isBearish = conditions.isSarSwitchedToBearish; + + // + has = isBullish || + isBearish; + if (has) + { + // + // Bullish ... + has = + isBullish && + (!lastSarBullish.IsValid() + ? true + : lastSarBullish.at < conditions.bars[1].time); + if (has) + { + // + lastSarBullish.Clean(); + + // + lastSarBullish.type = "SAR"; + lastSarBullish.symbol = conditions.symbol; + lastSarBullish.period = conditions.period; + lastSarBullish.at = conditions.bars[1].time; + lastSarBullish.shiftTo = X_DIRECTION_BULLISH; + lastSarBullish.after = conditions.sarBuffer[1]; + lastSarBullish.before = conditions.sarBuffer[2]; + } + + // + // Bearish ... + has = + isBearish && + (!lastSarBearish.IsValid() + ? true + : lastSarBearish.at < conditions.bars[1].time); + if (has) + { + // + lastSarBearish.Clean(); + + // + lastSarBearish.type = "SAR"; + lastSarBearish.symbol = conditions.symbol; + lastSarBearish.period = conditions.period; + lastSarBearish.at = conditions.bars[1].time; + lastSarBearish.shiftTo = X_DIRECTION_BEARISH; + lastSarBearish.after = conditions.sarBuffer[1]; + lastSarBearish.before = conditions.sarBuffer[2]; + } + } + + // + // TREND ... + + // + isBullish = conditions.isTrendSwitchedToBullish; + isBearish = conditions.isTrendSwitchedToBearish; + + // + has = isBullish || + isBearish; + if (has) + { + // + // Bullish ... + has = + isBullish && + (!lastTrendBullish.IsValid() + ? true + : lastTrendBullish.at < conditions.bars[1].time); + if (has) + { + // + lastTrendBullish.Clean(); + + // + lastTrendBullish.type = "TREND"; + lastTrendBullish.symbol = conditions.symbol; + lastTrendBullish.period = conditions.period; + lastTrendBullish.at = conditions.bars[1].time; + lastTrendBullish.shiftTo = X_DIRECTION_BULLISH; + lastTrendBullish.after = conditions.trendBuffer[1]; + lastTrendBullish.before = conditions.trendBuffer[2]; + } + + // + // Bearish ... + has = + isBearish && + (!lastTrendBearish.IsValid() + ? true + : lastTrendBearish.at < conditions.bars[1].time); + if (has) + { + // + lastTrendBearish.Clean(); + + // + lastTrendBearish.type = "TREND"; + lastTrendBearish.symbol = conditions.symbol; + lastTrendBearish.period = conditions.period; + lastTrendBearish.at = conditions.bars[1].time; + lastTrendBearish.shiftTo = X_DIRECTION_BEARISH; + lastTrendBearish.after = conditions.trendBuffer[1]; + lastTrendBearish.before = conditions.trendBuffer[2]; + } + } + + // + // DELTA ... + + // + isBullish = + // + ( + // + // Delta is Up ... + conditions.deltaBuffer[1] > conditions.deltaBuffer[2] && + // + // Delta Signal is Up ... + conditions.deltaSignalBuffer[1] > conditions.deltaSignalBuffer[2] && + // + // Delta Crossed Over Delta ... + conditions.deltaBuffer[1] > conditions.deltaSignalBuffer[1] && + conditions.deltaBuffer[2] <= conditions.deltaSignalBuffer[2] + // + ) + // + ; + + // + isBearish = + // + ( + // + // Delta is Down ... + conditions.deltaBuffer[1] < conditions.deltaBuffer[2] && + // + // Delta Signal is Down ... + conditions.deltaSignalBuffer[1] < conditions.deltaSignalBuffer[2] && + // + // Delta Crossed Under Delta Signal ... + conditions.deltaBuffer[1] < conditions.deltaSignalBuffer[1] && + conditions.deltaBuffer[2] >= conditions.deltaSignalBuffer[2] + // + ) + // + ; + + // + has = isBullish || + isBearish; + if (has) + { + // + // Bullish ... + has = + isBullish && + (!lastDeltaBullish.IsValid() + ? true + : lastDeltaBullish.at < conditions.bars[1].time); + if (has) + { + // + lastDeltaBullish.Clean(); + + // + lastDeltaBullish.type = "DELTA"; + lastDeltaBullish.symbol = conditions.symbol; + lastDeltaBullish.period = conditions.period; + lastDeltaBullish.at = conditions.bars[1].time; + lastDeltaBullish.shiftTo = X_DIRECTION_BULLISH; + lastDeltaBullish.after = conditions.bars[1].close; + lastDeltaBullish.before = conditions.bars[2].close; + } + + // + // Bearish ... + has = + isBearish && + (!lastDeltaBearish.IsValid() + ? true + : lastDeltaBearish.at < conditions.bars[1].time); + if (has) + { + // + lastDeltaBearish.Clean(); + + // + lastDeltaBearish.type = "DELTA"; + lastDeltaBearish.symbol = conditions.symbol; + lastDeltaBearish.period = conditions.period; + lastDeltaBearish.at = conditions.bars[1].time; + lastDeltaBearish.shiftTo = X_DIRECTION_BEARISH; + lastDeltaBearish.after = conditions.bars[1].close; + lastDeltaBearish.before = conditions.bars[2].close; + } + } + + // + // VOLUME ... + + // + isBullish = + // + ( + // + // Volume is Up ... + conditions.bullishVolumeBuffer[1] > conditions.bullishVolumeBuffer[2] && + // + // Volume Signal is Up ... + conditions.bullishVolumeSignalBuffer[1] > conditions.bullishVolumeSignalBuffer[2] && + // + // Volume Signals Crossed Over ... + conditions.bullishVolumeSignalBuffer[1] > conditions.bearishVolumeSignalBuffer[1] && + conditions.bullishVolumeSignalBuffer[2] <= conditions.bearishVolumeSignalBuffer[2] + // + ) + // + ; + + // + isBullish = + // + ( + // + // Volume is Up ... + conditions.bearishVolumeBuffer[1] > conditions.bearishVolumeBuffer[2] && + // + // Volume Signal is Up ... + conditions.bearishVolumeSignalBuffer[1] > conditions.bearishVolumeSignalBuffer[2] && + // + // Volume Signals Crossed Over ... + conditions.bearishVolumeSignalBuffer[1] > conditions.bullishVolumeSignalBuffer[1] && + conditions.bearishVolumeSignalBuffer[2] <= conditions.bullishVolumeSignalBuffer[2] + // + ) + // + ; + + // + has = isBullish || + isBearish; + if (has) + { + // + // Bullish ... + has = + isBullish && + (!lastVolumeBullish.IsValid() + ? true + : lastVolumeBullish.at < conditions.bars[1].time); + if (has) + { + // + lastVolumeBullish.Clean(); + + // + lastVolumeBullish.type = "VOLUME"; + lastVolumeBullish.symbol = conditions.symbol; + lastVolumeBullish.period = conditions.period; + lastVolumeBullish.at = conditions.bars[1].time; + lastVolumeBullish.shiftTo = X_DIRECTION_BULLISH; + lastVolumeBullish.after = conditions.bars[1].close; + lastVolumeBullish.before = conditions.bars[2].close; + } + + // + // Bearish ... + has = + isBearish && + (!lastVolumeBearish.IsValid() + ? true + : lastVolumeBearish.at < conditions.bars[1].time); + if (has) + { + // + lastVolumeBearish.Clean(); + + // + lastVolumeBearish.type = "VOLUME"; + lastVolumeBearish.symbol = conditions.symbol; + lastVolumeBearish.period = conditions.period; + lastVolumeBearish.at = conditions.bars[1].time; + lastVolumeBearish.shiftTo = X_DIRECTION_BEARISH; + lastVolumeBearish.after = conditions.bars[1].close; + lastVolumeBearish.before = conditions.bars[2].close; + } + } + + // + // SIGNAL Bar ... + + // + isBullish = conditions.isSBarSwitchedToBullish; + isBearish = conditions.isSBarSwitchedToBearish; + + // + has = isBullish || + isBearish; + if (has) + { + // + // Bullish ... + has = + isBullish && + (!lastSignalBarBullish.IsValid() + ? true + : lastSignalBarBullish.at < conditions.bars[1].time); + if (has) + { + // + lastSignalBarBullish.Clean(); + + // + lastSignalBarBullish.type = "SIGNALBAR"; + lastSignalBarBullish.symbol = conditions.symbol; + lastSignalBarBullish.period = conditions.period; + lastSignalBarBullish.at = conditions.bars[1].time; + lastSignalBarBullish.shiftTo = X_DIRECTION_BULLISH; + lastSignalBarBullish.after = conditions.sBarCloseBuffer[1]; + lastSignalBarBullish.before = conditions.sBarCloseBuffer[2]; + } + + // + // Bearish ... + has = + isBearish && + (!lastSignalBarBearish.IsValid() + ? true + : lastSignalBarBearish.at < conditions.bars[1].time); + if (has) + { + // + lastSignalBarBearish.Clean(); + + // + lastSignalBarBearish.type = "SIGNALBAR"; + lastSignalBarBearish.symbol = conditions.symbol; + lastSignalBarBearish.period = conditions.period; + lastSignalBarBearish.at = conditions.bars[1].time; + lastSignalBarBearish.shiftTo = X_DIRECTION_BEARISH; + lastSignalBarBearish.after = conditions.sBarCloseBuffer[1]; + lastSignalBarBearish.before = conditions.sBarCloseBuffer[2]; + } + } + + // + // HKSIGNAL Bar ... + + // + isBullish = conditions.isHKSBarSwitchedToBullish; + isBearish = conditions.isHKSBarSwitchedToBearish; + + // + has = isBullish || + isBearish; + if (has) + { + // + // Bullish ... + has = + isBullish && + (!lastHKSignalBarBullish.IsValid() + ? true + : lastHKSignalBarBullish.at < conditions.bars[1].time); + if (has) + { + // + lastHKSignalBarBullish.Clean(); + + // + lastHKSignalBarBullish.type = "HKSIGNALBAR"; + lastHKSignalBarBullish.symbol = conditions.symbol; + lastHKSignalBarBullish.period = conditions.period; + lastHKSignalBarBullish.at = conditions.bars[1].time; + lastHKSignalBarBullish.shiftTo = X_DIRECTION_BULLISH; + lastHKSignalBarBullish.after = conditions.hkSBarCloseBuffer[1]; + lastHKSignalBarBullish.before = conditions.hkSBarCloseBuffer[2]; + } + + // + // Bearish ... + has = + isBearish && + (!lastHKSignalBarBearish.IsValid() + ? true + : lastHKSignalBarBearish.at < conditions.bars[1].time); + if (has) + { + // + lastHKSignalBarBearish.Clean(); + + // + lastHKSignalBarBearish.type = "HKSIGNALBAR"; + lastHKSignalBarBearish.symbol = conditions.symbol; + lastHKSignalBarBearish.period = conditions.period; + lastHKSignalBarBearish.at = conditions.bars[1].time; + lastHKSignalBarBearish.shiftTo = X_DIRECTION_BEARISH; + lastHKSignalBarBearish.after = conditions.hkSBarCloseBuffer[1]; + lastHKSignalBarBearish.before = conditions.hkSBarCloseBuffer[2]; + } + } + + // + // Cleanup Resources ... + + // + conditions.Clean(); + } + + // + // Inputs ... + + // + X121XCatbInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + X121XCatbInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Readers ... + + // + // Readers ... + + // + // SAR ... + + // + double GetKI( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(kiBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return kiBuffer[barIndex]; + } + + // + int CopyKI( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + kiBuffer, + buffer, + forceClean + // + ); + } + + // + // KI State ... + + // + double GetKIState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(kiStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return kiStateBuffer[barIndex]; + } + + // + int CopyKIState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + kiStateBuffer, + buffer, + forceClean + // + ); + } + + // + // SAR ... + + // + double GetSar( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(sarBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return sarBuffer[barIndex]; + } + + // + 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(start); + + // + // Copy Items ... + return Copy( + 0, + count, + sarBuffer, + buffer, + forceClean + // + ); + } + + // + // SAR State ... + + // + double GetSarState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(sarStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return sarStateBuffer[barIndex]; + } + + // + int CopySarState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + sarStateBuffer, + buffer, + forceClean + // + ); + } + + // + // PEAK ... + + // + double GetPeak( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(peakBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return peakBuffer[barIndex]; + } + + // + 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(start); + + // + // Copy Items ... + return Copy( + 0, + count, + peakBuffer, + buffer, + forceClean + // + ); + } + + // + // VALE ... + + // + double GetVale( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(valeBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return valeBuffer[barIndex]; + } + + // + 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(start); + + // + // Copy Items ... + return Copy( + 0, + count, + valeBuffer, + buffer, + forceClean + // + ); + } + + // + // PEAK Golden ... + + // + double GetPeakGolden( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(peakGoldenBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return peakGoldenBuffer[barIndex]; + } + + // + int CopyPeakGolden( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + peakGoldenBuffer, + buffer, + forceClean + // + ); + } + + // + // VALE Golden ... + + // + double GetValeGolden( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(valeGoldenBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return valeGoldenBuffer[barIndex]; + } + + // + int CopyValeGolden( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + valeGoldenBuffer, + buffer, + forceClean + // + ); + } + + // + // ATR ... + + // + double GetATR( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(atrBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return atrBuffer[barIndex]; + } + + // + 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(start); + + // + // Copy Items ... + return Copy( + 0, + count, + atrBuffer, + buffer, + forceClean + // + ); + } + + // + // ATR Band Upper ... + + // + double GetATRUpper( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(atrUpperBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return atrUpperBuffer[barIndex]; + } + + // + int CopyATRUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + atrUpperBuffer, + buffer, + forceClean + // + ); + } + + // + // ATR Band Lower ... + + // + double GetATRLower( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(atrLowerBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return atrLowerBuffer[barIndex]; + } + + // + int CopyATRLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + atrLowerBuffer, + buffer, + forceClean + // + ); + } + + // + // TREND ... + + // + double GetTrend( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(trendBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return trendBuffer[barIndex]; + } + + // + 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(start); + + // + // Copy Items ... + return Copy( + 0, + count, + trendBuffer, + buffer, + forceClean + // + ); + } + + // + // TREND State ... + + // + double GetTrendState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(trendStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return trendStateBuffer[barIndex]; + } + + // + int CopyTrendState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + trendStateBuffer, + buffer, + forceClean + // + ); + } + + // + // SIGNAL Bar ... + + // + // OPEN ... + + // + double GetSBarOpen( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(sBarOpenBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return sBarOpenBuffer[barIndex]; + } + + // + int CopySBarOpen( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + sBarOpenBuffer, + buffer, + forceClean + // + ); + } + + // + // CLOSE ... + + // + double GetSBarClose( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(sBarCloseBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return sBarCloseBuffer[barIndex]; + } + + // + int CopySBarClose( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + sBarCloseBuffer, + buffer, + forceClean + // + ); + } + + // + // XHK SIGNAL Bar ... + + // + // OPEN ... + + // + double GetHKSBarOpen( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hkSBarOpenBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hkSBarOpenBuffer[barIndex]; + } + + // + int CopyHKSBarOpen( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hkSBarOpenBuffer, + buffer, + forceClean + // + ); + } + + // + // CLOSE ... + + // + double GetHKSBarClose( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hkSBarCloseBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hkSBarCloseBuffer[barIndex]; + } + + // + int CopyHKSBarClose( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hkSBarCloseBuffer, + buffer, + forceClean + // + ); + } + + // + // CYCLES Range ... + + // + // SHORT ... + + // + // HH ... + + // + double GetSHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(sHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return sHHBuffer[barIndex]; + } + + // + int CopySHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + sHHBuffer, + buffer, + forceClean + // + ); + } + + // + // LL ... + + // + double GetSLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(sLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return sLLBuffer[barIndex]; + } + + // + int CopySLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + sLLBuffer, + buffer, + forceClean + // + ); + } + + // + // MEDIUM ... + + // + // HH ... + + // + double GetMHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(mHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return mHHBuffer[barIndex]; + } + + // + int CopyMHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + mHHBuffer, + buffer, + forceClean + // + ); + } + + // + // LL ... + + // + double GetMLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(mLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return mLLBuffer[barIndex]; + } + + // + int CopyMLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + mLLBuffer, + buffer, + forceClean + // + ); + } + + // + // LONG ... + + // + // HH ... + + // + double GetLHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(lHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return lHHBuffer[barIndex]; + } + + // + int CopyLHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + lHHBuffer, + buffer, + forceClean + // + ); + } + + // + // LL ... + + // + double GetLLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(lLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return lLLBuffer[barIndex]; + } + + // + int CopyLLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + lLLBuffer, + buffer, + forceClean + // + ); + } + + // + // HIND ... + + // + // HH ... + + // + double GetHHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hHHBuffer[barIndex]; + } + + // + int CopyHHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hHHBuffer, + buffer, + forceClean + // + ); + } + + // + // LL ... + + // + double GetHLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hLLBuffer[barIndex]; + } + + // + int CopyHLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hLLBuffer, + buffer, + forceClean + // + ); + } + + // + // ADX ... + + // + double GetADX( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(adxBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return adxBuffer[barIndex]; + } + + // + int CopyADX( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + adxBuffer, + buffer, + forceClean + // + ); + } + + // + // ADXP ... + + // + double GetADXP( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(adxpBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return adxpBuffer[barIndex]; + } + + // + int CopyADXP( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + adxpBuffer, + buffer, + forceClean + // + ); + } + + // + // ADXN ... + + // + double GetADXN( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(adxnBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return adxnBuffer[barIndex]; + } + + // + int CopyADXN( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + adxnBuffer, + buffer, + forceClean + // + ); + } + + // + // DELTA ... + + // + double GetDelta( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(deltaBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return deltaBuffer[barIndex]; + } + + // + int CopyDelta( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + deltaBuffer, + buffer, + forceClean + // + ); + } + + // + // DELTA Signal ... + + // + double GetDeltaSignal( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(deltaSignalBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return deltaSignalBuffer[barIndex]; + } + + // + int CopyDeltaSignal( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + deltaSignalBuffer, + buffer, + forceClean + // + ); + } + + // + // VOLUME ... + + // + // Bullish ... + + // + double GetBullishVolume( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(bullishVolumeBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return bullishVolumeBuffer[barIndex]; + } + + // + int CopyBullishVolume( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + bullishVolumeBuffer, + buffer, + forceClean + // + ); + } + + // + // Bearish ... + + // + double GetBearishVolume( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(bearishVolumeBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return bearishVolumeBuffer[barIndex]; + } + + // + int CopyBearishVolume( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + bearishVolumeBuffer, + buffer, + forceClean + // + ); + } + + // + // VOLUME Signal ... + + // + // Bullish ... + + // + double GetBullishVolumeSignal( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(bullishVolumeSignalBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return bullishVolumeSignalBuffer[barIndex]; + } + + // + int CopyBullishVolumeSignal( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + bullishVolumeSignalBuffer, + buffer, + forceClean + // + ); + } + + // + // Bearish ... + + // + double GetBearishVolumeSignal( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(bearishVolumeSignalBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return bearishVolumeSignalBuffer[barIndex]; + } + + // + int CopyBearishVolumeSignal( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + bearishVolumeSignalBuffer, + buffer, + forceClean + // + ); + } + + // + // XHK ... + + // + // Open ... + + // + double GetHKOpen( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hkOpenBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hkOpenBuffer[barIndex]; + } + + // + int CopyHKOpen( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hkOpenBuffer, + buffer, + forceClean + // + ); + } + + // + // High ... + + // + double GetHKHigh( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hkHighBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hkHighBuffer[barIndex]; + } + + // + int CopyHKHigh( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hkHighBuffer, + buffer, + forceClean + // + ); + } + + // + // Low ... + + // + double GetHKLow( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hkLowBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hkLowBuffer[barIndex]; + } + + // + int CopyHKLow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hkLowBuffer, + buffer, + forceClean + // + ); + } + + // + // Close ... + + // + double GetHKClose( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(hkCloseBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hkCloseBuffer[barIndex]; + } + + // + int CopyHKClose( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(start); + + // + // Copy Items ... + return Copy( + 0, + count, + hkCloseBuffer, + buffer, + forceClean + // + ); + } + + // + // RSI ... + + // + double GetRSI( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(barIndex); + + // + int count = ArraySize(rsiBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return rsiBuffer[barIndex]; + } + + // + 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(start); + + // + // Copy Items ... + return Copy( + 0, + count, + rsiBuffer, + buffer, + forceClean + // + ); + } + + // + // Tools ... + + // + void Update( + int barIndex // Bar Index + ) + { + // + Calculate(barIndex); + } + + // + void Free() override + { + Cleanup(10); + } + + // + bool GetConditions( + X121XCatbConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = true; + + // + if (loopback < 5) + { + loopback = 5; + } + + // + conditions.Clean(); + + // + conditions.symbol = mSymbol; + conditions.period = mPeriod; + conditions.time = TimeCurrent(); + + // + // Filling Bars ... + int barsCount = GetBars( + conditions.bars, + mSymbol, + mPeriod, + barIndex, + loopback // + ); + result = barsCount == loopback; + if (!result) + { + // + conditions.Clean(); + + // + return result; + } + + // + int zIDX = 0; + int cIDX = 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + int p3IDX = p2IDX + 1; + int p4IDX = p3IDX + 1; + + // + conditions.to = conditions.bars[0].time; + conditions.from = conditions.bars[ArraySize(conditions.bars) - 1].time; + + // + int zIndex = barIndex; + + // + // Buffers ... + + CopyKI( + zIndex, + loopback, + conditions.kiBuffer // + ); + + // + CopyKIState( + zIndex, + loopback, + conditions.kiStateBuffer // + ); + + CopySar( + zIndex, + loopback, + conditions.sarBuffer // + ); + + // + CopySarState( + zIndex, + loopback, + conditions.sarStateBuffer // + ); + + // + CopyPeak( + zIndex, + loopback, + conditions.peakBuffer // + ); + + // + CopyVale( + zIndex, + loopback, + conditions.valeBuffer // + ); + + // + CopyPeakGolden( + zIndex, + loopback, + conditions.peakGoldenBuffer // + ); + + // + CopyValeGolden( + zIndex, + loopback, + conditions.valeGoldenBuffer // + ); + + // + CopyATR( + zIndex, + loopback, + conditions.atrBuffer // + ); + + // + CopyATRUpper( + zIndex, + loopback, + conditions.atrUpperBuffer // + ); + + // + CopyATRLower( + zIndex, + loopback, + conditions.atrLowerBuffer // + ); + + // + CopyTrend( + zIndex, + loopback, + conditions.trendBuffer // + ); + + // + CopyTrendState( + zIndex, + loopback, + conditions.trendStateBuffer // + ); + + // + CopySBarOpen( + zIndex, + loopback, + conditions.sBarOpenBuffer // + ); + + // + CopySBarClose( + zIndex, + loopback, + conditions.sBarCloseBuffer // + ); + + // + CopyHKSBarOpen( + zIndex, + loopback, + conditions.hkSBarOpenBuffer // + ); + + // + CopyHKSBarClose( + zIndex, + loopback, + conditions.hkSBarCloseBuffer // + ); + + // + CopySHH( + zIndex, + loopback, + conditions.sHHBuffer // + ); + + // + CopySLL( + zIndex, + loopback, + conditions.sLLBuffer // + ); + + // + CopyMHH( + zIndex, + loopback, + conditions.mHHBuffer // + ); + + // + CopyMLL( + zIndex, + loopback, + conditions.mLLBuffer // + ); + + // + CopyLHH( + zIndex, + loopback, + conditions.lHHBuffer // + ); + + // + CopyLLL( + zIndex, + loopback, + conditions.lLLBuffer // + ); + + // + CopyHHH( + zIndex, + loopback, + conditions.hHHBuffer // + ); + + // + CopyHLL( + zIndex, + loopback, + conditions.hLLBuffer // + ); + + // + CopyADX( + zIndex, + loopback, + conditions.adxBuffer // + ); + + // + CopyADXP( + zIndex, + loopback, + conditions.adxpBuffer // + ); + + // + CopyADXN( + zIndex, + loopback, + conditions.adxnBuffer // + ); + + // + CopyDelta( + zIndex, + loopback, + conditions.deltaBuffer // + ); + + // + CopyDeltaSignal( + zIndex, + loopback, + conditions.deltaSignalBuffer // + ); + + // + CopyBullishVolume( + zIndex, + loopback, + conditions.bullishVolumeBuffer // + ); + + // + CopyBearishVolume( + zIndex, + loopback, + conditions.bearishVolumeBuffer // + ); + + // + CopyBullishVolumeSignal( + zIndex, + loopback, + conditions.bullishVolumeSignalBuffer // + ); + + // + CopyBearishVolumeSignal( + zIndex, + loopback, + conditions.bearishVolumeSignalBuffer // + ); + + // + CopyHKOpen( + zIndex, + loopback, + conditions.hkOpenBuffer // + ); + + // + CopyHKHigh( + zIndex, + loopback, + conditions.hkHighBuffer // + ); + + // + CopyHKLow( + zIndex, + loopback, + conditions.hkLowBuffer // + ); + + // + CopyHKClose( + zIndex, + loopback, + conditions.hkCloseBuffer // + ); + + // + CopyRSI( + zIndex, + loopback, + conditions.rsiBuffer // + ); + + // + // Calculate ... + + // + double _rsiOBLevel = mInputs.rsiOBLevel; // Over Bought Level + double _rsiOSLevel = mInputs.rsiOSLevel; // Over Sold Level + double _adxThreshold = mInputs.adxThreshold; // Big Movement Threshold + + // + // Reading Values ... + + // + // ATR Upper ... + double zATRUpper = conditions.atrUpperBuffer[zIDX]; + double cATRUpper = conditions.atrUpperBuffer[cIDX]; + double pATRUpper = conditions.atrUpperBuffer[pIDX]; + double p2ATRUpper = conditions.atrUpperBuffer[p2IDX]; + double p3ATRUpper = conditions.atrUpperBuffer[p3IDX]; + + // + // ATR Lower ... + double zATRLower = conditions.atrLowerBuffer[zIDX]; + double cATRLower = conditions.atrLowerBuffer[cIDX]; + double pATRLower = conditions.atrLowerBuffer[pIDX]; + double p2ATRLower = conditions.atrLowerBuffer[p2IDX]; + double p3ATRLower = conditions.atrLowerBuffer[p3IDX]; + + // + // KI ... + + // + double zKI = conditions.kiBuffer[zIDX]; + double cKI = conditions.kiBuffer[cIDX]; + double pKI = conditions.kiBuffer[pIDX]; + double p2KI = conditions.kiBuffer[p2IDX]; + double p3KI = conditions.kiBuffer[p3IDX]; + + // + double zKIState = conditions.kiStateBuffer[zIDX]; + double cKIState = conditions.kiStateBuffer[cIDX]; + double pKIState = conditions.kiStateBuffer[pIDX]; + double p2KIState = conditions.kiStateBuffer[p2IDX]; + double p3KIState = conditions.kiStateBuffer[p3IDX]; + + // + // SAR ... + + // + double zSAR = conditions.sarBuffer[zIDX]; + double cSar = conditions.sarBuffer[cIDX]; + double pSAR = conditions.sarBuffer[pIDX]; + double p2SAR = conditions.sarBuffer[p2IDX]; + double p3SAR = conditions.sarBuffer[p3IDX]; + + // + double zSarState = conditions.sarStateBuffer[zIDX]; + double cSarState = conditions.sarStateBuffer[cIDX]; + double pSarState = conditions.sarStateBuffer[pIDX]; + double p2SarState = conditions.sarStateBuffer[p2IDX]; + double p3SarState = conditions.sarStateBuffer[p3IDX]; + + // + // ADX ... + + // + double zADX = conditions.adxBuffer[zIDX]; + double cADX = conditions.adxBuffer[cIDX]; + double pADX = conditions.adxBuffer[pIDX]; + double p2ADX = conditions.adxBuffer[p2IDX]; + double p3ADX = conditions.adxBuffer[p3IDX]; + + // + // ADX P ... + + // + double zADXP = conditions.adxpBuffer[zIDX]; + double cADXP = conditions.adxpBuffer[cIDX]; + double pADXP = conditions.adxpBuffer[pIDX]; + double p2ADXP = conditions.adxpBuffer[p2IDX]; + double p3ADXP = conditions.adxpBuffer[p3IDX]; + + // + // ADX N ... + + // + double zADXN = conditions.adxnBuffer[zIDX]; + double cADXN = conditions.adxnBuffer[cIDX]; + double pADXN = conditions.adxnBuffer[pIDX]; + double p2ADXN = conditions.adxnBuffer[p2IDX]; + double p3ADXN = conditions.adxnBuffer[p3IDX]; + + // + // RSI ... + + // + double zRSI = conditions.rsiBuffer[zIDX]; + double cRSI = conditions.rsiBuffer[cIDX]; + double pRSI = conditions.rsiBuffer[pIDX]; + double p2RSI = conditions.rsiBuffer[p2IDX]; + double p3RSI = conditions.rsiBuffer[p3IDX]; + + // + // SIGNAL Bar ... + + // + double zSBarO = conditions.sBarOpenBuffer[zIDX]; + double cSBarO = conditions.sBarOpenBuffer[cIDX]; + double pSBarO = conditions.sBarOpenBuffer[pIDX]; + double p2SBarO = conditions.sBarOpenBuffer[p2IDX]; + double p3SBarO = conditions.sBarOpenBuffer[p3IDX]; + + // + double zSBarC = conditions.sBarCloseBuffer[zIDX]; + double cSBarC = conditions.sBarCloseBuffer[cIDX]; + double pSBarC = conditions.sBarCloseBuffer[pIDX]; + double p2SBarC = conditions.sBarCloseBuffer[p2IDX]; + double p3SBarC = conditions.sBarCloseBuffer[p3IDX]; + + // + // XHK SIGNAL Bar ... + + // + double zHKSBarO = conditions.hkSBarOpenBuffer[zIDX]; + double cHKSBarO = conditions.hkSBarOpenBuffer[cIDX]; + double pHKSBarO = conditions.hkSBarOpenBuffer[pIDX]; + double p2HKSBarO = conditions.hkSBarOpenBuffer[p2IDX]; + double p3HKSBarO = conditions.hkSBarOpenBuffer[p3IDX]; + + // + double zHKSBarC = conditions.hkSBarCloseBuffer[zIDX]; + double cHKSBarC = conditions.hkSBarCloseBuffer[cIDX]; + double pHKSBarC = conditions.hkSBarCloseBuffer[pIDX]; + double p2HKSBarC = conditions.hkSBarCloseBuffer[p2IDX]; + double p3HKSBarC = conditions.hkSBarCloseBuffer[p3IDX]; + + // + // TREND ... + + // + double zTrend = conditions.trendBuffer[zIDX]; + double cTrend = conditions.trendBuffer[cIDX]; + double pTrend = conditions.trendBuffer[pIDX]; + double p2Trend = conditions.trendBuffer[p2IDX]; + double p3Trend = conditions.trendBuffer[p3IDX]; + + // + double zTrendState = conditions.trendStateBuffer[zIDX]; + double cTrendState = conditions.trendStateBuffer[cIDX]; + double pTrendState = conditions.trendStateBuffer[pIDX]; + double p2TrendState = conditions.trendStateBuffer[p2IDX]; + double p3TrendState = conditions.trendStateBuffer[p3IDX]; + + // + // XPV ... + + // + double zPEAK = conditions.peakBuffer[zIDX]; + double cPEAK = conditions.peakBuffer[cIDX]; + double pPEAK = conditions.peakBuffer[pIDX]; + double p2PEAK = conditions.peakBuffer[p2IDX]; + double p3PEAK = conditions.peakBuffer[p3IDX]; + + // + double zVALE = conditions.valeBuffer[zIDX]; + double cVALE = conditions.valeBuffer[cIDX]; + double pVALE = conditions.valeBuffer[pIDX]; + double p2VALE = conditions.valeBuffer[p2IDX]; + double p3VALE = conditions.valeBuffer[p3IDX]; + + // + // DELTA ... + + // + double zDelta = conditions.deltaBuffer[zIDX]; + double cDelta = conditions.deltaBuffer[cIDX]; + double pDelta = conditions.deltaBuffer[pIDX]; + double p2Delta = conditions.deltaBuffer[p2IDX]; + double p3Delta = conditions.deltaBuffer[p3IDX]; + + // + double zDeltaSignal = conditions.deltaSignalBuffer[zIDX]; + double cDeltaSignal = conditions.deltaSignalBuffer[cIDX]; + double pDeltaSignal = conditions.deltaSignalBuffer[pIDX]; + double p2DeltaSignal = conditions.deltaSignalBuffer[p2IDX]; + double p3DeltaSignal = conditions.deltaSignalBuffer[p3IDX]; + + // + // VOLUME ... + + // + double zBullishVolume = conditions.bullishVolumeBuffer[zIDX]; + double cBullishVolume = conditions.bullishVolumeBuffer[cIDX]; + double pBullishVolume = conditions.bullishVolumeBuffer[pIDX]; + double p2BullishVolume = conditions.bullishVolumeBuffer[p2IDX]; + double p3BullishVolume = conditions.bullishVolumeBuffer[p3IDX]; + + // + double zBearishVolume = conditions.bearishVolumeBuffer[zIDX]; + double cBearishVolume = conditions.bearishVolumeBuffer[cIDX]; + double pBearishVolume = conditions.bearishVolumeBuffer[pIDX]; + double p2BearishVolume = conditions.bearishVolumeBuffer[p2IDX]; + double p3BearishVolume = conditions.bearishVolumeBuffer[p3IDX]; + + // + double zBullishVolumeSignal = conditions.bullishVolumeSignalBuffer[zIDX]; + double cBullishVolumeSignal = conditions.bullishVolumeSignalBuffer[cIDX]; + double pBullishVolumeSignal = conditions.bullishVolumeSignalBuffer[pIDX]; + double p2BullishVolumeSignal = conditions.bullishVolumeSignalBuffer[p2IDX]; + double p3BullishVolumeSignal = conditions.bullishVolumeSignalBuffer[p3IDX]; + + // + double zBearishVolumeSignal = conditions.bearishVolumeSignalBuffer[zIDX]; + double cBearishVolumeSignal = conditions.bearishVolumeSignalBuffer[cIDX]; + double pBearishVolumeSignal = conditions.bearishVolumeSignalBuffer[pIDX]; + double p2BearishVolumeSignal = conditions.bearishVolumeSignalBuffer[p2IDX]; + double p3BearishVolumeSignal = conditions.bearishVolumeSignalBuffer[p3IDX]; + + // + // ATR Band ... + + // + bool isATRUp = + cATRUpper > pATRUpper && + cATRLower > pATRLower; + bool isATRDown = + cATRUpper < pATRUpper && + cATRLower < pATRLower; + + // + bool isClosedOverATRUpper = + conditions.bars[cIDX].close > cATRUpper; + bool isClosedUnderATRLower = + conditions.bars[cIDX].close < cATRLower; + + // + // KI ... + + // + bool isKIUp = cKI > pKI; + bool isKIDown = cKI < pKI; + + // + bool isKIBullish = cKIState > 0; + bool isKIBearish = cKIState < 0; + + // + bool isKISameAsLast = cKI == pKI; + + // + bool isKISwitchedToBullish = + cKIState > 0 && + pKIState <= 0; + + // + bool isKISwitchedToBearish = + cKIState < 0 && + pKIState >= 0; + + // + // SAR ... + + // + bool isSarBullish = cSarState > 0; + bool isSarBearish = cSarState < 0; + + // + bool isSarSwitchedToBullish = + cSarState > 0 && + pSarState <= 0; + bool isSarSwitchedToBearish = + cSarState < 0 && + pSarState >= 0; + + // + // ADX ... + + // + bool isADXBiggerLast = + cADX > pADX; + bool isADXLesserLast = + cADX < pADX; + + // + bool isPADXBiggerLast = + pADX > p2ADX; + bool isPADXLesserLast = + pADX < p2ADX; + + // + bool isADXOverThreshold = + cADX > _adxThreshold; + bool isADXUnderThreshold = + cADX < _adxThreshold; + + // + bool isPADXOverThreshold = + pADX > _adxThreshold; + bool isPADXUnderThreshold = + pADX < _adxThreshold; + + // + bool isDXPBiggerThanDXN = + cADXP > cADXN; + bool isDXNBiggerThanDXP = + cADXN > cADXP; + + // + bool isPDXPBiggerThanDXN = + pADXP > pADXN; + bool isPDXNBiggerThanDXP = + pADXN > pADXP; + + // + bool isADXBullish = + isADXBiggerLast && + isADXOverThreshold; + bool isADXBearish = + isADXLesserLast && + isADXUnderThreshold; + + // + bool isPADXBullish = + isPADXBiggerLast && + isPADXOverThreshold; + bool isPADXBearish = + isPADXLesserLast && + isPADXUnderThreshold; + + // + bool isADXSwitchedToBullish = + isADXBullish && + !isPADXBullish; + bool isADXSwitchedToBearish = + isADXBearish && + !isPADXBearish; + + // + // RSI ... + + // + bool isRSIBullish = + cRSI > pRSI; + bool isRSIBearish = + cRSI < pRSI; + + // + bool isRSISwitchedToBullish = + cRSI > pRSI && + pRSI <= cRSI; + bool isRSISwitchedToBearish = + cRSI < pRSI && + pRSI >= cRSI; + + // + bool isRSIOB = + cRSI > _rsiOBLevel; + bool isRSIOS = + cRSI < _rsiOSLevel; + + // + bool isRSICrossedOverOB = + cRSI > _rsiOBLevel && + pRSI <= _rsiOBLevel; + bool isRSICrossedOverOS = + cRSI > _rsiOSLevel && + pRSI <= _rsiOSLevel; + + // + bool isRSICrossedUnderOB = + cRSI < _rsiOBLevel && + pRSI >= _rsiOBLevel; + bool isRSICrossedUnderOS = + cRSI < _rsiOSLevel && + pRSI >= _rsiOSLevel; + + // + // DELTA ... + + // + bool isDeltaUp = + cDelta > pDelta; + bool isDeltaDown = + cDelta < pDelta; + + // + bool isDeltaBullish = + cDelta > pDelta && + cDeltaSignal > cDelta && + cDeltaSignal > pDeltaSignal; + bool isPDeltaBullish = + pDelta > p2Delta && + pDeltaSignal > pDelta && + pDeltaSignal > p2DeltaSignal; + + // + bool isDeltaBearish = + cDelta < pDelta && + cDeltaSignal < cDelta && + cDeltaSignal < pDeltaSignal; + bool isPDeltaBearish = + pDelta < p2Delta && + pDeltaSignal < pDelta && + pDeltaSignal < p2DeltaSignal; + + // + bool isDeltaSwitchedToBullish = + isDeltaBullish && + !isPDeltaBullish; + bool isDeltaSwitchedToBearish = + isDeltaBearish && + !isPDeltaBearish; + + // + // VOLUME ... + + // + bool isVolumeBullish = + cBullishVolume > pBullishVolume && + cBullishVolume > cBearishVolume; + bool isVolumeBearish = + cBearishVolume > pBearishVolume && + cBearishVolume > cBullishVolume; + + // + bool isVolumeSwitchedToBullish = + isVolumeBullish && + cBullishVolumeSignal > cBearishVolumeSignal && + pBullishVolumeSignal <= pBearishVolumeSignal; + bool isVolumeSwitchedToBearish = + isVolumeBearish && + cBearishVolumeSignal > cBullishVolumeSignal && + pBearishVolumeSignal <= pBullishVolumeSignal; + + // + // SIGNAL Bar ... + + // + bool isSBarBullish = + cSBarO < cSBarC; + bool isSBarBearish = + cSBarO > cSBarC; + + // + bool isSBarSwitchedToBullish = + cSBarO < cSBarC && + pSBarO >= pSBarC; + bool isSBarSwitchedToBearish = + cSBarO > cSBarC && + pSBarO <= pSBarC; + + // + // XHK Signal Bar ... + + // + bool isHKSBarBullish = + cHKSBarO < cHKSBarC; + bool isHKSBarBearish = + cHKSBarO > cHKSBarC; + + // + bool isHKSBarSwitchedToBullish = + cHKSBarO < cHKSBarC && + pHKSBarO >= pHKSBarC; + bool isHKSBarSwitchedToBearish = + cHKSBarO > cHKSBarC && + pHKSBarO <= pHKSBarC; + + // + // TREND ... + + // + bool isTrendUp = + cTrend > pTrend; + bool isTrendDown = + cTrend < pTrend; + + // + bool isTrendBullish = + cTrendState > 0; + bool isTrendBearish = + cTrendState < 0; + + // + bool isTrendSwitchedToBullish = + isTrendUp && + cTrendState > 0 && + pTrendState <= 0; + bool isTrendSwitchedToBearish = + isTrendDown && + cTrendState < 0 && + pTrendState >= 0; + + // + // PEAK ... + + // + bool isPeakSameLast = + cPEAK > 0 && + cPEAK == pPEAK; + bool isPeakOverLast = + pPEAK > 0 && + cPEAK > pPEAK; + bool isPeakUnderLast = + cPEAK > 0 && + cPEAK < pPEAK; + + // + // VALE ... + + // + bool isValeSameLast = + cVALE > 0 && + cVALE == pVALE; + bool isValeOverLast = + pVALE > 0 && + cVALE > pVALE; + bool isValeUnderLast = + cVALE > 0 && + cVALE < pVALE; + + // + // Attached ... + + // + conditions.isKIUp = isKIUp; + conditions.isATRUp = isATRUp; + conditions.isRSIOB = isRSIOB; + conditions.isRSIOS = isRSIOS; + conditions.isKIDown = isKIDown; + conditions.isDeltaUp = isDeltaUp; + conditions.isATRDown = isATRDown; + conditions.isTrendUp = isTrendUp; + conditions.rsiOBLevel = _rsiOBLevel; + conditions.rsiOSLevel = _rsiOSLevel; + conditions.isDeltaDown = isDeltaDown; + conditions.isTrendDown = isTrendDown; + conditions.isKIBullish = isKIBullish; + conditions.isKIBearish = isKIBearish; + conditions.isSarBullish = isSarBullish; + conditions.isSarBearish = isSarBearish; + conditions.isADXBullish = isADXBullish; + conditions.isADXBearish = isADXBearish; + conditions.isRSIBullish = isRSIBullish; + conditions.isRSIBearish = isRSIBearish; + conditions.adxThreshold = _adxThreshold; + conditions.isSBarBullish = isSBarBullish; + conditions.isSBarBearish = isSBarBearish; + conditions.isKISameAsLast = isKISameAsLast; + conditions.isDeltaBullish = isDeltaBullish; + conditions.isDeltaBearish = isDeltaBearish; + conditions.isTrendBullish = isTrendBullish; + conditions.isTrendBearish = isTrendBearish; + conditions.isPeakSameLast = isPeakSameLast; + conditions.isPeakOverLast = isPeakOverLast; + conditions.isValeSameLast = isValeSameLast; + conditions.isValeOverLast = isValeOverLast; + conditions.isVolumeBullish = isVolumeBullish; + conditions.isVolumeBearish = isVolumeBearish; + conditions.isADXBiggerLast = isADXBiggerLast; + conditions.isADXLesserLast = isADXLesserLast; + conditions.isHKSBarBullish = isHKSBarBullish; + conditions.isHKSBarBearish = isHKSBarBearish; + conditions.isPeakUnderLast = isPeakUnderLast; + conditions.isValeUnderLast = isValeUnderLast; + conditions.isRSICrossedOverOB = isRSICrossedOverOB; + conditions.isRSICrossedOverOS = isRSICrossedOverOS; + conditions.isADXOverThreshold = isADXOverThreshold; + conditions.isDXPBiggerThanDXN = isDXPBiggerThanDXN; + conditions.isDXNBiggerThanDXP = isDXNBiggerThanDXP; + conditions.isRSICrossedUnderOB = isRSICrossedUnderOB; + conditions.isRSICrossedUnderOS = isRSICrossedUnderOS; + conditions.isADXUnderThreshold = isADXUnderThreshold; + conditions.isClosedOverATRUpper = isClosedOverATRUpper; + conditions.isKISwitchedToBullish = isKISwitchedToBullish; + conditions.isKISwitchedToBearish = isKISwitchedToBearish; + conditions.isClosedUnderATRLower = isClosedUnderATRLower; + conditions.isSarSwitchedToBullish = isSarSwitchedToBullish; + conditions.isSarSwitchedToBearish = isSarSwitchedToBearish; + conditions.isADXSwitchedToBullish = isADXSwitchedToBullish; + conditions.isADXSwitchedToBearish = isADXSwitchedToBearish; + conditions.isRSISwitchedToBullish = isRSISwitchedToBullish; + conditions.isRSISwitchedToBearish = isRSISwitchedToBearish; + conditions.isSBarSwitchedToBullish = isSBarSwitchedToBullish; + conditions.isSBarSwitchedToBearish = isSBarSwitchedToBearish; + conditions.isTrendSwitchedToBullish = isTrendSwitchedToBullish; + conditions.isTrendSwitchedToBearish = isTrendSwitchedToBearish; + conditions.isDeltaSwitchedToBullish = isDeltaSwitchedToBullish; + conditions.isDeltaSwitchedToBearish = isDeltaSwitchedToBearish; + conditions.isVolumeSwitchedToBullish = isVolumeSwitchedToBullish; + conditions.isVolumeSwitchedToBearish = isVolumeSwitchedToBearish; + conditions.isHKSBarSwitchedToBullish = isHKSBarSwitchedToBullish; + conditions.isHKSBarSwitchedToBearish = isHKSBarSwitchedToBearish; + + // + // Cleanup Resources ... + + // + Cleanup(); + + // + return result; + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + X121XCatbInputs mInputs; // Inputs ... + + // + // Buffers ... + // Define in Public ... + + // + void Calculate( + int barIndex = 0, + int maxRequiredBars = 100 // + ) + { + // + // Buffers ... + if (barIndex < 0) + { + barIndex = 0; + } + + // + CopyBuffer( + mHandler, + X121_XCATB_KI_LINE, + barIndex, + maxRequiredBars, + kiBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_KI_STATE_LINE, + barIndex, + maxRequiredBars, + kiStateBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_SAR_LINE, + barIndex, + maxRequiredBars, + sarBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_SAR_STATE_LINE, + barIndex, + maxRequiredBars, + sarStateBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_PEAK_LINE, + barIndex, + maxRequiredBars, + peakBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_VALE_LINE, + barIndex, + maxRequiredBars, + valeBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_PEAK_GOLDEN_LINE, + barIndex, + maxRequiredBars, + peakGoldenBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_VALE_GOLDEN_LINE, + barIndex, + maxRequiredBars, + valeGoldenBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_ATR_BAND_UPPER_LINE, + barIndex, + maxRequiredBars, + atrUpperBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_ATR_BAND_LOWER_LINE, + barIndex, + maxRequiredBars, + atrLowerBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_TREND_LINE, + barIndex, + maxRequiredBars, + trendBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_TREND_STATE_LINE, + barIndex, + maxRequiredBars, + trendStateBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_SBAR_O_LINE, + barIndex, + maxRequiredBars, + sBarOpenBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_SBAR_C_LINE, + barIndex, + maxRequiredBars, + sBarCloseBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_HK_SBAR_O_LINE, + barIndex, + maxRequiredBars, + hkSBarOpenBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_HK_SBAR_C_LINE, + barIndex, + maxRequiredBars, + hkSBarCloseBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_S_HH_LINE, + barIndex, + maxRequiredBars, + sHHBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_S_LL_LINE, + barIndex, + maxRequiredBars, + sLLBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_M_HH_LINE, + barIndex, + maxRequiredBars, + mHHBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_M_LL_LINE, + barIndex, + maxRequiredBars, + mLLBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_L_HH_LINE, + barIndex, + maxRequiredBars, + lHHBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_L_LL_LINE, + barIndex, + maxRequiredBars, + lLLBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_H_HH_LINE, + barIndex, + maxRequiredBars, + hHHBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_H_LL_LINE, + barIndex, + maxRequiredBars, + hLLBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_RSI_LINE, + barIndex, + maxRequiredBars, + rsiBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_ADX_LINE, + barIndex, + maxRequiredBars, + adxBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_ADXP_LINE, + barIndex, + maxRequiredBars, + adxpBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_ADXN_LINE, + barIndex, + maxRequiredBars, + adxnBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_DELTA_LINE, + barIndex, + maxRequiredBars, + deltaBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_DELTA_SIGNAL_LINE, + barIndex, + maxRequiredBars, + deltaSignalBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_VOLUME_BULLISH_LINE, + barIndex, + maxRequiredBars, + bullishVolumeBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_VOLUME_BEARISH_LINE, + barIndex, + maxRequiredBars, + bearishVolumeBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_VOLUME_VOLUME_BULLISH_SIGNAL_LINE, + barIndex, + maxRequiredBars, + bullishVolumeSignalBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_VOLUME_VOLUME_BEARISH_SIGNAL_LINE, + barIndex, + maxRequiredBars, + bearishVolumeSignalBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_ATR_LINE, + barIndex, + maxRequiredBars, + atrBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_HK_BAR_O_LINE, + barIndex, + maxRequiredBars, + hkOpenBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_HK_BAR_H_LINE, + barIndex, + maxRequiredBars, + hkHighBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_HK_BAR_L_LINE, + barIndex, + maxRequiredBars, + hkLowBuffer // + ); + + // + CopyBuffer( + mHandler, + X121_XCATB_HK_BAR_C_LINE, + barIndex, + maxRequiredBars, + hkCloseBuffer // + ); + } + + // + void Cleanup( + int maxAllowed = 100 // + ) + { + // + CleanupArray( + kiBuffer, + maxAllowed // + ); + + // + CleanupArray( + kiStateBuffer, + maxAllowed // + ); + + // + CleanupArray( + sarBuffer, + maxAllowed // + ); + + // + CleanupArray( + sarStateBuffer, + maxAllowed // + ); + + // + CleanupArray( + peakBuffer, + maxAllowed // + ); + + // + CleanupArray( + valeBuffer, + maxAllowed // + ); + + // + CleanupArray( + peakGoldenBuffer, + maxAllowed // + ); + + // + CleanupArray( + valeGoldenBuffer, + maxAllowed // + ); + + // + CleanupArray( + atrUpperBuffer, + maxAllowed // + ); + + // + CleanupArray( + atrLowerBuffer, + maxAllowed // + ); + + // + CleanupArray( + trendBuffer, + maxAllowed // + ); + + // + CleanupArray( + trendStateBuffer, + maxAllowed // + ); + + // + CleanupArray( + sBarOpenBuffer, + maxAllowed // + ); + + // + CleanupArray( + sBarCloseBuffer, + maxAllowed // + ); + + // + CleanupArray( + hkSBarOpenBuffer, + maxAllowed // + ); + + // + CleanupArray( + hkSBarCloseBuffer, + maxAllowed // + ); + + // + CleanupArray( + sHHBuffer, + maxAllowed // + ); + + // + CleanupArray( + sLLBuffer, + maxAllowed // + ); + + // + CleanupArray( + mHHBuffer, + maxAllowed // + ); + + // + CleanupArray( + mLLBuffer, + maxAllowed // + ); + + // + CleanupArray( + lHHBuffer, + maxAllowed // + ); + + // + CleanupArray( + lLLBuffer, + maxAllowed // + ); + + // + CleanupArray( + hHHBuffer, + maxAllowed // + ); + + // + CleanupArray( + hLLBuffer, + maxAllowed // + ); + + // + CleanupArray( + rsiBuffer, + maxAllowed // + ); + + // + CleanupArray( + adxBuffer, + maxAllowed // + ); + + // + CleanupArray( + adxpBuffer, + maxAllowed // + ); + + // + CleanupArray( + adxnBuffer, + maxAllowed // + ); + + // + CleanupArray( + deltaBuffer, + maxAllowed // + ); + + // + CleanupArray( + deltaSignalBuffer, + maxAllowed // + ); + + // + CleanupArray( + bullishVolumeBuffer, + maxAllowed // + ); + + // + CleanupArray( + bearishVolumeBuffer, + maxAllowed // + ); + + // + CleanupArray( + bullishVolumeSignalBuffer, + maxAllowed // + ); + + // + CleanupArray( + bearishVolumeSignalBuffer, + maxAllowed // + ); + + // + CleanupArray( + atrBuffer, + maxAllowed // + ); + + // + CleanupArray( + hkOpenBuffer, + maxAllowed // + ); + + // + CleanupArray( + hkHighBuffer, + maxAllowed // + ); + + // + CleanupArray( + hkLowBuffer, + maxAllowed // + ); + + // + CleanupArray( + hkCloseBuffer, + maxAllowed // + ); + } + + // +}; + +// +// Extensions ... + +// +enum ENUM_XCATB_DIRECTION_SHIFT_TYPES +{ + XCATB_DIRECTION_SHIFT_TYPE_NONE, // None + XCATB_DIRECTION_SHIFT_TYPE_SAR, // XSARB + XCATB_DIRECTION_SHIFT_TYPE_TREND, // XTRNDB + XCATB_DIRECTION_SHIFT_TYPE_DELTA, // XDELTAB + XCATB_DIRECTION_SHIFT_TYPE_VOLUME, // XVLMB + XCATB_DIRECTION_SHIFT_TYPE_SIGNAL_BAR, // XSBARB + XCATB_DIRECTION_SHIFT_TYPE_HK_SIGNAL_BAR, // XHKSBARB +}; + +// +bool IsValid(ENUM_XCATB_DIRECTION_SHIFT_TYPES value) +{ + return value != XCATB_DIRECTION_SHIFT_TYPE_NONE; +} + +// +string ToString(ENUM_XCATB_DIRECTION_SHIFT_TYPES value) +{ + return EnumToString(value); +} + +// +ENUM_XCATB_DIRECTION_SHIFT_TYPES GetDirectionShiftType(XBoxZone &box) +{ + // + ENUM_XCATB_DIRECTION_SHIFT_TYPES result = XCATB_DIRECTION_SHIFT_TYPE_NONE; + + // + if (!box.IsValid()) + { + return result; + } + + // + ENUM_XCATB_DIRECTION_SHIFT_TYPES all[] = { + XCATB_DIRECTION_SHIFT_TYPE_SAR, + XCATB_DIRECTION_SHIFT_TYPE_TREND, + XCATB_DIRECTION_SHIFT_TYPE_DELTA, + XCATB_DIRECTION_SHIFT_TYPE_VOLUME, + XCATB_DIRECTION_SHIFT_TYPE_SIGNAL_BAR, + XCATB_DIRECTION_SHIFT_TYPE_HK_SIGNAL_BAR, + }; + + // + int count = ArraySize(all); + for (int i = 0; i < count; i++) + { + // + if (box.type == ToString(all[i])) + { + // + result = all[i]; + break; + } + } + + // + return result; +} + +// +bool IsDirectionShift(XBoxZone &box) +{ + // + bool result = false; + + // + result = IsValid(GetDirectionShiftType(box)); + + // + return result; +} + +/** + * Generate Sar Direction Shift Box ... + * + * @param box: XBoxZone instance reference, Holds Generated Box ... + * @param helper: XCX121XCatbHelper instance pointer ... + * @param conditions: X121XCatbConditions instance reference, Specified Market Conditions ... + * + * @return ( bool ) + */ +bool GenerateSarDirectionShiftBox( + XBoxZone &box, + XCX121XCatbHelper *helper, + X121XCatbConditions &conditions // +) +{ + // + bool result = false; + + // + // Normalize Args ... + box.Clean(); + + // + // Validate Args ... + result = + helper != NULL; + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + int idx = -1; + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + + // + // Check Sar Direction Changed Happens or not ... + + // + bool isBullish = + // + ( + // + // Current SAR is Directional ... + conditions.isSarBullish && + // + // Previous InDirectional Sar Exists ... + helper.lastSarBearish.IsValid() && + // + // Current Close is Over previous Sar ... + conditions.bars[cIDX].close > helper.lastSarBearish.after && + // + // Before Close is not Over previous Sar ... + conditions.bars[pIDX].close <= helper.lastSarBearish.after + // + ) + // + ; + + // + bool isBearish = + // + ( + // + // Current SAR is Directional ... + conditions.isSarBearish && + // + // Previous InDirectional Sar Exists ... + helper.lastSarBullish.IsValid() && + // + // Current Close is Under previous ... + conditions.bars[cIDX].close < helper.lastSarBullish.after && + // + // Before Close is not Under previous ... + conditions.bars[pIDX].close >= helper.lastSarBullish.after + // + ) + // + ; + + // + result = + isBullish || + isBearish; + if (!result) + { + return result; + } + + // + // Assign Last Direction Shift ... + XDirectionShift lastBullish = helper.lastSarBullish; + XDirectionShift lastBearish = helper.lastSarBearish; + XDirectionShift selected = isBullish + ? lastBearish + : lastBullish; + + // + // Convert to Box ... + box.type = "XSARB"; + box.from = selected.at; + box.symbol = selected.symbol; + box.period = selected.period; + box.dir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + box.to = conditions.bars[zIDX].time; + + // + // Detect Boundary ... + idx = selected.Index(); + result = IsValidIndex(idx); + if (result) + { + // + box.lower = conditions.bars[zIDX].FindLowest(idx, MODE_CLOSE); + box.upper = conditions.bars[zIDX].FindHighest(idx, MODE_CLOSE); + } + + // + // Summarize Result ... + result = box.IsValid(); + + // + // Cleanup Resources ... + + // + if (!result) + { + box.Clean(); + } + + // + selected.Clean(); + lastBullish.Clean(); + lastBearish.Clean(); + + // + return result; +} + +/** + * Generate Trend Direction Shift Box ... + * + * @param box: XBoxZone instance reference, Holds Generated Box ... + * @param helper: XCX121XCatbHelper instance pointer ... + * @param conditions: X121XCatbConditions instance reference, Specified Market Conditions ... + * + * @return ( bool ) + */ +bool GenerateTrendDirectionShiftBox( + XBoxZone &box, + XCX121XCatbHelper *helper, + X121XCatbConditions &conditions // +) +{ + // + bool result = false; + + // + // Normalize Args ... + box.Clean(); + + // + // Validate Args ... + result = + helper != NULL; + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + int idx = -1; + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + + // + // Check Sar Direction Changed Happens or not ... + + // + bool isBullish = + // + ( + // + // Current Trend is Directional ... + conditions.isTrendBullish && + // + // Previous InDirectiona; Trend Exists ... + helper.lastTrendBearish.IsValid() && + // + // Current Close is Over previous ... + conditions.bars[cIDX].close > helper.lastTrendBearish.after && + // + // Before close is not Over previous ... + conditions.bars[pIDX].close <= helper.lastTrendBearish.after + // + ) + // + ; + + // + bool isBearish = + // + ( + // + // Current Trend is Directional ... + conditions.isTrendBearish && + // + // Previous InDirectiona; Trend Exists ... + helper.lastTrendBullish.IsValid() && + // + // Current Close is Under previous ... + conditions.bars[cIDX].close < helper.lastTrendBullish.after && + // + // Before close is not Under previous ... + conditions.bars[pIDX].close >= helper.lastTrendBullish.after + // + ) + // + ; + + // + result = + isBullish || + isBearish; + if (!result) + { + return result; + } + + // + // Assign Last Direction Shift ... + XDirectionShift lastBullish = helper.lastTrendBullish; + XDirectionShift lastBearish = helper.lastTrendBearish; + XDirectionShift selected = isBullish + ? lastBearish + : lastBullish; + + // + // Convert to Box ... + box.type = "XTRNDB"; + box.from = selected.at; + box.symbol = selected.symbol; + box.period = selected.period; + box.dir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + box.to = conditions.bars[zIDX].time; + + // + // Detect Boundary ... + idx = selected.Index(); + result = IsValidIndex(idx); + if (result) + { + // + box.lower = conditions.bars[zIDX].FindLowest(idx, MODE_CLOSE); + box.upper = conditions.bars[zIDX].FindHighest(idx, MODE_CLOSE); + } + + // + // Summarize Result ... + result = box.IsValid(); + + // + // Cleanup Resources ... + + // + if (!result) + { + box.Clean(); + } + + // + selected.Clean(); + lastBullish.Clean(); + lastBearish.Clean(); + + // + return result; +} + +/** + * Generate Delta Direction Shift Box ... + * + * @param box: XBoxZone instance reference, Holds Generated Box ... + * @param helper: XCX121XCatbHelper instance pointer ... + * @param conditions: X121XCatbConditions instance reference, Specified Market Conditions ... + * + * @return ( bool ) + */ +bool GenerateDeltaDirectionShiftBox( + XBoxZone &box, + XCX121XCatbHelper *helper, + X121XCatbConditions &conditions // +) +{ + // + bool result = false; + + // + // Normalize Args ... + box.Clean(); + + // + // Validate Args ... + result = + helper != NULL; + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + int idx = -1; + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + + // + // Check Sar Direction Changed Happens or not ... + + // + bool isBullish = + // + // Check State ... + ( + // + // Delta is Up ... + conditions.deltaBuffer[cIDX] > conditions.deltaBuffer[pIDX] && + // + // Delta Signal is Up ... + conditions.deltaSignalBuffer[cIDX] > conditions.deltaSignalBuffer[pIDX] && + // + // Delta Crossed Over Delta Signal ... + conditions.deltaBuffer[cIDX] > conditions.deltaSignalBuffer[cIDX] + // + ) + // + && + // + // Check Last InDirectional Exists ... + helper.lastDeltaBearish.IsValid() && + // + // Current Close is Over last ... + conditions.bars[cIDX].close > helper.lastDeltaBearish.after && + // + // Before Close is not Over last ... + conditions.bars[pIDX].close <= helper.lastDeltaBearish.after + // + ; + + // + bool isBearish = + // + // Check State ... + ( + // + // Delta is Down ... + conditions.deltaBuffer[cIDX] < conditions.deltaBuffer[pIDX] && + // + // Delta Signal is Down ... + conditions.deltaSignalBuffer[cIDX] < conditions.deltaSignalBuffer[pIDX] && + // + // Delta Crossed Under Delta Signal ... + conditions.deltaBuffer[cIDX] < conditions.deltaSignalBuffer[cIDX] + // + ) + // + && + // + // Check Last InDirectional Exists ... + helper.lastDeltaBullish.IsValid() && + // + // Current Close is Under last ... + conditions.bars[cIDX].close < helper.lastDeltaBullish.after && + // + // Before Close is not Under last ... + conditions.bars[pIDX].close >= helper.lastDeltaBullish.after + // + ; + + // + result = + isBullish || + isBearish; + if (!result) + { + return result; + } + + // + // Assign Last Direction Shift ... + XDirectionShift lastBullish = helper.lastDeltaBullish; + XDirectionShift lastBearish = helper.lastDeltaBearish; + XDirectionShift selected = isBullish + ? lastBearish + : lastBullish; + + // + // Convert to Box ... + box.type = "XDELTAB"; + box.from = selected.at; + box.symbol = selected.symbol; + box.period = selected.period; + box.dir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + box.to = conditions.bars[zIDX].time; + + // + // Detect Boundary ... + idx = selected.Index(); + result = IsValidIndex(idx); + if (result) + { + // + box.lower = conditions.bars[zIDX].FindLowest(idx, MODE_CLOSE); + box.upper = conditions.bars[zIDX].FindHighest(idx, MODE_CLOSE); + } + + // + // Summarize Result ... + result = box.IsValid(); + + // + // Cleanup Resources ... + + // + if (!result) + { + box.Clean(); + } + + // + selected.Clean(); + lastBullish.Clean(); + lastBearish.Clean(); + + // + return result; +} + +/** + * Generate Volume Direction Shift Box ... + * + * @param box: XBoxZone instance reference, Holds Generated Box ... + * @param helper: XCX121XCatbHelper instance pointer ... + * @param conditions: X121XCatbConditions instance reference, Specified Market Conditions ... + * + * @return ( bool ) + */ +bool GenerateVolumeDirectionShiftBox( + XBoxZone &box, + XCX121XCatbHelper *helper, + X121XCatbConditions &conditions // +) +{ + // + bool result = false; + + // + // Normalize Args ... + box.Clean(); + + // + // Validate Args ... + result = + helper != NULL; + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + int idx = -1; + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + + // + // Check Sar Direction Changed Happens or not ... + + // + bool isBullish = + // + ( + // + // + // Volume is Up ... + conditions.bullishVolumeBuffer[1] > conditions.bullishVolumeBuffer[2] && + // + // Volume Signal is Up ... + conditions.bullishVolumeSignalBuffer[1] > conditions.bullishVolumeSignalBuffer[2] && + // + // Volume Signals Crossed Over ... + conditions.bullishVolumeSignalBuffer[1] > conditions.bearishVolumeSignalBuffer[1] + // + ) + // + && + // + // Check Last InDirectional Exists ... + helper.lastVolumeBearish.IsValid() && + // + // Current Close is Over last ... + conditions.bars[cIDX].close > helper.lastVolumeBearish.after && + // + // Before Close is not Over last ... + conditions.bars[pIDX].close <= helper.lastVolumeBearish.after + // + ; + + // + bool isBearish = + // + ( + // + // + // Volume is Up ... + conditions.bearishVolumeBuffer[1] > conditions.bearishVolumeBuffer[2] && + // + // Volume Signal is Up ... + conditions.bearishVolumeSignalBuffer[1] > conditions.bearishVolumeSignalBuffer[2] && + // + // Volume Signals Crossed Over ... + conditions.bearishVolumeSignalBuffer[1] > conditions.bullishVolumeSignalBuffer[1] + // + ) + // + && + // + // Check Last InDirectional Exists ... + helper.lastVolumeBullish.IsValid() && + // + // Current Close is Over last ... + conditions.bars[cIDX].close < helper.lastVolumeBullish.after && + // + // Before Close is not Over last ... + conditions.bars[pIDX].close >= helper.lastVolumeBullish.after + // + ; + + // + result = + isBullish || + isBearish; + if (!result) + { + return result; + } + + // + // Assign Last Direction Shift ... + XDirectionShift lastBullish = helper.lastVolumeBullish; + XDirectionShift lastBearish = helper.lastVolumeBearish; + XDirectionShift selected = isBullish + ? lastBearish + : lastBullish; + + // + // Convert to Box ... + box.type = "XVLMB"; + box.from = selected.at; + box.symbol = selected.symbol; + box.period = selected.period; + box.dir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + box.to = conditions.bars[zIDX].time; + + // + // Detect Boundary ... + idx = selected.Index(); + result = IsValidIndex(idx); + if (result) + { + // + box.lower = conditions.bars[zIDX].FindLowest(idx, MODE_CLOSE); + box.upper = conditions.bars[zIDX].FindHighest(idx, MODE_CLOSE); + } + + // + // Summarize Result ... + result = box.IsValid(); + + // + // Cleanup Resources ... + + // + if (!result) + { + box.Clean(); + } + + // + selected.Clean(); + lastBullish.Clean(); + lastBearish.Clean(); + + // + return result; +} + +/** + * Generate Signal Bar Direction Shift Box ... + * + * @param box: XBoxZone instance reference, Holds Generated Box ... + * @param helper: XCX121XCatbHelper instance pointer ... + * @param conditions: X121XCatbConditions instance reference, Specified Market Conditions ... + * + * @return ( bool ) + */ +bool GenerateSignalBarDirectionShiftBox( + XBoxZone &box, + XCX121XCatbHelper *helper, + X121XCatbConditions &conditions // +) +{ + // + bool result = false; + + // + // Normalize Args ... + box.Clean(); + + // + // Validate Args ... + result = + helper != NULL; + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + int idx = -1; + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + + // + // Check Sar Direction Changed Happens or not ... + + // + bool isBullish = + // + ( + // + // Check Direction ... + conditions.isSBarBullish && + // + // Previous InDirectional Exists ... + helper.lastSignalBarBearish.IsValid() && + // + // Current Signal Bar close over prev ... + conditions.sBarCloseBuffer[cIDX] > helper.lastSignalBarBearish.after && + // + // Prev Signal Bar not close over prev ... + conditions.sBarCloseBuffer[pIDX] <= helper.lastSignalBarBearish.after + // + ) + // + ; + + // + bool isBearish = + // + ( + // + // Check Direction ... + conditions.isSBarBearish && + // + // Previous InDirectional Exists ... + helper.lastSignalBarBullish.IsValid() && + // + // Current Signal Bar close over prev ... + conditions.sBarCloseBuffer[cIDX] < helper.lastSignalBarBullish.after && + // + // Prev Signal Bar not close over prev ... + conditions.sBarCloseBuffer[pIDX] >= helper.lastSignalBarBullish.after + // + ) + // + ; + + // + result = + isBullish || + isBearish; + if (!result) + { + return result; + } + + // + // Assign Last Direction Shift ... + XDirectionShift lastBullish = helper.lastSignalBarBullish; + XDirectionShift lastBearish = helper.lastSignalBarBearish; + XDirectionShift selected = isBullish + ? lastBearish + : lastBullish; + + // + // Convert to Box ... + box.type = "XSBARB"; + box.from = selected.at; + box.symbol = selected.symbol; + box.period = selected.period; + box.dir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + box.to = conditions.bars[zIDX].time; + + // + // Detect Boundary ... + idx = selected.Index(); + result = IsValidIndex(idx); + if (result) + { + // + box.lower = conditions.bars[zIDX].FindLowest(idx, MODE_CLOSE); + box.upper = conditions.bars[zIDX].FindHighest(idx, MODE_CLOSE); + } + + // + // Summarize Result ... + result = box.IsValid(); + + // + // Cleanup Resources ... + + // + if (!result) + { + box.Clean(); + } + + // + selected.Clean(); + lastBullish.Clean(); + lastBearish.Clean(); + + // + return result; +} + +/** + * Generate HK Signal Bar Direction Shift Box ... + * + * @param box: XBoxZone instance reference, Holds Generated Box ... + * @param helper: XCX121XCatbHelper instance pointer ... + * @param conditions: X121XCatbConditions instance reference, Specified Market Conditions ... + * + * @return ( bool ) + */ +bool GenerateHKSignalBarDirectionShiftBox( + XBoxZone &box, + XCX121XCatbHelper *helper, + X121XCatbConditions &conditions // +) +{ + // + bool result = false; + + // + // Normalize Args ... + box.Clean(); + + // + // Validate Args ... + result = + helper != NULL; + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + int idx = -1; + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + + // + // Check Sar Direction Changed Happens or not ... + + // + bool isBullish = + // + ( + // + // Check Direction ... + conditions.isHKSBarBullish && + // + // Previous InDirectional Exists ... + helper.lastHKSignalBarBearish.IsValid() && + // + // Current Signal Bar close over prev ... + conditions.hkSBarCloseBuffer[cIDX] > helper.lastHKSignalBarBearish.after && + // + // Prev Signal Bar not close over prev ... + conditions.hkSBarCloseBuffer[pIDX] <= helper.lastHKSignalBarBearish.after + // + ) + // + ; + + // + bool isBearish = + // + ( + // + // Check Direction ... + conditions.isHKSBarBearish && + // + // Previous InDirectional Exists ... + helper.lastHKSignalBarBullish.IsValid() && + // + // Current Signal Bar close over prev ... + conditions.hkSBarCloseBuffer[cIDX] < helper.lastHKSignalBarBullish.after && + // + // Prev Signal Bar not close over prev ... + conditions.hkSBarCloseBuffer[pIDX] >= helper.lastHKSignalBarBullish.after + // + ) + // + ; + + // + result = + isBullish || + isBearish; + if (!result) + { + return result; + } + + // + // Assign Last Direction Shift ... + XDirectionShift lastBullish = helper.lastHKSignalBarBullish; + XDirectionShift lastBearish = helper.lastHKSignalBarBearish; + XDirectionShift selected = isBullish + ? lastBearish + : lastBullish; + + // + // Convert to Box ... + box.type = "XHKSBARB"; + box.from = selected.at; + box.symbol = selected.symbol; + box.period = selected.period; + box.dir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + box.to = conditions.bars[zIDX].time; + + // + // Detect Boundary ... + idx = selected.Index(); + result = IsValidIndex(idx); + if (result) + { + // + box.lower = conditions.bars[zIDX].FindLowest(idx, MODE_CLOSE); + box.upper = conditions.bars[zIDX].FindHighest(idx, MODE_CLOSE); + } + + // + // Summarize Result ... + result = box.IsValid(); + + // + // Cleanup Resources ... + + // + if (!result) + { + box.Clean(); + } + + // + selected.Clean(); + lastBullish.Clean(); + lastBearish.Clean(); + + // + return result; +} + +// \ No newline at end of file diff --git a/BKPS/14040316/Helpers/x-saherelm.x121.xcc.helper.mq5 b/BKPS/14040316/Helpers/x-saherelm.x121.xcc.helper.mq5 new file mode 100644 index 0000000..6771036 --- /dev/null +++ b/BKPS/14040316/Helpers/x-saherelm.x121.xcc.helper.mq5 @@ -0,0 +1,259 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCX121XCCHelper +// 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.x-helper.class.mq5" + +// +// Definitions ... + +// +// Input Models ... +struct X121XCCInputs +{ + // + // Props ... + + // + // Chart Style ... + ENUM_CHART_MODE mode; // Mode + color upColor; // Up Color + color downColor; // Down Color + color lineColor; // Line mode and Doji candlestick Color + color bearishColor; // Bullish Color + color bullishColor; // Bearish Color + color volumesColor; // Volumes Color + + // + // Presentation ... + bool showCandles; // Show Candles + + // + // Constructor(s) ... + X121XCCInputs() + { + // + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + mode = CHART_CANDLES; + + // + upColor = CLR_NONE; + downColor = CLR_NONE; + lineColor = CLR_NONE; + bearishColor = CLR_NONE; + bullishColor = CLR_NONE; + volumesColor = CLR_NONE; + + // + showCandles = false; + + // + ZeroMemory(this); + } + + // + // Default ... + void Default() + { + // + mode = CHART_CANDLES; + + // + upColor = clrLime; + downColor = clrRed; + lineColor = clrLime; + bearishColor = clrRed; + bullishColor = clrLime; + volumesColor = clrGreen; + // + showCandles = true; + } + + // + // Hide all Visible Buffers ... + void Hide() + { + showCandles = 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 XCX121XCCHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructors ... + XCX121XCCHelper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCX121XCCHelper() + { + mInputs.Clean(); + } + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + X121XCCInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.xcc", + // + // Inputs ... + // + // Chart Style ... + "", + mInputs.mode, // Mode + mInputs.upColor, // Up Color + mInputs.downColor, // Down Color + mInputs.lineColor, // Line mode and Doji candlestick Color + mInputs.bullishColor, // Bearish Color + mInputs.bearishColor, // Bullish Color + mInputs.volumesColor, // Volumes Color + // + // Presentation ... + "", + mInputs.showCandles // Show Candles + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + X121XCCInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + X121XCCInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + X121XCCInputs mInputs; // Inputs ... +}; + +// +// Tools ... \ No newline at end of file diff --git a/BKPS/14040316/Helpers/x-saherelm.x121.xct.helper.mq5 b/BKPS/14040316/Helpers/x-saherelm.x121.xct.helper.mq5 new file mode 100644 index 0000000..6c5284e --- /dev/null +++ b/BKPS/14040316/Helpers/x-saherelm.x121.xct.helper.mq5 @@ -0,0 +1,241 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCX121XCTHelper +// 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.x-helper.class.mq5" + +// +// Definitions ... + +// +// Input Models ... +struct X121XCTInputs +{ + // + // Props ... + + // + string font; // Font + int fontSize; // Font Size; + color clr; // Text Color + ENUM_BASE_CORNER corner; // Text Position + + // + // Presentation ... + bool showCandleTime; // Show Candle Time + + // + // Constructor(s) ... + X121XCTInputs() + { + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + font = NULL; + fontSize = 15; + clr = CLR_NONE; + corner = CORNER_RIGHT_LOWER; + + // + // Presentation ... + showCandleTime = false; + + // + ZeroMemory(this); + } + + // + // Default ... + void Default() + { + // + font = "Arial"; + fontSize = 15; + clr = clrYellow; + corner = CORNER_RIGHT_LOWER; + + // + // Presentation ... + showCandleTime = true; + } + + // + // Hide all Visible Buffers ... + void Hide() + { + 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 XCX121XCTHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructors ... + XCX121XCTHelper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCX121XCTHelper() + { + mInputs.Clean(); + } + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + X121XCTInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.xct", + // + // Inputs ... + mInputs.fontSize, // Font Size ... + mInputs.font, // Font ... + 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 ... + + // + X121XCTInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + X121XCTInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + X121XCTInputs mInputs; // Inputs ... +}; + +// +// Tools ... \ No newline at end of file diff --git a/BKPS/14040316/Indicators/x-saherelm.x121.xcatb.mq5 b/BKPS/14040316/Indicators/x-saherelm.x121.xcatb.mq5 new file mode 100644 index 0000000..81c63b5 --- /dev/null +++ b/BKPS/14040316/Indicators/x-saherelm.x121.xcatb.mq5 @@ -0,0 +1,2706 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XCATB +// Description: Integrates All Requirements inside +// this indicator for analyse Markets to +// Detect Trigger Blocks ... +// +// - HK Bars; +// - ATR Band; +// - Signal Bars; +// - Parabolic Sar; +// - HK Signal Bars; +// - Peaks and Vales; +// - Peaks and Vales Goldens; +// - Trending Average Prices; +// +// - ATR; +// - RSI; +// - ADX; +// - DELTA; +// - VOLUME; +// +// 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 XCATB Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121 XCATB" + +// +// Imports ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +input group "Market"; + +// +// Short ... +input ENUM_X_PERIOD_METHOD scMethod = X_PERIOD_AUTO; // How to Find Short Period +input ENUM_TIMEFRAMES scPeriod = NULL; // Short Period + +// +// Medium ... +input ENUM_X_PERIOD_METHOD mcMethod = X_PERIOD_AUTO; // How to Find Medium Period +input ENUM_TIMEFRAMES mcPeriod = NULL; // Medium Period + +// +// Long ... +input ENUM_X_PERIOD_METHOD lcMethod = X_PERIOD_AUTO; // How to Find Long Period +input ENUM_TIMEFRAMES lcPeriod = NULL; // Long Period + +// +// Hind ... +input ENUM_X_PERIOD_METHOD hcMethod = X_PERIOD_AUTO; // How to Find Hind Period +input ENUM_TIMEFRAMES hcPeriod = NULL; // Hind Period + +// +// Select Trending Cycle ... +// this Cycle Used for All Calculations ... +input ENUM_X_MARKET_CYCLES appliedCycle = X_MARKET_CYCLE_HIND; // Applied Cycle + +// +// Presentation ... +input group "Presentation"; +input bool showBars = true; // Show Bars +input bool showKI = false; // Show KI +input bool showPV = false; // Show PV +input bool showPVGolden = false; // Show PV Golden +input bool showSar = false; // Show Sar +input bool showTrend = false; // Show Trend +input bool showATRBand = false; // Show ATR Band +input bool showSignalBars = false; // Show Signal Bars +input bool showHKSignalBars = false; // Show Hiken Ashi Signal Bars + +// +input int startCalculationForLastBars = 1500; // Calculate Last n Bars + +// +// Non Inputs ... +double sarStep = 0.02; // Step +double sarMax = 0.2; // Maximum +double rsiOBLevel = 70.0; // RSI OB Level +double rsiOSLevel = 30.0; // RSI OS Level +double adxThreshold = 25.0; // ADX Threshold +int kiLength = 144; // KI Length +int sarArrowCode = 159; // Parabolic Sar Arrow Code +int peakArrowCode = 159; // Peaks Arrow Code +int valeArrowCode = 159; // Vales Arrow Code +double atrMultiplier = 1.5; // ATR Band Multiplier +bool showShortCycle = false; // Show Short Cycle Range +bool showMediumCycle = false; // Show Medium Cycle Range +bool showLongCycle = false; // Show Long Cycle Range +bool showHindCycle = false; // Show Hind Cycle Range +ENUM_MA_METHOD trendMode = MODE_SMA; // Trend Mode +ENUM_SERIESMODE upperMode = MODE_HIGH; // Peak Method +ENUM_SERIESMODE lowerMode = MODE_LOW; // Vale Method +ENUM_X_PRICE atrUpperPriceType = X_PRICE_HIGH; // ATR Upper Zone Applied To +ENUM_X_PRICE atrLowerPriceType = X_PRICE_LOW; // ATR Lower Zone Applied To +ENUM_APPLIED_PRICE rsiAppliedTo = PRICE_CLOSE; // RSI Applied To +ENUM_APPLIED_PRICE trendAppliedTo = PRICE_MEDIAN; // Trend Applied To +ENUM_X_MA_METHOD atrSignalMethod = X_MA_MODE_EMA; // ATR Signalling Method +ENUM_X_MA_METHOD barsSignalMethod = X_MA_MODE_EMA; // Bars Signalling Method +ENUM_X_MA_METHOD deltaSignalMethod = X_MA_MODE_EMA; // Delta Signalling Method +ENUM_X_MA_METHOD hkSignalBarMethod = X_MA_MODE_EMA; // Hiken Ashi Signal Method +ENUM_X_MA_METHOD volumeSignalMethod = X_MA_MODE_EMA; // Volume Signalling Method + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#define bullishState 1 +#define neuturalState 0 +#define bearishState -1 + +// +#define emptyValue 0.0 + +// +// Buffers ... + +// +#property indicator_chart_window + +// +// Plot: 18 +// Color: 4 +// Bar: 8 +// Data Buffer: 29 +#property indicator_buffers 50 +#property indicator_plots 19 + +// +// Plot Buffers ... + +// +// SAR ... + +// +#define sarBufferIndex 0 +#define sarBufferPlotIndex 0 +double sarBuffer[]; + +// +#define sarColorBufferIndex 1 +double sarColorBuffer[]; + +// +#property indicator_label1 "SAR" +#property indicator_type1 DRAW_COLOR_ARROW +#property indicator_color1 CLR_NONE, clrLime, clrRed, clrGray +#property indicator_width1 2 + +// +// PEAKS ... + +// +#define peakBufferIndex 2 +#define peakBufferPlotIndex 1 +double peakBuffer[]; + +// +#property indicator_label2 "PEAK" +#property indicator_type2 DRAW_ARROW +#property indicator_color2 clrMagenta +#property indicator_width2 1 + +// +// VALES ... + +// +#define valeBufferIndex 3 +#define valeBufferPlotIndex 2 +double valeBuffer[]; + +// +#property indicator_label3 "VALE" +#property indicator_type3 DRAW_ARROW +#property indicator_color3 clrAqua +#property indicator_width3 1 + +// +// PEAKS Golden ... + +// +#define peakGoldenBufferIndex 4 +#define peakGoldenBufferPlotIndex 3 +double peakGoldenBuffer[]; + +// +#property indicator_label4 "PEAK Golden" +#property indicator_type4 DRAW_LINE +#property indicator_color4 clrMagenta +#property indicator_style4 STYLE_DOT +#property indicator_width4 1 + +// +// VALE Golden ... + +// +#define valeGoldenBufferIndex 5 +#define valeGoldenBufferPlotIndex 4 +double valeGoldenBuffer[]; + +// +#property indicator_label5 "VALES Golden" +#property indicator_type5 DRAW_LINE +#property indicator_color5 clrAqua +#property indicator_style5 STYLE_DOT +#property indicator_width5 1 + +// +// ATR ... + +// +// Upper ... + +// +#define atrUpperBufferIndex 6 +#define atrUpperBufferPlotIndex 5 +double atrUpperBuffer[]; + +// +#property indicator_label6 "XATRU" +#property indicator_type6 DRAW_LINE +#property indicator_color6 clrYellow +#property indicator_style6 STYLE_SOLID +#property indicator_width6 1 + +// +// Lower ... + +// +#define atrLowerBufferIndex 7 +#define atrLowerBufferPlotIndex 6 +double atrLowerBuffer[]; + +// +#property indicator_label7 "XATRL" +#property indicator_type7 DRAW_LINE +#property indicator_color7 clrYellow +#property indicator_style7 STYLE_SOLID +#property indicator_width7 1 + +// +// TREND ... + +// +#define trendBufferIndex 8 +#define trendBufferPlotIndex 7 +double trendBuffer[]; + +// +#define trendColorBufferIndex 9 +double trendColorBuffer[]; + +// +#property indicator_label8 "Trend" +#property indicator_type8 DRAW_COLOR_LINE +#property indicator_color8 CLR_NONE, clrAqua, clrMagenta, clrGray +#property indicator_style8 STYLE_SOLID +#property indicator_width8 2 + +// +// Signal Bar ... + +// +#define sBarOpenBufferIndex 10 +double sBarOpenBuffer[]; + +// +#define sBarHighBufferIndex 11 +double sBarHighBuffer[]; + +// +#define sBarLowBufferIndex 12 +double sBarLowBuffer[]; + +// +#define sBarCloseBufferIndex 13 +double sBarCloseBuffer[]; + +// +#define sBarColorBufferIndex 14 +double sBarColorBuffer[]; + +// +#define sBarBufferPlotIndex 8 +#property indicator_label9 "XSGB Open;XSGB High;XSGB Low;XSGB Close" +#property indicator_type9 DRAW_COLOR_CANDLES +#property indicator_color9 CLR_NONE, clrLime, clrRed + +// +// XHK SIGNAL ... + +// +#define hkSBarOpenBufferIndex 15 +double hkSBarOpenBuffer[]; + +// +#define hkSBarHighBufferIndex 16 +double hkSBarHighBuffer[]; + +// +#define hkSBarLowBufferIndex 17 +double hkSBarLowBuffer[]; + +// +#define hkSBarCloseBufferIndex 18 +double hkSBarCloseBuffer[]; + +// +#define hkSBarColorBufferIndex 19 +double hkSBarColorBuffer[]; + +// +#define hkSBarBufferPlotIndex 9 +#property indicator_label10 "XHKSGB Open;XHKSGB High;XHKSGB Low;XHKSGB Close" +#property indicator_type10 DRAW_COLOR_CANDLES +#property indicator_color10 CLR_NONE, clrAqua, clrMagenta + +// +// CYCLES Range ... + +// +// SHORT ... + +// +#define sHHBufferIndex 20 +#define sHHBufferPlotIndex 10 +double sHHBuffer[]; + +// +#property indicator_label11 "SH" +#property indicator_type11 DRAW_LINE +#property indicator_color11 clrGray +#property indicator_style11 STYLE_DOT +#property indicator_width11 1 + +// +#define sLLBufferIndex 21 +#define sLLBufferPlotIndex 11 +double sLLBuffer[]; + +// +#property indicator_label12 "SL" +#property indicator_type12 DRAW_LINE +#property indicator_color12 clrGray +#property indicator_style12 STYLE_DOT +#property indicator_width12 1 + +// +// MEDIUM ... + +// +#define mHHBufferIndex 22 +#define mHHBufferPlotIndex 12 +double mHHBuffer[]; + +// +#property indicator_label13 "MH" +#property indicator_type13 DRAW_LINE +#property indicator_color13 clrIndigo +#property indicator_style13 STYLE_DOT +#property indicator_width13 1 + +// +#define mLLBufferIndex 23 +#define mLLBufferPlotIndex 13 +double mLLBuffer[]; + +// +#property indicator_label14 "ML" +#property indicator_type14 DRAW_LINE +#property indicator_color14 clrIndigo +#property indicator_style14 STYLE_DOT +#property indicator_width14 1 + +// +// LONG ... + +// +#define lHHBufferIndex 24 +#define lHHBufferPlotIndex 14 +double lHHBuffer[]; + +// +#property indicator_label15 "LH" +#property indicator_type15 DRAW_LINE +#property indicator_color15 clrGoldenrod +#property indicator_style15 STYLE_DOT +#property indicator_width15 1 + +// +#define lLLBufferIndex 25 +#define lLLBufferPlotIndex 15 +double lLLBuffer[]; + +// +#property indicator_label16 "LL" +#property indicator_type16 DRAW_LINE +#property indicator_color16 clrGoldenrod +#property indicator_style16 STYLE_DOT +#property indicator_width16 1 + +// +// HIND ... + +// +#define hHHBufferIndex 26 +#define hHHBufferPlotIndex 16 +double hHHBuffer[]; + +// +#property indicator_label17 "HH" +#property indicator_type17 DRAW_LINE +#property indicator_color17 clrBrown +#property indicator_style17 STYLE_DOT +#property indicator_width17 1 + +// +#define hLLBufferIndex 27 +#define hLLBufferPlotIndex 17 +double hLLBuffer[]; + +// +#property indicator_label18 "HL" +#property indicator_type18 DRAW_LINE +#property indicator_color18 clrBrown +#property indicator_style18 STYLE_DOT +#property indicator_width18 1 + +// +// KI ... + +// +#define kiBufferIndex 28 +#define kiBufferPlotIndex 18 +double kiBuffer[]; + +// +#define kiColorBufferIndex 29 +double kiColorBuffer[]; + +// +#property indicator_label19 "KI" +#property indicator_type19 DRAW_COLOR_LINE +#property indicator_color19 CLR_NONE, clrGreen, clrRed, clrGray +#property indicator_style19 STYLE_DASHDOTDOT +#property indicator_width19 2 + +// +// Data Buffers ... + +// +#define mLastBufferIndex 29 + +// +// SAR ... + +// +#define sarStateBufferIndex mLastBufferIndex + 1 +double sarStateBuffer[]; + +// +// TREND State ... + +// +#define trendStateBufferIndex mLastBufferIndex + 2 +double trendStateBuffer[]; + +// +// RSI ... + +// +#define rsiBufferIndex mLastBufferIndex + 3 +double rsiBuffer[]; + +// +// ADX ... + +// +#define adxBufferIndex mLastBufferIndex + 4 +double adxBuffer[]; + +// +#define adxpBufferIndex mLastBufferIndex + 5 +double adxpBuffer[]; + +// +#define adxnBufferIndex mLastBufferIndex + 6 +double adxnBuffer[]; + +// +// DELTA ... + +// +#define deltaBufferIndex mLastBufferIndex + 7 +double deltaBuffer[]; + +// +#define deltaSignalBufferIndex mLastBufferIndex + 8 +double deltaSignalBuffer[]; + +// +// VOLUMES ... + +// +#define bullishVolumeBufferIndex mLastBufferIndex + 9 +double bullishVolumeBuffer[]; + +// +#define bearishVolumeBufferIndex mLastBufferIndex + 10 +double bearishVolumeBuffer[]; + +// +#define bullishVolumeSignalBufferIndex mLastBufferIndex + 11 +double bullishVolumeSignalBuffer[]; + +// +#define bearishVolumeSignalBufferIndex mLastBufferIndex + 12 +double bearishVolumeSignalBuffer[]; + +// +// ATR ... + +// +#define atrBufferIndex mLastBufferIndex + 13 +double atrBuffer[]; + +// +#define atrUpperRawBufferIndex mLastBufferIndex + 14 +double atrUpperRawBuffer[]; + +// +#define atrLowerRawBufferIndex mLastBufferIndex + 15 +double atrLowerRawBuffer[]; + +// +// HK ... + +// +#define openHKBufferIndex mLastBufferIndex + 16 +double openHKBuffer[]; + +// +#define highHKBufferIndex mLastBufferIndex + 17 +double highHKBuffer[]; + +// +#define lowHKBufferIndex mLastBufferIndex + 18 +double lowHKBuffer[]; + +// +#define closeHKBufferIndex mLastBufferIndex + 19 +double closeHKBuffer[]; + +// +// KI ... + +// +#define kiStateBufferIndex mLastBufferIndex + 20 +double kiStateBuffer[]; + +// +// Variables, Properties and etc ... + +// +int limit; + +// +int maxLength; + +// +int firstBarIndex; + +// +// Bars Color Variables ... +color _upColor = clrLime; +color _downColor = clrRed; +color _lineColor = clrLime; +color _bullishColor = clrLime; +color _bearishColor = clrRed; + +// +// XMarketCycle sc; +int mSCLength = 0; +ENUM_TIMEFRAMES mSCPeriod = NULL; + +// +// XMarketCycle mc; +int mMCLength = 0; +ENUM_TIMEFRAMES mMCPeriod = NULL; + +// +// XMarketCycle lc; +int mLCLength = 0; +ENUM_TIMEFRAMES mLCPeriod = NULL; + +// +// XMarketCycle hc; +int mHCLength = 0; +ENUM_TIMEFRAMES mHCPeriod = NULL; + +// +// Applied Cycle ... +int mAppliedLength; +ENUM_TIMEFRAMES mAppliedPeriod = NULL; + +// +// Handlers ... +int atrHandler = INVALID_HANDLE; +int sarHandler = INVALID_HANDLE; +int rsiHandler = INVALID_HANDLE; +int adxHandler = INVALID_HANDLE; +int trendHandler = INVALID_HANDLE; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + bool has = false; + + // + ReadBarStyle(); + + // + // Validate Inputs ... + has = ValidateInputs(); + if (!has) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + has = InitCycles(); + if (!has) + { + return INIT_FAILED; + } + + // + // 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(); + + // + // Initial Requirements ... + has = InitRequirements(); + if (!has) + { + return INIT_FAILED; + } + + // + if (showBars) + { + ShowBars(); + } + else + { + HideBars(); + } + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; + + // +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +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 + + // + ShowBars(); + + // + // De Initialize all Handlers and etc ... + IndicatorRelease(atrHandler); + IndicatorRelease(sarHandler); + IndicatorRelease(rsiHandler); + IndicatorRelease(adxHandler); + IndicatorRelease(trendHandler); +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // 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); + + // + // Validate Calculated Bars ... + + // + // ATR ... + int atrCalculatedBars = BarsCalculated(atrHandler); + + // + // SAR ... + int sarCalculatedBars = BarsCalculated(sarHandler); + + // + // RSI ... + int rsiCalculatedBars = BarsCalculated(rsiHandler); + + // + // ADX ... + int adxCalculatedBars = BarsCalculated(adxHandler); + + // + // TREND ... + int trendCalculatedBars = BarsCalculated(trendHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // ATR ... + atrCalculatedBars >= maxLength && + // + // SAR ... + sarCalculatedBars >= maxLength && + // + // RSI ... + rsiCalculatedBars >= maxLength && + // + // ADX ... + adxCalculatedBars >= maxLength && + // + // TREND ... + trendCalculatedBars >= maxLength + // + ; + if (!isPassedRequiredCalculatedBars) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + + // + // ATR ... + int copiedAtrs = CopyBuffer(atrHandler, MAIN_LINE, 0, limit, atrBuffer); + + // + // SAR ... + int copiedSars = CopyBuffer(sarHandler, MAIN_LINE, 0, limit, sarBuffer); + + // + // RSI ... + int copiedRSIs = CopyBuffer(rsiHandler, MAIN_LINE, 0, limit, rsiBuffer); + + // + // ADX ... + int copiedADXs = CopyBuffer(adxHandler, MAIN_LINE, 0, limit, adxBuffer); + + // + // ADX Plus ... + int copiedADXPs = CopyBuffer(adxHandler, PLUSDI_LINE, 0, limit, adxpBuffer); + + // + // ADX Negative ... + int copiedADXNs = CopyBuffer(adxHandler, MINUSDI_LINE, 0, limit, adxnBuffer); + + // + // TREND ... + int copiedTrends = CopyBuffer(trendHandler, MAIN_LINE, 0, limit, trendBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // ATR ... + copiedAtrs >= limit && + // + // SAR ... + copiedSars >= limit && + // + // RSI ... + copiedRSIs >= limit && + // + // TREND ... + copiedTrends >= limit + // + ; + if (!isPassedRequiredCopiedItems) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + if (prev_calculated == 0) + { + // + string message = "History Finished ..."; + Print(message); + } + + // + return rates_total; +} + +// +// Custom Functions ... + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + // + IndicatorSetInteger(INDICATOR_DIGITS, _Digits); + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + result = + // + sarMax > 0 && + sarStep > 0 && + rsiOBLevel > 0 && + rsiOSLevel > 0 && + adxThreshold > 0 && + sarMax > sarStep && + atrMultiplier > 0 && + // + IsValid(appliedCycle) && + // + IsValid(atrUpperPriceType) && + IsValid(atrLowerPriceType) && + // + // CYCLES ... + (IsValid(scMethod, scPeriod) && + IsValid(mcMethod, mcPeriod) && + IsValid(lcMethod, lcPeriod) && + IsValid(hcMethod, hcPeriod)) + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(mSCLength, mMCLength); + result = MathMax(result, mLCLength); + result = MathMax(result, mHCLength); + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + + // + // SAR ... + + // + ArraySetAsSeries(sarBuffer, true); + SetIndexBuffer(sarBufferIndex, sarBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(sarBufferPlotIndex, PLOT_SHOW_DATA, showSar); + PlotIndexSetDouble(sarBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(sarBufferPlotIndex, PLOT_ARROW, sarArrowCode); + + // + ArraySetAsSeries(sarColorBuffer, true); + SetIndexBuffer(sarColorBufferIndex, sarColorBuffer, INDICATOR_COLOR_INDEX); + + // + ArraySetAsSeries(sarStateBuffer, true); + SetIndexBuffer(sarStateBufferIndex, sarStateBuffer, INDICATOR_CALCULATIONS); + + // + // PEAK / VALE ... + + // + ENUM_DRAW_TYPE pvDrawType = showPV ? DRAW_ARROW : DRAW_NONE; + + // + // PEAK ... + + // + ArraySetAsSeries(peakBuffer, true); + SetIndexBuffer(peakBufferIndex, peakBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(peakBufferPlotIndex, PLOT_SHOW_DATA, showPV); + PlotIndexSetInteger(peakBufferPlotIndex, PLOT_DRAW_TYPE, pvDrawType); + + // + PlotIndexSetDouble(peakBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(peakBufferPlotIndex, PLOT_ARROW, peakArrowCode); + + // + // VALE ... + + // + ArraySetAsSeries(valeBuffer, true); + SetIndexBuffer(valeBufferIndex, valeBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(valeBufferPlotIndex, PLOT_SHOW_DATA, showPV); + PlotIndexSetInteger(valeBufferPlotIndex, PLOT_DRAW_TYPE, pvDrawType); + + // + PlotIndexSetDouble(valeBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(valeBufferPlotIndex, PLOT_ARROW, valeArrowCode); + + // + // PV GOLDEN ... + + // + ENUM_DRAW_TYPE pvGoldenDrawType = showPVGolden ? DRAW_LINE : DRAW_NONE; + + // + // PEAK Golden ... + + // + ArraySetAsSeries(peakGoldenBuffer, true); + SetIndexBuffer(peakGoldenBufferIndex, peakGoldenBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(peakGoldenBufferPlotIndex, PLOT_SHOW_DATA, showPVGolden); + PlotIndexSetInteger(peakGoldenBufferPlotIndex, PLOT_DRAW_TYPE, pvGoldenDrawType); + + // + PlotIndexSetDouble(peakGoldenBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // VALE Golden ... + + // + ArraySetAsSeries(valeGoldenBuffer, true); + SetIndexBuffer(valeGoldenBufferIndex, valeGoldenBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(valeGoldenBufferPlotIndex, PLOT_SHOW_DATA, showPVGolden); + PlotIndexSetInteger(valeGoldenBufferPlotIndex, PLOT_DRAW_TYPE, pvGoldenDrawType); + + // + PlotIndexSetDouble(valeGoldenBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // ATR Band ... + + // + // UPPER ... + ENUM_DRAW_TYPE atrUpperDrawType = showATRBand ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(atrUpperBuffer, true); + SetIndexBuffer(atrUpperBufferIndex, atrUpperBuffer, INDICATOR_DATA); + + // + PlotIndexSetDouble(atrUpperBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(atrUpperBufferPlotIndex, PLOT_SHOW_DATA, showATRBand); + PlotIndexSetInteger(atrUpperBufferPlotIndex, PLOT_DRAW_TYPE, atrUpperDrawType); + + // + // LOWER ... + ENUM_DRAW_TYPE atrLowerDrawType = showATRBand ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(atrLowerBuffer, true); + SetIndexBuffer(atrLowerBufferIndex, atrLowerBuffer, INDICATOR_DATA); + + // + PlotIndexSetDouble(atrLowerBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(atrLowerBufferPlotIndex, PLOT_SHOW_DATA, showATRBand); + PlotIndexSetInteger(atrLowerBufferPlotIndex, PLOT_DRAW_TYPE, atrLowerDrawType); + + // + // TREND ... + + // + ArraySetAsSeries(trendBuffer, true); + SetIndexBuffer(trendBufferIndex, trendBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(trendBufferPlotIndex, PLOT_SHOW_DATA, showTrend); + PlotIndexSetDouble(trendBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(trendColorBuffer, true); + SetIndexBuffer(trendColorBufferIndex, trendColorBuffer, INDICATOR_COLOR_INDEX); + + // + ArraySetAsSeries(trendStateBuffer, true); + SetIndexBuffer(trendStateBufferIndex, trendStateBuffer, INDICATOR_CALCULATIONS); + + // + // SIGNAL Bar ... + + // + // Signal Bars Color ... + ArraySetAsSeries(sBarColorBuffer, true); + SetIndexBuffer(sBarColorBufferIndex, sBarColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Set EMPTY_VALUE on XHK Bar Buffer ... + PlotIndexSetDouble(sBarBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(sBarBufferPlotIndex, PLOT_SHOW_DATA, false); + + // + // Open ... + ArraySetAsSeries(sBarOpenBuffer, true); + SetIndexBuffer(sBarOpenBufferIndex, sBarOpenBuffer, INDICATOR_DATA); + + // + // High ... + ArraySetAsSeries(sBarHighBuffer, true); + SetIndexBuffer(sBarHighBufferIndex, sBarHighBuffer, INDICATOR_DATA); + + // + // Low ... + ArraySetAsSeries(sBarLowBuffer, true); + SetIndexBuffer(sBarLowBufferIndex, sBarLowBuffer, INDICATOR_DATA); + + // + // Close ... + ArraySetAsSeries(sBarCloseBuffer, true); + SetIndexBuffer(sBarCloseBufferIndex, sBarCloseBuffer, INDICATOR_DATA); + + // + // XHK SIGNAL Bar ... + + // + // HK Bars Color ... + ArraySetAsSeries(hkSBarColorBuffer, true); + SetIndexBuffer(hkSBarColorBufferIndex, hkSBarColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Set EMPTY_VALUE on XHK Bar Buffer ... + PlotIndexSetDouble(hkSBarBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(hkSBarBufferPlotIndex, PLOT_SHOW_DATA, false); + + // + // Open ... + ArraySetAsSeries(hkSBarOpenBuffer, true); + SetIndexBuffer(hkSBarOpenBufferIndex, hkSBarOpenBuffer, INDICATOR_DATA); + + // + // High ... + ArraySetAsSeries(hkSBarHighBuffer, true); + SetIndexBuffer(hkSBarHighBufferIndex, hkSBarHighBuffer, INDICATOR_DATA); + + // + // Low ... + ArraySetAsSeries(hkSBarLowBuffer, true); + SetIndexBuffer(hkSBarLowBufferIndex, hkSBarLowBuffer, INDICATOR_DATA); + + // + // Close ... + ArraySetAsSeries(hkSBarCloseBuffer, true); + SetIndexBuffer(hkSBarCloseBufferIndex, hkSBarCloseBuffer, INDICATOR_DATA); + + // + // CYCLES ... + + // + // SHORT ... + + // + ENUM_DRAW_TYPE sDrawType = showShortCycle ? DRAW_LINE : DRAW_NONE; + + // + // HH ... + + // + ArraySetAsSeries(sHHBuffer, true); + SetIndexBuffer(sHHBufferIndex, sHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(sHHBufferPlotIndex, PLOT_SHOW_DATA, showShortCycle); + PlotIndexSetInteger(sHHBufferPlotIndex, PLOT_DRAW_TYPE, sDrawType); + PlotIndexSetDouble(sHHBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LL ... + + // + ArraySetAsSeries(sLLBuffer, true); + SetIndexBuffer(sLLBufferIndex, sLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(sLLBufferPlotIndex, PLOT_SHOW_DATA, showShortCycle); + PlotIndexSetInteger(sLLBufferPlotIndex, PLOT_DRAW_TYPE, sDrawType); + PlotIndexSetDouble(sLLBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // MEDIUM ... + + // + ENUM_DRAW_TYPE mDrawType = showMediumCycle ? DRAW_LINE : DRAW_NONE; + + // + // HH ... + + // + ArraySetAsSeries(mHHBuffer, true); + SetIndexBuffer(mHHBufferIndex, mHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(mHHBufferPlotIndex, PLOT_SHOW_DATA, showMediumCycle); + PlotIndexSetInteger(mHHBufferPlotIndex, PLOT_DRAW_TYPE, mDrawType); + PlotIndexSetDouble(mHHBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LL ... + + // + ArraySetAsSeries(mLLBuffer, true); + SetIndexBuffer(mLLBufferIndex, mLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(mLLBufferPlotIndex, PLOT_SHOW_DATA, showMediumCycle); + PlotIndexSetInteger(mLLBufferPlotIndex, PLOT_DRAW_TYPE, mDrawType); + PlotIndexSetDouble(mLLBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LONG ... + + // + ENUM_DRAW_TYPE lDrawType = showLongCycle ? DRAW_LINE : DRAW_NONE; + + // + // HH ... + + // + ArraySetAsSeries(lHHBuffer, true); + SetIndexBuffer(lHHBufferIndex, lHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(lHHBufferPlotIndex, PLOT_SHOW_DATA, showLongCycle); + PlotIndexSetInteger(lHHBufferPlotIndex, PLOT_DRAW_TYPE, lDrawType); + PlotIndexSetDouble(lHHBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LL ... + + // + ArraySetAsSeries(lLLBuffer, true); + SetIndexBuffer(lLLBufferIndex, lLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(lLLBufferPlotIndex, PLOT_SHOW_DATA, showLongCycle); + PlotIndexSetInteger(lLLBufferPlotIndex, PLOT_DRAW_TYPE, lDrawType); + PlotIndexSetDouble(lLLBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // HIND ... + + // + ENUM_DRAW_TYPE hDrawType = showHindCycle ? DRAW_LINE : DRAW_NONE; + + // + // HH ... + + // + ArraySetAsSeries(hHHBuffer, true); + SetIndexBuffer(hHHBufferIndex, hHHBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(hHHBufferPlotIndex, PLOT_SHOW_DATA, showHindCycle); + PlotIndexSetInteger(hHHBufferPlotIndex, PLOT_DRAW_TYPE, hDrawType); + PlotIndexSetDouble(hHHBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // LL ... + + // + ArraySetAsSeries(hLLBuffer, true); + SetIndexBuffer(hLLBufferIndex, hLLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(hLLBufferPlotIndex, PLOT_SHOW_DATA, showHindCycle); + PlotIndexSetInteger(hLLBufferPlotIndex, PLOT_DRAW_TYPE, hDrawType); + PlotIndexSetDouble(hLLBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + // KI ... + + // + ArraySetAsSeries(kiBuffer, true); + SetIndexBuffer(kiBufferIndex, kiBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(kiBufferPlotIndex, PLOT_SHOW_DATA, showKI); + PlotIndexSetDouble(kiBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); + + // + ArraySetAsSeries(kiColorBuffer, true); + SetIndexBuffer(kiColorBufferIndex, kiColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Data Buffers ... + + // + // RSI ... + ArraySetAsSeries(rsiBuffer, true); + SetIndexBuffer(rsiBufferIndex, rsiBuffer, INDICATOR_CALCULATIONS); + + // + // ADX ... + + // + ArraySetAsSeries(adxBuffer, true); + SetIndexBuffer(adxBufferIndex, adxBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(adxpBuffer, true); + SetIndexBuffer(adxpBufferIndex, adxpBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(adxnBuffer, true); + SetIndexBuffer(adxnBufferIndex, adxnBuffer, INDICATOR_CALCULATIONS); + + // + // DELTA ... + + // + ArraySetAsSeries(deltaBuffer, true); + SetIndexBuffer(deltaBufferIndex, deltaBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(deltaSignalBuffer, true); + SetIndexBuffer(deltaSignalBufferIndex, deltaSignalBuffer, INDICATOR_CALCULATIONS); + + // + // VOLUME ... + + // + ArraySetAsSeries(bullishVolumeBuffer, true); + SetIndexBuffer(bullishVolumeBufferIndex, bullishVolumeBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(bearishVolumeBuffer, true); + SetIndexBuffer(bearishVolumeBufferIndex, bearishVolumeBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(bullishVolumeSignalBuffer, true); + SetIndexBuffer(bullishVolumeSignalBufferIndex, bullishVolumeSignalBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(bearishVolumeSignalBuffer, true); + SetIndexBuffer(bearishVolumeSignalBufferIndex, bearishVolumeSignalBuffer, INDICATOR_CALCULATIONS); + + // + // ATR ... + + ArraySetAsSeries(atrBuffer, true); + SetIndexBuffer(atrBufferIndex, atrBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(atrUpperRawBuffer, true); + SetIndexBuffer(atrUpperRawBufferIndex, atrUpperRawBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(atrLowerRawBuffer, true); + SetIndexBuffer(atrLowerRawBufferIndex, atrLowerRawBuffer, INDICATOR_CALCULATIONS); + + // + // XHK ... + + // + ArraySetAsSeries(openHKBuffer, true); + SetIndexBuffer(openHKBufferIndex, openHKBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(highHKBuffer, true); + SetIndexBuffer(highHKBufferIndex, highHKBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(lowHKBuffer, true); + SetIndexBuffer(lowHKBufferIndex, lowHKBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(closeHKBuffer, true); + SetIndexBuffer(closeHKBufferIndex, closeHKBuffer, INDICATOR_CALCULATIONS); + + // + // KI ... + + // + ArraySetAsSeries(kiStateBuffer, true); + SetIndexBuffer(kiStateBufferIndex, kiStateBuffer, INDICATOR_CALCULATIONS); + + // +} + +/** + * Initial Market Cycles ... + * + * @return ( bool ) + */ +bool InitCycles() +{ + // + bool result = false; + + // + int cPeriodSeconds = PeriodSeconds(_Period); + + // + // Find Cycle Period ... + if (scMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mSCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_SHORT, + _Period // + ); + } + else + { + mSCPeriod = scPeriod; + } + + // + if (IsValid(mSCPeriod)) + { + mSCLength = PeriodSeconds(mSCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (mcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mMCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_MEDIUM, + _Period // + ); + } + else + { + mMCPeriod = mcPeriod; + } + + // + if (IsValid(mMCPeriod)) + { + mMCLength = PeriodSeconds(mMCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (lcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mLCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_LONG, + _Period // + ); + } + else + { + mLCPeriod = lcPeriod; + } + + // + if (IsValid(mLCPeriod)) + { + mLCLength = PeriodSeconds(mLCPeriod) / cPeriodSeconds; + } + + // + // Find Cycle Period ... + if (hcMethod == X_PERIOD_AUTO) + { + // + // Select Period ... + mHCPeriod = GetCyclePeriod( + X_MARKET_CYCLE_HIND, + _Period // + ); + } + else + { + mHCPeriod = hcPeriod; + } + + // + if (IsValid(mHCPeriod)) + { + mHCLength = PeriodSeconds(mHCPeriod) / cPeriodSeconds; + } + + // + result = mSCLength > 0 && + mMCLength > mSCLength && + mLCLength > mMCLength && + mHCLength > mLCLength; + + // + // Selecte Applied Cycle ... + if (result) + { + // + switch (appliedCycle) + { + // + case X_MARKET_CYCLE_SHORT: + // + mAppliedLength = mSCLength; + mAppliedPeriod = mSCPeriod; + break; + + // + case X_MARKET_CYCLE_MEDIUM: + // + mAppliedLength = mMCLength; + mAppliedPeriod = mMCPeriod; + break; + + // + case X_MARKET_CYCLE_LONG: + // + mAppliedLength = mLCLength; + mAppliedPeriod = mLCPeriod; + break; + + // + case X_MARKET_CYCLE_HIND: + // + mAppliedLength = mHCLength; + mAppliedPeriod = mHCPeriod; + break; + } + } + + // + return result; +} + +/** + * Initial all Indicator Requirements ... + * + * @return ( false ) + * + */ +bool InitRequirements() +{ + // + bool result = false; + + // + // Handlers ... + + // + // SAR ... + sarHandler = iSAR( + _Symbol, + _Period, + sarStep, + sarMax // + ); + result = sarHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // ATR ... + atrHandler = iATR( + _Symbol, + _Period, + mAppliedLength // + ); + result = atrHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // RSI ... + rsiHandler = iRSI( + _Symbol, + _Period, + mAppliedLength, + rsiAppliedTo // + ); + result = rsiHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // ADX ... + adxHandler = iADX( + _Symbol, + _Period, + mAppliedLength // + ); + result = adxHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // TREND ... + trendHandler = iMA( + _Symbol, + _Period, + mAppliedLength, + 0, + trendMode, + trendAppliedTo // + ); + result = trendHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; +} + +/** + * Calculate Custom Buffers ... + * + * @param barIndex: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateBuffers( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + if (barsLimit == 0) + { + // + barsLimit = ratesTotal; + firstBarIndex = barsLimit - 1; + } + else + { + firstBarIndex = startCalculationForLastBars; + } + + // + // bool canCalculate = true; + bool canCalculate = + barIndex <= barsLimit; + if (canCalculate) + { + // + // Calculate Values ... + CalculateValues( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + else + { + FillBuffersZero(barIndex); + } +} + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + kiColorBuffer[barIndex] = hideColorIDX; + sarColorBuffer[barIndex] = hideColorIDX; + trendColorBuffer[barIndex] = hideColorIDX; + + // + atrUpperRawBuffer[barIndex] = emptyValue; + atrLowerRawBuffer[barIndex] = emptyValue; +} + +// +// Custom Handlers ... + +/** + * Calculate Values ... + * + * @param barIndex: int, Specified Bar Index ... + * @param prevCalculated: int, Provides Previous Calculated Bars ... + * @param ratesTotal: int, Provides All Availabled Bars ... + * @param open: double Collection, Provides Open Prices Time Series ... + * @param high: double Collection, Provides High Prices Time Series ... + * @param close: double Collection, Provides Close Prices Time Series ... + * @param low: double Collection, Provides Low Prices Time Series ... + * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... + */ +void CalculateValues( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = barIndex + 1; + int maxBarIndex = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : ratesTotal; + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + // Cycle Ranges ... + CalculateCycleRanges( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // KI ... + CalculateKI( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // PV ... + CalculatePV( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // SAR ... + CalculateSAR( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // SBAR ... + CalculateSBar( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // HKBAR ... + CalculateHKBar( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // DELTA ... + CalculateDelta( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // TREND ... + CalculateTrend( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // VOLUME ... + CalculateVolume( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // ATR Band ... + CalculateATRBand( + barIndex, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); +} + +// +void CalculateCycleRanges( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // SHORT ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_SHORT, + sHHBuffer, + sLLBuffer // + ); + + // + // MEDIUM ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_MEDIUM, + mHHBuffer, + mLLBuffer // + ); + + // + // LONG ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_LONG, + lHHBuffer, + lLLBuffer // + ); + + // + // HIND ... + CalculateCycle( + barIndex, + X_MARKET_CYCLE_HIND, + hHHBuffer, + hLLBuffer // + ); +} + +// +void CalculateKI( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = barIndex + 1; + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + XOHCL iBar; + bool isInited = iBar.Init( + _Symbol, + _Period, + barIndex // + ); + + // + double iClose = close[barIndex]; + + // + // Calculate KI / Color ... + double lastKI = + isFirstBar + ? emptyValue + : kiBuffer[lastBarIndex]; + double iKI = lastKI; + if (isInited) + { + // + double iLLKI = iBar.FindLowest(kiLength, MODE_LOW); + double iHHKI = iBar.FindHighest(kiLength, MODE_HIGH); + + // + iKI = (iHHKI + iLLKI) / 2; + if (iLLKI == 0 || iHHKI == 0) + { + iKI = lastKI; + } + } + else + { + iKI = lastKI; + } + kiBuffer[barIndex] = iKI; + + // + double iKIState = neuturalState; + double iKIColor = neuturalColorIDX; + if (iClose > iKI) + { + // + iKIState = bullishState; + iKIColor = + !showKI + ? hideColorIDX + : bullishColorIDX; + } + else if (iClose < iKI) + { + // + iKIState = bearishState; + iKIColor = + !showKI + ? hideColorIDX + : bearishColorIDX; + } + kiStateBuffer[barIndex] = iKIState; + kiColorBuffer[barIndex] = iKIColor; + + // + iBar.Clean(); +} + +// +void CalculatePV( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = barIndex + 1; + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + double iSHH = sHHBuffer[barIndex]; + double iSLL = sLLBuffer[barIndex]; + + // + double iMHH = mHHBuffer[barIndex]; + double iMLL = mLLBuffer[barIndex]; + + // + double iLHH = lHHBuffer[barIndex]; + double iLLL = lLLBuffer[barIndex]; + + // + double iHHH = hHHBuffer[barIndex]; + double iHLL = hLLBuffer[barIndex]; + + // + // Calculate VALE ... + bool isVale = iSLL == iMLL && + iMLL == iLLL && + iLLL == iHLL; + double iPVale = + isFirstBar + ? emptyValue + : valeBuffer[lastBarIndex]; + double iVale = + isVale + ? iSLL + : iPVale; + valeBuffer[barIndex] = iVale; + + // + // Calculate PEAK ... + bool isPeak = iSHH == iMHH && + iMHH == iLHH && + iLHH == iHHH; + double iPPeak = + isFirstBar + ? emptyValue + : peakBuffer[lastBarIndex]; + double iPeak = + isPeak + ? iSHH + : iPPeak; + peakBuffer[barIndex] = iPeak; + + // + // GOLDEN ... + + XOHCL iBar; + bool isInited = iBar.Init( + _Symbol, + _Period, + barIndex // + ); + + // + // Calculate PV Gold ... + double lastPeakGold = + isFirstBar + ? emptyValue + : peakGoldenBuffer[lastBarIndex]; + double lastValeGold = + isFirstBar + ? emptyValue + : valeGoldenBuffer[lastBarIndex]; + double iPeakGold = lastPeakGold; + double iValeGold = lastValeGold; + if (isInited) + { + // + iPeakGold = iBar.FindHighest(mHCLength, MODE_CLOSE); + if (iPeakGold == 0) + { + iPeakGold = lastPeakGold; + } + + // + iValeGold = iBar.FindLowest(mHCLength, MODE_CLOSE); + if (iValeGold == 0) + { + iValeGold = lastValeGold; + } + } + else + { + // + iPeakGold = lastPeakGold; + iValeGold = lastValeGold; + } + + // + peakGoldenBuffer[barIndex] = iPeakGold; + valeGoldenBuffer[barIndex] = iValeGold; + + // + iBar.Clean(); +} + +// +void CalculateSAR( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + double iLow = low[barIndex]; + double iHigh = low[barIndex]; + double iSar = sarBuffer[barIndex]; + + // + bool isBullish = iSar < iLow; + bool isBearish = iSar > iHigh; + + // + double iSarState = isBullish + ? 1 + : isBearish + ? -1 + : 0; + double iSarColor = iSarState > 0 + ? bullishColorIDX + : iSarState < 0 + ? bearishColorIDX + : neuturalColorIDX; + sarStateBuffer[barIndex] = iSarState; + sarColorBuffer[barIndex] = showSar + ? iSarColor + : hideColorIDX; +} + +// +void CalculateSBar( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // Open ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + open, + sBarOpenBuffer, + barsSignalMethod // + ); + + // + // Close ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + close, + sBarCloseBuffer, + barsSignalMethod // + ); + + // + double min = MathMin(sBarCloseBuffer[barIndex], sBarOpenBuffer[barIndex]); + double max = MathMin(sBarCloseBuffer[barIndex], sBarOpenBuffer[barIndex]); + + // + sBarLowBuffer[barIndex] = min; + sBarHighBuffer[barIndex] = max; + + // + // Calculate HK Signal Color ... + double iSignalColorValue = + sBarOpenBuffer[barIndex] < sBarCloseBuffer[barIndex] + ? bullishColorIDX + : bearishColorIDX; + sBarColorBuffer[barIndex] = + showSignalBars + ? iSignalColorValue + : hideColorIDX; +} + +// +void CalculateHKBar( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = barIndex + 1; + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + double lastHKOpen = + isFirstBar + ? emptyValue + : openHKBuffer[lastBarIndex]; + double lastHKClose = + isFirstBar + ? emptyValue + : closeHKBuffer[lastBarIndex]; + + // + double iHKOpenValue = (lastHKOpen + lastHKClose) / 2; + double iHKCloseValue = (open[barIndex] + high[barIndex] + close[barIndex] + low[barIndex]) / 4; + double iHKHighValue = MathMax(high[barIndex], MathMax(iHKOpenValue, iHKCloseValue)); + double iHKLowValue = MathMin(low[barIndex], MathMin(iHKOpenValue, iHKCloseValue)); + + // + // Raw HK Buffers ... + openHKBuffer[barIndex] = iHKOpenValue; + highHKBuffer[barIndex] = iHKHighValue; + lowHKBuffer[barIndex] = iHKLowValue; + closeHKBuffer[barIndex] = iHKCloseValue; + + // + // XHK Signal ... + + // + // Open ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + openHKBuffer, + hkSBarOpenBuffer, + hkSignalBarMethod // + ); + + // + // Close ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + closeHKBuffer, + hkSBarCloseBuffer, + hkSignalBarMethod // + ); + + // + double min = MathMin(hkSBarCloseBuffer[barIndex], hkSBarOpenBuffer[barIndex]); + double max = MathMin(hkSBarCloseBuffer[barIndex], hkSBarOpenBuffer[barIndex]); + + // + hkSBarLowBuffer[barIndex] = min; + hkSBarHighBuffer[barIndex] = max; + + // + // Calculate HK Signal Color ... + double iHKSignalColorValue = + hkSBarOpenBuffer[barIndex] < hkSBarCloseBuffer[barIndex] + ? bullishColorIDX + : bearishColorIDX; + hkSBarColorBuffer[barIndex] = + showHKSignalBars + ? iHKSignalColorValue + : hideColorIDX; +} + +// +void CalculateDelta( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int lastBarIndex = barIndex + 1; + bool isFirstBar = + startCalculationForLastBars > 0 + ? barIndex == startCalculationForLastBars + : barIndex == firstBarIndex; + + // + double iClose = close[barIndex]; + double iOpen = open[barIndex]; + double iVolume = (double)iVolume(_Symbol, _Period, barIndex); + + // + bool isBullish = iClose > iOpen; + bool isBearish = iClose < iOpen; + + // + // DELTA ... + double lastDelta = + isFirstBar + ? emptyValue + : deltaBuffer[lastBarIndex]; + double iAppliedVolume = + isBullish + ? iVolume + : -1 * iVolume; + double iDelta = + lastDelta + iAppliedVolume; + deltaBuffer[barIndex] = iDelta; + + // + // Calculate Delta Signal ... + int deltaSignalsCount = iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + deltaBuffer, + deltaSignalBuffer, + deltaSignalMethod // + ); +} + +// +void CalculateTrend( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + double iLow = low[barIndex]; + double iHigh = high[barIndex]; + double iClose = close[barIndex]; + double iTrend = trendBuffer[barIndex]; + + // + bool isBullish = iTrend < iLow; + bool isBearish = iTrend > iHigh; + + // + double iTrendState = + isBullish + ? 1 + : isBearish + ? -1 + : 0; + double iTrendColor = + iTrendState > 0 + ? bullishColorIDX + : iTrendState < 0 + ? bearishColorIDX + : neuturalColorIDX; + trendStateBuffer[barIndex] = iTrendState; + trendColorBuffer[barIndex] = showTrend + ? iTrendColor + : hideColorIDX; +} + +// +void CalculateVolume( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + double iClose = close[barIndex]; + double iOpen = open[barIndex]; + double iVolume = (double)iVolume(_Symbol, _Period, barIndex); + + // + bool isBullish = iClose > iOpen; + bool isBearish = iClose < iOpen; + + // + double iBullishVolume = emptyValue; + double iBearishVolume = emptyValue; + if (isBullish) + { + iBullishVolume = iVolume; + } + else if (isBearish) + { + iBearishVolume = iVolume; + } + else + { + // + double iHalfVolume = iVolume / 2; + + // + iBullishVolume = iHalfVolume; + iBearishVolume = iHalfVolume; + } + bullishVolumeBuffer[barIndex] = iBullishVolume; + bearishVolumeBuffer[barIndex] = iBearishVolume; + + // + // Calculate Volume Signals ... + + // + int bullishVolumeSignalsCount = iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + bullishVolumeBuffer, + bullishVolumeSignalBuffer, + volumeSignalMethod // + ); + + // + int bearishVolumeSignalsCount = iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + bearishVolumeBuffer, + bearishVolumeSignalBuffer, + volumeSignalMethod // + ); +} + +// +void CalculateATRBand( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + double iATR = atrBuffer[barIndex]; + double iAppliedATR = atrMultiplier * iATR; + double iATRUpperPrice = GetAppliedPrice( + atrUpperPriceType, + open, + high, + low, + close, + barIndex // + ); + double iATRLowerPrice = GetAppliedPrice( + atrLowerPriceType, + open, + high, + low, + close, + barIndex // + ); + double iATRUpper = iATRUpperPrice + iAppliedATR; + double iATRLower = iATRLowerPrice - iAppliedATR; + atrUpperRawBuffer[barIndex] = iATRUpper; + atrLowerRawBuffer[barIndex] = iATRLower; + + // + bool canSignalATR = IsValid(atrSignalMethod); + if (canSignalATR) + { + // + // Upper ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + atrUpperRawBuffer, + atrUpperBuffer, + atrSignalMethod // + ); + + // + // Lower ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + barIndex, + mAppliedLength, + atrLowerRawBuffer, + atrLowerBuffer, + atrSignalMethod // + ); + } + else + { + // + atrUpperBuffer[barIndex] = iATRUpper; + atrLowerBuffer[barIndex] = iATRLower; + } +} + +/** + * Calculate Specified Market Cycle Info ... + * + * @param barIndex: Integer, Bar Index ... + * @param cycle: ENUM_X_MARKET_CYCLES member, Specified Cycle ... + * @param hhBuffer: Highest High Buffer Reference ... + * @param llBuffer: Lowest Low Buffer Reference ... + */ +void CalculateCycle( + int barIndex, + ENUM_X_MARKET_CYCLES cycle, + double &hhBuffer[], + double &llBuffer[] // +) +{ + // + XOHCL bar; + bool isBarInited = bar.Init( + _Symbol, + _Period, + barIndex + // + ); + if (!isBarInited) + { + return; + } + + // + int mLength = 0; + switch (cycle) + { + // + case X_MARKET_CYCLE_SHORT: + mLength = mSCLength; + break; + + // + case X_MARKET_CYCLE_MEDIUM: + mLength = mMCLength; + break; + + // + case X_MARKET_CYCLE_LONG: + mLength = mLCLength; + break; + + // + case X_MARKET_CYCLE_HIND: + mLength = mHCLength; + break; + } + + // + if (mLength == 0) + { + return; + } + + // + // Find Highest High ... + double hhValue = bar.FindHighest( + mLength, + upperMode // + ); + hhBuffer[barIndex] = hhValue; + + // + // Find Lowest Low ... + double llValue = bar.FindLowest( + mLength, + lowerMode // + ); + llBuffer[barIndex] = llValue; + + // + bar.Clean(); +} + +// +void ReadBarStyle() +{ + // + long chartId = ChartID(); + + // + _upColor = GetChartUpColor(chartId); + _downColor = GetChartDownColor(chartId); + _lineColor = GetChartLineColor(chartId); + _bullishColor = GetChartBullishColor(chartId); + _bearishColor = GetChartBearishColor(chartId); +} + +// +void ShowBars() +{ + // + long chartId = ChartID(); + + // + SetChartUpColor(_upColor, chartId); + SetChartDownColor(_downColor, chartId); + SetChartLineColor(_lineColor, chartId); + SetChartBullishColor(_bullishColor, chartId); + SetChartBearishColor(_bearishColor, chartId); +} + +// +void HideBars() +{ + // + long chartId = ChartID(); + + // + SetChartUpColor(CLR_NONE, chartId); + SetChartDownColor(CLR_NONE, chartId); + SetChartLineColor(CLR_NONE, chartId); + SetChartBullishColor(CLR_NONE, chartId); + SetChartBearishColor(CLR_NONE, chartId); +} + +// \ No newline at end of file diff --git a/BKPS/14040316/Indicators/x-saherelm.x121.xcc.mq5 b/BKPS/14040316/Indicators/x-saherelm.x121.xcc.mq5 new file mode 100644 index 0000000..2f45b84 --- /dev/null +++ b/BKPS/14040316/Indicators/x-saherelm.x121.xcc.mq5 @@ -0,0 +1,437 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Candle Styles +// --------------------------------------------------- +// Name: X121 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 X121 XCC Indicator" +#property strict + +// +// START Constants ... +// + +// +// Indicator Short Name ... +#define ShortName "X121 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 = clrGreen; // Up Color +input color downColor = clrRed; // Down Color +input color lineColor = clrGreen; // Line mode and Doji candlestick Color +input color bullishColor = clrGreen; // Bullish Color +input color bearishColor = clrRed; // 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( + 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; +} + +// +// 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/BKPS/14040316/Indicators/x-saherelm.x121.xct.mq5 b/BKPS/14040316/Indicators/x-saherelm.x121.xct.mq5 new file mode 100644 index 0000000..286882a --- /dev/null +++ b/BKPS/14040316/Indicators/x-saherelm.x121.xct.mq5 @@ -0,0 +1,262 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// --------------------------------------------- +// Name: X121 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 X121 XCT Indicator" +#property strict + +// +// START Constants ... +// + +// +#define ShortName "X121 XCT" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input int fontSize = 15; // Font Size +input string font = "Arial"; // Font +input color clr = clrYellow; // Text Color +input ENUM_BASE_CORNER corner = CORNER_RIGHT_LOWER; // Text Position + +// +input group "Presentation"; +input bool showTimer = 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 ... +// +bool isCreatedObject; +string tag; +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + + // + tag = ShortName + _Symbol + ToString(_Period); + + // + // 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 + + // + // Delete Object ... + ObjectDelete(0, tag); + + // + 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 ... +) +{ + // + if (!showTimer) + { + return rates_total; + } + + // + 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; + + // + if (IsValid(tag) && !isCreatedObject) + { + CreateIndicatorObject(); + } + + // + if (isCreatedObject) + { + ObjectSetString(0, tag, OBJPROP_TEXT, objText); + } + + // + 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 (!showTimer || + !IsValid(tag)) + { + return; + } + + // + isCreatedObject = ObjectCreate(0, tag, OBJ_LABEL, 0, 0, 0); + ObjectSetInteger(0, tag, OBJPROP_CORNER, corner); + ObjectSetInteger(0, tag, OBJPROP_XDISTANCE, 10); + ObjectSetInteger(0, tag, 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; + } + + // + int mFontSize = fontSize > 0 + ? fontSize + : 10; + + // + string mFont = IsValid(font) + ? font + : "Arial"; + + // + ObjectSetString(0, tag, OBJPROP_FONT, mFont); + ObjectSetInteger(0, tag, OBJPROP_COLOR, clr); + ObjectSetInteger(0, tag, OBJPROP_ANCHOR, Anchor); + ObjectSetInteger(0, tag, OBJPROP_FONTSIZE, mFontSize); +} + +// +// END Functions ... +// diff --git a/BKPS/14040316/Libraries/x-saherelm.common.extensions.lib.mq5 b/BKPS/14040316/Libraries/x-saherelm.common.extensions.lib.mq5 new file mode 100644 index 0000000..50719e6 --- /dev/null +++ b/BKPS/14040316/Libraries/x-saherelm.common.extensions.lib.mq5 @@ -0,0 +1,6759 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Common Library +// -------------------------------------- +// Name: XCommonExtensionsLib +// 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 + +// +#include "../Classes/x-saherelm.x-md5.class.mq5" +#include "../Libraries/x-saherelm.x-enums.lib.mq5" + +// +#include + +// +// Constants ... +#define X_MIN_SIZE 0 +#define X_INVALID_INDEX -1 + +// +// START Value Checkers ... +// + +// +// Check a Value Not Empty ... +template +bool NotEmpty(T value) +{ + return value != EMPTY_VALUE; +} + +// +// Check a Value Not Empty and Zero ... +template +bool NotEmptyZero(T value) +{ + return value != 0 && + value != EMPTY_VALUE; +} + +// +// END Value Checkers ... +// + +// +// START Validators ... +// + +/** + * Validate Strings ... + * + * @param value: string + * + * @return ( bool ) + */ +bool IsValid(string value) +{ + // + bool result = false; + + // + result = + // + value != NULL && + StringLen(value) > 0 + // + ; + + // + return result; +} +bool IsSpecifiedValid(string value) +{ + return IsValid(value); +} + +/** + * Validate Date ... + * + * @param value: datetime + * + * @return ( bool ) + */ +bool IsValid(datetime value) +{ + // + bool result = false; + + // + result = NotEmpty(value) && value != NULL; + + // + return result; +} +bool IsSpecifiedValid(datetime value) +{ + return IsValid(value); +} + +/** + * Validate Time Frame ... + * + * @param value: ENUM_TIMEFRAMES member ... + * + * @return ( bool ) + */ +bool IsValid(ENUM_TIMEFRAMES value) +{ + // + bool result = false; + + // + result = + // + value != NULL + // + ; + + // + return result; +} +bool IsSpecifiedValid(ENUM_TIMEFRAMES value) +{ + // + return IsValid(value); +} + +/** + * Validate Specific Period Mode ... + * + * @param mMethod: ENUM_X_PERIOD_METHOD member, Period Select Method ... + * @param mPeriod: ENUM_TIMEFRAMES member, Selected Period ... + * + * @return ( bool ) + */ +bool IsValid( + ENUM_X_PERIOD_METHOD mMethod, + ENUM_TIMEFRAMES mPeriod // +) +{ + // + bool result = false; + + // + result = + // + mMethod == X_PERIOD_NONE + ? false + : mMethod == X_PERIOD_MANUALLY + ? mPeriod != NULL + : mMethod == X_PERIOD_AUTO + ? true + : false + // + ; + + // + return result; +} +bool IsSpecifiedValid( + ENUM_X_PERIOD_METHOD mMethod, + ENUM_TIMEFRAMES mPeriod // +) +{ + return IsValid( + mMethod, + mPeriod // + ); +} + +/** + * Validate a Size Value ... + * + * @param value: int, Provided Size ... + * + * @return ( bool ) + */ +bool IsValidSize(int value) +{ + // + bool result = value > X_MIN_SIZE; + + // + return result; +} + +/** + * Check a Given Index is Valid or not ... + * + * @param value: int, Provided Index ... + * + * @return ( bool ) + */ +bool IsValidIndex(int value) +{ + return value >= X_MIN_SIZE; +} + +// +// END Validators ... +// + +// +// START Normalizations ... +// + +/** + * Normalize Symbol ... + * + * @param value: string, Provided Symbols ... + * + * @return ( string ) + */ +string NormalizeSymbol(string value) +{ + // + string result = value; + + // + if (!IsValid(result)) + { + result = _Symbol; + } + + // + return result; +} + +/** + * Normalize Time ... + * + * @param value: datetime, Provided Time ... + * + * @return ( datetime ) + */ +datetime NormalizeTime(datetime value) +{ + // + datetime result = value; + + // + if (!IsValid(result)) + { + result = TimeCurrent(); + } + + // + return result; +} + +/** + * Normalize Period ... + * + * @param value: ENUM_TIMEFRAMES member, Provided Period ... + * + * @return ( ENUM_TIMEFRAMES ) + */ +ENUM_TIMEFRAMES NormalizePeriod(ENUM_TIMEFRAMES value) +{ + // + ENUM_TIMEFRAMES result = value; + + // + if (!IsValid(value)) + { + result = _Period; + } + + // + return result; +} + +/** + * Normalize Market Cycle ... + * + * @param value: ENUM_X_MARKET_CYCLES, Provided Cycle ... + * + * @return ( ENUM_X_MARKET_CYCLES ) + */ +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; +} + +/** + * Normalize Price Boundary ... + * + * @param value: ENUM_X_BOUNDARY_PRICE, Provided Boundary Mode ... + * + * @return ( ENUM_X_BOUNDARY_PRICE ) + */ +ENUM_X_BOUNDARY_PRICE NormalizeBoundary(ENUM_X_BOUNDARY_PRICE value) +{ + // + ENUM_X_BOUNDARY_PRICE result = value; + + // + if (!IsValid(result)) + { + result = X_BOUNDARY_PRICE_HIGH_LOW; + } + + // + return result; +} + +/** + * Normalize Integer Value ... + * + * @param value: int, Provided Value ... + * @param min: int, Minimum Allowed Value ... + * @param max: int, Maximum Allowed Value ... + * + * @return ( int ) + */ +int NormalizeInt( + int value, + int min = 0, + int max = INT_MAX // +) +{ + // + if (value < min) + { + value = min; + } + + // + if (value > max) + { + value = max; + } + + // + return value; +} + +/** + * Normalize Double Value ... + * + * @param value: double, Provided Value ... + * @param min: double, Minimum Allowed Value ... + * @param max: double, Maximum Allowed Value ... + * + * @return ( double ) + */ +double NormalizeDouble( + double value, + double min = 0, + double max = DBL_MAX // +) +{ + // + if (value < min) + { + value = min; + } + + // + if (value > max) + { + value = max; + } + + // + return value; +} + +/** + * Normalize Index based on Collection ... + * + * @param index: int, Provided Index ... + * @param buffer: Collection Reference ... + */ +template +bool NormalizeIndex( + int &index, + T &buffer[] // +) +{ + // + bool result = false; + + // + int size = ArraySize(buffer); + result = IsValidSize(size); + if (!result) + { + return result; + } + + // + if (!IsValidIndex(index)) + { + index = X_MIN_SIZE; + } + + // + if (index > size - 1) + { + index = size - 1; + } + + // + result = IsValidIndex(index) && + index >= X_MIN_SIZE && + index < size; + + // + return result; +} + +/** + * Normalize Start and Count based on Specified Buffer ... + * + * @param start: int, Provided Start index ... + * @param count: int, Provided Number of Iteration ... + * @param buffer: Collection instance ... + */ +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 - start) + { + count = bufferSize - start; + } +} + +/** + * Normalize a Volume ... + * + * @param mVolume: double, Provided Volume ... + * @param mSymbol: string, Specified Symbol ... + * @param mLength: int, Provided Default floating Length ... + * + * @return ( double ) + */ +double NormalizeVolume( + double mVolume, + string mSymbol = NULL, + int mLength = 2 // +) +{ + // + double result = mVolume; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double maxAvailableVolume = SymbolInfoDouble(mSymbol, SYMBOL_VOLUME_MAX); + double minAvailableVolume = SymbolInfoDouble(mSymbol, SYMBOL_VOLUME_MIN); + + // + // Normalize Digits ... + int digits = GetDigits(minAvailableVolume); + + // + mLength = + mLength == 0 || mLength > digits + ? digits + : MathMin(mLength, digits); + + // + // Normalize Volume ... + result = NormalizeDouble(result, mLength); + + // + // Validate Result ... + if (result > maxAvailableVolume) + { + result = maxAvailableVolume; + } + else if (result < minAvailableVolume) + { + result = minAvailableVolume; + } + + // + return result; +} + +/** + * Normalize a Price Value ... + * + * @param mPrice: double, Provided Price ... + * @param mSymbol: string, Provided Symbol ... + * + * @return ( double ) + */ +double NormalizePrice( + double mPrice, + string mSymbol = NULL // +) +{ + // + 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; +} + +// +// END Normalizations ... +// + +// +// START Position ... +// + +/** + * Determine a Position type is Long or not ... + * + * @param value: ENUM_POSITION_TYPE member, Specified Type ... + * + * @return ( bool ) + */ +bool IsLong(ENUM_POSITION_TYPE value) +{ + // + bool result = value == POSITION_TYPE_BUY; + + // + return result; +} + +/** + * Determine a Position type is Long or not ... + * + * @param value: ENUM_ORDER_TYPE member, Specified Type ... + * + * @return ( bool ) + */ +bool IsLong(ENUM_ORDER_TYPE value) +{ + // + bool result = value == ORDER_TYPE_BUY; + + // + return result; +} + +/** + * Determine a Position type is Long or not ... + * + * @param value: ENUM_X_DIRECTION member, Specified Type ... + * + * @return ( bool ) + */ +bool IsLong(ENUM_X_DIRECTION value) +{ + // + bool result = value == X_DIRECTION_BULLISH; + + // + return result; +} + +/** + * Determine a Position type is Short or not ... + * + * @param value: ENUM_POSITION_TYPE member, Specified Type ... + * + * @return ( bool ) + */ +bool IsShort(ENUM_POSITION_TYPE value) +{ + // + bool result = value == POSITION_TYPE_SELL; + + // + return result; +} + +/** + * Determine a Position type is Short or not ... + * + * @param value: ENUM_ORDER_TYPE member, Specified Type ... + * + * @return ( bool ) + */ +bool IsShort(ENUM_ORDER_TYPE value) +{ + // + bool result = value == ORDER_TYPE_SELL; + + // + return result; +} + +/** + * Determine a Position type is Short or not ... + * + * @param value: ENUM_X_DIRECTION member, Specified Type ... + * + * @return ( bool ) + */ +bool IsShort(ENUM_X_DIRECTION value) +{ + // + bool result = value == X_DIRECTION_BEARISH; + + // + return result; +} + +/** + * Converts Opposit Direction Type ... + * + * @param value: ENUM_POSITION_TYPE member, Specified Type ... + * + * @return ( ENUM_POSITION_TYPE ) + */ +ENUM_POSITION_TYPE Opposit(ENUM_POSITION_TYPE value) +{ + // + ENUM_POSITION_TYPE result = NULL; + + // + bool isLong = IsLong(value); + result = isLong + ? POSITION_TYPE_SELL + : POSITION_TYPE_BUY; + + // + return result; +} + +/** + * Converts Opposit Direction Type ... + * + * @param value: ENUM_ORDER_TYPE member, Specified Type ... + * + * @return ( ENUM_ORDER_TYPE ) + */ +ENUM_ORDER_TYPE Opposit(ENUM_ORDER_TYPE value) +{ + // + ENUM_ORDER_TYPE result = NULL; + + // + bool isLong = IsLong(value); + result = isLong + ? ORDER_TYPE_SELL + : ORDER_TYPE_BUY; + + // + return result; +} + +/** + * Converts To String ... + * + * @param value: ENUM_POSITION_TYPE member ... + * + * @return ( string ) + */ +string ToString(ENUM_POSITION_TYPE value) +{ + // + string result = NULL; + + // + result = + // + IsLong(value) + ? "Long" + : "Short" + // + ; + + // + return result; +} + +/** + * Converts To String ... + * + * @param value: ENUM_ORDER_TYPE member ... + * + * @return ( string ) + */ +string ToString(ENUM_ORDER_TYPE value) +{ + // + string result = NULL; + + // + result = + // + IsLong(value) + ? "Long" + : "Short" + // + ; + + // + return result; +} + +/** + * Get Ask Price ... + * + * @param mSymbol: string, Provided Symbol ... + * + * @return ( double ) + */ +double GetAsk( + string mSymbol = NULL // +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double result = SymbolInfoDouble(mSymbol, SYMBOL_ASK); + + // + return result; +} + +/** + * Get Bid Price ... + * + * @param mSymbol: string, Provided Symbol ... + * + * @return ( double ) + */ +double GetBid( + string mSymbol = NULL // +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double result = SymbolInfoDouble(mSymbol, SYMBOL_BID); + + // + return result; +} + +/** + * Get Spread Price ... + * + * @param mSymbol: string, Provided Symbol ... + * + * @return ( double ) + */ +double GetSpread( + string mSymbol = NULL // +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double ask = GetAsk(mSymbol); + double bid = GetBid(mSymbol); + + // + double result = MathAbs(ask - bid); + + // + return result; +} + +/** + * Get Point Price ... + * + * @param mSymbol: string, Provided Symbol ... + * + * @return ( double ) + */ +double GetPoints( + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double result = SymbolInfoDouble(mSymbol, SYMBOL_POINT); + + // + return result; +} + +/** + * Converts Price to Point ... + * + * @param price: double, price ... + * @param mSymbol: string, Symbol ... + * + * @return ( double ) + */ +double PriceToPoint( + double mPrice, // the price amount which required to calculate + string mSymbol = NULL // Trading Symbol +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + mPrice = NormalizePrice(mPrice, mSymbol); + + // + double point = GetPoints(mSymbol); + result = mPrice / point; + + // + return result; +} + +/** + * Get Digits Length ... + * + * @param mSymbol: string, Provided Symbol ... + * + * @return ( double ) + */ +int GetDigits( + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + int result = (int)SymbolInfoInteger(mSymbol, SYMBOL_DIGITS); + + // + return result; +} + +/** + * Get Entry Price ... + * + * @param mSymbol: string, Provided Symbol ... + * @param type: ENUM_POSITION_TYPE member, Specified Entry type ... + * + * @return ( double ) + */ +double GetEntry( + string mSymbol = NULL, + ENUM_POSITION_TYPE type = POSITION_TYPE_BUY // +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + result = + IsLong(type) + ? GetAsk(mSymbol) + : GetBid(mSymbol); + result = NormalizePrice(result, mSymbol); + + // + return result; +} + +/** + * Get Entry Price ... + * + * @param mSymbol: string, Provided Symbol ... + * @param type: ENUM_X_DIRECTION member, Specified Entry type ... + * + * @return ( double ) + */ +double GetEntry( + string mSymbol = NULL, + ENUM_X_DIRECTION type = X_DIRECTION_BULLISH // +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + result = + IsBullish(type) + ? GetAsk(mSymbol) + : GetBid(mSymbol); + result = NormalizePrice(result, mSymbol); + + // + return result; +} + +/** + * Get Exit Price ... + * + * @param mSymbol: string, Provided Symbol ... + * @param type: ENUM_POSITION_TYPE member, Specified Exit type ... + * + * @return ( double ) + */ +double GetExit( + string mSymbol = NULL, + ENUM_POSITION_TYPE type = POSITION_TYPE_BUY // +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + result = + IsLong(type) + ? GetBid(mSymbol) + : GetAsk(mSymbol); + result = NormalizePrice(result, mSymbol); + + // + return result; +} + +/** + * Get Exit Price ... + * + * @param mSymbol: string, Provided Symbol ... + * @param type: ENUM_X_DIRECTION member, Specified Exit type ... + * + * @return ( double ) + */ +double GetExit( + string mSymbol = NULL, + ENUM_X_DIRECTION type = X_DIRECTION_BULLISH // +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + result = + IsBullish(type) + ? GetBid(mSymbol) + : GetAsk(mSymbol); + result = NormalizePrice(result, mSymbol); + + // + return result; +} + +/** + * Retrieve Current Tick ... + */ +bool GetTick( + string mSymbol, + MqlTick &tick // +) +{ + return SymbolInfoTick(mSymbol, tick); +} + +// +// END Position ... +// + +// +// START Tools ... +// + +/** + * Check Expert Running in Testing Mode or not ... + * + * @return ( bool ) + */ +bool IsRunningOnTestMode() +{ + // + bool result = false; + + // + // check programm mode ... + result = MQL5InfoInteger(MQL5_TESTING); + + // + return result; +} + +/** + * Find Chart ID ... + * + * @param mSymbol: string, Specified Symbol ... + * @param mPeriod: ENUM_TIMEFRAMES member, Specified Period ... + * + * @return ( long ) + */ +long FindChartID( + string mSymbol = NULL, + ENUM_TIMEFRAMES mPeriod = NULL // +) +{ + // + 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; +} + +/** + * Retrieve Available Symbols ... + * + * @param symbols: string Collection reference to Hold Symbols ... + * @param onlyInWatchList: bool, Force Extracts only Watch List Symbols ... + * + * @return ( int ) + */ +int GetAllSymbols( + string &symbols[], // Hold Result + bool onlyInWatchList = false // Specified Retrieve only Symbols which in Watch List +) +{ + // + int result = 0; + + // + Clean(symbols); + + // + int count = SymbolsTotal(onlyInWatchList); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + string iSymbol = SymbolName( + i, + onlyInWatchList // + ); + if (!IsValid(iSymbol)) + { + continue; + } + + // + Add( + iSymbol, + symbols // + ); + } + + // + result = ArraySize(symbols); + + // + return result; +} + +/** + * Filter Symbols Collections ... + * + * @param query: string, Provided Query to Search Symbols ... + * @param symbols: string, Collection resources to Hold's Filtered results ... + * @param onlyInWatchList: bool, Specified Apply Filter only on Watch List Symbols ... + * @param ignoreCase: bool, Ignore Case Sesitive ... + * @param querySeparator: string, Provided Separator of Query ... + * + * @return ( int ) + */ +int FilterSymbols( + string query, + string &symbols[], + bool onlyInWatchList = false, + bool ignoreCase = true, + string querySeparator = "," // If Provided means query is a Collection of Queries and need to be Splitted +) +{ + // + int result = 0; + + // + 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 // + ); + } + + // + string allSymbols[]; + int allSymbolsCount = GetAllSymbols( + allSymbols, + onlyInWatchList // + ); + 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 // + ); + } + } + + // + result = ArraySize(symbols); + + // + return result; +} + +/** + * Extract Symbols to Find Only USD Side Assets ... + * + * @param symbols: string, Collection resources to Hold's Filtered results ... + * @param onlyInWatchList: bool, Specified Apply Filter only on Watch List Symbols ... + * @param ignoreCase: bool, Ignore Case Sesitive ... + * @param querySeparator: string, Provided Separator of Query ... + * + * @return ( int ) + */ +int FilterUSDSymbols( + string &symbols[], + bool onlyInWatchList = false, + bool ignoreCase = true, + string querySeparator = "," // +) +{ + // + return FilterSymbols( + "USD", + symbols, + onlyInWatchList, + ignoreCase, + querySeparator // + ); +} + +/** + * Get Digits Length of Specified Double Value ... + * + * @param value: double, Provided Value ... + * + * @return ( int ) + */ +int GetDigits(double value) +{ + // + int d = 0; + double p = 1; + while (MathRound(value * p) / p != value) + { + p = MathPow(10, ++d); + } + + // + return d; +} + +/** + * Retrieve Specific Object Types Name ... + * + * @param t: T object reference ... + * + * @return ( string ) + * + */ +template +string GetTypeName(const T &t) +{ + return typename(T); +} + +/** + * Get Specified Types Token ... + * + * @param item: T, object reference ... + * + * @return ( string ) + */ +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; +} +template +string GetSpecificToken(T &item) +{ + return GetToken(item); +} + +/** + * Generate Unique Tags ... + * + * @param model: T, object reference ... + * + * @return ( string ) + */ +template +string GenerateTag(T &model) +{ + // + string result = ""; + + // + string tag = model.ToString(); + if (StringLen(tag) == 0) + { + return result; + } + + // + XSCMD5 *md5; + md5 = new XCMD5(); + + // + result = md5.Hash(tag); + + // + ZeroMemory(md5); + + // + return result; +} + +/** + * Hash Specified Content ... + * + * @param content: T, Proveded Content ... + * + * @return ( string ) + */ +template +string ToMD5(T content) +{ + // + string result = ""; + + // + string strContent = ToString(content); + if (StringLen(strContent) == 0) + { + return result; + } + + // + XCMD5 *md5; + md5 = new XCMD5(); + + // + result = md5.Hash(strContent); + + // + ZeroMemory(md5); + + // + return result; +} + +/** + * Calculate Fibo Level ... + * + * @param mUp: double, Specified Upper Price ... + * @param mDown: double, Specified Lower Price ... + * @param mLevel: ENUM_X_FIBO_LEVELS member, Specified Fibo Level ... + * @param mForDir: ENUM_X_DIRECTION member, Specified Calculation Direction ... + * + * @return ( double ) + */ +double GetFibonacciLevel( + double mUp, + double mDown, + ENUM_X_FIBO_LEVELS mLevel, + ENUM_X_DIRECTION mForDir // +) +{ + // + double result = 0; + + // + double levelValue = GetFiboLevelValue(mLevel); + + // + bool isValid = + // + mUp > 0 && + mDown > 0 && + levelValue > 0 && + mUp > mDown && + HasDirection(mForDir) + // + ; + if (!isValid) + { + return result; + } + + // + bool isBullish = IsBullish(mForDir); + + // + double ling = mUp - mDown; + double pLevel = (ling / 100) * (levelValue * 100); + + // + result = + isBullish + ? mUp - pLevel + : mDown + pLevel; + + // + return result; +} + +/** + * Calculate Sspecified Buffer's Moving Averages ... + * + * @param rates_total: Integer, number of items ... + * @param prev_calculated: Integer, Previous Calculate Items ... + * @param begin: Integer, Bar Index ... + * @param period: Integer, Moving Average Length ... + * @param source: Double Array, Specified Array for Calculating Moving Averages ... + * @param buffer: Double Array, Specified Array to Apply Calculated Moving Average on it ... + * @param method: ENUM_MA_METHOD member Specified Moving Average Calculation Method ... + * + * @return ( int ) + */ +int iMAOnBuffer( + const int _rates_total, + const int _prev_calculated, + const int _begin, + const int _period, + const double &_source[], + double &_buffer[], + ENUM_X_MA_METHOD _method = X_MA_MODE_SMA // +) +{ + // + int result = 0; + + // + if ( + _period < 0 || + _rates_total <= 0 || + _prev_calculated < 0 || + _method == X_MA_MODE_NONE || + _prev_calculated > _rates_total) + { + return result; + } + + // + switch (_method) + { + // + case X_MA_MODE_SMA: + result = SimpleMAOnBuffer( + _rates_total, + _prev_calculated, + _begin, + _period, + _source, + _buffer // + ); + break; + + // + case X_MA_MODE_EMA: + result = ExponentialMAOnBuffer( + _rates_total, + _prev_calculated, + _begin, + _period, + _source, + _buffer // + ); + break; + + // + case X_MA_MODE_LWMA: + result = LinearWeightedMAOnBuffer( + _rates_total, + _prev_calculated, + _begin, + _period, + _source, + _buffer // + ); + break; + + // + case X_MA_MODE_SMMA: + result = SmoothedMAOnBuffer( + _rates_total, + _prev_calculated, + _begin, + _period, + _source, + _buffer // + ); + break; + } + + // + return result; +} + +// +// END Tools ... +// + +// +// START String ... +// + +/** + * Search a Content Contains Specific String or not ... + * + * @param mQuery: string, Search Query ... + * @param mContent: string, Search Content ... + * @param ignoreCase: bool, Force Ignore Case Sensitive ... + * + * @return ( bool ) + */ +bool Contains( + string mQuery, + string mContent, + bool ignoreCase = true // +) +{ + // + 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; +} + +/** + * Search a Content Contains Specifics Query or not ... + * + * @param mQueries: string collection, Search Queries ... + * @param mContent: string, Search Content ... + * @param ignoreCase: bool, Force Ignore Case Sensitive ... + * + * @return ( bool ) + */ +bool Contains( + string &mQueries[], + string mContent, + bool ignoreCase = true // +) +{ + // + 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; +} + +/** + * Search a Content and Extract Occuranse Indexes ... + * + * @param mQuery: string, Search Query ... + * @param mContent: string, Search Content ... + * @param result: int collection reference, Holds Founded Indexes ... + * @param ignoreCase: bool, Force Ignore Case Sensitive ... + * + * @return ( int ) + */ +int FindIndexes( + string mQuery, + string mContent, + int &result[], + bool ignoreCase = false // +) +{ + // + int mResult = 0; + + // + Clean(result); + + // + // Validate Inputs ... + if (!IsValid(mQuery) || + !IsValid(mContent)) + { + return mResult; + } + + // + // Apply Ignore Case if Provided ... + if (ignoreCase) + { + // + bool isConverted = StringToLower(mQuery); + if (!isConverted) + { + return mResult; + } + + // + isConverted = StringToLower(mContent); + if (!isConverted) + { + return mResult; + } + } + + // + // Search First Index ... + int lastPos = 0; + int idx = StringFind( + mContent, + mQuery, + lastPos // + ); + while (idx >= 0) + { + // + // Add Position to Result ... + Add( + idx, + result // + ); + + // + lastPos = idx + StringLen(mQuery); + idx = StringFind( + mContent, + mQuery, + lastPos // + ); + } + + // + mResult = ArraySize(result); + + // + return mResult; +} + +/** + * Convert From String ... + * + * @param value: string, Provided Value ... + * + * @return ( T ) + */ +template +T FromString(string value) +{ + // + T result = NULL; + + // + if (!IsValid(value)) + { + return result; + } + + // + result = (T)value; + + // + return result; +} + +/** + * Converts to String ... + * + * @param value: T, Provided Value ... + * + * @return ( string ) + */ +template +string ToString(T value) +{ + return (string)value; +} + +string Trim(string value) +{ + // + string result = NULL; + + // + result = value; + + // + StringTrimRight(result); + StringTrimLeft(result); + + // + return result; +} + +// +// 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; + + // + bool canSet = + IsBoolean(ToString(value)) + ? (bool)value || !ignoreFalseConditions + : true; + + // + result = canSet + ? prefix + + prefixSeparator + " " + + ToString(value) + + lineSeparator + : ""; + + // + return result; +} + +// +template +string ToString( + string prefix, // Title + T value, // Value + string lineSeparator = "\n", // Line Separator + string prefixSeparator = ":" // Title Separator +) +{ + // + string result = NULL; + + // + result = 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; +} + +/** + * Check a String Value is Boolean or Not ... + * + * @param value: string representation of value ... + * + * @return ( bool ) + */ +bool IsBoolean(string value) +{ + // + bool result = false; + + // + string istring = value; + string normalizedValue = ToString(istring); + StringToLower(normalizedValue); + normalizedValue = Trim(normalizedValue); + + // + result = + !IsValid(normalizedValue) + ? false + : (normalizedValue == "true" || + normalizedValue == "false"); + + // + return result; +} + +/** + * Converts String to boolean ... + * + * @param value: string, Provided Value ... + * + * @return ( bool ) + */ +bool ToBoolean(string value) +{ + // + bool result = false; + + // + if (!IsBoolean(value) || + StringLen(value) <= 0) + { + return result; + } + + // + value = Trim(value); + StringToLower(value); + + // + bool isTrue = value == "true"; + bool isFalse = value == "false"; + + // + result = isTrue + ? true + : false; + + // + 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; +} + +// +// END String ... +// + +// +// START Cycles ... +// + +/** + * Converts String To Period ... + * + * @param value: string ... + * + * @return ( ENUM_TIMEFRAMES ) + */ +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 To String ... + * + * @param value: ENUM_TIMEFRAMES member ... + * + * @return ( string ) + */ +string ToString(ENUM_TIMEFRAMES value) +{ + // + string result = ""; + + // + string mPStr = EnumToString(value); + + 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; +} + +// +// 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: + case PERIOD_M3: + result = PERIOD_M5; + break; + + // + case PERIOD_M4: + case PERIOD_M5: + case PERIOD_M6: + result = PERIOD_M10; + break; + + // + case PERIOD_M10: + case PERIOD_M12: + case PERIOD_M15: + result = PERIOD_M20; + break; + + // + case PERIOD_M20: + case PERIOD_M30: + result = PERIOD_H1; + break; + + // + case PERIOD_H1: + case PERIOD_H2: + result = PERIOD_H3; + break; + + // + case PERIOD_H3: + result = PERIOD_H4; + break; + + // + case PERIOD_H4: + result = PERIOD_H6; + break; + + // + case PERIOD_H6: + result = PERIOD_H8; + break; + + // + case PERIOD_H8: + result = PERIOD_H12; + break; + + // + default: + result = mPeriod; + 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: + case PERIOD_M3: + result = PERIOD_M10; + break; + + // + case PERIOD_M4: + case PERIOD_M5: + case PERIOD_M6: + result = PERIOD_M15; + break; + + // + case PERIOD_M10: + case PERIOD_M12: + case PERIOD_M15: + result = PERIOD_M30; + break; + + // + case PERIOD_M20: + case PERIOD_M30: + result = PERIOD_H2; + break; + + // + case PERIOD_H1: + case PERIOD_H2: + result = PERIOD_H4; + break; + + // + case PERIOD_H3: + result = PERIOD_H6; + break; + + // + case PERIOD_H4: + result = PERIOD_H8; + break; + + // + case PERIOD_H6: + result = PERIOD_H12; + break; + + // + case PERIOD_H8: + result = PERIOD_D1; + break; + + // + default: + result = mPeriod; + 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: + case PERIOD_M3: + result = PERIOD_M30; + break; + + // + case PERIOD_M4: + case PERIOD_M5: + case PERIOD_M6: + result = PERIOD_H1; + break; + + // + case PERIOD_M10: + case PERIOD_M12: + case PERIOD_M15: + result = PERIOD_H2; + break; + + // + case PERIOD_M20: + case PERIOD_M30: + result = PERIOD_H4; + break; + + // + case PERIOD_H1: + case PERIOD_H2: + result = PERIOD_H6; + break; + + // + case PERIOD_H3: + result = PERIOD_H8; + break; + + // + case PERIOD_H4: + result = PERIOD_H12; + break; + + // + case PERIOD_H6: + result = PERIOD_D1; + break; + + // + case PERIOD_H8: + result = PERIOD_W1; + break; + + // + default: + result = mPeriod; + 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: + case PERIOD_M3: + result = PERIOD_H1; + break; + + // + case PERIOD_M4: + case PERIOD_M5: + case PERIOD_M6: + result = PERIOD_H2; + break; + + // + case PERIOD_M10: + case PERIOD_M12: + case PERIOD_M15: + result = PERIOD_H4; + break; + + // + case PERIOD_M20: + case PERIOD_M30: + result = PERIOD_H6; + break; + + // + case PERIOD_H1: + case PERIOD_H2: + result = PERIOD_H8; + break; + + // + case PERIOD_H3: + result = PERIOD_H12; + break; + + // + case PERIOD_H4: + result = PERIOD_D1; + break; + + // + case PERIOD_H6: + result = PERIOD_W1; + break; + + // + case PERIOD_H8: + result = PERIOD_MN1; + break; + + // + default: + result = mPeriod; + 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; +} + +// +// Calculate a Cycle Length based on Host Period ... +int GetCycleLengthOn( + ENUM_TIMEFRAMES _hostPeriod, + ENUM_X_MARKET_CYCLES _cycle, + ENUM_X_PERIOD_METHOD _method, + ENUM_TIMEFRAMES _period // +) +{ + // + int result = 0; + + // + // Validate ... + bool isValid = + // + IsValid(_hostPeriod) && + IsValid(_method, _Period) + // + ; + if (!isValid) + { + return result; + } + + // + // Calculate Period ... + isValid = + _method != X_PERIOD_NONE && + _cycle != X_MARKET_CYCLE_UNKNOWN; + if (!isValid) + { + return result; + } + + // + if (_method == X_PERIOD_AUTO) + { + // + _period = GetCyclePeriod( + _cycle, + _hostPeriod // + ); + } + isValid = IsValid(_period); + if (!isValid) + { + return result; + } + + // + int _hostPeriodSeconds = PeriodSeconds(_hostPeriod); + int _periodSeconds = PeriodSeconds(_period); + + // + isValid = _periodSeconds >= _hostPeriodSeconds; + if (!isValid) + { + return result; + } + + // + result = _periodSeconds / _hostPeriodSeconds; + + // + return result; +} + +/** + * Retrieve Sharp Change Info for Specified Period ... + * + * @param priceChange: double, required Price Change ... + * @param mPeriod: ENUM_TIMEFRAMES member, Specified Period ... + * + * @return ( int ) + */ +int GetPeriodSharpData( + double &priceChange, + ENUM_TIMEFRAMES mPeriod = NULL // +) +{ + // + int result = 0; + + // + priceChange = 0.0; + + // + mPeriod = NormalizePeriod(mPeriod); + + // + switch (mPeriod) + { + // + case PERIOD_M1: + // + priceChange = 0.000006; + result = 14; + break; + + // + case PERIOD_M2: + // + priceChange = 0.000006; + result = 14; + break; + + // + case PERIOD_M3: + // + priceChange = 0.00007; + result = 14; + break; + + // + case PERIOD_M4: + // + priceChange = 0.000007; + result = 14; + break; + + // + case PERIOD_M5: + // + priceChange = 0.000009; + result = 14; + break; + + // + case PERIOD_M6: + // + priceChange = 0.000009; + result = 14; + break; + + // + case PERIOD_M10: + // + priceChange = 0.00001; + result = 12; + break; + + // + case PERIOD_M12: + // + priceChange = 0.000011; + result = 11; + break; + + // + case PERIOD_M15: + // + priceChange = 0.000011; + result = 9; + break; + + // + case PERIOD_M20: + // + priceChange = 0.000012; + result = 9; + break; + + // + case PERIOD_M30: + // + priceChange = 0.000012; + result = 7; + break; + + // + case PERIOD_H1: + // + priceChange = 0.000013; + result = 5; + break; + + // + case PERIOD_H2: + // + priceChange = 0.000013; + result = 5; + break; + + // + case PERIOD_H3: + // + priceChange = 0.000014; + result = 5; + break; + + // + case PERIOD_H4: + // + priceChange = 0.000014; + result = 5; + break; + + // + case PERIOD_H6: + // + priceChange = 0.000015; + result = 5; + break; + + // + case PERIOD_H8: + // + priceChange = 0.000017; + result = 5; + break; + + // + case PERIOD_H12: + // + priceChange = 0.000017; + result = 5; + break; + + // + case PERIOD_D1: + // + priceChange = 0.000019; + result = 3; + break; + + // + case PERIOD_W1: + // + priceChange = 0.00002; + result = 3; + break; + + // + case PERIOD_MN1: + // + priceChange = 0.000021; + result = 3; + break; + } + + // + return result; +} + +// +// END Cycles ... +// + +// +// START Collections ... +// + +// +// 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; +} + +// +// Check Specified Array Has Childs or not ... +template +bool HasChild(T &buffer[]) +{ + return IsValidSize(ArraySize(buffer)); +} +template +bool SpecificHasChild(T &buffer[]) +{ + return HasChild(buffer); +} + +// +// 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[]) +{ + // + ArrayResize(buffer, 0); + ArrayFree(buffer); + ZeroMemory(buffer); +} +template +void SpecificClean(T &buffer[]) +{ + Clean(buffer); +} + +// +// 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 + bool forceStart = true // Force To Clean buffer +) +{ + // + int result = 0; + + // + if (forceClean) + { + Clean(dest); + } + + // + if (start < 0 && forceStart) + { + 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; +} + +// +// Remove Last Item of Specified Buffer ... +template +bool RemoveLastItem( + T &buffer[] // Specified Buffer +) +{ + // + bool result = false; + + // + int count = ArraySize(buffer); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + ArrayRemove( + buffer, + count - 1, + 1 // + ); + + // + return result; +} + +template +void CleanupArray( + T &buffer[], // Buffer to Cleanup ... + int maxAllowed = 0 // Max Allowed Number of items ... +) +{ + // + if (maxAllowed <= 0) + { + return; + } + + // + int count = ArraySize(buffer); + if (!IsValidSize(count) || + count <= maxAllowed) + { + return; + } + + // + int mustRemove = count - maxAllowed; + if (!IsValidSize(mustRemove)) + { + return; + } + + // + ArrayRemove( + buffer, + 0, + mustRemove // + ); +} + +template +void CleanupArray( + int &removedIndexes[], + T &buffer[] // Buffer to Cleanup ... +) +{ + // + bool isValid = HasChild(buffer) && + HasChild(removedIndexes); + if (!isValid) + { + return; + } + + // + for (int i = 0; i < ArraySize(removedIndexes); i++) + { + // + int idx = removedIndexes[i]; + if (IsValidIndex(idx) && ArraySize(buffer) > idx) + { + // + ArrayRemove( + buffer, + idx, + 1 // + ); + } + } + + // + Clean(removedIndexes); +} + +// +// 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; +} +// +// 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; +} + +// +// 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 Sum ... +template +double GetSum( + 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]; + } + + // + 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 +T GetMax( + T &buffer[], // the Buffer which required to search + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + // + T 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++) + { + // + T iValue = tmp[i]; + + // + result = + // + result == 0 || result < iValue + // + ? iValue + // + : result + // + ; + } + + // + return result; +} +template +T GetMaxWidthIndex( + T &buffer[], // the Buffer which required to search + int &index, // Item Index ... + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + // + T result = 0; + index = -1; + + // + 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++) + { + // + T iValue = tmp[i]; + + // + bool isNew = result == 0; + bool canSet = isNew || + (!isNew && + result < iValue); + if (canSet) + { + // + index = i; + result = iValue; + } + } + + // + return result; +} +template +T GetSpecifiedMax( + T &buffer[], // the Buffer which required to search + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + return GetMax( + buffer, + start, + count // + ); +} +template +T GetSpecifiedMaxWidthIndex( + T &buffer[], // the Buffer which required to search + int &index, // Item Index ... + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + return GetMaxWidthIndex( + buffer, + index, + start, + count // + ); +} + +// +// Get Min of Specific Loopback of a Buffer ... +template +T GetMin( + T &buffer[], // the Buffer which required to search + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + // + T 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++) + { + // + T iValue = tmp[i]; + + // + result = + // + result == 0 || result > iValue + // + ? iValue + // + : result + // + ; + } + + // + return result; +} +template +T GetMinWidthIndex( + T &buffer[], // the Buffer which required to search + int &index, // Item Index ... + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + // + T result = 0; + index = -1; + + // + 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++) + { + // + T iValue = tmp[i]; + + // + bool isNew = result == 0; + bool canSet = isNew || + (!isNew && + result > iValue); + if (canSet) + { + // + index = i; + result = iValue; + } + } + + // + return result; +} +template +T GetSpecifiedMin( + T &buffer[], // the Buffer which required to search + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + return GetMin( + buffer, + start, + count // + ); +} +template +T GetSpecifiedMinWidthIndex( + T &buffer[], // the Buffer which required to search + int &index, // Item Index ... + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + return GetMinWidthIndex( + buffer, + index, + start, + count // + ); +} + +// +// 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; +} +template +T FindLesserThanByIndex( + T value, // Specified Value ... + int &index, // Item Index ... + const T &source[], // Source ... + bool isDescend = false // Find Biggest Lesser Value ... +) +{ + // + T result = -1; + index = -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) + { + // + index = i; + 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; +} +template +T FindBiggerThanByIndex( + T value, // Specified Value ... + int &index, // Item Index ... + const T &source[], // Source ... + bool isDescend = false // Find Smallest Bigger Value ... +) +{ + // + T result = -1; + index = -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) + { + // + index = i; + 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); + } +} + +// +// END Collections ... +// + +// +// START Buffers ... +// + +// +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 double &buffer[], // the Buffer which required to search + int from = -1, // Last Time Index + int to = -1 // Fisrs Tima Index +) +{ + // + bool result = false; + + // + if (from == -1) + { + from = ArraySize(buffer) - 1; + } + + // + if (to == -1) + { + to = 0; + } + + // + // 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( + buffer, + from, + i // + ); + + // + // Check Result ... + result = result && isPassed && isIIncreasing; + if (!result) + { + break; + } + } + + // + return result; +} + +// +// Check if a Value Decreasing in Loopback ... +bool IsDecreasing( + const double &buffer[], // the Buffer which required to search + int from = -1, // Last Time Index + int to = -1 // Fisrs Tima Index +) +{ + // + bool result = false; + + // + if (from == -1) + { + from = ArraySize(buffer) - 1; + } + + // + if (to == -1) + { + to = 0; + } + + // + // 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( + buffer, + from, + i // + ); + + // + // 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; +} + +// +// END Buffers ... +// + +// +// START Time ... +// + +// +// 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; +} + +// +// Converts Hours to Seconds ... +int HoursToSeconds(int value) +{ + // + int result = 0; + + // + if (value < 0) + { + value = 0; + } + + // + if (value == 0) + { + return result; + } + + // + result = value * 60 * 60; + + // + return result; +} + +// +// Retrieve DateTime Structure ... +MqlDateTime GetCurrentTime() +{ + // + MqlDateTime result = {}; + + // + datetime cTime = TimeCurrent(); + TimeToStruct(cTime, 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; +} + +// +int GetLocalOffset() +{ + // + MqlDateTime cTimeStruct; + datetime cTime = TimeCurrent(cTimeStruct); + + // + MqlDateTime cLTimeStruct; + datetime cLTime = TimeLocal(cLTimeStruct); + + // + cTimeStruct.sec = 0; + cTime = StructToTime(cTimeStruct); + + // + cLTimeStruct.sec = 0; + cLTime = StructToTime(cLTimeStruct); + + // + int result = ((int)cLTime - (int)cTime); + + // + return result; +} + +// +int GetUTCRequiredTimeOffset() +{ + // + int utcOffset = TimeGMTOffset(); + int localOffset = GetLocalOffset(); + + // + int result = utcOffset + localOffset; + + // + return result; +} + +// +datetime GetUTCTime( + datetime time = NULL, + bool applyTradeServerTime = false // +) +{ + // + datetime result = NULL; + + // + NormalizeTime(time); + + // + datetime cTime = TimeCurrent(); + datetime cTimeLocal = TimeLocal(); + + // + int cLocalOffset = ((int)cTimeLocal - (int)cTime); + int gmtOffset = TimeGMTOffset(); + int offsetDelte = gmtOffset + cLocalOffset; + int requiredUTCOffset = GetUTCRequiredTimeOffset(); + if (requiredUTCOffset > 0) + { + requiredUTCOffset = -1 * requiredUTCOffset; + } + + // + int timeSeconds = (int)time; + int resultSeconds = timeSeconds + requiredUTCOffset; + + // + result = (datetime)(resultSeconds); + + // + return result; +} + +// +// Retrieve only Hour and Minute as String ... +string GetTimeString( + datetime time = NULL // +) +{ + // + NormalizeTime(time); + + // + string result = NULL; + + // + MqlDateTime tStruct; + bool isStructed = TimeToStruct(time, tStruct); + if (!isStructed) + { + return result; + } + + // + string hour = ToString(tStruct.hour); + hour = + StringLen(hour) == 1 + ? "0" + hour + : hour; + + // + string minute = ToString(tStruct.min); + minute = + StringLen(minute) == 1 + ? "0" + minute + : minute; + + // + result = hour + ":" + minute; + + // + return result; +} + +// +// Converts a Date time to File Format ... +string ToFormatString( + datetime mTime, + string separator = "_" // +) +{ + // + string result = NULL; + + // + if (!IsValid(mTime)) + { + return result; + } + + // + MqlDateTime timeStruct; + bool isConverts = TimeToStruct( + mTime, + timeStruct // + ); + if (!isConverts) + { + return result; + } + + // + string year = ToString(timeStruct.year); + string month = ToString(timeStruct.mon); + string day = ToString(timeStruct.day); + string hour = ToString(timeStruct.hour); + string minute = ToString(timeStruct.min); + string second = ToString(timeStruct.sec); + + // + result = + // + // Year ... + year + separator + + // + // Month ... + (StringLen(month) == 1 + ? "0" + month + : month) + + separator + + // + // Day ... + (StringLen(day) == 1 + ? "0" + day + : day) + + separator + + // + // Hour ... + (StringLen(hour) == 1 + ? "0" + hour + : hour) + + separator + + // + // Minute ... + (StringLen(minute) == 1 + ? "0" + minute + : minute) + + separator + + // + // Seconds ... + (StringLen(second) == 1 + ? "0" + second + : second) + + separator + + // + "" + // + ; + + // + return result; +} + +/** + * Converts an String Represetation of Time (00:00) to Date Time .. + * + * @param value: String ... + * + * @return ( datetime ) + */ +datetime ParseDateTimeFromTimeString(string value) +{ + // + datetime result = NULL; + + // + if (!IsValid(value)) + { + return result; + } + + // + // Check Signalling Time ... + MqlDateTime cTime; + bool isTimeRecieved = TimeCurrent(cTime); + if (!isTimeRecieved) + { + return result; + } + + // + // Split ... + string parts[]; + int partsCount = SplitContent( + parts, + value, + ":" + // + ); + if (!IsValidSize(partsCount)) + { + return result; + } + + // + int hour = 0; + int minute = 0; + if (partsCount >= 1) + { + hour = (int)(parts[0]); + } + if (partsCount >= 2) + { + minute = (int)(parts[1]); + } + + // + cTime.day_of_week = 0; + cTime.day_of_year = 0; + + // + cTime.hour = hour; + cTime.min = minute; + + // + result = StructToTime(cTime); + + // + return result; +} + +// +// Check Specific Time in Range of another Time ... +bool IsTimeInRange( + datetime currentTime = NULL, + datetime startTime = NULL, + datetime stopTime = NULL // +) +{ + // + bool result = false; + + // + // Normallize Current Time ... + currentTime = NormalizeTime(currentTime); + + // + result = !IsValid(startTime) && + !IsValid(stopTime); + if (result) + { + return result; + } + + // + result = IsValid(startTime) && + IsValid(stopTime); + if (!result) + { + // + result = IsValid(startTime) && + currentTime >= startTime; + + // + return result; + } + + // + result = currentTime >= startTime && + currentTime < stopTime; + + // + return result; +} +bool IsTimeInRange( + datetime currentTime, + string startTime, + string endTime // +) +{ + // + bool result = false; + + // + result = IsValid(startTime) && + IsValid(endTime); + if (!result) + { + // + // Here Since there isnot provide any + // data source we pass result as true ... + result = true; + return result; + } + + // + // Converts String Representation to Time ... + datetime st = ParseDateTimeFromTimeString(startTime); + datetime et = ParseDateTimeFromTimeString(endTime); + + // + result = IsTimeInRange( + currentTime, + st, + et // + ); + + // + return result; +} + +// +// END Time ... +// + +// +// START Price ... +// + +// +// 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; +} + +/** + * Calculate Applied Price ... + * + * @param mType: ENUM_X_PRICE member, Price Type ... + * @param mOpen: double collection, Open Prices ... + * @param mHigh: double collection, High Prices ... + * @param mLow: double collection, Low Prices ... + * @param mClose: double collection, Close Prices ... + * @param barIndex: int, Index ... + * + * @return ( double ) + */ +double GetAppliedPrice( + ENUM_X_PRICE mType, // Type of Price Selection + const double &mOpen[], // Open Prices + const double &mHigh[], // High Preices + const double &mLow[], // Low Prices + const double &mClose[], // Close Prices + int barIndex // Bar Index +) +{ + // + double result = 0; + + // + switch (mType) + { + // + case X_PRICE_NONE: + result = 0; + break; + + // + case X_PRICE_HIGH: + result = mHigh[barIndex]; + break; + + // + case X_PRICE_OPEN: + result = mOpen[barIndex]; + break; + + // + case X_PRICE_CLOSE: + result = mClose[barIndex]; + break; + + // + case X_PRICE_LOW: + result = mLow[barIndex]; + break; + + // + case X_PRICE_UP: + result = MathMax(mOpen[barIndex], mClose[barIndex]); + break; + + // + case X_PRICE_DOWN: + result = MathMin(mOpen[barIndex], mClose[barIndex]); + break; + + // + case X_PRICE_MEDIAN: + result = ((mHigh[barIndex] + mLow[barIndex]) / 2.0); + break; + + // + case X_PRICE_BODY_MEDIAN: + result = ((mOpen[barIndex] + mClose[barIndex]) / 2.0); + break; + + // + case X_PRICE_TYPICAL: + result = ((mHigh[barIndex] + mLow[barIndex] + mClose[barIndex]) / 3.0); + break; + + // + case X_PRICE_WEIGHTED: + result = (((mHigh[barIndex] + mLow[barIndex] + mClose[barIndex] + mClose[barIndex]) / 4.0)); + break; + } + + // + return result; +} + +/** + * Calculate Applied Price ... + * + * @param mType: ENUM_X_PRICE member, Price Type ... + * @param mOpen: double, Open Price ... + * @param mHigh: double, High Price ... + * @param mLow: double, Low Price ... + * @param mClose: double, Close Price ... + * @param barIndex: int, Index ... + * + * @return ( double ) + */ +double GetAppliedPrice( + ENUM_X_PRICE mType, // Type of Price Selection + double mOpen, // Open Prices + double mHigh, // High Preices + double mLow, // Low Prices + double mClose // Close Prices +) +{ + // + double result = 0; + + // + switch (mType) + { + // + case X_PRICE_NONE: + result = 0; + break; + + // + case X_PRICE_HIGH: + result = mHigh; + break; + + // + case X_PRICE_OPEN: + result = mOpen; + break; + + // + case X_PRICE_CLOSE: + result = mClose; + break; + + // + case X_PRICE_LOW: + result = mLow; + break; + + // + case X_PRICE_UP: + result = MathMax(mOpen, mClose); + break; + + // + case X_PRICE_DOWN: + result = MathMin(mOpen, mClose); + break; + + // + case X_PRICE_MEDIAN: + result = ((mHigh + mLow) / 2.0); + break; + + // + case X_PRICE_BODY_MEDIAN: + result = ((mOpen + mClose) / 2.0); + break; + + // + case X_PRICE_TYPICAL: + result = ((mHigh + mLow + mClose) / 3.0); + break; + + // + case X_PRICE_WEIGHTED: + result = (((mHigh + mLow + mClose + mClose) / 4.0)); + break; + } + + // + return result; +} + +/** + * Calculate Applied Price ... + * + * @param mSymbol: string, Specified Symbol ... + * @param mPeriod: ENUM_TIMEFRAMES member, Specified PEriod ... + * @param barIndex: int, Specified Bar Index ... + * @param mType: ENUM_X_PRICE member, Specified Price Type ... + * + * @return ( double ) + */ +double GetAppliedPrice( + string mSymbol = NULL, // Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Period + int barIndex = 0, // Bar Index + ENUM_X_PRICE mType = X_PRICE_CLOSE // Type of Price Selection +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + barIndex = NormalizeInt(barIndex, 0); + + // + bool has = IsValid(mType); + if (!has) + { + return result; + } + + // + double open = iOpen( + mSymbol, + mPeriod, + barIndex // + ); + + // + double high = iHigh( + mSymbol, + mPeriod, + barIndex // + ); + + // + double low = iLow( + mSymbol, + mPeriod, + barIndex // + ); + + // + double close = iClose( + mSymbol, + mPeriod, + barIndex // + ); + + // + // Retrieve Applied Price ... + result = GetAppliedPrice( + mType, + open, + high, + low, + close // + ); + + // + return result; +} + +/** + * Calculate Applied Price ... + * + * @param mSymbol: string, Specified Symbol ... + * @param mPeriod: ENUM_TIMEFRAMES member, Specified PEriod ... + * @param time: int, Specified Bar Time ... + * @param mType: ENUM_X_PRICE member, Specified Price Type ... + * + * @return ( double ) + */ +double GetAppliedPrice( + string mSymbol = NULL, // Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Period + datetime mTime = NULL, // Bar Time + ENUM_X_PRICE mType = X_PRICE_CLOSE // Type of Price Selection +) +{ + // + double result = 0; + + // + mTime = NormalizeTime(mTime); + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + bool has = IsValid(mType); + if (!has) + { + return result; + } + + // + int barIndex = GetBarIndex( + mSymbol, + mPeriod, + mTime // + ); + has = IsValidIndex(barIndex); + if (!has) + { + return result; + } + + // + // Retrieve Applied Price ... + result = GetAppliedPrice( + mSymbol, + mPeriod, + barIndex, + mType // + ); + + // + return result; +} + +/** + * Calculate Price Boundary ... + * + * @param upper: double collection reference, Upper Boundary ... + * @param lower: double collection reference, Lower Boundary ... + * @param mSymbol: string, Specified Symbol ... + * @param mPeriod: ENUM_TIMEFRAMES member, Specified PEriod ... + * @param mMode: ENUM_X_BOUNDARY_PRICE member, Specified Boundary Mode ... + * @param mLength: int, Loopback Length of Bondary ... + * @param barIndex: int, Specified Bar Index ... + * @return ( int ) + */ +int GetPriceBoundary( + double &upper[], // Upper Boundary + double &lower[], // Lower Boundary + string mSymbol = NULL, // Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Period + ENUM_X_BOUNDARY_PRICE mMode = NULL, // Boundary Mode + int mLength = 1, // Length + int barIndex = 0 // Bar Index +) +{ + // + int result = 0; + + // + Clean(upper); + Clean(lower); + + // + // Normalize Args ... + mMode = NormalizeBoundary(mMode); + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + mLength = NormalizeInt(mLength, 1); + barIndex = NormalizeInt(barIndex, 0); + + // + // Prepare Boundary Price Types ... + ENUM_X_PRICE upperType = + mMode == X_BOUNDARY_PRICE_UP_DOWN + ? X_PRICE_UP + : mMode == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_HIGH + : X_PRICE_NONE; + ENUM_X_PRICE lowerType = + mMode == X_BOUNDARY_PRICE_UP_DOWN + ? X_PRICE_DOWN + : mMode == X_BOUNDARY_PRICE_HIGH_LOW + ? X_PRICE_LOW + : X_PRICE_NONE; + + // + // Check Boundary Type Validation ... + bool isValid = IsValid(lowerType) && + IsValid(upperType); + if (!isValid) + { + return result; + } + + // + // Loop through Loopbacks ... + int start = barIndex + mLength; + int end = barIndex; + for (int i = start; i >= end; i--) + { + // + double iUpper = GetAppliedPrice( + mSymbol, + mPeriod, + i, + upperType // + ); + double iLower = GetAppliedPrice( + mSymbol, + mPeriod, + i, + lowerType // + ); + + // + Add( + iUpper, + upper // + ); + + // + Add( + iLower, + lower // + ); + } + + // + result = ArraySize(upper); + + // + return result; +} + +// +// END Price ... +// + +// +// START Bar ... +// + +/** + * Retrieve Specific Bar's Time ... + * + * @param mSymbol: string, Provided Symbol ... + * @param mPeriod: ENUM_TIMEFRAMES member, Provided Period ... + * @param barIndex: int, Provided Bar Index ... + * + * @return ( datetime ) + */ +datetime GetBarTime( + string mSymbol = NULL, // 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 Specific Bar's Index ... + * + * @param mSymbol: string, Provided Symbol ... + * @param mPeriod: ENUM_TIMEFRAMES member, Provided Period ... + * @param barTime: datetime, Provided Bar Time ... + * + * @return ( datetime ) + */ +int GetBarIndex( + string mSymbol = NULL, // Specify Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Specify TimeFrame + datetime barTime = NULL // Specify Bar Time +) +{ + // + // Validate and Normalize Args ... + + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + // Retrieve Bar Time ... + int result = iBarShift( + mSymbol, + mPeriod, + barTime // + ); + + // + return result; +} + +// +// END Bar ... +// + +// +// START Chart Info ... +// + +ENUM_CHART_MODE GetChartMode(long chartId = 0) +{ + return (ENUM_CHART_MODE)ChartGetInteger(chartId, CHART_MODE); +} + +color GetChartUpColor(long chartId = 0) +{ + return (color)ChartGetInteger(chartId, CHART_COLOR_CHART_UP); +} + +color GetChartDownColor(long chartId = 0) +{ + return (color)ChartGetInteger(chartId, CHART_COLOR_CHART_DOWN); +} + +color GetChartBullishColor(long chartId = 0) +{ + return (color)ChartGetInteger(chartId, CHART_COLOR_CANDLE_BULL); +} + +color GetChartBearishColor(long chartId = 0) +{ + return (color)ChartGetInteger(chartId, CHART_COLOR_CANDLE_BEAR); +} + +color GetChartLineColor(long chartId = 0) +{ + return (color)ChartGetInteger(chartId, CHART_COLOR_CHART_LINE); +} + +color GetChartForeGroundColor(long chartId = 0) +{ + return (color)ChartGetInteger(chartId, CHART_COLOR_FOREGROUND); +} + +color GetChartBackGroundColor(long chartId = 0) +{ + return (color)ChartGetInteger(chartId, CHART_COLOR_BACKGROUND); +} + +color GetChartGridColor(long chartId = 0) +{ + return (color)ChartGetInteger(chartId, CHART_COLOR_GRID); +} + +color GetChartBidLineColor(long chartId = 0) +{ + return (color)ChartGetInteger(chartId, CHART_COLOR_BID); +} + +color GetChartAskLineColor(long chartId = 0) +{ + return (color)ChartGetInteger(chartId, CHART_COLOR_ASK); +} + +color GetChartStopColor(long chartId = 0) +{ + return (color)ChartGetInteger(chartId, CHART_COLOR_STOP_LEVEL); +} + +color GetChartVolumesColor(long chartId = 0) +{ + return (color)ChartGetInteger(chartId, CHART_COLOR_VOLUME); +} + +bool GetChartShowBidLine(long chartId = 0) +{ + return (bool)ChartGetInteger(chartId, CHART_SHOW_BID_LINE); +} + +bool GetChartShowAskLine(long chartId = 0) +{ + return (bool)ChartGetInteger(chartId, CHART_SHOW_ASK_LINE); +} + +bool GetChartShowGrid(long chartId = 0) +{ + return (bool)ChartGetInteger(chartId, CHART_SHOW_GRID); +} + +bool GetChartShowVolumes(long chartId = 0) +{ + return (bool)ChartGetInteger(chartId, CHART_SHOW_VOLUMES); +} + +bool GetChartShowTradeLevels(long chartId = 0) +{ + return (bool)ChartGetInteger(chartId, CHART_SHOW_TRADE_LEVELS); +} + +bool GetChartAutoScroll(long chartId = 0) +{ + return (bool)ChartGetInteger(chartId, CHART_AUTOSCROLL); +} + +bool GetChartQuickNavigation(long chartId = 0) +{ + return (bool)ChartGetInteger(chartId, CHART_QUICK_NAVIGATION); +} + +// +// +// + +bool SetChartMode( + ENUM_CHART_MODE value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_MODE, value); +} + +bool SetChartShowBidLine( + bool value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_SHOW_BID_LINE, value); +} + +bool SetChartShowAskLine( + bool value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_SHOW_ASK_LINE, value); +} + +bool SetChartShowGrid( + bool value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_SHOW_GRID, value); +} + +bool SetChartShowVolumes( + bool value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_SHOW_VOLUMES, value); +} + +bool SetChartShowTradeLevels( + bool value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_SHOW_TRADE_LEVELS, value); +} + +bool SetChartAutoScroll( + bool value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_AUTOSCROLL, value); +} + +bool SetChartQuickNavigation( + bool value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_QUICK_NAVIGATION, value); +} + +bool SetChartForeGroundColor( + color value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_COLOR_FOREGROUND, value); +} + +bool SetChartBackGroundColor( + color value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_COLOR_BACKGROUND, value); +} + +bool SetChartUpColor( + color value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_COLOR_CHART_UP, value); +} + +bool SetChartDownColor( + color value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_COLOR_CHART_DOWN, value); +} + +bool SetChartBullishColor( + color value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_COLOR_CANDLE_BULL, value); +} + +bool SetChartBearishColor( + color value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_COLOR_CANDLE_BEAR, value); +} + +bool SetChartGridColor( + color value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_COLOR_GRID, value); +} + +bool SetChartBidLineColor( + color value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_COLOR_BID, value); +} + +bool SetChartAskLineColor( + color value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_COLOR_ASK, value); +} + +bool SetChartStopColor( + color value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_COLOR_STOP_LEVEL, value); +} + +bool SetChartLineColor( + color value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_COLOR_CHART_LINE, value); +} + +bool SetChartVolumesColor( + color value, + long chartId = 0 // +) +{ + return ChartSetInteger(chartId, CHART_COLOR_VOLUME, value); +} + +// +// END Chart Info ... +// + +// diff --git a/BKPS/14040316/Libraries/x-saherelm.common.lib.mq5 b/BKPS/14040316/Libraries/x-saherelm.common.lib.mq5 new file mode 100644 index 0000000..cad150f --- /dev/null +++ b/BKPS/14040316/Libraries/x-saherelm.common.lib.mq5 @@ -0,0 +1,157 @@ +/////////////////////////////////////////////////////// +// +// 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 "../Libraries/x-saherelm.common.extensions.lib.mq5" +#include "../Libraries/x-saherelm.common.models.lib.mq5" +#include "../Libraries/x-saherelm.x-ohcl.lib.mq5" + +// +// Models ... + +// +// Consolidation Zone ... +struct XConsolidationZone +{ + // + // Props ... + + // + string symbol; // Symbol ... + ENUM_TIMEFRAMES period; // Period ... + + // + double upper; // Upper ... + double lower; // Lower ... + + // + datetime from; // Start Date + datetime to; // Breake Date + + // + ENUM_X_DIRECTION dir; // Break Direction ... + + // + // Constructor ... + XConsolidationZone() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + upper = 0; + lower = 0; + + // + to = NULL; + from = NULL; + symbol = NULL; + period = NULL; + dir = X_DIRECTION_NONE; + + // + ZeroMemory(this); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + // + upper > 0 && + lower > 0 && + IsValid(to) && + IsValid(from) && + IsValid(symbol) && + IsValid(period) && + HasDirection(dir) + // + ; + + // + return result; + } + + bool IsSameAs( + XConsolidationZone &item // + ) + { + // + bool result = false; + + // + result = IsValid() && + item.IsValid() && + dir == item.dir && + from == item.from && + upper == item.upper && + lower == item.lower && + symbol == item.symbol && + period == item.period; + + // + return result; + } + + /** + * Retrieve Unique Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + // + string result = + // + "XCZONE" + "_" + + ToString(dir) + "_" + + symbol + "_" + + ToString(period) + "_" + + ToString(upper) + "_" + + ToString(lower) + // + ; + + // + return result; + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14040316/Libraries/x-saherelm.common.models.lib.mq5 b/BKPS/14040316/Libraries/x-saherelm.common.models.lib.mq5 new file mode 100644 index 0000000..c8e3186 --- /dev/null +++ b/BKPS/14040316/Libraries/x-saherelm.common.models.lib.mq5 @@ -0,0 +1,392 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Common Library +// -------------------------------------- +// Name: XModelsLib +// 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 + +// +#include "../Libraries/x-saherelm.common.extensions.lib.mq5" + +// +// Use To Parse Symbols for +// Ignore Brokers Additional Suffixes ... +struct XSymbolParser +{ + // + string version; // Temp ... + + // + // Symbol Parsing ... + + // + // Forext ... + + // + bool IsEURUSD(string symbol) + { + // + string symbolIdentifiers[] = { + "EUR", + "USD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsUSDJPY(string symbol) + { + // + string symbolIdentifiers[] = { + "USD", + "JPY" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsEURJPY(string symbol) + { + // + string symbolIdentifiers[] = { + "EUR", + "JPY" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsUSDCHF(string symbol) + { + // + string symbolIdentifiers[] = { + "USD", + "CHF" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsEURCHF(string symbol) + { + // + string symbolIdentifiers[] = { + "EUR", + "CHF" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsGBPUSD(string symbol) + { + // + string symbolIdentifiers[] = { + "GBP", + "USD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsEURGBP(string symbol) + { + // + string symbolIdentifiers[] = { + "EUR", + "GBP" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsAUDUSD(string symbol) + { + // + string symbolIdentifiers[] = { + "AUD", + "USD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsEURAUD(string symbol) + { + // + string symbolIdentifiers[] = { + "EUR", + "AUD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsUSDCAD(string symbol) + { + // + string symbolIdentifiers[] = { + "USD", + "CAD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsEURCAD(string symbol) + { + // + string symbolIdentifiers[] = { + "EUR", + "CAD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsNZDUSD(string symbol) + { + // + string symbolIdentifiers[] = { + "NZD", + "USD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsEURNZD(string symbol) + { + // + string symbolIdentifiers[] = { + "EUR", + "NZD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + // Metals ... + + // + bool IsXAUUSD(string symbol) + { + // + string symbolIdentifiers[] = { + "XAU", + "USD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsXAGUSD(string symbol) + { + // + string symbolIdentifiers[] = { + "XAG", + "USD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + // Indexes ... + + // + bool IsDowJones(string symbol) + { + // + bool result = Contains( + "DowJones30", + symbol // + ); + + // + return result; + } + + // + // Oil ... + + // + bool IsBrent(string symbol) + { + // + bool result = Contains( + "BRENT", + symbol // + ); + + // + return result; + } + + // + // Symbol Finder ... + string GetEURUSDSymbol() + { + // + string result = NULL; + + // + string symbols[]; + int symbolsCount = GetAllSymbols( + symbols // + ); + if (!IsValidSize(symbolsCount)) + { + return result; + } + + // + for (int i = 0; i < symbolsCount; i++) + { + // + string iSymbol = symbols[i]; + if (IsEURUSD(iSymbol)) + { + // + result = iSymbol; + break; + } + } + + // + return result; + } +}; diff --git a/BKPS/14040316/Libraries/x-saherelm.draw.lib.mq5 b/BKPS/14040316/Libraries/x-saherelm.draw.lib.mq5 new file mode 100644 index 0000000..ab7f39b --- /dev/null +++ b/BKPS/14040316/Libraries/x-saherelm.draw.lib.mq5 @@ -0,0 +1,2626 @@ +/////////////////////////////////////////////////////// +// +// 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; + + // + ZeroMemory(this); + } + + // + 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(); + + // + ZeroMemory(this); + } + + // + 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; +} + +// +// Find Specific Object Name ... +string FindObjectName( + string suggest, + long chartId = 0, + int subWindow = 0 // +) +{ + // + string result = NULL; + + // + int objectsCount = ObjectsTotal(chartId, subWindow); + if (objectsCount <= 0) + { + return result; + } + + // + for (int i = objectsCount - 1; i >= 0; i--) + { + // + string iObjectName = ObjectName(chartId, i, subWindow); + bool isExists = StringFind(iObjectName, suggest) >= 0; + if (isExists) + { + // + result = iObjectName; + 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; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // 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, objName, 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; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // delete an arrow ... + result = !ObjectDelete(chartID, objName); + + // + 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; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // change the arrow code ... + result = ObjectSetInteger(chartID, objName, 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; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // change anchor type ... + result = !ObjectSetInteger(chartID, objName, 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; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // 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, objName, 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; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // delete a horizontal line ... + result = ObjectDelete(chartID, objName); + + // + 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; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // if line time is not set, move the line to the last bar ... + if (!time) + { + time = TimeCurrent(); + } + + // + // move the vertical line ... + result = ObjectMove(chartID, objName, 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; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // delete the vertical line ... + result = ObjectDelete(chartID, objName); + + // + 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, // down first point time + double price1 = 0, // down first point price + datetime time2 = 0, // up second point time + double price2 = 0, // up 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); + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // Create a rectangle by the given coordinates ... + result = ObjectCreate( + chartID, + objName, + OBJ_RECTANGLE, + subWindow, + time1, + price1, + time2, + price2 // + ); + if (!result) + { + return result; + } + + // + // Set rectangle color ... + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // Set the style of rectangle lines + ObjectSetInteger(chartID, objName, OBJPROP_STYLE, style); + + // + // Set width of the rectangle lines ... + ObjectSetInteger(chartID, objName, OBJPROP_WIDTH, width); + + // + // Enable (true) or disable (false) the mode of filling the rectangle ... + ObjectSetInteger(chartID, objName, OBJPROP_FILL, fill); + + // + // Display in the foreground (false) or background (true) ... + ObjectSetInteger(chartID, objName, 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, 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 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; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // 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, objName, 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; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + result = ObjectDelete(chartID, objName); + + // + 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; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // move the rectangle label ... + result = ObjectSetInteger(chartID, objName, OBJPROP_XDISTANCE, x); + if (!result) + { + return result; + } + + // + result = ObjectSetInteger(chartID, objName, 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; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // delete the label ... + result = ObjectDelete(chartID, objName); + + // + 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; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // change label size ... + result = ObjectSetInteger(chartID, objName, OBJPROP_XSIZE, width); + if (!result) + { + return result; + } + + // + result = ObjectSetInteger(chartID, objName, 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; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // change border type ... + result = ObjectSetInteger(chartID, objName, 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; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // 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, objName, 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; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // delete a trend line ... + result = ObjectDelete(chartID, objName); + + // + 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; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // + // 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, objName, 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; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // change object text ... + result = ObjectSetString(chartID, objName, 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; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // delete the object ... + result = ObjectDelete(chartID, objName); + + // + 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; + } + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // set the number of levels ... + ObjectSetInteger(chartID, objName, OBJPROP_LEVELS, levels); + + // + // set the properties of levels in the loop ... + for (int i = 0; i < levels; i++) + { + // + // level value ... + ObjectSetDouble(chartID, objName, OBJPROP_LEVELVALUE, i, values[i]); + + // + // level color ... + ObjectSetInteger(chartID, objName, OBJPROP_LEVELCOLOR, i, colors[i]); + + // + // level style ... + ObjectSetInteger(chartID, objName, OBJPROP_LEVELSTYLE, i, styles[i]); + + // + // level width ... + ObjectSetInteger(chartID, objName, OBJPROP_LEVELWIDTH, i, widths[i]); + + // + // level description ... + // ObjectSetString(chartID, name, OBJPROP_LEVELTEXT, i, DoubleToString(100 * values[i], 1)); + ObjectSetString(chartID, objName, 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; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // 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, objName, 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; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // delete the object ... + result = ObjectDelete(chartID, objName); + + // + 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(); + } + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + result = ObjectCreate(chartID, objName, OBJ_EVENT, subWindow, time, 0); + if (!result) + { + return result; + } + + // + // set event text + ObjectSetString(chartID, objName, OBJPROP_TEXT, text); + + // + // set color + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // set anchor point width if the object is highlighted + 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 event 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; +} + +// +// 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; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // change object text + result = ObjectSetString(chartID, objName, 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; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // if time is not set, move event to the last bar + if (!time) + { + time = TimeCurrent(); + } + + // + // move the object + result = ObjectMove(chartID, objName, 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; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // delete the object + result = ObjectDelete(chartID, objName); + + // + 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; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // create the button + result = ObjectCreate(chartID, objName, OBJ_BUTTON, subWindow, 0, 0); + if (!result) + { + return result; + } + + // + // set button coordinates + ObjectSetInteger(chartID, objName, OBJPROP_XDISTANCE, x); + ObjectSetInteger(chartID, objName, OBJPROP_YDISTANCE, y); + + // + // set button size + ObjectSetInteger(chartID, objName, OBJPROP_XSIZE, width); + ObjectSetInteger(chartID, objName, OBJPROP_YSIZE, height); + + // + // set the chart's corner, relative to which point coordinates are defined + ObjectSetInteger(chartID, objName, OBJPROP_CORNER, corner); + + // + // 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 text color + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // set background color + ObjectSetInteger(chartID, objName, OBJPROP_BGCOLOR, bgColor); + + // + // set border color + ObjectSetInteger(chartID, objName, OBJPROP_BORDER_COLOR, borderColor); + + // + // display in the foreground false or background true + ObjectSetInteger(chartID, objName, OBJPROP_BACK, back); + + // + // set button state + ObjectSetInteger(chartID, objName, OBJPROP_STATE, state); + + // + // enable true or disable false the mode of moving the button 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); + + // + 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 + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + result = ObjectSetInteger(chartID, objName, OBJPROP_XDISTANCE, x); + if (!result) + { + return result; + } + + // + result = ObjectSetInteger(chartID, objName, 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 + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + result = ObjectSetInteger(chartID, objName, OBJPROP_XSIZE, width); + if (!result) + { + return result; + } + + // + result = ObjectSetInteger(chartID, objName, 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; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // change anchor corner + result = ObjectSetInteger(chartID, objName, 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; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // change object text + result = ObjectSetString(chartID, objName, 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; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // delete the button + result = ObjectDelete(chartID, objName); + + // + 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/BKPS/14040316/Libraries/x-saherelm.x-enums.lib.mq5 b/BKPS/14040316/Libraries/x-saherelm.x-enums.lib.mq5 new file mode 100644 index 0000000..e212425 --- /dev/null +++ b/BKPS/14040316/Libraries/x-saherelm.x-enums.lib.mq5 @@ -0,0 +1,1251 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Common Library +// -------------------------------------- +// Name: XEnumsLib +// 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 + +// +// START Price Type ... +// + +// +// Availables Price Types ... +enum ENUM_X_PRICE +{ + X_PRICE_NONE, // None + X_PRICE_HIGH, // High + X_PRICE_OPEN, // Open + X_PRICE_CLOSE, // Close + X_PRICE_LOW, // Low + X_PRICE_UP, // Body Up + X_PRICE_DOWN, // Body Down + X_PRICE_MEDIAN, // Median + X_PRICE_BODY_MEDIAN, // Body Median + X_PRICE_TYPICAL, // Typical + X_PRICE_WEIGHTED // Weighted +}; + +// +// Extensions ... + +/** + * Validate ... + * + * @param value: ENUM_X_PRICE member ... + * + * @return ( bool ) + */ +bool IsValid(ENUM_X_PRICE value) +{ + // + bool result = false; + + // + result = + value != NULL && + value != X_PRICE_NONE; + + // + return result; +} + +/** + * Converts Series Mode to ENUM_X_PRICE ... + * + * @param value: ENUM_SERIESMODE member ... + * + * @return ( ENUM_X_PRICE ) + */ +ENUM_X_PRICE ToXPrice(ENUM_SERIESMODE value) +{ + // + ENUM_X_PRICE result = X_PRICE_CLOSE; + + // + switch (value) + { + // + // 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; +} + +/** + * Converts Applied Price to ENUM_X_PRICE ... + * + * @param value: ENUM_APPLIED_PRICE member ... + * + * @return ( ENUM_X_PRICE ) + */ +ENUM_X_PRICE ToXPrice(ENUM_APPLIED_PRICE value) +{ + // + ENUM_X_PRICE result = X_PRICE_NONE; + + // + switch (value) + { + // + case PRICE_HIGH: + result = X_PRICE_HIGH; + break; + + // + case PRICE_OPEN: + result = X_PRICE_OPEN; + break; + + // + case PRICE_CLOSE: + result = X_PRICE_CLOSE; + break; + + // + case PRICE_LOW: + result = X_PRICE_LOW; + break; + + // + case PRICE_MEDIAN: + result = X_PRICE_MEDIAN; + break; + + // + case PRICE_TYPICAL: + result = X_PRICE_TYPICAL; + break; + + // + case PRICE_WEIGHTED: + result = X_PRICE_WEIGHTED; + break; + } + + // + return result; +} + +/** + * Converts Price Type to Applied Price ... + * + * @param value: ENUM_X_PRICE member ... + * + * @return ( ENUM_APPLIED_PRICE ) + */ +ENUM_APPLIED_PRICE ToAppliedPrice(ENUM_X_PRICE value) +{ + // + // Default ... + ENUM_APPLIED_PRICE result = PRICE_CLOSE; + + // + if (!IsValid(value) || + value == X_PRICE_UP || + value == X_PRICE_DOWN || + value == X_PRICE_BODY_MEDIAN) + { + return result; + } + + // + switch (value) + { + // + case X_PRICE_HIGH: + result = PRICE_HIGH; + break; + + // + case X_PRICE_OPEN: + result = PRICE_OPEN; + break; + + // + case X_PRICE_CLOSE: + result = PRICE_CLOSE; + break; + + // + case X_PRICE_LOW: + result = PRICE_LOW; + break; + + // + case X_PRICE_MEDIAN: + result = PRICE_MEDIAN; + break; + + // + case X_PRICE_TYPICAL: + result = PRICE_TYPICAL; + break; + + // + case X_PRICE_WEIGHTED: + result = PRICE_WEIGHTED; + break; + } + + // + return result; +} + +/** + * Converts To String ... + * + * @param value: ENUM_X_PRICE member ... + * + * @return ( string ) + */ +string ToString(ENUM_X_PRICE value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_PRICE_NONE: + result = "None"; + break; + + // + case X_PRICE_HIGH: + result = "High"; + break; + + // + case X_PRICE_OPEN: + result = "Open"; + break; + + // + case X_PRICE_CLOSE: + result = "Close"; + break; + + // + case X_PRICE_LOW: + result = "Low"; + break; + + // + case X_PRICE_UP: + result = "Body Up"; + break; + + // + case X_PRICE_DOWN: + result = "Body Down"; + break; + + // + case X_PRICE_MEDIAN: + result = "Median"; + break; + + // + case X_PRICE_BODY_MEDIAN: + result = "Body Median"; + break; + + // + case X_PRICE_TYPICAL: + result = "Typical"; + break; + + // + case X_PRICE_WEIGHTED: + result = "Weighted"; + break; + } + + // + return result; +} + +// +// END Price Type ... +// + +// +// START Boundary Price Type ... +// + +// +// Available Boundary Price Types ... +enum ENUM_X_BOUNDARY_PRICE +{ + X_BOUNDARY_PRICE_NONE, // None + X_BOUNDARY_PRICE_UP_DOWN, // Up/Down + X_BOUNDARY_PRICE_HIGH_LOW, // High/Low +}; + +/** + * Validate ... + * + * @param value: ENUM_X_BOUNDARY_PRICE member ... + * + * @return ( bool ) + */ +bool IsValid(ENUM_X_BOUNDARY_PRICE value) +{ + // + bool result = false; + + // + result = + value != NULL && + value != X_BOUNDARY_PRICE_NONE; + + // + return result; +} + +/** + * Converts To String ... + * + * @param value: ENUM_X_BOUNDARY_PRICE member ... + * + * @return ( string ) + */ +string ToString(ENUM_X_BOUNDARY_PRICE value) +{ + // + string result = NULL; + + // + if (!IsValid(value)) + { + value = X_BOUNDARY_PRICE_NONE; + } + + // + result = EnumToString(value); + + // + return result; +} + +// +// END Boundary Price Type ... +// + +// +// START Direction ... +// + +// +// Directions ... +enum ENUM_X_DIRECTION +{ + X_DIRECTION_ALL, // All + X_DIRECTION_NONE, // None + X_DIRECTION_BULLISH, // Bullish + X_DIRECTION_BEARISH, // Bearish +}; + +// +// Extensions ... + +/** + * Validate ... + * + * @param value: ENUM_X_DIRECTION member ... + * + * @return ( bool ) + */ +bool IsValid(ENUM_X_DIRECTION value) +{ + // + bool result = false; + + // + result = + value != NULL && + value != X_DIRECTION_NONE; + + // + return result; +} + +/** + * Validate value Has Specified Direction ... + * + * @param value: ENUM_X_DIRECTION member ... + * + * @return ( bool ) + */ +bool HasDirection(ENUM_X_DIRECTION value) +{ + // + bool result = false; + + // + result = IsValid(value) && + value != X_DIRECTION_ALL; + + // + return result; +} + +/** + * Check a Direction is Bullish or not ... + * + * @param value: ENUM_X_DIRECTION member ... + * + * @return ( bool ) + */ +bool IsBullish(ENUM_X_DIRECTION value) +{ + // + bool result = false; + + // + result = value == X_DIRECTION_BULLISH; + + // + return result; +} +bool IsSpecifiedBullish(ENUM_X_DIRECTION value) +{ + // + bool result = false; + + // + result = value == X_DIRECTION_BULLISH; + + // + return result; +} + +/** + * Check a Direction is Bearish or not ... + * + * @param value: ENUM_X_DIRECTION member ... + * + * @return ( bool ) + */ +bool IsBearish(ENUM_X_DIRECTION value) +{ + // + bool result = false; + + // + result = value == X_DIRECTION_BEARISH; + + // + return result; +} +bool IsSpecifiedBearish(ENUM_X_DIRECTION value) +{ + // + bool result = false; + + // + result = value == X_DIRECTION_BEARISH; + + // + return result; +} + +/** + * Converts Specified Direction to Opposit ... + * + * @param value: ENUM_X_DIRECTION member ... + * + * @return ( ENUM_X_DIRECTION ) + */ +ENUM_X_DIRECTION Opposit(ENUM_X_DIRECTION value) +{ + // + ENUM_X_DIRECTION result = X_DIRECTION_NONE; + + // + if (!HasDirection(value)) + { + return result; + } + + // + result = + IsBullish(value) + ? X_DIRECTION_BEARISH + : X_DIRECTION_BULLISH; + + // + return result; +} + +/** + * Converts To String ... + * + * @param value: ENUM_X_DIRECTION member ... + * + * @return ( string ) + */ +string ToString(ENUM_X_DIRECTION value) +{ + // + string result = NULL; + + // + switch (value) + { + case X_DIRECTION_ALL: + result = "ALL"; + break; + case X_DIRECTION_NONE: + result = "NONE"; + break; + case X_DIRECTION_BULLISH: + result = "BULLISH"; + break; + case X_DIRECTION_BEARISH: + result = "BEARISH"; + break; + } + + // + return result; +} + +// +// END Direction ... +// + +// +// START Fibo Level ... +// + +// +// Fibonacci Levels ... +enum ENUM_X_FIBO_LEVELS +{ + X_FIBO_LEVEL_236, // 0.236 + X_FIBO_LEVEL_270, // 0.27 + X_FIBO_LEVEL_382, // 0.382 + X_FIBO_LEVEL_500, // 0.5 + X_FIBO_LEVEL_618, // 0.618 + X_FIBO_LEVEL_730, // 0.730 + X_FIBO_LEVEL_764, // 0.764 + X_FIBO_LEVEL_786, // 0.786 +}; + +// +// Extensions ... + +/** + * Converts To String ... + * + * @param value: ENUM_X_FIBO_LEVELS member ... + * + * @return ( string ) + */ +string ToString(ENUM_X_FIBO_LEVELS value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_FIBO_LEVEL_236: + result = "0.236"; + break; + + // + case X_FIBO_LEVEL_270: + result = "0.270"; + break; + + // + case X_FIBO_LEVEL_382: + result = "0.382"; + break; + + // + case X_FIBO_LEVEL_500: + result = "0.500"; + break; + + // + case X_FIBO_LEVEL_618: + result = "0.618"; + break; + + // + case X_FIBO_LEVEL_730: + result = "0.730"; + break; + + // + case X_FIBO_LEVEL_764: + result = "0.764"; + break; + + // + case X_FIBO_LEVEL_786: + result = "0.786"; + break; + } + + // + return result; +} + +/** + * Converts To String ... + * + * @param value: ENUM_X_FIBO_LEVELS member ... + * + * @return ( double ) + */ +double GetFiboLevelValue(ENUM_X_FIBO_LEVELS value) +{ + // + double result = 0; + + // + switch (value) + { + // + case X_FIBO_LEVEL_236: + result = 0.236; + break; + + // + case X_FIBO_LEVEL_270: + result = 0.270; + break; + + // + case X_FIBO_LEVEL_382: + result = 0.382; + break; + + // + case X_FIBO_LEVEL_500: + result = 0.500; + break; + + // + case X_FIBO_LEVEL_618: + result = 0.618; + break; + + // + case X_FIBO_LEVEL_730: + result = 0.730; + break; + + // + case X_FIBO_LEVEL_764: + result = 0.764; + break; + + // + case X_FIBO_LEVEL_786: + result = 0.786; + break; + } + + // + return result; +} + +// +// END Fibo Level ... +// + +// +// START Swing Types ... +// + +// +// Swing Types ... +enum ENUM_X_SWING_TYPE +{ + X_SWING_NONE, // None + X_SWING_LOW, // Swing Low + X_SWING_HIGH, // Swing High +}; + +// +// Extensions ... + +/** + * Validate ... + * + * @param value: ENUM_X_DIRECTION member ... + * + * @return ( bool ) + */ +bool IsValid(ENUM_X_SWING_TYPE value) +{ + // + bool result = false; + + // + result = + value != NULL && + value != X_SWING_NONE; + + // + return result; +} + +/** + * Converts To String ... + * + * @param value: ENUM_X_SWING_TYPE member ... + * + * @return ( string ) + */ +string ToString(ENUM_X_SWING_TYPE value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_SWING_NONE: + result = "None"; + break; + + // + case X_SWING_LOW: + result = "Swing Low"; + break; + + // + case X_SWING_HIGH: + result = "Swing High"; + break; + } + + // + return result; +} + +/** + * Converts To ENUM_SERIESMODE ... + * + * @param value: ENUM_X_SWING_TYPE member ... + * + * @return ( ENUM_SERIESMODE ) + */ +ENUM_SERIESMODE ToSeriesMode(ENUM_X_SWING_TYPE value) +{ + // + ENUM_SERIESMODE result = MODE_HIGH; + + // + switch (value) + { + // + case X_SWING_HIGH: + result = MODE_HIGH; + break; + + // + case X_SWING_LOW: + default: + result = MODE_LOW; + break; + } + + // + return result; +} + +// +// END Swing Types ... +// + +// +// START Period Method ... +// + +// +// Period Calculation Method ... +enum ENUM_X_PERIOD_METHOD +{ + X_PERIOD_NONE, // None + X_PERIOD_AUTO, // Auto Select + X_PERIOD_MANUALLY // Manually +}; + +// +// Extensions ... + +/** + * Validate ... + * + * @param value: ENUM_X_PERIOD_METHOD member ... + * + * @return ( bool ) + */ +bool IsValid(ENUM_X_PERIOD_METHOD value) +{ + // + bool result = false; + + // + result = + value != NULL && + value != X_PERIOD_NONE; + + // + return result; +} + +/** + * Converts To String ... + * + * @param value: ENUM_X_PERIOD_METHOD member ... + * + * @return ( string ) + */ +string ToString(ENUM_X_PERIOD_METHOD value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_PERIOD_NONE: + result = "None"; + break; + + // + case X_PERIOD_AUTO: + result = "Auto Select"; + break; + + // + case X_PERIOD_MANUALLY: + result = "Manually"; + break; + } + + // + return result; +} + +// +// END Period Method ... +// + +// +// START Market Cycles ... +// + +// +// 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 +}; + +// +// Extensions ... + +/** + * Validate ... + * + * @param value: ENUM_X_MARKET_CYCLES member ... + * + * @return ( bool ) + */ +bool IsValid(ENUM_X_MARKET_CYCLES value) +{ + // + bool result = false; + + // + result = + // + value != NULL && + value != X_MARKET_CYCLE_UNKNOWN + // + ; + + // + return result; +} + +/** + * Converts an String to it's related Market Cycle ... + * + * @param value: string ... + * + * @return ( ENUM_X_MARKET_CYCLES ) + */ +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 To String ... + * + * @param value: ENUM_X_MARKET_CYCLES member ... + * + * @return ( string ) + */ +string ToString(ENUM_X_MARKET_CYCLES value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_MARKET_CYCLE_UNKNOWN: + result = "Unknown Cycle"; + break; + + // + case X_MARKET_CYCLE_SHORT: + result = "Short Cycle"; + break; + + // + case X_MARKET_CYCLE_MEDIUM: + result = "Medium Cycle"; + break; + + // + case X_MARKET_CYCLE_LONG: + result = "Long Cycle"; + break; + + // + case X_MARKET_CYCLE_HIND: + result = "Hind Cycle"; + break; + } + + // + return result; +} + +/** + * Retrieve All Availabled Market Cycles ... + * + * @param cycles: ENUM_X_MARKET_CYCLES member collection ... + * + * @return ( int ) + */ +int GetAllMarketCycles(ENUM_X_MARKET_CYCLES &cycles[]) +{ + // + ZeroMemory(cycles); + ArrayResize(cycles, 0); + + // + ArrayResize(cycles, ArraySize(cycles) + 1); + cycles[ArraySize(cycles) - 1] = X_MARKET_CYCLE_UNKNOWN; + + // + ArrayResize(cycles, ArraySize(cycles) + 1); + cycles[ArraySize(cycles) - 1] = X_MARKET_CYCLE_SHORT; + + // + ArrayResize(cycles, ArraySize(cycles) + 1); + cycles[ArraySize(cycles) - 1] = X_MARKET_CYCLE_MEDIUM; + + // + ArrayResize(cycles, ArraySize(cycles) + 1); + cycles[ArraySize(cycles) - 1] = X_MARKET_CYCLE_LONG; + + // + ArrayResize(cycles, ArraySize(cycles) + 1); + cycles[ArraySize(cycles) - 1] = X_MARKET_CYCLE_HIND; + + // + int result = ArraySize(cycles); + + // + return result; +} + +// +// END Market Cycles ... +// + +// +// START Week Days ... +// + +// +// Week Days ... +enum ENUM_X_WEEK_DAYS +{ + X_WEEK_DAY_NONE = -1, // None + X_WEEK_DAY_SUNDAY = 0, // Sunday + X_WEEK_DAY_MONDAY = 1, // Monday + X_WEEK_DAY_TUESDAY = 2, // Tuesday + X_WEEK_DAY_WEDNESDAY = 3, // Wednesday + X_WEEK_DAY_THURSDAY = 4, // Thursday + X_WEEK_DAY_FRIDAY = 5, // Friday + X_WEEK_DAY_SATURDAY = 6, // Saturday +}; + +// +// Extensions ... + +/** + * Validate ... + * + * @param value: ENUM_X_WEEK_DAYS member ... + * + * @return ( bool ) + */ +bool IsValid(ENUM_X_WEEK_DAYS value) +{ + // + bool result = false; + + // + result = + // + value != NULL && + value != X_WEEK_DAY_NONE + // + ; + + // + return result; +} + +/** + * Converts To String ... + * + * @param value: ENUM_X_WEEK_DAYS member ... + * + * @return ( string ) + */ +string ToString(ENUM_X_WEEK_DAYS value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_WEEK_DAY_NONE: + result = "None"; + break; + + // + case X_WEEK_DAY_SUNDAY: + result = "Sunday"; + break; + + // + case X_WEEK_DAY_MONDAY: + result = "Monday"; + break; + + // + case X_WEEK_DAY_TUESDAY: + result = "Tuesday"; + break; + + // + case X_WEEK_DAY_WEDNESDAY: + result = "Wednesday"; + break; + + // + case X_WEEK_DAY_THURSDAY: + result = "Thursday"; + break; + + // + case X_WEEK_DAY_FRIDAY: + result = "Friday"; + break; + + // + case X_WEEK_DAY_SATURDAY: + result = "Saturday"; + break; + } + + // + return result; +} + +// +// END Week Days ... +// + +// +// START Ma Methods ... +// + +// +// Ma Methods ... +enum ENUM_X_MA_METHOD +{ + X_MA_MODE_NONE, // None + X_MA_MODE_SMA, // SMA + X_MA_MODE_EMA, // EMA + X_MA_MODE_LWMA, // LWMA + X_MA_MODE_SMMA, // SMMA +}; + +// +// Extensions ... + +/** + * Validate ... + * + * @param value: ENUM_X_MA_METHOD member ... + * + * @return ( bool ) + */ +bool IsValid(ENUM_X_MA_METHOD value) +{ + // + bool result = false; + + // + result = + // + value != NULL && + value != X_MA_MODE_NONE + // + ; + + // + return result; +} + +/** + * Converts To String ... + * + * @param value: ENUM_X_MA_METHOD member ... + * + * @return ( string ) + */ +string ToString(ENUM_X_MA_METHOD value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_MA_MODE_NONE: + result = "None"; + break; + + // + case X_MA_MODE_SMA: + result = "SMA"; + break; + + // + case X_MA_MODE_EMA: + result = "EMA"; + break; + + // + case X_MA_MODE_LWMA: + result = "LWMA"; + break; + + // + case X_MA_MODE_SMMA: + result = "SMMA"; + break; + } + + // + return result; +} + +// +// END Ma Methods ... +// + +// \ No newline at end of file diff --git a/BKPS/14040316/Libraries/x-saherelm.x-ohcl.lib.mq5 b/BKPS/14040316/Libraries/x-saherelm.x-ohcl.lib.mq5 new file mode 100644 index 0000000..943f9d7 --- /dev/null +++ b/BKPS/14040316/Libraries/x-saherelm.x-ohcl.lib.mq5 @@ -0,0 +1,2003 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Common Library +// -------------------------------------- +// Name: XOHCLLib +// 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 + +// +#include "../Libraries/x-saherelm.common.extensions.lib.mq5" + +// +// Describe an Specific Candle ... +struct XOHCL +{ + // + // Props ... + + // + double high; + double open; + double close; + double low; + long volume; + double spread; + + // + 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 // + ); + open = NormalizePrice(open, mSymbol); + + // + close = iClose( + mSymbol, + mPeriod, + barIndex // + ); + close = NormalizePrice(close, mSymbol); + + // + high = iHigh( + mSymbol, + mPeriod, + barIndex // + ); + high = NormalizePrice(high, mSymbol); + + // + low = iLow( + mSymbol, + mPeriod, + barIndex // + ); + low = NormalizePrice(low, mSymbol); + + // + spread = iSpread( + mSymbol, + mPeriod, + barIndex // + ); + spread = NormalizePrice(spread, mSymbol); + + // + volume = iTickVolume( + 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; + } + + // + // Tools ... + + // + void Clean() + { + // + low = 0; + high = 0; + open = 0; + close = 0; + spread = 0; + volume = 0; + + // + time = NULL; + symbol = NULL; + period = NULL; + + // + ZeroMemory(this); + } + + // + // Validate Bar ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + low > 0 && + high > 0 && + open > 0 && + close > 0 && + spread > 0 && + volume > 0 + // + ; + + // + return result; + } + + // + int TotalBars() + { + // + int result = 0; + + // + result = iBars( + symbol, + period // + ); + + // + return result; + } + + // + // Calculate X_PRICE Specified Type ... + double GetPrice(ENUM_X_PRICE mPType) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + return GetAppliedPrice( + mPType, + open, + high, + low, + close // + ); + } + + // + // Retrieve Price base On Series Mode ... + double GetPrice(ENUM_SERIESMODE mMode) + { + // + ENUM_X_PRICE mType = ToXPrice(mMode); + + // + return GetPrice(mType); + } + + // + // Calculate Applied Price ... + double GetPrice(ENUM_APPLIED_PRICE mPType) + { + // + ENUM_X_PRICE mType = ToXPrice(mPType); + + // + return GetPrice(mType); + } + + // + // Find Specific Price ... + bool FindHigherPriceBar( + XOHCL &bar, + double price, + ENUM_X_PRICE _type = X_PRICE_HIGH // + ) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int totalBars = TotalBars(); + result = IsValidSize(totalBars); + if (!result) + { + return result; + } + + // + int start = Index(); + int maxAllowedLoopback = totalBars / 5; + for (int i = start; i < maxAllowedLoopback; i++) + { + // + result = bar.Init( + symbol, + period, + i // + ); + + // + if (!result) + { + break; + } + + // + double iPrice = bar.GetPrice(_type); + + // + result = + // + iPrice > 0 && + iPrice > price + // + ; + if (result) + { + break; + } + } + + // + if (!result) + { + bar.Clean(); + } + + // + return result; + } + + // + // Find Specific Price ... + bool FindLowerPriceBar( + XOHCL &bar, + double price, + ENUM_X_PRICE _type = X_PRICE_HIGH // + ) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int totalBars = TotalBars(); + result = IsValidSize(totalBars); + if (!result) + { + return result; + } + + // + int start = Index(); + int maxAllowedLoopback = totalBars / 5; + for (int i = start; i < maxAllowedLoopback; i++) + { + // + result = bar.Init( + symbol, + period, + i // + ); + + // + if (!result) + { + break; + } + + // + double iPrice = bar.GetPrice(_type); + + // + result = + // + iPrice > 0 && + iPrice < price + // + ; + if (result) + { + break; + } + } + + // + if (!result) + { + bar.Clean(); + } + + // + 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; + } + + // + // Get Direction of Bar ... + ENUM_X_DIRECTION GetDirection() + { + // + ENUM_X_DIRECTION result = X_DIRECTION_NONE; + + // + bool isBullish = IsBullish(); + bool isBearish = IsBearish(); + + // + result = + isBullish && isBearish + ? X_DIRECTION_ALL + : !isBullish && !isBearish + ? X_DIRECTION_NONE + : isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + 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; + } + + // + // Calculate Last Bar Open Time in Smaller Period ... + datetime GetLastBarTimeOfPeriod( + ENUM_TIMEFRAMES smallerPeriod // + ) + { + // + datetime result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + int sourceSeconds = PeriodSeconds(period); + int destSeconds = PeriodSeconds(smallerPeriod); + if (destSeconds >= sourceSeconds) + { + // + result = time; + return result; + } + + // + result = (datetime)((((int)time) + sourceSeconds) - destSeconds); + + // + return result; + } + + // + // Calculate Close Time ... + datetime GetCloseTime() + { + // + datetime result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + int seconds = PeriodSeconds(period); + + // + result = (datetime)(((int)time) + seconds); + + // + return result; + } + + // + bool BarAt( + int index, + XOHCL &bar // + ) + { + // + bool result = false; + + // + bar.Clean(); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + if (index < 0) + { + index = 0; + } + + // + result = bar.Init( + symbol, + period, + index // + ); + + // + return result; + } + + // + bool BarIn( + ENUM_TIMEFRAMES _period, + XOHCL &bar // + ) + { + // + bool result = false; + + // + bar.Clean(); + + // + result = IsValid() && + IsSpecifiedValid(_period); + if (!result) + { + return result; + } + + // + int index = Index(_period); + result = bar.Init( + symbol, + _period, + index // + ); + + // + return result; + } + + // + // Find Current Bar Index on Chart ... + int Index() + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + result = iBarShift( + symbol, + period, + time + // + ); + + // + return result; + } + + // + int Index(datetime value) + { + // + int result = -1; + + // + value = NormalizeTime(value); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + result = iBarShift( + symbol, + period, + value // + ); + + // + return result; + } + + // + int Index(ENUM_TIMEFRAMES value) + { + // + int result = -1; + + // + result = IsValid() && + IsSpecifiedValid(value); + if (!result) + { + return result; + } + + // + result = iBarShift( + symbol, + value, + time // + ); + + // + return result; + } + + // + bool GetNextBar(XOHCL &bar) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int idx = Index(); + result = idx > 0; + if (!result) + { + return result; + } + + // + result = bar.Init( + this.symbol, + this.period, + idx - 1 // + ); + + // + if (!result) + { + bar.Clean(); + } + + // + 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 // + ); + + // + if (!result) + { + bar.Clean(); + } + + // + return result; + } + + // + bool HasFiboPressure( + ENUM_X_DIRECTION forDir, + ENUM_X_FIBO_LEVELS level = X_FIBO_LEVEL_382 // + ) + { + // + bool result = false; + + // + result = IsValid() && + HasDirection(forDir); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + bool isBearish = IsBearish(forDir); + + // + double fiboLevelValue = GetFibonacciLevel( + high, + low, + level, + forDir // + ); + + // + isBullish = + isBullish && + GetDown() > fiboLevelValue; + isBearish = + isBearish && + GetUp() < fiboLevelValue; + + // + result = isBullish || + isBearish; + + // + return result; + } + + // + bool IsRejected( + double price, + ENUM_X_DIRECTION forDir, + bool forceType = false, + bool forcePressure = false // + ) + { + // + bool result = false; + + // + result = IsValid() && + price > 0 && + HasDirection(forDir); + if (!result) + { + return result; + } + + // + bool isBullish = + IsBullish(forDir) && + low < price && + GetDown() > price; + + // + bool isBearish = + IsBearish(forDir) && + high > price && + GetUp() < price; + + // + if (forceType) + { + // + isBullish = + isBullish && + IsBullish(); + + // + isBearish = + isBearish && + IsBearish(); + } + + // + if (forcePressure) + { + // + isBullish = + isBullish && + HasFiboPressure(forDir); + + // + isBearish = + isBearish && + HasFiboPressure(forDir); + } + + // + result = isBullish || + isBearish; + + // + return result; + } + + // + bool IsBreaked( + double price, + ENUM_X_DIRECTION forDir // + ) + { + // + bool result = false; + + // + result = IsValid() && + price > 0 && + HasDirection(forDir); + if (!result) + { + return result; + } + + // + bool isBullish = + IsBullish() && + IsBullish(forDir) && + close > price && + open < price; + + // + bool isBearish = + IsBearish() && + IsBearish(forDir) && + close < price && + open > price; + + // + result = isBullish || + isBearish; + + // + return result; + } + + // + // Find Highest 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 Highest ... + 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 Highest ... + double FindHighestUp( + int mLength // Loopback ... + ) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = FindHighest(mLength, MODE_OPEN); + result = MathMax(mLength, FindHighest(mLength, MODE_CLOSE)); + + // + 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; + } + + // + // Find Lowest ... + double FindLowesttDown( + int mLength // Loopback ... + ) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = FindLowest(mLength, MODE_OPEN); + result = MathMax(mLength, FindLowest(mLength, MODE_CLOSE)); + + // + return result; + } + + // + // Other ... + string GetTag(string prefix = "") + { + // + string result = NULL; + + // + result = + (IsValid(prefix) + ? prefix + "_" + : "") + + "XOHCL_" + symbol + "_" + ToString(period) + "_" + ToFormatString(time); + + // + 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; + } +}; + +// +// Models ... + +// +// 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; + + // + ZeroMemory(this); + } + + // + // 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; + } +}; + +// +// Tracking Times ... +struct XTimeTracker +{ + // + // Props ... + int xMonth; + int xDayOfWeek; + int xForWeekDay; + int xDay; + int xHour; + int xMinute; + + // + // Constructor ... + XTimeTracker() + { + Clean(); + } + + // + // Tools ... + + // + void Clean() + { + // + xDay = -1; + xHour = -1; + xMonth = -1; + xMinute = -1; + xDayOfWeek = -1; + xForWeekDay = -1; + + // + ZeroMemory(this); + } + + // + // Detecting New Minute ... + bool IsNewMinute() + { + // + bool result = false; + + // + // Retrieve Current Time as Struct ... + MqlDateTime timeStruct = GetCurrentTime(); + + // + // Check Houre ... + result = timeStruct.min != xMinute; + if (result) + { + xMinute = timeStruct.min; + } + + // + return result; + } + + // + // 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 ... + + // + bool waitsUntilNext; // Waits Until Next 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 iBars( + 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; + } + + // + bool CanProcessBar() + { + // + bool _isInTestMode = IsRunningOnTestMode(); + + // + bool isNewBar = IsNewBar(); + + // + bool result = + _isInTestMode + ? isNewBar + : !waitsUntilNext + ? true + : isNewBar; + if (result && waitsUntilNext) + { + waitsUntilNext = false; + } + + // + return result; + } + + // + void Waits() + { + this.waitsUntilNext = true; + } + + // + // Tools ... + void Clean() + { + // + symbol = NormalizeSymbol(NULL); + period = NormalizePeriod(NULL); + + // + ZeroMemory(this); + } + + // + bool GetBar( + XOHCL &bar, + int index = 0 // + ) + { + // + bool result = false; + + // + result = bar.Init( + symbol, + period, + index // + ); + + // + return result; + } + + // + bool GetBar( + XOHCL &bar, + datetime time = NULL // + ) + { + // + bool result = false; + + // + NormalizeTime(time); + + // + int barIndex = iBarShift( + symbol, + period, + time, + false // + ); + + // + result = barIndex >= 0; + if (!result) + { + return result; + } + + // + result = bar.Init( + symbol, + period, + barIndex // + ); + + // + return result; + } + + // + int Index(datetime time = NULL) + { + // + int result = 0; + + // + NormalizeTime(time); + + // + result = iBarShift( + symbol, + period, + time, + false // + ); + + // + return result; + } +}; + +// +// Extensions ... + +// +// Extract Specific Range of Bars ... +// using Start Bar Index ... +int GetBars( + XOHCL &bars[], // 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 +) +{ + // + int result = 0; + + // + from = NormalizeInt(from); + 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; + } + + // + Clean(bars); + + // + for (int i = start; i < end; i++) + { + // + XOHCL iBar; + bool isValid = iBar.Init( + mSymbol, + mPeriod, + i // + ); + + // + if (isValid) + { + // + AddRef( + iBar, + bars // + ); + } + } + + // + result = ArraySize(bars); + + // + return result; +} + +// +// Extract Specific Range of Bars ... +// using Start Bar Time ... +int GetBars( + XOHCL &bars[], // 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 +) +{ + // + from = NormalizeTime(from); + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + int barIndex = GetBarIndex( + mSymbol, + mPeriod, + from // + ); + + // + return GetBars( + bars, + mSymbol, + mPeriod, + barIndex, + count // + ); +} + +// \ No newline at end of file diff --git a/BKPS/14040316/Libraries/x-saherelm.x-poi.extensions.lib.mq5 b/BKPS/14040316/Libraries/x-saherelm.x-poi.extensions.lib.mq5 new file mode 100644 index 0000000..7f984fa --- /dev/null +++ b/BKPS/14040316/Libraries/x-saherelm.x-poi.extensions.lib.mq5 @@ -0,0 +1,3804 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Seriallize Library +// --------------------------------------- +// Name: XPOILib +// Description: All models related to POIs ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright `023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Libraries/x-saherelm.x-poi.lib.mq5" + +// +// Extensions ... + +template +bool ToZone( + T *&source[], + XCZone *&dest[] // +) +{ + // + bool result = false; + + // + Clean(dest); + + // + int count = ArraySize(source); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + T *item = source[i]; + + // + if (item != NULL) + { + // + Add( + (XCZone *)item, + dest // + ); + } + } + + // + int destCount = ArraySize(dest); + result = IsValidSize(destCount); + + // + return result; +} + +template +bool ToBox( + T *&source[], + XBoxZone &dest[] // +) +{ + // + bool result = false; + + // + Clean(dest); + + // + int count = ArraySize(source); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + T *item = source[i]; + + // + if (item != NULL) + { + // + XBoxZone iBox; + bool hasBox = ToBox( + iBox, + item // + ); + + // + if (hasBox) + { + // + AddRef( + iBox, + dest // + ); + } + } + } + + // + int destCount = ArraySize(dest); + result = IsValidSize(destCount); + + // + return result; +} + +template +int GetOldest( + T *&source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone boxes[]; + bool isConverted = ToBox( + source, + boxes // + ); + if (!isConverted) + { + return result; + } + + // + int boxesCount = ArraySize(boxes); + + // + if (count != boxesCount) + { + return result; + } + + // + result = GetOldest(boxes); + + // + Clean(boxes); + + // + return result; +} + +template +int GetYoungest( + T *&source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone boxes[]; + bool isConverted = ToBox( + source, + boxes // + ); + if (!isConverted) + { + return result; + } + + // + int boxesCount = ArraySize(boxes); + + // + if (count != boxesCount) + { + return result; + } + + // + result = GetYoungest(boxes); + + // + Clean(boxes); + + // + return result; +} + +template +int GetLowest( + T *&source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone boxes[]; + bool isConverted = ToBox( + source, + boxes // + ); + if (!isConverted) + { + return result; + } + + // + int boxesCount = ArraySize(boxes); + + // + if (count != boxesCount) + { + return result; + } + + // + result = GetLowest(boxes); + + // + Clean(boxes); + + // + return result; +} + +template +int GetHighest( + T *&source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone boxes[]; + bool isConverted = ToBox( + source, + boxes // + ); + if (!isConverted) + { + return result; + } + + // + int boxesCount = ArraySize(boxes); + + // + if (count != boxesCount) + { + return result; + } + + // + result = GetHighest(boxes); + + // + Clean(boxes); + + // + return result; +} + +template +bool IsSame( + T *source, + T *dest // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = sourceBox.IsSameAs(destBox); + + // + return result; +} + +template +bool IsSameDiff( + T *source, + F *dest // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = sourceBox.IsSame(destBox); + + // + return result; +} + +template +bool IsBelow( + T *source, + T *dest, + bool ignoreInside = false // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = IsBoxBelow( + sourceBox, + destBox, + ignoreInside // + ); + + // + return result; +} + +template +bool IsBelowDiff( + T *source, + F *dest, + bool ignoreInside = false // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = IsBoxBelow( + sourceBox, + destBox, + ignoreInside // + ); + + // + return result; +} + +template +bool IsAbove( + T *source, + T *dest, + bool ignoreInside = false // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = IsBoxAbove( + sourceBox, + destBox, + ignoreInside // + ); + + // + return result; +} + +template +bool IsAboveDiff( + T *source, + F *dest, + bool ignoreInside = false // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = IsBoxAbove( + sourceBox, + destBox, + ignoreInside // + ); + + // + return result; +} + +template +bool IsInside( + T *source, + T *dest // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = IsBoxInside( + sourceBox, + destBox // + ); + + // + return result; +} + +template +bool IsInsideOr( + T *source, + T *dest // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = IsBoxInsideOr( + sourceBox, + destBox // + ); + + // + return result; +} + +template +bool IsInsideDiff( + T *source, + F *dest, + bool forceSideOut = false // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = IsBoxInside( + sourceBox, + destBox, + forceSideOut // + ); + + // + return result; +} + +template +bool IsInsideOrDiff( + T *source, + F *dest, + bool forceSideOut = false // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = IsBoxInsideOr( + sourceBox, + destBox // + ); + + // + return result; +} + +template +bool FindIndex( + int &index, + T *item, + T *&items[] // +) +{ + // + bool result = false; + + // + index = -1; + + // + XBoxZone itemBox; + result = ToBox( + itemBox, + item // + ); + if (!result) + { + return result; + } + + // + XBoxZone itemsBox[]; + result = ToBox( + items, + itemsBox // + ); + if (!result) + { + return result; + } + + // + result = FindBoxIndex( + index, + itemBox, + itemsBox // + ); + + // + return result; +} + +template +bool IsInside( + double value, + T *source // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + result = IsInsideBox( + value, + sourceBox // + ); + + // + return result; +} + +template +bool IsAbove( + double value, + T *source // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + result = IsAboveBox( + value, + sourceBox // + ); + + // + return result; +} + +template +bool IsBelow( + double value, + T *source // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + result = IsBelowBox( + value, + sourceBox // + ); + + // + return result; +} + +/** + * Find Specified Box Index inside a Collection of Boxes ... + * + * @param box: XBoxZone instance Reference ... + * @param boxes: XBoxZone instance Reference Collection ... + * + * @return ( int ) + */ +bool FindBoxIndex( + int &index, + XBoxZone &box, + XBoxZone &boxes[] // +) +{ + // + bool result = false; + + // + index = -1; + + // + int count = ArraySize(boxes); + result = box.IsValid() && + IsValidSize(count); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = boxes[i]; + + // + bool isSame = box.IsSameAs(iBox); + if (isSame) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; +} + +/** + * Check a BaxHas Valid Place for Specified Bar ... + * + * @param bar: XOHCL instance reference, Specified Bar ... + * #param box: XBoxZone instance reference, Specified Box ... + * + * @return ( bool ) + */ +bool IsBoxPlaceValidForBar( + XOHCL &bar, + XBoxZone &box // +) +{ + // + bool result = false; + + // + result = bar.IsValid() && + box.IsValid(); + if (!result) + { + return result; + } + + // + result = + box.IsBullish() + ? bar.low > box.upper + : bar.high < box.upper; + + // + return result; +} + +/** + * Check Source Box is Below Dest ... + * + * @param source: XBoxZone instance Reference ... + * @param dest: XBoxZone instance Reference ... + * @param ignoreInside: bool ... + * + * @return ( bool ) + */ +bool IsBoxBelow( + XBoxZone &source, + XBoxZone &dest, + bool ignoreInside = false // +) +{ + // + bool result = false; + + // + result = source.IsValid() && + dest.IsValid() && + !source.IsSameAs(dest); + if (!result) + { + return result; + } + + // + if (!ignoreInside) + { + result = source.upper < dest.lower; + } + else + { + result = (source.upper < dest.lower || + source.upper >= dest.upper) && + source.lower < dest.lower; + } + + // + return result; +} + +/** + * Check Source Box is Above Dest ... + * + * @param source: XBoxZone instance Reference ... + * @param dest: XBoxZone instance Reference ... + * @param ignoreInside: bool ... + * + * @return ( bool ) + */ +bool IsBoxAbove( + XBoxZone &source, + XBoxZone &dest, + bool ignoreInside = false // +) +{ + // + bool result = false; + + // + result = source.IsValid() && + dest.IsValid() && + !source.IsSameAs(dest); + if (!result) + { + return result; + } + + // + if (!ignoreInside) + { + result = source.lower > dest.upper; + } + else + { + result = (source.lower > dest.upper || + source.lower <= dest.upper) && + source.upper > dest.upper; + } + + // + return result; +} + +/** + * Check Source Box is Inside Dest ... + * + * @param source: XBoxZone instance Reference ... + * @param dest: XBoxZone instance Reference ... + * @param forceSideOut: bool, force check Box has One Side Out ... + * @param ignoreSideOut: bool, Accept if source Box one Side is out of Dest Box ... + * + * @return ( bool ) + */ +bool IsBoxInside( + XBoxZone &source, + XBoxZone &dest, + bool forceSideOut = false, // + bool ignoreSideOut = true // +) +{ + // + bool result = false; + + // + result = source.IsValid() && + dest.IsValid() && + !source.IsSameAs(dest); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(dest.dir); + + // + if (!forceSideOut) + { + // + if (ignoreSideOut) + { + // + result = source.lower >= dest.lower && + source.upper <= dest.upper; + } + else + { + result = source.lower >= dest.lower || + source.upper <= dest.upper; + } + } + else + { + // + bool hasSideIn = + isBullish + ? source.lower >= dest.lower + : source.upper <= dest.upper; + bool hasSideOut = + isBullish + ? source.upper >= dest.upper + : source.lower <= dest.lower; + result = + hasSideIn && + hasSideOut; + } + + // + return result; +} + +/** + * Detect source BoX is Inside Dest Box or Have a Side Out on it ... + * + * @param source: XBoxZone instance, source box which checks by dest ... + * @param dest: XBoxZone instance, dest Box which compares source with it ... + * + * @return ( bool ) + */ +bool IsBoxInsideOr( + XBoxZone &source, + XBoxZone &dest, + bool forceInside = false // +) +{ + // + bool result = false; + + // + result = source.IsValid() && + dest.IsValid() && + !source.IsSameAs(dest); + if (!result) + { + return result; + } + + // + bool isInside = + source.upper <= dest.upper && + source.upper >= dest.lower && + source.lower >= dest.lower && + source.lower <= dest.upper; + bool isUpperInside = + source.upper <= dest.upper && + source.upper >= dest.lower; + bool isLowerInside = + source.lower >= dest.lower && + source.lower <= dest.upper; + + // + result = + forceInside + ? isInside + : (isInside || + isLowerInside || + isUpperInside); + + // + return result; +} + +/** + * Check Value is Inside Specified Box ... + * + * @param value: double ... + * @param box: XCBozZone instance Reference ... + * + * @return ( bool ) + */ +bool IsInsideBox( + double value, + XBoxZone &box // +) +{ + // + bool result = false; + + // + result = value > 0 && + box.IsValid() && + value <= box.upper && + value >= box.lower; + + // + return result; +} + +/** + * Check Bar is Inside Specified Box ... + * + * @param bar: XOHCL instance reference, Specified Bar ... + * @param box: XCBozZone instance Reference ... + * + * @return ( bool ) + */ +bool IsInsideBox( + XOHCL &bar, + XBoxZone &box // +) +{ + // + bool result = false; + + // + // Validate Args ... + result = bar.IsValid() && + box.IsValid(); + if (!result) + { + return result; + } + + // + result = + bar.close <= box.upper && + bar.close >= box.lower; + + // + return result; +} + +/** + * Check Value is Above Specified Box ... + * + * @param value: double ... + * @param box: XCBozZone instance Reference ... + * + * @return ( bool ) + */ +bool IsAboveBox( + double value, + XBoxZone &box // +) +{ + // + bool result = false; + + // + result = value > 0 && + box.IsValid() && + value > box.upper; + + // + return result; +} + +/** + * Check Value is Below Specified Box ... + * + * @param value: double ... + * @param box: XCBozZone instance Reference ... + * + * @return ( bool ) + */ +bool IsBelowBox( + double value, + XBoxZone &box // +) +{ + // + bool result = false; + + // + result = value > 0 && + box.IsValid() && + value < box.lower; + + // + return result; +} + +/** + * Check a Box is Used or not ... + * + * @param box: XBoxZone instance Reference ... + * @param fromIndex: int ... + * @param toIndex: int + * @param forPeriod: Specified Period ... + * + * @return ( bool ) + */ +bool IsBoxUsed( + XBoxZone &box, + int fromIndex, + int toIndex = 0, + ENUM_TIMEFRAMES forPeriod = NULL // +) +{ + // + bool result = false; + + // + if (toIndex < 0) + { + toIndex = 0; + } + + // + result = + // + box.IsValid() && + fromIndex > 0 && + fromIndex > toIndex + // + ; + if (!result) + { + return result; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = box.period; + } + + // + ENUM_X_DIRECTION forDir = box.dir; + bool isBullish = IsBullish(forDir); + + // + bool isTouched = false; + for (int i = fromIndex; i >= toIndex; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + box.symbol, + forPeriod, + i // + ); + + // + isTouched = + isInited && + (isBullish + ? iBar.low > box.upper + : iBar.high < box.lower); + if (!isTouched) + { + continue; + } + + // + iBar.Clean(); + break; + } + + // + result = isTouched; + + // + return result; +} + +/** + * Validate Box ... + * + * @param box: XBoxZone instance ... + * @param barIndex: int, Current Bar Index ... + * @param forPeriod: Testing Period ... + * + * @return ( bool ) + */ +bool IsBoxValid( + XBoxZone &box, + int barIndex = 0, + ENUM_TIMEFRAMES forPeriod = NULL // +) +{ + // + bool result = false; + + // + result = box.IsValid(); + if (!result) + { + return result; + } + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = box.period; + } + + // + int toIndex = iBarShift( + box.symbol, + forPeriod, + box.to // + ); + result = IsValidIndex(toIndex); + if (!result) + { + return result; + } + + // + XOHCL iBar; + bool isBullish = box.IsBullish(); + for (int i = barIndex; i < toIndex; i++) + { + // + result = iBar.Init( + box.symbol, + forPeriod, + i // + ); + if (!result) + { + break; + } + + // + result = + isBullish + ? iBar.low > box.upper + : iBar.high < box.lower; + if (!result) + { + break; + } + + // + iBar.Clean(); + } + + // + iBar.Clean(); + + // + return result; +} + +/** + * Check Box Breaked ... + * + * @param box: XBoxZone instance ... + * @param barIndex: int, Current Bar Index ... + * @param forPeriod: Testing Period ... + * + * @return ( bool ) + */ +bool IsBoxBreaked( + XBoxZone &box, + int barIndex = 0, + ENUM_TIMEFRAMES forPeriod = NULL // +) +{ + // + bool result = false; + + // + result = box.IsValid(); + if (!result) + { + return result; + } + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = box.period; + } + + // + int toIndex = iBarShift( + box.symbol, + forPeriod, + box.to // + ); + result = IsValidIndex(toIndex); + if (!result) + { + return result; + } + + // + XOHCL iBar; + bool isBullish = box.IsBullish(); + for (int i = barIndex; i < toIndex; i++) + { + // + result = iBar.Init( + box.symbol, + forPeriod, + i // + ); + if (!result) + { + break; + } + + // + result = + isBullish + ? iBar.high < box.lower + : iBar.low > box.upper; + if (!result) + { + break; + } + + // + iBar.Clean(); + } + + // + iBar.Clean(); + + // + return result; +} + +/** + * Check a Box is Breaked or not ... + * + * @param box: XBoxZone instance Reference ... + * @param fromIndex: int ... + * @param toIndex: int + * @param forPeriod: Specified Period ... + * + * @return ( bool ) + */ +bool IsBoxBreaked( + XBoxZone &box, + int fromIndex, + int toIndex = 0, + ENUM_TIMEFRAMES forPeriod = NULL // +) +{ + // + bool result = false; + + // + if (toIndex < 0) + { + toIndex = 0; + } + + // + result = + // + box.IsValid() && + fromIndex > 0 && + fromIndex > toIndex + // + ; + if (!result) + { + return result; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = box.period; + } + + // + ENUM_X_DIRECTION forDir = box.dir; + bool isBullish = IsBullish(forDir); + + // + bool isBreaked = false; + for (int i = fromIndex; i >= toIndex; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + box.symbol, + forPeriod, + i // + ); + + // + isBreaked = + isInited && + (isBullish + ? iBar.high <= box.lower + : iBar.low >= box.upper); + if (!isBreaked) + { + continue; + } + + // + iBar.Clean(); + break; + } + + // + result = isBreaked; + + // + return result; +} + +/** + * Find an Inside Box of source in a Collection ... + * + * @param index: int, Founded Index ... + * @param source: XBoxZone instance ... + * @param dest: XBoxZone instance Collection ... + * + * @return ( bool ) + */ +bool HasInsideBox( + int &index, + XBoxZone &source, + XBoxZone &dest[] // +) +{ + // + bool result = false; + + // + index = -1; + + // + result = source.IsValid() && + HasChild(dest); + + // + int count = ArraySize(dest); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = dest[i]; + + // + bool isInside = !iBox.IsSameAs(source) && + IsBoxInsideOr( + iBox, + source // + ); + if (isInside) + { + // + index = i; + iBox.Clean(); + + // + break; + } + + // + iBox.Clean(); + } + + // + result = IsValidIndex(index); + + // + return result; +} + +/** + * Remove Specified Box from Collection ... + */ +bool RemoveBox( + XBoxZone &box, + XBoxZone &boxes[] // +) +{ + // + bool result = false; + + // + result = + box.IsValid() && + HasChild(boxes); + if (!result) + { + return result; + } + + // + int idx = -1; + result = FindBoxIndex( + idx, + box, + boxes // + ); + if (!result) + { + return result; + } + + // + result = ArrayRemove( + boxes, + idx, + 1 // + ); + + // + return result; +} + +/** + * Converts to XBoxZone ... + * + * @return ( bool ) + */ +bool ToBox( + XBoxZone &box, + XCOrderBlock *item // +) +{ + // + bool result = false; + + // + box.Clean(); + + // + result = item != NULL && + item.IsValid(); + if (!result) + { + return result; + } + + // + box.to = item.To(); + box.from = item.From(); + box.upper = item.Upper(); + box.lower = item.Lower(); + box.symbol = item.GetSymbol(); + box.period = item.GetPeriod(); + box.type = item.TypeAsString(); + box.dir = item.IsBullish() + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = box.IsValid(); + + // + return result; +} + +/** + * Converts to XBoxZone ... + * + * @return ( bool ) + */ +bool ToBox( + XBoxZone &box, + XCFVG *item // +) +{ + // + bool result = false; + + // + box.Clean(); + + // + result = item != NULL && + item.IsValid(); + if (!result) + { + return result; + } + + // + box.to = item.To(); + box.from = item.From(); + box.upper = item.Upper(); + box.lower = item.Lower(); + box.symbol = item.GetSymbol(); + box.period = item.GetPeriod(); + box.type = item.TypeAsString(); + box.dir = item.IsBullish() + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = box.IsValid(); + + // + return result; +} + +/** + * Converts to XBoxZone ... + * + * @return ( bool ) + */ +bool ToBox( + XBoxZone &box, + XCSupportZone *item // +) +{ + // + bool result = false; + + // + box.Clean(); + + // + result = item != NULL && + item.IsValid(); + if (!result) + { + return result; + } + + // + box.to = item.To(); + box.from = item.From(); + box.upper = item.Upper(); + box.lower = item.Lower(); + box.symbol = item.GetSymbol(); + box.period = item.GetPeriod(); + box.type = item.TypeAsString(); + box.dir = X_DIRECTION_BULLISH; + + // + result = box.IsValid(); + + // + return result; +} + +/** + * Converts to XBoxZone ... + * + * @return ( bool ) + */ +bool ToBox( + XBoxZone &box, + XCResistanceZone *item // +) +{ + // + bool result = false; + + // + box.Clean(); + + // + result = item != NULL && + item.IsValid(); + if (!result) + { + return result; + } + + // + box.to = item.To(); + box.from = item.From(); + box.upper = item.Upper(); + box.lower = item.Lower(); + box.symbol = item.GetSymbol(); + box.period = item.GetPeriod(); + box.type = item.TypeAsString(); + box.dir = X_DIRECTION_BEARISH; + + // + result = box.IsValid(); + + // + return result; +} + +/** + * Converts to XBoxZone ... + * + * @return ( bool ) + */ +bool ToBox( + XBoxZone &box, + XCSupplyZone *item // +) +{ + // + bool result = false; + + // + box.Clean(); + + // + result = item != NULL && + item.IsValid(); + if (!result) + { + return result; + } + + // + box.to = item.To(); + box.from = item.From(); + box.upper = item.Upper(); + box.lower = item.Lower(); + box.symbol = item.GetSymbol(); + box.period = item.GetPeriod(); + box.type = item.TypeAsString(); + box.dir = X_DIRECTION_BEARISH; + + // + result = box.IsValid(); + + // + return result; +} + +/** + * Converts to XBoxZone ... + * + * @return ( bool ) + */ +bool ToBox( + XBoxZone &box, + XCDemandZone *item // +) +{ + // + bool result = false; + + // + box.Clean(); + + // + result = item != NULL && + item.IsValid(); + if (!result) + { + return result; + } + + // + box.to = item.To(); + box.from = item.From(); + box.upper = item.Upper(); + box.lower = item.Lower(); + box.symbol = item.GetSymbol(); + box.period = item.GetPeriod(); + box.type = item.TypeAsString(); + box.dir = X_DIRECTION_BULLISH; + + // + result = box.IsValid(); + + // + return result; +} + +/** + * Converts to XBoxZone ... + * + * @return ( bool ) + */ +bool ToBox( + XBoxZone &box, + XConsolidationZone &item // +) +{ + // + bool result = false; + + // + box.Clean(); + + // + result = item.IsValid(); + if (!result) + { + return result; + } + + // + box.to = item.to; + box.dir = item.dir; + box.from = item.from; + box.upper = item.upper; + box.lower = item.lower; + box.symbol = item.symbol; + box.period = item.period; + box.type = IsBullish(item.dir) + ? ToString(X_BULLISH_CONSOLIDATION_ZONE) + : ToString(X_BEARISH_CONSOLIDATION_ZONE); + + // + result = box.IsValid(); + + // + return result; +} + +/** + * Converts to XBoxZone ... + * + * @return ( bool ) + */ +int ToBox( + XConsolidationZone &source[], + XBoxZone &dest[] // +) +{ + // + int result = 0; + + // + Clean(dest); + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XConsolidationZone iZone = source[i]; + + // + XBoxZone iBox; + bool hasBox = ToBox( + iBox, + iZone // + ); + + // + if (hasBox) + { + // + AddRef( + iBox, + dest // + ); + } + + // + iBox.Clean(); + iZone.Clean(); + } + + // + result = ArraySize(dest); + + // + return result; +} + +/** + * Get Oldest Box Index ... + * + * @param source: XBoxZone instance Reference Collection ... + * + * @return ( int ) + */ +int GetOldest( + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = source[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.from > iBox.from; + if (canSet) + { + // + result = i; + selected = iBox; + } + + // + iBox.Clean(); + } + + // + selected.Clean(); + + // + return result; +} +int GetOldest( + XOHCL &bar, + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + if (!bar.IsValid()) + { + return result; + } + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = source[i]; + + // + bool isBoxValidForBar = IsBoxPlaceValidForBar(bar, iBox); + if (!isBoxValidForBar) + { + // + iBox.Clean(); + + // + continue; + } + + // + bool canSet = + !selected.IsValid() + ? true + : selected.from > iBox.from; + if (canSet) + { + // + result = i; + selected = iBox; + } + + // + iBox.Clean(); + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Get Youngest Box Index ... + * + * @param source: XBoxZone instance Reference Collection ... + * + * @return ( int ) + */ +int GetYoungest( + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = source[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.from < iBox.from; + if (canSet) + { + // + result = i; + selected = iBox; + } + + // + iBox.Clean(); + } + + // + selected.Clean(); + + // + return result; +} +int GetYoungest( + XOHCL &bar, + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + if (!bar.IsValid()) + { + return result; + } + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = source[i]; + + // + bool isBoxValidForBar = IsBoxPlaceValidForBar(bar, iBox); + if (!isBoxValidForBar) + { + // + iBox.Clean(); + + // + continue; + } + + // + bool canSet = + !selected.IsValid() + ? true + : selected.from < iBox.from; + if (canSet) + { + // + result = i; + selected = iBox; + } + + // + iBox.Clean(); + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Get Highest Box Index ... + * + * @param source: XBoxZone instance Reference Collection ... + * + * @return ( int ) + */ +int GetHighest( + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = source[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.upper < iBox.upper; + if (canSet) + { + // + result = i; + selected = iBox; + } + + // + iBox.Clean(); + } + + // + selected.Clean(); + + // + return result; +} +int GetHighest( + XOHCL &bar, + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + if (!bar.IsValid()) + { + return result; + } + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = source[i]; + + // + bool isBoxValidForBar = IsBoxPlaceValidForBar(bar, iBox); + if (!isBoxValidForBar) + { + // + iBox.Clean(); + + // + continue; + } + + // + bool canSet = + !selected.IsValid() + ? true + : selected.upper < iBox.upper; + if (canSet) + { + // + result = i; + selected = iBox; + } + + // + iBox.Clean(); + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Get Lowest Box Index ... + * + * @param source: XBoxZone instance Reference Collection ... + * + * @return ( int ) + */ +int GetLowest( + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = source[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.lower > iBox.lower; + if (canSet) + { + // + result = i; + selected = iBox; + } + + // + iBox.Clean(); + } + + // + selected.Clean(); + + // + return result; +} +int GetLowest( + XOHCL &bar, + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + if (!bar.IsValid()) + { + return result; + } + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = source[i]; + + // + bool isBoxValidForBar = IsBoxPlaceValidForBar(bar, iBox); + if (!isBoxValidForBar) + { + // + iBox.Clean(); + + // + continue; + } + + // + bool canSet = + !selected.IsValid() + ? true + : selected.lower > iBox.lower; + if (canSet) + { + // + result = i; + selected = iBox; + } + + // + iBox.Clean(); + } + + // + selected.Clean(); + + // + return result; +} + +// +// +// + +/** + * Get Oldest Index ... + * + * @param source: XConsolidationZone instance Reference Collection ... + * + * @return ( int ) + */ +int GetOldest( + XConsolidationZone &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone tmpBoxes[]; + int boxesCount = ToBox( + source, + tmpBoxes // + ); + if (!IsValidSize(boxesCount)) + { + // + Clean(tmpBoxes); + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < boxesCount; i++) + { + // + XBoxZone iBox = tmpBoxes[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.from > iBox.from; + if (canSet) + { + // + result = i; + selected = iBox; + } + } + + // + Clean(tmpBoxes); + selected.Clean(); + + // + return result; +} + +/** + * Get Youngest Index ... + * + * @param source: XConsolidationZone instance Reference Collection ... + * + * @return ( int ) + */ +int GetYoungest( + XConsolidationZone &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone tmpBoxes[]; + int boxesCount = ToBox( + source, + tmpBoxes // + ); + if (!IsValidSize(boxesCount)) + { + // + Clean(tmpBoxes); + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < boxesCount; i++) + { + // + XBoxZone iBox = tmpBoxes[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.from < iBox.from; + if (canSet) + { + // + result = i; + selected = iBox; + } + } + + // + Clean(tmpBoxes); + selected.Clean(); + + // + return result; +} + +/** + * Get Highest Index ... + * + * @param source: XConsolidationZone instance Reference Collection ... + * + * @return ( int ) + */ +int GetHighest( + XConsolidationZone &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone tmpBoxes[]; + int boxesCount = ToBox( + source, + tmpBoxes // + ); + if (!IsValidSize(boxesCount)) + { + // + Clean(tmpBoxes); + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < boxesCount; i++) + { + // + XBoxZone iBox = tmpBoxes[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.upper < iBox.upper; + if (canSet) + { + // + result = i; + selected = iBox; + } + } + + // + Clean(tmpBoxes); + selected.Clean(); + + // + return result; +} + +/** + * Get Lowest Index ... + * + * @param source: XConsolidationZone instance Reference Collection ... + * + * @return ( int ) + */ +int GetLowest( + XConsolidationZone &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone tmpBoxes[]; + int boxesCount = ToBox( + source, + tmpBoxes // + ); + if (!IsValidSize(boxesCount)) + { + // + Clean(tmpBoxes); + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < boxesCount; i++) + { + // + XBoxZone iBox = tmpBoxes[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.lower > iBox.lower; + if (canSet) + { + // + result = i; + selected = iBox; + } + } + + // + Clean(tmpBoxes); + selected.Clean(); + + // + return result; +} + +// +// +// + +// +template +void SortZones( + T *&source[], + ENUM_X_DIRECTION forDir, + bool ignoreInside = true // +) +{ + // + int idx = -1; + int count = 0; + bool has = false; + + // + has = HasDirection(forDir); + if (!has) + { + return; + } + + // + bool isBullish = IsBullish(forDir); + + // + count = ArraySize(source); + has = IsValidSize(count); + if (!has) + { + return; + } + + // + T *tmpItems[]; + T *last = NULL; + bool hasLast = false; + while (HasChild(source)) + { + // + if (!hasLast) + { + // + idx = GetOldest(source); + hasLast = IsValidIndex(idx); + if (hasLast) + { + // + last = source[idx]; + ArrayRemove( + source, + idx, + 1 // + ); + + // + Add( + last, + tmpItems // + ); + } + + // + count = ArraySize(source); + has = IsValidSize(count); + if (!has) + { + // + ZeroMemory(last); + break; + } + } + if (!hasLast) + { + // + ZeroMemory(last); + break; + } + + // + T *item = NULL; + idx = GetOldest(source); + has = IsValidIndex(idx); + if (!has) + { + // + ZeroMemory(last); + ZeroMemory(item); + break; + } + item = source[idx]; + ArrayRemove( + source, + idx, + 1 // + ); + + // + bool isAbove = IsAbove( + item, + last, + ignoreInside // + ); + + // + bool isBelow = IsBelow( + item, + last, + ignoreInside // + ); + + // + has = + isBullish + ? isAbove + : isBelow; + if (has) + { + // + Add( + item, + tmpItems // + ); + + // + last = item; + hasLast = item != NULL; + } + } + + // + Clean(source); + Copy( + tmpItems, + source // + ); + + // + Clean(tmpItems); +} + +/** + * Extract all Zones Which provided bar is Inside it ... + * + * @return ( int ) + */ +template +int ExtractInsideZones( + XOHCL &bar, // Bar ... + T *&zones[], // Source of Zones ... + T *&dest[] // Dest (all inside Zones) ... +) +{ + // + int result = 0; + + // + Clean(dest); + + // + int count = ArraySize(zones); + bool isValid = bar.IsValid() && + IsValidSize(count); + if (!isValid) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + T *iZone = zones[i]; + + // + bool isHighInside = IsInside( + bar.high, + iZone // + ); + + // + bool isLowInside = IsInside( + bar.low, + iZone // + ); + + // + bool isInside = + isLowInside && + isHighInside; + + // + if (isInside) + { + // + Add( + iZone, + dest // + ); + } + + // + ZeroMemory(iZone); + } + + // + result = ArraySize(dest); + + // + return result; +} + +/** + * Add Specific Item into a Collection Reference only if it's not Exists ... + * + * @return ( bool ) + */ +template +bool AddIfNotExists( + T *item, + T *&items[] // +) +{ + // + bool result = false; + + // + result = item != NULL; + if (!result) + { + return result; + } + + // + int before = ArraySize(items); + + // + int idx = FindIndex( + item, + items // + ); + bool has = IsValidIndex(idx); + result = !has; + if (!result) + { + return result; + } + + // + Add( + item, + items // + ); + + // + int after = ArraySize(items); + + // + result = after > before; + + // + return result; +} +bool AddIfNotExists( + XConsolidationZone &item, + XConsolidationZone &items[] // +) +{ + // + bool result = false; + + // + result = item.IsValid(); + if (!result) + { + return result; + } + + // + int before = ArraySize(items); + + // + int idx = FindIndex( + item, + items // + ); + bool has = IsValidIndex(idx); + result = !has; + if (!result) + { + return result; + } + + // + AddRef( + item, + items // + ); + + // + int after = ArraySize(items); + + // + result = after > before; + + // + return result; +} + +/** + * Add items Collection reference Members into source Collection only if it's not Exists ...alignas + * @return ( int ) + */ +template +int AddIfNotExists( + T *&items[], + T *&sources[] // +) +{ + // + int result = 0; + + // + bool has = HasChild(items); + if (!has) + { + return result; + } + + // + int before = ArraySize(sources); + + // + int count = ArraySize(items); + for (int i = 0; i < count; i++) + { + // + has = AddIfNotExists( + items[i], + sources // + ); + } + + // + int after = ArraySize(sources); + + // + result = after > before; + + // + return result; +} +int AddIfNotExists( + XConsolidationZone &items[], + XConsolidationZone &sources[] // +) +{ + // + int result = 0; + + // + bool has = HasChild(items); + if (!has) + { + return result; + } + + // + int before = ArraySize(sources); + + // + int count = ArraySize(items); + for (int i = 0; i < count; i++) + { + // + has = AddIfNotExists( + items[i], + sources // + ); + } + + // + int after = ArraySize(sources); + + // + result = after > before; + + // + return result; +} + +/** + * Update to Time of Specifiex Collection ... + * + * @param items: XOBFVG instance Collection ... + * @param value: datetime ... + */ +template +void SpecifiedUpdateTo( + T *&items[], + datetime value = NULL // +) +{ + // + value = NormalizeTime(value); + + // + int count = ArraySize(items); + bool has = HasChild(items); + if (!has) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + items[i].To(value); + } +} + +// +template +int FilterZones( + // + T *&source[], + // + ENUM_X_DIRECTION forDir, + ENUM_TIMEFRAMES forPeriod = NULL, + datetime after = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false, + // + bool applySort = false, + // + bool ignoreInside = true + // +) +{ + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + has = HasDirection(forDir); + if (!has) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + count = ArraySize(source); + has = IsValidSize(count); + if (!has) + { + return result; + } + + // + T *tmpZones[]; + XOHCL passedBar; + bool isPassed = false; + for (int i = 0; i < count; i++) + { + // + T *iZone = source[i]; + + // + // Apply after Filter ... + isPassed = + !IsValid(after) + ? true + : iZone.From() >= after; + if (!isPassed) + { + // + ZeroMemory(iZone); + continue; + } + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + forDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + forDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + forDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + forDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + tmpZones // + ); + if (has) + { + // + ZeroMemory(iZone); + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + tmpZones // + ); + } + + // + Clean(source); + + // + has = HasChild(tmpZones); + if (!has) + { + // + Clean(tmpZones); + passedBar.Clean(); + return result; + } + + // + // Apply Sorting ... + if (applySort) + { + // + T *last = NULL; + bool hasLast = false; + while (HasChild(tmpZones)) + { + // + idx = GetYoungest(tmpZones); + hasLast = IsValidIndex(idx); + if (hasLast) + { + // + last = tmpZones[idx]; + ArrayRemove( + tmpZones, + idx, + 1 // + ); + + // + Add( + last, + source // + ); + } + + // + has = HasChild(tmpZones); + if (!has) + { + break; + } + + // + T *zone = NULL; + bool hasZone = false; + idx = GetYoungest(tmpZones); + hasZone = IsValidIndex(idx); + if (hasZone) + { + // + zone = tmpZones[idx]; + ArrayRemove( + tmpZones, + idx, + 1 // + ); + } + if (!hasZone) + { + // + ZeroMemory(zone); + continue; + } + + // + bool isAbove = IsAbove( + zone, + last, + ignoreInside // + ); + + // + bool isBelow = IsBelow( + zone, + last, + ignoreInside // + ); + + // + isPassed = + isBullish + ? isAbove + : isBelow; + if (!isPassed) + { + // + ZeroMemory(zone); + continue; + } + + // + Add( + zone, + source // + ); + } + } + else + { + // + Copy( + tmpZones, + source // + ); + } + + // + result = ArraySize(source); + + // + return result; +} + +// +// +// + +/** + * Detect Nearest Price Out of Specified Box ... + * + * @param box: XBoxZone instance Reference ... + * @param outSideBar: XOHCL instance Reference which Represents Out Side Bar if Exists ... + * @param forPeriod: ENUM_TIMEFRAMES member which provides time frame of Out Bar, if not Provides used box Period as Default ... + * @param forDir: ENUM_X_DIRECTION member which Specified outSide Direction, use Box Dir as Default ... + * @param forceBodyIn: bool value which Specifyed Body Breakes or not, Default is false ... + * @param barIndex: integer value which Specified Start Bar Index, Default is 0 ... + * + * @return ( bool ) + */ +bool DetectBoxNearestPriceOut( + XBoxZone &box, + XOHCL &outSideBar, + ENUM_TIMEFRAMES forPeriod = NULL, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + bool forceBodyIn = false, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + outSideBar.Clean(); + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + result = box.IsValid(); + if (!result) + { + return result; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = box.period; + } + + // + if (!HasDirection(forDir)) + { + forDir = box.dir; + } + + // + bool isBullish = IsBullish(forDir); + + // + int fromIndex = iBarShift( + box.symbol, + forPeriod, + box.from // + ); + result = IsValidIndex(fromIndex); + if (!result) + { + return result; + } + + // + XOHCL iBar; + XOHCL iPBar; + bool has = false; + for (int i = barIndex; i < fromIndex; i++) + { + // + has = iBar.Init( + box.symbol, + forPeriod, + i // + ); + if (!has) + { + continue; + } + + // + has = iBar.GetPreviousBar(iPBar); + if (!has) + { + continue; + } + + // + bool isInsideFromLower = + iBar.high < box.lower && + iPBar.high > box.lower; + + // + bool isInsideFromUpper = + iBar.low > box.upper && + iPBar.low < box.upper; + + // + bool isInsideBodyFromLower = + iPBar.GetUp() > box.lower; + + // + bool isInsideBodyFromUpper = + iPBar.GetDown() < box.upper; + + // + result = + isBullish + ? (!forceBodyIn + ? isInsideFromLower + : isInsideFromLower && + isInsideBodyFromLower) + : (!forceBodyIn + ? isInsideFromUpper + : isInsideFromUpper && + isInsideBodyFromUpper); + if (result) + { + // + outSideBar = iBar; + break; + } + } + + // + iBar.Clean(); + iPBar.Clean(); + + // + return result; +} + +/** + * Count number of Box Retests ... + * + * @param box: XBoxZone instance Reference ... + * @param forDir: ENUM_X_DIRECTION member, Specified Retesting Direction ... + * @param forPeriod: ENUM_TIMEFRAMES member, Specified Retesting Period ... + * @param forceType: bool, Specified Retest Bar Direction is Same as Retesting Direction ... + * @param forcePressure: bool, Specified Retest Bar must Has Fibo Pressure or not ... + * + * @return ( int ) + */ +int CountBoxRetest( + XBoxZone &box, + ENUM_X_DIRECTION forDir = NULL, + ENUM_TIMEFRAMES forPeriod = NULL, + bool forceType = false, + bool forcePressure = false // +) +{ + // + int result = 0; + + // + if (!IsValid(forPeriod)) + { + forPeriod = box.period; + } + + // + if (!IsValid(forDir)) + { + forDir = box.dir; + } + + // + bool isValid = + box.IsValid() && + IsValid(forDir); + if (!isValid) + { + return result; + } + + // + int fromIDX = GetBarIndex( + box.symbol, + forPeriod, + box.from // + ); + + // + int toIDX = GetBarIndex( + box.symbol, + forPeriod, + box.to // + ); + + // + for (int i = fromIDX; i >= toIDX; i--) + { + // + // Initialize Indexed Bar ... + XOHCL iBar; + isValid = iBar.Init( + box.symbol, + forPeriod, + i // + ); + if (!isValid) + { + // + iBar.Clean(); + continue; + } + + // + bool isUpperBullishRejected = iBar.IsRejected( + box.upper, + X_DIRECTION_BULLISH, + forceType, + forcePressure // + ); + bool isUpperBearishRejected = iBar.IsRejected( + box.upper, + X_DIRECTION_BEARISH, + forceType, + forcePressure // + ); + + // + bool isLowerBullishRejected = iBar.IsRejected( + box.lower, + X_DIRECTION_BULLISH, + forceType, + forcePressure // + ); + bool isLowerBearishRejected = iBar.IsRejected( + box.lower, + X_DIRECTION_BEARISH, + forceType, + forcePressure // + ); + + // + if (forDir == X_DIRECTION_ALL || + forDir == X_DIRECTION_BULLISH) + { + // + if (isUpperBullishRejected || + isLowerBullishRejected) + { + result++; + } + } + + // + if (forDir == X_DIRECTION_ALL || + forDir == X_DIRECTION_BEARISH) + { + // + if (isUpperBearishRejected || + isLowerBearishRejected) + { + result++; + } + } + + // + iBar.Clean(); + } + + // + return result; +} + +// \ No newline at end of file diff --git a/BKPS/14040316/Libraries/x-saherelm.x-poi.lib.mq5 b/BKPS/14040316/Libraries/x-saherelm.x-poi.lib.mq5 new file mode 100644 index 0000000..207c81a --- /dev/null +++ b/BKPS/14040316/Libraries/x-saherelm.x-poi.lib.mq5 @@ -0,0 +1,6083 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Seriallize Library +// --------------------------------------- +// Name: XPOILib +// Description: All models related to POIs ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright `023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.base.class.mq5" +#include + +// +// Definitions ... + +// +// All Available POI(s) ... +enum ENUM_XPOIS +{ + // + X_POI_NONE, + // + X_POI_TICKS_ZONES, // Ticks Zone ... + // + // Trading Day ... + X_POI_TRADING_DAY, // Trading Day ... + // + // Market Session ... + X_POI_MARKET_SESSION, // Market Session ... + // + // Momentum Bar ... + X_POI_MOMENTUM_BAR, // Momentum Bar ... + // + // Rejection Bar ... + X_POI_REJECTION_BAR, // Rejection Bar ... + // + // Swings ... + X_POI_SWING_HIGH, // Simple Swing High ... + X_POI_SWING_LOW, // Simple Swing Low ... + // + // Support nad Resistance ... + X_POI_SUPPORT_ZONE, // Support Zone ... + X_POI_RESISTANCE_ZONE, // Resistance Zone ... + // + // Supply and Demand Zones ... + X_POI_SUPPLY_ZONE, // Supply Zone ... + X_POI_DEMAND_ZONE, // Demand Zone ... + // + // Order Blocks ... + X_POI_BULLISH_ORDERBLOCK, // Bullish Order Block ... + X_POI_BEARISH_ORDERBLOCK, // Bearish Order Block ... + // + // Fair Value Gaps ... + X_POI_BULLISH_FVG, // Bullish Order Block ... + X_POI_BEARISH_FVG, // Bearish Order Block ... + // + X_BULLISH_CONSOLIDATION_ZONE, + X_BEARISH_CONSOLIDATION_ZONE, + // + X_BULLISH_SHARP, + X_BEARISH_SHARP, + // + X_BULLISH_SPIKE, + X_BEARISH_SPIKE, + // + X_BULLISH_PULLBACK, + X_BEARISH_PULLBACK, +}; + +// +// Event Types ... +enum ENUM_XPOI_EVENTS +{ + // + X_POI_EVENT_NONE, + // + // Trading Days ... + X_TRADE_DAY_FIRST_BAR, // Trading Day First Bar ... + X_TRADE_DAY_LAST_BAR, // Trading Day Last Bar ... + // + // Session ... + X_SESSION_FIRST_BAR, // Session First Bar ... + X_SESSION_LAST_BAR, // Session Last Bar ... + // + // Momentum Bar ... + X_BULLISH_MOMENTUM_BAR_DETECTED, + X_BEARISH_MOMENTUM_BAR_DETECTED, + // + // Rejection Bar ... + X_BULLISH_REJECTION_BAR_DETECTED, + X_BEARISH_REJECTION_BAR_DETECTED, + // + // Swings ... + X_SWING_HIGH_DETECTED, + X_SWING_LOW_DETECTED, + // + // Support nad Resistance ... + X_SUPPORT_ZONE_DETECTED, // Support Zone ... + X_RESISTANCE_ZONE_DETECTED, // Resistance Zone ... + // + // Supply nad Demand ... + X_SUPPLY_ZONE_DETECTED, // Supply Zone ... + X_DEMAND_ZONE_DETECTED, // Demand Zone ... + // + // Order Blocks ... + X_BULLISH_ORDERBLOCK_DETECTED, // Bullish Order Block ... + X_BEARISH_ORDERBLOCK_DETECTED, // Bearish Order Block ... + // + // Fair Value Gaps ... + X_BULLISH_FVG_DETECTED, // Bullish Fair Value GapÙ‘ ... + X_BEARISH_FVG_DETECTED, // Bearish Fair Value GapÙ‘ ... + X_BULLISH_CONSOLIDATION_ZONE_DETECTED, + X_BEARISH_CONSOLIDATION_ZONE_DETECTED, + X_BULLISH_SHARP_DETECTED, + X_BEARISH_SHARP_DETECTED, + X_BULLISH_SPIKE_DETECTED, + X_BEARISH_SPIKE_DETECTED, + X_BULLISH_PULLBACK_DETECTED, + X_BEARISH_PULLBACK_DETECTED, +}; + +// +enum ENUM_XZONE_STATE +{ + XZONE_STATE_NONE, + XZONE_STATE_PASSED, + XZONE_STATE_FAILED, + XZONE_STATE_IGNORED, +}; + +// +// Forext Sessions ... +enum ENUM_XSESSION +{ + X_TOKYO, + X_SYDNEY, + X_LONDON, + X_NEW_YORK, + X_FRANKFORT, +}; + +/** + * Converts ENUM_XPOI value to String Representation ... + * + * @param value: ENUM_XPOI member ... + * + * @return ( string ) + */ +string ToString(ENUM_XPOIS value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_POI_TRADING_DAY: + result = "XTDAY"; + break; + + // + case X_POI_MARKET_SESSION: + result = "XMSESS"; + break; + + // + case X_POI_MOMENTUM_BAR: + result = "XMNTMB"; + break; + + // + case X_POI_REJECTION_BAR: + result = "XRJCTB"; + break; + + // + case X_POI_SWING_HIGH: + result = "XSPH"; + break; + + // + case X_POI_SWING_LOW: + result = "XSPL"; + break; + + // + case X_POI_SUPPORT_ZONE: + result = "XSUP"; + break; + + // + case X_POI_RESISTANCE_ZONE: + result = "XRES"; + break; + + // + case X_POI_SUPPLY_ZONE: + result = "XSUPPLY"; + break; + + // + case X_POI_DEMAND_ZONE: + result = "XDEMAND"; + break; + + // + case X_POI_BULLISH_ORDERBLOCK: + result = "XBULLOB"; + break; + + // + case X_POI_BEARISH_ORDERBLOCK: + result = "XBEAROB"; + break; + + // + case X_POI_BULLISH_FVG: + result = "XBULLFVG"; + break; + + // + case X_POI_BEARISH_FVG: + result = "XBEARFVG"; + break; + + // + case X_POI_TICKS_ZONES: + result = "XTKSZ"; + break; + + // + case X_BULLISH_CONSOLIDATION_ZONE: + result = "XBULLCZ"; + break; + + // + case X_BEARISH_CONSOLIDATION_ZONE: + result = "XBEARCZ"; + break; + + // + case X_BULLISH_SPIKE: + result = "XBULLSPK"; + break; + + // + case X_BEARISH_SPIKE: + result = "XBEARSPK"; + break; + } + + // + return result; +} + +/** + * Converts ENUM_XSESSION value to String Representation ... + * + * @param value: ENUM_XSESSION member ... + * + * @return ( string ) + */ +string ToString(ENUM_XSESSION value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_SYDNEY: + result = "Sydney"; + break; + + // + case X_TOKYO: + result = "Tokyo"; + break; + + // + case X_FRANKFORT: + result = "FrankGurt"; + break; + + // + case X_LONDON: + result = "London"; + break; + + // + case X_NEW_YORK: + result = "NewYork"; + break; + } + + // + return result; +} + +/** + * Generate General Event Messages ... + * + * @param value: ENUM_XPOI_EVENTS member ... + * + * @return ( string ) + */ +string ToString(ENUM_XPOI_EVENTS value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_TRADE_DAY_FIRST_BAR: + result = "First Bar of Day"; + break; + + // + case X_TRADE_DAY_LAST_BAR: + result = "Last Bar of Day"; + break; + + // + case X_SESSION_FIRST_BAR: + result = "First Bar of Session"; + break; + + // + case X_SESSION_LAST_BAR: + result = "Last Bar of Session"; + break; + + // + case X_BULLISH_MOMENTUM_BAR_DETECTED: + result = "Bullish Momentum Bar Detected"; + break; + + // + case X_BEARISH_MOMENTUM_BAR_DETECTED: + result = "Bearish Momentum Bar Detected"; + break; + + // + case X_BULLISH_REJECTION_BAR_DETECTED: + result = "Bullish Rejection Bar Detected"; + break; + + // + case X_BEARISH_REJECTION_BAR_DETECTED: + result = "Bearish Rejection Bar Detected"; + break; + + // + case X_SWING_HIGH_DETECTED: + result = "Swing High Detected"; + break; + + // + case X_SWING_LOW_DETECTED: + result = "Swing Low Detected"; + break; + + // + case X_SUPPORT_ZONE_DETECTED: + result = "Support Zone Detected"; + break; + + // + case X_RESISTANCE_ZONE_DETECTED: + result = "Resistance Zone Detected"; + break; + + // + case X_SUPPLY_ZONE_DETECTED: + result = "Supply Zone Detected"; + break; + + // + case X_DEMAND_ZONE_DETECTED: + result = "Demand Zone Detected"; + break; + + // + case X_BULLISH_ORDERBLOCK_DETECTED: + result = "Bullish Order Block Detected"; + break; + + // + case X_BEARISH_ORDERBLOCK_DETECTED: + result = "Bearish Orer Block Detected"; + break; + + // + case X_BULLISH_FVG_DETECTED: + result = "Bullish FVG Detected"; + break; + + // + case X_BEARISH_FVG_DETECTED: + result = "Bearish FVg Detected"; + break; + } + + // + return result; +} + +// +// Implementation ... + +// +// Base POI Model Class ... +class XCBasePOI : public XCBase +{ + // + public: + // + + // + // Constructor ... + void XCBasePOI() + { + // + Clean(); + + // + mSep = "_"; + mLineSep = "\n"; + } + + // + // Deconstructor ... + void ~XCBasePOI() + { + Clean(); + } + + // + // Virtual ... + + /** + * Cleanup ... + */ + virtual void Clean() + { + mType = X_POI_NONE; + } + + /** + * Validate ... + * + * @return ( virtual bool ) + */ + virtual bool IsValid() + { + return false; + } + + /** + * Retrieve POI Type ... + * + * @return ( virtual ENUM_XPOIS member ) + */ + virtual ENUM_XPOIS Type() + { + return mType; + } + + /** + * Retrieve POI Type ... + * + * @return ( virtual string ) + */ + virtual string TypeAsString() + { + return ToString(mType); + } + + /** + * Retrieve POI Tag ... + * + * @return ( virtual string ) + */ + virtual string GetTag() + { + return NULL; + } + + /** + * Retrieve POI Tooltip ... + * + * @return ( virtual string ) + */ + virtual string GetTooltip() + { + return NULL; + } + + // + protected: + // + // Props ... + string mSep; // Separator ... + string mLineSep; // Line Separator ... + ENUM_XPOIS mType; // Type ... + + // + private: + // +}; + +// +typedef void (*TOnPOIEvent)(ENUM_XPOI_EVENTS event, + XCBasePOI *param // +); + +// +// Zone POI Class ... +class XCZone : public XCBasePOI +{ + // + public: + // + + // + // Constructor ... + void XCZone() + { + } + + // + // Deconstructor ... + void ~XCZone() + { + } + + // + // Tools ... + + // + // Getter(s) / Setter(s) ... + + /** + * Get Zone Upper Boundary ... + * + * @return ( double ) + */ + double Upper() + { + return mUpper; + } + + /** + * Set Zone Upper Boundary ... + */ + void Upper(double value) + { + mUpper = value; + } + + /** + * Get Zone Lower Boundary ... + * + * @return ( double ) + */ + double Lower() + { + return mLower; + } + + /** + * Set Zone Lower Boundary ... + */ + void Lower(double value) + { + mLower = value; + } + + /** + * Retrieve Zone Range ... + * + * @return ( double ) + */ + double Range() + { + // + double result = 0; + + // + double upper = Upper(); + double lower = Lower(); + + // + if (upper > 0 && lower > 0 && upper > lower) + { + result = upper - lower; + } + + // + return result; + } + + double RangePercent() + { + // + double result = 0; + + // + double range = Range(); + if (range > 0) + { + result = range / 100; + } + + // + return result; + } + + // + // Virtuals ... + + /** + * Get Zone Start Date ... + * + * @return ( virtual datetime ) + */ + virtual datetime From() + { + return NULL; + } + + /** + * Get Zone End Date ... + * + * @return ( virtual datetime ) + */ + virtual datetime To() + { + return NULL; + } + + // + // Getter(s) / Setter(s) ... + + // + // Overrides ... + + // + // Validators ... + + /** + * Validate Upper and Lower of Zone ... + * + * @return ( bool ) + */ + bool IsValidBoundary() + { + // + bool result = false; + + // + result = + // + mUpper > 0 && + mLower > 0 && + mUpper >= mLower + // + ; + + // + return result; + } + + /** + * Check From Date of Zone is Valid ... + * + * @return ( bool ) + */ + bool IsValidFrom() + { + // + bool result = false; + + // + datetime from = From(); + result = IsSpecifiedValid(from); + + // + return result; + } + + // + protected: + // + // Props ... + double mUpper; // Zone Upper ... + double mLower; // Zone Lower ... + + // + private: + // + // Props ... + + // +}; + +// +// From To Zone ... +class XCFromToZone : public XCBasePOI +{ + // + public: + // + + // + // Constructor ... + void XCFromToZone() + { + } + + // + // Deconstructor ... + void ~XCFromToZone() + { + } + + // + // Tools ... + + bool InitFromTo( + ENUM_XPOIS type, + string title, + datetime from // + ) + { + // + bool result = false; + + // + result = type != X_POI_NONE && + IsSpecifiedValid(from) && + IsSpecifiedValid(title); + + // + mType = type; + mFrom = from; + mTitle = title; + mTo = TimeCurrent(); + + // + result = IsValid(); + + // + return result; + } + + bool InitFromTo( + ENUM_XPOIS type, + string title, + datetime from, + datetime to // + ) + { + // + bool result = false; + + // + result = IsValid(); + + // + result = InitFromTo( + type, + title, + from // + ); + if (!result) + { + return result; + } + + // + to = NormalizeTime(to); + mTo = to; + + // + result = IsValid(); + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Get Zone Start Time ... + * + * @return ( datetime ) + */ + datetime From() + { + return mFrom; + } + + /** + * Set Zone Start Time ... + * + * @param value: Datetime + */ + void From(datetime value) + { + // + value = NormalizeTime(value); + + // + mFrom = value; + } + + /** + * Get Zone End Time ... + * + * @return ( datetime ) + */ + datetime To() + { + return mTo; + } + + /** + * Set Zone End Time ... + * + * @param value: Datetime + */ + void To(datetime value) + { + // + value = NormalizeTime(value); + + // + mTo = value; + } + + /** + * Get Title ... + * + * @return ( string ) + */ + string Title() + { + return mTitle; + } + + /** + * Set Title ... + * + * @param value: String ... + */ + // void Title(string value) + // { + // mTitle = value; + // } + + // + // Overrides ... + + void Clean() override + { + // + mTo = NULL; + mFrom = NULL; + mType = X_POI_NONE; + } + + bool IsValid() override + { + // + bool result = false; + + // + result = + // + mType != X_POI_NONE && + IsSpecifiedValid(mTo) && + IsSpecifiedValid(mFrom) && + IsSpecifiedValid(mTitle) + // + ; + + // + return result; + } + + string GetTag() override + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + string hash = TypeAsString() + mSep + ToString(From()) + mSep + Title(); + hash = ToMD5(hash); + + // + result = TypeAsString() + "[" + Title() + "]" + mSep + hash; + + // + return result; + } + + // + protected: + // + + // + private: + // + // Props ... + datetime mFrom; // Start Date + datetime mTo; // End Date + string mTitle; // Zone Title + + // +}; + +// +// Bar Zone ... +class XCBarZone : public XCZone +{ + // + public: + // + + // + // Constructor ... + void XCBarZone() + { + } + + // + // Deconstructor ... + void ~XCBarZone() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param bar: XOHCL instance ... + * @param type: ENUM_XPOIS member ... + * @param upperPrice: ENUM_X_PRICE member ... + * @param lowerPrice: ENUM_X_PRICE member ... + * + * @return ( bool ) + */ + bool InitBarZone( + XOHCL &bar, + ENUM_XPOIS type, + ENUM_X_PRICE upperPrice, + ENUM_X_PRICE lowerPrice // + ) + { + // + bool result = false; + + // + result = bar.IsValid() && + type != X_POI_NONE && + upperPrice != lowerPrice; + if (!result) + { + return result; + } + + // + mBar = bar; + mType = type; + mUpperPrice = upperPrice; + mLowerPrice = lowerPrice; + mUpper = bar.GetPrice(upperPrice); + mLower = bar.GetPrice(lowerPrice); + + // + result = IsValidBarZone(); + if (result) + { + // + From(bar.time); + To(TimeCurrent()); + } + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Fill Bar as XOHCL struct ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool FillBar( + XOHCL &bar // + ) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + bar = mBar; + result = mBar.IsValid(); + + // + return result; + } + + /** + * Set From Date ... + * + * @param value: DateTime ... + */ + void From(datetime value) + { + // + if (!IsValidBarZone()) + { + return; + } + + // + value = NormalizeTime(value); + + // + mFrom = value; + } + + /** + * Set To Date ... + * + * @param value: DateTime ... + */ + void To(datetime value) + { + // + if (!IsValidBarZone()) + { + return; + } + + // + value = NormalizeTime(value); + + // + mTo = value; + } + + /** + * Retrieve Bar Time ... + * + * @return ( datetime ) + */ + datetime BarTime() + { + return mBar.time; + } + + /** + * Get Symbol ... + * + * @return ( string ) + */ + string GetSymbol() + { + // + string result = NULL; + + // + if (!mBar.IsValid()) + { + return result; + } + + // + return mBar.symbol; + + // + return result; + } + + /** + * Get Period ... + * + * @return ( int ) + */ + ENUM_TIMEFRAMES GetPeriod() + { + // + ENUM_TIMEFRAMES result = NULL; + + // + if (!mBar.IsValid()) + { + return result; + } + + // + return mBar.period; + + // + return result; + } + + /** + * Check Zone Started or not ... + * First Exit in Direction of Zone after From ... + * + * @param forDir: exit direction ... + * @param startedBar: specified Start Bar ... + * @param isBodyOut: specified Start Bar Close is Out of Zone or not ... + * @param forPeriod: specified Period ... + * + * @return ( bool ) + */ + bool IsStarted( + ENUM_X_DIRECTION forDir, + XOHCL &startedBar, + bool &isBodyOut, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + isBodyOut = false; + startedBar.Clean(); + + // + result = HasDirection(forDir) && + IsValidBarZone(); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + // Detect From Bar Index ... + int fromIndex = iBarShift( + GetSymbol(), + forPeriod, + From() // + ); + + // + for (int i = fromIndex; i >= 0; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + result = isInited; + if (!result) + { + // + iBar.Clean(); + continue; + } + + // + bool isBreakedFromUpper = + // + iBar.low > Upper() || + (iBar.low <= Upper() && + iBar.high > Upper() && + iBar.close > Upper()) + // + ; + + // + bool isBreakedFromLower = + // + iBar.low < Lower() || + (iBar.high >= Lower() && + iBar.low < Lower() && + iBar.close < Lower()) + // + ; + + // + bool isBreaked = + isBreakedFromUpper || + isBreakedFromLower; + if (isBreaked) + { + // + result = isBreaked && + isBullish + ? isBreakedFromUpper + : isBreakedFromLower; + if (result) + { + // + startedBar = iBar; + iBar.Clean(); + break; + } + } + + // + iBar.Clean(); + } + + // + result = startedBar.IsValid(); + if (result) + { + // + isBodyOut = + isBullish + ? startedBar.IsBullish() && + startedBar.GetUp() > Upper() + : startedBar.IsBearish() && + startedBar.GetDown() < Lower(); + } + + // + return result; + } + + /** + * Check Zone Activated or not ... + * First Enter in Opposit Direction of Zone after Start ... + * + * @param forDir: exit direction ... + * @param activatedBar: specified Activation Bar ... + * @param isBodyIn: specified Activation Bar Close is Inside of Zone or not ... + * @param forPeriod: specified Period ... + * + * @return ( bool ) + */ + bool IsActivated( + ENUM_X_DIRECTION forDir, + XOHCL &activatedBar, + bool &isBodyIn, + bool forceBodyOutStarted = true, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + isBodyIn = false; + activatedBar.Clean(); + + // + result = HasDirection(forDir) && + IsValidBarZone(); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + XOHCL startedBar; + bool isBodyOut = false; + bool isStarted = IsStarted( + forDir, + startedBar, + isBodyOut, + forPeriod // + ); + result = + !forceBodyOutStarted + ? isStarted + : isStarted && + isBodyOut; + if (!result) + { + // + startedBar.Clean(); + return result; + } + + // + int fromIndex = startedBar.Index() - 1; + + // + for (int i = fromIndex; i >= 0; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + result = isInited; + if (!result) + { + // + iBar.Clean(); + continue; + } + + // + bool isInsideFromUpper = + // + iBar.high < Upper() || + (iBar.high > Upper() && + iBar.low <= Upper() && + iBar.close <= Upper()) + // + ; + + // + bool isInsideFromLower = + // + iBar.low > Lower() || + (iBar.low < Lower() && + iBar.high >= Lower() && + iBar.close >= Lower()) + // + ; + + // + bool isInside = + isInsideFromUpper || + isInsideFromLower; + if (isInside) + { + // + result = isInside && + isBullish + ? isInsideFromUpper + : isInsideFromLower; + if (result) + { + // + activatedBar = iBar; + iBar.Clean(); + startedBar.Clean(); + break; + } + } + + // + iBar.Clean(); + startedBar.Clean(); + } + + // + result = activatedBar.IsValid(); + if (result) + { + // + isBodyIn = + isBullish + ? activatedBar.IsBearish() && + activatedBar.GetDown() < Upper() + : activatedBar.IsBullish() && + activatedBar.GetUp() > Lower(); + } + + // + return result; + } + + /** + * Check Zone Breaked or not ... + * + * @param forDir: exit direction ... + * @param breakedBar: specified Breaked Bar ... + * @param isBodyOut: specified Breaked Bar Close is Out of Zone or not ... + * @param ignoreStart: Ignore Zone Start (Calculate from From()) ... + * @param startedBodyOut: Started Bar Body Close State, if use Start for Calculation ... + * @param forPeriod: specified Period ... + * + * @return ( bool ) + */ + bool IsBreaked( + ENUM_X_DIRECTION forDir, + XOHCL &breakedBar, + bool &isBodyOut, + bool ignoreStart = false, + bool startedBodyOut = false, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + isBodyOut = false; + breakedBar.Clean(); + + // + result = HasDirection(forDir) && + IsValidBarZone(); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + int fromIndex = -1; + if (!ignoreStart) + { + // + XOHCL startedBar; + bool isBodyOut = false; + bool isStarted = IsStarted( + forDir, + startedBar, + isBodyOut, + forPeriod // + ); + + // + bool isStartPassed = + !startedBodyOut + ? isStarted + : isStarted && + isBodyOut; + if (isStartPassed) + { + fromIndex = startedBar.Index() - 1; + } + + // + startedBar.Clean(); + } + else + { + // + fromIndex = iBarShift( + GetSymbol(), + forPeriod, + From() // + ); + } + + // + result = IsValidIndex(fromIndex); + if (!result) + { + return result; + } + + // + for (int i = fromIndex; i >= 0; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + result = isInited; + if (!result) + { + // + iBar.Clean(); + continue; + } + + // + bool isBreakedFromUpper = + // + iBar.low > Upper() || + (iBar.low <= Upper() && + iBar.high > Upper() && + iBar.close > Upper()) + // + ; + + // + bool isBreakedFromLower = + // + iBar.low < Lower() || + (iBar.high >= Lower() && + iBar.low < Lower() && + iBar.close < Lower()) + // + ; + + // + bool isBreaked = + isBreakedFromUpper || + isBreakedFromLower; + if (isBreaked) + { + // + result = isBreaked && + (isBullish + ? isBreakedFromLower + : isBreakedFromUpper); + if (result) + { + // + breakedBar = iBar; + iBar.Clean(); + break; + } + } + + // + iBar.Clean(); + } + + // + result = breakedBar.IsValid(); + if (result) + { + // + isBodyOut = + isBullish + ? breakedBar.IsBearish() && + breakedBar.GetDown() < Lower() + : breakedBar.IsBullish() && + breakedBar.GetUp() > Upper(); + } + + // + return result; + } + + /** + * Check Zone Worked or not ... + * + * @param forDir: exit direction ... + * @param workedBar: specified Worked Bar ... + * @param isBodyOut: specified Worked Bar Close is Out of Zone or not ... + * @param ignoreActivation: Ignore Zone Activation (Calculate from From()) ... + * @param activationStartedOut: Specified Zone Start Bar State ... + * @param activationBodyIn: Specified Zone Activation Bar State ... + * @param forPeriod: specified Period ... + * + * @return ( bool ) + */ + bool IsWorked( + ENUM_X_DIRECTION forDir, + XOHCL &workedBar, + bool &isBodyOut, + bool ignoreActivation = false, + bool activationStartedOut = false, + bool activationBodyIn = false, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + isBodyOut = false; + workedBar.Clean(); + + // + result = HasDirection(forDir) && + IsValidBarZone(); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + int fromIndex = -1; + if (!ignoreActivation) + { + // + XOHCL activatedBar; + bool isBodyIn = false; + bool isActivated = IsActivated( + forDir, + activatedBar, + isBodyIn, + activationStartedOut, + forPeriod // + ); + + // + bool isActivationPassed = + !activationBodyIn + ? isActivated + : isActivated && + isBodyIn; + if (isActivationPassed) + { + fromIndex = activatedBar.Index() - 1; + } + + // + activatedBar.Clean(); + } + else + { + // + fromIndex = iBarShift( + GetSymbol(), + forPeriod, + From() // + ); + } + + // + result = IsValidIndex(fromIndex); + if (!result) + { + return result; + } + + // + for (int i = fromIndex; i >= 0; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + result = isInited; + if (!result) + { + // + iBar.Clean(); + continue; + } + + // + bool isBreakedFromUpper = + // + iBar.low > Upper() || + (iBar.low <= Upper() && + iBar.high > Upper() && + iBar.close > Upper()) + // + ; + + // + bool isBreakedFromLower = + // + iBar.low < Lower() || + (iBar.high >= Lower() && + iBar.low < Lower() && + iBar.close < Lower()) + // + ; + + // + bool isBreaked = + isBreakedFromUpper || + isBreakedFromLower; + if (isBreaked) + { + // + result = isBreaked && + isBullish + ? isBreakedFromUpper + : isBreakedFromLower; + if (result) + { + // + workedBar = iBar; + iBar.Clean(); + break; + } + } + + // + iBar.Clean(); + } + + // + result = workedBar.IsValid(); + if (result) + { + // + isBodyOut = + isBullish + ? workedBar.IsBullish() && + workedBar.GetUp() > Upper() + : workedBar.IsBearish() && + workedBar.GetDown() < Lower(); + } + + // + return result; + } + + /** + * Check to Find Nearest Bar which Breakes Upper ... + * + * @param bar: XOHCL instance Reference, Breaker Bar ... + * @param forPeriod: ENUM_TIMEFRAMES member, Breaker Bar Detection Period, default is Zone Period ... + * + * @return ( bool ) + */ + bool FindNearestInsideBarFromUpper( + XOHCL &bar, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + bar.Clean(); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int from = 1; + int to = iBarShift( + GetSymbol(), + forPeriod, + From() // + ); + + // + for (int i = from; i < to; i++) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + if (!isInited) + { + break; + } + + // + bool isInside = iBar.low < Upper(); + if (isInside) + { + // + bar = iBar; + break; + } + } + + // + result = bar.IsValid(); + + // + return result; + } + + /** + * Check to Find Nearest Bar which Breakes Lower ... + * + * @param bar: XOHCL instance Reference, Breaker Bar ... + * @param forPeriod: ENUM_TIMEFRAMES member, Breaker Bar Detection Period, default is Zone Period ... + * + * @return ( bool ) + */ + bool FindNearestInsideBarFromLower( + XOHCL &bar, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + bar.Clean(); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int from = 1; + int to = iBarShift( + GetSymbol(), + forPeriod, + From() // + ); + + // + for (int i = from; i < to; i++) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + if (!isInited) + { + break; + } + + // + bool isInside = iBar.high > Lower(); + if (isInside) + { + // + bar = iBar; + break; + } + } + + // + result = bar.IsValid(); + + // + return result; + } + + // + // Overrides ... + + void Clean() override + { + // + mBar.Clean(); + mUpper = 0; + mLower = 0; + mType = X_POI_NONE; + } + + datetime From() override + { + return mFrom; + } + + datetime To() override + { + return mTo; + } + + string GetTag() override + { + // + string result = NULL; + + // + if (!IsValidBarZone()) + { + return result; + } + + // + string hash = ToMD5(mBar.GetTag()); + + // + result = + // + TypeAsString() + mSep + + ToString(mBar.period) + mSep + + hash + // + ; + + // + return result; + } + + string GetTooltip() override + { + // + string result = NULL; + + // + if (!IsValidBarZone()) + { + return result; + } + + // + return result; + } + + // + protected: + // + // Props ... + XOHCL mBar; // Bar ... + ENUM_X_PRICE mUpperPrice; // Upper Price Selection + ENUM_X_PRICE mLowerPrice; // Lower Price Selection + + /** + * Check Bar Zone Validation ... + * + * @return ( bool ) + */ + bool IsValidBarZone() + { + // + bool result = false; + + // + result = mBar.IsValid() && + mType != X_POI_NONE && + IsValidBoundary(); + + // + return result; + } + + // + private: + // + // Props ... + datetime mFrom; + datetime mTo; + + // +}; +class XCTwoBarZone : public XCZone +{ + // + public: + // + + // + // Constructor ... + void XCTwoBarZone() + { + } + + // + // Deconstructor ... + void ~XCTwoBarZone() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param bar: XOHCL instance ... + * @param type: ENUM_XPOIS member ... + * @param upperPrice: ENUM_X_PRICE member ... + * @param lowerPrice: ENUM_X_PRICE member ... + * + * @return ( bool ) + */ + bool InitTwoBarZone( + XOHCL &startBar, + XOHCL &endBar, + ENUM_XPOIS type, + ENUM_X_PRICE startPrice, + ENUM_X_PRICE endPrice // + ) + { + // + bool result = false; + + // + result = startBar.IsValid() && + endBar.IsValid() && + startBar.symbol == endBar.symbol && + startBar.period == endBar.period && + startBar.time < endBar.time && + type != X_POI_NONE; + if (!result) + { + return result; + } + + // + mType = type; + mEndBar = endBar; + mStartBar = startBar; + + // + int startIndex = startBar.Index(); + int endIndex = endBar.Index(); + + // + double mStartPrice = startBar.GetPrice(startPrice); + double mEndPrice = endBar.GetPrice(endPrice); + bool isStartOverEnd = mStartPrice > mEndPrice; + + // + if (isStartOverEnd) + { + // + mUpperPrice = startPrice; + mLowerPrice = endPrice; + } + else + { + // + mUpperPrice = endPrice; + mLowerPrice = startPrice; + } + + // + mUpper = MathMax(mStartPrice, mEndPrice); + mLower = MathMin(mStartPrice, mEndPrice); + + // + result = IsValidTwoBarZone(); + if (result) + { + // + From(startBar.time); + To(endBar.time); + } + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Set From Date ... + * + * @param value: DateTime ... + */ + void From(datetime value) + { + // + if (!IsValidTwoBarZone()) + { + return; + } + + // + value = NormalizeTime(value); + + // + mFrom = value; + } + + /** + * Set To Date ... + * + * @param value: DateTime ... + */ + void To(datetime value) + { + // + if (!IsValidTwoBarZone()) + { + return; + } + + // + value = NormalizeTime(value); + + // + mTo = value; + } + + /** + * Fill Start Bar ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool FillStartBar(XOHCL &bar) + { + // + bool result = false; + + // + result = IsValidTwoBarZone(); + if (!result) + { + return result; + } + + // + bar = mStartBar; + + // + return result; + } + + /** + * Fill End Bar ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool FillEndBar(XOHCL &bar) + { + // + bool result = false; + + // + result = IsValidTwoBarZone(); + if (!result) + { + return result; + } + + // + bar = mEndBar; + + // + return result; + } + + /** + * Get Symbol ... + * + * @return ( string ) + */ + string GetSymbol() + { + // + string result = NULL; + + // + if (!mStartBar.IsValid()) + { + return result; + } + + // + return mStartBar.symbol; + + // + return result; + } + + /** + * Get Period ... + * + * @return ( int ) + */ + ENUM_TIMEFRAMES GetPeriod() + { + // + ENUM_TIMEFRAMES result = NULL; + + // + if (!mStartBar.IsValid()) + { + return result; + } + + // + return mStartBar.period; + + // + return result; + } + + /** + * Check Zone Started or not ... + * First Exit in Direction of Zone after From ... + * + * @param forDir: exit direction ... + * @param startedBar: specified Start Bar ... + * @param isBodyOut: specified Start Bar Close is Out of Zone or not ... + * @param forPeriod: specified Period ... + * + * @return ( bool ) + */ + bool IsStarted( + ENUM_X_DIRECTION forDir, + XOHCL &startedBar, + bool &isBodyOut, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + isBodyOut = false; + startedBar.Clean(); + + // + result = HasDirection(forDir) && + IsValidTwoBarZone(); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + // Detect From Bar Index ... + int fromIndex = iBarShift( + GetSymbol(), + forPeriod, + From() // + ); + + // + for (int i = fromIndex; i >= 0; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + result = isInited; + if (!result) + { + // + iBar.Clean(); + continue; + } + + // + bool isBreakedFromUpper = + // + iBar.low > Upper() || + (iBar.low <= Upper() && + iBar.high > Upper() && + iBar.close > Upper()) + // + ; + + // + bool isBreakedFromLower = + // + iBar.low < Lower() || + (iBar.high >= Lower() && + iBar.low < Lower() && + iBar.close < Lower()) + // + ; + + // + bool isBreaked = + isBreakedFromUpper || + isBreakedFromLower; + if (isBreaked) + { + // + result = isBreaked && + isBullish + ? isBreakedFromUpper + : isBreakedFromLower; + if (result) + { + // + startedBar = iBar; + iBar.Clean(); + break; + } + } + + // + iBar.Clean(); + } + + // + result = startedBar.IsValid(); + if (result) + { + // + isBodyOut = + isBullish + ? startedBar.IsBullish() && + startedBar.GetUp() > Upper() + : startedBar.IsBearish() && + startedBar.GetDown() < Lower(); + } + + // + return result; + } + + /** + * Check Zone Activated or not ... + * First Enter in Opposit Direction of Zone after Start ... + * + * @param forDir: exit direction ... + * @param activatedBar: specified Activation Bar ... + * @param isBodyIn: specified Activation Bar Close is Inside of Zone or not ... + * @param forPeriod: specified Period ... + * + * @return ( bool ) + */ + bool IsActivated( + ENUM_X_DIRECTION forDir, + XOHCL &activatedBar, + bool &isBodyIn, + bool forceBodyOutStarted = true, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + isBodyIn = false; + activatedBar.Clean(); + + // + result = HasDirection(forDir) && + IsValidTwoBarZone(); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + XOHCL startedBar; + bool isBodyOut = false; + bool isStarted = IsStarted( + forDir, + startedBar, + isBodyOut, + forPeriod // + ); + result = + !forceBodyOutStarted + ? isStarted + : isStarted && + isBodyOut; + if (!result) + { + // + startedBar.Clean(); + return result; + } + + // + int fromIndex = startedBar.Index() - 1; + + // + for (int i = fromIndex; i >= 0; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + result = isInited; + if (!result) + { + // + iBar.Clean(); + continue; + } + + // + bool isInsideFromUpper = + // + iBar.high < Upper() || + (iBar.high > Upper() && + iBar.low <= Upper() && + iBar.close <= Upper()) + // + ; + + // + bool isInsideFromLower = + // + iBar.low > Lower() || + (iBar.low < Lower() && + iBar.high >= Lower() && + iBar.close >= Lower()) + // + ; + + // + bool isInside = + isInsideFromUpper || + isInsideFromLower; + if (isInside) + { + // + result = isInside && + isBullish + ? isInsideFromUpper + : isInsideFromLower; + if (result) + { + // + activatedBar = iBar; + iBar.Clean(); + startedBar.Clean(); + break; + } + } + + // + iBar.Clean(); + startedBar.Clean(); + } + + // + result = activatedBar.IsValid(); + if (result) + { + // + isBodyIn = + isBullish + ? activatedBar.IsBearish() && + activatedBar.GetDown() < Upper() + : activatedBar.IsBullish() && + activatedBar.GetUp() > Lower(); + } + + // + return result; + } + + /** + * Check Zone reaked or not ... + * + * @param forDir: exit direction ... + * @param breakedBar: specified Breaked Bar ... + * @param isBodyOut: specified Breaked Bar Close is Out of Zone or not ... + * @param ignoreStart: Ignore Zone Start (Calculate from From()) ... + * @param startedBodyOut: Started Bar Body Close State, if use Start for Calculation ... + * @param forPeriod: specified Period ... + * + * @return ( bool ) + */ + bool IsBreaked( + ENUM_X_DIRECTION forDir, + XOHCL &breakedBar, + bool &isBodyOut, + bool ignoreStart = false, + bool startedBodyOut = false, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + isBodyOut = false; + breakedBar.Clean(); + + // + result = HasDirection(forDir) && + IsValidTwoBarZone(); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + int fromIndex = -1; + if (!ignoreStart) + { + // + XOHCL startedBar; + bool isBodyOut = false; + bool isStarted = IsStarted( + forDir, + startedBar, + isBodyOut, + forPeriod // + ); + + // + bool isStartPassed = + !startedBodyOut + ? isStarted + : isStarted && + isBodyOut; + if (isStartPassed) + { + fromIndex = startedBar.Index() - 1; + } + + // + startedBar.Clean(); + } + else + { + // + fromIndex = iBarShift( + GetSymbol(), + forPeriod, + From() // + ); + } + + // + result = IsValidIndex(fromIndex); + if (!result) + { + return result; + } + + // + for (int i = fromIndex; i >= 0; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + result = isInited; + if (!result) + { + // + iBar.Clean(); + continue; + } + + // + bool isBreakedFromUpper = + // + iBar.low > Upper() || + (iBar.low <= Upper() && + iBar.high > Upper() && + iBar.close > Upper()) + // + ; + + // + bool isBreakedFromLower = + // + iBar.low < Lower() || + (iBar.high >= Lower() && + iBar.low < Lower() && + iBar.close < Lower()) + // + ; + + // + bool isBreaked = + isBreakedFromUpper || + isBreakedFromLower; + if (isBreaked) + { + // + result = isBreaked && + (isBullish + ? isBreakedFromLower + : isBreakedFromUpper); + if (result) + { + // + breakedBar = iBar; + iBar.Clean(); + break; + } + } + + // + iBar.Clean(); + } + + // + result = breakedBar.IsValid(); + if (result) + { + // + isBodyOut = + isBullish + ? breakedBar.IsBearish() && + breakedBar.GetDown() < Lower() + : breakedBar.IsBullish() && + breakedBar.GetUp() > Upper(); + } + + // + return result; + } + + /** + * Check Zone Worked or not ... + * + * @param forDir: exit direction ... + * @param workedBar: specified Worked Bar ... + * @param isBodyOut: specified Worked Bar Close is Out of Zone or not ... + * @param ignoreActivation: Ignore Zone Activation (Calculate from From()) ... + * @param activationStartedOut: Specified Zone Start Bar State ... + * @param activationBodyIn: Specified Zone Activation Bar State ... + * @param forPeriod: specified Period ... + * + * @return ( bool ) + */ + bool IsWorked( + ENUM_X_DIRECTION forDir, + XOHCL &workedBar, + bool &isBodyOut, + bool ignoreActivation = false, + bool activationStartedOut = false, + bool activationBodyIn = false, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + isBodyOut = false; + workedBar.Clean(); + + // + result = HasDirection(forDir) && + IsValidTwoBarZone(); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + int fromIndex = -1; + if (!ignoreActivation) + { + // + XOHCL activatedBar; + bool isBodyIn = false; + bool isActivated = IsActivated( + forDir, + activatedBar, + isBodyIn, + activationStartedOut, + forPeriod // + ); + + // + bool isActivationPassed = + !activationBodyIn + ? isActivated + : isActivated && + isBodyIn; + if (isActivationPassed) + { + fromIndex = activatedBar.Index() - 1; + } + + // + activatedBar.Clean(); + } + else + { + // + fromIndex = iBarShift( + GetSymbol(), + forPeriod, + From() // + ); + } + + // + result = IsValidIndex(fromIndex); + if (!result) + { + return result; + } + + // + for (int i = fromIndex; i >= 0; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + result = isInited; + if (!result) + { + // + iBar.Clean(); + continue; + } + + // + bool isBreakedFromUpper = + // + iBar.low > Upper() || + (iBar.low <= Upper() && + iBar.high > Upper() && + iBar.close > Upper()) + // + ; + + // + bool isBreakedFromLower = + // + iBar.low < Lower() || + (iBar.high >= Lower() && + iBar.low < Lower() && + iBar.close < Lower()) + // + ; + + // + bool isBreaked = + isBreakedFromUpper || + isBreakedFromLower; + if (isBreaked) + { + // + result = isBreaked && + isBullish + ? isBreakedFromUpper + : isBreakedFromLower; + if (result) + { + // + workedBar = iBar; + iBar.Clean(); + break; + } + } + + // + iBar.Clean(); + } + + // + result = workedBar.IsValid(); + if (result) + { + // + isBodyOut = + isBullish + ? workedBar.IsBullish() && + workedBar.GetUp() > Upper() + : workedBar.IsBearish() && + workedBar.GetDown() < Lower(); + } + + // + return result; + } + + /** + * Check to Find Nearest Bar which Breakes Upper ... + * + * @param bar: XOHCL instance Reference, Breaker Bar ... + * @param forPeriod: ENUM_TIMEFRAMES member, Breaker Bar Detection Period, default is Zone Period ... + * + * @return ( bool ) + */ + bool FindNearestInsideBarFromUpper( + XOHCL &bar, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + bar.Clean(); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int from = 1; + int to = iBarShift( + GetSymbol(), + forPeriod, + From() // + ); + + // + for (int i = from; i < to; i++) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + if (!isInited) + { + break; + } + + // + bool isInside = iBar.low < Upper(); + if (isInside) + { + // + bar = iBar; + break; + } + } + + // + result = bar.IsValid(); + + // + return result; + } + + /** + * Check to Find Nearest Bar which Breakes Lower ... + * + * @param bar: XOHCL instance Reference, Breaker Bar ... + * @param forPeriod: ENUM_TIMEFRAMES member, Breaker Bar Detection Period, default is Zone Period ... + * + * @return ( bool ) + */ + bool FindNearestInsideBarFromLower( + XOHCL &bar, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + bar.Clean(); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int from = 1; + int to = iBarShift( + GetSymbol(), + forPeriod, + From() // + ); + + // + for (int i = from; i < to; i++) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + if (!isInited) + { + break; + } + + // + bool isInside = iBar.high > Lower(); + if (isInside) + { + // + bar = iBar; + break; + } + } + + // + result = bar.IsValid(); + + // + return result; + } + + // + // Overrides ... + + void Clean() override + { + // + mStartBar.Clean(); + mEndBar.Clean(); + mUpper = 0; + mLower = 0; + mUseStartBarForUpper = false; + mType = X_POI_NONE; + } + + datetime From() override + { + return mFrom; + } + + datetime To() override + { + return mTo; + } + + string GetTag() override + { + // + string result = NULL; + + // + if (!IsValidTwoBarZone()) + { + return result; + } + + // + string hash = ToMD5(mStartBar.GetTag() + mSep + mEndBar.GetTag()); + + // + result = + // + TypeAsString() + mSep + + ToString(mStartBar.period) + mSep + + hash + // + ; + + // + return result; + } + + string GetTooltip() override + { + // + string result = NULL; + + // + if (!IsValidTwoBarZone()) + { + return result; + } + + // + return result; + } + + // + protected: + // + // Props ... + XOHCL mStartBar; // Start (Oldest) Bar ... + XOHCL mEndBar; // End (Newest) Bar ... + bool mUseStartBarForUpper; // Use Start Bar for Upper Calculation ... + ENUM_X_PRICE mUpperPrice; // Upper Price Selection + ENUM_X_PRICE mLowerPrice; // Lower Price Selection + + /** + * Check Two Bar Zone Validation ... + * + * @return ( bool ) + */ + bool IsValidTwoBarZone() + { + // + bool result = false; + + // + result = mStartBar.IsValid() && + mEndBar.IsValid() && + mStartBar.symbol == mEndBar.symbol && + mStartBar.period == mEndBar.period && + mStartBar.time < mEndBar.time && + mType != X_POI_NONE && + IsValidBoundary(); + + // + return result; + } + + // + private: + // + // Props ... + datetime mFrom; + datetime mTo; + + // +}; + +// +// Swing Class ... +class XCSwing : public XCBasePOI +{ + // + public: + // + + // + // Constructor ... + void XCSwing() + { + } + + // + // Deconstructor ... + void ~XCSwing() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param bar: XOHCL instance ... + * @param type: ENUM_XPOIS member ... + * + * @return ( bool ) + */ + bool Init( + XOHCL &bar, + ENUM_XPOIS type // + ) + { + // + bool result = false; + + // + result = bar.IsValid() && + (type == X_POI_SWING_HIGH || + type == X_POI_SWING_LOW); + if (!result) + { + return result; + } + + // + mBar = bar; + mType = type; + + // + result = IsValid(); + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Fill Bar as XOHCL struct ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool FillBar( + XOHCL &bar // + ) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + bar = mBar; + result = mBar.IsValid(); + + // + return result; + } + + /** + * Get Time of Swing ... + * + * @return ( datetime ) + */ + datetime GetTime() + { + // + datetime result = NULL; + + // + if (!IsValid() || !mBar.IsValid()) + { + return result; + } + + // + result = mBar.time; + + // + return result; + } + + ENUM_TIMEFRAMES GetPeriod() + { + // + ENUM_TIMEFRAMES result = NULL; + + // + XOHCL bar; + bool isFilled = FillBar(bar); + if (!isFilled) + { + return result; + } + + // + result = bar.period; + + // + return result; + } + + /** + * Check Swing High or not ... + * + * @return ( bool ) + */ + bool IsSwingHigh() + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + result = + Type() == X_POI_SWING_HIGH; + + // + return result; + } + + /** + * Check Swing Low or not ... + * + * @return ( bool ) + */ + bool IsSwingLow() + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + result = + Type() == X_POI_SWING_LOW; + + // + return result; + } + + /** + * Get Swing Value ... + * + * @return ( double ) + */ + double GetValue() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = + IsSwingHigh() + ? mBar.high + : mBar.low; + + // + return result; + } + + // + // Overrides ... + + void Clean() override + { + // + mBar.Clean(); + mType = X_POI_NONE; + } + + bool IsValid() override + { + // + bool result = false; + + // + result = mBar.IsValid() && + (mType == X_POI_SWING_HIGH || + mType == X_POI_SWING_LOW); + + // + return result; + } + + string GetTag() override + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + string hash = ToMD5(mBar.GetTag()); + + // + string subType = IsSwingHigh() + ? "High" + : "Low"; + + // + result = + // + TypeAsString() + mSep + + subType + mSep + + ToString(mBar.period) + mSep + + hash + // + ; + + // + return result; + } + + string GetTooltip() override + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + return result; + } + + // + protected: + // + // Props ... + XOHCL mBar; // Swing Bar ... + + // + private: + // +}; + +// +// Supply Zone ... +class XCSupplyZone : public XCBarZone +{ + // + public: + // + + // + // Constructor ... + void XCSupplyZone() + { + } + + // + // Deconstructor ... + void ~XCSupplyZone() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param bar: XOHCL instance ... + * @param range: Integer, Detection Range ... + * + * @return ( bool ) + */ + bool Init( + XOHCL &bar, + int range = 0, + bool useRangeAsStart = false // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + result = InitBarZone( + bar, + X_POI_SUPPLY_ZONE, + X_PRICE_HIGH, + X_PRICE_LOW // + ); + if (!result) + { + return result; + } + + // + result = IsValid(); + if (result && + range > 0) + { + // + datetime time = bar.time; + int periodSeconds = PeriodSeconds(bar.period); + + // + datetime from = + !useRangeAsStart + ? (datetime)((int)time - (range * periodSeconds)) + : time; + datetime to = (datetime)((int)time + (range * periodSeconds)); + + // + From(from); + To(to); + } + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + // + // Overrides ... + + bool IsValid() override + { + // + bool result = false; + + // + result = IsValidBarZone() && + mType == X_POI_SUPPLY_ZONE; + + // + return result; + } + + // + protected: + // + + // + private: + // + + // +}; + +// +// Demand Zone ... +class XCDemandZone : public XCBarZone +{ + // + public: + // + + // + // Constructor ... + void XCDemandZone() + { + } + + // + // Deconstructor ... + void ~XCDemandZone() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param bar: XOHCL instance ... + * @param range: Integer, Detection Range ... + * + * @return ( bool ) + */ + bool Init( + XOHCL &bar, + int range = 0, + bool useRangeAsStart = false // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + result = InitBarZone( + bar, + X_POI_DEMAND_ZONE, + X_PRICE_HIGH, + X_PRICE_LOW // + ); + if (!result) + { + return result; + } + + // + result = IsValid(); + if (result && + range > 0) + { + // + datetime time = bar.time; + int periodSeconds = PeriodSeconds(bar.period); + + // + datetime from = + !useRangeAsStart + ? (datetime)((int)time - (range * periodSeconds)) + : time; + datetime to = (datetime)((int)time + (range * periodSeconds)); + + // + From(from); + To(to); + } + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + // + // Overrides ... + + bool IsValid() override + { + // + bool result = false; + + // + result = IsValidBarZone() && + mType == X_POI_DEMAND_ZONE; + + // + return result; + } + + // + protected: + // + + // + private: + // + + // +}; + +// +// Support Zone ... +class XCSupportZone : public XCBarZone +{ + // + public: + // + + // + // Constructor ... + void XCSupportZone() + { + } + + // + // Deconstructor ... + void ~XCSupportZone() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param bar: XOHCL instance ... + * @param range: Integer, Detection Range ... + * + * @return ( bool ) + */ + bool Init( + XOHCL &bar, + int range = 0, + bool useRangeAsStart = false // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + result = InitBarZone( + bar, + X_POI_SUPPORT_ZONE, + X_PRICE_DOWN, + X_PRICE_LOW // + ); + if (!result) + { + return result; + } + + // + result = IsValid(); + if (result && + range > 0) + { + // + datetime time = bar.time; + int periodSeconds = PeriodSeconds(bar.period); + + // + datetime from = + !useRangeAsStart + ? (datetime)((int)time - (range * periodSeconds)) + : time; + datetime to = (datetime)((int)time + (range * periodSeconds)); + + // + From(from); + To(to); + } + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + // + // Overrides ... + + bool IsValid() override + { + // + bool result = false; + + // + result = IsValidBarZone() && + mType == X_POI_SUPPORT_ZONE; + + // + return result; + } + + // + protected: + // + + // + private: + // + + // +}; + +// +// Resistance Zone ... +class XCResistanceZone : public XCBarZone +{ + // + public: + // + + // + // Constructor ... + void XCResistanceZone() + { + } + + // + // Deconstructor ... + void ~XCResistanceZone() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param bar: XOHCL instance ... + * @param range: Integer, Detection Range ... + * + * @return ( bool ) + */ + bool Init( + XOHCL &bar, + int range = 0, + bool useRangeAsStart = false // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + result = InitBarZone( + bar, + X_POI_RESISTANCE_ZONE, + X_PRICE_HIGH, + X_PRICE_UP // + ); + if (!result) + { + return result; + } + + // + result = IsValid(); + if (result && + range > 0) + { + // + datetime time = bar.time; + int periodSeconds = PeriodSeconds(bar.period); + + // + datetime from = + !useRangeAsStart + ? (datetime)((int)time - (range * periodSeconds)) + : time; + datetime to = (datetime)((int)time + (range * periodSeconds)); + + // + From(from); + To(to); + } + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + // + // Overrides ... + + bool IsValid() override + { + // + bool result = false; + + // + result = IsValidBarZone() && + mType == X_POI_RESISTANCE_ZONE; + + // + return result; + } + + // + protected: + // + + // + private: + // + + // +}; + +// +// Order Block ... +class XCOrderBlock : public XCBarZone +{ + // + public: + // + + // + // Constructor ... + void XCOrderBlock() + { + } + + // + // Deconstructor ... + void ~XCOrderBlock() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param bar: XOHCL instance ... + * @param dir: ENUM_X_DIRECTION member ... + * + * @return ( bool ) + */ + bool Init( + XOHCL &bar, + ENUM_X_DIRECTION dir // + ) + { + // + bool result = false; + + // + result = bar.IsValid() && + (dir == X_DIRECTION_BULLISH || + dir == X_DIRECTION_BEARISH); + if (!result) + { + return result; + } + + // + ENUM_XPOIS mTT = + IsSpecifiedBullish(dir) + ? X_POI_BULLISH_ORDERBLOCK + : X_POI_BEARISH_ORDERBLOCK; + + // + result = InitBarZone( + bar, + mTT, + X_PRICE_HIGH, + X_PRICE_LOW // + ); + if (!result) + { + return result; + } + + // + result = IsValid(); + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Check is Bullish ... + * + * @return ( bool ) + */ + bool IsBullish() + { + // + bool result = false; + + // + result = IsValid() && + Type() == X_POI_BULLISH_ORDERBLOCK; + + // + return result; + } + + /** + * Check is Bearish ... + * + * @return ( bool ) + */ + bool IsBearish() + { + // + bool result = false; + + // + result = IsValid() && + Type() == X_POI_BEARISH_ORDERBLOCK; + + // + return result; + } + + ENUM_X_DIRECTION GetDirection() + { + // + ENUM_X_DIRECTION result = X_DIRECTION_NONE; + + // + if (!IsValid()) + { + return result; + } + + // + result = + IsBullish() + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; + } + + // + // Overrides ... + + bool IsValid() override + { + // + bool result = false; + + // + result = IsValidBarZone() && + (mType == X_POI_BULLISH_ORDERBLOCK || + mType == X_POI_BEARISH_ORDERBLOCK); + + // + return result; + } + + // + protected: + // + + // + private: + // + + // +}; + +// +// Rejection Bar ... +class XCRejectionBar : public XCBarZone +{ + // + public: + // + + // + // Constructor ... + void XCRejectionBar() + { + } + + // + // Deconstructor ... + void ~XCRejectionBar() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool Init( + XOHCL &bar // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + bool isBullish = + bar.GetLowShadow() > bar.GetHighShadow(); + bool isBearish = + bar.GetHighShadow() > bar.GetLowShadow(); + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + ENUM_X_PRICE upPrice = isBullish + ? X_PRICE_HIGH + : X_PRICE_DOWN; + // + ENUM_X_PRICE loPrice = isBullish + ? X_PRICE_UP + : X_PRICE_LOW; + + // + result = InitBarZone( + bar, + X_POI_REJECTION_BAR, + upPrice, + loPrice // + ); + if (!result) + { + return result; + } + + // + result = IsValid(); + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Check is Bullish ... + * + * @return ( bool ) + */ + bool IsBullish() + { + // + bool result = false; + + // + result = IsValid() && + Type() == X_POI_REJECTION_BAR && + mBar.GetLowShadow() > mBar.GetHighShadow(); + + // + return result; + } + + /** + * Check is Bearish ... + * + * @return ( bool ) + */ + bool IsBearish() + { + // + bool result = false; + + // + result = IsValid() && + Type() == X_POI_REJECTION_BAR && + mBar.GetHighShadow() > mBar.GetLowShadow(); + + // + return result; + } + + // + // Overrides ... + + bool IsValid() override + { + // + bool result = false; + + // + result = IsValidBarZone() && + mType == X_POI_REJECTION_BAR; + + // + return result; + } + + // + protected: + // + + // + private: + // + + // +}; + +// +// Momentum Bar ... +class XCMomentumBar : public XCBarZone +{ + // + public: + // + + // + // Constructor ... + void XCMomentumBar() + { + } + + // + // Deconstructor ... + void ~XCMomentumBar() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool Init( + XOHCL &bar // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + bool isBullish = bar.IsBullish(); + bool isBearish = bar.IsBearish(); + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + result = InitBarZone( + bar, + X_POI_MOMENTUM_BAR, + X_PRICE_HIGH, + X_PRICE_LOW // + ); + if (!result) + { + return result; + } + + // + result = IsValid(); + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Check is Bullish ... + * + * @return ( bool ) + */ + bool IsBullish() + { + // + bool result = false; + + // + result = IsValid() && + mBar.IsBullish() && + Type() == X_POI_MOMENTUM_BAR; + + // + return result; + } + + /** + * Check is Bearish ... + * + * @return ( bool ) + */ + bool IsBearish() + { + // + bool result = false; + + // + result = IsValid() && + mBar.IsBearish() && + Type() == X_POI_MOMENTUM_BAR; + + // + return result; + } + + // + // Overrides ... + + bool IsValid() override + { + // + bool result = false; + + // + result = IsValidBarZone() && + mType == X_POI_MOMENTUM_BAR; + + // + return result; + } + + // + protected: + // + + // + private: + // + + // +}; + +// +// Fair Value Gap ... +class XCFVG : public XCTwoBarZone +{ + // + public: + // + + // + // Constructor ... + void XCFVG() + { + } + + // + // Deconstructor ... + void ~XCFVG() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param startBar: XOHCL instance ... + * @param endBar: XOHCL instance ... + * @param dir: ENUM_X_DIRECTION member ... + * + * @return ( bool ) + */ + bool Init( + XOHCL &startBar, + XOHCL &endBar, + ENUM_X_DIRECTION dir // + ) + { + // + bool result = false; + + // + result = endBar.IsValid() && + startBar.IsValid() && + (dir == X_DIRECTION_BULLISH || + dir == X_DIRECTION_BEARISH); + if (!result) + { + return result; + } + + // + bool isDirBullish = IsSpecifiedBullish(dir); + ENUM_XPOIS mTT = + isDirBullish + ? X_POI_BULLISH_FVG + : X_POI_BEARISH_FVG; + + // + ENUM_X_PRICE startPrice = isDirBullish + ? X_PRICE_HIGH + : X_PRICE_LOW; + ENUM_X_PRICE endPrice = isDirBullish + ? X_PRICE_LOW + : X_PRICE_HIGH; + + // + result = InitTwoBarZone( + startBar, + endBar, + mTT, + startPrice, + endPrice // + ); + if (!result) + { + return result; + } + + // + result = IsValid(); + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Check is Bullish ... + * + * @return ( bool ) + */ + bool IsBullish() + { + // + bool result = false; + + // + result = IsValid() && + Type() == X_POI_BULLISH_FVG; + + // + return result; + } + + /** + * Check is Bearish ... + * + * @return ( bool ) + */ + bool IsBearish() + { + // + bool result = false; + + // + result = IsValid() && + Type() == X_POI_BEARISH_FVG; + + // + return result; + } + + ENUM_X_DIRECTION GetDirection() + { + // + ENUM_X_DIRECTION result = X_DIRECTION_NONE; + + // + if (!IsValid()) + { + return result; + } + + // + result = + IsBullish() + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; + } + + // + // Overrides ... + + bool IsValid() override + { + // + bool result = false; + + // + result = IsValidTwoBarZone() && + (mType == X_POI_BULLISH_FVG || + mType == X_POI_BEARISH_FVG); + + // + return result; + } + + // + protected: + // + + // + private: + // + + // +}; + +// +// Ticks Zones ... + +// +class XCTickZone : public CObject +{ + // + // Public ... + public: + // + // Props ... + string symbol; + ENUM_TIMEFRAMES period; + + // + double high; + double low; + int ticks; + double percent; + + // + ulong volume; + double volumePercent; + + // + // Compare Two Zone With Each Other ... + virtual int Compare( + const CObject *node, + const int mode = 0 // + ) const + { + // + const XCTickZone *other = (XCTickZone *)node; + + // + return other.ticks - ticks; + } + + // + bool IsValid() + { + // + bool result = false; + + // + result = high > 0 && + low > 0 && + high > low && + ticks > 0 && + percent > 0; + + // + return result; + } + + // + // Protected ... + protected: + // + // Private ... + private: + // +}; + +// +class XCTicksZone : public XCTwoBarZone +{ + // + public: + // + + // + // Constructor ... + void XCTicksZone() + { + Default(); + } + + // + // Deconstructor ... + void ~XCTicksZone() + { + } + + // + // Getter(s) / Setter(s) ... + + /** + * Get Number of Ticks Levels ... + * + * @return ( int ) + */ + int Levels() + { + return mLevels; + } + + /** + * Set Number of Ticks Levels ... + * + * @return ( int ) + */ + void Levels(int value) + { + // + if (value < 2) + { + value = 2; + } + + // + mLevels = value; + } + + /** + * Apply Default Config ... + */ + virtual void Default() + { + // + Levels(10); + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param startBar: XOHCL instance ... + * @param endBar: XOHCL instance ... + * + * @return ( bool ) + */ + bool Init( + XOHCL &startBar, + XOHCL &endBar, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + result = endBar.IsValid() && + startBar.IsValid(); + if (!result) + { + return result; + } + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = endBar.period; + } + + // + // Calculate Start and End Time ... + datetime from = startBar.time; + datetime to = endBar.time; + ulong fromM = ((ulong)to * 1000); + ulong toM = ((ulong)from * 1000); + + // + // Symbol and Period ... + string symbol = startBar.symbol; + ENUM_TIMEFRAMES period = startBar.period; + + // + // Prepare Zones Array ... + mZones.Clear(); + + // + // Retrieve Ticks between Times ... + SpecificClean(mTicks); + int res = CopyTicksRange( + symbol, + mTicks, + COPY_TICKS_ALL, + fromM, + toM // + ); + + // + // Ticks Volumes ... + int ticksVolumeCount = CopyTickVolume( + symbol, + forPeriod, + from, + to, + mTickVolumes // + ); + if (IsValidSize(ticksVolumeCount)) + { + // + mVolumes = 0; + for (int i = 0; i < ticksVolumeCount; i++) + { + mVolumes += mTickVolumes[i]; + } + } + + // + // Retrieve Highs ... + SpecificClean(mHighs); + CopyHigh( + symbol, + period, + from, + to, + mHighs // + ); + + // + // Retrieve Lows ... + SpecificClean(mLows); + CopyLow( + symbol, + period, + from, + to, + mLows // + ); + + // + // Find Highest Value in Range ... + int highIDX = ArrayMaximum(mHighs); + mRangeHigh = mHighs[highIDX]; + + // + // Find Lowest Value in Range ... + int lowIDX = ArrayMinimum(mLows); + mRangeLow = mLows[lowIDX]; + + // + datetime mTimes[]; + CopyTime( + symbol, + period, + from, + to, + mTimes // + ); + mRangeHighTime = mTimes[highIDX]; + mRangeLowTime = mTimes[lowIDX]; + + // + double mRangeSize = mRangeHigh - mRangeLow; + + // + // Create Zones ... + for (int i = 0; i < Levels(); i++) + { + // + // Instance a New Zone ... + XCTickZone *iZone = new XCTickZone(); + + // + iZone.symbol = symbol; + iZone.period = period; + + // + // Calculate Each Zones High / Low based on Range ... + double iH = mRangeHigh - mRangeSize * i / Levels(); + double iL = mRangeHigh - mRangeSize * (i + 1) / Levels(); + + // + // Set Zone High Low Properties ... + iZone.low = iL; + iZone.high = iH; + + // + // Add Zone to Zone Array Objects ... + mZones.Add(iZone); + } + + // + // Calculate Each Zone Ticks ... + int ticksCount = ArraySize(mTicks); + for (int i = 0; i < ticksCount; i++) + { + // + // Retrieve Tick ... + MqlTick iTick = mTicks[i]; + + // + // Loop through Zones ... + for (int j = 0; j < Levels(); j++) + { + // + // Rejrieve j indexed Zone Object ... + XCTickZone *jZone = mZones.At(j); + + // + bool isInRange = IsTickInZoneRange( + iTick, + jZone // + ); + if (isInRange) + { + // + jZone.ticks++; + break; + } + } + } + + // + // Calculating Zone Percents ... + for (int i = 0; i < Levels(); i++) + { + // + XCTickZone *iZone = mZones.At(i); + + // + double percent = CalculateZoneTickPercent(iZone); + iZone.percent = percent; + } + + // + // Sort Zones Based on Percents ... + mZones.Sort(); + + // + mUpper = mRangeHigh; + mLower = mRangeLow; + mType = X_POI_TICKS_ZONES; + mEndBar = endBar; + mStartBar = startBar; + From(endBar.time); + To(startBar.time); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + // Try to Find Out PERIOD_1M times in each zone ... + datetime to1M = (datetime)((int)endBar.time + PeriodSeconds(period) - 60); + int to1MIndex = iBarShift( + symbol, + forPeriod, + to1M // + ); + int from1MIndex = iBarShift( + symbol, + forPeriod, + from // + ); + for (int i = from1MIndex; i > to1MIndex; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + symbol, + forPeriod, + i // + ); + if (!isInited) + { + continue; + } + ulong iVolume = iTickVolume( + symbol, + forPeriod, + i // + ); + + // + // Loop through Zones ... + for (int j = 0; j < Levels(); j++) + { + // + XCTickZone *jZone = mZones.At(j); + if (!jZone.IsValid()) + { + continue; + } + + // + // Check iBar is Inside jZone ... + bool isIBarInside = + iBar.GetUp() < jZone.high && + iBar.GetDown() > jZone.low; + // iBar.low < jZone.high || + // iBar.high > jZone.low; + if (isIBarInside) + { + jZone.volume += iVolume; + } + } + } + + // + // Calculate Volume Percent ... + for (int i = 0; i < Levels(); i++) + { + // + XCTickZone *iZone = mZones.At(i); + + // + if (mVolumes > 0) + { + iZone.volumePercent = (double)(iZone.volume * 100 / mVolumes); + } + } + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Retrieve Zones Count ... + * + * @return ( int ) + */ + int Count() + { + return mZones.Total(); + } + + /** + * Retrieve Specified Sorted Zones ... + * + * @param index: Integer ... + * + * @return ( XCTickZone * ) + */ + XCTickZone *GetZone(int index) + { + // + if (!IsValidIndex(index)) + { + return NULL; + } + + // + return mZones.At(index); + } + + /** + * Calculate Liquidity Percent for Specified Direction ... + * + * @param forDirection: ENUM_X_DIRECTION member, Specified Liquidity ... + * @param price: Double, Specified Price ... + * + * @return ( double ) + */ + double CalculateLiquidityPercent( + ENUM_X_DIRECTION forDirection, + double price // + ) + { + // + double result = 0; + + // + int count = Count(); + if (price <= 0 || + !IsValid() || + !IsValidSize(count) || + forDirection == X_DIRECTION_ALL || + forDirection == X_DIRECTION_NONE) + { + return result; + } + + // + bool isBullish = forDirection == X_DIRECTION_BULLISH; + + // + for (int i = 0; i < count; i++) + { + // + XCTickZone *iZone = GetZone(i); + + // + if (iZone.IsValid()) + { + // + result += !isBullish && + price > iZone.high + ? iZone.percent + : isBullish && + price < iZone.low + ? iZone.percent + : 0; + } + } + + // + return result; + } + + // + // Overrides ... + bool IsValid() override + { + // + bool result = false; + + // + result = + IsValidFrom() && + IsValidTwoBarZone() && + Levels() > 0 && + mZones.Total() == Levels() && + mRangeHigh > 0 && + mRangeLow > 0; + + // + return result; + } + + // + bool GetMaxTickZone(XCTickZone *&zone) + { + // + bool result = false; + + // + zone = NULL; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int count = Count(); + for (int i = 0; i < count; i++) + { + // + XCTickZone *iZone = GetZone(i); + + // + bool canSet = + zone == NULL + ? true + : zone.ticks < iZone.ticks + ? true + : false; + if (canSet) + { + zone = iZone; + } + + // + ZeroMemory(iZone); + } + + // + result = zone != NULL && + zone.IsValid(); + + // + return result; + } + + // + bool GetMinTickZone(XCTickZone *&zone) + { + // + bool result = false; + + // + zone = NULL; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int count = Count(); + for (int i = 0; i < count; i++) + { + // + XCTickZone *iZone = GetZone(i); + + // + bool canSet = + zone == NULL + ? true + : zone.ticks > iZone.ticks + ? true + : false; + if (canSet) + { + zone = iZone; + } + + // + ZeroMemory(iZone); + } + + // + result = zone != NULL && + zone.IsValid(); + + // + return result; + } + + // + bool GetMaxVolumeZone(XCTickZone *&zone) + { + // + bool result = false; + + // + zone = NULL; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int count = Count(); + for (int i = 0; i < count; i++) + { + // + XCTickZone *iZone = GetZone(i); + + // + bool canSet = + zone == NULL + ? true + : zone.volume < iZone.volume + ? true + : false; + if (canSet) + { + zone = iZone; + } + + // + ZeroMemory(iZone); + } + + // + result = zone != NULL && + zone.IsValid(); + + // + return result; + } + + // + bool GetMinVolumeZone(XCTickZone *&zone) + { + // + bool result = false; + + // + zone = NULL; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int count = Count(); + for (int i = 0; i < count; i++) + { + // + XCTickZone *iZone = GetZone(i); + + // + bool canSet = + zone == NULL + ? true + : zone.volume > iZone.volume + ? true + : false; + if (canSet) + { + zone = iZone; + } + + // + ZeroMemory(iZone); + } + + // + result = zone != NULL && + zone.IsValid(); + + // + return result; + } + + // + protected: + // + + // + private: + // + // Props ... + + // + MqlTick mTicks[]; + double mHighs[]; + double mLows[]; + ulong mVolumes; + ulong mTickVolumes[]; + double mRangeHigh; + datetime mRangeHighTime; + double mRangeLow; + datetime mRangeLowTime; + + // + int mLevels; // Number of Ticks Levels ... + + // + CArrayObj mZones; + + /** + * Check a Tick is in a Zone rage or not ... + * + * @param tick: MqlTick instance ... + * @param zone: XCTickZone instance ... + * + * @return ( bool ) + */ + bool IsTickInZoneRange( + MqlTick &tick, + XCTickZone *zone // + ) + { + // + bool result = false; + + // + result = + // + tick.bid >= zone.low && + tick.bid <= zone.high + // + ; + + // + return result; + } + + /** + * Calculate Zone Tick Percent ... + * + * @param zone: XCTickZone instance ... + * @param normalizationDigits: Integer ... + * + * @return ( double ) + */ + double CalculateZoneTickPercent( + XCTickZone *zone, + int normalizationDigits = 2 // + ) + { + // + double result = 0; + + // + if (normalizationDigits < 2 || normalizationDigits > 5) + { + normalizationDigits = 2; + } + + // + int ticksCount = ArraySize(mTicks); + if (ticksCount <= 0) + { + return result; + } + + // + result = (double)zone.ticks / ticksCount * 100; + result = NormalizeDouble(result, normalizationDigits); + + // + return result; + } + + // +}; + +// +// Trading Day ... +class XCDay : public XCFromToZone +{ + // + public: + // + + // + // Constructor ... + void XCDay() + { + } + + // + // Deconstructor ... + void ~XCDay() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @return ( bool ) + */ + bool Init() + { + // + bool result = false; + + // + result = IsValid(); + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + // + // Overrides ... + + // + protected: + // + + // + private: + // + + // +}; + +// +// Trading Session ... +class XCSession : public XCFromToZone +{ + // + public: + // + + // + // Constructor ... + void XCSession() + { + } + + // + // Deconstructor ... + void ~XCSession() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @return ( bool ) + */ + bool Init() + { + // + bool result = false; + + // + result = IsValid(); + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + // + // Overrides ... + + // + protected: + // + + // + private: + // + + // +}; + +// +struct XBoxZone +{ + // + // Props ... + string symbol; + ENUM_TIMEFRAMES period; + + // + double upper; + double lower; + + // + datetime from; + datetime to; + + // + string type; + ENUM_X_DIRECTION dir; + + // + // Constructor ... + XBoxZone() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup Model ... + */ + void Clean() + { + // + upper = 0; + lower = 0; + to = NULL; + from = NULL; + symbol = NULL; + period = NULL; + dir = X_DIRECTION_NONE; + + // + ZeroMemory(this); + } + + /** + * Validate Model ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + // + upper > 0 && + lower > 0 && + from < to && + IsValid(to) && + upper >= lower && + IsValid(from) && + IsValid(symbol) && + IsValid(period) + // + ; + + // + return result; + } + + /** + * Check Box is Bullish or not ... + * + * @return ( bool ) + */ + bool IsBullish() + { + return IsValid() && + IsBullish(dir); + } + + /** + * Check Box is Bearish or not ... + * + * @return ( bool ) + */ + bool IsBearish() + { + return IsValid() && + IsBearish(dir); + } + + /** + * Clone Box by Provided Source ... + * + * @return ( bool ) + */ + bool Clone(XBoxZone &source) + { + // + bool result = false; + + // + Clean(); + result = source.IsValid(); + if (!result) + { + return result; + } + + // + // Filling Props ... + to = source.to; + dir = source.dir; + from = source.from; + type = source.type; + upper = source.upper; + lower = source.lower; + symbol = source.symbol; + period = source.period; + + // + result = IsValid(); + if (!result) + { + Clean(); + } + + // + return result; + } + + /** + * Check Box is Same as Other ... + * + * @param item: XBoxZone instance Resource ... + * + * @return ( bool ) + */ + bool IsSameAs(XBoxZone &item) + { + // + return IsValid() && + item.IsValid() && + dir == item.dir && + from == item.from && + type == item.type && + lower == item.lower && + upper == item.upper && + symbol == item.symbol && + period == item.period; + } + + /** + * Retrieve Box Age ... + * + * @param forPeriod: ENUM_TIMEFRAMES member ... + * + * @return ( int ) + */ + int GetAge( + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + result = iBarShift( + symbol, + forPeriod, + from // + ); + + // + return result; + } + + /** + * Calculate Box Middle Price ... + * + * @return ( double ) + */ + double GetMid() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + double diffAvg = (upper - lower) / 2; + result = lower + diffAvg; + result = NormalizePrice(result, symbol); + + // + return result; + } + + /** + * Calculate Box Leg N Price ... + * N default is 2 + * + * @param leg: int ... + * + * @return ( double ) + */ + double GetLeg(int leg = 2) + { + // + double result = 0; + + // + leg = NormalizeInt(leg, 2); + + // + if (!IsValid()) + { + return result; + } + + // + double range = (upper - lower) * leg; + result = + IsBullish() + ? upper + range + : lower - range; + result = NormalizePrice(result, symbol); + + // + return result; + } + + /** + * Calculate Box Range ... + * + * @return ( double ) + */ + double GetRange() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = (upper - lower); + result = NormalizePrice(result, symbol); + + // + return result; + } + + /** + * Extract Rejection Price based on Box Direction ... + * + * @return ( double ) + */ + double GetRejection() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = + IsBullish() + ? upper + : lower; + + // + return result; + } + + /** + * To Bar Index ... + * + * @return ( int ) + */ + int ToIndex( + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + result = GetBarIndex( + symbol, + forPeriod, + to // + ); + + // + return result; + } + + /** + * Retrieve To Bar ... + * + * @return ( bool ) + */ + bool ToBar(XOHCL &bar) + { + // + bool result = false; + + // + bar.Clean(); + + // + int idx = ToIndex(); + + // + result = + IsValid() && + IsValidIndex(idx); + if (!result) + { + return result; + } + + // + result = bar.Init( + symbol, + period, + idx // + ); + + // + return result; + } + + /** + * From Bar Index ... + * + * @return ( int ) + */ + int FromIndex( + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + result = GetBarIndex( + symbol, + forPeriod, + from // + ); + + // + return result; + } + + /** + * Retrieve From Bar ... + * + * @return ( bool ) + */ + bool FromBar(XOHCL &bar) + { + // + bool result = false; + + // + bar.Clean(); + + // + int idx = FromIndex(); + + // + result = + IsValid() && + IsValidIndex(idx); + if (!result) + { + return result; + } + + // + result = bar.Init( + symbol, + period, + idx // + ); + + // + return result; + } + + /** + * Retrieve Unique Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + // + int digits = GetDigits(symbol); + double nUpper = NormalizeDouble(NormalizePrice(upper, symbol), digits); + double nLower = NormalizeDouble(NormalizePrice(lower, symbol), digits); + + // + string typeStr = IsValid(type) + ? type + : "XBOX"; + string result = + // + typeStr + "_" + + ToString(dir) + "_" + + symbol + "_" + + ToString(period) + "_" + + ToString(nUpper) + "_" + + ToString(nLower) + // + ; + + // + return result; + } + + /** + * Retrieve Unique Middle Identifier ... + * + * @return ( string ) + */ + string GetMiddleTag() + { + // + int digits = GetDigits(symbol); + double nMid = NormalizeDouble(NormalizePrice(GetMid(), symbol), digits); + + // + string typeStr = IsValid(type) + ? type + : "XBOX"; + string result = + // + typeStr + "_" + + "Mid_" + + ToString(dir) + "_" + + symbol + "_" + + ToString(period) + "_" + + ToString(nMid) + // + ; + + // + return result; + } +}; + +// +struct XDirectionShift +{ + // + // Props ... + string type; + datetime at; + double after; + double before; + string symbol; + ENUM_TIMEFRAMES period; + ENUM_X_DIRECTION shiftTo; + + // + // Constructor ... + XDirectionShift() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + at = NULL; + after = 0; + before = 0; + type = NULL; + symbol = NULL; + period = NULL; + shiftTo = X_DIRECTION_NONE; + + // + ZeroMemory(this); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + after > 0 && + IsValid(at) && + IsValid(type) && + after != before && + IsValid(symbol) && + IsValid(period) && + HasDirection(shiftTo); + + // + return result; + } + + // + // Get Bar Index of Direction Shift ... + int Index() + { + // + int result = -1; + + // + // Validate ... + if (!IsValid()) + { + return result; + } + + // + // Retrieve Bar Index ... + result = GetBarIndex( + symbol, + period, + at // + ); + + // + return result; + } + + // + // Get At Bar ... + bool AtBar(XOHCL &bar) + { + // + bool result = false; + + // + // Normalize ... + bar.Clean(); + + // + // Validate ... + result = IsValid(); + if (!result) + { + return result; + } + + // + int idx = Index(); + if (IsValidIndex(idx)) + { + // + result = bar.Init( + symbol, + period, + idx // + ); + } + + // + result = bar.IsValid(); + + // + return result; + } + + // + // Check Same ... + bool IsSameAs(XDirectionShift &item) + { + // + bool result = false; + + // + result = IsValid() && + item.IsValid(); + if (!result) + { + return result; + } + + // + result = + // + at == item.at && + type == item.type && + after == item.after && + before == item.before && + symbol == item.symbol && + period == item.period && + shiftTo == item.shiftTo + // + ; + + // + return result; + } +}; + +// diff --git a/BKPS/14040316/Libraries/x-saherelm.x-poi.state.lib.mq5 b/BKPS/14040316/Libraries/x-saherelm.x-poi.state.lib.mq5 new file mode 100644 index 0000000..e52ea2b --- /dev/null +++ b/BKPS/14040316/Libraries/x-saherelm.x-poi.state.lib.mq5 @@ -0,0 +1,4680 @@ + +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Seriallize Library +// --------------------------------------- +// Name: XPOILib +// Description: All models related to POIs ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright `023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Libraries/x-saherelm.x-poi.extensions.lib.mq5" +#include "../Libraries/x-saherelm.x-poi.lib.mq5" + +// +enum ENUM_X_OBFVG_FVG_FILTERS +{ + X_OBFVG_FVG_FILTER_NONE, + X_OBFVG_FVG_FILTER_INSIDE_OR, + X_OBFVG_FVG_FILTER_ABOVE_BELOW, +}; + +// +enum ENUM_X_OBFVG_FVG_SELECTION +{ + X_OBFVG_FVG_SELECT_NONE, + X_OBFVG_FVG_SELECT_OLDEST, + X_OBFVG_FVG_SELECT_LOWEST, + X_OBFVG_FVG_SELECT_HIGHEST, + X_OBFVG_FVG_SELECT_YOUNGEST, + X_OBFVG_FVG_SELECT_HIGHEST_LOWEST, + X_OBFVG_FVG_SELECT_LOWEST_HIGHEST, +}; + +// +struct XSignalBox +{ + // + XBoxZone ob; + XBoxZone fvg; + XBoxZone sharp; + + // + double sl; + double tp; + + // + // Constructor ... + XSignalBox() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup Model ... + */ + void Clean() + { + // + sl = 0; + tp = 0; + + // + ob.Clean(); + fvg.Clean(); + sharp.Clean(); + + // + ZeroMemory(this); + } + + /** + * Validate Model ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + ob.IsValid() && + fvg.IsValid() && + sharp.IsValid(); + + // + return result; + } + + /** + * Update Structure Models To Date ... + * + * @param value: datetime ... + */ + void UpdateTo(datetime value = NULL) + { + // + value = NormalizeTime(value); + + // + if (ob.IsValid()) + { + ob.to = value; + } + + // + if (fvg.IsValid()) + { + fvg.to = value; + } + + // + if (sharp.IsValid()) + { + sharp.to = value; + } + } + + // +}; + +// +// Model State Parsing ... +struct XPOIStateEvents +{ + // + // Props ... + + // + // Swings ... + bool hasNewSwing; + bool hasNewSwingLow; + bool hasNewSwingHigh; + + // + // Momentums ... + bool hasNewMomentum; + bool hasNewBullishMomentum; + bool hasNewBearishMomentum; + + // + // Rejections ... + bool hasNewRejection; + bool hasNewBullishRejection; + bool hasNewBearishRejection; + + // + // Pullbacks ... + bool hasNewPullback; + bool hasNewBullishPullback; + bool hasNewBearishPullback; + + // + // Support/Resistance (s) ... + bool hasNewSupportZone; + bool hasNewResistanceZone; + + // + // Supply/Demand (s) ... + bool hasNewSupplyZone; + bool hasNewDemandZone; + + // + // Fair Value Gaps ... + bool hasNewFairValueGap; + bool hasNewBullishFairValueGap; + bool hasNewBearishFairValueGap; + + // + // Order Blocks ... + bool hasNewOrderBlock; + bool hasNewBullishOrderBlock; + bool hasNewBearishOrderBlock; + + // + // Spikes ... + bool hasNewSpike; + bool hasNewBullishSpike; + bool hasNewBearishSpike; + + // + // Sharps ... + bool hasNewSharp; + bool hasNewBullishSharp; + bool hasNewBearishSharp; + + // + // Consolidation Zones ... + bool hasNewConsolidationZone; + bool hasNewBullishConsolidationZone; + bool hasNewBearishConsolidationZone; + + // + // Constructor ... + XPOIStateEvents() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup Model ... + */ + void Clean() + { + // + hasNewSwing = false; + hasNewSwingLow = false; + hasNewSwingHigh = false; + + // + hasNewMomentum = false; + hasNewBullishMomentum = false; + hasNewBearishMomentum = false; + + // + hasNewRejection = false; + hasNewBullishRejection = false; + hasNewBearishRejection = false; + + // + hasNewSupportZone = false; + hasNewResistanceZone = false; + + // + hasNewSupplyZone = false; + hasNewDemandZone = false; + + // + hasNewFairValueGap = false; + hasNewBullishFairValueGap = false; + hasNewBearishFairValueGap = false; + + // + hasNewOrderBlock = false; + hasNewBullishOrderBlock = false; + hasNewBearishOrderBlock = false; + + // + hasNewSpike = false; + hasNewBullishSpike = false; + hasNewBearishSpike = false; + + // + hasNewSharp = false; + hasNewBullishSharp = false; + hasNewBearishSharp = false; + + // + hasNewConsolidationZone = false; + hasNewBullishConsolidationZone = false; + hasNewBearishConsolidationZone = false; + + // + ZeroMemory(this); + } + + /** + * Initialize Event Parser Model ... + * + * @param events: ENUM_XPOI_EVENTS members Collection Reference ... + */ + void Init(ENUM_XPOI_EVENTS &events[]) + { + // + hasNewSwing = HasNewSwing(events); + hasNewSwingLow = HasNewSwingLow(events); + hasNewSwingHigh = HasNewSwingHigh(events); + + // + hasNewMomentum = HasNewMomentum(events); + hasNewBullishMomentum = HasNewBullishMomentum(events); + hasNewBearishMomentum = HasNewBearishMomentum(events); + + // + hasNewRejection = HasNewRejection(events); + hasNewBullishRejection = HasNewBullishRejection(events); + hasNewBearishRejection = HasNewBearishRejection(events); + + // + hasNewPullback = HasNewPullback(events); + hasNewBullishPullback = HasNewBullishPullback(events); + hasNewBearishPullback = HasNewBearishPullback(events); + + // + hasNewSupportZone = HasNewSupportZone(events); + hasNewResistanceZone = HasNewResistanceZone(events); + + // + hasNewSupplyZone = HasNewSupplyZone(events); + hasNewDemandZone = HasNewDemandZone(events); + + // + hasNewFairValueGap = HasNewFairValueGap(events); + hasNewBullishFairValueGap = HasNewBullishFairValueGap(events); + hasNewBearishFairValueGap = HasNewBearishFairValueGap(events); + + // + hasNewOrderBlock = HasNewOrderBlock(events); + hasNewBullishOrderBlock = HasNewBullishOrderBlock(events); + hasNewBearishOrderBlock = HasNewBearishOrderBlock(events); + + // + hasNewSpike = HasNewSpike(events); + hasNewBullishSpike = HasNewBullishSpike(events); + hasNewBearishSpike = HasNewBearishSpike(events); + + // + hasNewSharp = HasNewSharp(events); + hasNewBullishSharp = HasNewBullishSharp(events); + hasNewBearishSharp = HasNewBearishSharp(events); + + // + hasNewConsolidationZone = HasNewConsolidationZone(events); + hasNewBullishConsolidationZone = HasNewBullishConsolidationZone(events); + hasNewBearishConsolidationZone = HasNewBearishConsolidationZone(events); + } + + // +}; + +// +// Model Exists Founded POIs ... +struct XPOIState +{ + // + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + XCSwing *swings[]; // Holds Founded Swing ... + XCSwing *swingLows[]; // Holds Founded Swing Lows ... + XCSwing *swingHighs[]; // Holds Founded Swing Highs ... + + // + XCMomentumBar *momentums[]; // Holds Founded Momentum Bars ... + XCMomentumBar *bullishMomentums[]; // Holds Founded Bullish Momentum Bars ... + XCMomentumBar *bearishMomentums[]; // Holds Founded Bearish Momentum Bars ... + + // + XCRejectionBar *rejections[]; // Holds Founded Rejection Bars ... + XCRejectionBar *bullishRejections[]; // Holds Founded Bullish Rejection Bars ... + XCRejectionBar *bearishRejections[]; // Holds Founded Bearish Rejection Bars ... + + // + XCSupportZone *supportZones[]; // Holds Founded Support Zones ... + XCResistanceZone *resistanceZones[]; // Holds Founded Resistance Zones ... + + // + XCSupplyZone *supplyZones[]; // Holds Founded Supply Zones ... + XCDemandZone *demandZones[]; // Holds Founded Demand Zones ... + + // + XCOrderBlock *orderBlocks[]; // Holds Founded Order Blocks ... + XCOrderBlock *bullishOrderBlocks[]; // Holds Founded Bullish Order Blocks ... + XCOrderBlock *bearishOrderBlocks[]; // Holds Founded Bearish Order Blocks ... + + // + XCFVG *fairValueGaps[]; // Holds Founded Fair Value Gaps ... + XCFVG *bullishFairValueGaps[]; // Holds Founded Bullish Fair Value Gaps ... + XCFVG *bearishFairValueGaps[]; // Holds Founded Bearish Fair Value Gaps ... + + // + XConsolidationZone consolidationZones[]; // Holds Founded Consolidation Zones ... + XConsolidationZone bullishConsolidationZones[]; // Holds Founded Bullish Consolidation Zones ... + XConsolidationZone bearishConsolidationZones[]; // Holds Founded Bearih Consolidation Zones ... + + // + XBoxZone spikes[]; // Holds Founded Spikes ... + XBoxZone bullishSpikes[]; // Holds Founded Bullish Spikes ... + XBoxZone bearishSpikes[]; // Holds Founded Bearih Spikes ... + + // + XBoxZone sharps[]; // Holds Founded Sharps ... + XBoxZone bullishSharps[]; // Holds Founded Bullish Sharps ... + XBoxZone bearishSharps[]; // Holds Founded Bearih Sharps ... + + // + XBoxZone pullbacks[]; // Holds Founded Pullbacks ... + XBoxZone bullishPullbacks[]; // Holds Founded Bullish Pullbacks ... + XBoxZone bearishPullbacks[]; // Holds Founded Bearish Pullbacks ... + + // + // Constructor ... + void XPOIState() + { + Clean(); + } + + // + // Actions ... + + /** + * Cleanup all props ... + */ + void Clean() + { + // + time = NULL; + symbol = NULL; + period = NULL; + + // + // Swings ... + Clean(swings); + Clean(swingLows); + Clean(swingHighs); + + // + // Momentums ... + Clean(momentums); + Clean(bullishMomentums); + Clean(bearishMomentums); + + // + // Rejections ... + Clean(rejections); + Clean(bullishRejections); + Clean(bearishRejections); + + // + // Support / Resistance Zones ... + Clean(supportZones); + Clean(resistanceZones); + + // + // Supply / Demand Zones ... + Clean(supplyZones); + Clean(demandZones); + + // + // Fair Value Gaps ... + Clean(fairValueGaps); + Clean(bullishFairValueGaps); + Clean(bearishFairValueGaps); + + // + // Order Blocks ... + Clean(orderBlocks); + Clean(bullishOrderBlocks); + Clean(bearishOrderBlocks); + + // + // Spikes ... + Clean(spikes); + Clean(bullishSpikes); + Clean(bearishSpikes); + + // + // Sharps ... + Clean(sharps); + Clean(bullishSharps); + Clean(bearishSharps); + + // + // Pullbaks ... + Clean(pullbacks); + Clean(bullishPullbacks); + Clean(bearishPullbacks); + + // + // Consolidation Zones ... + Clean(consolidationZones); + Clean(bullishConsolidationZones); + Clean(bearishConsolidationZones); + + // + ZeroMemory(this); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + IsSpecifiedValid(symbol) && + IsSpecifiedValid(period) && + IsSpecifiedValid(time); + + // + return result; + } + + /** + * Check State has Childs or not ... + * + * @return ( bool ) + */ + bool HasChild() + { + // + bool result = false; + + // + result = + // + // Swings ... + HasSwings() || + HasSwingLows() || + HasSwingHighs() || + // + // Momentums ... + HasMomentums() || + HasBullishMomentums() || + HasBearishMomentums() || + // + // Rejections ... + HasRejections() || + HasBullishRejections() || + HasBearishRejections() || + // + // Pullbacks ... + HasPullbacks() || + HasBullishPullbacks() || + HasBearishPullbacks() || + // + // Support / Resistance Zones ... + HasSupportZones() || + HasResistanceZones() || + // + // Supply / Demand Zones ... + HasSupplyZones() || + HasDemandZones() || + // + // Fair Value Gaps ... + HasFairValueGaps() || + HasBullishFairValueGaps() || + HasBearishFairValueGaps() || + // + // Order Blocks ... + HasOrderBlocks() || + HasBullishOrderBlocks() || + HasBearishOrderBlocks() || + // + // Spikes ... + HasSpikes() || + HasBullishSpikes() || + HasBearishSpikes() || + // + // Sharps ... + HasSharps() || + HasBullishSharps() || + HasBearishSharps() || + // + // Consolidation Zones ... + HasConsolidationZones() || + HasBullishConsolidationZones() || + HasBearishConsolidationZones() + // + ; + + // + return result; + } + + // + // Checkers ... + + // + // Swings ... + + // + // Has ... + + // + bool HasSwings() + { + return HasChild(swings); + } + + // + bool HasSwingLows() + { + return HasChild(swingLows); + } + + // + bool HasSwingHighs() + { + return HasChild(swingHighs); + } + + // + // Count ... + + // + int CountSwings() + { + return ArraySize(swings); + } + + // + int CountSwingLows() + { + return ArraySize(swingLows); + } + + // + int CountSwingHighs() + { + return ArraySize(swingHighs); + } + + // + // Momentums ... + + // + // Has ... + + // + bool HasMomentums() + { + return HasChild(momentums); + } + + // + bool HasBullishMomentums() + { + return HasChild(bullishMomentums); + } + + // + bool HasBearishMomentums() + { + return HasChild(bearishMomentums); + } + + // + // Count ... + + // + int CountMomentums() + { + return ArraySize(momentums); + } + + // + int CountBullishMomentums() + { + return ArraySize(bullishMomentums); + } + + // + int CountBearishMomentums() + { + return ArraySize(bearishMomentums); + } + + // + // Rejections ... + + // + // Has ... + + // + bool HasRejections() + { + return HasChild(rejections); + } + + // + bool HasBullishRejections() + { + return HasChild(bullishRejections); + } + + // + bool HasBearishRejections() + { + return HasChild(bearishRejections); + } + + // + // Count ... + + // + int CountRejections() + { + return ArraySize(rejections); + } + + // + int CountBullishRejections() + { + return ArraySize(bullishRejections); + } + + // + int CountBearishRejections() + { + return ArraySize(bearishRejections); + } + + // + // Pullbacks ... + + // + // Has ... + + // + bool HasPullbacks() + { + return HasChild(pullbacks); + } + + // + bool HasBullishPullbacks() + { + return HasChild(bullishPullbacks); + } + + // + bool HasBearishPullbacks() + { + return HasChild(bearishPullbacks); + } + + // + // Count ... + + // + int CountPullbacks() + { + return ArraySize(pullbacks); + } + + // + int CountBullishPullbacks() + { + return ArraySize(bullishPullbacks); + } + + // + int CountBearishPullbacks() + { + return ArraySize(bearishPullbacks); + } + + // + // Support / Resistance Zones ... + + // + // Has ... + + // + bool HasSupportZones() + { + return HasChild(supportZones); + } + + // + bool HasResistanceZones() + { + return HasChild(resistanceZones); + } + + // + // Count ... + + // + int CountSupportZones() + { + return ArraySize(supportZones); + } + + // + int CountResistanceZones() + { + return ArraySize(resistanceZones); + } + + // + // Supply / Demand Zones ... + + // + // Has ... + + // + bool HasSupplyZones() + { + return HasChild(supplyZones); + } + + // + bool HasDemandZones() + { + return HasChild(demandZones); + } + + // + // Count ... + + // + int CountSupplyZones() + { + return ArraySize(supplyZones); + } + + // + int CountDemandZones() + { + return ArraySize(demandZones); + } + + // + // Fair Value Gaps ... + + // + // Has ... + + // + bool HasFairValueGaps() + { + return HasChild(fairValueGaps); + } + + // + bool HasBullishFairValueGaps() + { + return HasChild(bullishFairValueGaps); + } + + // + bool HasBearishFairValueGaps() + { + return HasChild(bearishFairValueGaps); + } + + // + // Count ... + + // + int CountFairValueGaps() + { + return ArraySize(fairValueGaps); + } + + // + int CountBullishFairValueGaps() + { + return ArraySize(bullishFairValueGaps); + } + + // + int CountBearishFairValueGaps() + { + return ArraySize(bearishFairValueGaps); + } + + // + // Order Blocks ... + + // + // Has ... + + // + bool HasOrderBlocks() + { + return HasChild(orderBlocks); + } + + // + bool HasBullishOrderBlocks() + { + return HasChild(bullishOrderBlocks); + } + + // + bool HasBearishOrderBlocks() + { + return HasChild(bearishOrderBlocks); + } + + // + // Count ... + + // + int CountOrderBlocks() + { + return ArraySize(orderBlocks); + } + + // + int CountBullishOrderBlocks() + { + return ArraySize(bullishOrderBlocks); + } + + // + int CountBearishOrderBlocks() + { + return ArraySize(bearishOrderBlocks); + } + + // + // Spikes ... + + // + // Has ... + + // + bool HasSpikes() + { + return HasChild(spikes); + } + + // + bool HasBullishSpikes() + { + return HasChild(bullishSpikes); + } + + // + bool HasBearishSpikes() + { + return HasChild(bearishSpikes); + } + + // + // Count ... + + // + int CountSpikes() + { + return ArraySize(spikes); + } + + // + int CountBullishSpikes() + { + return ArraySize(bullishSpikes); + } + + // + int CountBearishSpikes() + { + return ArraySize(bearishSpikes); + } + + // + // Sharps ... + + // + // Has ... + + // + bool HasSharps() + { + return HasChild(sharps); + } + + // + bool HasBullishSharps() + { + return HasChild(bullishSharps); + } + + // + bool HasBearishSharps() + { + return HasChild(bearishSharps); + } + + // + // Count ... + + // + int CountSharps() + { + return ArraySize(sharps); + } + + // + int CountBullishSharps() + { + return ArraySize(bullishSharps); + } + + // + int CountBearishSharps() + { + return ArraySize(bearishSharps); + } + + // + // Consolidation Zone ... + + // + // Has ... + + // + bool HasConsolidationZones() + { + return HasChild(consolidationZones); + } + + // + bool HasBullishConsolidationZones() + { + return HasChild(bullishConsolidationZones); + } + + // + bool HasBearishConsolidationZones() + { + return HasChild(bearishConsolidationZones); + } + + // + // Count ... + + // + int CountConsolidationZones() + { + return ArraySize(consolidationZones); + } + + // + int CountBullishConsolidationZones() + { + return ArraySize(bullishConsolidationZones); + } + + // + int CountBearishConsolidationZones() + { + return ArraySize(bearishConsolidationZones); + } + + // + // Box Retrievers ... + + // + int SupportResistancesAsBox(XBoxZone &items[]) + { + // + XBoxZone tmpBoxes[]; + + // + ToBox( + supportZones, + tmpBoxes // + ); + Copy( + tmpBoxes, + items, + false // + ); + Clean(tmpBoxes); + + // + ToBox( + resistanceZones, + tmpBoxes // + ); + Copy( + tmpBoxes, + items, + false // + ); + Clean(tmpBoxes); + + // + int result = ArraySize(items); + + // + return result; + } + + // + int SupplyDemandsAsBox(XBoxZone &items[]) + { + // + XBoxZone tmpBoxes[]; + + // + ToBox( + supplyZones, + tmpBoxes // + ); + Copy( + tmpBoxes, + items, + false // + ); + Clean(tmpBoxes); + + // + ToBox( + demandZones, + tmpBoxes // + ); + Copy( + tmpBoxes, + items, + false // + ); + Clean(tmpBoxes); + + // + int result = ArraySize(items); + + // + return result; + } + + // + int OrderBlocksAsBox(XBoxZone &items[]) + { + // + XBoxZone tmpBoxes[]; + + // + ToBox( + bullishOrderBlocks, + tmpBoxes // + ); + Copy( + tmpBoxes, + items, + false // + ); + Clean(tmpBoxes); + + // + ToBox( + bearishOrderBlocks, + tmpBoxes // + ); + Copy( + tmpBoxes, + items, + false // + ); + Clean(tmpBoxes); + + // + int result = ArraySize(items); + + // + return result; + } + + // + int FairValueGapsAsBox(XBoxZone &items[]) + { + // + XBoxZone tmpBoxes[]; + + // + ToBox( + bullishFairValueGaps, + tmpBoxes // + ); + Copy( + tmpBoxes, + items, + false // + ); + Clean(tmpBoxes); + + // + ToBox( + bearishFairValueGaps, + tmpBoxes // + ); + Copy( + tmpBoxes, + items, + false // + ); + Clean(tmpBoxes); + + // + int result = ArraySize(items); + + // + return result; + } + + // + int SpikesAsBox(XBoxZone &items[]) + { + // + Copy( + bullishSpikes, + items, + false // + ); + + // + Copy( + bearishSpikes, + items, + false // + ); + + // + int result = ArraySize(items); + + // + return result; + } + + // + int SharpsAsBox(XBoxZone &items[]) + { + // + Copy( + bullishSharps, + items, + false // + ); + + // + Copy( + bearishSharps, + items, + false // + ); + + // + int result = ArraySize(items); + + // + return result; + } + + // + // Tools ... + + // + void UpdateTo(datetime value = NULL) + { + // + value = NormalizeTime(value); + + // + int count = 0; + bool has = false; + + // + has = HasMomentums(); + if (has) + { + // + count = CountMomentums(); + for (int i = 0; i < count; i++) + { + momentums[i].To(value); + } + } + + // + has = HasBullishMomentums(); + if (has) + { + // + count = CountBullishMomentums(); + for (int i = 0; i < count; i++) + { + bullishMomentums[i].To(value); + } + } + + // + has = HasBearishMomentums(); + if (has) + { + // + count = CountBearishMomentums(); + for (int i = 0; i < count; i++) + { + bearishMomentums[i].To(value); + } + } + + // + has = HasRejections(); + if (has) + { + // + count = CountRejections(); + for (int i = 0; i < count; i++) + { + rejections[i].To(value); + } + } + + // + has = HasBullishRejections(); + if (has) + { + // + count = CountBullishRejections(); + for (int i = 0; i < count; i++) + { + bullishRejections[i].To(value); + } + } + + // + has = HasBearishRejections(); + if (has) + { + // + count = CountBearishRejections(); + for (int i = 0; i < count; i++) + { + bearishRejections[i].To(value); + } + } + + // + has = HasSupportZones(); + if (has) + { + // + count = CountSupportZones(); + for (int i = 0; i < count; i++) + { + supportZones[i].To(value); + } + } + + // + has = HasResistanceZones(); + if (has) + { + // + count = CountResistanceZones(); + for (int i = 0; i < count; i++) + { + resistanceZones[i].To(value); + } + } + + // + has = HasSupplyZones(); + if (has) + { + // + count = CountSupplyZones(); + for (int i = 0; i < count; i++) + { + supplyZones[i].To(value); + } + } + + // + has = HasDemandZones(); + if (has) + { + // + count = CountDemandZones(); + for (int i = 0; i < count; i++) + { + demandZones[i].To(value); + } + } + + // + has = HasOrderBlocks(); + if (has) + { + // + count = CountOrderBlocks(); + for (int i = 0; i < count; i++) + { + orderBlocks[i].To(value); + } + } + + // + has = HasBullishOrderBlocks(); + if (has) + { + // + count = CountBullishOrderBlocks(); + for (int i = 0; i < count; i++) + { + bullishOrderBlocks[i].To(value); + } + } + + // + has = HasBearishOrderBlocks(); + if (has) + { + // + count = CountBearishOrderBlocks(); + for (int i = 0; i < count; i++) + { + bearishOrderBlocks[i].To(value); + } + } + + // + has = HasFairValueGaps(); + if (has) + { + // + count = CountFairValueGaps(); + for (int i = 0; i < count; i++) + { + fairValueGaps[i].To(value); + } + } + + // + has = HasBullishFairValueGaps(); + if (has) + { + // + count = CountBullishFairValueGaps(); + for (int i = 0; i < count; i++) + { + bullishFairValueGaps[i].To(value); + } + } + + // + has = HasBearishFairValueGaps(); + if (has) + { + // + count = CountBearishFairValueGaps(); + for (int i = 0; i < count; i++) + { + bearishFairValueGaps[i].To(value); + } + } + + // + has = HasConsolidationZones(); + if (has) + { + // + count = CountConsolidationZones(); + for (int i = 0; i < count; i++) + { + consolidationZones[i].to = value; + } + } + + // + has = HasBullishConsolidationZones(); + if (has) + { + // + count = CountBullishConsolidationZones(); + for (int i = 0; i < count; i++) + { + bullishConsolidationZones[i].to = value; + } + } + + // + has = HasBearishConsolidationZones(); + if (has) + { + // + count = CountBearishConsolidationZones(); + for (int i = 0; i < count; i++) + { + bearishConsolidationZones[i].to = value; + } + } + + // + has = HasSpikes(); + if (has) + { + // + count = CountSpikes(); + for (int i = 0; i < count; i++) + { + spikes[i].to = value; + } + } + + // + has = HasBullishSpikes(); + if (has) + { + // + count = CountBullishSpikes(); + for (int i = 0; i < count; i++) + { + bullishSpikes[i].to = value; + } + } + + // + has = HasBearishSpikes(); + if (has) + { + // + count = CountBearishSpikes(); + for (int i = 0; i < count; i++) + { + bearishSpikes[i].to = value; + } + } + + // + has = HasSharps(); + if (has) + { + // + count = CountSharps(); + for (int i = 0; i < count; i++) + { + sharps[i].to = value; + } + } + + // + has = HasBullishSharps(); + if (has) + { + // + count = CountBullishSharps(); + for (int i = 0; i < count; i++) + { + bullishSharps[i].to = value; + } + } + + // + has = HasBearishSharps(); + if (has) + { + // + count = CountBearishSharps(); + for (int i = 0; i < count; i++) + { + bearishSharps[i].to = value; + } + } + } + + // + // Filter Zones ... + + // + // Support ... + int FilterSupportZones( + XCSupportZone *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasSupportZones(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + passedDir = X_DIRECTION_BULLISH; + count = CountSupportZones(); + for (int i = 0; i < count; i++) + { + // + XCSupportZone *iZone = supportZones[i]; + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // Resistance ... + int FilterResistanceZones( + XCResistanceZone *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasResistanceZones(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + passedDir = X_DIRECTION_BEARISH; + count = CountResistanceZones(); + for (int i = 0; i < count; i++) + { + // + XCResistanceZone *iZone = resistanceZones[i]; + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // Supply ... + int FilterSupplyZones( + XCSupplyZone *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasSupplyZones(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + passedDir = X_DIRECTION_BEARISH; + count = CountSupplyZones(); + for (int i = 0; i < count; i++) + { + // + XCSupplyZone *iZone = supplyZones[i]; + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // Demand ... + int FilterDemandZones( + XCDemandZone *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasDemandZones(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + passedDir = X_DIRECTION_BULLISH; + count = CountDemandZones(); + for (int i = 0; i < count; i++) + { + // + XCDemandZone *iZone = demandZones[i]; + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // OrderBlock ... + int FilterOrderBlocks( + XCOrderBlock *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasOrderBlocks(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + count = CountOrderBlocks(); + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iZone = orderBlocks[i]; + passedDir = iZone.GetDirection(); + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // Bullish OrderBlock ... + int FilterBullishOrderBlocks( + XCOrderBlock *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasBullishOrderBlocks(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + passedDir = X_DIRECTION_BULLISH; + count = CountBullishOrderBlocks(); + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iZone = bullishOrderBlocks[i]; + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // Bearish OrderBlock ... + int FilterBearishOrderBlocks( + XCOrderBlock *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasBearishOrderBlocks(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + passedDir = X_DIRECTION_BEARISH; + count = CountBearishOrderBlocks(); + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iZone = bearishOrderBlocks[i]; + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // FairValueGap ... + int FilterFairValueGaps( + XCFVG *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasFairValueGaps(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + count = CountFairValueGaps(); + for (int i = 0; i < count; i++) + { + // + XCFVG *iZone = fairValueGaps[i]; + passedDir = iZone.GetDirection(); + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // Bullish FairValueGap ... + int FilterBullishFairValueGaps( + XCFVG *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasBullishFairValueGaps(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + passedDir = X_DIRECTION_BULLISH; + count = CountBullishFairValueGaps(); + for (int i = 0; i < count; i++) + { + // + XCFVG *iZone = bullishFairValueGaps[i]; + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // Bearish FairValueGap ... + int FilterBearishFairValueGaps( + XCFVG *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasBearishFairValueGaps(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + passedDir = X_DIRECTION_BEARISH; + count = CountBearishFairValueGaps(); + for (int i = 0; i < count; i++) + { + // + XCFVG *iZone = bearishFairValueGaps[i]; + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + void Filter( + XPOIState &dest, + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int count = 0; + bool has = false; + + // + dest.Clean(); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasChild(); + if (!has) + { + return; + } + + // + dest = this; + + // + // Support Zones ... + FilterSupportZones( + dest.supportZones, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + // Resistance Zones ... + FilterResistanceZones( + dest.resistanceZones, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + // Supply Zones ... + FilterSupplyZones( + dest.supplyZones, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + // Demand Zones ... + FilterDemandZones( + dest.demandZones, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + // OrderBlocks ... + FilterOrderBlocks( + dest.orderBlocks, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + // Bullish OrderBlocks ... + FilterBullishOrderBlocks( + dest.bullishOrderBlocks, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + // Bearish OrderBlocks ... + FilterBearishOrderBlocks( + dest.bearishOrderBlocks, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + // FairValueGaps ... + FilterFairValueGaps( + dest.fairValueGaps, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + // Bullish FairValueGaps ... + FilterBullishFairValueGaps( + dest.bullishFairValueGaps, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + // Bearish FairValueGaps ... + FilterBearishFairValueGaps( + dest.bearishFairValueGaps, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + } + + // +}; + +// +// Extensions Functions ... +// + +/** + * Get Oldest Index ... + * + * @param source: XSignalBox instance Reference Collection ... + * + * @return ( int ) + */ +int GetOldest( + XSignalBox &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XSignalBox selected; + for (int i = 0; i < count; i++) + { + // + XSignalBox iBox = source[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.fvg.IsValid() && + iBox.fvg.IsValid() + ? selected.fvg.from > iBox.fvg.from + : selected.fvg.IsValid() && + !iBox.fvg.IsValid() + ? selected.fvg.from > iBox.ob.from + : !selected.fvg.IsValid() && + iBox.fvg.IsValid() + ? selected.ob.from > iBox.fvg.from + : !selected.fvg.IsValid() && + !iBox.fvg.IsValid() + ? selected.ob.from > iBox.ob.from + : false; + if (canSet) + { + // + result = i; + selected = iBox; + } + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Get Youngest Index ... + * + * @param source: XSignalBox instance Reference Collection ... + * + * @return ( int ) + */ +int GetYoungest( + XSignalBox &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XSignalBox selected; + for (int i = 0; i < count; i++) + { + // + XSignalBox iBox = source[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.fvg.IsValid() && + iBox.fvg.IsValid() + ? selected.fvg.from < iBox.fvg.from + : selected.fvg.IsValid() && + !iBox.fvg.IsValid() + ? selected.fvg.from < iBox.ob.from + : !selected.fvg.IsValid() && + iBox.fvg.IsValid() + ? selected.ob.from < iBox.fvg.from + : !selected.fvg.IsValid() && + !iBox.fvg.IsValid() + ? selected.ob.from < iBox.ob.from + : false; + if (canSet) + { + // + result = i; + selected = iBox; + } + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Get Highest Index ... + * + * @param source: XSignalBox instance Reference Collection ... + * + * @return ( int ) + */ +int GetHighest( + XSignalBox &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XSignalBox selected; + for (int i = 0; i < count; i++) + { + // + XSignalBox iBox = source[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.fvg.IsValid() && + iBox.fvg.IsValid() + ? selected.fvg.upper < iBox.fvg.upper + : selected.fvg.IsValid() && + !iBox.fvg.IsValid() + ? selected.fvg.upper < iBox.ob.upper + : !selected.fvg.IsValid() && + iBox.fvg.IsValid() + ? selected.ob.upper < iBox.fvg.upper + : !selected.fvg.IsValid() && + !iBox.fvg.IsValid() + ? selected.ob.upper < iBox.ob.upper + : false; + if (canSet) + { + // + result = i; + selected = iBox; + } + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Get Lowest Index ... + * + * @param source: XSignalBox instance Reference Collection ... + * + * @return ( int ) + */ +int GetLowest( + XSignalBox &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XSignalBox selected; + for (int i = 0; i < count; i++) + { + // + XSignalBox iBox = source[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.fvg.IsValid() && + iBox.fvg.IsValid() + ? selected.fvg.lower > iBox.fvg.lower + : selected.fvg.IsValid() && + !iBox.fvg.IsValid() + ? selected.fvg.lower > iBox.ob.lower + : !selected.fvg.IsValid() && + iBox.fvg.IsValid() + ? selected.ob.lower > iBox.fvg.lower + : !selected.fvg.IsValid() && + !iBox.fvg.IsValid() + ? selected.ob.lower > iBox.ob.lower + : false; + if (canSet) + { + // + result = i; + selected = iBox; + } + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Find Index of a Signal Box on another ... + * + * @param index: int, index of exists ... + * @param item: XSignal Box ... + * @param items: XSignal Box Collection ... + * + * @return ( bool ) + */ +bool FindIndex( + int &index, + XSignalBox &item, + XSignalBox &items[] // +) +{ + // + bool result = false; + + // + index = -1; + int count = ArraySize(items); + + // + result = item.IsValid() && + HasChild(items); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + bool isSame = item.ob + .IsSameAs(items[i].ob); + if (isSame) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; +} + +/** + * Find Index of a Signal Box on another ... + * + * @param index: int, index of exists ... + * @param item: XSignal Box ... + * @param items: XSignal Box Collection ... + * + * @return ( bool ) + */ +bool FindIndex( + int &index, + XBoxZone &item, + XSignalBox &items[] // +) +{ + // + bool result = false; + + // + index = -1; + int count = ArraySize(items); + + // + result = item.IsValid() && + HasChild(items); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + bool isSame = item.IsSameAs(items[i].ob); + if (isSame) + { + // + index = i; + break; + } + + // + isSame = item.IsSameAs(items[i].fvg); + if (isSame) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; +} + +/** + * Add a Signal Box in a Collection if not Exists ... + * + * @param item: XSignal Box ... + * @param items: XSignal Box Collection ... + * + * @return ( bool ) + */ +bool AddIfNotExists( + XSignalBox &item, + XSignalBox &items[] // +) +{ + // + bool result = false; + + // + result = item.IsValid(); + if (!result) + { + return result; + } + + // + int idx = -1; + result = !FindIndex( + idx, + item, + items // + ); + if (!result) + { + return result; + } + + // + AddRef( + item, + items // + ); + + // + return result; +} + +// +// XPOI State Event Parsers ... + +// +// Swings ... + +// +bool HasNewSwing(ENUM_XPOI_EVENTS &events[]) +{ + return HasNewSwingLow(events) || + HasNewSwingHigh(events); +} + +// +bool HasNewSwingLow(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_SWING_LOW_DETECTED, + events // + ); +} + +// +bool HasNewSwingHigh(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_SWING_HIGH_DETECTED, + events // + ); +} + +// +// Momentums ... + +// +bool HasNewMomentum(ENUM_XPOI_EVENTS &events[]) +{ + return HasNewBullishMomentum(events) || + HasNewBearishMomentum(events); +} + +// +bool HasNewBullishMomentum(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_BULLISH_MOMENTUM_BAR_DETECTED, + events // + ); +} + +// +bool HasNewBearishMomentum(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_BEARISH_MOMENTUM_BAR_DETECTED, + events // + ); +} + +// +// Rejections ... + +// +bool HasNewRejection(ENUM_XPOI_EVENTS &events[]) +{ + return HasNewBullishRejection(events) || + HasNewBearishRejection(events); +} + +// +bool HasNewBullishRejection(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_BULLISH_REJECTION_BAR_DETECTED, + events // + ); +} + +// +bool HasNewBearishRejection(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_BEARISH_REJECTION_BAR_DETECTED, + events // + ); +} + +// +// Support / Resistance Zones ... + +// +bool HasNewSupportZone(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_SUPPORT_ZONE_DETECTED, + events // + ); +} + +// +bool HasNewResistanceZone(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_RESISTANCE_ZONE_DETECTED, + events // + ); +} + +// +// Supply / Demand Zones ... + +// +bool HasNewSupplyZone(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_SUPPLY_ZONE_DETECTED, + events // + ); +} + +// +bool HasNewDemandZone(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_DEMAND_ZONE_DETECTED, + events // + ); +} + +// +// Fair Value Gaps ... + +// +bool HasNewFairValueGap(ENUM_XPOI_EVENTS &events[]) +{ + return HasNewBullishFairValueGap(events) || + HasNewBearishFairValueGap(events); +} + +// +bool HasNewBullishFairValueGap(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_BULLISH_FVG_DETECTED, + events // + ); +} + +// +bool HasNewBearishFairValueGap(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_BEARISH_FVG_DETECTED, + events // + ); +} + +// +// Order Blocks ... + +// +bool HasNewOrderBlock(ENUM_XPOI_EVENTS &events[]) +{ + return HasNewBullishOrderBlock(events) || + HasNewBearishOrderBlock(events); +} + +// +bool HasNewBullishOrderBlock(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_BULLISH_ORDERBLOCK_DETECTED, + events // + ); +} + +// +bool HasNewBearishOrderBlock(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_BEARISH_ORDERBLOCK_DETECTED, + events // + ); +} + +// +// Spikes ... + +// +bool HasNewSpike(ENUM_XPOI_EVENTS &events[]) +{ + return HasNewBullishSpike(events) || + HasNewBearishSpike(events); +} + +// +bool HasNewBullishSpike(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_BULLISH_SPIKE_DETECTED, + events // + ); +} + +// +bool HasNewBearishSpike(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_BEARISH_SPIKE_DETECTED, + events // + ); +} + +// +// Sharps ... + +// +bool HasNewSharp(ENUM_XPOI_EVENTS &events[]) +{ + return HasNewBullishSharp(events) || + HasNewBearishSharp(events); +} + +// +bool HasNewBullishSharp(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_BULLISH_SHARP_DETECTED, + events // + ); +} + +// +bool HasNewBearishSharp(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_BEARISH_SHARP_DETECTED, + events // + ); +} + +// +// Pullbacks ... + +// +bool HasNewPullback(ENUM_XPOI_EVENTS &events[]) +{ + return HasNewBullishPullback(events) || + HasNewBearishPullback(events); +} + +// +bool HasNewBullishPullback(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_BULLISH_PULLBACK_DETECTED, + events // + ); +} + +// +bool HasNewBearishPullback(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_BEARISH_PULLBACK_DETECTED, + events // + ); +} + +// +// Consolidation Zones ... + +// +bool HasNewConsolidationZone(ENUM_XPOI_EVENTS &events[]) +{ + return HasNewBullishConsolidationZone(events) || + HasNewBearishConsolidationZone(events); +} + +// +bool HasNewBullishConsolidationZone(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_BULLISH_CONSOLIDATION_ZONE_DETECTED, + events // + ); +} + +// +bool HasNewBearishConsolidationZone(ENUM_XPOI_EVENTS &events[]) +{ + return Contains( + X_BEARISH_CONSOLIDATION_ZONE_DETECTED, + events // + ); +} diff --git a/BKPS/14040316/Libraries/x-saherelm.x-trade.lib.mq5 b/BKPS/14040316/Libraries/x-saherelm.x-trade.lib.mq5 new file mode 100644 index 0000000..f90862f --- /dev/null +++ b/BKPS/14040316/Libraries/x-saherelm.x-trade.lib.mq5 @@ -0,0 +1,5146 @@ +/////////////////////////////////////////////////////// +// +// 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 "../Libraries/x-saherelm.common.lib.mq5" +#include + +// +// 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 XEQPToken = "EQP"; + +// +string XSLTrailToken = "SLT"; + +// +string XActionToken = "A"; + +// +string XDirectionalToken = "D"; +string XINDirectionalToken = "IND"; + +// +string XRecoveryToken = "XRCV"; + +// +// 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 +}; + +// +string ToString(ENUM_X_ORDER_MODES value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_ORDER_MODE_MARKET: + result = "Market"; + break; + + // + case X_ORDER_MODE_LIMIT: + result = "Limit"; + break; + + // + case X_ORDER_MODE_STOP: + result = "Stop"; + break; + + // + case X_ORDER_MODE_STOP_LIMIT: + result = "StopLimit"; + break; + } + + // + return result; +} + +// +// 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_NOT_ALLOWED, // Not Allowed Trade Type + X_SIGNAL_EXECUTION_FAILED_NO_EQUITY, // No Equity for Trade + X_SIGNAL_EXECUTION_FAILED_PRICE_ERROR, // Price Error + X_SIGNAL_EXECUTION_FAILED_PREV_PROFIT_ERROR, // Prev Profit Error + X_SIGNAL_EXECUTION_FAILED_MAX_REACHED, // Max Allowed Positions Reached + X_SIGNAL_EXECUTION_FAILED_DELAY_NOT_PASSED, // Same Positions Delay Not Passed + X_SIGNAL_EXECUTION_FAILED_INVALID_PARAMS, // Invalid Params +}; + +// +enum ENUM_X_POSITION_TYPES +{ + X_POSITION_TYPE_NONE = 0, + X_POSITION_TYPE_ALL = 1, + X_POSITION_TYPE_LONG = 2, + X_POSITION_TYPE_SHORT = 3, +}; + +// +bool IsValid(ENUM_X_POSITION_TYPES value) +{ + return value != X_POSITION_TYPE_NONE; +} + +// +bool HasSpecifiedType(ENUM_X_POSITION_TYPES value) +{ + // + return value == X_POSITION_TYPE_LONG || + value == X_POSITION_TYPE_SHORT; +} + +// +string ToString(ENUM_X_POSITION_TYPES value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_POSITION_TYPE_ALL: + result = "All"; + break; + + // + case X_POSITION_TYPE_NONE: + result = "NONE"; + break; + + // + case X_POSITION_TYPE_SHORT: + result = "Short"; + break; + + // + case X_POSITION_TYPE_LONG: + result = "Long"; + break; + } + + // + return result; +} + +// +bool IsLong(ENUM_X_POSITION_TYPES value) +{ + return value == X_POSITION_TYPE_LONG; +} + +// +bool IsShort(ENUM_X_POSITION_TYPES value) +{ + return value == X_POSITION_TYPE_SHORT; +} + +// +bool ToPositionType( + ENUM_POSITION_TYPE &dest, + ENUM_X_POSITION_TYPES source // +) +{ + // + bool result = false; + + // + result = source == X_POSITION_TYPE_LONG || + source == X_POSITION_TYPE_SHORT; + if (!result) + { + return result; + } + + // + dest = + source == X_POSITION_TYPE_LONG + ? POSITION_TYPE_BUY + : POSITION_TYPE_SELL; + + // + return result; +} + +// +ENUM_X_POSITION_TYPES ToPositionType(ENUM_POSITION_TYPE value) +{ + return IsLong(value) + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_SHORT; +} + +// +ENUM_X_POSITION_TYPES OppositPositionType(ENUM_POSITION_TYPE type) +{ + // + ENUM_X_POSITION_TYPES result = X_POSITION_TYPE_NONE; + + // + bool isLong = IsLong(type); + bool isShort = IsShort(type); + + // + result = + // + isLong + ? X_POSITION_TYPE_SHORT + : isShort + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_NONE + // + ; + + // + return result; +} + +// +ENUM_X_DIRECTION ToDirection(ENUM_POSITION_TYPE value) +{ + // + ENUM_X_DIRECTION result = X_DIRECTION_NONE; + + // + result = IsLong(value) + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; +} + +// +ENUM_X_DIRECTION ToDirection(ENUM_X_POSITION_TYPES value) +{ + // + ENUM_X_DIRECTION result = X_DIRECTION_NONE; + + // + result = value == X_POSITION_TYPE_ALL + ? X_DIRECTION_ALL + : value == X_POSITION_TYPE_LONG + ? X_DIRECTION_BULLISH + : value == X_POSITION_TYPE_SHORT + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + return result; +} + +// +// Structs ... + +// +struct XRR +{ + // + double tps[]; + + // + double sl; + double entry; + + // + string prefix; + string symbol; + datetime time; + ENUM_TIMEFRAMES period; + + // + ENUM_X_POSITION_TYPES type; + + // + // Constructor ... + XRR() + { + Clean(); + } + + // + // Tools ... + + // + void Clean() + { + // + sl = 0; + entry = 0; + + // + time = NULL; + prefix = NULL; + period = NULL; + symbol = NULL; + + // + type = X_POSITION_TYPE_NONE; + + // + Clean(tps); + + // + ZeroMemory(this); + } + + // + bool Init( + string _symbol, + ENUM_TIMEFRAMES _period, + double _sl, + double _entry, + ENUM_X_POSITION_TYPES _type, + string _prefix = NULL // + ) + { + // + bool result = false; + + // + result = + _sl > 0 && + _entry > 0 && + IsValid(_symbol) && + IsValid(_period) && + _type != X_POSITION_TYPE_ALL && + _type != X_POSITION_TYPE_NONE && + (_type == X_POSITION_TYPE_LONG + ? _entry > _sl + : _entry < _sl); + if (!result) + { + return result; + } + + // + Default(); + + // + sl = _sl; + type = _type; + entry = _entry; + symbol = _symbol; + period = _period; + prefix = _prefix; + + // + time = TimeCurrent(); + + // + result = IsValid(); + + // + return result; + } + + // + void Default() + { + // + Add( + 1.0, + tps // + ); + Add( + 1.5, + tps // + ); + Add( + 2.0, + tps // + ); + Add( + 3.0, + tps // + ); + Add( + 4.0, + tps // + ); + Add( + 5.0, + tps // + ); + Add( + 6.0, + tps // + ); + } + + // + bool IsValid() + { + // + bool result = false; + + // + result = + sl > 0 && + entry > 0 && + IsValid(time) && + IsValid(symbol) && + IsValid(period) && + IsValidSize(ArraySize(tps)) && + type != X_POSITION_TYPE_ALL && + type != X_POSITION_TYPE_NONE && + (type == X_POSITION_TYPE_LONG + ? entry > 0 + : entry < sl); + + // + return result; + } + + // + string GetTag() + { + // + string result = NULL; + + // + if (!IsValid()) + { + // + result = GetTypeName(this); + return result; + } + + // + string sep = "_"; + + // + result = + GetTypeName(this) + sep + (IsValid(prefix) ? prefix + sep : "") + symbol + sep + ToString(period) + sep + ToFormatString(time) + sep + ToString(type); + + // + return result; + } +}; + +// +// Model a Target ... +struct XTarget +{ + // + // Props ... + bool doRF; // Do RF on Target + double target; // Target Price for Actions + double volumeMultiplier; // Volume Multiplier for Partial Close + + // + // Constructor ... + XTarget() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + target = 0; + doRF = false; + volumeMultiplier = 0; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = target > 0; + + // + return result; + } +}; + +// +// Get Lowest Target index ... +int GetLowest(XTarget &targets[]) +{ + // + int result = -1; + + // + if (!HasChild(targets)) + { + return result; + } + + // + XTarget iTarget; + int count = ArraySize(targets); + for (int i = 0; i < count; i++) + { + // + bool canSet = + !iTarget.IsValid() + ? true + : iTarget.target > targets[i].target; + if (canSet) + { + // + result = i; + iTarget = targets[i]; + } + } + + // + iTarget.Clean(); + + // + return result; +} + +// +// Get Highest Target index ... +int GetHighest(XTarget &targets[]) +{ + // + int result = -1; + + // + if (!HasChild(targets)) + { + return result; + } + + // + XTarget iTarget; + int count = ArraySize(targets); + for (int i = 0; i < count; i++) + { + // + bool canSet = + !iTarget.IsValid() + ? true + : iTarget.target < targets[i].target; + if (canSet) + { + // + result = i; + iTarget = targets[i]; + } + } + + // + iTarget.Clean(); + + // + return result; +} + +// +// Apply Sorting on Targets ... +void ApplySortOnTargets( + ENUM_X_DIRECTION forDir, // Target Sorting Direction ... + XTarget &targets[] // Targets to Apply Sorting ... +) +{ + // + bool has = HasChild(targets) && + HasDirection(forDir); + if (!has) + { + return; + } + + // + bool isBullish = IsBullish(forDir); + bool isBearish = IsBearish(forDir); + + // + XTarget tmp[]; + Copy( + targets, + tmp // + ); + Clean(targets); + while (HasChild(tmp)) + { + // + int idx = -1; + if (isBullish) + { + idx = GetLowest(tmp); + } + else if (isBearish) + { + idx = GetHighest(tmp); + } + + // + has = IsValidIndex(idx); + if (!has) + { + break; + } + + // + XTarget iTarget = tmp[idx]; + ArrayRemove( + tmp, + idx, + 1 // + ); + AddRef( + iTarget, + targets // + ); + } + + // + Clean(tmp); +} + +// +// 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; + + // + ZeroMemory(this); + } + + // + // 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; + } + + // + double GetPointsValue() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetPoints(symbol); + + // + return result; + } + + // + double GetProfitInPoint() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + double tickSize = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE); // Tick size + double tickValue = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE); // Tick value + double pointSize = SymbolInfoDouble(symbol, SYMBOL_POINT); // Point size + double pointValue = tickValue * pointSize / tickSize; // Point value + + // + result = profit / (volume * tickValue); + + // + 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; + } + + // + double GetRewardInPoint() + { + // + double result = 0; + + // + result = GetReward() / GetPoints(); + + // + return result; + } + + // + // Find Risk Reward Ratio ... + double GetRiskRewardRatio() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetReward() / GetRisk(); + + // + return result; + } + + // + // Calculate TP Levels ... + int CalculateTPLevels(double &tps[]) + { + + // + int result = 0; + + // + Clean(tps); + + // + bool isValid = IsValid(); + if (!isValid) + { + return result; + } + + // + double risk = GetRisk(); + int r2r = (int)GetRiskRewardRatio(); + bool isLong = IsLong(type); + for (int i = 0; i < r2r; i++) + { + // + double iValue = + isLong + ? entry + risk + (i * risk) + : entry - risk - (i * risk); + // + Add( + iValue, + tps // + ); + } + + // + result = ArraySize(tps); + + // + return result; + } + + // + // Calculate Reached TP Levels ... + void CalculateReahedTP( + double &reachedLevel, + double &reachedPrice // + ) + { + // + reachedLevel = -1; + reachedPrice = 0; + double tps[]; + bool isLong = IsLong(type); + double exitPrice = GetExit(); + int tpLevels = CalculateTPLevels(tps); + if (!IsValidSize(tpLevels) || exitPrice <= 0) + { + return; + } + + // + for (int i = 0; i < tpLevels - 1; i++) + { + // + double cTP = tps[i]; + double nTP = tps[i + 1]; + + // + bool isReached = + isLong + ? exitPrice > cTP && + exitPrice < nTP + : exitPrice < cTP && + exitPrice > nTP; + if (isReached) + { + // + reachedLevel = i + 1; + reachedPrice = cTP; + } + } + } + + // + // Calculate Touched Reward ... + double CalculateTouchedReward() + { + // + double result = 0.0; + + // + bool has = IsValid() && + profit > 0; + if (!has) + { + return result; + } + + // + double risk = MathAbs(entry - sl); + double currentReward = MathAbs(price - entry); + + // + result = currentReward / risk; + + // + 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_X_POSITION_TYPES 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 ... + + // + string conditions; // Signal Conditions ... + + // + // Additional ... + + // + // Traget ... + XTarget targets[]; // Provided Targets ... + int appliedTargetIDX; // Last Applied Target Index ... + bool ignoreEAVolume; // Ignore EA Volume ... + bool isTargetApplied; // Check if Target Applied or not ... + + // + // Constructor ... + XSignal() + { + Default(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + entry = 0; + volume = 0; + positionId = 0; + + // + time = NULL; + type = NULL; + mode = NULL; + symbol = NULL; + period = NULL; + comment = NULL; + provider = NULL; + conditions = NULL; + + // + Clean(targets); + appliedTargetIDX = -1; + ignoreEAVolume = false; + isTargetApplied = false; + + // + ZeroMemory(this); + } + + // + // Default Values ... + void Default() + { + // + entry = 0; + volume = 0; + positionId = 0; + + // + time = NULL; + type = NULL; + mode = NULL; + symbol = NULL; + period = NULL; + comment = NULL; + provider = NULL; + conditions = NULL; + + // + Clean(targets); + appliedTargetIDX = -1; + ignoreEAVolume = false; + isTargetApplied = false; + } + + // + // 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 // + ); + } + + // + // 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; + } + + // + string GetTag() + { + // + string result = NULL; + + // + result = "XSignal_" + + symbol + "_" + + ToString(period) + "_" + + ToString(type) + "_" + + ToString(sl) + "_" + + ToString(tp) + "_" + + ToString(entry); + + // + return result; + } + + // + // Retrieve String Representation of Signal ... + string ToString() + { + // + string result = NULL; + + // + result = + // + ToString("Symbol", symbol) + + ToString("Period", period) + + ToString("Provider", provider) + + ToString("Type", type) + + ToString("Mode", mode) + + ToString("Volume", volume) + + ToString("Entry", entry) + + ToString("TP", tp) + + ToString("SL", sl) + + ToString("Time", time) + + ToString("Comment", comment) + + // + "" + // + ; + + // + return result; + } + + // + bool IsSameAs(XSignal &item) + { + // + bool result = false; + + // + result = + // + IsValid() && + item.IsValid() && + // + tp == item.tp && + sl == item.sl && + mode == item.mode && + time == item.time && + type == item.type && + entry == item.entry && + symbol == item.symbol && + period == item.period && + provider == item.provider + // + ; + + // + return result; + } + + // + string GetMessage(string action = NULL) + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + result = ToString(type) + + " Signal" + + (!IsValid(action) + ? "" + : " " + action) + + " by: " + provider + + " on (" + symbol + ")" + + " in: " + ToString(period); + + // + return result; + } + + // + string GetFileName() + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + result = + // + symbol + "\\" + + ToString(type) + "\\" + + ToString(period) + "_" + + ToFormatString(time) + // + ; + + // + 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; + + // + ZeroMemory(this); + } + + // + // 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_X_POSITION_TYPES 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; + + // + ZeroMemory(this); + } + + // + // 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; + + // + ZeroMemory(this); + } + + // + // 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; + } +}; + +// +struct XSymbolPositions +{ + // + string symbol; + + // + double profit; + double volume; + + // + double longsProfit; + double longSupportsProfit; + + // + double shortsProfit; + double shortSupportsProfit; + + // + double longsVolume; + double longSupportsVolume; + + // + double shortsVolume; + double shortSupportsVolume; + + // + double requiredProfitForHedge; + + // + XPosition longs[]; + XPosition shorts[]; + XPosition supports[]; + XPosition positions[]; + XPosition longSupports[]; + XPosition shortSupports[]; + + // + bool forceHedge; + + // + XSymbolPositions() + { + Clean(); + } + + // + bool Update( + double mMinProfitPerTrade, + double mMinProfitPerVolumeFactor // + ) + { + // + bool result = false; + + // + bool hasChild = HasChild(); + if (!hasChild) + { + return result; + } + + // + XPosition _supports[]; + XPosition _positions[]; + + // + XPosition _tmp[]; + + // + Copy( + positions, + _tmp // + ); + + // + Clean(positions); + + // + int tmpsCount = ArraySize(_tmp); + for (int i = 0; i < tmpsCount; i++) + { + // + XPosition iPosition = _tmp[i]; + + // + bool isSupport = IsSupport(iPosition.comment); + if (!isSupport) + { + // + AddRef( + iPosition, + _positions // + ); + } + else + { + // + AddRef( + iPosition, + _supports // + ); + } + } + + // + Clean(_tmp); + + // + Copy( + _positions, + positions // + ); + Clean(_positions); + + // + // Extract Types ... + ExtractPositions( + positions, + longs, + shorts // + ); + + // + Copy( + _supports, + supports // + ); + Clean(_supports); + + // + // Extract Types ... + ExtractPositions( + supports, + longSupports, + shortSupports // + ); + + // + int numOfLongs = 0; + int numOfShorts = 0; + CountPositions( + positions, + numOfLongs, + longsProfit, + longsVolume, + numOfShorts, + shortsProfit, + shortsVolume // + ); + + // + numOfLongs = 0; + numOfShorts = 0; + CountPositions( + supports, + numOfLongs, + longSupportsProfit, + longSupportsVolume, + numOfShorts, + shortSupportsProfit, + shortSupportsVolume // + ); + + // + XPosition _allPositions[]; + Copy( + positions, + _allPositions, + false // + ); + Copy( + supports, + _allPositions, + false // + ); + + // + profit = longsProfit + shortsProfit + longSupportsProfit + shortSupportsProfit; + volume = longsVolume + shortsVolume + longSupportsVolume + shortSupportsVolume; + requiredProfitForHedge = SpecifiedCalculateRequiredProfitForHedge( + _allPositions, + mMinProfitPerTrade, + mMinProfitPerVolumeFactor // + ); + + // + Clean(_allPositions); + + // + result = true; + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + symbol = NULL; + forceHedge = false; + + // + profit = 0; + longsProfit = 0; + shortsProfit = 0; + + // + volume = 0; + longsVolume = 0; + shortsVolume = 0; + + // + requiredProfitForHedge = 0; + + // + Clean(longs); + Clean(shorts); + Clean(positions); + + // + ZeroMemory(this); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = IsValid(symbol); + + // + return result; + } + + // + // Has Child ... + bool HasChild() + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int count = Count(); + result = IsValidSize(count); + + // + return result; + } + + // + // Count ... + int Count() + { + return ArraySize(positions); + } + + // + int CountSupports() + { + return ArraySize(supports); + } + + // + int CountLongs() + { + return ArraySize(longs); + } + + // + int CountShorts() + { + return ArraySize(shorts); + } + + // + int CountLongSupports() + { + return ArraySize(longSupports); + } + + // + int CountShortSupports() + { + return ArraySize(shortSupports); + } + + // + int GetOldest( + XPosition &_oldest, // + ENUM_POSITION_TYPE _type // + ) + { + // + int result = -1; + + // + bool isLong = IsLong(_type); + + // + int count = + isLong + ? CountLongs() + : CountShorts(); + if (!IsValidSize(count)) + { + return result; + } + + // + if (isLong) + { + // + result = GetOldest( + _oldest, + longs // + ); + } + else + { + // + result = GetOldest( + _oldest, + shorts // + ); + } + + // + return result; + } + + // + int GetYoungest( + XPosition &_youngest, // + ENUM_POSITION_TYPE _type // + ) + { + // + int result = -1; + + // + bool isLong = IsLong(_type); + + // + int count = + isLong + ? CountLongs() + : CountShorts(); + if (!IsValidSize(count)) + { + return result; + } + + // + if (isLong) + { + // + result = GetYoungest( + _youngest, + longs // + ); + } + else + { + // + result = GetYoungest( + _youngest, + shorts // + ); + } + + // + return result; + } + + // + int GetMaxInProfit( + XPosition &_position, + ENUM_POSITION_TYPE _type // + ) + { + // + int result = -1; + + // + bool isLong = IsLong(_type); + + // + int count = + isLong + ? CountLongs() + : CountShorts(); + if (!IsValidSize(count)) + { + return result; + } + + // + if (isLong) + { + // + result = FindMaxProfitIndex( + longs // + ); + + // + if (IsValidIndex(result)) + { + _position = longs[result]; + } + } + else + { + // + result = FindMaxProfitIndex( + shorts // + ); + + // + if (IsValidIndex(result)) + { + _position = shorts[result]; + } + } + + // + return result; + } + + // + int GetMinInProfit( + XPosition &_position, + ENUM_POSITION_TYPE _type // + ) + { + // + int result = -1; + + // + bool isLong = IsLong(_type); + + // + int count = + isLong + ? CountLongs() + : CountShorts(); + if (!IsValidSize(count)) + { + return result; + } + + // + if (isLong) + { + // + result = FindMinProfitIndex( + longs // + ); + + // + if (IsValidIndex(result)) + { + _position = longs[result]; + } + } + else + { + // + result = FindMinProfitIndex( + shorts // + ); + + // + if (IsValidIndex(result)) + { + _position = shorts[result]; + } + } + + // + return result; + } + + // + int GetMaxInDrawdown( + XPosition &_position, + ENUM_POSITION_TYPE _type // + ) + { + // + int result = -1; + + // + bool isLong = IsLong(_type); + + // + int count = + isLong + ? CountLongs() + : CountShorts(); + if (!IsValidSize(count)) + { + return result; + } + + // + if (isLong) + { + // + result = FindMaxDrawdownIndex( + longs // + ); + + // + if (IsValidIndex(result)) + { + _position = longs[result]; + } + } + else + { + // + result = FindMaxDrawdownIndex( + shorts // + ); + + // + if (IsValidIndex(result)) + { + _position = shorts[result]; + } + } + + // + return result; + } + + // + int GetMinInDrawdown( + XPosition &_position, + ENUM_POSITION_TYPE _type // + ) + { + // + int result = -1; + + // + bool isLong = IsLong(_type); + + // + int count = + isLong + ? CountLongs() + : CountShorts(); + if (!IsValidSize(count)) + { + return result; + } + + // + if (isLong) + { + // + result = FindMinDrawdownIndex( + longs // + ); + + // + if (IsValidIndex(result)) + { + _position = longs[result]; + } + } + else + { + // + result = FindMinDrawdownIndex( + shorts // + ); + + // + if (IsValidIndex(result)) + { + _position = shorts[result]; + } + } + + // + return result; + } + + // +}; + +// +// TypeDefs ... + +// +typedef void (*TOnSignal)(XSignal &signal); + +// +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); + +// +typedef void (*TOnForceClose)( + const ulong ticket, + const XPosition &position, + const string comment // +); + +// +typedef void (*TOnPartialClose)( + const ulong ticket, + const double profit, + const string comment // +); + +// +typedef void (*TOnModify)( + const ulong ticket, + const double profit, + const string comment // +); + +// +// Classes ... + +// +// 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; +} + +// +int FindMaxProfitIndex( + XPosition &positions[] // Position Collection +) +{ + // + int result = -1; + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + double max = 0; + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + if (iPosition.profit <= 0) + { + continue; + } + + // + if (max == 0 || + max < iPosition.profit) + { + // + result = i; + max = iPosition.profit; + } + } + + // + return result; +} + +// +int FindMinProfitIndex( + XPosition &positions[] // Position Collection +) +{ + // + int result = -1; + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + double min = 0; + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + if (iPosition.profit <= 0) + { + continue; + } + + // + if (min == 0 || + min > iPosition.profit) + { + // + result = i; + min = iPosition.profit; + } + } + + // + return result; +} + +// +int ExtractInProfitPositions( + XPosition &positions[], // Position Collection + XPosition &inProfits[] // Result +) +{ + // + int result = 0; + + // + Clean(inProfits); + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + if (iPosition.profit > 0) + { + // + AddRef( + iPosition, + inProfits // + ); + } + } + + // + result = ArraySize(inProfits); + + // + return result; +} + +// +int FindMaxDrawdownIndex( + XPosition &positions[] // Position Collection +) +{ + // + int result = -1; + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + double max = 0; + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + if (iPosition.profit >= 0) + { + continue; + } + + // + if (max == 0 || + MathAbs(max) < MathAbs(iPosition.profit)) + { + // + result = i; + max = iPosition.profit; + } + } + + // + return result; +} + +// +int FindMinDrawdownIndex( + XPosition &positions[] // Position Collection +) +{ + // + int result = -1; + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + double min = 0; + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + if (iPosition.profit >= 0) + { + continue; + } + + // + if (min == 0 || + min > iPosition.profit) + { + // + result = i; + min = iPosition.profit; + } + } + + // + return result; +} + +// +int ExtractInDrawdownPositions( + XPosition &positions[], // Position Collection + XPosition &inDradowns[] // Result +) +{ + // + int result = 0; + + // + Clean(inDradowns); + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + if (iPosition.profit < 0) + { + // + AddRef( + iPosition, + inDradowns // + ); + } + } + + // + result = ArraySize(inDradowns); + + // + 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 + // +) +{ + // + bool result = type == item.type; + + // + return result; +} +template +bool IsTypeFilterPassed( + ENUM_X_POSITION_TYPES type, + T &item + // +) +{ + // + bool result = type == NULL || type == X_POSITION_TYPE_ALL + ? true + : ((type == X_POSITION_TYPE_LONG && ((int)item.type == (int)POSITION_TYPE_BUY || (int)item.type == (int)ORDER_TYPE_BUY)) || + (type == X_POSITION_TYPE_SHORT && ((int)item.type == (int)POSITION_TYPE_SELL || (int)item.type == (int)ORDER_TYPE_SELL))); + + // + return result; +} +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; +} + +// + +// +// +// 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; +} + +// +int FindCoverageDrawdownPosition( + XPosition &position, // In Drawdown Position + XPosition &inProfits[], // In Profit Positions + XPosition &coverage[], // Coverage Positons + double mMinProfitPerTrade, + double mMinProfitPerVolumeFactor // +) +{ + // + int result = 0; + + // + Clean(coverage); + + // + if (!position.IsValid() || position.profit >= 0) + { + return result; + } + + // + int inProfitsCount = ArraySize(inProfits); + if (!IsValidSize(inProfitsCount)) + { + return result; + } + + // + // Copy in Profits to TMP ... + XPosition tmp[]; + Copy( + inProfits, + tmp // + ); + + // + bool isCoverPassed = false; + while (!isCoverPassed || ArraySize(tmp) > 0) + { + // + XPosition max; + int idx = FindMaxProfitIndex(tmp); + if (idx >= 0) + { + // + if (tmp[idx].profit > 0) + { + AddRef( + tmp[idx], + coverage // + ); + + // + ArrayRemove( + tmp, + idx, + 1 // + ); + } + } + + // + // Check Cover Passed ... + XPosition tmpPositions[]; + Copy( + coverage, + tmpPositions // + ); + AddRef( + position, + tmpPositions // + ); + + // + double profits = SpecifiedCalculatePositionsProfit(tmpPositions); + double requiredProfit = SpecifiedCalculateRequiredProfitForHedge( + tmpPositions, + mMinProfitPerTrade, + mMinProfitPerVolumeFactor // + ); + isCoverPassed = profits >= requiredProfit; + if (isCoverPassed) + { + break; + } + + // + if (!isCoverPassed && ArraySize(tmp) == 0) + { + break; + } + } + + // + result = ArraySize(coverage); + + // + return result; +} + +// +// Extract a Collection of Positions SL ... +int ExtractSLs( + XPosition &positions[], + double &sls[] // +) +{ + // + int result = 0; + + // + Clean(sls); + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + if (iPosition.sl > 0) + { + // + Add( + iPosition.sl, + sls // + ); + } + } + + // + result = ArraySize(sls); + + // + return result; +} + +// +// Extract a Colletion of Positions TP ... +int ExtractTPs( + XPosition &positions[], + double &tps[] // +) +{ + // + int result = 0; + + // + Clean(tps); + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + if (iPosition.tp > 0) + { + // + Add( + iPosition.tp, + tps // + ); + } + } + + // + result = ArraySize(tps); + + // + 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_NOT_ALLOWED: + result = "not 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_PREV_PROFIT_ERROR: + result = "Previous Position Profit not Passed for Accept Next"; + break; + + // + case X_SIGNAL_EXECUTION_FAILED_MAX_REACHED: + result = "Max Allowed Positions Reached"; + break; + + // + case X_SIGNAL_EXECUTION_FAILED_DELAY_NOT_PASSED: + result = "Min Delay Between to Signal not Passed"; + 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; +} +ENUM_ORDER_TYPE ToOrderType(ENUM_X_POSITION_TYPES value) +{ + // + ENUM_POSITION_TYPE mType = + value == X_POSITION_TYPE_SHORT + ? POSITION_TYPE_SELL + : POSITION_TYPE_BUY; + + // + bool isLong = IsLong(mType); + + // + 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 + // + ); +} + +// +// Extract Support ... +template +int ExtractSupports( + T &source[], + T &dest[] // Result ... +) +{ + // + int result = 0; + + // + Clean(dest); + + // + int sourceCount = ArraySize(source); + if (!IsValidSize(sourceCount)) + { + return result; + } + + // + for (int i = 0; i < sourceCount; i++) + { + // + T iSource = source[i]; + + // + ulong isSupport = ExtractSupportedTicket(iSource.comment) > 0; + ulong iEQMSupport = ExtractEQMSupportedTicket(iSource.comment) > 0; + if (isSupport || iEQMSupport) + { + // + AddRef( + iSource, + dest // + ); + } + } + + // + result = ArraySize(dest); + + // + return result; +} + +// +// 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 + // + ); +} + +// +bool IsSupport(string value) +{ + // + bool result = false; + + // + bool isSupport = ExtractSupportedTicket(value) > 0; + bool isEQMSupport = ExtractEQMSupportedTicket(value) > 0; + + // + result = + // + isSupport + // + || + // + isEQMSupport + // + ; + + // + return result; +} + +// +ulong ExtractParentTicket(string value) +{ + // + ulong result = 0; + + // + if (!IsSupport(value)) + { + return result; + } + + // + result = ExtractSupportedTicket(value); + if (result > 0) + { + return result; + } + + // + result = ExtractEQMSupportedTicket(value); + + // + return result; +} + +// +// XRecovery ... + +// +string GenerateRecoveryTag(ulong ticket) +{ + // + return Surround( + XRecoveryToken, + ticket // + ); +} + +// +ulong ExtractRecoveredTicket(string value) +{ + // + return ParseLongSurrounded( + value, + XRecoveryToken // + ); +} + +// +// Extract Recoveries ... +template +int ExtractRecoveries( + T &source[], + T &dest[] // Result ... +) +{ + // + int result = 0; + + // + Clean(dest); + + // + int sourceCount = ArraySize(source); + if (!IsValidSize(sourceCount)) + { + return result; + } + + // + for (int i = 0; i < sourceCount; i++) + { + // + T iSource = source[i]; + + // + ulong isRecovery = ExtractRecoveredTicket(iSource.comment) > 0; + if (isRecovery) + { + // + AddRef( + iSource, + dest // + ); + } + } + + // + result = ArraySize(dest); + + // + return result; +} + +// +// Extract Specified Position's Recoveries ... +int ExtractRecoveries( + ulong ticket, + XPosition &source[], + XPosition &dest[] // Result ... +) +{ + // + int result = 0; + + // + Clean(dest); + + // + int sourceCount = ArraySize(source); + if (!IsValidSize(sourceCount)) + { + return result; + } + + // + for (int i = 0; i < sourceCount; i++) + { + // + XPosition iSource = source[i]; + + // + ulong parentTicket = ExtractRecoveredTicket(iSource.comment); + bool isRecovery = parentTicket > 0; + if (isRecovery && parentTicket == ticket) + { + // + AddRef( + iSource, + dest // + ); + } + } + + // + result = ArraySize(dest); + + // + return result; +} + +// +// 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; +} + +// +// 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; + } + } +} + +// +// Extract Positions based On Type ... +void ExtractPositions( + XPosition &positions[], + XPosition &longs[], + XPosition &shorts[] // +) +{ + // + int count = ArraySize(positions); + if (!IsValidSize(count)) + { + return; + } + + // + Clean(longs); + Clean(shorts); + + // + for (int i = 0; i < count; i++) + { + // + XPosition iPosition = positions[i]; + + // + bool isLong = IsLong(iPosition.type); + if (isLong) + { + AddRef( + iPosition, + longs // + ); + } + else + { + AddRef( + iPosition, + shorts // + ); + } + } +} + +// +int FindSymbolIndex( + string mSymbol, + XSymbolPositions &mItems[] // +) +{ + // + int result = -1; + + // + if (!IsValid(mSymbol)) + { + return result; + } + + // + int count = ArraySize(mItems); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XSymbolPositions iItem = mItems[i]; + + // + if (iItem.symbol == mSymbol) + { + // + result = i; + break; + } + } + + // + return result; +} + +// +int ExtractSymbolPositions( + XPosition &positions[], + XSymbolPositions &items[], // Holds Result + double mMinProfitPerTrade, + double mMinProfitPerVolumeFactor // +) +{ + // + int result = 0; + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + Clean(items); + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + if (!iPosition.IsValid()) + { + continue; + } + + // + int itemIDX = FindSymbolIndex( + iPosition.symbol, + items // + ); + if (!IsValidIndex(itemIDX)) + { + // + // Add New One ... + XSymbolPositions item; + item.symbol = iPosition.symbol; + + // + AddRef( + item, + items // + ); + itemIDX = FindSymbolIndex(iPosition.symbol, items); + } + + // + AddRef( + iPosition, + items[itemIDX].positions // + ); + } + + // + result = ArraySize(items); + if (IsValidSize(result)) + { + // + for (int i = 0; i < result; i++) + { + // + items[i].Update( + mMinProfitPerTrade, + mMinProfitPerVolumeFactor // + ); + } + } + + // + return result; +} + +// +// Apply a Collection of Targets +// on Specified Signal ... +void ApplyTargetsOnSignal( + ENUM_X_DIRECTION sortingDir, // Target Sorting Direction ... + XTarget &targets[], // Required Targets ... + XSignal &signal // Destination Signal ... +) +{ + // + bool has = + HasChild(targets) && + HasDirection(sortingDir); + if (!has) + { + return; + } + + // + // Sort Targets ... + ApplySortOnTargets( + sortingDir, + targets // + ); + + // + Copy( + targets, + signal.targets // + ); +} + +// \ No newline at end of file diff --git a/BKPS/14040316/XCATBEA/Classes/xcatbea.expert.class.mq5 b/BKPS/14040316/XCATBEA/Classes/xcatbea.expert.class.mq5 new file mode 100644 index 0000000..ac4e0f7 --- /dev/null +++ b/BKPS/14040316/XCATBEA/Classes/xcatbea.expert.class.mq5 @@ -0,0 +1,2956 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCXCATBEAExpert ... +// Description: XCATB Expert Class ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XCATB Expert Class" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-guard.class.mq5" +#include "../../Classes/x-saherelm.x-trade.class.mq5" +#include "../../Classes/x-saherelm.x-volume.class.mq5" +#include "../Classes/xcatbea.signaller.class.mq5" +#include "../Classes/xcatbea.x-trade.manager.class.mq5" + +// +// Definitions ... +#define XCATBEA_INPUTS_PREFIX "X121XCATBEA" + +// +// Implementation ... + +// +class XCXCATBEASignallerInputParser : public XCBase +{ + // + // Public ... + public: + // + + // + // Constructor(s) ... + XCXCATBEASignallerInputParser( + XCAlert *_alert // + ) + { + // + alert = _alert; + + // + // Instantiate Data Collector ... + collector = new XCDataCollector(); + + // + // Generate Path and Attached to Data Collector ... + // string mPath = alert.GetPrefix(); + collector.Path(""); + } + + // + // Deconstructor ... + ~XCXCATBEASignallerInputParser() + { + // + delete collector; + ZeroMemory(collector); + } + + // + // Tools and Actions ... + + /** + * Retrieve Specified Symbol / Period Signaller Inputs ... + * + * @param symbol: string, Specified Signaller Symbol ... + * @param period: ENUM_TIMEFRAMES member, Specified Signaller Period ... + * + * @return ( bool ) + */ + string GetFileName( + string symbol, + ENUM_TIMEFRAMES period // + ) + { + // + string result = NULL; + + // + // Validate Args ... + if (!IsValid(symbol) || + !IsValid(period)) + { + return result; + } + + // + result = XCATBEA_INPUTS_PREFIX + "_" + symbol + "_" + ToString(period); + result = collector.GetFilePath(result); + + // + return result; + } + + /** + * Check Specified Symbol / Period Signaller Inputs File Exists ... + * + * @param symbol: string, Specified Signaller Symbol ... + * @param period: ENUM_TIMEFRAMES member, Specified Signaller Period ... + * + * @return ( bool ) + */ + bool IsSignallerInputsFileExists( + string symbol, + ENUM_TIMEFRAMES period // + ) + { + // + bool result = false; + + // + string fileName = GetFileName( + symbol, + period // + ); + result = IsValid(fileName); + if (!result) + { + return result; + } + + // + result = collector.IsExists(fileName); + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Parse Specified Symbol / Period Signaller Inputs file ... + * + * @param inputs: XCATBEASignallerInputs instance reference, To Fill Loaded Configs ... + * @param symbol: string, Specified Signaller Symbol ... + * @param period: ENUM_TIMEFRAMES member, Specified Signaller Period ... + * + * @return ( bool ) + */ + bool ParseSignallerInputs( + XCATBEASignallerInputs &inputs, + string symbol, + ENUM_TIMEFRAMES period // + ) + { + // + bool result = false; + + // + // Validate Args ... + result = + IsValid(symbol) && + IsValid(period); + if (!result) + { + return result; + } + + // + inputs.symbol = symbol; + inputs.period = period; + + // + // Prepare File Name and Check File Exists ... + string fileName = GetFileName(symbol, period); + result = collector.IsExists(fileName); + if (!result) + { + return result; + } + + // + // Read Content ... + string content[]; + result = collector.Read(fileName, content); + if (!result) + { + return result; + } + + // + // Try to Parse Content ... + result = HasChild(content); + if (result) + { + // + int count = ArraySize(content); + for (int i = 0; i < count; i++) + { + // + string iLine = content[i]; + + // + Parse(iLine, inputs); + } + } + + // + return result; + } + + // + // Protected ... + protected: + // + + // + // Private ... + private: + // + // Props ... + XCAlert *alert; + XCDataCollector *collector; + + /** + * Parse Condition and Attached to related Properties if Exists ... + */ + void Parse( + string line, + XCATBEASignallerInputs &inputs // + ) + { + // + string parts[]; + bool has = false; + int partsCount = 0; + + // + // Validations ... + + // + // eaForceHasSwing ... + has = Contains( + "eaForceHasSwing", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.validations.forceHasSwing = has; + } + } + } + + // + // eaForceOBBarType ... + has = Contains( + "eaForceOBBarType", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.validations.forceOBBarType = has; + } + } + } + + // + // eaForceFVGBarType ... + has = Contains( + "eaForceFVGBarType", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.validations.forceFVGBarType = has; + } + } + } + + // + // eaForceHasFLiquidity ... + has = Contains( + "eaForceHasFLiquidity", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.validations.forceHasFLiquidity = has; + } + } + } + + // + // eaForceHasRLiquidity ... + has = Contains( + "eaForceHasRLiquidity", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.validations.forceHasRLiquidity = has; + } + } + } + + // + // eaValidateGapSequence ... + has = Contains( + "eaValidateGapSequence", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.validations.validateGapSequence = has; + } + } + } + + // + // eaValidateBlockEdgeBreakout ... + has = Contains( + "eaValidateBlockEdgeBreakout", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.validations.validateBlockEdgeBreakout = has; + } + } + } + + // + // Filters ... + + // + // eaFilterBasedOnKI ... + has = Contains( + "eaFilterBasedOnKI", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.filterBasedOnKI = has; + } + } + } + + // + // eaFilterBasedOnPV ... + has = Contains( + "eaFilterBasedOnPV", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.filterBasedOnPV = has; + } + } + } + + // + // eaFilterBasedOnSar ... + has = Contains( + "eaFilterBasedOnSar", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.filterBasedOnSar = has; + } + } + } + + // + // eaForceSarSwitched ... + has = Contains( + "eaForceSarSwitched", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.forceSarSwitched = has; + } + } + } + + // + // eaForceSarOnBothSide ... + has = Contains( + "eaForceSarOnBothSide", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.forceSarOnBothSide = has; + } + } + } + + // + // eaForceSarHasBreakout ... + has = Contains( + "eaForceSarHasBreakout", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.forceSarHasBreakout = has; + } + } + } + + // + // eaForceSarHasReversalSide ... + has = Contains( + "eaForceSarHasReversalSide", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.forceSarHasReversalSide = has; + } + } + } + + // + // eaFilterBasedOnRSI ... + has = Contains( + "eaFilterBasedOnRSI", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.filterBasedOnRSI = has; + } + } + } + + // + // eaForceHasRSITrending ... + has = Contains( + "eaForceHasRSITrending", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.forceHasRSITrending = has; + } + } + } + + // + // eaForceHasRSIVPattern ... + has = Contains( + "eaForceHasRSIVPattern", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.forceHasRSIVPattern = has; + } + } + } + + // + // eaForceHasRSICrossing ... + has = Contains( + "eaForceHasRSICrossing", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.forceHasRSICrossing = has; + } + } + } + + // + // eaFilterBasedOnADX ... + has = Contains( + "eaFilterBasedOnADX", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.filterBasedOnADX = has; + } + } + } + + // + // eaForceHasADXTrending ... + has = Contains( + "eaForceHasADXTrending", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.forceHasADXTrending = has; + } + } + } + + // + // eaForceHasADXCrossing ... + has = Contains( + "eaForceHasADXCrossing", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.forceHasADXCrossing = has; + } + } + } + + // + // eaFilterBasedOnATR ... + has = Contains( + "eaFilterBasedOnATR", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.filterBasedOnATR = has; + } + } + } + + // + // eaForceHasATRTrending ... + has = Contains( + "eaForceHasATRTrending", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.forceHasATRTrending = has; + } + } + } + + // + // eaForceHasATRBreakout ... + has = Contains( + "eaForceHasATRBreakout", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.forceHasATRBreakout = has; + } + } + } + + // + // eaFilterBasedOnTrend ... + has = Contains( + "eaFilterBasedOnTrend", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.filterBasedOnTrend = has; + } + } + } + + // + // eaForceHasTrendDir ... + has = Contains( + "eaForceHasTrendDir", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.forceHasTrendDir = has; + } + } + } + + // + // eaForceHasTrendPlace ... + has = Contains( + "eaForceHasTrendPlace", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.forceHasTrendPlace = has; + } + } + } + + // + // eaForceHasTrendChange ... + has = Contains( + "eaForceHasTrendChange", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.forceHasTrendChange = has; + } + } + } + + // + // eaForceHasTrendTrending ... + has = Contains( + "eaForceHasTrendTrending", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.forceHasTrendTrending = has; + } + } + } + + // + // eaForceHasTrendRejection ... + has = Contains( + "eaForceHasTrendRejection", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.forceHasTrendRejection = has; + } + } + } + + // + // eaForceHasTrendLineInside ... + has = Contains( + "eaForceHasTrendLineInside", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.forceHasTrendLineInside = has; + } + } + } + + // + // eaForceHasTrendDirOnBothSide ... + has = Contains( + "eaForceHasTrendDirOnBothSide", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.forceHasTrendDirOnBothSide = has; + } + } + } + + // + // eaFilterBasedOnDelta ... + has = Contains( + "eaFilterBasedOnDelta", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.filterBasedOnDelta = has; + } + } + } + + // + // eaFilterBasedOnVolume ... + has = Contains( + "eaFilterBasedOnVolume", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.filterBasedOnVolume = has; + } + } + } + + // + // eaFilterBasedOnSignalBar ... + has = Contains( + "eaFilterBasedOnSignalBar", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.filterBasedOnSignalBar = has; + } + } + } + + // + // eaFilterBasedOnHKSignalBar ... + has = Contains( + "eaFilterBasedOnHKSignalBar", + line, + false // + ); + if (has) + { + // + // Split Content ... + partsCount = SplitContent( + parts, + line, + ":" // + ); + has = partsCount == 2; + if (has) + { + // + has = ToBoolean(parts[1]); + if (has) + { + inputs.filters.filterBasedOnHKSignalBar = has; + } + } + } + + // + } + + // +}; + +// +class XCXCATBEAExpert : public XCBase +{ + // + // public ... + public: + // + // Props ... + + // + // Common ... + long eaMagicNumber; // Magic Number + int eaSlippage; // Slippgae + string eaLogSuffix; // Log Suffix + + // + // Detector ... + + // + // Validating ... + bool eaForceHasSwing; // Force Block to Has Propper Swing + bool eaForceOBBarType; // Force Order Block to Has InDirectional Bars + int eaMinRequiredOBBar; // Min Required OB Bar + bool eaForceFVGBarType; // Force Fair Value Gaps Bars Type + int eaLiquidityLoopback; // Liquidity Detection Loopback + double eaMaxAllowedRange; // Max Allowed Order Block Range + double eaMinAllowedRange; // Min Allowed Order Block Range + bool eaForceHasFLiquidity; // Force Order Block To Has Reversal Liquidity + bool eaForceHasRLiquidity; // Force Order Block to Has Following Liquidity + bool eaValidateGapSequence; // Validate Fair Value Gaps Bar Sequences + int eaMinAllowedBlockLength; // Min Allowed Block Length + bool eaValidateBlockEdgeBreakout; // Validate Order Block Edge Breakeout + + // + // Filtering ... + bool eaFilterBasedOnKI; // Filter Based On KI Flats + bool eaFilterBasedOnPV; // Filter Based On PV + int eaBosLoopback; // PV Based Filtering BOS Lookup + bool eaFilterBasedOnSar; // Filter Based On SAR + bool eaForceSarSwitched; // SAR Switched on Sides for Filtering + bool eaForceSarOnBothSide; // SAR Check on Both Sides for Filtering + bool eaForceSarHasBreakout; // SAR Must Breakout + bool eaForceSarHasReversalSide; // SAR Must Has Reversal Direction + bool eaFilterBasedOnRSI; // Filter Based On RSI + bool eaForceHasRSITrending; // RSI Must Has Trending + bool eaForceHasRSIVPattern; // RSI Must Has Pattern + bool eaForceHasRSICrossing; // RSI Must Has Crossing Levels + bool eaFilterBasedOnADX; // Filter Based On ADX + bool eaForceHasADXTrending; // ADX Must Has Trending + bool eaForceHasADXCrossing; // ADX Must Has Crossing +DI/-DI + bool eaFilterBasedOnATR; // Filter Based On ATR + bool eaForceHasATRTrending; // ATR Must Has Trending + bool eaForceHasATRBreakout; // ATR Must Has Breakout + bool eaFilterBasedOnTrend; // Filter Based On Trend + bool eaForceHasTrendDir; // TREND Must Has Following Direction + bool eaForceHasTrendPlace; // TREND Place Based Filtering + bool eaForceHasTrendChange; // TREND Change Filtering + bool eaForceHasTrendTrending; // TREND Must Has Trending + bool eaForceHasTrendRejection; // TREND Line Must Rejected + bool eaForceHasTrendLineInside; // TREND Line has Inside + bool eaForceHasTrendDirOnBothSide; // TREND Must Has Following Direction in Both Side + bool eaFilterBasedOnDelta; // Filter Based On Delta + bool eaFilterBasedOnVolume; // Filter Based On Volume + bool eaFilterBasedOnSignalBar; // Filter Based on Signal Bar + bool eaFilterBasedOnHKSignalBar; // Filter Based On HK Signal Bar + + // + // Signal ... + int eaSignalR2R; // Risk Reward Ratio + double eaSLATRMultiplier; // ATR Multiplier for SL + bool eaAllowSignallingBasedOnConditions; // Signalling Based on Market Conditions + bool eaAllowSignallingBasedOnTriggerBlocks; // Signalling Based on Trigger Blocks + bool eaAllowSignallingBasedOnTriggerBlocksInsideOther; // Signalling Based on Trigger Blocks Seccond inputs + bool eaSecondsTriggersSLUsingFirstTriggerBlock; // Use First Trigger Block for SL of Seconds Trigger Block Signalss + bool eaApplyValidateAndFilterOnSelectInsideOthers; // Select Trigger Blocks by Applying Validations and Filterss + bool eaAllowSignallingConditions1; // Allow Market Conditions Signaller to Using Sar Starter Signals + bool eaAllowSignallingConditions2; // Allow Market Conditions Signaller to Using Trend Starter Signals + bool eaAllowSignallingConditions3; // Allow Market Conditions Signaller to Using Delta Starter Signals + bool eaAllowSignallingConditions4; // Allow Market Conditions Signaller to Using Volume Starter Signals + bool eaAllowSignallingConditions5; // Allow Market Conditions Signaller to Using Signal Bar Starter Signals + bool eaAllowSignallingConditions6; // Allow Market Conditions Signaller to Using HK Signal Bar Starter Signals + + // + // Volume ... + ENUM_X_VOLUME_SELECT_TYPE eaVolumeSelect; // Volume Applying Type + double eaStaticVoluem; // Static Volume + double eaDynamicVolumeStepBalance; // Step of Balance for Increase Volume + double eaDynamicVolumeStepVolume; // Step of Volume Increasing + double eaConstantRiskBalance; // Constant Risk Balance per Trade + double eaConstantPercent; // Constant Percent of Balance Per Trade + double eaConstantBalance; // Constant Balance for Calculations + + // + // Management ... + string eaSymbols; // Allowed Trading Symbols + bool eaAllowGuards; // Allow Guards + bool eaAllowTrade; // Allow Trade on Signals + bool eaAllowLongs; // Allow Long Trades + bool eaAllowShorts; // Allow Short Trades + string eaSessions; // Active Sessions + ENUM_XCATBEA_TRADE_RESTRICTION_PERIOD eaRestrictionsPeriod; // Restrictions Period + int eaMaxAllowedTPs; // Max Allowed TP(s) in Restrictions Period + int eaMaxAllowedSLs; // Max Allowed SL(s) in Restrictions Period + int eaMaxAllowedTrades; // Max Allowed Trades in Restrictions Period + int eaMaxAllowedPositions; // Max Allowed Same Time Trades + double eaMaxAllowedSpread; // Max Allowed Spread For Trade + double eaMaxAllowedDrawdownFactor; // Max Allowed DrawDown for Trade + string eaCloseAllOpenTradesAt; // Close All Open Trades per Day At Specified Time + + // + // Alert ... + bool eaEnableAlerts; // Enable Alerts + bool eaSaveAlerts; // Save Alerts + bool eaLogAlerts; // Log Alerts + bool eaMailAlerts; // Mail Alerts + bool eaPushAlerts; // Push Alerts + bool eaTerminalAlerts; // Terminal Alerts + + // + // Time Report ... + bool eaReportNewMonths; // Report New Month + bool eaReportNewWeeks; // Report New Weeks + bool eaReportNewDays; // Report New Days + bool eaReportNewHours; // Report New Hours + bool eaReportTrades; // Report Trades + bool eaReportSignals; // Report Signals + bool eaReportProtector; // Report Protector Actions + bool eaReportRestrictions; // Report Restrictions + bool eaReportAfterTradesBalance; // Report Balance after a Trade Finished + + // + // Collector ... + bool eaSaveTrades; // Save Trades + bool eaSaveSignals; // Save Signals + bool eaSaveWins; // Save Winning Conditions + bool eaSaveLosts; // Save Lost Conditions + bool eaSaveRestrictions; // Save Restriction Reports + + // + // Requirements ... + + // + XCAlert *eaAlert; // EA Scope Alert Handler ... + XCTrade *eaTrade; // EA Scope Trade Handler ... + XCGuard *eaGuard; // EA Scope Guard Handler ... + XCVolume *eaVolume; // EA Scope Voluem Handler ... + XTimeTracker eaTimeTracker; // EA Scope Time Tracker ... + XCDataCollector *eaCollector; // EA Scope Data Collector ... + XCXCATBEASignaller *eaSignallers[]; // EA Signallers Collection ... + XCXCATBEATradeManager *eaTradeManager; // EA Scope Trade Manager ... + XCXCATBEASignallerInputParser *eaSignallerInputParser; // EA Scope Signaller Input Parser ... + + // + // Tools / Actions / Handlers ... + + // + // Trade Event Handlers ... + + // + void AddOnStopLossEventHandler(TOnStopLoss handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mStopLossEventHandlers + // + ); + } + + // + void AddOnTakeProfitEventHandler(TOnTakeProfit handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mTakeProfitEventHandlers + // + ); + } + + // + void AddOnDealsChangedEventHandler(TOnDealsChanged handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mDealsChangedEventHandlers + // + ); + } + + // + void AddOnOrdersChangedEventHandler(TOnOrdersChanged handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOrdersChangedEventHandlers + // + ); + } + + // + void AddOnModifyPositionEventHandler(TOnModify handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnModifyEventHandlers + // + ); + } + + // + void AddOnPositionsChangedEventHandler(TOnPositionsChanged handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mPositionsChangedEventHandlers + // + ); + } + + // + void AddOnTradeStateChangedEventHandler(TOnTradeStateChanged handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mTradeStateChangedEventHandlers + // + ); + } + + // + void AddOnForceClosePositionEventHandler(TOnForceClose handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnForceCloseEventHandlers + // + ); + } + + // + void AddOnPartialClosePositionEventHandler(TOnPartialClose handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnPartialCloseEventHandlers + // + ); + } + + // + // Validators ... + + /** + * Validate Inputs ... + * + * @return ( bool ) + */ + bool ValidateInputs() + { + // + bool result = false; + + // + // Implement all Inputs Validation ... + result = eaMagicNumber > 0 && + eaSignalR2R > 0; + + // + return result; + } + + // + // Expert Advisor Event Handlers ... + + /** + * Handle Initialization of Expert ... + * + * @return ( bool ) + */ + bool HandleOnInit() + { + // + bool result = false; + + // + // Validate Inputs ... + result = ValidateInputs(); + if (!result) + { + return result; + } + + // + bool has = false; + int count = -1; + + // + // Initialize Alert Handler ... + eaAlert = new XCAlert(); + eaAlert.SetPrefix(eaLogSuffix); + eaAlert.SetLogAlerts(eaLogAlerts); + eaAlert.SetMailAlerts(eaMailAlerts); + eaAlert.SetPushAlerts(eaPushAlerts); + eaAlert.SetSaveAlerts(eaSaveAlerts); + eaAlert.SetEnableAlerts(eaEnableAlerts); + eaAlert.SetTerminalAlerts(eaTerminalAlerts); + + // + // Initialize Volume Manager ... + eaVolume = new XCVolume(); + result = eaVolume.Init( + eaVolumeSelect, + eaStaticVoluem, + eaDynamicVolumeStepBalance, + eaDynamicVolumeStepVolume, + eaConstantRiskBalance, + eaConstantPercent, + eaConstantBalance // + ); + if (!result) + { + return result; + } + + // + // Initialize Trader ... + eaTrade = new XCTrade( + eaSlippage, + eaMagicNumber, + eaMaxAllowedSpread, + eaMaxAllowedPositions, + eaMaxAllowedDrawdownFactor // + ); + + // + // Trade Handler Attachments ... + + // + // Position Modifiy Event Handlers ... + count = ArraySize(mOnModifyEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnModifyPositionEventHandler(mOnModifyEventHandlers[i]); + } + } + + // + // Position Stop Loss Event Handlers ... + if (has) + { + // + count = ArraySize(mStopLossEventHandlers); + has = IsValidSize(count); + for (int i = 0; i < count; i++) + { + eaTrade.AddOnStopLossEventHandler(mStopLossEventHandlers[i]); + } + } + + // + // Position Take Profit Event Handlers ... + count = ArraySize(mTakeProfitEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnTakeProfitEventHandler(mTakeProfitEventHandlers[i]); + } + } + + // + // Position Force Close Event Handlers ... + count = ArraySize(mOnForceCloseEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnForceClosePositionEventHandler(mOnForceCloseEventHandlers[i]); + } + } + + // + // Deals Changed Event Handlers ... + count = ArraySize(mDealsChangedEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnDealsChangedEventHandler(mDealsChangedEventHandlers[i]); + } + } + + // + // Orders Changed Event Handlers ... + count = ArraySize(mOrdersChangedEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnOrdersChangedEventHandler(mOrdersChangedEventHandlers[i]); + } + } + + // + // Positions Changed Event Handlers ... + count = ArraySize(mPositionsChangedEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnPositionsChangedEventHandler(mPositionsChangedEventHandlers[i]); + } + } + // + // Trade Changed Event Handlers ... + count = ArraySize(mTradeStateChangedEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnTradeStateChangedEventHandler(mTradeStateChangedEventHandlers[i]); + } + } + // + // Postion Partially Close Event Handlers ... + count = ArraySize(mOnPartialCloseEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnPartialClosePositionEventHandler(mOnPartialCloseEventHandlers[i]); + } + } + + // + // Initialize Guard Handler ... + eaGuard = new XCGuard( + eaAlert, + eaTrade // + ); + + // + // Initialize Data Collector ... + eaCollector = new XCDataCollector(); + string mPath = eaAlert.GetPrefix() + "\\" + "Configs"; + eaCollector.Path(mPath); + + // + // Instantiating Signaller Input Parser ... + eaSignallerInputParser = new XCXCATBEASignallerInputParser(eaAlert); + + // + // Initialize Trae Manager ... + eaTradeManager = new XCXCATBEATradeManager( + eaAlert, + eaTrade // + ); + + // + eaTradeManager.SaveWins(eaSaveWins); + eaTradeManager.SaveLosts(eaSaveLosts); + eaTradeManager.SaveTrades(eaSaveTrades); + eaTradeManager.SaveSignals(eaSaveSignals); + eaTradeManager.SaveRestrictions(eaSaveRestrictions); + + // + // Enable Force Close At ... + eaTradeManager.SetForceCloseTradesAt(eaCloseAllOpenTradesAt); + + // + // Setting Trade Reports ... + eaTradeManager + .SetTradeReports( + eaReportTrades, + eaReportSignals, + eaReportProtector, + eaReportRestrictions, + eaReportAfterTradesBalance // + ); + + // + // Setting Trade Permissions ... + eaTradeManager + .SetTradePermissions( + eaAllowTrade, + eaAllowLongs, + eaAllowShorts // + ); + + // + // Setting Trade Restrictions ... + eaTradeManager + .SetTradeRestrictions( + eaRestrictionsPeriod, + eaMaxAllowedTPs, + eaMaxAllowedSLs, + eaMaxAllowedTrades // + ); + + // + // Parsing Symbols ... + + // + string symbols[]; + int symbolsCount = 0; + if (IsValid(eaSymbols)) + { + // + symbolsCount = SplitContent( + symbols, + eaSymbols, + "," // + ); + } + + // + // Adding Default Symbol, if eaSymbols not Filled ... + if (!HasChild(symbols)) + { + // + Add( + _Symbol, + symbols // + ); + + // + symbolsCount = ArraySize(symbols); + } + bool hasSymbols = HasChild(symbols); + + // + // Initializing Sessions ... + string sessions[]; + int sessionsCount = 0; + bool hasSession = IsValid(eaSessions); + if (hasSession) + { + // + // Extract Per Symbol Sessions ... + sessionsCount = SplitContent( + sessions, + eaSessions, + "," // + ); + + // + // Try to Extract Start and End Times Series ... + hasSession = IsValidSize(sessionsCount); + if (hasSession) + { + // + // Iterate Sessions ... + for (int i = 0; i < sessionsCount; i++) + { + // + // Ignore unused Cases and Extracts only Content ... + string iSessionDescriptorStr = ExtractString(sessions[i]); + bool isInited = IsValid(iSessionDescriptorStr); + if (isInited) + { + // + // Extract Session Descriptor Data ... + string parts[]; + int partsCount = SplitContent( + parts, + iSessionDescriptorStr, + "_" // + ); + isInited = IsValidSize(partsCount) && partsCount == 3; + if (isInited) + { + // + string iName = parts[0]; + string iStart = parts[1]; + string iEnd = parts[2]; + isInited = IsValid(iName) && + IsValid(iStart) && + IsValid(iEnd); + if (isInited) + { + // + // Set Active Session Per Symbols ... + if (hasSymbols) + { + // + for (int j = 0; j < symbolsCount; j++) + { + // + eaTradeManager + .SetTradeSession( + symbols[j], + iStart, + iEnd, + iName // + ); + } + } + } + } + } + } + } + } + + // + // Initialize Signallers ... + if (hasSymbols) + { + // + // Prepare Signaller Inputs ... + XCATBEASignallerInputs iSignallerInputs; + + // + // Common Configs ... + + // + // Provider Name ... + iSignallerInputs.period = _Period; + iSignallerInputs.allowDraws = true; + iSignallerInputs.provider = "XTRGB"; + iSignallerInputs.allowGuards = eaAllowGuards; + iSignallerInputs.riskToRewardRatio = eaSignalR2R; + iSignallerInputs.slATRMultiplier = eaSLATRMultiplier; + + // + // CATB Indicator ... + iSignallerInputs.catbInputs.Default(); + iSignallerInputs.catbInputs.Hide(); + + // + // Make Available all Requirement Buffers of XCATB indicator ... + iSignallerInputs.catbInputs.showPV = false; + iSignallerInputs.catbInputs.showKI = false; + iSignallerInputs.catbInputs.showSar = false; + iSignallerInputs.catbInputs.showTrend = false; + iSignallerInputs.catbInputs.showATRBand = false; + iSignallerInputs.catbInputs.showPVGolden = false; + + // + // Signalling Configurations ... + iSignallerInputs.signallerConfigs.allowSignallingBasedOnConditions = eaAllowSignallingBasedOnConditions; + iSignallerInputs.signallerConfigs.allowSignallingBasedOnTriggerBlocks = eaAllowSignallingBasedOnTriggerBlocks; + iSignallerInputs.signallerConfigs.secondsTriggersSLUsingFirstTriggerBlock = eaSecondsTriggersSLUsingFirstTriggerBlock; + iSignallerInputs.signallerConfigs.applyValidateAndFilterOnSelectInsideOthers = eaApplyValidateAndFilterOnSelectInsideOthers; + iSignallerInputs.signallerConfigs.allowSignallingBasedOnTriggerBlocksInsideOther = eaAllowSignallingBasedOnTriggerBlocksInsideOther; + iSignallerInputs.signallerConfigs.allowSignallingConditions1 = eaAllowSignallingConditions1; + iSignallerInputs.signallerConfigs.allowSignallingConditions2 = eaAllowSignallingConditions2; + iSignallerInputs.signallerConfigs.allowSignallingConditions3 = eaAllowSignallingConditions3; + iSignallerInputs.signallerConfigs.allowSignallingConditions4 = eaAllowSignallingConditions4; + iSignallerInputs.signallerConfigs.allowSignallingConditions5 = eaAllowSignallingConditions5; + iSignallerInputs.signallerConfigs.allowSignallingConditions6 = eaAllowSignallingConditions6; + // + // Prepare Trigger Block Validations ... + + // + iSignallerInputs.validations.forceHasSwing = eaForceHasSwing; + iSignallerInputs.validations.forceOBBarType = eaForceOBBarType; + iSignallerInputs.validations.minRequiredOBBar = eaMinRequiredOBBar; + iSignallerInputs.validations.forceFVGBarType = eaForceFVGBarType; + iSignallerInputs.validations.liquidityLoopback = eaLiquidityLoopback; + iSignallerInputs.validations.maxAllowedRange = eaMaxAllowedRange; + iSignallerInputs.validations.minAllowedRange = eaMinAllowedRange; + iSignallerInputs.validations.forceHasFLiquidity = eaForceHasFLiquidity; + iSignallerInputs.validations.forceHasRLiquidity = eaForceHasRLiquidity; + iSignallerInputs.validations.validateGapSequence = eaValidateGapSequence; + iSignallerInputs.validations.minAllowedBlockLength = eaMinAllowedBlockLength; + iSignallerInputs.validations.validateBlockEdgeBreakout = eaValidateBlockEdgeBreakout; + + // + // Prepare Trigger Block Filters ... + + // + iSignallerInputs.filters.filterBasedOnPV = eaFilterBasedOnPV; + iSignallerInputs.filters.bosLoopback = eaBosLoopback; + + // + iSignallerInputs.filters.filterBasedOnSar = eaFilterBasedOnSar; + iSignallerInputs.filters.forceSarSwitched = eaForceSarSwitched; + iSignallerInputs.filters.forceSarOnBothSide = eaForceSarOnBothSide; + iSignallerInputs.filters.forceSarHasBreakout = eaForceSarHasBreakout; + iSignallerInputs.filters.forceSarHasReversalSide = eaForceSarHasReversalSide; + + // + iSignallerInputs.filters.filterBasedOnRSI = eaFilterBasedOnRSI; + iSignallerInputs.filters.forceHasRSITrending = eaForceHasRSITrending; + iSignallerInputs.filters.forceHasRSIVPattern = eaForceHasRSIVPattern; + iSignallerInputs.filters.forceHasRSICrossing = eaForceHasRSICrossing; + + // + iSignallerInputs.filters.filterBasedOnADX = eaFilterBasedOnADX; + iSignallerInputs.filters.forceHasADXTrending = eaForceHasADXTrending; + iSignallerInputs.filters.forceHasADXCrossing = eaForceHasADXCrossing; + + // + iSignallerInputs.filters.filterBasedOnATR = eaFilterBasedOnATR; + iSignallerInputs.filters.forceHasATRTrending = eaForceHasATRTrending; + iSignallerInputs.filters.forceHasATRBreakout = eaForceHasATRBreakout; + + // + iSignallerInputs.filters.filterBasedOnTrend = eaFilterBasedOnTrend; + iSignallerInputs.filters.forceHasTrendDir = eaForceHasTrendDir; + iSignallerInputs.filters.forceHasTrendPlace = eaForceHasTrendPlace; + iSignallerInputs.filters.forceHasTrendChange = eaForceHasTrendChange; + iSignallerInputs.filters.forceHasTrendTrending = eaForceHasTrendTrending; + iSignallerInputs.filters.forceHasTrendRejection = eaForceHasTrendRejection; + iSignallerInputs.filters.forceHasTrendLineInside = eaForceHasTrendLineInside; + iSignallerInputs.filters.forceHasTrendDirOnBothSide = eaForceHasTrendDirOnBothSide; + + // + iSignallerInputs.filters.filterBasedOnKI = eaFilterBasedOnKI; + iSignallerInputs.filters.filterBasedOnDelta = eaFilterBasedOnDelta; + iSignallerInputs.filters.filterBasedOnVolume = eaFilterBasedOnVolume; + iSignallerInputs.filters.filterBasedOnSignalBar = eaFilterBasedOnSignalBar; + iSignallerInputs.filters.filterBasedOnHKSignalBar = eaFilterBasedOnHKSignalBar; + + // + // Loop through Symbols and Initialize Signaller + // for it, then Attached it to eaSignallers ... + for (int i = 0; i < symbolsCount; i++) + { + // + // Attach Symbol ... + iSignallerInputs.symbol = symbols[i]; + + // + // Check if Provided Inputs File Exists ... + // if Exists, Load and Parse it ... + LoadConfig(iSignallerInputs); + + // + // Check Inputs Validation ... + if (iSignallerInputs.IsValid()) + { + // + // Initialize Signaller ... + XCXCATBEASignaller *iSignaller = new XCXCATBEASignaller(iSignallerInputs); + + // + // Add it to the Signallers List ... + Add( + iSignaller, + eaSignallers // + ); + + // + ZeroMemory(iSignaller); + } + } + + // + // Cleanup Resources ... + iSignallerInputs.Clean(); + } + + // + // since atleast one Signaller must + // exists to Expert works ... + // we check it as Last Step ... + result = hasSymbols && + HasChild(eaSignallers); + if (result) + { + // + string message = "Initialized Successfully ..."; + eaAlert.SendAlert(message); + + // + SaveConfigs(); + } + else + { + // + string message = "Initialization Failed ..."; + eaAlert.SendAlert(message); + } + + // + return result; + } + + /** + * Handle De Initialization of Expert ... + */ + void HandleOnDeInit() + { + // + delete eaTrade; + ZeroMemory(eaTrade); + + // + delete eaGuard; + ZeroMemory(eaGuard); + + // + delete eaVolume; + ZeroMemory(eaVolume); + + // + eaTimeTracker.Clean(); + + // + Clean(eaSignallers); + + // + delete eaTradeManager; + ZeroMemory(eaTradeManager); + + // + delete eaCollector; + ZeroMemory(eaCollector); + + // + delete eaSignallerInputParser; + ZeroMemory(eaSignallerInputParser); + + // + string message = "DeInitialized Successfully ..."; + eaAlert.SendAlert(message); + + // + delete eaAlert; + ZeroMemory(eaAlert); + } + + /** + * Handle Tick ... + */ + void HandleOnTick() + { + // + // Time Report Handling ... + HandleTimeReport(); + + // + // Position Management / Protections Handling ... + eaTradeManager.Manage(); + + // + // Check Signallers Registered ... + bool has = HasChild(eaSignallers); + if (!has) + { + return; + } + + // + // Define Collection of Requirements ... + XGuard guards[]; + XCATBEAStrategyConditions conditions[]; + + // + // Loop through Registered Signallers to Proccess Ticks and + // Collect: + // - Guards; + // - Triggered Conditions; + // - ... + int count = ArraySize(eaSignallers); + for (int i = 0; i < count; i++) + { + // + // Retrieve indexed Signaller ... + XCXCATBEASignaller *iSignaller = eaSignallers[i]; + + // + string iSymbol = iSignaller.GetSymbol(); + string iProvider = iSignaller.GetProvider(); + ENUM_TIMEFRAMES iPeriod = iSignaller.GetPeriod(); + + // + // Now we Have to Check Handle Tick Resoult ... + + // + // Requirements ... + XGuard iGuards[]; // Hold Provided Guards ... + XPosition iPositions[]; // Retrieve Signaller Positions ... + XCATBEAStrategyConditions iConditions; // Recieve Triggered Conditions ... + + // + // Check Active Session ... + bool isActiveSession = eaTradeManager.IsActiveSession(iSymbol); + + // + // Reading Signaller Positions ... + eaTradeManager.GetPositions( + iPositions, + iSymbol, + iProvider, + iPeriod // + ); + + // + // Processing Tick for Signaller ... + iSignaller.ProcessTick( + iPositions, + iGuards, + iConditions, + isActiveSession // + ); + + // + // Check Results ... + has = HasChild(iGuards); + if (has) + { + // + Copy( + iGuards, + guards, + false // Force Clean ... + ); + } + + // + // Check Triggered Conditions ... + has = iConditions.IsValid() && + iConditions.IsSetuped() && + iConditions.CanTrigger(); + if (has) + { + // + AddRef( + iConditions, + conditions // + ); + } + + // + // Cleanup Resources ... + Clean(iGuards); + Clean(iPositions); + iConditions.Clean(); + } + + // + // Do Actions Based on Provided Info ... + + // + // Guards ... + has = HasChild(guards); + if (has) + { + // + // Handle Guards Firing ... + eaGuard.DoGuards(guards); + } + + // + // Triggers ... + has = HasChild(conditions); + if (has) + { + // + // Handle Conditions Triggering ... + TriggerConditions(conditions); + } + + // + // Cleanup Resources ... + + // + Clean(guards); + Clean(conditions); + } + + /** + * Handle Trade ... + */ + void HandleOnTrade() + { + eaTrade.HandleOnTrade(); + } + + /** + * Handle Timer ... + */ + void HandleOnTimer() + { + } + + /** + * Handle Chart Event ... + * + * @param id: int, Event id ... + * @param lparam: long, Event Long Parameter ... + * @param dparam: double, Event Double Parameter ... + * @param sparam: string, Event String Parameter ... + */ + void HandleOnChartEvent( + const int id, + const long &lparam, + const double &dparam, + const string &sparam // + ) + { + } + + // + // Trade Event Handlers ... + + /** + * Handle Stop Loss Event Triggered ... + * + * @param deal: XDeal instance refrence, provides Triggered Deal info ... + */ + void HandleOnStopLossTriggered(const XDeal &deal) + { + eaTradeManager.HandleSL(deal); + } + + /** + * Handle Take Profit Event Triggered ... + * + * @param deal: XDeal instance refrence, provides Triggered Deal info ... + */ + void HandleOnTakeProfitTriggered(const XDeal &deal) + { + eaTradeManager.HandleTP(deal); + } + + /** + * Handle Position Force Closed Event ... + * + * @param ticket: ulong, triggered Positions ticket ... + * @param position: XPosition instance refrence, Triggered Position ... + * @param comment: string, Comment ... + */ + void HandleOnPositionForceClosed( + const ulong ticket, + const XPosition &position, + const string comment // + ) + { + eaTradeManager.HandleForceClose(position); + } + + /** + * Handle Position Partially Closed Event ... + * + * @param ticket: ulong, triggered Positions ticket ... + * @param profit: double, Position Profit ... + * @param comment: string, Comment ... + */ + void HandleOnPositionPartialClosed( + const ulong ticket, + const double profit, + const string comment // + ) + { + // + eaTradeManager.HandlePartiallyClosed( + ticket, + profit, + comment // + ); + } + + /** + * Handle Deals Changed ... + * + * @param count: int, number of changes ... + * if the count is positive, means new added ... + * if the count is negative, means removed ... + */ + void HandleOnDealsChanged(int count) + { + } + + /** + * Handle Orders Changed ... + * + * @param count: int, number of changes ... + * if the count is positive, means new added ... + * if the count is negative, means removed ... + */ + void HandleOnOrdersChanged(int count) + { + } + + /** + * Handle Positions Changed ... + * + * @param count: int, number of changes ... + * if the count is positive, means new added ... + * if the count is negative, means removed ... + */ + void HandleOnPositionsChanged(int count) + { + } + + /** + * Handle Position Modified Event ... + * + * @param ticket: ulong, triggered Positions ticket ... + * @param profit: double, Position Profit ... + * @param comment: string, Comment ... + */ + void HandleOnPositionModified( + const ulong ticket, + const double profit, + const string comment // + ) + { + } + + /** + * Handle all Trades States Changed Event ... + * + * @param state: XOnTradeHandlerState instance refrence, Changed Trade State data ... + */ + void HandleOnTradeStateChanged(const XOnTradeHandlerState &state) + { + } + + // + // protected ... + protected: + // + + /** + * Report Time Changes based on Given Configurations ... + */ + void HandleTimeReport() + { + // + if (eaAlert == NULL) + { + return; + } + + // + // Monthly Report .... + if (eaReportNewMonths && + eaTimeTracker.IsNewMonth()) + { + // + string msg = "New Month ..."; + + // + eaAlert.SendAlert(msg); + } + + // + // Weekly Report .... + if (eaReportNewWeeks && + eaTimeTracker.IsNewWeek()) + { + // + string msg = "New Week ..."; + + // + eaAlert.SendAlert(msg); + } + + // + // Daily Report .... + if (eaReportNewDays && + eaTimeTracker.IsNewDay()) + { + // + string msg = "New Day ..."; + + // + eaAlert.SendAlert(msg); + } + + // + // Hourly Report .... + if (eaReportNewHours && + eaTimeTracker.IsNewHour()) + { + // + string msg = "New Hour ..."; + + // + eaAlert.SendAlert(msg); + } + } + + /** + * Update Signal Targets ... + */ + void UpdateSignalTargets(XSignal &signal) + { + // + bool has = signal.IsValid(); + if (!has) + { + return; + } + + // + // Clean Signal Targets ... + Clean(signal.targets); + + // + // Calculate Requirements ... + double r2r = eaSignalR2R > 0 + ? eaSignalR2R + : 1; + double risk = signal.GetRisk(); + double reward = risk * r2r; + + // + double isLong = IsLong(signal.type); + + // + // Handling Signal TP ... + signal.tp = + isLong + ? signal.entry + reward + : signal.entry - reward; + + // + // Try to Apply Money Management ... + + // + // Sort Targets ... + ENUM_X_DIRECTION sortingDir = + isLong + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + ApplySortOnTargets( + sortingDir, + signal.targets // + ); + } + + /** + * Convert a Triggered Conditions to Signal and + * Execute it ... + */ + void TriggerConditions(XCATBEAStrategyConditions &conditions[]) + { + // + int count = 0; + bool has = false; + + // + has = HasChild(conditions); + if (!has) + { + return; + } + + // + count = ArraySize(conditions); + for (int i = 0; i < count; i++) + { + // + // Retrieve Indexed Conditions ... + XCATBEAStrategyConditions iConditions = conditions[i]; + + // + // Define Signal Structure ... + XSignal iSignal; + + // + // Check Conditions is Valid Triggered Conditions ... + has = + iConditions.IsValid() && + iConditions.IsSetuped() && + iConditions.CanTrigger(); + if (has) + { + // + // Preparing Signal ... + has = ToSignal( + iSignal, + iConditions // + ); + } + + // + // Validate Signal ... + has = iSignal.IsValid(); + if (has) + { + // + // Retrieve Signal Type ... + bool isLong = IsLong(iSignal.type); + + // + // Update Signal Entry ... + iSignal.entry = GetEntry( + iSignal.symbol, + iSignal.type // + ); + + // + // Update Signal Targets ... + UpdateSignalTargets(iSignal); + + // + // Handle Volume Management ... + double iVolume = eaVolume.CalculateVolume(iSignal); + has = iVolume > X_MIN_VOLUME && + iVolume != iSignal.volume; + if (has) + { + iSignal.volume = iVolume; + } + + // + // Execute Signal ... + has = eaTradeManager.Execute( + iSignal, + iConditions // + ); + } + + // + // Cleanup Resources ... + + // + iSignal.Clean(); + iConditions.Clean(); + } + } + + // + // private ... + private: + // + + // + TOnModify mOnModifyEventHandlers[]; + TOnStopLoss mStopLossEventHandlers[]; + TOnTakeProfit mTakeProfitEventHandlers[]; + TOnForceClose mOnForceCloseEventHandlers[]; + TOnDealsChanged mDealsChangedEventHandlers[]; + TOnOrdersChanged mOrdersChangedEventHandlers[]; + TOnPartialClose mOnPartialCloseEventHandlers[]; + TOnPositionsChanged mPositionsChangedEventHandlers[]; + TOnTradeStateChanged mTradeStateChangedEventHandlers[]; + + // + void SaveConfigs() + { + // + string content = NULL; + + // + string separator = "\n"; + bool ignoreFalseConditions = false; + + // + // Preparng Condtions ... + content += + // + "-----------------------" + separator + + "Validating: " + separator + + "-----------------------" + separator + + ToString("eaForceHasSwing", eaForceHasSwing, ignoreFalseConditions, separator) + + ToString("eaForceOBBarType", eaForceOBBarType, ignoreFalseConditions, separator) + + ToString("eaForceFVGBarType", eaForceFVGBarType, ignoreFalseConditions, separator) + + ToString("eaForceHasFLiquidity", eaForceHasFLiquidity, ignoreFalseConditions, separator) + + ToString("eaForceHasRLiquidity", eaForceHasRLiquidity, ignoreFalseConditions, separator) + + ToString("eaValidateGapSequence", eaValidateGapSequence, ignoreFalseConditions, separator) + + ToString("eaValidateBlockEdgeBreakout", eaValidateBlockEdgeBreakout, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "Filtering: " + separator + + "-----------------------" + separator + + ToString("eaFilterBasedOnKI", eaFilterBasedOnKI, ignoreFalseConditions, separator) + + ToString("eaFilterBasedOnPV", eaFilterBasedOnPV, ignoreFalseConditions, separator) + + ToString("eaFilterBasedOnSar", eaFilterBasedOnSar, ignoreFalseConditions, separator) + + ToString("eaForceSarSwitched", eaForceSarSwitched, ignoreFalseConditions, separator) + + ToString("eaForceSarOnBothSide", eaForceSarOnBothSide, ignoreFalseConditions, separator) + + ToString("eaForceSarHasBreakout", eaForceSarHasBreakout, ignoreFalseConditions, separator) + + ToString("eaForceSarHasReversalSide", eaForceSarHasReversalSide, ignoreFalseConditions, separator) + + ToString("eaFilterBasedOnRSI", eaFilterBasedOnRSI, ignoreFalseConditions, separator) + + ToString("eaForceHasRSITrending", eaForceHasRSITrending, ignoreFalseConditions, separator) + + ToString("eaForceHasRSIVPattern", eaForceHasRSIVPattern, ignoreFalseConditions, separator) + + ToString("eaForceHasRSICrossing", eaForceHasRSICrossing, ignoreFalseConditions, separator) + + ToString("eaFilterBasedOnADX", eaFilterBasedOnADX, ignoreFalseConditions, separator) + + ToString("eaForceHasADXTrending", eaForceHasADXTrending, ignoreFalseConditions, separator) + + ToString("eaForceHasADXCrossing", eaForceHasADXCrossing, ignoreFalseConditions, separator) + + ToString("eaFilterBasedOnATR", eaFilterBasedOnATR, ignoreFalseConditions, separator) + + ToString("eaForceHasATRTrending", eaForceHasATRTrending, ignoreFalseConditions, separator) + + ToString("eaForceHasATRBreakout", eaForceHasATRBreakout, ignoreFalseConditions, separator) + + ToString("eaFilterBasedOnTrend", eaFilterBasedOnTrend, ignoreFalseConditions, separator) + + ToString("eaForceHasTrendDir", eaForceHasTrendDir, ignoreFalseConditions, separator) + + ToString("eaForceHasTrendPlace", eaForceHasTrendPlace, ignoreFalseConditions, separator) + + ToString("eaForceHasTrendChange", eaForceHasTrendChange, ignoreFalseConditions, separator) + + ToString("eaForceHasTrendTrending", eaForceHasTrendTrending, ignoreFalseConditions, separator) + + ToString("eaForceHasTrendRejection", eaForceHasTrendRejection, ignoreFalseConditions, separator) + + ToString("eaForceHasTrendLineInside", eaForceHasTrendLineInside, ignoreFalseConditions, separator) + + ToString("eaForceHasTrendDirOnBothSide", eaForceHasTrendDirOnBothSide, ignoreFalseConditions, separator) + + ToString("eaFilterBasedOnDelta", eaFilterBasedOnDelta, ignoreFalseConditions, separator) + + ToString("eaFilterBasedOnVolume", eaFilterBasedOnVolume, ignoreFalseConditions, separator) + + ToString("eaFilterBasedOnSignalBar", eaFilterBasedOnSignalBar, ignoreFalseConditions, separator) + + ToString("eaFilterBasedOnHKSignalBar", eaFilterBasedOnHKSignalBar, ignoreFalseConditions, separator) + + // + "" + // + ; + + // + // Try to Save Condtions ... + string fileName = eaCollector.GetFilePath("XConfigs"); + bool has = IsValid(fileName); + if (!has) + { + return; + } + + // + eaCollector.Save( + fileName, + content // + ); + + // + // Try to Save Inputs ... + fileName = eaCollector.GetFilePath("XInputs"); + has = IsValid(fileName); + if (!has) + { + return; + } + + // + // Preparing Inputs String Reperesentation ... + content = NULL; + content += + // + "//" + separator + + "// Common ..." + separator + + ToString("eaMagicNumber", eaMagicNumber, separator) + + ToString("eaSlippage", eaSlippage, separator) + + ToString("eaLogSuffix", eaLogSuffix, separator) + + "" + separator + + "//" + separator + + "// Detector ..." + separator + + "" + separator + + "//" + separator + + "// Validating ..." + separator + + ToString("eaForceHasSwing", eaForceHasSwing, ignoreFalseConditions, separator) + + ToString("eaForceOBBarType", eaForceOBBarType, ignoreFalseConditions, separator) + + ToString("eaMinRequiredOBBar", eaMinRequiredOBBar, ignoreFalseConditions, separator) + + ToString("eaForceFVGBarType", eaForceFVGBarType, ignoreFalseConditions, separator) + + ToString("eaLiquidityLoopback", eaLiquidityLoopback, ignoreFalseConditions, separator) + + ToString("eaMaxAllowedRange", ToString(eaMaxAllowedRange), separator) + + ToString("eaMinAllowedRange", ToString(eaMinAllowedRange), separator) + + ToString("eaForceHasFLiquidity", eaForceHasFLiquidity, ignoreFalseConditions, separator) + + ToString("eaForceHasRLiquidity", eaForceHasRLiquidity, ignoreFalseConditions, separator) + + ToString("eaValidateGapSequence", eaValidateGapSequence, ignoreFalseConditions, separator) + + ToString("eaMinAllowedBlockLength", eaMinAllowedBlockLength, ignoreFalseConditions, separator) + + ToString("eaValidateBlockEdgeBreakout", eaValidateBlockEdgeBreakout, ignoreFalseConditions, separator) + + "" + separator + + "//" + separator + + "// Filtering ..." + separator + + ToString("eaFilterBasedOnKI", eaFilterBasedOnKI, ignoreFalseConditions, separator) + + ToString("eaFilterBasedOnPV", eaFilterBasedOnPV, ignoreFalseConditions, separator) + + ToString("eaBosLoopback", eaBosLoopback, ignoreFalseConditions, separator) + + ToString("eaFilterBasedOnSar", eaFilterBasedOnSar, ignoreFalseConditions, separator) + + ToString("eaForceSarSwitched", eaForceSarSwitched, ignoreFalseConditions, separator) + + ToString("eaForceSarOnBothSide", eaForceSarOnBothSide, ignoreFalseConditions, separator) + + ToString("eaForceSarHasBreakout", eaForceSarHasBreakout, ignoreFalseConditions, separator) + + ToString("eaForceSarHasReversalSide", eaForceSarHasReversalSide, ignoreFalseConditions, separator) + + ToString("eaFilterBasedOnRSI", eaFilterBasedOnRSI, ignoreFalseConditions, separator) + + ToString("eaForceHasRSITrending", eaForceHasRSITrending, ignoreFalseConditions, separator) + + ToString("eaForceHasRSIVPattern", eaForceHasRSIVPattern, ignoreFalseConditions, separator) + + ToString("eaForceHasRSICrossing", eaForceHasRSICrossing, ignoreFalseConditions, separator) + + ToString("eaFilterBasedOnADX", eaFilterBasedOnADX, ignoreFalseConditions, separator) + + ToString("eaForceHasADXTrending", eaForceHasADXTrending, ignoreFalseConditions, separator) + + ToString("eaForceHasADXCrossing", eaForceHasADXCrossing, ignoreFalseConditions, separator) + + ToString("eaFilterBasedOnATR", eaFilterBasedOnATR, ignoreFalseConditions, separator) + + ToString("eaForceHasATRTrending", eaForceHasATRTrending, ignoreFalseConditions, separator) + + ToString("eaForceHasATRBreakout", eaForceHasATRBreakout, ignoreFalseConditions, separator) + + ToString("eaFilterBasedOnTrend", eaFilterBasedOnTrend, ignoreFalseConditions, separator) + + ToString("eaForceHasTrendDir", eaForceHasTrendDir, ignoreFalseConditions, separator) + + ToString("eaForceHasTrendPlace", eaForceHasTrendPlace, ignoreFalseConditions, separator) + + ToString("eaForceHasTrendChange", eaForceHasTrendChange, ignoreFalseConditions, separator) + + ToString("eaForceHasTrendTrending", eaForceHasTrendTrending, ignoreFalseConditions, separator) + + ToString("eaForceHasTrendRejection", eaForceHasTrendRejection, ignoreFalseConditions, separator) + + ToString("eaForceHasTrendLineInside", eaForceHasTrendLineInside, ignoreFalseConditions, separator) + + ToString("eaForceHasTrendDirOnBothSide", eaForceHasTrendDirOnBothSide, ignoreFalseConditions, separator) + + ToString("eaFilterBasedOnDelta", eaFilterBasedOnDelta, ignoreFalseConditions, separator) + + ToString("eaFilterBasedOnVolume", eaFilterBasedOnVolume, ignoreFalseConditions, separator) + + ToString("eaFilterBasedOnSignalBar", eaFilterBasedOnSignalBar, ignoreFalseConditions, separator) + + ToString("eaFilterBasedOnHKSignalBar", eaFilterBasedOnHKSignalBar, ignoreFalseConditions, separator) + + "" + separator + + "//" + separator + + "// Signal ..." + separator + + ToString("eaSignalR2R", eaSignalR2R, ignoreFalseConditions, separator) + + ToString("eaSLATRMultiplier", ToString(eaSLATRMultiplier), separator) + + ToString("eaAllowSignallingBasedOnConditions", eaAllowSignallingBasedOnConditions, ignoreFalseConditions, separator) + + ToString("eaAllowSignallingBasedOnTriggerBlocks", eaAllowSignallingBasedOnTriggerBlocks, ignoreFalseConditions, separator) + + ToString("eaAllowSignallingBasedOnTriggerBlocksInsideOther", eaAllowSignallingBasedOnTriggerBlocksInsideOther, ignoreFalseConditions, separator) + + ToString("eaSecondsTriggersSLUsingFirstTriggerBlock", eaSecondsTriggersSLUsingFirstTriggerBlock, ignoreFalseConditions, separator) + + ToString("eaApplyValidateAndFilterOnSelectInsideOthers", eaApplyValidateAndFilterOnSelectInsideOthers, ignoreFalseConditions, separator) + + ToString("eaAllowSignallingConditions1", eaAllowSignallingConditions1, ignoreFalseConditions, separator) + + ToString("eaAllowSignallingConditions2", eaAllowSignallingConditions2, ignoreFalseConditions, separator) + + ToString("eaAllowSignallingConditions3", eaAllowSignallingConditions3, ignoreFalseConditions, separator) + + ToString("eaAllowSignallingConditions4", eaAllowSignallingConditions4, ignoreFalseConditions, separator) + + ToString("eaAllowSignallingConditions5", eaAllowSignallingConditions5, ignoreFalseConditions, separator) + + ToString("eaAllowSignallingConditions6", eaAllowSignallingConditions6, ignoreFalseConditions, separator) + + "" + separator + + "//" + separator + + "// Volume ..." + separator + + ToString("eaVolumeSelect", ToString(eaVolumeSelect), separator) + + ToString("eaStaticVoluem", ToString(eaStaticVoluem), separator) + + ToString("eaDynamicVolumeStepBalance", ToString(eaDynamicVolumeStepBalance), separator) + + ToString("eaDynamicVolumeStepVolume", ToString(eaDynamicVolumeStepVolume), separator) + + ToString("eaConstantRiskBalance", ToString(eaConstantRiskBalance), separator) + + ToString("eaConstantPercent", ToString(eaConstantPercent), separator) + + ToString("eaConstantBalance", ToString(eaConstantBalance), separator) + + "" + separator + + "//" + separator + + "// Management ..." + separator + + ToString("eaSymbols", eaSymbols, separator) + + ToString("eaAllowGuards", eaAllowGuards, ignoreFalseConditions, separator) + + ToString("eaAllowTrade", eaAllowTrade, ignoreFalseConditions, separator) + + ToString("eaAllowLongs", eaAllowLongs, ignoreFalseConditions, separator) + + ToString("eaAllowShorts", eaAllowShorts, ignoreFalseConditions, separator) + + ToString("eaSessions", eaSessions, separator) + + ToString("eaRestrictionsPeriod", ToString(eaRestrictionsPeriod), separator) + + ToString("eaMaxAllowedTPs", eaMaxAllowedTPs, ignoreFalseConditions, separator) + + ToString("eaMaxAllowedSLs", eaMaxAllowedSLs, ignoreFalseConditions, separator) + + ToString("eaMaxAllowedTrades", eaMaxAllowedTrades, ignoreFalseConditions, separator) + + ToString("eaMaxAllowedPositions", eaMaxAllowedPositions, ignoreFalseConditions, separator) + + ToString("eaMaxAllowedSpread", ToString(eaMaxAllowedSpread), separator) + + ToString("eaMaxAllowedDrawdownFactor", ToString(eaMaxAllowedDrawdownFactor), separator) + + ToString("eaCloseAllOpenTradesAt", eaCloseAllOpenTradesAt, separator) + + "" + separator + + "//" + separator + + "// Alert ..." + separator + + ToString("eaEnableAlerts", eaEnableAlerts, ignoreFalseConditions, separator) + + ToString("eaSaveAlerts", eaSaveAlerts, ignoreFalseConditions, separator) + + ToString("eaLogAlerts", eaLogAlerts, ignoreFalseConditions, separator) + + ToString("eaMailAlerts", eaMailAlerts, ignoreFalseConditions, separator) + + ToString("eaPushAlerts", eaPushAlerts, ignoreFalseConditions, separator) + + ToString("eaTerminalAlerts", eaTerminalAlerts, ignoreFalseConditions, separator) + + "" + separator + + "//" + separator + + "// Time Report ..." + separator + + ToString("eaReportNewMonths", eaReportNewMonths, ignoreFalseConditions, separator) + + ToString("eaReportNewWeeks", eaReportNewWeeks, ignoreFalseConditions, separator) + + ToString("eaReportNewDays", eaReportNewDays, ignoreFalseConditions, separator) + + ToString("eaReportNewHours", eaReportNewHours, ignoreFalseConditions, separator) + + ToString("eaReportTrades", eaReportTrades, ignoreFalseConditions, separator) + + ToString("eaReportSignals", eaReportSignals, ignoreFalseConditions, separator) + + ToString("eaReportProtector", eaReportProtector, ignoreFalseConditions, separator) + + ToString("eaReportRestrictions", eaReportRestrictions, ignoreFalseConditions, separator) + + ToString("eaReportAfterTradesBalance", eaReportAfterTradesBalance, ignoreFalseConditions, separator) + + "" + separator + + "//" + separator + + "// Collector ..." + separator + + ToString("eaSaveTrades", eaSaveTrades, ignoreFalseConditions, separator) + + ToString("eaSaveSignals", eaSaveSignals, ignoreFalseConditions, separator) + + ToString("eaSaveWins", eaSaveWins, ignoreFalseConditions, separator) + + ToString("eaSaveLosts", eaSaveLosts, ignoreFalseConditions, separator) + + ToString("eaSaveRestrictions", eaSaveRestrictions, ignoreFalseConditions, separator) + + // + "" + // + ; + + // + eaCollector.Save( + fileName, + content // + ); + } + + // + bool LoadConfig(XCATBEASignallerInputs &inputs) + { + // + bool result = false; + + // + // Validate Args ... + result = + IsValid(inputs.period) && + IsValid(inputs.symbol); + if (!result) + { + return result; + } + + // + // Check the Provided File Exists or not ... + result = + eaSignallerInputParser + .IsSignallerInputsFileExists( + inputs.symbol, + inputs.period // + ); + if (!result) + { + return result; + } + + // + // Parse File Content ... + result = + eaSignallerInputParser + .ParseSignallerInputs( + inputs, + inputs.symbol, + inputs.period // + ); + + // + return result; + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14040316/XCATBEA/Classes/xcatbea.signaller.class.mq5 b/BKPS/14040316/XCATBEA/Classes/xcatbea.signaller.class.mq5 new file mode 100644 index 0000000..e7b8b4d --- /dev/null +++ b/BKPS/14040316/XCATBEA/Classes/xcatbea.signaller.class.mq5 @@ -0,0 +1,2147 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCXCATBEASignaller ... +// Description: Class for XCATBEA Signaller ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XCXCATBEASignaller Class" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-bar.analyser.class.mq5" +#include "../../Classes/x-saherelm.x-guard.class.mq5" +#include "../../Helpers/x-saherelm.x121.xcatb.helper.mq5" +#include "../Classes/xcatbea.x-poi.detector.class.mq5" +#include "../Classes/xcatbea.x-poi.drawer.class.mq5" +#include "../Libraries/xcatbea.lib.mq5" +#include "../Libraries/xcatbea.signaller.lib.mq5" +#include "../Libraries/xcatbea.x-poi.extensions.lib.mq5" + +// +// Definitions ... + +// +// Configure Signalelrs ... +struct XCATBEASignallingConfigs +{ + // + // Signalling Method ... + bool allowSignallingBasedOnConditions; // Signalling Based on Market Conditions + bool allowSignallingBasedOnTriggerBlocks; // Signalling Based on Trigger Blocks + bool allowSignallingBasedOnTriggerBlocksInsideOther; // Signalling Based on Trigger Blocks Seccond inputs + + // + // Others ... + bool applyValidateAndFilterOnSelectInsideOthers; // Select Trigger Blocks by Applying Validations and Filterss + bool secondsTriggersSLUsingFirstTriggerBlock; // Use First Trigger Block for SL of Seconds Trigger Block Signalss + + // + // Market Conditions Signall Providers ... + bool allowSignallingConditions1; // Allow Market Conditions Signaller to Using Sar Starter Signals + bool allowSignallingConditions2; // Allow Market Conditions Signaller to Using Trend Starter Signals + bool allowSignallingConditions3; // Allow Market Conditions Signaller to Using Delta Starter Signals + bool allowSignallingConditions4; // Allow Market Conditions Signaller to Using Volume Starter Signals + bool allowSignallingConditions5; // Allow Market Conditions Signaller to Using Signal Bar Starter Signals + bool allowSignallingConditions6; // Allow Market Conditions Signaller to Using HK Signal Bar Starter Signals + + // + // Constructor ... + XCATBEASignallingConfigs() + { + Clean(); + } + + // + // Tools ... + + // + // Cleaning Up ... + void Clean() + { + // + allowSignallingBasedOnConditions = false; + allowSignallingBasedOnTriggerBlocks = false; + allowSignallingBasedOnTriggerBlocksInsideOther = false; + + // + secondsTriggersSLUsingFirstTriggerBlock = false; + applyValidateAndFilterOnSelectInsideOthers = false; + + // + allowSignallingConditions1 = false; + allowSignallingConditions2 = false; + allowSignallingConditions3 = false; + allowSignallingConditions4 = false; + allowSignallingConditions5 = false; + allowSignallingConditions6 = false; + } +}; + +// +struct XCATBEASignallerInputs +{ + // + // Pros ... + string symbol; + string provider; + bool allowDraws; + bool allowGuards; + int riskToRewardRatio; + ENUM_TIMEFRAMES period; + double slATRMultiplier; + X121XCatbInputs catbInputs; + XTriggerBlockFilters filters; + XTriggerBlockValidationRules validations; + XCATBEASignallingConfigs signallerConfigs; + + // + // Constructor(s) ... + XCATBEASignallerInputs() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + symbol = NULL; + period = NULL; + provider = NULL; + filters.Clean(); + catbInputs.Clean(); + allowDraws = false; + validations.Clean(); + allowGuards = false; + slATRMultiplier = 0; + riskToRewardRatio = 0; + signallerConfigs.Clean(); + + // + ZeroMemory(this); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + IsValid(symbol) && + IsValid(period) && + IsValid(provider) && + catbInputs.IsValid() && + riskToRewardRatio > 0; + + // + return result; + } + + // +}; + +// +// Implementations ... +class XCXCATBEASignaller : XCBase +{ + // + // Public ... + public: + // + // Props ... + + // + bool allowSignallingBasedOnConditions; // Signalling Based on Market Conditions + bool allowSignallingBasedOnTriggerBlocks; // Signalling Based on Trigger Blocks + bool allowSignallingBasedOnTriggerBlocksInsideOther; // Signalling Based on Trigger Blocks Seccond inputs + + // + bool secondsTriggersSLUsingFirstTriggerBlock; // Use First Trigger Block for SL of Seconds Trigger Block Signalss + bool applyValidateAndFilterOnSelectInsideOthers; // Select Trigger Blocks by Applying Validations and Filterss + + // + // Market Conditions Signall Providers ... + bool allowSignallingConditions1; // Allow Market Conditions Signaller to Using Sar Starter Signals + bool allowSignallingConditions2; // Allow Market Conditions Signaller to Using Trend Starter Signals + bool allowSignallingConditions3; // Allow Market Conditions Signaller to Using Delta Starter Signals + bool allowSignallingConditions4; // Allow Market Conditions Signaller to Using Volume Starter Signals + bool allowSignallingConditions5; // Allow Market Conditions Signaller to Using Signal Bar Starter Signals + bool allowSignallingConditions6; // Allow Market Conditions Signaller to Using HK Signal Bar Starter Signals + + // + bool allowDraws; // Allow Draws or not ... + bool allowGuards; // Allow Guards or not ... + int riskToRewardRatio; // Signals R2R ... + double slATRMultiplier; // SL ATR Multiplier ... + + // + XBarTracker barTraker; // Bar Tracker ... + XCX121XCatbHelper *helper; // XCATB Helper Class instance ... + XCBarAnalyser *barAnalyser; // Bar Analyser ... + XCXCATBEAPOIDrawer *drawer; // POI Drawer ... + XTriggerBlockFilters filters; // Trigger Block Filters ... + XCXCATBEAPOIDetector *detector; // POI Detector ... + XTriggerBlockValidationRules validations; // Trigger Block Validations ... + + // + XBoxZone cPeak; // Current Peak ... + XBoxZone cVale; // Current Vale ... + XBoxZone unavailableZones[]; // Un Available Zones ... + XTriggerBlock cTriggerBlock; // Currently Selected Trigger Block ... + XTriggerBlock triggerBlocks[]; // Founded Trigger Blocks ... + bool waitsUntilPeakInvalidate; // Waits Until Peak Invalidate ... + bool waitsUntilValeInvalidate; // Waits Until Vale Invalidate ... + XTriggerBlock cInsideTriggerBlock; // a TriggerBlock which Currently Selected Trigger Block is Inside it ... + + // + XCATBEAStrategyConditions mConditions; + XCATBEAStrategyConditions mConditionsCollection[]; + + // + // Constructor ... + XCXCATBEASignaller(XCATBEASignallerInputs &inputs) + { + Init(inputs); + } + + // + // Deconstructor ... + ~XCXCATBEASignaller() + { + DeInit(); + } + + // + // Properties ... + + // + string GetSymbol() + { + return symbol; + } + + // + string GetProvider() + { + return provider; + } + + // + ENUM_TIMEFRAMES GetPeriod() + { + return period; + } + + // + double GetR2R() + { + return riskToRewardRatio; + } + + // + // Tick Analyser ... + + /** + * Process Tick ... + */ + void ProcessTick( + XPosition &positions[], + XGuard &guards[], + XCATBEAStrategyConditions &conditions, + bool isActiveSession = true // + ) + { + // + Clean(guards); + conditions.Clean(); + + // + XOHCL bar; + int count = 0; + bool has = false; + int barIndex = 0; + cTriggerBlock.Clean(); + cInsideTriggerBlock.Clean(); + + // + // Check Guards ... + has = DetectGuards( + guards, + positions, + barIndex // + ); + + // + // Check Triggered Conditions ... + has = HasChild(mConditionsCollection); + if (has) + { + // + int selectedIDX = -1; + count = ArraySize(mConditionsCollection); + for (int i = 0; i < count; i++) + { + // + // Select indexed Conditions ... + XCATBEAStrategyConditions iConditions = mConditionsCollection[i]; + + // + // Check Conditions Triggered ... + has = DetectSignalTrigger( + iConditions, + barIndex // + ); + if (has) + { + // + selectedIDX = i; + conditions = iConditions; + iConditions.Clean(); + + // + break; + } + + // + // When Setup Invalidated + // Signaller Clean Conditions ... + if (!has && + !iConditions.IsValid()) + { + // + selectedIDX = i; + break; + } + + // + // Cleanup Resources ... + iConditions.Clean(); + } + + // + // Check Can Trigger ... + has = IsValidIndex(selectedIDX) && + conditions.IsValid() && + conditions.IsSetuped() && + conditions.CanTrigger(); + if (has) + { + // + ArrayRemove( + mConditionsCollection, + selectedIDX, + 1 // + ); + } + else + { + // + // Check Selected Index for Invalid Conditions ... + if (IsValidIndex(selectedIDX)) + { + // + // Remove Invalidated Conditions ... + ArrayRemove( + mConditionsCollection, + selectedIDX, + 1 // + ); + } + + // + // Cleanup Resource ... + conditions.Clean(); + } + } + + // + // Check Bar Processing ... + if (!barTraker.CanProcessBar()) + { + return; + } + + // + // Initialize Bar ... + bar.Init( + symbol, + period, + barIndex // + ); + + // + // Detect POI(s) ... + detector.Detect(barIndex); + + // + // Validate POI(s) ... + detector.Validate( + unavailableZones, + barIndex // + ); + + // + // Check Helper Last Changes ... + helper.Check(barIndex); + + // + // Draw POI(s) ... + if (allowDraws) + { + // drawer.Draw(bar.time); + } + + // + // Detect Trigger Blocks and Collect them ... + XTriggerBlock iTriggerBlock; + X121XCatbConditions iConditions; + XTriggerBlockFilters iFilters; + XTriggerBlockValidationRules iValidations; + if (applyValidateAndFilterOnSelectInsideOthers) + { + // + // Validations ... + iValidations.forceHasSwing = validations.forceHasSwing; + iValidations.forceOBBarType = validations.forceOBBarType; + iValidations.forceFVGBarType = validations.forceFVGBarType; + iValidations.maxAllowedRange = validations.maxAllowedRange; + iValidations.minAllowedRange = validations.minAllowedRange; + iValidations.minRequiredOBBar = validations.minRequiredOBBar; + iValidations.liquidityLoopback = validations.liquidityLoopback; + iValidations.forceHasFLiquidity = validations.forceHasFLiquidity; + iValidations.forceHasRLiquidity = validations.forceHasRLiquidity; + iValidations.validateGapSequence = validations.validateGapSequence; + iValidations.minAllowedBlockLength = validations.minAllowedBlockLength; + iValidations.validateBlockEdgeBreakout = validations.validateBlockEdgeBreakout; + + // + // Clone Filters and Validations ... + iFilters.bosLoopback = filters.bosLoopback; + iFilters.filterBasedOnKI = filters.filterBasedOnKI; + iFilters.filterBasedOnPV = filters.filterBasedOnPV; + iFilters.filterBasedOnSar = filters.filterBasedOnSar; + iFilters.filterBasedOnRSI = filters.filterBasedOnRSI; + iFilters.filterBasedOnADX = filters.filterBasedOnADX; + iFilters.filterBasedOnATR = filters.filterBasedOnATR; + iFilters.forceSarSwitched = filters.forceSarSwitched; + iFilters.forceHasTrendDir = filters.forceHasTrendDir; + iFilters.filterBasedOnTrend = filters.filterBasedOnTrend; + iFilters.filterBasedOnDelta = filters.filterBasedOnDelta; + iFilters.forceSarOnBothSide = filters.forceSarOnBothSide; + iFilters.forceHasTrendPlace = filters.forceHasTrendPlace; + iFilters.forceSarHasBreakout = filters.forceSarHasBreakout; + iFilters.filterBasedOnVolume = filters.filterBasedOnVolume; + iFilters.forceHasRSITrending = filters.forceHasRSITrending; + iFilters.forceHasRSIVPattern = filters.forceHasRSIVPattern; + iFilters.forceHasRSICrossing = filters.forceHasRSICrossing; + iFilters.forceHasADXTrending = filters.forceHasADXTrending; + iFilters.forceHasADXCrossing = filters.forceHasADXCrossing; + iFilters.forceHasATRTrending = filters.forceHasATRTrending; + iFilters.forceHasATRBreakout = filters.forceHasATRBreakout; + iFilters.forceHasTrendChange = filters.forceHasTrendChange; + iFilters.forceHasTrendTrending = filters.forceHasTrendTrending; + iFilters.forceHasTrendRejection = filters.forceHasTrendRejection; + iFilters.filterBasedOnSignalBar = filters.filterBasedOnSignalBar; + iFilters.forceHasTrendLineInside = filters.forceHasTrendLineInside; + iFilters.forceSarHasReversalSide = filters.forceSarHasReversalSide; + iFilters.filterBasedOnHKSignalBar = filters.filterBasedOnHKSignalBar; + iFilters.forceHasTrendDirOnBothSide = filters.forceHasTrendDirOnBothSide; + } + has = DetectTriggerBlock( + helper, + barAnalyser, + iTriggerBlock, + iConditions, + iValidations, + iFilters, + barIndex, + 10 // Loopback ... + ); + if (has) + { + // + // Add Trigger Block to Collection if not Exists ... + AddIfNotExists( + iTriggerBlock, + triggerBlocks // + ); + } + iFilters.Clean(); + iConditions.Clean(); + iValidations.Clean(); + iTriggerBlock.Clean(); + + // + // Draw Trigger Blocks ... + if (allowDraws) + { + // + // Handle To Updating ... + // datetime cTime = TimeCurrent(); + // DrawTriggerBlocks(cTime); + } + + // + // Here we Check Active Session ... + // and Prevent Moving forward if there is not + // Session actives ... + // for improvement Calculation Speeds ... + if (isActiveSession) + { + // + // Check Signal Setups ... + has = DetectSignalSetup(barIndex); + if (has) + { + // + barTraker.Waits(); + + // + AddConditionsIfNotExists(); + + // + mConditions.Clean(); + } + } + + // + // Cleanup Resources ... + bar.Clean(); + } + + // + // Signalling Tools ... + + /** + * Detect Setup Conditions based on Signalling ... + * + * @param maxAllowedSLDistanceInPoint: int, Max Allowed SL Distance in Points (if Bigger thn Zero Provided) ... + * + * @return ( bool ) + */ + bool DetectSignalSetup(int barIndex = 0) + { + // + bool result = false; + + // + // Normalize Args ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Update All Required Buffers ... + helper.Update(barIndex); + + // + bool has = false; + datetime cTime = TimeCurrent(); + + // + // cPeak and cVale ... + // these Helpes Us to Detect Price Levels ... + // + // Draw Peak and Vale if Exists ... + + // + // Peak ... + if (cPeak.IsValid()) + { + // + cPeak.to = cTime; + // drawer.DrawBox(cPeak); + } + + // + // Vale ... + if (cVale.IsValid()) + { + // + cVale.to = cTime; + // drawer.DrawBox(cVale); + } + + // + // Try to Validate cPeak an cVale if Exists ... + XOHCL zBar; + XOHCL cBar; + bool isInited = zBar.Init( + symbol, + period, + barIndex // + ); + isInited = zBar.GetPreviousBar(cBar); + isInited = helper.GetConditions( + mConditions.conditions, + barIndex, + 10 // + ); + if (isInited) + { + // + // Validate cPeak and cVale if Exists ... + + // + // cPeak ... + if (cPeak.IsValid()) + { + // + isInited = cBar.high < cPeak.lower; + if (!isInited) + { + // + cPeak.Clean(); + cVale.Clean(); + + // + waitsUntilPeakInvalidate = false; + waitsUntilValeInvalidate = false; + } + } + + // + // cVale ... + if (cVale.IsValid()) + { + // + isInited = cBar.low > cVale.upper; + if (!isInited) + { + // + cPeak.Clean(); + cVale.Clean(); + + // + waitsUntilPeakInvalidate = false; + waitsUntilValeInvalidate = false; + } + } + + // + // Try To Detect Peak and Vale based on cBar ... + + // + // Selecting Peak ... + if (!cPeak.IsValid()) + { + // + XBoxZone tmpPeaks[]; + detector.FillPeakPivots(tmpPeaks); + while (HasChild(tmpPeaks)) + { + // + // Find Index ... + int idx = GetLowest(tmpPeaks); + if (!IsValidIndex(idx)) + { + break; + } + + // + // Select ... + cPeak = tmpPeaks[idx]; + ArrayRemove( + tmpPeaks, + idx, + 1 // + ); + + // + // Validate Peak ... + bool isValid = cPeak.lower > cBar.high; + if (isValid) + { + break; + } + + // + cPeak.Clean(); + } + Clean(tmpPeaks); + } + + // + // Selecting Vale ... + if (!cVale.IsValid()) + { + // + XBoxZone tmpVales[]; + detector.FillValePivots(tmpVales); + while (HasChild(tmpVales)) + { + // + // Find Index ... + int idx = GetHighest(tmpVales); + if (!IsValidIndex(idx)) + { + break; + } + + // + // Select ... + cVale = tmpVales[idx]; + ArrayRemove( + tmpVales, + idx, + 1 // + ); + + // + // Validate Vale ... + bool isValid = cVale.upper < cBar.low; + if (isValid) + { + break; + } + + // + cVale.Clean(); + } + Clean(tmpVales); + } + } + + // + // Detect Signal Setup Based on Market Conditions ... + if (!result && + allowSignallingBasedOnConditions) + { + // + // Detect Signalling Zone ... + result = DetectSignalZone( + helper, + drawer, + detector, + barAnalyser, + mConditions.conditions, + mConditions.pivotZone, + allowSignallingConditions1, + allowSignallingConditions2, + allowSignallingConditions3, + allowSignallingConditions4, + allowSignallingConditions5, + allowSignallingConditions6, + barIndex, + 10 // Loopback ... + ); + if (result) + { + // + // Use Signal Zone ... + UseBox(mConditions.pivotZone); + + // + // Prepare Condition ... + + // + // Prepare Signal ... + mConditions.dir = + mConditions + .pivotZone + .dir; + mConditions.symbol = symbol; + mConditions.period = period; + mConditions.provider = provider; + mConditions.reward = riskToRewardRatio; + mConditions.time = mConditions.conditions.bars[0].time; + mConditions.setupTime = mConditions.conditions.bars[0].time; + + // + // Prepare Target ... + double targets[]; + for (int i = 1; i <= riskToRewardRatio; i++) + { + // + Add( + (double)i, + targets // + ); + } + + // + // Calculate SL Additions ... + double iATR = 0; + if (barIndex > 0 && + barIndex < ArraySize(helper.atrBuffer)) + { + iATR = helper.atrBuffer[barIndex]; + } + double slAdditional = slATRMultiplier * iATR; + + // + // Preparing Signal ... + XSignal iSignal; + result = ToSignal( + mConditions.pivotZone, + iSignal, + targets, + slAdditional // + ); + if (result) + { + // + mConditions.sl = iSignal.sl; + mConditions.tp = iSignal.tp; + mConditions.pivot = iSignal.sl; + mConditions.entry = iSignal.entry; + mConditions.point = iSignal.entry; + mConditions.type = ToPositionType(iSignal.type); + + // + // Draw Trigger Block ... + if (allowDraws) + { + // + XCBoxObject *iObj; + has = drawer + .drawer + .DrawBox( + mConditions.pivotZone, + iObj // + ); + if (has) + { + mObjects.Add(iObj); + } + ZeroMemory(iObj); + } + } + iSignal.Clean(); + } + } + + // + // Detect Signal Setup Based on Trigger Block Detection ... + if (!result && + allowSignallingBasedOnTriggerBlocks) + { + // + // Detect Trigger Block ... + result = DetectTriggerBlock( + helper, + barAnalyser, + mConditions.triggerBlock, + mConditions.conditions, + validations, + filters, + barIndex, + 10 // Loopback ... + ); + if (result) + { + // + // Use Trigger Block ... + UseTriggerBlock(mConditions.triggerBlock); + + // + // Prepare Condition ... + + // + // Prepare Signal ... + mConditions.dir = + mConditions + .triggerBlock + .GetDirection(); + mConditions.symbol = symbol; + mConditions.period = period; + mConditions.provider = provider; + mConditions.reward = riskToRewardRatio; + mConditions.time = mConditions.conditions.bars[0].time; + mConditions.setupTime = mConditions.conditions.bars[0].time; + + // + // Prepare Target ... + double targets[]; + for (int i = 1; i <= riskToRewardRatio; i++) + { + // + Add( + (double)i, + targets // + ); + } + + // + // Calculate SL Additions ... + double iATR = 0; + if (barIndex > 0 && + barIndex < ArraySize(helper.atrBuffer)) + { + iATR = helper.atrBuffer[barIndex]; + } + double slAdditional = slATRMultiplier * iATR; + + // + // Preparing Signal ... + result = ToSignal( + mConditions.triggerBlock.trigger, + mConditions.triggerBlock.signal, + targets, + slAdditional // + ); + if (result) + { + // + mConditions.triggerBlock.signal.provider = provider; + mConditions.sl = mConditions.triggerBlock.signal.sl; + mConditions.tp = mConditions.triggerBlock.signal.tp; + mConditions.pivot = mConditions.triggerBlock.signal.sl; + mConditions.entry = mConditions.triggerBlock.signal.entry; + mConditions.point = mConditions.triggerBlock.signal.entry; + mConditions.type = ToPositionType(mConditions.triggerBlock.signal.type); + + // + // Draw Trigger Block ... + if (allowDraws) + { + // + DrawTriggerBlock( + mConditions.triggerBlock, + drawer.drawer, + mObjects, + NULL, // To ... + false // Draw Signal ... + ); + } + } + } + } + + // + // Detect Signal Setup Based On Trigger Blocks Second Entry ... + if (!result && + allowSignallingBasedOnTriggerBlocksInsideOther) + { + // + // Trigger Block Detection ... + result = HasChild(triggerBlocks) && + ArraySize(triggerBlocks) > 1 && + !waitsUntilPeakInvalidate && + !waitsUntilValeInvalidate; + if (result) + { + // + // Check Newest Trigger Block ... + bool isTriggerBlockSelected = false; + XTriggerBlock tmpTBs[]; + Copy( + triggerBlocks, + tmpTBs // + ); + while (HasChild(tmpTBs)) + { + // + int idx = GetYoungest(tmpTBs); + if (!IsValidIndex(idx)) + { + break; + } + + // + // Select ... + // and Remove From Collection ... + cTriggerBlock = tmpTBs[idx]; + ArrayRemove( + tmpTBs, + idx, + 1 // + ); + + // + // Validate ... + isTriggerBlockSelected = + // + // Check Bar is Valid ... + cBar.IsValid() && + // + // Currently Happens ... + (cTriggerBlock.trigger.to == zBar.time || + cTriggerBlock.trigger.to == cBar.time) && + // + // Price Validations ... + (cTriggerBlock.IsBullish() + ? cBar.low > cTriggerBlock.trigger.lower + : cBar.high < cTriggerBlock.trigger.upper) + // + ; + if (isTriggerBlockSelected) + { + break; + } + + // + // Clean Trigger Block ... + cTriggerBlock.Clean(); + } + Clean(tmpTBs); + + // + // Check Trigger Block Selection ... + result = isTriggerBlockSelected; + if (result) + { + // + bool isBullish = cTriggerBlock.IsBullish(); + bool isBearish = cTriggerBlock.IsBearish(); + + // + // Now we have to Check Newest Trigger Block Place ... + int insideTBIDX = DetectInsideTriggerBlock( + cTriggerBlock, + cInsideTriggerBlock, + triggerBlocks // + ); + + // + // Check InsideTB is Exists and Valid ... + result = + cInsideTriggerBlock.IsValid() && + IsValidIndex(insideTBIDX); + if (result) + { + // + // Now we Have to Detect Peak and Vales ... + result = + cPeak.IsValid() && + cVale.IsValid(); + + // + // If Exists Before Validate them based Trigger Blocks ... + if (result) + { + // + // Validate cPeak and cVale based on + // cTriggerBlock and cInsideTriggerBlock ... + result = + // + // Peak ... + cPeak.lower > cTriggerBlock.trigger.upper && + cPeak.lower > cInsideTriggerBlock.trigger.upper && + // + // Vale ... + cVale.upper < cTriggerBlock.trigger.lower && + cVale.upper < cInsideTriggerBlock.trigger.lower && + // + // Bar Validation ... + cBar.IsValid() && + cBar.low > cVale.upper && + cBar.high < cPeak.lower + // + ; + if (!result) + { + // + cPeak.Clean(); + cVale.Clean(); + + // + waitsUntilPeakInvalidate = false; + waitsUntilValeInvalidate = false; + } + } + + // + // if not Exists, or Clean them on Invalidating Process, try to Find Corrects ... + if (!result) + { + // + // Selecting Peak ... + XBoxZone tmpPeaks[]; + detector.FillPeakPivots(tmpPeaks); + while (HasChild(tmpPeaks)) + { + // + // Find Index ... + int idx = GetLowest(tmpPeaks); + if (!IsValidIndex(idx)) + { + break; + } + + // + // Select ... + cPeak = tmpPeaks[idx]; + ArrayRemove( + tmpPeaks, + idx, + 1 // + ); + + // + // Validate Peak ... + bool isValid = + // + // Bar Validation ... + cBar.IsValid() && + cBar.high < cPeak.lower && + // + // Peak Validation ... + cPeak.lower > cTriggerBlock.trigger.upper && + cPeak.lower > cInsideTriggerBlock.trigger.upper; + if (isValid) + { + break; + } + + // + cPeak.Clean(); + } + Clean(tmpPeaks); + + // + // Selecting Vale ... + XBoxZone tmpVales[]; + detector.FillValePivots(tmpVales); + while (HasChild(tmpVales)) + { + // + // Find Index ... + int idx = GetHighest(tmpVales); + if (!IsValidIndex(idx)) + { + break; + } + + // + // Select ... + cVale = tmpVales[idx]; + ArrayRemove( + tmpVales, + idx, + 1 // + ); + + // + // Validate Vale ... + bool isValid = + // + // Bar Validation ... + cBar.IsValid() && + cBar.low > cVale.upper && + // + // Vale Validation ... + cVale.upper < cTriggerBlock.trigger.lower && + cVale.upper < cInsideTriggerBlock.trigger.lower; + if (isValid) + { + break; + } + + // + cVale.Clean(); + } + Clean(tmpVales); + + // + // Summarizing Result ... + result = + cPeak.IsValid() && + cVale.IsValid(); + } + + // + // Check Peak and Vale Exists ... + if (result) + { + // + // Remove Peak from Detector Collections ... + // and Make it unavailable ... + UseBox(cPeak); + + // + // Remove Vale from Detector Collections ... + // and Make it unavailable ... + UseBox(cVale); + + // + // Remove Selected Trigger Block ... + // and Make it unavailable ... + RemoveTriggerBlock( + cTriggerBlock, + triggerBlocks // + ); + UseTriggerBlock(cTriggerBlock); + + // + // Remove Selected Inside Trigger Block ... + // and Make it unavailable ... + RemoveTriggerBlock( + cInsideTriggerBlock, + triggerBlocks // + ); + UseTriggerBlock(cInsideTriggerBlock); + + // + // Update Peak and Vales To ... + cPeak.to = cTime; + cVale.to = cTime; + + // + // Draw Peak and Vales ... + if (allowDraws) + { + // + drawer.DrawBox(cPeak); + drawer.DrawBox(cVale); + } + + // + // Validate Peaks and Vales ... + bool isPeakPassed = false; + bool isValePassed = false; + cInsideTriggerBlock.trigger.to = cTime; + int toIDX = cInsideTriggerBlock.ToIndex(); + int fromIDX = cInsideTriggerBlock.FromIndex(); + for (int i = toIDX; i < fromIDX; i++) + { + // + // Reading Values ... + + // + double iPeak = helper.GetPeak(i); + double iPPeak = helper.GetPeak(i + 1); + + // + double iVale = helper.GetVale(i); + double iPVale = helper.GetVale(i + 1); + + // + bool isPeakOverLast = iPeak > iPPeak; + bool isPeakUnderLast = iPeak < iPPeak; + + // + bool isValeOverLast = iVale > iPVale; + bool isValeUnderLast = iVale < iPVale; + + // + if (!isPeakPassed) + { + // + isPeakPassed = + isBullish ? isPeakOverLast + : isPeakUnderLast; + } + + // + if (!isValePassed) + { + // + isValePassed = + isBullish + ? isValeUnderLast + : isPeakOverLast; + } + + // + result = + isPeakPassed && + isValePassed; + if (result) + { + break; + } + } + if (result) + { + // + // Draw Trigger Blocks if Allowed ... + if (allowDraws) + { + // + // Draw Blocks ... + + // + // mObjects.Clear(); + + // + // Detected Block ... + DrawTriggerBlock( + cTriggerBlock, + drawer.drawer, + mObjects, + cTime, + false // Draw Signal ... + ); + + // + // Inside Block ... + DrawTriggerBlock( + cInsideTriggerBlock, + drawer.drawer, + mObjects, + cTime, + false // Draw Signal ... + ); + } + + // + if (isBullish) + { + waitsUntilPeakInvalidate = true; + } + else if (isBearish) + { + waitsUntilValeInvalidate = true; + } + + // + mConditions.triggerBlock = cTriggerBlock; + } + } + } + } + } + + // + // Preparing Conditions based on result ... + if (result) + { + // + bool isBullish = mConditions.triggerBlock.IsBullish(); + + // + // Preparing mConditions ... + mConditions.dir = + mConditions + .triggerBlock + .GetDirection(); + mConditions.symbol = symbol; + mConditions.period = period; + mConditions.provider = provider; + mConditions.reward = riskToRewardRatio; + mConditions.time = mConditions.conditions.bars[0].time; + mConditions.setupTime = mConditions.conditions.bars[0].time; + + // + // Prepare Target ... + double targets[]; + for (int i = 1; i <= riskToRewardRatio; i++) + { + // + Add( + (double)i, + targets // + ); + } + + // + // Calculate SL Additions ... + double iATR = 0; + if (barIndex > 0 && + barIndex < ArraySize(helper.atrBuffer)) + { + iATR = helper.atrBuffer[barIndex]; + } + double slAdditional = slATRMultiplier * iATR; + + // + // Preparing Signal ... + result = ToSignal( + mConditions.triggerBlock.trigger, + mConditions.triggerBlock.signal, + targets, + slAdditional // + ); + XSignal insideTBSignal; + result = + result && + ToSignal( + cInsideTriggerBlock.trigger, + insideTBSignal, + targets, + slAdditional // + ); + if (result) + { + // + // Try to Use SL Based on Inside Trigger Block ... + double sl = 0; + double tp = 0; + if (secondsTriggersSLUsingFirstTriggerBlock) + { + // + sl = insideTBSignal.sl; + tp = insideTBSignal.tp; + + // + // Add Target for usuall Signal TP ... + XTarget iTarget; + iTarget.doRF = true; + iTarget.target = mConditions.triggerBlock.signal.tp; + + // + AddRef( + iTarget, + mConditions.targets); + + // + iTarget.Clean(); + } + else + { + // + sl = mConditions.triggerBlock.signal.sl; + tp = mConditions.triggerBlock.signal.tp; + } + + // + mConditions.sl = sl; + mConditions.tp = tp; + mConditions.pivot = sl; + mConditions.triggerBlock.signal.provider = provider; + mConditions.entry = mConditions.triggerBlock.signal.entry; + mConditions.point = mConditions.triggerBlock.signal.entry; + mConditions.type = ToPositionType(mConditions.triggerBlock.signal.type); + + // + // Draw Trigger Block ... + if (allowDraws) + { + // + DrawTriggerBlock( + mConditions.triggerBlock, + drawer.drawer, + mObjects, + NULL, // To ... + false // Draw Signal ... + ); + } + } + } + } + + // + // Check a Signal Setup Exists or not ... + result = mConditions.IsValid() && + mConditions.IsSetuped(); + + // + // Cleanup Resource ... + zBar.Clean(); + cBar.Clean(); + cTriggerBlock.Clean(); + cInsideTriggerBlock.Clean(); + + // + return result; + } + + /** + * Detect Trigger Conditions for Specified Signal ... + * + * @param conditions: XCATBEAStrategyConditions instance Reference, Specified Signal Conditions ... + * @param maxAllowedSetupAge: specified Setup Age for Expiration (if bigger than Zero) ... + * + * @return ( bool ) + */ + bool DetectSignalTrigger( + XCATBEAStrategyConditions &conditions, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Normalize Args ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Validate Setup ... + result = conditions.IsSetuped(); + if (!result) + { + return result; + } + + // + bool has = false; + datetime cTime = TimeCurrent(); + bool isBullish = IsBullish(conditions.dir); + bool isBearish = IsBearish(conditions.dir); + + // + bool isBasedOnPivotZone = conditions.pivotZone.IsValid(); + bool isBasedOnTriggerBlock = conditions.triggerBlock.IsValid(); + + // + // Reading Current Market Conditions ... + X121XCatbConditions cConditions; + result = + result && + helper.GetConditions( + cConditions, + barIndex, + 10 // + ); + + // + // Validate Direction of Setuped Conditions ... + result = + result && + (isBullish || + isBearish); + + // + // Detecting Trigger Bar ... + + // + ENUM_X_DIRECTION triggerDir; + bool isTriggerBar = barAnalyser + .IsValidForTrigger( + cConditions.bars[0], + triggerDir, + false, // Allow Cond 1 ... + false, // Allow Cond 2 ... + false, // Allow Cond 3 ... + false, // Allow Cond 4 ... + false, // Allow Cond 5 ... + false, // Allow Cond 6 ... + true // Allow Cond 7 ... + // + ); + bool isBullishTriggerBar = + isTriggerBar && + IsBullish(triggerDir); + bool isBearishTriggerBar = + isTriggerBar && + IsBearish(triggerDir); + + // + // Do Triggering Senario based on Trigger Block ... + if (result && + isBasedOnTriggerBlock) + { + // + // Checking Score ... + double bullishScore = 0; + double bearishScore = 0; + conditions + .conditions + .GenerateScore( + bullishScore, + bearishScore // + ); + bool isScorePassed = + isBullish + ? bullishScore > bearishScore + : bearishScore > bullishScore; + + // + // Complete Conditions Here ... + if (isScorePassed) + { + conditions.triggerTime = TimeCurrent(); + } + } + + // + // Do Triggering based on Market Conditions PivotZones ... + if (result && + isBasedOnPivotZone) + { + // + // Update Box To ... + conditions.pivotZone.to = cTime; + + // + // Draw Box ... + XCBoxObject *iObj; + has = drawer + .drawer + .DrawBox( + conditions.pivotZone, + iObj // + ); + if (has) + { + mObjects.Add(iObj); + } + + // + // Check atleast 3 Bars Close Outside of applied Edge ... + // Check Current Bar is a Trigger Bar ... + // TODO: Complete this ... + // + } + + // + // Do Other Validation Senarios ... + + // + result = conditions.IsValid() && + conditions.IsSetuped() && + conditions.CanTrigger(); + + // + // Check Setup Age or Setup Validations here ... + if (!result) + { + // + // Validate Trigger Block Based Setups ... + + // + // Validate Pivot Zone Based Setups ... + + // + // Validate Setup Age ... + } + + // + // Cleanup Resources ... + + // + return result; + } + + /** + * Detect Guards bsed on Signalling Class ... + * + * @param guards: XCAEAGuard instance Collection, Holds Provided Guards ... + * @param positions: XPosition instance Collection, Provides Signalling Based Positions for Apply Guards on them ... + * @param provider: X121SMCStrategySignalProviderData instance Reference, Specified Data for Cycles ... + * + * @return ( bool ) + */ + bool DetectGuards( + XGuard &guards[], + const XPosition &positions[], + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Normalize Args ... + Clean(guards); + barIndex = NormalizeInt(barIndex, 0); + + // + result = allowGuards && + HasChild(positions); + if (!result) + { + return result; + } + + // + // TODO: Implement this ... + + // + result = HasChild(guards); + + // + // Cleanup Resources ... + + // + if (!result) + { + Clean(guards); + } + + // + return result; + } + + // + // Protected ... + protected: + // + + /** + * Initialize ... + */ + void Init(XCATBEASignallerInputs &inputs) + { + // + maxAllowedCollection = 100; + + // + allowSignallingBasedOnConditions = inputs.signallerConfigs.allowSignallingBasedOnConditions; + allowSignallingBasedOnTriggerBlocks = inputs.signallerConfigs.allowSignallingBasedOnTriggerBlocks; + allowSignallingBasedOnTriggerBlocksInsideOther = inputs.signallerConfigs.allowSignallingBasedOnTriggerBlocksInsideOther; + + // + secondsTriggersSLUsingFirstTriggerBlock = inputs.signallerConfigs.secondsTriggersSLUsingFirstTriggerBlock; + applyValidateAndFilterOnSelectInsideOthers = inputs.signallerConfigs.applyValidateAndFilterOnSelectInsideOthers; + + // + allowSignallingConditions1 = inputs.signallerConfigs.allowSignallingConditions1; + allowSignallingConditions2 = inputs.signallerConfigs.allowSignallingConditions2; + allowSignallingConditions3 = inputs.signallerConfigs.allowSignallingConditions3; + allowSignallingConditions4 = inputs.signallerConfigs.allowSignallingConditions4; + allowSignallingConditions5 = inputs.signallerConfigs.allowSignallingConditions5; + allowSignallingConditions6 = inputs.signallerConfigs.allowSignallingConditions6; + + // + bool has = inputs.IsValid(); + if (!has) + { + return; + } + + // + symbol = inputs.symbol; + period = inputs.period; + filters = inputs.filters; + provider = inputs.provider; + allowDraws = inputs.allowDraws; + allowGuards = inputs.allowGuards; + validations = inputs.validations; + slATRMultiplier = inputs.slATRMultiplier; + riskToRewardRatio = inputs.riskToRewardRatio; + + // + mObjects = new CArrayObj(); + + // + // Initialize Bar Tracker ... + has = barTraker.Init( + symbol, + period // + ); + if (!has) + { + return; + } + + // + // Initialize Bar Analyser ... + barAnalyser = new XCBarAnalyser(); + + // + // initialize Helper ... + helper = new XCX121XCatbHelper(); + has = helper.Init( + symbol, + period, + inputs.catbInputs // + ); + if (!has) + { + return; + } + + // + mConditions.Clean(); + Clean(mConditionsCollection); + + // + InitPOI(); + } + + /** + * DeInitialize ... + */ + void DeInit() + { + // + mObjects.Clear(); + delete mObjects; + ZeroMemory(mObjects); + + // + drawer.Clear(); + delete drawer; + ZeroMemory(drawer); + + // + detector.CleanPivots(); + delete detector; + ZeroMemory(detector); + + // + delete helper; + ZeroMemory(helper); + + // + delete barAnalyser; + ZeroMemory(barAnalyser); + + // + barTraker.Clean(); + } + + /** + * Add Conditions to Conditions Collection if not Exists ... + * + * @param maxAllowed: int, Specified Max Allowed Holding Conditions ... + * + * @return ( int ) + */ + int AddConditionsIfNotExists( + int maxAllowed = 50 // + ) + { + // + int result = 0; + + // + // Normalize Args ... + maxAllowed = maxAllowedCollection; + + // + bool isSetuped = IsValid(mConditions.setupTime) && + HasDirection(mConditions.dir); + if (!isSetuped) + { + return result; + } + + // + int count = ArraySize(mConditionsCollection); + if (IsValidSize(count)) + { + // + // Copy Original Items ... + XCATBEAStrategyConditions tmpItems[]; + Copy( + mConditionsCollection, + tmpItems // + ); + + // + // Prese Item Data ... + bool isBullish = IsBullish(mConditions.dir); + + // + for (int i = 0; i < count; i++) + { + // + XCATBEAStrategyConditions iItem = tmpItems[i]; + + // + bool canRemove = mConditions.dir == iItem.dir && + mConditions.pivot == iItem.pivot; + if (canRemove) + { + // + ArrayRemove( + mConditionsCollection, + i, + 1 // + ); + } + } + + // + Clean(tmpItems); + } + + // + AddRef( + mConditions, + mConditionsCollection // + ); + + // + // Remove Olds ... + CleanupArray( + mConditionsCollection, + maxAllowed // + ); + + // + result = ArraySize(mConditionsCollection); + + // + return result; + } + + /** + * Add TriggerBlock if not Exists + * inside a Collection ... + */ + int AddIfNotExists( + XTriggerBlock &tb, + XTriggerBlock &tbs[], + int maxAllowed = 50 // + ) + { + // + int result = 0; + + // + // Normalize Args ... + maxAllowed = maxAllowedCollection; + + // + // First Validate ... + if (!tb.IsValid()) + { + return result; + } + + // + // Check Exists ... + // and prevent moving forward if exists ... + int idx = -1; + bool isExists = FindTriggerBlockIndex( + idx, + tb, + tbs // + ); + result = !isExists; + if (!result) + { + return result; + } + + // + // Add if not Exists ... + AddRef( + tb, + tbs // + ); + + // + // Cleanup ... + CleanupArray( + tbs, + maxAllowed // + ); + + // + result = ArraySize(tbs); + + // + return result; + } + + /** + * Use Specified Box and make it Unavailable ... + * + * @param box: XBoxZone instance reference ... + */ + void UseBox(XBoxZone &box) + { + // + // Validate Box ... + bool has = box.IsValid(); + if (!has) + { + return; + } + + // + // Check Box Added Before or not ... + int idx = -1; + has = FindBoxIndex( + idx, + box, + unavailableZones // + ); + if (has) + { + return; + } + + // + // Adding Box Reference to + // Unavailable Zones ... + AddRef( + box, + unavailableZones // + ); + + // + // Cleanup Array ... + CleanupArray( + unavailableZones, + maxAllowedCollection // + ); + + // + } + + /** + * Use Specified Trigger Block and Make it Un Available ... + * + * @param tb: XTriggerBlock instance reference, Specified Used Trigger Block ... + */ + void UseTriggerBlock(XTriggerBlock &tb) + { + // + bool has = tb.IsValid(); + if (!has) + { + return; + } + + // + // Trigger Box ... + has = tb.trigger.IsValid(); + if (has) + { + UseBox(tb.trigger); + } + + // + // Order Block Box ... + has = tb.ob.IsValid(); + if (has) + { + UseBox(tb.ob); + } + + // + // Fair Value Gap ... + has = tb.fvg.IsValid(); + if (has) + { + UseBox(tb.fvg); + } + + // + // Following Liquidity ... + has = tb.fLiquidity.IsValid(); + if (has) + { + UseBox(tb.fLiquidity); + } + + // + // Reversal Liquidity ... + has = tb.rLiquidity.IsValid(); + if (has) + { + UseBox(tb.rLiquidity); + } + } + + /** + * Draw Exists Trigger Blocks ... + */ + void DrawTriggerBlocks(datetime to = NULL) + { + // + // Check Has Child of trigger Blocks ... + bool has = HasChild(triggerBlocks); + if (!has) + { + return; + } + + // + // Loop through Blocks ... + int count = ArraySize(triggerBlocks); + for (int i = 0; i < count; i++) + { + // + // Draw Indexed Trigger Block ... + DrawTriggerBlock( + triggerBlocks[i], + drawer.drawer, + mObjects, + to, + false // + ); + } + } + + // + // Private ... + private: + // + // Props ... + string symbol; + string provider; + CArrayObj *mObjects; + ENUM_TIMEFRAMES period; + int maxAllowedCollection; // Max Allowed Collection Items ... + + // + // Initialize and Configure POI Detector and Drawer ... + void InitPOI() + { + // + // Initialize POI Detector ... + bool has = helper != NULL; + if (has) + { + // + detector = new XCXCATBEAPOIDetector(helper); + + // + // Configure ... + + // + detector.detectPeakPivots = true; + detector.detectValePivots = true; + + // + detector.detectMTBullishPivots = true; + detector.detectMTBearishPivots = true; + + // + detector.detectOBBullishPivots = true; + detector.detectOBBearishPivots = true; + } + + // + // Initialize POI Drawer ... + has = detector != NULL; + if (has) + { + // + drawer = new XCXCATBEAPOIDrawer(detector); + + // + // Configure ... + drawer.drawPeakPivots = true; + drawer.drawValePivots = true; + + // + XCATBPivotStyle iStyle; + + // + // Styling Peak Pivot ... + iStyle.width = 1; + iStyle.clr = clrMagenta; + iStyle.style = STYLE_SOLID; + + // + drawer.peakPivotStyle = iStyle; + + // + // Styling Vale Pivot ... + iStyle.width = 1; + iStyle.clr = clrAqua; + iStyle.style = STYLE_SOLID; + + // + drawer.valePivotStyle = iStyle; + + // + // Cleanup Resources ... + + // + iStyle.Clean(); + } + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14040316/XCATBEA/Classes/xcatbea.x-poi.detector.class.mq5 b/BKPS/14040316/XCATBEA/Classes/xcatbea.x-poi.detector.class.mq5 new file mode 100644 index 0000000..7f9d744 --- /dev/null +++ b/BKPS/14040316/XCATBEA/Classes/xcatbea.x-poi.detector.class.mq5 @@ -0,0 +1,2738 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCXCAYBEAPOIDetector ... +// Description: Class for XCATBEA POI Detector ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm Class for XCATBEA POI Detector" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-bar.analyser.class.mq5" +#include "../../Helpers/x-saherelm.x121.xcatb.helper.mq5" +#include "../../Libraries/x-saherelm.x-poi.extensions.lib.mq5" + +// +// Definitions ... + +// +enum ENUM_XCATB_PIVOTS +{ + XCATB_NONE, // None + XCATB_PEAK, // Peak + XCATB_VALE, // Vale + XCATB_BULLISH_MT, // MTBull + XCATB_BEARISH_MT, // MTBear + XCATB_BULLISH_OB, // OBBull + XCATB_BEARISH_OB, // OBBear +}; + +// +bool IsValid(ENUM_XCATB_PIVOTS value) +{ + // + bool result = false; + + // + result = value != XCATB_NONE; + + // + return result; +} + +// +string ToString(ENUM_XCATB_PIVOTS value) +{ + // + string result = NULL; + + // + result = EnumToString(value); + + // + return result; +} + +// +ENUM_X_DIRECTION GetDirection(ENUM_XCATB_PIVOTS value) +{ + // + ENUM_X_DIRECTION result = X_DIRECTION_NONE; + + // + switch (value) + { + // + case XCATB_VALE: + case XCATB_BULLISH_MT: + case XCATB_BULLISH_OB: + result = X_DIRECTION_BULLISH; + break; + + // + case XCATB_PEAK: + case XCATB_BEARISH_MT: + case XCATB_BEARISH_OB: + result = X_DIRECTION_BEARISH; + break; + } + + // + return result; +} + +// +string GetBoxType(ENUM_XCATB_PIVOTS value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case XCATB_VALE: + case XCATB_PEAK: + result = ToString(value); + break; + + // + case XCATB_BULLISH_MT: + case XCATB_BEARISH_MT: + result = "XMT"; + break; + + // + case XCATB_BULLISH_OB: + case XCATB_BEARISH_OB: + result = "XOB"; + break; + } + + // + return result; +} + +// +ENUM_XCATB_PIVOTS GetPivotType(XBoxZone &value) +{ + // + ENUM_XCATB_PIVOTS result = XCATB_NONE; + + // + bool has = value.IsValid(); + if (!has) + { + return result; + } + + // + bool isPeak = value.type == GetBoxType(XCATB_PEAK) && + value.dir == GetDirection(XCATB_PEAK); + bool isVale = value.type == GetBoxType(XCATB_VALE) && + value.dir == GetDirection(XCATB_VALE); + bool isBullishMT = value.type == GetBoxType(XCATB_BULLISH_MT) && + value.dir == GetDirection(XCATB_BULLISH_MT); + bool isBearishMT = value.type == GetBoxType(XCATB_BEARISH_MT) && + value.dir == GetDirection(XCATB_BEARISH_MT); + bool isBullishOB = value.type == GetBoxType(XCATB_BULLISH_OB) && + value.dir == GetDirection(XCATB_BULLISH_OB); + bool isBearishOB = value.type == GetBoxType(XCATB_BEARISH_OB) && + value.dir == GetDirection(XCATB_BEARISH_OB); + + // + if (isPeak) + { + result = XCATB_PEAK; + } + else if (isVale) + { + result = XCATB_VALE; + } + else if (isBullishMT) + { + result = XCATB_BULLISH_MT; + } + else if (isBearishMT) + { + result = XCATB_BEARISH_MT; + } + else if (isBullishOB) + { + result = XCATB_BULLISH_OB; + } + else if (isBearishOB) + { + result = XCATB_BEARISH_OB; + } + + // + return result; +} + +// +struct XCATBPivot +{ + // + // Props ... + datetime to; + double value; + string symbol; + datetime from; + double reserve; + ENUM_XCATB_PIVOTS type; + ENUM_TIMEFRAMES period; + + // + double values[]; + + // + // Constructor ... + XCATBPivot() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + value = 0; + to = NULL; + reserve = 0; + from = NULL; + symbol = NULL; + period = NULL; + type = XCATB_NONE; + + // + Clean(values); + + // + ZeroMemory(this); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + from < to && + value != 0 && + IsValid(to) && + IsValid(from) && + IsValid(type) && + IsValid(symbol) && + IsValid(period); + + // + return result; + } + + /** + * Check a Model is Same as this or not ... + * + * @param pivot: XCATBPivot ... + * + * @return ( bool ) + */ + bool IsSameAs(XCATBPivot &pivot) + { + // + bool result = false; + + // + result = + IsValid() && + pivot.IsValid(); + if (!result) + { + return result; + } + + // + result = + to == pivot.to && + from == pivot.from && + type == pivot.type && + value == pivot.value && + symbol == pivot.symbol && + period == pivot.period; + + // + return result; + } + + /** + * Retrieve To Index ... + * + * @param forPeriod: ENUM_TIMEFRAMES, Specified Period ... + * + * @return ( int ) + */ + int ToIndex( + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + result = GetBarIndex( + symbol, + forPeriod, + to // + ); + + // + return result; + } + + /** + * Retrieve From Index ... + * + * @param forPeriod: ENUM_TIMEFRAMES, Specified Period ... + * + * @return ( int ) + */ + int FromIndex( + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + result = GetBarIndex( + symbol, + forPeriod, + from // + ); + + // + return result; + } + + /** + * Retrieve Age of Pivot ... + * + * @param forPeriod: ENUM_TIMEFRAMES, Specified Period ... + * + * @return ( int ) + */ + int GetAge( + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + int toIDX = ToIndex(forPeriod); + int fromIDX = FromIndex(forPeriod); + + // + result = fromIDX - toIDX; + + // + return result; + } + + /** + * Converts Pivot to Box ... + * + * @param box: XBoxZone instance reference ... + * + * @return ( bool ) + */ + bool AsBox( + XBoxZone &box // + ) + { + // + bool result = false; + + // + box.Clean(); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + ENUM_X_DIRECTION iDir = GetDirection(type); + + // + result = HasDirection(iDir); + if (!result) + { + return result; + } + + // + bool isBullish = + IsBullish(iDir) && + value < reserve; + + // + bool isBearish = + IsBearish(iDir) && + value > reserve; + + // + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + box.to = to; + box.dir = iDir; + box.from = from; + box.symbol = symbol; + box.period = period; + + // + string typeStr = GetBoxType(type); + box.type = typeStr; + + // + box.upper = + isBullish + ? reserve + : value; + box.lower = + isBullish + ? value + : reserve; + + // + result = box.IsValid(); + if (!result) + { + box.Clean(); + } + + // + return result; + } + + // +}; + +// +// Implementations ... +class XCXCATBEAPOIDetector : public XCBase +{ + // + // Public ... + public: + // + // Props ... + int maxAllowedPivots; // Max Allowed Holding Pibots ... + int pivotVerifications; // Pivots Verifications ... + int pivotDetectionLoopbac; // Pivots Detection Loopback ... + + // + // Breaked Pivots ... + XBoxZone invalidPivots[]; + + // + // Constructors ... + XCXCATBEAPOIDetector( + XCX121XCatbHelper *_helper // + ) + { + // + helper = _helper; + barAnalyser = new XCBarAnalyser(); + + // + Default(); + } + + // + // De Constructors ... + ~XCXCATBEAPOIDetector() + { + // + CleanPivots(); + + // + ZeroMemory(helper); + + // + delete barAnalyser; + ZeroMemory(barAnalyser); + } + + // + // Properties ... + + // + // Tools ... + + // + virtual void Default() + { + // + // COMMON ... + + // + maxAllowedPivots = 50; + pivotVerifications = 5; + pivotDetectionLoopbac = 100; + + // + // PV ... + + // + maxAllowedPVLifetime = 0; + selectRejectedPVPivots = false; + selectEngulfedPVPivots = false; + + // + detectPeakPivots = false; + detectValePivots = false; + + // + detectMTBullishPivots = false; + detectMTBearishPivots = false; + + // + detectOBBullishPivots = false; + detectOBBearishPivots = false; + } + + // + void Detect( + int barIndex = 0 // + ) + { + // + barIndex = NormalizeInt(barIndex, 0); + int loopback = pivotDetectionLoopbac; + loopback = NormalizeInt(loopback, 50); + + // + int idx = -1; + int count = 0; + bool has = false; + + // + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + int p3IDX = p2IDX + 1; + + // + newPeakPivotDetected = false; + newValePivotDetected = false; + newMTBullishPivotDetected = false; + newMTBearishPivotDetected = false; + newOBBullishPivotDetected = false; + newOBBearishPivotDetected = false; + + // + int index = barIndex; + int start = index; + int end = index + loopback; + while (start < end) + { + // + // Retrieve Conditions ... + X121XCatbConditions conditions; + has = helper.GetConditions( + conditions, + start, + 10 // + ); + if (!has) + { + conditions.Clean(); + continue; + } + + // + // Retrieve Bars ... + XOHCL zBar; + XOHCL cBar; + XOHCL pBar; + XOHCL p2Bar; + has = zBar.Init( + conditions.symbol, + conditions.period, + start // + ); + has = + has && + zBar.GetPreviousBar(cBar); + has = + has && + cBar.GetPreviousBar(pBar); + has = + has && + pBar.GetPreviousBar(p2Bar); + if (!has) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + conditions.Clean(); + + // + continue; + } + + // + // Checking Pivots ... + + // + // PV ... + + // + // PEAK ... + if (detectPeakPivots) + { + // + newPeakPivotDetected = DetectPeakAndValePivot( + barIndex, + X_DIRECTION_BEARISH, + zBar, + cBar, + pBar, + p2Bar, + conditions // + ); + } + + // + // VALE ... + if (detectValePivots) + { + // + newValePivotDetected = DetectPeakAndValePivot( + barIndex, + X_DIRECTION_BULLISH, + zBar, + cBar, + pBar, + p2Bar, + conditions // + ); + } + + // + // MT ... + + // + // Bullish ... + if (detectMTBullishPivots) + { + // + newMTBullishPivotDetected = DetectMTPivot( + barIndex, + X_DIRECTION_BULLISH, + zBar, + cBar, + pBar, + p2Bar, + conditions // + ); + } + + // + // Bearish ... + if (detectMTBearishPivots) + { + // + newMTBearishPivotDetected = DetectMTPivot( + barIndex, + X_DIRECTION_BEARISH, + zBar, + cBar, + pBar, + p2Bar, + conditions // + ); + } + + // + // OB ... + + // + // Bullish ... + if (detectOBBullishPivots) + { + // + newOBBullishPivotDetected = DetectOBPivot( + barIndex, + X_DIRECTION_BULLISH, + zBar, + cBar, + pBar, + p2Bar, + conditions // + ); + } + + // + // Bearish ... + if (detectOBBearishPivots) + { + // + newOBBearishPivotDetected = DetectOBPivot( + barIndex, + X_DIRECTION_BEARISH, + zBar, + cBar, + pBar, + p2Bar, + conditions // + ); + } + + // + // Others ... + + // + start++; + + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + conditions.Clean(); + } + + // + SortPivots(); + } + + // + void Validate( + XBoxZone &unavailables[], + int barIndex = 0 // + ) + { + // + // Implement Validation Senarios ... + + // + // PV ... + ValidatePeakValePivots( + unavailables, + barIndex // + ); + + // + // MT ... + ValidateMTPivots( + unavailables, + barIndex // + ); + + // + // OB ... + ValidateOBPivots( + unavailables, + barIndex // + ); + + // + SortPivots(); + } + + // + void CleanPivots() + { + // + Clean(invalidPivots); + + // + peakPivot.Clean(); + valePivot.Clean(); + + // + Clean(peakPivots); + Clean(valePivots); + + // + Clean(mtBullishPivots); + Clean(mtBearishPivots); + + // + Clean(obBullishPivots); + Clean(obBearishPivots); + } + + // + // Pivots ... + + // + // INVALID Pivots ... + + // + bool HasInvalidPivots() + { + return HasChild(invalidPivots); + } + + // + int CountInvalidPivots() + { + return ArraySize(invalidPivots); + } + + // + // PV ... + + // + int maxAllowedPVLifetime; // Max Allowed PV Life ... + bool selectRejectedPVPivots; // Select Rejected PV Pivots ... + bool selectEngulfedPVPivots; // Select Engulfed PV Pivots ... + + // + bool DetectPeakAndValePivot( + int barIndex, + ENUM_X_DIRECTION forDir, + XOHCL &zBar, + XOHCL &cBar, + XOHCL &pBar, + XOHCL &p2Bar, + X121XCatbConditions &conditions // + ) + { + // + bool result = false; + + // + // Checking Direction ... + result = HasDirection(forDir); + if (!result) + { + return result; + } + + // + bool forBullish = IsBullish(forDir); + bool forBearish = IsBearish(forDir); + + // + // Check Allowed ... + result = + forBullish + ? detectValePivots + : detectPeakPivots; + if (!result) + { + return result; + } + + // + // Validate Args ... + result = + // + barIndex >= 0 && + zBar.IsValid() && + cBar.IsValid() && + pBar.IsValid() && + p2Bar.IsValid() + // + ; + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + + // + datetime cTime = zBar.time; + string symbol = zBar.symbol; + ENUM_TIMEFRAMES period = zBar.period; + double points = GetPoints(symbol); + + // + // Reading Conditional Values ... + + // + // PEAK ... + double zPeak = conditions.peakBuffer[zIDX]; + double cPeak = conditions.peakBuffer[cIDX]; + double pPeak = conditions.peakBuffer[pIDX]; + double p2Peak = conditions.peakBuffer[p2IDX]; + + // + // PEAK Golden ... + double zPeakGolden = conditions.peakGoldenBuffer[zIDX]; + double cPeakGolden = conditions.peakGoldenBuffer[cIDX]; + double pPeakGolden = conditions.peakGoldenBuffer[pIDX]; + double p2PeakGolden = conditions.peakGoldenBuffer[p2IDX]; + + // + // VALE ... + double zVale = conditions.valeBuffer[zIDX]; + double cVale = conditions.valeBuffer[cIDX]; + double pVale = conditions.valeBuffer[pIDX]; + double p2Vale = conditions.valeBuffer[p2IDX]; + + // + // VALE Golden ... + double zValeGolden = conditions.valeGoldenBuffer[zIDX]; + double cValeGolden = conditions.valeGoldenBuffer[cIDX]; + double pValeGolden = conditions.valeGoldenBuffer[pIDX]; + double p2ValeGolden = conditions.valeGoldenBuffer[p2IDX]; + + // + // Detecting Bar Conditions ... + + // + ENUM_X_DIRECTION cBarDir; + + // + // Rejected ... + bool isCBarRejected = barAnalyser + .IsRejected( + cBar, + cBarDir, + false, // Force Type ... + false // Force Fibo Pressure ... + ); + + // + bool isCBarBullishRejected = + forBullish && + isCBarRejected && + IsBullish(cBarDir); + bool isCBarBearishRejected = + forBearish && + isCBarRejected && + IsBearish(cBarDir); + + // + bool isPBarRejected = barAnalyser + .IsRejected( + pBar, + cBarDir, + false, // Force Type ... + false // Force Fibo Pressure ... + ); + bool isPBarBullishRejected = + forBullish && + isPBarRejected && + IsBullish(cBarDir); + bool isPBarBearishRejected = + forBearish && + isPBarRejected && + IsBearish(cBarDir); + + // + bool isBarBullishRejected = + forBullish && + (isCBarBullishRejected || + isPBarBullishRejected); + + // + bool isBarBearishRejected = + forBearish && + (isCBarBearishRejected || + isPBarBearishRejected); + + // + // Engulfed ... + bool isCBarEngulfed = barAnalyser + .IsEngulfed( + cBar, + cBarDir // + ); + bool isCBarBullishEngulfed = + forBullish && + isCBarEngulfed && + IsBullish(cBarDir); + bool isCBarBearishEngulfed = + forBearish && + isCBarEngulfed && + IsBearish(cBarDir); + + // + bool isPBarEngulfed = barAnalyser + .IsEngulfed( + pBar, + cBarDir // + ); + bool isPBarBullishEngulfed = + forBullish && + isPBarEngulfed && + IsBullish(cBarDir); + bool isPBarBearishEngulfed = + forBearish && + isPBarEngulfed && + IsBearish(cBarDir); + + // + bool isBarBullishEngulfed = + forBullish && + (isCBarBullishEngulfed || + isPBarBullishEngulfed); + + // + bool isBarBearishEngulfed = + forBearish && + (isCBarBearishEngulfed || + isPBarBearishEngulfed); + + // + // Prepare Conditinal Conditions ... + + // + // PEAK ... + + // + bool isPeakSameLast = cPeak == pPeak; + bool isPeakSameLastPrev = pPeak == p2Peak; + + // + bool isPeakSwitchedToSameLast = isPeakSameLast && + !isPeakSameLastPrev; + bool isPeakFinishedFromSameLast = !isPeakSameLast && + isPeakSameLastPrev; + + // + // VALE ... + + // + bool isValeSameLast = cVale == pVale; + bool isValeSameLastPrev = pVale == p2Vale; + + // + bool isValeSwitchedToSameLast = isValeSameLast && + !isValeSameLastPrev; + bool isValeFinishedFromSameLast = !isValeSameLast && + isValeSameLastPrev; + + // + // Summarizing Conditions ... + + // + result = false; + + // + bool hasStartCondition = + // + forBullish + ? isValeFinishedFromSameLast + : isPeakFinishedFromSameLast + // + ; + + // + bool hasContinuationCondition = + // + forBullish + ? isValeSameLast + : isPeakSameLast + // + ; + + // + bool hasEndCondition = + // + forBullish + ? isValeSwitchedToSameLast + : isPeakSwitchedToSameLast + // + ; + + // + // Apply Validations ... + if (hasEndCondition) + { + // + bool hasSelectionType = selectRejectedPVPivots || + selectEngulfedPVPivots; + + // + bool isPVRejected = + forBullish + ? (isBarBullishRejected && + selectRejectedPVPivots) + : (isBarBearishRejected && + selectRejectedPVPivots); + + // + bool isPVEngulfed = + forBullish + ? (isBarBullishEngulfed && + selectEngulfedPVPivots) + : (isBarBearishEngulfed && + selectEngulfedPVPivots); + + // + bool isBarPassed = + !hasSelectionType + ? true + : isPVRejected || + isPVEngulfed; + + // + hasEndCondition = + isBarPassed && + hasEndCondition; + if (!hasEndCondition) + { + // + // VALE ... + if (forBullish) + { + valePivot.Clean(); + } + + // + // PEAK ... + if (forBearish) + { + peakPivot.Clean(); + } + } + } + + // + // + // + + // + // ReInstance Pivot ... + if (hasStartCondition) + { + // + // VALE ... + if (forBullish) + { + // + valePivot.Clean(); + + // + valePivot.type = XCATB_VALE; + valePivot.symbol = symbol; + valePivot.period = period; + + // + valePivot.to = pBar.time; + valePivot.from = pBar.time; + valePivot.value = pVale; + valePivot.reserve = pValeGolden; + } + + // + // PEAK ... + if (forBearish) + { + // + peakPivot.Clean(); + + // + peakPivot.type = XCATB_PEAK; + peakPivot.symbol = symbol; + peakPivot.period = period; + + // + peakPivot.to = pBar.time; + peakPivot.from = pBar.time; + peakPivot.value = pPeak; + peakPivot.reserve = pPeakGolden; + } + } + + // + // Calculate and Fill Pivot Requirements ... + if (hasContinuationCondition) + { + // + // VALE ... + if (forBullish) + { + // + valePivot.from = pBar.time; + + // + valePivot.reserve = + valePivot.reserve == 0 + ? pValeGolden + : MathMin(valePivot.reserve, pValeGolden); + } + + // + // PEAK ... + if (forBearish) + { + // + peakPivot.from = pBar.time; + + // + peakPivot.reserve = + peakPivot.reserve == 0 + ? pPeakGolden + : MathMax(peakPivot.reserve, pPeakGolden); + } + } + + // + // End up Pivot and Store it ... + if (hasEndCondition) + { + // + // VALE ... + if (forBullish) + { + // + result = + valePivot.IsValid() && + valePivot.GetAge() >= pivotVerifications; + if (result) + { + // + XBoxZone iBox; + result = valePivot.AsBox(iBox); + if (result) + { + // + newValePivotDetected = AddBox( + iBox, + valePivots // + ); + } + + // + iBox.Clean(); + } + + // + valePivot.Clean(); + } + + // + // PEAK ... + if (forBearish) + { + // + result = + peakPivot.IsValid() && + peakPivot.GetAge() >= pivotVerifications; + if (result) + { + // + XBoxZone iBox; + result = peakPivot.AsBox(iBox); + if (result) + { + // + newPeakPivotDetected = AddBox( + iBox, + peakPivots // + ); + } + + // + iBox.Clean(); + } + + // + peakPivot.Clean(); + } + } + + // + return result; + } + + // + void ValidatePeakValePivots( + XBoxZone &unavailables[], + int barIndex = 0 // + ) + { + // + bool has = false; + + // + bool applyLifetimeValidating = maxAllowedPVLifetime > 0; + + // + // PEAK ... + has = HasPeakPivots(); + if (has) + { + // + ApplyValidationOnBoxes( + peakPivots, + unavailables, + barIndex // + ); + + // + if (applyLifetimeValidating) + { + // + ApplyLifeTimeValidationOnBoxes( + peakPivots, + maxAllowedPVLifetime, + barIndex // + ); + } + } + + // + // VALE ... + has = HasValePivots(); + if (has) + { + // + ApplyValidationOnBoxes( + valePivots, + unavailables, + barIndex // + ); + + // + if (applyLifetimeValidating) + { + // + ApplyLifeTimeValidationOnBoxes( + valePivots, + maxAllowedPVLifetime, + barIndex // + ); + } + } + } + + // + // PEAK ... + + // + XCATBPivot peakPivot; + bool detectPeakPivots; + XBoxZone peakPivots[]; + bool newPeakPivotDetected; + + // + bool HasPeakPivots() + { + return HasChild(peakPivots); + } + + // + int CountPeakPivots() + { + return ArraySize(peakPivots); + } + + // + int FillPeakPivots(XBoxZone &pivots[]) + { + // + int result = 0; + + // + Clean(pivots); + + // + if (!HasPeakPivots()) + { + return result; + } + + // + int count = CountPeakPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iPivot = peakPivots[i]; + + // + AddRef( + iPivot, + pivots // + ); + + // + iPivot.Clean(); + } + + // + result = ArraySize(pivots); + + // + return result; + } + + // + // VALE ... + + // + XCATBPivot valePivot; + bool detectValePivots; + XBoxZone valePivots[]; + bool newValePivotDetected; + + // + bool HasValePivots() + { + return HasChild(valePivots); + } + + // + int CountValePivots() + { + return ArraySize(valePivots); + } + + // + int FillValePivots(XBoxZone &pivots[]) + { + // + int result = 0; + + // + Clean(pivots); + + // + if (!HasValePivots()) + { + return result; + } + + // + int count = CountValePivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iPivot = valePivots[i]; + + // + AddRef( + iPivot, + pivots // + ); + + // + iPivot.Clean(); + } + + // + result = ArraySize(pivots); + + // + return result; + } + + // + // MITIGATIONBLOCK ... + + // + int maxAllowedMTLifetime; // Max Allowed MT Life ... + + // + bool DetectMTPivot( + int barIndex, + ENUM_X_DIRECTION forDir, + XOHCL &zBar, + XOHCL &cBar, + XOHCL &pBar, + XOHCL &p2Bar, + X121XCatbConditions &conditions // + ) + { + // + bool result = false; + + // + // Checking Direction ... + result = HasDirection(forDir); + if (!result) + { + return result; + } + + // + bool forBullish = IsBullish(forDir); + bool forBearish = IsBearish(forDir); + + // + // Check Allowed ... + result = + forBullish + ? detectMTBullishPivots + : detectMTBearishPivots; + if (!result) + { + return result; + } + + // + // Validate Args ... + result = + // + barIndex >= 0 && + zBar.IsValid() && + cBar.IsValid() && + pBar.IsValid() && + p2Bar.IsValid() + // + ; + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + + // + datetime cTime = zBar.time; + string symbol = zBar.symbol; + ENUM_TIMEFRAMES period = zBar.period; + double points = GetPoints(symbol); + + // + // Detecting Bar Conditions ... + + // + ENUM_X_DIRECTION cBarDir; + + // + // Rejected ... + bool isCBarRejected = barAnalyser + .IsRejected( + cBar, + cBarDir, + false, // Force Type ... + true // Force Fibo Pressure ... + ); + + // + bool isCBarBullishRejected = + forBullish && + isCBarRejected && + IsBullish(cBarDir); + bool isCBarBearishRejected = + forBearish && + isCBarRejected && + IsBearish(cBarDir); + + // + // Prepare Conditinal Conditions ... + + // + // Summarizing Conditions ... + + // + result = false; + + // + bool hasEndCondition = + // + forBullish + ? isCBarBullishRejected + : isCBarBearishRejected + // + ; + + // + // End up Pivot and Store it ... + if (hasEndCondition) + { + // + XBoxZone iPivot; + iPivot.to = zBar.time; + iPivot.from = cBar.time; + iPivot.symbol = cBar.symbol; + iPivot.period = cBar.period; + + // + // Bullish ... + if (forBullish) + { + // + iPivot.lower = cBar.low; + iPivot.upper = cBar.GetDown(); + iPivot.dir = X_DIRECTION_BULLISH; + iPivot.type = GetBoxType(XCATB_BULLISH_MT); + + // + result = iPivot.IsValid(); + if (result) + { + // + newMTBullishPivotDetected = AddBox( + iPivot, + mtBullishPivots // + ); + } + } + + // + // Bearish ... + if (forBearish) + { + // + iPivot.upper = cBar.high; + iPivot.lower = cBar.GetUp(); + iPivot.dir = X_DIRECTION_BEARISH; + iPivot.type = GetBoxType(XCATB_BEARISH_MT); + + // + result = iPivot.IsValid(); + if (result) + { + // + newMTBearishPivotDetected = AddBox( + iPivot, + mtBearishPivots // + ); + } + } + } + + // + return result; + } + + // + void ValidateMTPivots( + XBoxZone &unavailables[], + int barIndex = 0 // + ) + { + // + bool has = false; + + // + bool applyLifetimeValidating = maxAllowedMTLifetime > 0; + + // + // Bullish ... + has = HasMTBullishPivots(); + if (has) + { + // + ApplyValidationOnBoxes( + mtBullishPivots, + unavailables, + barIndex // + ); + + // + if (applyLifetimeValidating) + { + // + ApplyLifeTimeValidationOnBoxes( + mtBullishPivots, + maxAllowedMTLifetime, + barIndex // + ); + } + } + + // + // Bearish ... + has = HasMTBearishPivots(); + if (has) + { + // + ApplyValidationOnBoxes( + mtBearishPivots, + unavailables, + barIndex // + ); + + // + if (applyLifetimeValidating) + { + // + ApplyLifeTimeValidationOnBoxes( + mtBearishPivots, + maxAllowedMTLifetime, + barIndex // + ); + } + } + } + + // + // Bullish ... + XBoxZone mtBullishPivots[]; + bool detectMTBullishPivots; + bool newMTBullishPivotDetected; + + // + bool HasMTBullishPivots() + { + return HasChild(mtBullishPivots); + } + + // + int CountMTBullishPivots() + { + return ArraySize(mtBullishPivots); + } + + // + int FillMTBullishPivots(XBoxZone &pivots[]) + { + // + int result = 0; + + // + Clean(pivots); + + // + if (!HasMTBullishPivots()) + { + return result; + } + + // + int count = CountMTBullishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iPivot = mtBullishPivots[i]; + + // + AddRef( + iPivot, + pivots // + ); + + // + iPivot.Clean(); + } + + // + result = ArraySize(pivots); + + // + return result; + } + + // + // Bearish ... + XBoxZone mtBearishPivots[]; + bool detectMTBearishPivots; + bool newMTBearishPivotDetected; + + // + bool HasMTBearishPivots() + { + return HasChild(mtBearishPivots); + } + + // + int CountMTBearishPivots() + { + return ArraySize(mtBearishPivots); + } + + // + int FillMTBearishPivots(XBoxZone &pivots[]) + { + // + int result = 0; + + // + Clean(pivots); + + // + if (!HasMTBearishPivots()) + { + return result; + } + + // + int count = CountMTBearishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iPivot = mtBearishPivots[i]; + + // + AddRef( + iPivot, + pivots // + ); + + // + iPivot.Clean(); + } + + // + result = ArraySize(pivots); + + // + return result; + } + + // + // ORDERBLOCK ... + + // + int maxAllowedOBLifetime; // Max Allowed MT Life ... + + // + bool DetectOBPivot( + int barIndex, + ENUM_X_DIRECTION forDir, + XOHCL &zBar, + XOHCL &cBar, + XOHCL &pBar, + XOHCL &p2Bar, + X121XCatbConditions &conditions // + ) + { + // + bool result = false; + + // + // Checking Direction ... + result = HasDirection(forDir); + if (!result) + { + return result; + } + + // + bool forBullish = IsBullish(forDir); + bool forBearish = IsBearish(forDir); + + // + // Check Allowed ... + result = + forBullish + ? detectOBBullishPivots + : detectOBBearishPivots; + if (!result) + { + return result; + } + + // + // Validate Args ... + result = + // + barIndex >= 0 && + zBar.IsValid() && + cBar.IsValid() && + pBar.IsValid() && + p2Bar.IsValid() + // + ; + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + + // + datetime cTime = zBar.time; + string symbol = zBar.symbol; + ENUM_TIMEFRAMES period = zBar.period; + double points = GetPoints(symbol); + + // + XBoxZone iPivot; + + // + // Detecting Bar Conditions ... + + // + + // + // OB ... + bool isOB = barAnalyser + .IsOB( + cBar, + iPivot, + false, + false // + ); + + // + bool isBullishOB = + isOB && + iPivot.IsBullish(); + bool isBearishOB = + isOB && + iPivot.IsBearish(); + + // + // Prepare Conditinal Conditions ... + + // + // Summarizing Conditions ... + + // + result = false; + + // + bool hasEndCondition = + // + forBullish + ? isBullishOB + : isBearishOB + // + ; + + // + // End up Pivot and Store it ... + if (hasEndCondition) + { + // + // Bullish ... + if (forBullish) + { + // + iPivot.type = GetBoxType(XCATB_BULLISH_OB); + + // + result = iPivot.IsValid(); + if (result) + { + // + newOBBullishPivotDetected = AddBox( + iPivot, + obBullishPivots // + ); + } + } + + // + // Bearish ... + if (forBearish) + { + // + iPivot.type = GetBoxType(XCATB_BEARISH_OB); + + // + result = iPivot.IsValid(); + if (result) + { + // + newOBBearishPivotDetected = AddBox( + iPivot, + obBearishPivots // + ); + } + } + } + + // + return result; + } + + // + void ValidateOBPivots( + XBoxZone &unavailables[], + int barIndex = 0 // + ) + { + // + bool has = false; + + // + bool applyLifetimeValidating = maxAllowedOBLifetime > 0; + + // + // Bullish ... + has = HasOBBullishPivots(); + if (has) + { + // + ApplyValidationOnBoxes( + obBullishPivots, + unavailables, + barIndex // + ); + + // + if (applyLifetimeValidating) + { + // + ApplyLifeTimeValidationOnBoxes( + obBullishPivots, + maxAllowedOBLifetime, + barIndex // + ); + } + } + + // + // Bearish ... + has = HasOBBearishPivots(); + if (has) + { + // + ApplyValidationOnBoxes( + obBearishPivots, + unavailables, + barIndex // + ); + + // + if (applyLifetimeValidating) + { + // + ApplyLifeTimeValidationOnBoxes( + obBearishPivots, + maxAllowedOBLifetime, + barIndex // + ); + } + } + } + + // + // Bullish ... + XBoxZone obBullishPivots[]; + bool detectOBBullishPivots; + bool newOBBullishPivotDetected; + + // + bool HasOBBullishPivots() + { + return HasChild(obBullishPivots); + } + + // + int CountOBBullishPivots() + { + return ArraySize(obBullishPivots); + } + + // + int FillOBBullishPivots(XBoxZone &pivots[]) + { + // + int result = 0; + + // + Clean(pivots); + + // + if (!HasOBBullishPivots()) + { + return result; + } + + // + int count = CountOBBullishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iPivot = obBullishPivots[i]; + + // + AddRef( + iPivot, + pivots // + ); + + // + iPivot.Clean(); + } + + // + result = ArraySize(pivots); + + // + return result; + } + + // + // Bearish ... + XBoxZone obBearishPivots[]; + bool detectOBBearishPivots; + bool newOBBearishPivotDetected; + + // + bool HasOBBearishPivots() + { + return HasChild(obBearishPivots); + } + + // + int CountOBBearishPivots() + { + return ArraySize(obBearishPivots); + } + + // + int FillOBBearishPivots(XBoxZone &pivots[]) + { + // + int result = 0; + + // + Clean(pivots); + + // + if (!HasOBBearishPivots()) + { + return result; + } + + // + int count = CountOBBearishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iPivot = obBearishPivots[i]; + + // + AddRef( + iPivot, + pivots // + ); + + // + iPivot.Clean(); + } + + // + result = ArraySize(pivots); + + // + return result; + } + + // + // Protected ... + protected: + // + // Props ... + + // + bool AddBox( + XBoxZone &box, + XBoxZone &boxes[] // + ) + { + // + bool result = false; + + // + result = box.IsValid(); + if (!result) + { + return result; + } + + // + int idx = -1; + bool isExists = FindBoxIndex( + idx, + box, + boxes // + ); + result = !isExists; + if (!result) + { + return result; + } + + // + int before = ArraySize(boxes); + + // + AddRef( + box, + boxes // + ); + + // + int after = ArraySize(boxes); + + // + result = after > before; + + // + return result; + } + + // + bool ValidateBox( + XBoxZone &box, + XBoxZone &unavailables[], + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Normalize Bar Index ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Ceck Input Box is Valid ... + result = box.IsValid(); + if (!result) + { + return result; + } + + // + // Check Input Box is Available ... + bool canCheckUnAvailableBoxes = HasChild(unavailables); + if (canCheckUnAvailableBoxes) + { + // + int idx = -1; + bool isUnAvailable = FindBoxIndex( + idx, + box, + unavailables // + ); + result = !isUnAvailable; + if (!result) + { + return result; + } + } + + // + // Check Input Box is Breaked or not ... + + // + // Check Bar Index must after Box To Index ... + int toIDX = box.ToIndex(); + int fromIDX = box.FromIndex(); + result = toIDX > barIndex && + fromIDX > barIndex && + fromIDX > toIDX; + if (!result) + { + return result; + } + + // + // Detect Box Applied Boundary Price ... + // For Checking Break of Box ... + bool isBullish = box.IsBullish(); + double boundary = + isBullish + ? box.lower + : box.upper; + + // + // for validating Box Break we have to wait At Least 3 Bars Close + // out of Box Boundary ... + int barsLength = 3; + + // + // Calculate Start Checking Bar Index ... + int startCheckBreaktionBarIndex = toIDX - barsLength; + bool isBarIndexValid = startCheckBreaktionBarIndex > 0 && + barIndex < startCheckBreaktionBarIndex; + result = isBarIndexValid; + if (!result) + { + // + // Assume Box is Valid if Bar Index not Valid for Checking ... + result = true; + return result; + } + + // + // Try to Check Box Validation if Everything is OK ... + XOHCL cBar; + XOHCL pBar; + XOHCL p2Bar; + bool isValid = false; + bool isBreaked = false; + for (int i = barIndex; i < startCheckBreaktionBarIndex; i++) + { + // + // Initialize Bars ... + isValid = cBar.Init( + box.symbol, + box.period, + i + 1 // + ); + isValid = + result && + cBar.GetPreviousBar(pBar); + isValid = + result && + pBar.GetPreviousBar(p2Bar); + if (!isValid) + { + // + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + + // + result = false; + + // + break; + } + + // + // Preparing Conditions ... + + // + bool isBullishBreaked = + isBullish && + cBar.close < boundary && + pBar.close < boundary && + p2Bar.close < boundary; + + // + bool isBearishBreaked = + !isBullish && + cBar.close > boundary && + pBar.close > boundary && + p2Bar.close > boundary; + + // + // Calculate Result ... + isBreaked = isBullishBreaked || + isBearishBreaked; + if (isBreaked) + { + // + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + + // + result = false; + + // + break; + } + + // + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + } + + // + result = isValid && + !isBreaked; + if (!result) + { + // + int idx = -1; + bool isExists = FindBoxIndex( + idx, + box, + invalidPivots // + ); + if (!isExists) + { + // + AddRef( + box, + invalidPivots // + ); + } + } + + // + // Cleanup Resource ... + + // + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + // + void SortPivots() + { + // + bool has = false; + + // + // Invalid Pivots ... + has = HasInvalidPivots(); + if (has) + { + ApplySortOnBoxes(invalidPivots); + } + + // + // PV ... + + // + // PEAK ... + has = HasPeakPivots(); + if (has) + { + ApplySortOnBoxes(peakPivots); + } + + // + // VALE ... + has = HasValePivots(); + if (has) + { + ApplySortOnBoxes(valePivots); + } + + // + // MT Bullish ... + has = HasMTBullishPivots(); + if (has) + { + ApplySortOnBoxes(mtBullishPivots); + } + + // + // MT Bearish ... + has = HasMTBearishPivots(); + if (has) + { + ApplySortOnBoxes(mtBearishPivots); + } + + // + // OB Bullish ... + has = HasOBBullishPivots(); + if (has) + { + ApplySortOnBoxes(obBullishPivots); + } + + // + // OB Bearish ... + has = HasOBBearishPivots(); + if (has) + { + ApplySortOnBoxes(obBearishPivots); + } + } + + // + void ApplySortOnBoxes( + XBoxZone &items[] // + ) + { + // + int idx = -1; + bool has = false; + + // + has = HasChild(items); + if (!has) + { + return; + } + + // + XBoxZone tmp[]; + Copy( + items, + tmp // + ); + Clean(items); + + // + while (HasChild(tmp)) + { + // + idx = GetOldest(tmp); + has = IsValidIndex(idx); + if (!has) + { + break; + } + + // + XBoxZone iBox = tmp[idx]; + ArrayRemove( + tmp, + idx, + 1 // + ); + + // + AddRef( + iBox, + items // + ); + } + + // + CleanupArray( + items, + maxAllowedPivots // + ); + + // + Clean(tmp); + } + + // + void ApplyValidationOnBoxes( + XBoxZone &items[], + XBoxZone &unavailables[], + int barIndex = 0 // + ) + { + // + bool has = false; + + // + has = HasChild(items); + if (!has) + { + return; + } + + // + XBoxZone tmp[]; + Copy( + items, + tmp // + ); + Clean(items); + while (HasChild(tmp)) + { + // + XBoxZone iBox = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + has = ValidateBox( + iBox, + unavailables, + barIndex // + ); + if (has) + { + // + AddRef( + iBox, + items // + ); + } + + // + iBox.Clean(); + // + } + + // + Clean(tmp); + } + + // + void ApplyLifeTimeValidationOnBoxes( + XBoxZone &items[], + int maxAllowedAge = 0, + int barIndex = 0 // + ) + { + // + bool has = false; + + // + barIndex = NormalizeInt(barIndex, 0); + + // + has = + maxAllowedAge > 0 && + HasChild(items); + if (!has) + { + return; + } + + // + datetime cTime = GetBarTime( + helper.GetSymbol(), + helper.GetPeriod(), + barIndex // + ); + + // + XBoxZone tmp[]; + Copy( + items, + tmp // + ); + Clean(items); + + // + while (HasChild(tmp)) + { + // + XBoxZone iBox = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + datetime defTo = iBox.to; + iBox.to = cTime; + + // + int iAge = iBox.GetAge(); + has = iAge <= maxAllowedAge; + iBox.to = defTo; + if (has) + { + // + AddRef( + iBox, + items // + ); + } + else + { + // + int idx = -1; + bool isExists = FindBoxIndex( + idx, + iBox, + invalidPivots // + ); + if (!isExists) + { + // + AddRef( + iBox, + invalidPivots // + ); + } + } + + // + iBox.Clean(); + } + + // + Clean(tmp); + } + + // + // Prrivate ... + private: + // + // Props ... + + // + XCX121XCatbHelper *helper; + XCBarAnalyser *barAnalyser; + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14040316/XCATBEA/Classes/xcatbea.x-poi.drawer.class.mq5 b/BKPS/14040316/XCATBEA/Classes/xcatbea.x-poi.drawer.class.mq5 new file mode 100644 index 0000000..29c27aa --- /dev/null +++ b/BKPS/14040316/XCATBEA/Classes/xcatbea.x-poi.drawer.class.mq5 @@ -0,0 +1,1193 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCXCATBEAPOIDrawer ... +// Description: XCATBEA POI Drawer Class +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XCATBEA POI Drawer Class" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../Classes/xcatbea.x-poi.detector.class.mq5" + +// +// Definitions ... +struct XCATBPivotStyle +{ + // + // Properties ... + int width; + color clr; + ENUM_LINE_STYLE style; + + // + // Constructor ... + XCATBPivotStyle() + { + Default(); + } + + // + // Tools ... + + // + // Cleanup Model ... + void Clean() + { + // + width = 1; + clr = CLR_NONE; + style = STYLE_SOLID; + + // + ZeroMemory(this); + } + + // + // Default Props ... + void Default() + { + // + width = 1; + clr = CLR_NONE; + style = STYLE_SOLID; + } +}; + +// +// Implementations ... +class XCXCATBEAPOIDrawer : public XCBase +{ + // + // Public ... + public: + // + // Props ... + XCPOIDrawer *drawer; + + // + // Drawers ... + bool drawPeakPivots; + bool drawValePivots; + bool drawMTBullishPivots; + bool drawMTBearishPivots; + bool drawOBBullishPivots; + bool drawOBBearishPivots; + + // + // Styling ... + + // + XCATBPivotStyle defaultBullishStyle; + XCATBPivotStyle defaultBearishStyle; + + // + XCATBPivotStyle peakPivotStyle; + XCATBPivotStyle valePivotStyle; + + // + XCATBPivotStyle mtBullishPivotStyle; + XCATBPivotStyle mtBearishPivotStyle; + + // + XCATBPivotStyle obBullishPivotStyle; + XCATBPivotStyle obBearishPivotStyle; + + // + // Constructors ... + XCXCATBEAPOIDrawer( + XCXCATBEAPOIDetector *_detector // + ) + { + // + detector = _detector; + drawer = new XCPOIDrawer(); + + // + Default(); + } + + // + // De Constructors ... + ~XCXCATBEAPOIDrawer() + { + // + Clear(); + + // + delete drawer; + ZeroMemory(drawer); + + // + ZeroMemory(detector); + } + + // + // Properties ... + + // + // Tools ... + + // + virtual void Default() + { + // + // Drawing ... + drawPeakPivots = false; + drawValePivots = false; + drawMTBullishPivots = false; + drawMTBearishPivots = false; + drawOBBullishPivots = false; + drawOBBearishPivots = false; + + // + // Styling ... + + // + // Bullish ... + defaultBullishStyle.width = 1; + defaultBullishStyle.clr = clrLime; + defaultBullishStyle.style = STYLE_SOLID; + + // + // Bearish ... + defaultBearishStyle.width = 1; + defaultBearishStyle.clr = clrRed; + defaultBearishStyle.style = STYLE_SOLID; + + // + // Pivots ... + + // + // PV ... + peakPivotStyle = defaultBearishStyle; + valePivotStyle = defaultBullishStyle; + + // + // MT ... + mtBullishPivotStyle = defaultBullishStyle; + mtBearishPivotStyle = defaultBearishStyle; + + // + // OB ... + obBullishPivotStyle = defaultBullishStyle; + obBearishPivotStyle = defaultBearishStyle; + } + + // + void Draw(datetime to = NULL) + { + // + // PV ... + DrawPeakPivots(to); + DrawValePivots(to); + + // + // MT ... + DrawMTBullishPivots(to); + DrawMTBearishPivots(to); + + // + // OB ... + DrawOBBullishPivots(to); + DrawOBBearishPivots(to); + } + + // + void DrawPivot( + XBoxZone &pivot, + datetime to = NULL // + ) + { + // + DrawBox( + pivot, + to, + false, + false // + ); + } + + // + void DrawBox( + XBoxZone &box, + datetime to = NULL, + bool drawMiddle = false, + bool ignoreType = false // + ) + { + // + bool has = box.IsValid(); + if (!has) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + if (canUpdateTo) + { + box.to = to; + } + + // + // Draw Box as POI ... + if (!ignoreType) + { + // + // Detect Pivot Type ... + ENUM_XCATB_PIVOTS iType = GetPivotType(box); + has = IsValid(iType); + if (!has) + { + return; + } + + // + switch (iType) + { + // + case XCATB_PEAK: + // + DrawPeakPivot( + box, + to // + ); + break; + + // + case XCATB_VALE: + // + DrawValePivot( + box, + to // + ); + break; + + // + case XCATB_BULLISH_MT: + // + DrawMTBullishPivot( + box, + to // + ); + break; + + // + case XCATB_BEARISH_MT: + // + DrawMTBearishPivot( + box, + to // + ); + break; + + // + case XCATB_BULLISH_OB: + // + DrawOBBullishPivot( + box, + to // + ); + break; + + // + case XCATB_BEARISH_OB: + // + DrawOBBearishPivot( + box, + to // + ); + break; + } + } + // + // Draw Regular Box ... + else + { + // + // Select Styling Config ... + XCATBPivotStyle style; + + // + if (box.IsBullish()) + { + style = defaultBullishStyle; + } + else + { + style = defaultBearishStyle; + } + + // + // Draw Box itself ... + XCBoxObject *iBoxObj; + has = drawer.DrawBox( + box, + iBoxObj // + ); + if (has) + { + // + // Style Object ... + ApplyPivotStyle( + iBoxObj, + style // + ); + + // + // Store Object ... + mObjects.Add(iBoxObj); + } + + // + // Draw Box Middle Range ... + if (drawMiddle) + { + // + double middle = box.GetMid(); + string middleName = box.GetMiddleTag(); + + // + CChartObjectTrend *iMidObj; + iMidObj = new CChartObjectTrend(); + has = iMidObj.Create( + drawer.ChartIdentification(), + middleName, + drawer.SubWindowIdentification(), + box.from, + middle, + box.to, + middle // + ); + if (has) + { + // + // Styling Object ... + iMidObj.Color(style.clr); + iMidObj.Width(style.width); + iMidObj.Style(style.style); + + // + // Store Object ... + mObjects.Add(iMidObj); + } + } + + // + style.Clean(); + } + } + + // + void DrawBoxes( + XBoxZone &boxes[], + datetime to = NULL, + bool drawMiddle = false, + bool ignoreType = false // + ) + { + // + bool has = HasChild(boxes); + if (!has) + { + return; + } + + // + int count = ArraySize(boxes); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = boxes[i]; + + // + // Detect Pivot Type ... + DrawBox( + iBox, + to, + drawMiddle, + ignoreType // + ); + + // + iBox.Clean(); + } + } + + // + void Clear() + { + // + // Cleanup Models ... + defaultBullishStyle.Clean(); + defaultBearishStyle.Clean(); + + // + // Cleanup Styles ... + peakPivotStyle.Clean(); + valePivotStyle.Clean(); + mtBullishPivotStyle.Clean(); + mtBearishPivotStyle.Clean(); + obBullishPivotStyle.Clean(); + obBearishPivotStyle.Clean(); + + // + // Cleanup Pivot Objects Holder ... + mObjects.Clear(); + mPeakPivotObjects.Clear(); + mValePivotObjects.Clear(); + mMTBullishPivotObjects.Clear(); + mMTBearishPivotObjects.Clear(); + mOBBullishPivotObjects.Clear(); + mOBBearishPivotObjects.Clear(); + } + + // + // Collection Drawers ... + + // + void DrawPeakPivots(datetime to = NULL) + { + // + bool has = drawPeakPivots; + if (!has) + { + return; + } + + // + has = detector.HasPeakPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountPeakPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = detector.peakPivots[i]; + + // + DrawPeakPivot( + iBox, + to // + ); + + // + iBox.Clean(); + } + } + + // + void DrawValePivots(datetime to = NULL) + { + // + bool has = drawValePivots; + if (!has) + { + return; + } + + // + has = detector.HasValePivots(); + if (!has) + { + return; + } + + // + int count = detector.CountValePivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = detector.valePivots[i]; + + // + DrawValePivot( + iBox, + to // + ); + + // + iBox.Clean(); + } + } + + // + void DrawMTBullishPivots(datetime to = NULL) + { + // + bool has = drawMTBullishPivots; + if (!has) + { + return; + } + + // + has = detector.HasMTBullishPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountMTBullishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = detector.mtBullishPivots[i]; + + // + DrawMTBullishPivot( + iBox, + to // + ); + + // + iBox.Clean(); + } + } + + // + void DrawMTBearishPivots(datetime to = NULL) + { + // + bool has = drawMTBearishPivots; + if (!has) + { + return; + } + + // + has = detector.HasMTBearishPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountMTBearishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = detector.mtBearishPivots[i]; + + // + DrawMTBearishPivot( + iBox, + to // + ); + + // + iBox.Clean(); + } + } + + // + void DrawOBBullishPivots(datetime to = NULL) + { + // + bool has = drawOBBullishPivots; + if (!has) + { + return; + } + + // + has = detector.HasOBBullishPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountOBBullishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = detector.obBullishPivots[i]; + + // + DrawOBBullishPivot( + iBox, + to // + ); + + // + iBox.Clean(); + } + } + + // + void DrawOBBearishPivots(datetime to = NULL) + { + // + bool has = drawOBBearishPivots; + if (!has) + { + return; + } + + // + has = detector.HasOBBearishPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountOBBearishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = detector.obBearishPivots[i]; + + // + DrawOBBearishPivot( + iBox, + to // + ); + + // + iBox.Clean(); + } + } + + // + // One Item Drawers ... + + // + void DrawPeakPivot( + XBoxZone &item, + datetime to = NULL // + ) + { + // + bool has = drawPeakPivots; + if (!has) + { + return; + } + + // + has = item.IsValid() && + item.type == GetBoxType(XCATB_PEAK) && + item.dir == GetDirection(XCATB_PEAK); + if (!has) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + if (canUpdateTo) + { + item.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + item, + iObj // + ); + if (has) + { + // + // Style Object ... + ApplyPivotStyle( + iObj, + peakPivotStyle // + ); + + // + // Store Object ... + mPeakPivotObjects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + void DrawValePivot( + XBoxZone &item, + datetime to = NULL // + ) + { + // + bool has = drawValePivots; + if (!has) + { + return; + } + + // + has = item.IsValid() && + item.type == GetBoxType(XCATB_VALE) && + item.dir == GetDirection(XCATB_VALE); + if (!has) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + if (canUpdateTo) + { + item.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + item, + iObj // + ); + if (has) + { + // + // Style Object ... + ApplyPivotStyle( + iObj, + valePivotStyle // + ); + + // + // Store Object ... + mValePivotObjects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + void DrawMTBullishPivot( + XBoxZone &item, + datetime to = NULL // + ) + { + // + bool has = drawMTBullishPivots; + if (!has) + { + return; + } + + // + has = item.IsValid() && + item.type == GetBoxType(XCATB_BULLISH_MT) && + item.dir == GetDirection(XCATB_BULLISH_MT); + if (!has) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + if (canUpdateTo) + { + item.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + item, + iObj // + ); + if (has) + { + // + // Style Object ... + ApplyPivotStyle( + iObj, + mtBullishPivotStyle // + ); + + // + // Store Object ... + mMTBullishPivotObjects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + void DrawMTBearishPivot( + XBoxZone &item, + datetime to = NULL // + ) + { + // + bool has = drawMTBearishPivots; + if (!has) + { + return; + } + + // + has = item.IsValid() && + item.type == GetBoxType(XCATB_BEARISH_MT) && + item.dir == GetDirection(XCATB_BEARISH_MT); + if (!has) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + if (canUpdateTo) + { + item.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + item, + iObj // + ); + if (has) + { + // + // Style Object ... + ApplyPivotStyle( + iObj, + mtBearishPivotStyle // + ); + + // + // Store Object ... + mMTBearishPivotObjects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + void DrawOBBullishPivot( + XBoxZone &item, + datetime to = NULL // + ) + { + // + bool has = drawOBBullishPivots; + if (!has) + { + return; + } + + // + has = item.IsValid() && + item.type == GetBoxType(XCATB_BULLISH_OB) && + item.dir == GetDirection(XCATB_BULLISH_OB); + if (!has) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + if (canUpdateTo) + { + item.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + item, + iObj // + ); + if (has) + { + // + // Style Object ... + ApplyPivotStyle( + iObj, + obBullishPivotStyle // + ); + + // + // Store Object ... + mOBBullishPivotObjects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + void DrawOBBearishPivot( + XBoxZone &item, + datetime to = NULL // + ) + { + // + bool has = drawOBBearishPivots; + if (!has) + { + return; + } + + // + has = item.IsValid() && + item.type == GetBoxType(XCATB_BEARISH_OB) && + item.dir == GetDirection(XCATB_BEARISH_OB); + if (!has) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + if (canUpdateTo) + { + item.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + item, + iObj // + ); + if (has) + { + // + // Style Object ... + ApplyPivotStyle( + iObj, + obBearishPivotStyle // + ); + + // + // Store Object ... + mOBBearishPivotObjects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + // Styling Tools ... + + /** + * Apply Default Bullish Style ... + * + * @param object: XCBaseObject pointer, Specified Object to Apply Styling ... + */ + void ApplyBullishStyle(XCBoxObject *&object) + { + // + // Validate Args ... + if (object == NULL) + { + return; + } + + // + ApplyPivotStyle(object, defaultBullishStyle); + } + + /** + * Apply Default Bearish Style ... + * + * @param object: XCBaseObject pointer, Specified Object to Apply Styling ... + */ + void ApplyBearishStyle(XCBoxObject *&object) + { + // + // Validate Args ... + if (object == NULL) + { + return; + } + + // + ApplyPivotStyle(object, defaultBearishStyle); + } + + /** + * Apply Peak Style ... + * + * @param object: XCBaseObject pointer, Specified Object to Apply Styling ... + */ + void ApplyPeakPivotStyle(XCBoxObject *&object) + { + // + // Validate Args ... + if (object == NULL) + { + return; + } + + // + ApplyPivotStyle(object, peakPivotStyle); + } + + /** + * Apply Vale Style ... + * + * @param object: XCBaseObject pointer, Specified Object to Apply Styling ... + */ + void ApplyValePivotStyle(XCBoxObject *&object) + { + // + // Validate Args ... + if (object == NULL) + { + return; + } + + // + ApplyPivotStyle(object, valePivotStyle); + } + + /** + * Apply MT Bullish Style ... + * + * @param object: XCBaseObject pointer, Specified Object to Apply Styling ... + */ + void ApplyMTBullishPivotStyle(XCBoxObject *&object) + { + // + // Validate Args ... + if (object == NULL) + { + return; + } + + // + ApplyPivotStyle(object, mtBullishPivotStyle); + } + + /** + * Apply MT Bearish Style ... + * + * @param object: XCBaseObject pointer, Specified Object to Apply Styling ... + */ + void ApplyMTBearishPivotStyle(XCBoxObject *&object) + { + // + // Validate Args ... + if (object == NULL) + { + return; + } + + // + ApplyPivotStyle(object, mtBearishPivotStyle); + } + + /** + * Apply OB Bullish Style ... + * + * @param object: XCBaseObject pointer, Specified Object to Apply Styling ... + */ + void ApplyOBBullishPivotStyle(XCBoxObject *&object) + { + // + // Validate Args ... + if (object == NULL) + { + return; + } + + // + ApplyPivotStyle(object, obBullishPivotStyle); + } + + /** + * Apply OB Bearish Style ... + * + * @param object: XCBaseObject pointer, Specified Object to Apply Styling ... + */ + void ApplyOBBearishPivotStyle(XCBoxObject *&object) + { + // + // Validate Args ... + if (object == NULL) + { + return; + } + + // + ApplyPivotStyle(object, obBearishPivotStyle); + } + + /** + * Apply Pivot Style to Specified Object ... + */ + void ApplyPivotStyle( + XCBoxObject *&object, + XCATBPivotStyle &style // + ) + { + // + if (object == NULL) + { + return; + } + + // + object.BoxColor(style.clr); + object.BoxWidth(style.width); + object.BoxStyle(style.style); + } + + // + // Protected ... + protected: + // + // Props ... + + // + // Prrivate ... + private: + // + // Props ... + XCXCATBEAPOIDetector *detector; + + // + CArrayObj mObjects; + + // + CArrayObj mPeakPivotObjects; + CArrayObj mValePivotObjects; + + // + CArrayObj mMTBullishPivotObjects; + CArrayObj mMTBearishPivotObjects; + + // + CArrayObj mOBBullishPivotObjects; + CArrayObj mOBBearishPivotObjects; + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14040316/XCATBEA/Classes/xcatbea.x-trade.manager.class.mq5 b/BKPS/14040316/XCATBEA/Classes/xcatbea.x-trade.manager.class.mq5 new file mode 100644 index 0000000..49ceef8 --- /dev/null +++ b/BKPS/14040316/XCATBEA/Classes/xcatbea.x-trade.manager.class.mq5 @@ -0,0 +1,3782 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XCXCATBEATradeManager +// Description: provides all Requirements for Managing Trades ... +// +// +// 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.x-alert.class.mq5" +#include "../../Classes/x-saherelm.x-data.collector.class.mq5" +#include "../../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../../Classes/x-saherelm.x-trade.class.mq5" +#include "../../Libraries/x-saherelm.x-poi.lib.mq5" +#include "../Libraries/xcatbea.lib.mq5" +#include "../Libraries/xcatbea.signaller.lib.mq5" + +// +// Definitions ... + +// +enum ENUM_XCATBEA_TRADE_RESTRICTION_PERIOD +{ + XCATBEA_TRADE_RESTRICATION_NONE, // None + XCATBEA_TRADE_RESTRICATION_HOURLY, // Per Hour + XCATBEA_TRADE_RESTRICATION_DAILY, // Per Day + XCATBEA_TRADE_RESTRICATION_WEEKLY, // Per Week + XCATBEA_TRADE_RESTRICATION_MONTHLY, // Per Month +}; + +// +string ToString(ENUM_XCATBEA_TRADE_RESTRICTION_PERIOD value) +{ + // + string result = NULL; + + // + result = EnumToString(value); + + // + return result; +} + +// +enum ENUM_XCATBEA_TRADE_FINALIZATION +{ + XCATBEA_TRADE_FINAL_NONE, // None + XCATBEA_TRADE_FINAL_TP, // TP + XCATBEA_TRADE_FINAL_SL, // SL + XCATBEA_TRADE_FINAL_CLOSE_IN_PROFIT, // Profit + XCATBEA_TRADE_FINAL_CLOSE_IN_LOSE, // Lost +}; + +// +string ToString(ENUM_XCATBEA_TRADE_FINALIZATION value) +{ + // + string result = NULL; + + // + result = EnumToString(value); + + // + return result; +} + +// +// Position Selecting ... +enum ENUM_XCATBEA_POSITION_SELECT_TYPES +{ + XCATBEA_POSITION_SELECT_NONE = 0, // None + XCATBEA_POSITION_SELECT_ALL = 1, // All + XCATBEA_POSITION_SELECT_IN_PROFITS = 2, // In Profit Positions + XCATBEA_POSITION_SELECT_IN_DRAWDOWNS = 3, // In Drawdown Positions + XCATBEA_POSITION_SELECT_OLDEST = 4, // Oldest Position + XCATBEA_POSITION_SELECT_YOUNGEST = 5, // Youngest Position + XCATBEA_POSITION_SELECT_IN_PROFITS_OLDEST = 6, // In Profit Positions Oldest one + XCATBEA_POSITION_SELECT_IN_PROFITS_YOUNGEST = 7, // In Profit Positions Youngest one + XCATBEA_POSITION_SELECT_IN_PROFITS_MIN = 8, // Minimum Profitable Position + XCATBEA_POSITION_SELECT_IN_PROFITS_MAX = 9, // Maximum Profitable Position + XCATBEA_POSITION_SELECT_IN_DRAWDOWN_OLDEST = 10, // In Drawdown Positions Oldest one + XCATBEA_POSITION_SELECT_IN_DRAWDOWN_YOUNGEST = 11, // In Drawdown Positions Youngest one + XCATBEA_POSITION_SELECT_IN_DRAWDOWN_MIN = 12, // Minimum in Drawdown Position + XCATBEA_POSITION_SELECT_IN_DRAWDOWN_MAX = 13, // Maximum in Drawdown Position + XCATBEA_POSITION_SELECT_SAMES = 14, // Same Type Positions + XCATBEA_POSITION_SELECT_SAMES_OLDEST = 15, // Same Type Positions Oldest one + XCATBEA_POSITION_SELECT_SAMES_YOUNGEST = 16, // Same Type Positions Youngest one + XCATBEA_POSITION_SELECT_OPPOSITS = 17, // Opposit Type Positions + XCATBEA_POSITION_SELECT_OPPOSIT_OLDEST = 18, // Opposit Type Positions Oldest one + XCATBEA_POSITION_SELECT_OPPOSIT_YOUNGEST = 19, // Opposit Type Positions Youngest one + XCATBEA_POSITION_SELECT_SAME_IN_PROFITS = 20, // Same Type In Profit Positions + XCATBEA_POSITION_SELECT_SAME_IN_PROFITS_OLDEST = 21, // Same Type In Profit Positions Oldest one + XCATBEA_POSITION_SELECT_SAME_IN_PROFITS_YOUNGEST = 22, // Same Type In Profit Positions Youngest one + XCATBEA_POSITION_SELECT_SAME_IN_PROFITS_MIN = 23, // Minimum Profitable of Same Type Positions + XCATBEA_POSITION_SELECT_SAME_IN_PROFITS_MAX = 24, // Maximum Profitable of Same Type Positions + XCATBEA_POSITION_SELECT_OPPOSIT_IN_PROFITS = 25, // Opposit Type In Profit Positions + XCATBEA_POSITION_SELECT_OPPOSIT_IN_PROFITS_OLDEST = 26, // Opposit Type In Profit Positions Oldest one + XCATBEA_POSITION_SELECT_OPPOSIT_IN_PROFITS_YOUNGEST = 27, // Opposit Type In Profit Positions Youngest one + XCATBEA_POSITION_SELECT_OPPOSIT_IN_PROFITS_MIN = 28, // Minimum Profitable of Opposit Type Positions + XCATBEA_POSITION_SELECT_OPPOSIT_IN_PROFITS_MAX = 29, // Maximum Profitable of Opposit Type Positions + XCATBEA_POSITION_SELECT_SAME_IN_DRAWDOWNS = 30, // Same Type In Deawdown Positions + XCATBEA_POSITION_SELECT_SAME_IN_DRAWDOWN_OLDEST = 31, // Same Type In Deawdown Positions Oldest one + XCATBEA_POSITION_SELECT_SAME_IN_DRAWDOWN_YOUNGEST = 32, // Same Type In Deawdown Positions Youngest one + XCATBEA_POSITION_SELECT_SAME_IN_DRAWDOWN_MIN = 33, // Minimum In Drawdown of Same Type Positions + XCATBEA_POSITION_SELECT_SAME_IN_DRAWDOWN_MAX = 34, // Maximum In Drawdown of Same Type Positions + XCATBEA_POSITION_SELECT_OPPOSITS_IN_DRAWDOWNS = 35, // Opposit Type In Deawdown Positions + XCATBEA_POSITION_SELECT_OPPOSITS_IN_DRAWDOWN_OLDEST = 36, // Opposit Type In Deawdown Positions Oldest one + XCATBEA_POSITION_SELECT_OPPOSITS_IN_DRAWDOWN_YOUNGEST = 37, // Opposit Type In Deawdown Positions Youngest one + XCATBEA_POSITION_SELECT_OPPOSITS_IN_DRAWDOWN_MIN = 38, // Minimum In Drawdown of Opposit Type Positions + XCATBEA_POSITION_SELECT_OPPOSITS_IN_DRAWDOWN_MAX = 39, // Maximum In Drawdown of Opposit Type Positions +}; + +// +bool IsValid(ENUM_XCATBEA_POSITION_SELECT_TYPES value) +{ + return value != XCATBEA_POSITION_SELECT_NONE; +} + +// +string ToString(ENUM_XCATBEA_POSITION_SELECT_TYPES value) +{ + return EnumToString(value); +} + +/** + * Select Specified Position's Related Position(s) + * for Protecting ... + * + * @param selecteds: XPosition instance reference Collection, for Holding Selected Positions ... + * @param positions: XPosition instance reference Collection, All available source Positions ... + * @param forType: ENUM_X_POSITION_TYPES member, Spcified Position Type to Select for it ... + * @param selectType: ENUM_XCATBEA_POSITION_SELECT_TYPES member, Specified Positions Selecting Senario ... + * + * @return ( bool ) + */ +bool SelectPosition( + XPosition &selecteds[], + XPosition &positions[], + ENUM_X_POSITION_TYPES forType, + ENUM_XCATBEA_POSITION_SELECT_TYPES selectType // +) +{ + // + bool result = false; + + // + // Normalize Args ... + Clean(selecteds); + + // + // Validate Args ... + result = + IsValid(forType) && + HasChild(positions) && + IsValid(selectType); + if (!result) + { + return result; + } + + // + // Extract Separate Type of Positions ... + + // + int idx = -1; + bool has = false; + XPosition iPosition; + + // + bool isLong = IsLong(forType); + bool isShort = IsShort(forType); + int count = ArraySize(positions); + + // + XPosition samePositions[]; + XPosition oppositPositions[]; + XPosition inProfitPositions[]; + XPosition inDrawdownPositions[]; + XPosition sameInProfitPositions[]; + XPosition sameInDrawdownPositions[]; + XPosition oppositInProfitPositions[]; + XPosition oppositInDrawdownPositions[]; + + // + for (int i = 0; i < count; i++) + { + // + // Select Indexed Position ... + iPosition = positions[i]; + + // + bool isIPosLong = IsLong(iPosition.type); + bool isIPosShort = IsShort(iPosition.type); + + // + // Select if Same Type ... + bool isSame = + (isLong && isIPosLong) || + (isShort && isIPosShort); + if (isSame) + { + // + AddRef( + iPosition, + samePositions // + ); + } + + // + // Select if Opposit Type ... + bool isOpposit = + (isLong && isIPosShort) || + (isShort && isIPosLong); + if (isOpposit) + { + // + AddRef( + iPosition, + oppositPositions // + ); + } + + // + iPosition.Clean(); + } + + // + // Filling Other Requirement Collections ... + + // + ExtractInProfitPositions( + positions, + inProfitPositions // + ); + + // + ExtractInProfitPositions( + samePositions, + sameInProfitPositions // + ); + + // + ExtractInProfitPositions( + oppositPositions, + oppositInProfitPositions // + ); + + // + ExtractInDrawdownPositions( + positions, + inDrawdownPositions // + ); + + // + ExtractInDrawdownPositions( + samePositions, + sameInDrawdownPositions // + ); + + // + ExtractInDrawdownPositions( + oppositPositions, + oppositInDrawdownPositions // + ); + + // + // Implement Selection Senario ... + switch (selectType) + { + // + case XCATBEA_POSITION_SELECT_ALL: + // + Copy( + positions, + selecteds // + ); + break; + + // + case XCATBEA_POSITION_SELECT_IN_PROFITS: + // + Copy( + inProfitPositions, + selecteds // + ); + break; + + // + case XCATBEA_POSITION_SELECT_IN_DRAWDOWNS: + // + Copy( + inDrawdownPositions, + selecteds // + ); + break; + + // + case XCATBEA_POSITION_SELECT_OLDEST: + // + GetOldest( + iPosition, + positions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_YOUNGEST: + // + GetYoungest( + iPosition, + positions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_IN_PROFITS_OLDEST: + // + GetOldest( + iPosition, + inProfitPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_IN_PROFITS_YOUNGEST: + // + GetYoungest( + iPosition, + inProfitPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_IN_PROFITS_MIN: + // + idx = FindMinProfitIndex(inProfitPositions); + if (IsValidIndex(idx)) + { + // + iPosition = inProfitPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_IN_PROFITS_MAX: + // + idx = FindMaxProfitIndex(inProfitPositions); + if (IsValidIndex(idx)) + { + // + iPosition = inProfitPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_IN_DRAWDOWN_OLDEST: + // + GetOldest( + iPosition, + inDrawdownPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_IN_DRAWDOWN_YOUNGEST: + // + GetYoungest( + iPosition, + inDrawdownPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_IN_DRAWDOWN_MIN: + // + idx = FindMinDrawdownIndex(inDrawdownPositions); + if (IsValidIndex(idx)) + { + // + iPosition = inDrawdownPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_IN_DRAWDOWN_MAX: + // + idx = FindMaxDrawdownIndex(inDrawdownPositions); + if (IsValidIndex(idx)) + { + // + iPosition = inDrawdownPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_SAMES: + // + Copy( + samePositions, + selecteds // + ); + break; + + // + case XCATBEA_POSITION_SELECT_SAMES_OLDEST: + // + GetOldest( + iPosition, + samePositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_SAMES_YOUNGEST: + // + GetYoungest( + iPosition, + samePositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_OPPOSITS: + // + Copy( + oppositPositions, + selecteds // + ); + break; + + // + case XCATBEA_POSITION_SELECT_OPPOSIT_OLDEST: + // + GetOldest( + iPosition, + oppositPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_OPPOSIT_YOUNGEST: + // + GetYoungest( + iPosition, + oppositPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_SAME_IN_PROFITS: + // + Copy( + sameInProfitPositions, + selecteds // + ); + break; + + // + case XCATBEA_POSITION_SELECT_SAME_IN_PROFITS_OLDEST: + // + GetOldest( + iPosition, + sameInProfitPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_SAME_IN_PROFITS_YOUNGEST: + // + GetYoungest( + iPosition, + sameInProfitPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_SAME_IN_PROFITS_MIN: + // + idx = FindMinProfitIndex(sameInProfitPositions); + if (IsValidIndex(idx)) + { + // + iPosition = sameInProfitPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_SAME_IN_PROFITS_MAX: + // + idx = FindMaxProfitIndex(sameInProfitPositions); + if (IsValidIndex(idx)) + { + // + iPosition = sameInProfitPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_OPPOSIT_IN_PROFITS: + // + Copy( + oppositInProfitPositions, + selecteds // + ); + break; + + // + case XCATBEA_POSITION_SELECT_OPPOSIT_IN_PROFITS_OLDEST: + // + GetOldest( + iPosition, + oppositInProfitPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_OPPOSIT_IN_PROFITS_YOUNGEST: + // + GetYoungest( + iPosition, + oppositInProfitPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_OPPOSIT_IN_PROFITS_MIN: + // + idx = FindMinProfitIndex(oppositInProfitPositions); + if (IsValidIndex(idx)) + { + // + iPosition = oppositInProfitPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_OPPOSIT_IN_PROFITS_MAX: + // + idx = FindMaxProfitIndex(oppositInProfitPositions); + if (IsValidIndex(idx)) + { + // + iPosition = oppositInProfitPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_SAME_IN_DRAWDOWNS: + // + Copy( + sameInDrawdownPositions, + selecteds // + ); + break; + + // + case XCATBEA_POSITION_SELECT_SAME_IN_DRAWDOWN_OLDEST: + // + GetOldest( + iPosition, + sameInDrawdownPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_SAME_IN_DRAWDOWN_YOUNGEST: + // + GetYoungest( + iPosition, + sameInDrawdownPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_SAME_IN_DRAWDOWN_MIN: + // + idx = FindMinDrawdownIndex(sameInDrawdownPositions); + if (IsValidIndex(idx)) + { + // + iPosition = sameInDrawdownPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_SAME_IN_DRAWDOWN_MAX: + // + idx = FindMaxDrawdownIndex(sameInDrawdownPositions); + if (IsValidIndex(idx)) + { + // + iPosition = sameInDrawdownPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_OPPOSITS_IN_DRAWDOWNS: + // + Copy( + oppositInDrawdownPositions, + selecteds // + ); + break; + + // + case XCATBEA_POSITION_SELECT_OPPOSITS_IN_DRAWDOWN_OLDEST: + // + GetOldest( + iPosition, + oppositInDrawdownPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_OPPOSITS_IN_DRAWDOWN_YOUNGEST: + // + GetYoungest( + iPosition, + oppositInDrawdownPositions // + ); + if (iPosition.IsValid()) + { + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_OPPOSITS_IN_DRAWDOWN_MIN: + // + idx = FindMinDrawdownIndex(oppositInDrawdownPositions); + if (IsValidIndex(idx)) + { + // + iPosition = oppositInDrawdownPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + case XCATBEA_POSITION_SELECT_OPPOSITS_IN_DRAWDOWN_MAX: + // + idx = FindMaxDrawdownIndex(oppositInDrawdownPositions); + if (IsValidIndex(idx)) + { + // + iPosition = oppositInDrawdownPositions[idx]; + + // + AddRef( + iPosition, + selecteds // + ); + } + iPosition.Clean(); + break; + + // + } + + // + // Validate Result ... + result = HasChild(selecteds); + + // + // Cleanup Resources ... + + // + if (!result) + { + Clean(selecteds); + } + + // + Clean(samePositions); + Clean(oppositPositions); + Clean(inProfitPositions); + Clean(inDrawdownPositions); + Clean(sameInProfitPositions); + Clean(sameInDrawdownPositions); + Clean(oppositInProfitPositions); + Clean(oppositInDrawdownPositions); + + // + return result; +} + +// +struct XCATBEASymbolInfo +{ + // + // Properties ... + + // + string symbol; // Trading Symbol + + // + int longs; // All Long Trades + int shorts; // All Short Trades + + // + int trades; // All Trades + + // + int losses; // All Loosing Trades + int profits; // All Winning Trades + + // + datetime managedStart; // Managed Start Time + + // + int managedSLs; // Managed SL(s) + int managedTPs; // Managed TP(s) + int managedTrades; // Managed Trades + + // + double managedBalance; // Managed Start Balance + double managedProfits; // Managed Profit(s) + + // + // Constructor ... + XCATBEASymbolInfo() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + symbol = NULL; + + // + longs = 0; + shorts = 0; + + // + trades = 0; + + // + losses = 0; + profits = 0; + + // + managedStart = NULL; + + // + managedSLs = 0; + managedTPs = 0; + managedTrades = 0; + + // + managedBalance = 0; + managedProfits = 0; + + // + ZeroMemory(this); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = IsValid(symbol); + + // + return result; + } + + // + bool IsSameAs(XCATBEASymbolInfo &item) + { + // + bool result = false; + + // + result = IsValid() && + item.IsValid() && + symbol == item.symbol; + + // + return result; + } + + // + string GetRestrictionDescription( + ENUM_XCATBEA_TRADE_RESTRICTION_PERIOD period // + ) + { + // + string result = NULL; + + // + if (!IsValid() && + period != XCATBEA_TRADE_RESTRICATION_NONE) + { + return result; + } + + // + result += + "-------------------" + "\n" + + "Restrictions: " + "\n" + + "-------------------" + "\n" + + "Symbol: " + ToString(symbol) + "\n" + + "Period: " + ToString(period) + "\n" + + "Start: " + ToFormatString(managedStart) + "\n" + + "Balance: " + ToString(managedBalance) + "\n" + + "-------------------" + "\n" + + "Trades: " + ToString(managedTrades) + "\n" + + "SL: " + ToString(managedSLs) + "\n" + + "TP: " + ToString(managedTPs) + "\n" + + "Profit: " + ToString(managedProfits) + "\n" + + ""; + + // + return result; + } +}; + +// +struct XCATBEATradeSession +{ + // + // Properties ... + string start; // Session Start Time (hh:mm) + string end; // Session End Time (hh:mm) + string name; // Session Name + + // + // Constructor ... + XCATBEATradeSession() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + end = NULL; + name = NULL; + start = NULL; + + // + ZeroMemory(this); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = IsValid(start) && + IsValid(end); + if (!result) + { + return result; + } + + // + return result; + } + + // + // Check Session is Active or Not ... + bool IsActive(datetime time = NULL) + { + // + bool result = false; + + // + time = NormalizeTime(time); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + result = IsTimeInRange( + time, + start, + end // + ); + + // + return result; + } +}; + +struct XCATBEASymbolSession +{ + // + // Propeties ... + + // + string symbol; // Trading Symbol + XCATBEATradeSession sessions[]; // Trading Sessions + + // + // Constructor ... + XCATBEASymbolSession() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + symbol = NULL; + Clean(sessions); + + // + ZeroMemory(this); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = IsValid(symbol); + + // + return result; + } + + // + // Check Allow Trade in Active Sessions ... + bool CanTrade(datetime time = NULL) + { + // + bool result = false; + + // + // Normalize Args ... + time = NormalizeTime(time); + + // + // Validating ... + result = IsValid(); + if (!result) + { + return result; + } + + // + // if there is not any defined sessions for Symbol ... + // it's allow Trading in all times ... + result = !HasChild(sessions); + if (result) + { + return result; + } + + // + // Detect an Active Session ... + int count = ArraySize(sessions); + for (int i = 0; i < count; i++) + { + // + result = sessions[i].IsActive(time); + if (result) + { + break; + } + } + + // + return result; + } + + // +}; + +// +struct XCATBEATrade +{ + // + // Props ... + double swap; + double profit; + XSignal signal; + ulong positionID; + double commission; + XCATBEAStrategyConditions conditions; + ENUM_XCATBEA_TRADE_FINALIZATION finalize; + + // + datetime signaledAt; + datetime executedAt; + datetime finalizedAt; + + // + // Constructor ... + XCATBEATrade() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup Model ... + */ + void Clean() + { + // + swap = 0; + profit = 0; + signal.Clean(); + commission = 0; + positionID = 0; + conditions.Clean(); + finalize = XCATBEA_TRADE_FINAL_NONE; + + // + signaledAt = NULL; + executedAt = NULL; + finalizedAt = NULL; + + // + ZeroMemory(this); + } + + /** + * Check Has Signal ... + * + * @return ( bool ) + */ + bool HasSignal() + { + // + bool result = false; + + // + result = signal.IsValid(); + + // + return result; + } + + /** + * Check Signal Executed or Not ... + * + * @return ( bool ) + */ + bool IsExecuted() + { + // + bool result = false; + + // + result = positionID > 0; + + // + return result; + } + + /** + * Check a Trade is Finalized or not ... + * + * @return ( bool ) + */ + bool IsFinalized() + { + // + bool result = false; + + // + result = HasSignal() && + IsExecuted() && + finalize != XCATBEA_TRADE_FINAL_NONE; + + // + return result; + } + + /** + * Generate Summary Info ... + * + * @return ( string ) + */ + string Summary() + { + // + string result = NULL; + + // + result = + // + ToString("Swap", swap) + + ToString("Profit", profit) + + ToString("Commission", commission) + + ToString("Finalize", ToString(finalize)) + + ToString("PositionID", positionID) + + ToString("----------------") + "\n" + + ToString("Signaled At", ToFormatString(signaledAt)) + + ToString("Executed At", ToFormatString(executedAt)) + + ToString("Finalized At", ToFormatString(finalizedAt)) + // + ; + + // + return result; + } + + /** + * Get Data Collection File Name ... + * + * @return ( string ) + */ + string GetFileName() + { + // + string result = NULL; + + // + bool hasSignal = HasSignal(); + bool isExecuted = IsExecuted(); + bool isFinalized = IsFinalized(); + if (!hasSignal && !isExecuted && !isFinalized) + { + return result; + } + + // + result = + // + signal.symbol + "\\" + + ToString(signal.type) + "\\" + + (profit >= 0 ? "Profit" : "Loss") + "\\" + + ToString(positionID) + "_" + + ToString(signal.period) + "_" + + ToFormatString(signaledAt) + // + ; + + // + return result; + } + + /** + * Converts Model to String Representation ... + * + * @param onlySignals: Boolean, Specified Represent Only Signal or not ... + * + * @return ( string ) + */ + string ToString( + bool includeSummary = true, + bool includeSignal = true, + bool includeConditions = true // + ) + { + // + string result = NULL; + + // + // Generating Model Summary ... + string summary = Summary(); + + // + // Generating Signal Summary ... + string signalSummary = signal.ToString(); + + // + // Generating Conditions Summary ... + string conditionsSummary = conditions + .conditions + .GenerateSummary( + false, + true, + true, + false // Ignore False Conditions ... + ); + + // + if (includeSummary) + { + // + result += + ToString("----------------") + "\n" + + ToString("Summary: ") + "\n" + + ToString("----------------") + "\n" + + summary + "\n"; + } + + // + if (includeSignal) + { + // + result += + ToString("----------------") + "\n" + + ToString("Signal: ") + "\n" + + ToString("----------------") + "\n" + + signalSummary + "\n"; + } + + // + if (includeConditions) + { + // + result += + ToString("----------------") + "\n" + + ToString("Conditions: ") + "\n" + + ToString("----------------") + "\n" + + conditionsSummary + "\n"; + } + + // + return result; + } + + string GetConditionsString() + { + // + string result = NULL; + + // + double bullishScore = 0; + double bearishScore = 0; + conditions + .conditions + .GenerateScore( + bullishScore, + bearishScore // + ); + + // + string conditionsStr = + conditions + .conditions + .GenerateSummary( + false, + true, // Only Conditions ... + false, + false // Ignore False Conditions ... + ); + string condParts[]; + int condPartsCount = SplitContent( + condParts, + conditionsStr, + "\n" // + ); + if (IsValidSize(condPartsCount)) + { + // + conditionsStr = NULL; + while (HasChild(condParts)) + { + // + string iStr = condParts[0]; + ArrayRemove( + condParts, + 0, + 1 // + ); + + // + bool isLast = !HasChild(condParts); + + // + bool isCond = Contains( + "is", + iStr, + false // + ); + if (isCond) + { + // + string iParts[]; + int iPartsCount = SplitContent( + iParts, + iStr, + ":" // + ); + if (iPartsCount == 2) + { + // + string iVal = iParts[1]; + StringTrimLeft(iVal); + StringTrimRight(iVal); + bool isPassed = ToBoolean(iVal); + conditionsStr += (isPassed ? "" : "!") + "conditions." + iParts[0] + (!isLast ? " &&" : "") + "\n"; + } + } + } + Clean(condParts); + } + else + { + conditionsStr = NULL; + } + + // + result = + "(" + "\n" + + "\\" + "\\" + " " + ToString("Type", ToString(signal.type)) + + "\\" + "\\" + " " + ToString("Profit", profit) + + "\\" + "\\" + " " + ToString("Finalize", ToString(finalize)) + + "\\" + "\\" + " " + ToString("PositionID", positionID) + + "\\" + "\\" + " " + ToString("----------------") + "\n" + + "\\" + "\\" + " " + ToString("Signaled At", ToFormatString(signaledAt)) + + "\\" + "\\" + " " + ToString("Executed At", ToFormatString(executedAt)) + + "\\" + "\\" + " " + ToString("Finalized At", ToFormatString(finalizedAt)) + + "\\" + "\\" + " " + ToString("----------------") + "\n" + + "\\" + "\\" + " " + ToString("Scores:") + "\n" + + "\\" + "\\" + " " + ToString("Bullish", bullishScore) + + "\\" + "\\" + " " + ToString("Bearish", bearishScore) + + "\\" + "\\" + " " + ToString("----------------") + "\n" + + conditionsStr + + (IsValid(conditionsStr) ? "" : "") + + ") && "; + + // + return result; + } +}; + +// +// Implementations ... +class XCXCATBEATradeManager : public XCBase +{ + // + // Public ... + public: + // + // Props ... + XCAlert *alert; + XCTrade *trader; + bool drawSignal; + XCPOIDrawer *drawer; + XTimeTracker timeTracker; + XCDataCollector *collector; + + // + // Constructors ... + XCXCATBEATradeManager( + XCAlert *_alert, + XCTrade *_trader // + ) + { + // + alert = _alert; + trader = _trader; + drawSignal = true; + drawer = new XCPOIDrawer(); + + // + allowTrade = true; + allowLongs = true; + allowShorts = true; + + // + forceCloseAt = NULL; + isForceCloseAtTime = false; + + // + maxAllowedTPs = 0; + maxAllowedSLs = 0; + maxAllowedTrades = 0; + restrictionsPeriod = XCATBEA_TRADE_RESTRICATION_NONE; + + // + reportTrades = true; + reportSignals = true; + reportProtector = true; + reportAfterTradesBalance = true; + + // + SaveTrades(false); + + // + collector = new XCDataCollector(); + + // + // Setting Collector Path ... + string mPath = (IsValid(alert.GetPrefix()) + ? alert.GetPrefix() + "\\" + : "") + + trader.mAccount.GetCompany(); + collector.Path(mPath); + } + + // + // De Constructors ... + ~XCXCATBEATradeManager() + { + // + Clean(trades); + + // + timeTracker.Clean(); + + // + ZeroMemory(alert); + ZeroMemory(trader); + + // + delete drawer; + ZeroMemory(drawer); + + // + delete collector; + ZeroMemory(collector); + } + + // + // Properties ... + + // + bool SaveTrades() + { + return mSaveTrades; + } + + // + void SaveTrades(bool value) + { + mSaveTrades = value; + } + + // + bool SaveSignals() + { + return mSaveSignals; + } + + // + void SaveSignals(bool value) + { + mSaveSignals = value; + } + + // + bool SaveWins() + { + return mSaveWins; + } + + // + void SaveWins(bool value) + { + mSaveWins = value; + } + + // + bool SaveLosts() + { + return mSaveLosts; + } + + // + void SaveLosts(bool value) + { + mSaveLosts = value; + } + + // + bool SaveRestrictions() + { + return mSaveRestrictions; + } + + // + void SaveRestrictions(bool value) + { + mSaveRestrictions = value; + } + + // + void SetForceCloseTradesAt( + string _forceCloseAt // + ) + { + forceCloseAt = _forceCloseAt; + } + + // + void SetTradeSession( + string symbol, + string start, + string end, + string name = NULL // + ) + { + // + // Validate Args ... + bool has = IsValid(end) && + IsValid(start) && + IsValid(symbol); + if (!has) + { + return; + } + + // + // Create Session ... + + // + XCATBEATradeSession session; + + // + session.end = end; + session.name = name; + session.start = start; + + // + int sessionIDX = -1; + has = FindSymbolSession( + sessionIDX, + symbol // + ); + + // + if (!has) + { + // + // Add New Symbol Session ... + + // + XCATBEASymbolSession iSymbolSession; + iSymbolSession.symbol = symbol; + + // + AddTradingSession( + session, + iSymbolSession // + ); + + // + AddRef( + iSymbolSession, + sessions // + ); + + // + iSymbolSession.Clean(); + } + else + { + // + // Update Trading Sessions of Exists Symbol Session ... + AddTradingSession( + session, + sessions[sessionIDX] // + ); + } + + // + // Cleanup Resources ... + session.Clean(); + } + + // + void SetTradeReports( + bool _reportTrades, + bool _reportSignals, + bool _reportProtector, + bool _reportRestrictions, + bool _reportAfterTradesBalance // + ) + { + // + reportTrades = _reportTrades; + reportSignals = _reportSignals; + reportProtector = _reportProtector; + reportRestrictions = _reportRestrictions; + reportAfterTradesBalance = _reportAfterTradesBalance; + } + + // + void SetTradePermissions( + bool _allowTrade, + bool _allowLongs, + bool _allowShorts // + ) + { + // + allowTrade = _allowTrade; + allowLongs = _allowLongs; + allowShorts = _allowShorts; + } + + // + void SetTradeRestrictions( + ENUM_XCATBEA_TRADE_RESTRICTION_PERIOD _period, + int _maxAllowedTPs, + int _maxAllowedSLs, + int _maxAllowedTrades // + ) + { + // + // Normalizing Args ... + _maxAllowedTPs = NormalizeInt(_maxAllowedTPs, 0); + _maxAllowedSLs = NormalizeInt(_maxAllowedSLs, 0); + _maxAllowedTrades = NormalizeInt(_maxAllowedTrades, 0); + + // + restrictionsPeriod = _period; + maxAllowedTPs = _maxAllowedTPs; + maxAllowedSLs = _maxAllowedSLs; + maxAllowedTrades = _maxAllowedTrades; + } + + // + // Tools ... + + /** + * Do All Position Managing Senaros ... + */ + void Manage() + { + // + // Handle Restrictions ... + HandleRestrictions(); + + // + // Check Contains Trades for Managing ... + bool has = HasChild(trades); + if (!has) + { + return; + } + + // + // Update Required Infos of Trades ... + int count = ArraySize(trades); + for (int i = 0; i < count; i++) + { + // + has = trades[i].IsExecuted() && + !trades[i].IsFinalized(); + if (!has) + { + continue; + } + + // + XPosition iPosition; + has = trader.GetPosition( + trades[i].positionID, + iPosition // + ); + if (!has) + { + continue; + } + + // + // Update Trade Data ... + trades[i].swap = iPosition.swap; + trades[i].profit = iPosition.profit; + } + + // + // Do Trade Protection ... + Protect(); + } + + /** + * Do All Position Protection Here ... + */ + void Protect() + { + // + string prefix = "Protector: "; + int targetDistance = 5; + + // + bool has = HasChild(trades); + if (!has) + { + return; + } + + // + XPosition ownPosition[]; + XPosition ownLongPosition[]; + XPosition ownShortPosition[]; + + // + int count = ArraySize(trades); + for (int i = 0; i < count; i++) + { + // + has = + trades[i].IsExecuted() && + !trades[i].IsFinalized(); + if (!has) + { + continue; + } + + // + XPosition iPosition; + has = trader.GetPosition( + trades[i].positionID, + iPosition // + ); + if (!has) + { + continue; + } + + // + AddRef( + iPosition, + ownPosition // + ); + + // + if (IsLong(iPosition.type)) + { + // + AddRef( + iPosition, + ownLongPosition // + ); + } + else + { + // + AddRef( + iPosition, + ownShortPosition // + ); + } + } + + // + has = HasChild(ownPosition); + if (!has) + { + // + Clean(ownPosition); + Clean(ownLongPosition); + Clean(ownShortPosition); + + // + return; + } + + // + double swapSum = 0; + double profitSum = 0; + double commissionSum = 0; + + // + // Calculate Required Data On Collection ... + count = ArraySize(ownPosition); + for (int i = 0; i < count; i++) + { + // + XPosition iPosition = ownPosition[i]; + + // + swapSum += iPosition.swap; + profitSum += iPosition.profit; + commissionSum += iPosition.commission; + } + + // + // Do Collection Protectiong ... + + // + // Check Force Close ... + if (IsValid(forceCloseAt)) + { + // + datetime forceCloseTime = ParseDateTimeFromTimeString(forceCloseAt); + bool canForceClose = IsTimeInRange( + TimeCurrent(), + forceCloseTime // + ) && + !isForceCloseAtTime; + if (canForceClose) + { + // + isForceCloseAtTime = HandleForceCloseTrades(ownPosition); + + // + // Prevent Moving Forward ... + return; + } + } + + // + // Do Signle Protections ... + for (int i = 0; i < count; i++) + { + // + // Select Position ... + XPosition iPosition = ownPosition[i]; + int idx = -1; + has = HasTrade( + idx, + iPosition.ticket // + ); + if (!has) + { + continue; + } + + // + bool isLong = IsLong(iPosition.type); + double points = GetPoints(iPosition.symbol); + + // + // Handle RF On Targets ... + if (iPosition.profit > 0) + { + // + // Handle Risk Free On Targets ... + XTarget targets[]; + Copy( + trades[idx].signal.targets, + targets // + ); + int targetsCount = ArraySize(targets); + has = IsValidSize(targetsCount); + if (has) + { + // + for (int j = 0; j < targetsCount; j++) + { + // + XTarget jTarget = targets[j]; + + // + int appliedTargetIDX = -1; + + // + // Check Target is Applied Before or Not ... + has = + !trades[idx].signal.isTargetApplied + ? true + : trades[idx].signal.appliedTargetIDX < j; + if (!has) + { + continue; + } + + // + // Check Traget Validation ... + has = + iPosition.sl == 0 + ? true + : isLong + ? iPosition.sl < jTarget.target + : iPosition.sl > jTarget.target; + if (!has) + { + continue; + } + + // + double targetDelta = isLong + ? jTarget.target + (targetDistance * points) + : jTarget.target - (targetDistance * points); + + // + // Can Risk Free ... + bool canRF = + jTarget.doRF && + jTarget.target > 0 && + (isLong + ? jTarget.target > iPosition.entry + : jTarget.target < iPosition.entry) && + (isLong + ? iPosition.price > targetDelta + : iPosition.price < targetDelta); + + // + // Can Partial Close ... + bool canPC = + jTarget.volumeMultiplier > 0 && + jTarget.target > 0 && + (isLong + ? jTarget.target > iPosition.entry + : jTarget.target < iPosition.entry) && + (isLong + ? iPosition.price > targetDelta + : iPosition.price < targetDelta); + bool canRFPC = canRF || + canPC; + if (canRFPC) + { + // + // Handle Risk Free ... + bool isRFDone = false; + if (canRF) + { + // + double tp = iPosition.tp; + double sl = jTarget.target; + string comment = "RF On Target ..."; + isRFDone = trader.Modify( + iPosition.ticket, + sl, + tp, + comment // + ); + } + + // + // Handle Partail Close ... + bool isPCDone = false; + if (canPC) + { + // + double volume = jTarget.volumeMultiplier * iPosition.volume; + volume = NormalizeVolume(volume, iPosition.symbol); + string comment = "RF On Target ..."; + isPCDone = trader.ClosePartial( + iPosition.ticket, + volume, + comment // + ); + } + + // + // Handle Report Action ... + bool isRFPCDone = isRFDone || + isPCDone; + if (isRFPCDone) + { + // + trades[idx].signal.appliedTargetIDX = j; + trades[idx].signal.isTargetApplied = true; + + // + string message = prefix + + ToString(iPosition.type) + + " Position: " + + ToString(iPosition.ticket) + + (isRFDone ? " RF" : "") + + (isPCDone ? " PC" : "") + + " On Traget: " + ToString(jTarget.target) + + " Successfully ..."; + HandleReportProtector(message); + } + } + } + } + } + } + } + + /** + * Check Specified Symbol is Active for + * Analysing or Open Trades ... + */ + bool IsActiveSession(string symbol) + { + // + bool result = false; + + // + // Validate Args ... + result = IsValid(symbol); + if (!result) + { + return result; + } + + // + // Check Symbol Session Exists or not ... + int symbolSessionIDX = -1; + bool isSymbolSessionExists = FindSymbolSession( + symbolSessionIDX, + symbol // + ); + + // + // Chack Trade Session Validating ... + if (isSymbolSessionExists) + { + result = sessions[symbolSessionIDX].CanTrade(); + } + + // + return result; + } + + /** + * Check Signal Execution Conditions ... + * + * @param signal: XSignal instance reference ... + * @param executionResult: ENUM_X_SIGNAL_EXECUTION_RESULT member reference ... + * + * @return ( bool ) + */ + bool CheckSignal( + XSignal &signal, + ENUM_X_SIGNAL_EXECUTION_RESULT &executionResult // + ) + { + // + bool result = false; + + // + // Cleanup ... + executionResult = X_SIGNAL_EXECUTION_UNKNOWN; + + // + // Validate Signal ... + result = signal.IsValid(); + if (!result) + { + return result; + } + + // + // Reporting Signal ... + if (reportSignals) + { + // + string message = signal.GetMessage("Provided"); + alert.SendAlert(message); + } + + // + SaveSignal(signal); + + // + // Check Trade Permission ... + if (!allowTrade) + { + // + result = false; + executionResult = X_SIGNAL_EXECUTION_FAILED_NOT_ALLOWED; + + // + return result; + } + + // + bool isLong = IsLong(signal.type); + bool isShort = IsShort(signal.type); + + // + bool isLongAndAllowed = + isLong && + allowLongs; + + // + bool isShortAndAllowed = + isShort && + allowShorts; + + // + result = isLongAndAllowed || + isShortAndAllowed; + if (!result) + { + // + executionResult = X_SIGNAL_EXECUTION_FAILED_NOT_ALLOWED; + + // + return result; + } + + // + // Check Symbol Info Exists or not ... + int symbolInfoIDX = -1; + bool isSymbolInfoExists = FindSymbolIndex( + symbolInfoIDX, + signal.symbol // + ); + + // + // Check Symbol Session Exists or not ... + int symbolSessionIDX = -1; + bool isSymbolSessionExists = FindSymbolSession( + symbolSessionIDX, + signal.symbol // + ); + + // + // Chack Trade Session Validating ... + if (isSymbolSessionExists) + { + // + result = sessions[symbolSessionIDX].CanTrade(); + if (!result) + { + // + executionResult = X_SIGNAL_EXECUTION_FAILED_DELAY_NOT_PASSED; + + // + return result; + } + } + + // + // Check Trade Permissions Based on SL(s) Count ... + bool hasRestrictions = restrictionsPeriod != XCATBEA_TRADE_RESTRICATION_NONE; + if (hasRestrictions) + { + // + // Only Can Check Restrictions when + // Symbol Info Exists ... + if (isSymbolInfoExists) + { + // + bool isTPAllowed = maxAllowedTPs == 0 + ? true + : symbols[symbolInfoIDX].managedTPs < maxAllowedTPs; + bool isSLAllowed = maxAllowedSLs == 0 + ? true + : symbols[symbolInfoIDX].managedSLs < maxAllowedSLs; + bool isTradeAllowed = maxAllowedTrades == 0 + ? true + : symbols[symbolInfoIDX].managedTrades < maxAllowedTrades; + + // + result = isTPAllowed && + isSLAllowed && + isTradeAllowed; + } + + // + // Report Error ... + if (!result) + { + // + executionResult = X_SIGNAL_EXECUTION_FAILED_MAX_REACHED; + + // + return result; + } + } + + // + return result; + } + + /** + * Execute Specified Signal ... + * + * @param signal: XSignal instance reference ... + * @param conditions: XCATBEAStrategyConditions instance reference ... + * + * @return ( bool ) + */ + bool Execute( + XSignal &signal, + XCATBEAStrategyConditions &conditions // + ) + { + // + bool result = false; + + // + result = signal.IsValid(); + if (!result) + { + return result; + } + + // + int idx = -1; + bool isExists = HasTrade( + idx, + signal // + ); + result = !isExists; + if (!result) + { + return result; + } + + // + ENUM_X_SIGNAL_EXECUTION_RESULT executionResult; + + // + // Checking Signal For Execution ... + result = CheckSignal( + signal, + executionResult // + ); + if (result) + { + // + result = trader.ExecuteSignal( + signal, + executionResult // + ); + } + + // + // Alert Signal Execution ... + if (reportTrades) + { + // + string executionMessage = ToString(executionResult); + + // + string message = NULL; + if (result) + { + message = signal.GetMessage("Executed"); + } + else + { + message = signal.GetMessage("Failed due (" + executionMessage + ")"); + } + + // + alert.SendAlert(message); + } + + // + if (result) + { + // + // Draw Signal ... + if (drawSignal) + { + // + XCSignalObject *iObj; + isExists = drawer.DrawSignal( + signal, + iObj // + ); + + // + if (isExists) + { + // + mObjects.Add(iObj); + ZeroMemory(iObj); + } + } + + // + // Create Symbol Info Struct ... + XCATBEASymbolInfo iSymbolInfo; + + // + iSymbolInfo.trades = 1; + iSymbolInfo.managedTrades = 1; + iSymbolInfo.symbol = signal.symbol; + + // + bool isLong = IsLong(signal.type); + if (isLong) + { + iSymbolInfo.longs = 1; + } + else + { + iSymbolInfo.shorts = 1; + } + + // + // Fill Balance for Restrications ... + bool hasRestrictions = HasRestrictions(); + if (hasRestrictions) + { + // + // Read Balance ... + double balance = trader.mAccount.GetBalance(); + iSymbolInfo.managedBalance = balance; + iSymbolInfo.managedStart = TimeCurrent(); + } + + // + AddOrUpdateSymbolInfo(iSymbolInfo); + + // + // Create Trade Struct ... + XCATBEATrade iTrade; + + // + ulong positionID = trader.GetLastOpenPositionTicket(); + double commission = trader.GetPositionCommission(positionID); + + // + iTrade.signal = signal; + iTrade.conditions = conditions; + iTrade.positionID = positionID; + iTrade.commission = commission; + iTrade.signaledAt = signal.time; + iTrade.executedAt = TimeCurrent(); + + // + AddRef( + iTrade, + trades // + ); + } + + // + return result; + } + + /** + * Retrieve Specified Positions ... + * + * @param positions: XPosition instance Reference Array, which holds Founded Positions ... + * @param symbol: string, Specified Symbol Name ... + * @param provider: string, Specified Provider Name ... + * @param period: ENUM_TIMEFRAMES, Specified Period ... + * + * @return ( int ) + */ + int GetPositions( + XPosition &positions[], + string symbol, + string provider, + ENUM_TIMEFRAMES period // + ) + { + // + int result = 0; + + // + Clean(positions); + + // + bool has = + IsValid(symbol) && + IsValid(period) && + IsValid(provider); + if (!has) + { + return result; + } + + // + result = trader.GetPositions( + positions, + symbol, + provider, + period, + NULL, // All Types ... + true, // Filter By Magic ... + true // Force Clean ... + ); + + // + result = ArraySize(positions); + + // + return result; + } + + /** + * Handle Position Take Profit ... + * + * @param deal: XDeal instance reference ... + */ + void HandleTP(const XDeal &deal) + { + // + // Check Ticket Exists or not ... + int idx = -1; + bool isExists = HasTrade( + idx, + deal.positionId // + ); + if (!isExists) + { + return; + } + + // + // Apply Required Data ... + trades[idx].swap = deal.swap; + trades[idx].profit = deal.profit; + trades[idx].finalizedAt = TimeCurrent(); + trades[idx].finalize = XCATBEA_TRADE_FINAL_TP; + + // + // Save Trade ... + SaveWin(trades[idx]); + SaveTrade(trades[idx]); + + // + // Handle Balance Reporting ... + string prefix = "TP: " + ToString(trades[idx].profit); + HandleReportBalance(prefix); + + // + // Handle Symbol Info ... + + // + XCATBEASymbolInfo iSymbolInfo; + + // + iSymbolInfo.profits = 1; + iSymbolInfo.managedTPs = 1; + iSymbolInfo.symbol = trades[idx].signal.symbol; + iSymbolInfo.managedProfits = trades[idx].profit; + + // + AddOrUpdateSymbolInfo(iSymbolInfo); + + // + RemoveTrade(idx); + } + + /** + * Handle Position Stop Loss ... + * + * @param deal: XDeal instance reference ... + */ + void HandleSL(const XDeal &deal) + { + // + // Check Ticket Exists or not ... + int idx = -1; + bool isExists = HasTrade( + idx, + deal.positionId // + ); + if (!isExists) + { + return; + } + + // + // Apply Required Data ... + trades[idx].swap = deal.swap; + trades[idx].profit = deal.profit; + trades[idx].finalizedAt = TimeCurrent(); + trades[idx].finalize = XCATBEA_TRADE_FINAL_SL; + + // + // Save Trade ... + SaveTrade(trades[idx]); + + // + // Handle Balance Reporting ... + string prefix = "SL: " + ToString(trades[idx].profit); + HandleReportBalance(prefix); + + // + // Handle Symbol Info ... + + // + bool isInProfit = trades[idx].profit > 0; + if (isInProfit) + { + SaveWin(trades[idx]); + } + else + { + SaveLost(trades[idx]); + } + + // + XCATBEASymbolInfo iSymbolInfo; + + // + if (isInProfit) + { + // + iSymbolInfo.profits = 1; + iSymbolInfo.managedTPs = 1; + } + else + { + // + iSymbolInfo.losses = 1; + iSymbolInfo.managedSLs = 1; + } + iSymbolInfo.symbol = trades[idx].signal.symbol; + iSymbolInfo.managedProfits = trades[idx].profit; + + // + AddOrUpdateSymbolInfo(iSymbolInfo); + + // + RemoveTrade(idx); + } + + /** + * Handle Position Force Close ... + * + * @param deal: XDeal instance reference ... + */ + void HandleForceClose(const XPosition &position) + { + // + // Check Ticket Exists or not ... + int idx = -1; + bool isExists = HasTrade( + idx, + position.ticket // + ); + if (!isExists) + { + return; + } + + // + bool isInProfit = position.profit > 0; + + // + // Apply Required Data ... + trades[idx].swap = position.swap; + trades[idx].profit = position.profit; + trades[idx].finalizedAt = TimeCurrent(); + trades[idx].commission = position.commission; + trades[idx].finalize = isInProfit + ? XCATBEA_TRADE_FINAL_CLOSE_IN_PROFIT + : XCATBEA_TRADE_FINAL_CLOSE_IN_LOSE; + + // + // Save Trade ... + SaveTrade(trades[idx]); + if (isInProfit) + { + SaveWin(trades[idx]); + } + else + { + SaveLost(trades[idx]); + } + + // + // Handle Balance Reporting ... + string prefix = "Force Close " + + (isInProfit + ? "Profit" + : "Loss") + + ": " + + ToString(trades[idx].profit); + HandleReportBalance(prefix); + + // + // Handle Symbol Info ... + + // + XCATBEASymbolInfo iSymbolInfo; + + // + if (isInProfit) + { + // + iSymbolInfo.profits = 1; + iSymbolInfo.managedTPs = 1; + } + else + { + // + iSymbolInfo.losses = 1; + iSymbolInfo.managedSLs = 1; + } + iSymbolInfo.symbol = trades[idx].signal.symbol; + iSymbolInfo.managedProfits = trades[idx].profit; + + // + AddOrUpdateSymbolInfo(iSymbolInfo); + + // + RemoveTrade(idx); + } + + /** + * Handle Position Partially Closed Event ... + * + * @param ticket: ULONG ... + * @param profit: double ... + * @param comment: string ... + */ + void HandlePartiallyClosed( + const ulong ticket, + const double profit, + const string comment // + ) + { + // + // Handle Balance Reporting ... + string prefix = "Partially Closed: " + ToString(ticket); + + // + // Handle Balance Reporting ... + HandleReportBalance(prefix); + } + + /** + * Handle Force Close Trades ... + */ + bool HandleForceCloseTrades( + XPosition &positions[] // + ) + { + // + bool result = false; + + // + result = HasChild(positions); + if (!result) + { + return result; + } + + // + string prefix = "Protector: "; + string comment = "Force Close ..."; + + // + int closedsCount = trader.Close( + positions, + comment // + ); + result = IsValidSize(closedsCount); + if (result) + { + // + string message = prefix + "Force Close (" + ToString(closedsCount) + ") Trades at Specified Time ..."; + HandleReportProtector(message); + } + + // + return result; + } + + // + // TODO: Complete this ... + void HandleGuard() + { + } + + /** + * Find Executed Trade by Providing Position Ticket ... + * + * @param index: int reference, holding founded item index ... + * @param ticket: ulong, Specified Position Ticket ... + * + * @return ( bool ) + */ + bool HasTrade( + int &index, + ulong ticket // + ) + { + // + bool result = false; + + // + index = -1; + + // + result = + ticket > 0 && + HasChild(trades); + if (!result) + { + return result; + } + + // + int count = ArraySize(trades); + for (int i = 0; i < count; i++) + { + // + XCATBEATrade iTrade = trades[i]; + + // + result = + iTrade.HasSignal() && + iTrade.IsExecuted() && + iTrade.positionID == ticket; + if (result) + { + // + index = i; + + // + iTrade.Clean(); + break; + } + + // + iTrade.Clean(); + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Find Trade Item By Signal ... + * + * @param index: int reference, holding founded item index ... + * + * @return ( bool ) + */ + bool HasTrade( + int &index, + XSignal &signal // + ) + { + // + bool result = false; + + // + index = -1; + + // + result = + signal.IsValid() && + HasChild(trades); + if (!result) + { + return result; + } + + // + int count = ArraySize(trades); + for (int i = 0; i < count; i++) + { + // + XCATBEATrade iTrade = trades[i]; + + // + result = + iTrade.HasSignal() && + iTrade.signal.IsSameAs(signal); + if (result) + { + // + index = i; + + // + iTrade.Clean(); + break; + } + + // + iTrade.Clean(); + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * Remove a Trade From List ... + * + * @param index: int ... + */ + void RemoveTrade(int index) + { + // + bool has = + HasChild(trades) && + IsValidIndex(index) && + index < ArraySize(trades); + if (!has) + { + return; + } + + // + ArrayRemove( + trades, + index, + 1 // + ); + } + + // + // Protected ... + protected: + // + // Tools ... + + // + string GetTradeFilePath(XCATBEATrade &trade) + { + // + string fileName = trade.GetFileName(); + + // + return GetTradeFilePath(fileName); + } + + // + string GetTradeFilePath(string fileName) + { + // + string result = NULL; + + // + result = collector + .GetFilePath("Trades" + "\\" + fileName); + + // + return result; + } + + // + string GetSignalFilePath(string fileName) + { + // + string result = NULL; + + // + result = collector + .GetFilePath("Signals" + "\\" + fileName); + + // + return result; + } + + // + string GetWinsFilePath(XCATBEATrade &trade) + { + // + string result = NULL; + + // + result = collector + .GetFilePath("Conditions" + "\\" + + trade.signal.symbol + "\\" + + ToString(trade.signal.period) + "_wins"); + + // + return result; + } + + // + string GetLostsFilePath(XCATBEATrade &trade) + { + // + string result = NULL; + + // + result = collector + .GetFilePath("Conditions" + "\\" + + trade.signal.symbol + "\\" + + ToString(trade.signal.period) + "_losts"); + + // + return result; + } + + // + string GetRestrictionsFilePath(string symbol) + { + // + string result = NULL; + + // + if (!IsValid(symbol)) + { + return result; + } + + // + result = collector + .GetFilePath("Restrictions" + "\\" + symbol); + + // + return result; + } + + // + void HandleReportBalance(string prefix = NULL) + { + // + if (!reportAfterTradesBalance) + { + return; + } + + // + double balance = trader.mAccount.GetBalance(); + string currency = trader.mAccount.GetCurrency(); + + // + string message = + (IsValid(prefix) + ? prefix + " | " + : "") + + "Account Balance: " + ToString(balance) + currency; + alert.SendAlert(message); + } + + // + void HandleReportProtector(string message = NULL) + { + // + if (!reportProtector) + { + return; + } + + // + alert.SendAlert(message); + } + + // + // Save Trades ... + bool SaveTrade( + XCATBEATrade &trade, + bool includeSummary = true, + bool includeSignal = true, + bool includeConditions = true // + ) + { + // + bool result = false; + + // + if (!mSaveTrades) + { + return result; + } + + // + string filePath = GetTradeFilePath(trade); + result = IsValid(filePath); + if (!result) + { + return result; + } + + // + string content = trade.ToString( + includeSummary, + includeSignal, + includeConditions // + ); + + // + result = collector.Save( + filePath, + content // + ); + + // + return result; + } + + // + // Save Signals ... + bool SaveSignal(XSignal &signal) + { + // + bool result = false; + + // + // Check Signal Save is Enabled ... + if (!mSaveSignals) + { + return result; + } + + // + // Check Signal Validation ... + if (!signal.IsValid()) + { + return result; + } + + // + // Retrieve Signal File Name ... + string signalFileName = signal.GetFileName(); + result = IsValid(signalFileName); + if (!result) + { + return result; + } + + // + // Retriev and Validate File Name ... + string filePath = GetSignalFilePath(signalFileName); + result = IsValid(filePath); + if (!result) + { + return result; + } + + // + // Generate Content ... + string content = ""; + content += + ToString("----------------") + "\n" + + ToString("Signal: ") + "\n" + + ToString("----------------") + "\n" + + signal.ToString() + "\n"; + content += + ToString("----------------") + "\n" + + ToString("Conditions: ") + "\n" + + ToString("----------------") + "\n" + + signal.conditions + "\n"; + + // + // Save Content to File ... + result = collector.Save( + filePath, + content // + ); + + // + // Return Result ... + return result; + } + + // + bool SaveWin(XCATBEATrade &trade) + { + // + bool result = false; + + // + if (!mSaveWins) + { + return result; + } + + // + string filePath = GetWinsFilePath(trade); + result = IsValid(filePath); + if (!result) + { + return result; + } + + // + // Preparing Conditions Content ... + string content = trade.GetConditionsString(); + + // + result = collector.Append( + filePath, + content // + ); + + // + return result; + } + + // + bool SaveLost(XCATBEATrade &trade) + { + // + bool result = false; + + // + if (!mSaveLosts) + { + return result; + } + + // + string filePath = GetLostsFilePath(trade); + result = IsValid(filePath); + if (!result) + { + return result; + } + + // + // Preparing Conditions Content ... + string content = trade.GetConditionsString(); + + // + result = collector.Append( + filePath, + content // + ); + + // + return result; + } + + // + bool SaveRestrictions(XCATBEASymbolInfo &info) + { + // + bool result = false; + + // + if (!mSaveRestrictions) + { + return result; + } + + // + result = info.IsValid(); + if (!result) + { + return result; + } + + // + string filePath = GetRestrictionsFilePath(info.symbol); + result = IsValid(filePath); + if (!result) + { + return result; + } + + // + string content = info.GetRestrictionDescription(restrictionsPeriod); + + // + result = collector.Append( + filePath, + content // + ); + + // + return result; + } + + // + // Symbol Info ... + + // + bool FindSymbolIndex( + int &index, + XCATBEASymbolInfo &item // + ) + { + // + bool result = false; + + // + index = -1; + + // + result = item.IsValid(); + if (!result) + { + return result; + } + + // + result = HasChild(symbols); + if (!result) + { + return result; + } + + // + index = FindIndex( + item, + symbols // + ); + + // + result = IsValidIndex(index); + + // + return result; + } + + // + bool FindSymbolIndex( + int &index, + string symbol // + ) + { + // + bool result = false; + + // + index = -1; + + // + result = IsValid(symbol) && + HasChild(symbols); + if (!result) + { + return result; + } + + // + int count = ArraySize(symbols); + for (int i = 0; i < count; i++) + { + // + result = symbols[i].symbol == symbol; + if (result) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + // + void AddOrUpdateSymbolInfo(XCATBEASymbolInfo &item) + { + // + bool has = item.IsValid(); + if (!has) + { + return; + } + + // + int index = -1; + bool isExists = FindSymbolIndex( + index, + item // + ); + if (!isExists) + { + // + AddRef( + item, + symbols // + ); + } + else + { + // + symbols[index].longs += item.longs; + symbols[index].shorts += item.shorts; + symbols[index].trades += item.trades; + symbols[index].losses += item.losses; + symbols[index].profits += item.profits; + symbols[index].managedSLs += item.managedSLs; + symbols[index].managedTPs += item.managedTPs; + symbols[index].managedTrades += item.managedTrades; + symbols[index].managedProfits += item.managedProfits; + + // + // Handle Remove on Managed SL based On Managed TP ... + if (item.managedTPs > 0) + { + // + symbols[index].managedSLs -= item.managedTPs; + if (symbols[index].managedSLs < 0) + { + symbols[index].managedSLs = 0; + } + } + + // + // Handle Remove on Managed TP based On Managed SL ... + if (item.managedSLs > 0) + { + // + symbols[index].managedTPs -= item.managedSLs; + if (symbols[index].managedTPs < 0) + { + symbols[index].managedTPs = 0; + } + } + } + } + + // + void ResetSymbolsRestrictions() + { + // + bool has = HasChild(symbols); + if (has) + { + // + string prefix = "Protector: "; + + // + datetime start = TimeCurrent(); + double balance = trader.mAccount.GetBalance(); + bool hasRestrictions = HasRestrictions(); + if (!hasRestrictions) + { + // + balance = 0; + start = NULL; + } + + // + int count = ArraySize(symbols); + for (int i = 0; i < count; i++) + { + // + XCATBEASymbolInfo iInfo = symbols[i]; + if (reportRestrictions) + { + // + string message = iInfo.GetRestrictionDescription(restrictionsPeriod); + alert.SendAlert(message); + } + SaveRestrictions(iInfo); + + // + symbols[i].managedSLs = 0; + symbols[i].managedTPs = 0; + symbols[i].managedTrades = 0; + symbols[i].managedProfits = 0; + symbols[i].managedStart = start; + symbols[i].managedBalance = balance; + + // + iInfo.Clean(); + } + + // + string message = prefix + "Reset Symbols Restrictions"; + HandleReportProtector(message); + } + } + + // + void HandleRestrictions() + { + // + bool isNewDay = timeTracker.IsNewDay(); + bool isNewHour = timeTracker.IsNewHour(); + bool isNewWeek = timeTracker.IsNewWeek(); + bool isNewMonth = timeTracker.IsNewMonth(); + + // + // Reset Force Closed Flag on new Day Starts ... + if (isNewDay) + { + isForceCloseAtTime = false; + } + + // + bool canResetRestrictions = + ( + // + // Hourly ... + (isNewHour && + restrictionsPeriod == XCATBEA_TRADE_RESTRICATION_HOURLY) + // + || + // + // Daily ... + (isNewDay && + restrictionsPeriod == XCATBEA_TRADE_RESTRICATION_DAILY) + // + || + // + // Weekly ... + (isNewWeek && + restrictionsPeriod == XCATBEA_TRADE_RESTRICATION_WEEKLY) + // + || + // + // Monthly ... + (isNewMonth && + restrictionsPeriod == XCATBEA_TRADE_RESTRICATION_MONTHLY) + // + ) + // + ; + if (canResetRestrictions) + { + ResetSymbolsRestrictions(); + } + } + + // + // Symbol Session ... + + // + bool FindSymbolSession( + int &index, + string symbol // + ) + { + // + bool result = false; + + // + index = -1; + + // + result = IsValid(symbol) && + HasChild(sessions); + if (!result) + { + return result; + } + + // + int count = ArraySize(sessions); + for (int i = 0; i < count; i++) + { + // + result = sessions[i].symbol == symbol; + if (result) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + // + void AddTradingSession( + XCATBEATradeSession &session, + XCATBEASymbolSession &symbolSession // + ) + { + // + bool has = session.IsValid() && + symbolSession.IsValid(); + if (!has) + { + return; + } + + // + // Check Session Exists in Symbol Session ... + bool isExists = false; + if (HasChild(symbolSession.sessions)) + { + // + int count = ArraySize(symbolSession.sessions); + for (int i = 0; i < count; i++) + { + // + isExists = symbolSession.sessions[i].end == session.end && + symbolSession.sessions[i].start == session.start; + if (isExists) + { + break; + } + } + } + + // + if (!isExists) + { + // + AddRef( + session, + symbolSession.sessions // + ); + } + } + + // + // Private ... + private: + // + // Props ... + + // + bool allowTrade; + bool allowLongs; + bool allowShorts; + + // + string forceCloseAt; + bool isForceCloseAtTime; + + // + int maxAllowedTPs; + int maxAllowedSLs; + int maxAllowedTrades; + ENUM_XCATBEA_TRADE_RESTRICTION_PERIOD restrictionsPeriod; + bool HasRestrictions() + { + return restrictionsPeriod != XCATBEA_TRADE_RESTRICATION_NONE; + } + + // + bool mSaveWins; + bool mSaveLosts; + bool mSaveTrades; + bool mSaveSignals; + bool mSaveRestrictions; + + // + bool reportTrades; + bool reportSignals; + bool reportProtector; + bool reportRestrictions; + bool reportAfterTradesBalance; + + // + CArrayObj mObjects; + + // + XCATBEATrade trades[]; + XCATBEASymbolInfo symbols[]; + XCATBEASymbolSession sessions[]; +}; + +// diff --git a/BKPS/14040316/XCATBEA/Libraries/xcatbea.lib.mq5 b/BKPS/14040316/XCATBEA/Libraries/xcatbea.lib.mq5 new file mode 100644 index 0000000..992ab89 --- /dev/null +++ b/BKPS/14040316/XCATBEA/Libraries/xcatbea.lib.mq5 @@ -0,0 +1,2996 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XCATBEA Lib +// Description: Library for XCATBEA ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm Library for XCATBEA Signaller" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-bar.analyser.class.mq5" +#include "../../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../../Helpers/x-saherelm.x121.xcatb.helper.mq5" + +// +// Definiions ... + +// +#define XLiquidityToken "XLQ"; +#define XTriggerBlockToken "XTRG"; + +// +struct XTriggerBlock +{ + // + // Props ... + XBoxZone ob; // Order Block + XBoxZone fvg; // Fair Value Gap + XOHCL swingBar; // Swing of Trigger + XBoxZone trigger; // Trigger Block + XBoxZone rLiquidity; // Reversal Liquidity + XBoxZone fLiquidity; // Following Liquidity + + // + XSignal signal; // Pepared Signal + + // + // Constructor ... + XTriggerBlock() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + ob.Clean(); + fvg.Clean(); + signal.Clean(); + trigger.Clean(); + swingBar.Clean(); + rLiquidity.Clean(); + fLiquidity.Clean(); + + // + ZeroMemory(this); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = ob.IsValid() && + fvg.IsValid() && + trigger.IsValid(); + + // + return result; + } + + // + bool IsBullish() + { + return IsValid() && + ob.IsBullish(); + } + + // + bool IsBearish() + { + return IsValid() && + ob.IsBearish(); + } + + // + int ToIndex() + { + return trigger.ToIndex(); + } + + // + int FromIndex() + { + return trigger.FromIndex(); + } + + // + ENUM_X_DIRECTION GetDirection() + { + // + ENUM_X_DIRECTION result = X_DIRECTION_NONE; + + // + if (IsValid()) + { + result = ob.dir; + } + + // + return result; + } + + // +}; + +// +// Trigger Block Validation Rules ... +struct XTriggerBlockValidationRules +{ + // + // Props ... + bool forceHasSwing; // Force Block to Has Propper Swing ... + bool forceOBBarType; // Force Order Block to Has InDirectional Bars ... + int minRequiredOBBar; // Min Required OB Bar ... + bool forceFVGBarType; // Force Fair Value Gaps Bars Type ... + int liquidityLoopback; // Liquidity Detection Loopback ... + double maxAllowedRange; // Max Allowed Order Block Range ... + double minAllowedRange; // Min Allowed Order Block Range ... + bool forceHasFLiquidity; // Force Order Block To Has Reversal Liquidity ... + bool forceHasRLiquidity; // Force Order Block to Has Following Liquidity ... + bool validateGapSequence; // Validate Fair Value Gaps Bar Sequences ... + int minAllowedBlockLength; // Min Allowed Block Length ... + bool validateBlockEdgeBreakout; // Validate Order Block Edge Breakeout ... + + // + // Constructor(s) ... + XTriggerBlockValidationRules() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + maxAllowedRange = 0; + minAllowedRange = 0; + minRequiredOBBar = 0; + liquidityLoopback = 0; + forceHasSwing = false; + forceOBBarType = false; + forceFVGBarType = false; + minAllowedBlockLength = 0; + forceHasFLiquidity = false; + forceHasRLiquidity = false; + validateGapSequence = false; + validateBlockEdgeBreakout = false; + + // + ZeroMemory(this); + } +}; + +// +// Trigger Block Filters ... +struct XTriggerBlockFilters +{ + // + // Props ... + bool filterBasedOnKI; // Filter Based On KI Flats ... + bool filterBasedOnPV; // Filter Based On PV ... + bool filterBasedOnSar; // Filter Based On SAR ... + bool filterBasedOnRSI; // Filter Based On RSI ... + bool filterBasedOnADX; // Filter Based On ADX ... + bool filterBasedOnATR; // Filter Based On ATR ... + bool filterBasedOnTrend; // Filter Based On Trend ... + bool filterBasedOnDelta; // Filter Based On Delta ... + bool filterBasedOnVolume; // Filter Based On Volume ... + bool filterBasedOnSignalBar; // Filter Based on Signal Bar ... + bool filterBasedOnHKSignalBar; // Filter Based On HK Signal Bar ... + + // + int bosLoopback; // PV Based Filtering BOS Lookup ... + + // + bool forceSarSwitched; // SAR Switched on Sides for Filtering ... + bool forceSarOnBothSide; // SAR Check on Both Sides for Filtering ... + bool forceSarHasBreakout; // SAR Must SAR Must Breakout ... + bool forceSarHasReversalSide; // SAR Must SAR Must Has Reversal Direction ... + + // + bool forceHasRSITrending; // RSI Must Has Trending ... + bool forceHasRSIVPattern; // RSI Must Has Pattern ... + bool forceHasRSICrossing; // RSI Must Has Crossing Levels ... + + // + bool forceHasADXTrending; // ADX Must Has Trending ... + bool forceHasADXCrossing; // ADX Must Has Crossing +DI/-DI ... + + // + bool forceHasATRTrending; // ATR Must Has Trending ... + bool forceHasATRBreakout; // ATR Must Has Breakout ... + + // + bool forceHasTrendDir; // TREND Must Has Following Direction ... + bool forceHasTrendPlace; // TREND Place Based Filtering ... + bool forceHasTrendChange; // TREND Change Filtering ... + bool forceHasTrendTrending; // TREND Must Has Trending ... + bool forceHasTrendRejection; // TREND Line Must Rejected ... + bool forceHasTrendLineInside; // TREND Line has Inside ... + bool forceHasTrendDirOnBothSide; // TREND Must Has Following Direction in Both Side ... + + // + // Constructor(s) ... + XTriggerBlockFilters() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + filterBasedOnKI = false; + filterBasedOnPV = false; + filterBasedOnSar = false; + filterBasedOnRSI = false; + filterBasedOnADX = false; + filterBasedOnATR = false; + filterBasedOnTrend = false; + filterBasedOnDelta = false; + filterBasedOnVolume = false; + filterBasedOnSignalBar = false; + filterBasedOnHKSignalBar = false; + + // + bosLoopback = 0; + + // + forceSarSwitched = false; + forceSarOnBothSide = false; + forceSarHasBreakout = false; + forceSarHasReversalSide = false; + + // + forceHasRSITrending = false; + forceHasRSIVPattern = false; + forceHasRSICrossing = false; + + // + forceHasADXTrending = false; + forceHasADXCrossing = false; + + // + forceHasATRTrending = false; + forceHasATRBreakout = false; + + // + forceHasTrendDir = false; + forceHasTrendPlace = false; + forceHasTrendChange = false; + forceHasTrendTrending = false; + forceHasTrendRejection = false; + forceHasTrendLineInside = false; + forceHasTrendDirOnBothSide = false; + + // + ZeroMemory(this); + } +}; + +// +// Extensions ... + +/** + * Get Newest Trigger Block Index inside a Collection ... + * + * @return ( int ) + */ +int GetYoungest(XTriggerBlock &tbs[]) +{ + // + int result = -1; + + // + // Checking Collection Has Childs ... + if (!HasChild(tbs)) + { + return result; + } + + // + datetime selected = NULL; + int count = ArraySize(tbs); + for (int i = 0; i < count; i++) + { + // + bool canSelect = + !IsValid(selected) + ? true + : tbs[i].trigger.from > selected; + if (canSelect) + { + // + result = i; + selected = tbs[i].trigger.from; + } + } + + // + return result; +} + +/** + * Get Oldest Trigger Block Index inside a Collection ... + * + * @return ( int ) + */ +int GetOldest(XTriggerBlock &tbs[]) +{ + // + int result = -1; + + // + // Checking Collection Has Childs ... + if (!HasChild(tbs)) + { + return result; + } + + // + datetime selected = NULL; + int count = ArraySize(tbs); + for (int i = 0; i < count; i++) + { + // + bool canSelect = + !IsValid(selected) + ? true + : tbs[i].trigger.from < selected; + if (canSelect) + { + // + result = i; + selected = tbs[i].trigger.from; + } + } + + // + return result; +} + +/** + * Get Highest Trigger Block Index inside a Collection ... + * + * @return ( int ) + */ +int GetHighest(XTriggerBlock &tbs[]) +{ + // + int result = -1; + + // + // Checking Collection Has Childs ... + if (!HasChild(tbs)) + { + return result; + } + + // + double selected = 0; + int count = ArraySize(tbs); + for (int i = 0; i < count; i++) + { + // + bool canSelect = + selected <= 0 + ? true + : tbs[i].trigger.lower > selected; + if (canSelect) + { + // + result = i; + selected = tbs[i].trigger.lower; + } + } + + // + return result; +} + +/** + * Get Lowest Trigger Block Index inside a Collection ... + * + * @return ( int ) + */ +int GetLowest(XTriggerBlock &tbs[]) +{ + // + int result = -1; + + // + // Checking Collection Has Childs ... + if (!HasChild(tbs)) + { + return result; + } + + // + double selected = 0; + int count = ArraySize(tbs); + for (int i = 0; i < count; i++) + { + // + bool canSelect = + selected <= 0 + ? true + : tbs[i].trigger.upper < selected; + if (canSelect) + { + // + result = i; + selected = tbs[i].trigger.upper; + } + } + + // + return result; +} + +/** + * Find Trigger Block Index inside a Colletion ... + */ +bool FindTriggerBlockIndex( + int &index, + XTriggerBlock &tb, + XTriggerBlock &tbs[] // +) +{ + // + bool result = false; + + // + index = -1; + + // + result = tb.IsValid(); + if (!result) + { + return result; + } + + // + bool isExists = false; + bool has = HasChild(tbs); + if (has) + { + // + int count = ArraySize(tbs); + for (int i = 0; i < count; i++) + { + // + isExists = tb.trigger.IsSameAs(tbs[i].trigger); + if (isExists) + { + // + index = i; + break; + } + } + } + + // + result = + isExists && + IsValidIndex(index); + + // + return result; +} + +/** + * Remove Specified Trigger Block from a Collection, if Exists ... + * + * @param tb: XTriggerBlock instance reference, Specified Trigger Block for Checking ... + * @param tbs: XTriggerBlock instance reference Array, Collection of Trigger Blocks ... + * + * @return ( bool ) + */ +bool RemoveTriggerBlock( + XTriggerBlock &tb, + XTriggerBlock &tbs[] // +) +{ + // + bool result = false; + + // + // Validate Args ... + result = tb.IsValid() && + HasChild(tbs); + if (!result) + { + return result; + } + + // + int idx = -1; + result = FindTriggerBlockIndex( + idx, + tb, + tbs // + ); + if (!result) + { + return result; + } + + // + result = ArrayRemove( + tbs, + idx, + 1 // + ); + + // + return result; +} + +/** + * Detect a TriggerBlock which Specified TriggerBlock is Inside of it ... + * + * @param tb: XTriggerBlock instance reference, Specified Trigger Block for Checking ... + * @param insideTB: XTriggerBlock instance reference, Holds founded inside Trigger Block ... + * @param tbs: XTriggerBlock instance collection, Specified Collection for Checking ... + * @param minimumLengthBetweenTBs: int, Minimum Bars between two Trigger Blocks ... + * + * @return ( int ) founded Inside TriggerBlock index ... + */ +int DetectInsideTriggerBlock( + XTriggerBlock &tb, + XTriggerBlock &insideTB, + XTriggerBlock &tbs[], + int minimumLengthBetweenTBs = 5 // +) +{ + // + int result = -1; + + // + // Normalize Args ... + minimumLengthBetweenTBs = NormalizeInt(minimumLengthBetweenTBs, 3); + + // + // Check Collection has Childs ... + bool has = HasChild(tbs); + if (!has) + { + return result; + } + + // + insideTB.Clean(); + bool isBullish = tb.IsBullish(); + bool isBearish = tb.IsBearish(); + + // + int count = ArraySize(tbs); + for (int i = 0; i < count; i++) + { + // + // Check Trigger Block Conditions ... + bool isInside = + // + // Check Not Same ... + !tb.trigger.IsSameAs(tbs[i].trigger) && + // + // Check Direction ... + tb.trigger.dir == tbs[i].trigger.dir && + // + // Check Length of TBS ... + (minimumLengthBetweenTBs <= 0 + ? true + : tb.trigger.FromIndex() + minimumLengthBetweenTBs <= tbs[i].trigger.FromIndex()) && + // + // Check Inside it ... + (isBullish + ? (tb.trigger.lower < tbs[i].trigger.upper && + tb.trigger.lower > tbs[i].trigger.lower && + tb.trigger.lower < tbs[i].trigger.GetMid()) + : (tb.trigger.upper > tbs[i].trigger.lower && + tb.trigger.upper < tbs[i].trigger.upper && + tb.trigger.upper > tbs[i].trigger.GetMid())) && + // + // Check Last ... + (!insideTB.IsValid() + ? true + : isBullish + ? insideTB.trigger.upper > tbs[i].trigger.upper + : insideTB.trigger.lower < tbs[i].trigger.lower) + // + ; + if (isInside) + { + // + result = i; + insideTB = tbs[i]; + } + } + + // + return result; +} + +/** + * Detect Trigger Block ... + * + * @param helper: XCX121XCatbHelper instance pointer ... + * @param barAnalyser: XCBarAnalyser instance pointer ... + * @param triggerBlock: XTriggerBlock Refrence, holds Detected Trigger Block ... + * @param conditions: X121XCatbConditions Refrence, holds Trigger Block Conditions ... + * @param validations: XTriggerBlockValidationRules Refrence, Provides Trigger Block Validation Rules ... + * @param filters: XTriggerBlockFilters Refrence, Provides Trigger Block Filters ... + * @param barIndex: int, Bar Index ... + * @param loopback: int, Loopback for Conditions reading ... + * + * @return ( bool ) + */ +bool DetectTriggerBlock( + XCX121XCatbHelper *helper, + XCBarAnalyser *barAnalyser, + XTriggerBlock &triggerBlock, + X121XCatbConditions &conditions, + XTriggerBlockValidationRules &validations, + XTriggerBlockFilters &filters, + int barIndex = 0, + int loopback = 10 // +) +{ + // + bool result = false; + + // + // Normalize Args ... + conditions.Clean(); + triggerBlock.Clean(); + barIndex = NormalizeInt(barIndex, 0); + loopback = NormalizeInt(loopback, 0); + + // + // Validate Args ... + result = + helper != NULL && + barAnalyser != NULL; + if (!result) + { + return result; + } + + // + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + int p3IDX = p2IDX + 1; + int p4IDX = p3IDX + 1; + + // + bool has = false; + string symbol = helper.GetSymbol(); + ENUM_TIMEFRAMES period = helper.GetPeriod(); + + // + // Initial Requirements ... + + // + // Required Bars ... + XOHCL zBar; + XOHCL cBar; + result = + result && + zBar.Init( + symbol, + period, + barIndex // + ); + result = + result && + zBar.GetPreviousBar(cBar); + + // + // Here we Must Detect Order Block ... + // then Detect FVG ... + // then Prepare Trigger Box ... + + // + // Select Application Bar ... + XOHCL iBar; + if (barIndex == 0) + { + iBar = cBar; + } + else if (barIndex > 0) + { + iBar = zBar; + } + iBar = cBar; + result = + result && + iBar.IsValid(); + + // + // Detect Order Block ... + result = + result && + barAnalyser + .IsOB( + iBar, + triggerBlock.ob, + false, + false // + ); + + // + // Detect Fair Value Gap ... + result = + result && + barAnalyser + .IsFVG( + iBar, + triggerBlock.fvg, + false // + ); + + // + // Check Result and Create Trigger Box based on it ... + if (result) + { + // + triggerBlock.trigger = triggerBlock.ob; + triggerBlock.trigger.type = XTriggerBlockToken; + + // + // Update Upper and Lower ... + int toIDX = triggerBlock.ob.ToIndex(); + int fromIDX = triggerBlock.ob.FromIndex(); + + // + iBar.Clean(); + result = iBar.Init( + symbol, + period, + toIDX // + ); + if (result) + { + // + double iLL = iBar.FindLowest(fromIDX - toIDX, MODE_LOW); + double iHH = iBar.FindHighest(fromIDX - toIDX, MODE_HIGH); + + // + triggerBlock.trigger.upper = MathMax(iHH, triggerBlock.trigger.upper); + triggerBlock.trigger.lower = MathMin(iLL, triggerBlock.trigger.lower); + } + + // + iBar.Clean(); + } + + // + // Apply Validations ... + if (result) + { + // + result = ValidateTriggerBlock( + helper, + barAnalyser, + triggerBlock, + conditions, + validations, + barIndex, + loopback // + ); + + // + if (!result) + { + triggerBlock.Clean(); + } + } + + // + // Apply Filtering ... + if (result) + { + // + result = FilterTriggerBlock( + helper, + barAnalyser, + triggerBlock, + conditions, + filters, + barIndex, + loopback // + ); + + // + if (!result) + { + triggerBlock.Clean(); + } + } + + // + // Summarizing Result ... + result = + result && + triggerBlock.IsValid(); + + // + // Preparing Signal ... + if (result) + { + // + } + + // + // Cleanup Resources ... + + // + iBar.Clean(); + zBar.Clean(); + cBar.Clean(); + + // + if (!result) + { + triggerBlock.Clean(); + } + + // + return result; +} + +/** + * Validate a Trigger Block ... + * + * @param helper: XCX121XCatbHelper instance pointer ... + * @param barAnalyser: XCBarAnalyser instance pointer ... + * @param triggerBlock: XTriggerBlock Refrence, Trigger Block ... + * @param conditions: X121XCatbConditions Refrence, Trigger Block Conditions ... + * @param validations: XTriggerBlockValidationRules Refrence, Provides Trigger Block Validation Rules ... + * @param barIndex: int, Bar Index ... + * @param loopback: int, Loopback for Conditions reading ... + * + * @return ( bool ) + */ +bool ValidateTriggerBlock( + XCX121XCatbHelper *helper, + XCBarAnalyser *barAnalyser, + XTriggerBlock &triggerBlock, + X121XCatbConditions &conditions, + XTriggerBlockValidationRules &validations, + int barIndex = 0, + int loopback = 10 // +) +{ + // + bool result = false; + + // + // Checking Conditions ... + + // + // Normalize Args ... + conditions.Clean(); + barIndex = NormalizeInt(barIndex, 0); + loopback = NormalizeInt(loopback, 0); + + // + // Validate Args ... + result = + helper != NULL && + barAnalyser != NULL && + triggerBlock.IsValid(); + if (!result) + { + return result; + } + + // + // Reading Market Conditions ... + result = helper.GetConditions( + conditions, + barIndex, + loopback // + ); + if (!result) + { + // + conditions.Clean(); + + // + return result; + } + + // + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + int p3IDX = p2IDX + 1; + int p4IDX = p3IDX + 1; + + // + XOHCL iBar; + int count = 0; + int toIDX = -1; + int fromIDX = -1; + bool has = false; + bool isBullish = triggerBlock.IsBullish(); + bool isBearish = triggerBlock.IsBearish(); + double points = GetPoints(triggerBlock.ob.symbol); + ENUM_X_DIRECTION iDir = triggerBlock.GetDirection(); + + // + // Checking Conditions ... + + // + // Range Validation ... + + // + // Max Allowed OB Range ... + if (result && + validations.maxAllowedRange > 0) + { + // + double iRange = triggerBlock.ob.GetRange(); + result = iRange <= (validations.maxAllowedRange * points); + } + + // + // Min Allowed OB Range ... + if (result && + validations.minAllowedRange > 0) + { + // + double iRange = triggerBlock.ob.GetRange(); + result = iRange >= (validations.maxAllowedRange * points); + } + + // + // Has Swing ... + if (result && + validations.forceHasSwing) + { + // + bool isSwing = false; + toIDX = triggerBlock.ToIndex(); + fromIDX = triggerBlock.FromIndex(); + ENUM_X_DIRECTION swingDir = X_DIRECTION_NONE; + for (int i = toIDX; i <= fromIDX; i++) + { + // + // Initialize iBar ... + has = iBar.Init( + conditions.symbol, + conditions.period, + i // + ); + isSwing = + has && + barAnalyser + .IsSimpleSwing( + iBar, + swingDir // + ); + if (isSwing && + swingDir == iDir) + { + break; + } + + // + iBar.Clean(); + } + + // + result = + isSwing && + iBar.IsValid() && + swingDir == iDir; + if (result) + { + // + // Initialize Swing Bar ... + result = triggerBlock + .swingBar + .Init( + iBar.symbol, + iBar.period, + iBar.Index() + 2 // + ); + } + + // + iBar.Clean(); + } + + // + // Force FVG Bar Types ... + if (result && + validations.forceFVGBarType) + { + // + toIDX = triggerBlock.fvg.ToIndex(); + fromIDX = triggerBlock.fvg.FromIndex(); + for (int i = toIDX; i < fromIDX; i++) + { + // + // Initialize iBar ... + result = iBar.Init( + conditions.symbol, + conditions.period, + i // + ); + result = + result && + iDir == iBar.GetDirection(); + + // + iBar.Clean(); + + // + if (!result) + { + break; + } + } + + // + iBar.Clean(); + } + + // + // Force OB Start By InDirectional Bars ... + if (result && + validations.forceOBBarType) + { + // + count = 0; + fromIDX = triggerBlock.fvg.FromIndex() + 1; + int sIDX = fromIDX; + has = true; + while (has) + { + // + // Initialize iBar .. + has = iBar.Init( + conditions.symbol, + conditions.period, + fromIDX // + ); + has = has && + iDir == Opposit(iBar.GetDirection()); + if (has) + { + count++; + } + + // + fromIDX++; + } + + // + int required = + validations.minRequiredOBBar > 0 + ? validations.minRequiredOBBar + : 1; + + // + result = count >= required; + + // + // Update Trigger Block Box based on OB Bar Types ... + if (result) + { + // + result = iBar.Init( + conditions.symbol, + conditions.period, + sIDX // + ); + if (result) + { + // + datetime iFrom = GetBarTime( + conditions.symbol, + conditions.period, + sIDX + count // + ); + double iLL = iBar.FindLowest(count, MODE_LOW); + double iHH = iBar.FindHighest(count, MODE_HIGH); + + // + triggerBlock.trigger.from = iFrom; + triggerBlock.trigger.upper = MathMax(iHH, triggerBlock.trigger.upper); + triggerBlock.trigger.lower = MathMin(iLL, triggerBlock.trigger.lower); + } + } + + // + iBar.Clean(); + } + + // + // Force Fair Value Gap to Following Sequence ... + if (result && + validations.validateGapSequence) + { + // + XOHCL iPBar; + toIDX = triggerBlock.fvg.ToIndex(); + fromIDX = triggerBlock.fvg.FromIndex() - 1; + for (int i = toIDX; i < fromIDX; i++) + { + // + result = iBar.Init( + conditions.symbol, + conditions.period, + i // + ); + result = + result && + iBar.GetPreviousBar(iPBar); + result = + result && + (isBullish + ? iBar.low > iPBar.low + : iBar.high < iPBar.high); + if (!result) + { + break; + } + + // + iBar.Clean(); + iPBar.Clean(); + } + + // + iBar.Clean(); + iPBar.Clean(); + } + + // + // Validate OB Edge Breakeout Using Gaps End Bar ... + if (result && + validations.validateBlockEdgeBreakout) + { + // + // Initialize Gap End Bar ... + toIDX = triggerBlock.fvg.ToIndex(); + result = iBar.Init( + conditions.symbol, + conditions.period, + toIDX // + ); + + // + result = + result && + (isBullish + ? iBar.open < triggerBlock.ob.upper && + iBar.close > triggerBlock.ob.upper + : iBar.open > triggerBlock.ob.lower && + iBar.close < triggerBlock.ob.lower); + + // + // Here we Can Apply Edge Breakout Using Fibo ... + + // + iBar.Clean(); + } + + // + // Force Block to Has Liquidity ... + if (result && + validations.liquidityLoopback > 0 && + (validations.forceHasFLiquidity || + validations.forceHasRLiquidity)) + { + // + toIDX = triggerBlock.ToIndex(); + fromIDX = triggerBlock.FromIndex(); + ENUM_X_DIRECTION iLiqDir = X_DIRECTION_NONE; + for (int i = toIDX; i < fromIDX + validations.liquidityLoopback; i++) + { + // + // Initialize iBar ... + has = iBar.Init( + conditions.symbol, + conditions.period, + i // + ); + has = + has && + barAnalyser + .IsRejected( + iBar, + iLiqDir, + false, // Force Bar Type ... + true // Force Fibo Pressure ... + ); + + // + bool isFLiq = + has && + iLiqDir == iDir; + if (isFLiq && + validations.forceHasFLiquidity && + !triggerBlock.fLiquidity.IsValid()) + { + // + FillLiquidity( + iBar, + iLiqDir, + triggerBlock.fLiquidity, + triggerBlock.trigger.to // + ); + } + + // + bool isRLiq = + has && + iLiqDir == Opposit(iDir); + if (isRLiq && + validations.forceHasRLiquidity && + !triggerBlock.rLiquidity.IsValid()) + { + // + FillLiquidity( + iBar, + iLiqDir, + triggerBlock.rLiquidity, + triggerBlock.trigger.to // + ); + } + + // + // Here We Can Apply Liquidity Validations ... + ValidateTriggerBlockLiquidities( + helper, + barAnalyser, + triggerBlock, + conditions, + validations // + ); + + // + // Check Liquidities ... + has = (!validations.forceHasFLiquidity + ? true + : triggerBlock.fLiquidity.IsValid()) && + (!validations.forceHasRLiquidity + ? true + : triggerBlock.rLiquidity.IsValid()); + + // + iBar.Clean(); + + // + if (has) + { + break; + } + } + + // + // Check Result ... + result = (!validations.forceHasFLiquidity + ? true + : triggerBlock.fLiquidity.IsValid()) && + (!validations.forceHasRLiquidity + ? true + : triggerBlock.rLiquidity.IsValid()); + + // + iBar.Clean(); + } + + // + // Validating Block Length Based on Direction ... + if (result && + validations.minAllowedBlockLength) + { + // + count = 0; + fromIDX = triggerBlock.FromIndex(); + int sIDX = fromIDX; + has = true; + while (has) + { + // + // Initialize iBar ... + has = iBar.Init( + conditions.symbol, + conditions.period, + sIDX // + ); + + // + has = + has && + (isBullish + ? iBar.low > triggerBlock.trigger.lower + : iBar.high < triggerBlock.trigger.upper); + + // + if (!has) + { + break; + } + + // + sIDX++; + count++; + iBar.Clean(); + } + + // + result = + iBar.IsValid() && + count >= validations.minAllowedBlockLength; + if (result) + { + // + // Update Trigger Block ... + bool usaMinAllowedForBlockLength = false; + if (usaMinAllowedForBlockLength) + { + fromIDX = fromIDX + validations.minAllowedBlockLength; + } + else + { + fromIDX = sIDX - 1; + } + + // + triggerBlock.trigger.from = GetBarTime( + conditions.symbol, + conditions.period, + fromIDX // + ); + } + + // + iBar.Clean(); + } + + // + if (!result) + { + triggerBlock.Clean(); + } + + // + // Summarize result ... + result = triggerBlock.IsValid(); + + // + // Cleanup Resources ... + + // + iBar.Clean(); + + // + if (!result) + { + // + conditions.Clean(); + triggerBlock.Clean(); + } + + // + return result; +} + +/** + * Filter a Trigger Block ... + * + * @param helper: XCX121XCatbHelper instance pointer ... + * @param barAnalyser: XCBarAnalyser instance pointer ... + * @param triggerBlock: XTriggerBlock Refrence, Trigger Block ... + * @param conditions: X121XCatbConditions Refrence, Trigger Block Conditions ... + * @param filters: XTriggerBlockFilters Refrence, Provides Trigger Block Filters ... + * @param barIndex: int, Bar Index ... + * @param loopback: int, Loopback for Conditions reading ... + * + * @return ( bool ) + */ +bool FilterTriggerBlock( + XCX121XCatbHelper *helper, + XCBarAnalyser *barAnalyser, + XTriggerBlock &triggerBlock, + X121XCatbConditions &conditions, + XTriggerBlockFilters &filters, + int barIndex = 0, + int loopback = 10 // +) +{ + // + bool result = false; + + // + // Checking Conditions ... + + // + // Normalize Args ... + conditions.Clean(); + barIndex = NormalizeInt(barIndex, 0); + loopback = NormalizeInt(loopback, 0); + + // + // Validate Args ... + result = + helper != NULL && + barAnalyser != NULL && + triggerBlock.IsValid(); + if (!result) + { + return result; + } + + // + // Reading Market Conditions ... + result = helper.GetConditions( + conditions, + barIndex, + loopback // + ); + if (!result) + { + // + conditions.Clean(); + + // + return result; + } + + // + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + int p3IDX = p2IDX + 1; + int p4IDX = p3IDX + 1; + + // + XOHCL iBar; + int toIDX = -1; + int fromIDX = -1; + bool has = false; + bool isBullish = triggerBlock.IsBullish(); + bool isBearish = triggerBlock.IsBearish(); + double points = GetPoints(triggerBlock.ob.symbol); + ENUM_X_DIRECTION iDir = triggerBlock.GetDirection(); + + // + // Checking Conditions ... + + // + // Filter Based KI ... + if (result && + filters.filterBasedOnKI) + { + // + int count = 0; + toIDX = triggerBlock.ob.ToIndex(); + fromIDX = triggerBlock.ob.FromIndex(); + double lKI = conditions.kiBuffer[zIDX]; + for (int i = toIDX; i < fromIDX; i++) + { + // + double iKI = helper.GetKI(i); + if (iKI == lKI) + { + count++; + } + else + { + break; + } + } + + // + result = count >= 3; + } + + // + // Filter Based On PV ... + if (result && + filters.filterBasedOnPV) + { + // + // For PV Filtering ... + + // + // Detect BOS ... + + // + // When Loopback for BOS has Specified Value ... + // we Lookup for BOS on Specific Period ... + if (filters.bosLoopback > 0) + { + // + has = true; + int fBOSIDX = -1; + int rBOSIDX = -1; + bool isBOS = false; + bool isFBOS = false; + bool isRBOS = false; + bool isPeakOverLast = false; + bool isValeUnderLast = false; + toIDX = triggerBlock.ob.ToIndex(); + fromIDX = triggerBlock.ob.FromIndex(); + int sIDX = fromIDX; + while (has) + { + // + double iPeak = helper.GetPeak(sIDX); + double iPPeak = helper.GetPeak(sIDX + 1); + + // + double iVale = helper.GetVale(sIDX); + double iPVale = helper.GetVale(sIDX + 1); + + // + isPeakOverLast = + iPeak > 0 && + iPeak > iPPeak; + + // + isValeUnderLast = + iVale > 0 && + iVale < iPVale; + + // + isFBOS = + isBullish + ? isPeakOverLast + : isValeUnderLast; + if (isFBOS) + { + fBOSIDX = sIDX; + } + + // + isRBOS = + isBullish + ? isValeUnderLast + : isPeakOverLast; + if (isRBOS) + { + rBOSIDX = sIDX; + } + + // + isBOS = + (isBullish && + isPeakOverLast) || + (isBearish && + isValeUnderLast); + if (isBOS) + { + break; + } + + // + sIDX++; + has = !isBOS && + sIDX < fromIDX + filters.bosLoopback; + } + + // + isFBOS = IsValidIndex(fBOSIDX); + isRBOS = IsValidIndex(rBOSIDX); + + // + result = isBOS && + isFBOS && + !isRBOS; + } + + // + // When Loopback for BOS has not Specified Value ... + // we Lookup for BOS on GAP End Bar ... + if (filters.bosLoopback <= 0) + { + // + toIDX = triggerBlock.ToIndex(); + + // + // Initialize iBar ... + result = iBar.Init( + conditions.symbol, + conditions.period, + toIDX // + ); + result = + result && + (isBullish ? iBar.high > helper.GetPeak(toIDX + 1) + : iBar.low < helper.GetVale(toIDX + 1)); + } + } + + // + // Filter Based on SAR ... + if (result && + filters.filterBasedOnSar) + { + // + toIDX = triggerBlock.ToIndex(); + fromIDX = triggerBlock.FromIndex(); + + // + double iSarState = helper.GetSarState(toIDX); + double iPSarState = helper.GetSarState(toIDX + 1); + + // + double iFSarState = helper.GetSarState(fromIDX); + double iPFSarState = helper.GetSarState(fromIDX + 1); + + // + bool isSarBullish = + iSarState > 0; + + // + bool isSarBearish = + iSarState < 0; + + // + bool isFSarBullish = + iFSarState > 0; + + // + bool isFSarBearish = + iFSarState < 0; + + // + bool isSarSwitchedToBullish = + iSarState > 0 && + iPSarState <= 0; + + // + bool isSarSwitchedToBearish = + iSarState < 0 && + iPSarState >= 0; + + // + bool isFSarSwitchedToBullish = + iFSarState > 0 && + iPFSarState <= 0; + + // + bool isFSarSwitchedToBearish = + iFSarState < 0 && + iPFSarState >= 0; + + // + // Check SAR Direction ... + + // + if (result && + !filters.forceSarSwitched) + { + // + result = isBullish + ? isSarBullish + : isSarBearish; + } + + // + if (result && + filters.forceSarSwitched) + { + // + result = isBullish + ? isSarSwitchedToBullish + : isSarSwitchedToBearish; + } + + // + if (result && + filters.forceSarOnBothSide) + { + // + if (result && + !filters.forceSarSwitched) + { + // + result = isBullish + ? isFSarBullish + : isFSarBearish; + } + + // + if (result && + filters.forceSarSwitched) + { + // + result = isBullish + ? isFSarSwitchedToBullish + : isFSarSwitchedToBearish; + } + } + + // + // Check Sar Has Reversal Direction inside Trigger Block ... + if (result && + filters.forceSarHasReversalSide) + { + // + toIDX = triggerBlock.ToIndex(); + fromIDX = triggerBlock.FromIndex(); + for (int i = toIDX; i < fromIDX; i++) + { + // + double iSarState = helper.GetSarState(i); + + // + has = + isBullish + ? iSarState > 0 + : iSarState < 0; + if (has) + { + break; + } + } + + // + result = has; + } + + // + // Force Sar Breakouts ... + // in this Senario Sar must in following Direction and + // there is not any Switches ... + // but must breakout Bar the last in Reversal Direction + // of Sar ... + if (result && + filters.forceSarHasBreakout) + { + // + bool isSarBullishStart = + // + ( + // + // Current SAR is Directional ... + conditions.isSarBullish && + // + // Previous InDirectional Sar Exists ... + helper.lastSarBearish.IsValid() && + // + // Current Close is Over previous Sar ... + conditions.bars[cIDX].close > helper.lastSarBearish.after && + // + // Before Close is not Over previous Sar ... + conditions.bars[pIDX].close <= helper.lastSarBearish.after + // + ) + // + ; + + // + bool isSarBearishStart = + // + ( + // + // Current SAR is Directional ... + conditions.isSarBearish && + // + // Previous InDirectional Sar Exists ... + helper.lastSarBullish.IsValid() && + // + // Current Close is Under previous ... + conditions.bars[cIDX].close < helper.lastSarBullish.after && + // + // Before Close is not Under previous ... + conditions.bars[pIDX].close >= helper.lastSarBullish.after + // + ) + // + ; + + // + result = + isBullish + ? isSarBullishStart + : isSarBearishStart; + } + } + + // + // Filter Based On RSI ... + if (result && + filters.filterBasedOnRSI) + { + // + // Here We Can Apply RSI Filters ... + // Since RSI Filters must be Check on FVG Bars ... + // we Have to Loop back Based on FVG Bars to Detect Conditions ... + double rsiTrend = (conditions.rsiOBLevel + conditions.rsiOSLevel) / 2; + + // + toIDX = triggerBlock.fvg.ToIndex(); + fromIDX = triggerBlock.fvg.FromIndex(); + + // + // Filter Using RSI Trending ... + if (result && + filters.forceHasRSITrending) + { + // + for (int i = toIDX; i < fromIDX; i++) + { + // + double iRSI = helper.GetRSI(i); + double iPRSI = helper.GetRSI(i + 1); + + // + has = + (isBullish + ? (iRSI > rsiTrend && + iRSI > iPRSI) + : (iRSI < rsiTrend && + iRSI < iPRSI)); + if (has) + { + break; + } + } + + // + result = has; + } + + // + // Filter Using RSI V Pattern ... + if (result && + filters.forceHasRSIVPattern) + { + // + for (int i = toIDX; i < fromIDX; i++) + { + // + double iRSI = helper.GetRSI(i); + double iPRSI = helper.GetRSI(i + 1); + double iP2RSI = helper.GetRSI(i + 2); + + // + bool isRSIVBullish = + iRSI > iPRSI && + iP2RSI > iPRSI; + + // + bool isRSIVBearish = + iRSI < iPRSI && + iP2RSI < iPRSI; + + // + has = + (isBullish + ? isRSIVBullish + : isRSIVBearish); + if (has) + { + break; + } + } + + // + result = has; + } + + // + // Filter Using RSI Crossing on OB/OS Levels ... + if (result && + filters.forceHasRSICrossing) + { + // + for (int i = toIDX; i < fromIDX; i++) + { + // + double iRSI = helper.GetRSI(i); + double iPRSI = helper.GetRSI(i + 1); + + // + bool isRSICrossedOverOS = + iRSI > conditions.rsiOSLevel && + iPRSI <= conditions.rsiOSLevel; + + // + bool isRSICrossedUnderOB = + iRSI < conditions.rsiOBLevel && + iPRSI >= conditions.rsiOBLevel; + + // + has = + (isBullish + ? isRSICrossedOverOS + : isRSICrossedUnderOB); + if (has) + { + break; + } + } + + // + result = has; + } + } + + // + // Filter Based On ADX ... + if (result && + filters.filterBasedOnADX) + { + // + // Here We Can Apply ADX Filters ... + // Since ADX Filters must be Check on FVG Bars ... + // we Have to Loop back Based on FVG Bars to Detect Conditions ... + + // + toIDX = triggerBlock.fvg.ToIndex(); + fromIDX = triggerBlock.fvg.FromIndex(); + + // + // Filter Using ADX Trending ... + if (result && + filters.forceHasADXTrending) + { + // + for (int i = toIDX; i < fromIDX; i++) + { + // + double iADX = helper.GetADX(i); + double iPADX = helper.GetADX(i + 1); + + // + has = iADX > conditions.adxThreshold && + iADX > iPADX; + if (has) + { + break; + } + } + + // + result = has; + } + + // + // Filter Using ADX Crossing on +DI/-DI ... + if (result && + filters.forceHasADXCrossing) + { + // + for (int i = toIDX; i < fromIDX; i++) + { + // + double iDIPlus = helper.GetADXP(i); + double iPDIPlus = helper.GetADXP(i + 1); + + // + double iDIMinus = helper.GetADXN(i); + double iPDIMinus = helper.GetADXN(i + 1); + + // + bool isADXPlusCrossedOverMinus = + iDIPlus > iDIMinus && + iPDIPlus <= iDIMinus; + + // + bool isADXMinusCrossedOverPlus = + iDIMinus > iDIPlus && + iPDIMinus <= iDIPlus; + + // + has = + isBullish + ? isADXPlusCrossedOverMinus + : isADXMinusCrossedOverPlus; + if (has) + { + break; + } + } + + // + result = has; + } + } + + // + // Filter Based On ATR Band ... + if (result && + filters.filterBasedOnATR) + { + // + // Here We Can Apply ATR Filters ... + // Since ATR Filters must be Check on OB Bars ... + // we Have to Loop back Based on OB Bars to Detect Conditions ... + + // + toIDX = triggerBlock.ob.ToIndex(); + fromIDX = triggerBlock.ob.FromIndex(); + + // + // Filter Using ATR Trending ... + if (result && + filters.forceHasATRTrending) + { + // + for (int i = toIDX; i < fromIDX; i++) + { + // + double iATRUpper = helper.GetATRUpper(i); + double iPATRUpper = helper.GetATRUpper(i + 1); + + // + double iATRLower = helper.GetATRLower(i); + double iPATRLower = helper.GetATRLower(i + 1); + + // + bool isATRUp = + iATRLower > iPATRLower; + + // + bool isATRDown = + iATRUpper < iPATRUpper; + + // + has = isBullish + ? isATRUp + : isATRDown; + if (has) + { + break; + } + } + + // + result = has; + } + + // + // Filter Using ATR Breakout ... + if (result && + filters.forceHasATRBreakout) + { + // + for (int i = toIDX; i < fromIDX; i++) + { + // + double iATRUpper = helper.GetATRUpper(i); + double iATRLower = helper.GetATRLower(i); + + // + has = isBullish + ? triggerBlock.ob.lower < iATRLower + : triggerBlock.ob.upper > iATRUpper; + if (has) + { + break; + } + } + + // + result = has; + } + } + + // + // Filter Based On Trend ... + if (result && + filters.filterBasedOnTrend) + { + // + toIDX = triggerBlock.fvg.ToIndex(); + fromIDX = triggerBlock.fvg.FromIndex(); + + // + // Filter Using Trend Direction ... + if (result && + filters.forceHasTrendDir) + { + // + result = + result && + isBullish + ? conditions.isTrendBullish + : conditions.isTrendBearish; + } + + // + // Filter Using Trend Direction On Both Side ... + if (result && + filters.forceHasTrendDirOnBothSide) + { + // + // Side To ... + result = + result && + isBullish + ? conditions.isTrendBullish + : conditions.isTrendBearish; + + // + // Side From ... + int sFIDX = triggerBlock.ob.FromIndex(); + double sFTrendState = helper.GetTrendState(sFIDX); + result = + result && + isBullish + ? sFTrendState > 0 + : sFTrendState < 0; + } + + // + // Filter Using Trend Change ... + if (result && + filters.forceHasTrendChange) + { + // + for (int i = toIDX; i < fromIDX; i++) + { + // + double iTrendState = helper.GetTrendState(i); + double iPTrendState = helper.GetTrendState(i + 1); + + // + bool isTrendSwitchedToBullish = + iTrendState > 0 && + iPTrendState <= 0; + + // + bool isTrendSwitchedToBearish = + iTrendState < 0 && + iPTrendState >= 0; + + // + has = + isBullish + ? isTrendSwitchedToBullish + : isTrendSwitchedToBearish; + if (has) + { + break; + } + } + + // + result = has; + } + + // + // Filter Using Trend Trending ... + if (result && + filters.forceHasTrendTrending) + { + // + result = + result && + (isBullish + ? conditions.trendBuffer[cIDX] > conditions.trendBuffer[pIDX] + : conditions.trendBuffer[cIDX] < conditions.trendBuffer[pIDX]); + } + + // + // Filter Using Trend Rejection ... + if (result && + filters.forceHasTrendRejection) + { + // + toIDX = triggerBlock.ob.ToIndex(); + fromIDX = triggerBlock.ob.FromIndex(); + for (int i = toIDX; i < fromIDX; i++) + { + // + // Initialize iBar ... + has = iBar.Init( + conditions.symbol, + conditions.period, + i // + ); + + // + // Read Trend Value ... + double iTrend = helper.GetTrend(i); + + // + bool isTrendBullishRejected = + has && + iBar.low < iTrend && + iBar.GetDown() > iTrend; + + // + bool isTrendBearishRejected = + has && + iBar.high > iTrend && + iBar.GetUp() < iTrend; + + // + has = + has && + (isBullish + ? isTrendBullishRejected + : isTrendBearishRejected); + if (has) + { + break; + } + } + + // + result = has; + } + + // + // Filter Using Trend Inside ... + if (result && + filters.forceHasTrendLineInside) + { + // + result = + result && + conditions.trendBuffer[cIDX] > triggerBlock.ob.lower && + conditions.trendBuffer[cIDX] < triggerBlock.ob.upper; + } + + // + // Filter Using Trend Place ... + if (result && + filters.forceHasTrendPlace) + { + // + toIDX = triggerBlock.ob.ToIndex(); + fromIDX = triggerBlock.ob.FromIndex(); + double mult = + isBullish + ? 1 + : -1; + double edge = isBullish + ? triggerBlock.ob.lower + : triggerBlock.ob.upper; + double factor = edge + (mult * (triggerBlock.ob.GetRange() / 4)); + for (int i = toIDX; i < fromIDX; i++) + { + // + double iTrend = helper.GetTrend(i); + + // + has = + isBullish + ? factor >= iTrend + : factor <= iTrend; + if (has) + { + break; + } + } + + // + result = has; + } + } + + // + // Filter Using Delta ... + if (result && + filters.filterBasedOnDelta) + { + // + toIDX = triggerBlock.ob.ToIndex(); + fromIDX = triggerBlock.ob.FromIndex(); + + // + for (int i = toIDX; i < fromIDX; i++) + { + // + double iDelta = helper.GetDelta(i); + double iPDelta = helper.GetDelta(i + 1); + + // + double iDeltaSignal = helper.GetDeltaSignal(i); + double iPDeltaSignal = helper.GetDeltaSignal(i + 1); + + // + bool isDeltaUp = + iDelta > iPDelta; + + // + bool isDeltaDown = + iDelta < iPDelta; + + // + bool isDeltaSignalUp = + iDeltaSignal > iPDeltaSignal; + + // + bool isDeltaSignalDown = + iDeltaSignal < iPDeltaSignal; + + // + bool isDeltaCrossedOverSignal = + iDelta > iDeltaSignal && + iPDelta <= iPDeltaSignal; + + // + bool isDeltaCrossedUnderSignal = + iDelta < iDeltaSignal && + iPDelta >= iPDeltaSignal; + + // + has = + isBullish + ? (isDeltaUp && + isDeltaSignalUp && + isDeltaCrossedOverSignal) + : (isDeltaDown && + isDeltaSignalDown && + isDeltaCrossedUnderSignal); + if (has) + { + break; + } + } + + // + result = has; + } + + // + // Filter Using Volume ... + if (result && + filters.filterBasedOnVolume) + { + // + toIDX = triggerBlock.ob.ToIndex(); + fromIDX = triggerBlock.ob.FromIndex(); + + // + for (int i = toIDX; i < fromIDX; i++) + { + // + double iBullVolume = helper.GetBullishVolume(i); + double iPBullVolume = helper.GetBullishVolume(i + 1); + + // + double iBullVolumeSignal = helper.GetBullishVolumeSignal(i); + double iPBullVolumeSignal = helper.GetBullishVolumeSignal(i + 1); + + // + double iBearVolume = helper.GetBearishVolume(i); + double iPBearVolume = helper.GetBearishVolume(i + 1); + + // + double iBearVolumeSignal = helper.GetBearishVolumeSignal(i); + double iPBearVolumeSignal = helper.GetBearishVolumeSignal(i + 1); + + // + bool isBullVolumeUp = + iBullVolume > iPBullVolume; + + // + bool isBullVolumeSignalUp = + iBullVolumeSignal > iPBullVolumeSignal; + + // + bool isBearVolumeUp = + iBearVolume > iPBearVolume; + + // + bool isBearVolumeSignalUp = + iBearVolumeSignal > iPBearVolumeSignal; + + // + bool isVolumeSwitchedToBullish = + iBullVolumeSignal > iBearVolumeSignal && + iPBullVolumeSignal <= iPBearVolumeSignal; + + // + bool isVolumeSwitchedToBearish = + iBearVolumeSignal > iBullVolumeSignal && + iPBearVolumeSignal <= iPBullVolumeSignal; + + // + has = + isBullish + ? (isBullVolumeUp && + isBullVolumeSignalUp && + isVolumeSwitchedToBullish) + : (isBearVolumeUp && + isBearVolumeSignalUp && + isVolumeSwitchedToBearish); + if (has) + { + break; + } + } + + // + result = has; + } + + // + // Filter Using Signal Bar ... + if (result && + filters.filterBasedOnSignalBar) + { + // + toIDX = triggerBlock.ob.ToIndex(); + fromIDX = triggerBlock.ob.FromIndex(); + + // + double iSOpen = helper.GetSBarOpen(toIDX); + double iPSOpen = helper.GetSBarOpen(toIDX + 1); + + // + double iSClose = helper.GetSBarClose(toIDX); + double iPSClose = helper.GetSBarClose(toIDX + 1); + + // + double iSPow = MathAbs(iSOpen - iSClose); + double iPSPow = MathAbs(iPSOpen - iPSClose); + + // + result = + result && + iSPow > iPSPow && + (isBullish + ? iSClose > iSOpen + : iSClose < iSOpen); + + // + // Now Looking for Dir Change ... + if (result) + { + // + for (int i = toIDX; i < fromIDX; i++) + { + // + iSOpen = helper.GetSBarOpen(toIDX); + iPSOpen = helper.GetSBarOpen(toIDX + 1); + + // + iSClose = helper.GetSBarClose(toIDX); + iPSClose = helper.GetSBarClose(toIDX + 1); + + // + bool isSBullish = + iSClose > iSOpen; + + // + bool isPSBullish = + iPSClose > iPSOpen; + + // + bool isSBearish = + iSClose < iSOpen; + + // + bool isPSBearish = + iPSClose < iPSOpen; + + // + bool isSSwitchedToBullish = + isSBullish && + !isPSBullish; + + // + bool isSSwitchedToBearish = + isSBearish && + !isPSBearish; + + // + has = + isBullish + ? isSSwitchedToBullish + : isSSwitchedToBearish; + if (has) + { + break; + } + } + + // + result = has; + } + } + + // + // Filter Using Signal Bar ... + if (result && + filters.filterBasedOnHKSignalBar) + { + // + toIDX = triggerBlock.ob.ToIndex(); + fromIDX = triggerBlock.ob.FromIndex(); + + // + double iSOpen = helper.GetHKSBarOpen(toIDX); + double iPSOpen = helper.GetHKSBarOpen(toIDX + 1); + + // + double iSClose = helper.GetHKSBarClose(toIDX); + double iPSClose = helper.GetHKSBarClose(toIDX + 1); + + // + double iSPow = MathAbs(iSOpen - iSClose); + double iPSPow = MathAbs(iPSOpen - iPSClose); + + // + result = + result && + iSPow > iPSPow && + (isBullish + ? iSClose > iSOpen + : iSClose < iSOpen); + + // + // Now Looking for Dir Change ... + if (result) + { + // + for (int i = toIDX; i < fromIDX; i++) + { + // + iSOpen = helper.GetHKSBarOpen(toIDX); + iPSOpen = helper.GetHKSBarOpen(toIDX + 1); + + // + iSClose = helper.GetHKSBarClose(toIDX); + iPSClose = helper.GetHKSBarClose(toIDX + 1); + + // + bool isSBullish = + iSClose > iSOpen; + + // + bool isPSBullish = + iPSClose > iPSOpen; + + // + bool isSBearish = + iSClose < iSOpen; + + // + bool isPSBearish = + iPSClose < iPSOpen; + + // + bool isSSwitchedToBullish = + isSBullish && + !isPSBullish; + + // + bool isSSwitchedToBearish = + isSBearish && + !isPSBearish; + + // + has = + isBullish + ? isSSwitchedToBullish + : isSSwitchedToBearish; + if (has) + { + break; + } + } + + // + result = has; + } + } + + // + if (!result) + { + triggerBlock.Clean(); + } + + // + // Summarize result ... + result = triggerBlock.IsValid(); + + // + // Cleanup Resources ... + + // + iBar.Clean(); + + // + if (!result) + { + // + conditions.Clean(); + triggerBlock.Clean(); + } + + // + return result; +} + +// +void ValidateTriggerBlockLiquidities( + XCX121XCatbHelper *helper, + XCBarAnalyser *barAnalyser, + XTriggerBlock &triggerBlock, + X121XCatbConditions &conditions, + XTriggerBlockValidationRules &validations // +) +{ + // + bool has = false; + + // + has = + helper != NULL && + barAnalyser != NULL && + triggerBlock.IsValid() && + (triggerBlock.fLiquidity.IsValid() || + triggerBlock.rLiquidity.IsValid()); + if (!has) + { + return; + } + + // + bool hasFLiq = triggerBlock.fLiquidity.IsValid(); + bool hasRLiq = triggerBlock.rLiquidity.IsValid(); + + // + // TODO: Implement Liquidity Validation ... +} + +// +// Draw Specific Trigger Block ... +bool DrawTriggerBlock( + XTriggerBlock &trigger, + XCPOIDrawer *drawer, + CArrayObj &objects, + datetime to = NULL, + // + bool _drawSignals = false, + int rrZoneLength = 10, + // Styles ... + // + // Trigger Block ... + int tbWidth = 1, // Trigger Block Width + color tbBullishColor = clrAqua, // Trigger Block Bullish Color + color tbBearishColor = clrMagenta, // Trigger Block Bearish Color + ENUM_LINE_STYLE tbStyle = STYLE_DASHDOTDOT, // Trigger Block Style + // + // OB ... + int obWidth = 1, // OB Width + color obBullishColor = clrLime, // OB Bullish Color + color obBearishColor = clrRed, // OB Bearish Color + ENUM_LINE_STYLE obStyle = STYLE_DOT, // OB Style + // + // FVG ... + int fvgWidth = 2, // FVG Width + color fvgBullishColor = clrLime, // FVG Bullish Color + color fvgBearishColor = clrRed, // FVG Bearish Color + ENUM_LINE_STYLE fvgStyle = STYLE_SOLID // FVG Style +) +{ + // + bool result = false; + + // + // Validate Args ... + result = trigger.IsValid() && + drawer != NULL; + if (!result) + { + return result; + } + + // + XTriggerBlock _trigger = trigger; + + // + // Update To ... + bool canUpdateTo = IsValid(to); + if (canUpdateTo) + { + // + _trigger.trigger.to = to; + _trigger.rLiquidity.to = to; + _trigger.fLiquidity.to = to; + } + + // + bool isBullish = _trigger.IsBullish(); + + // + // Draw OB ... + if (_trigger.ob.IsValid()) + { + // + XCBoxObject *iOBObj; + result = drawer.DrawBox( + _trigger.ob, + iOBObj // + ); + if (result) + { + // + // Style Object ... + + // + color iClr = + isBullish + ? obBullishColor + : obBearishColor; + + // + iOBObj.BoxColor(iClr); + iOBObj.BoxWidth(obWidth); + iOBObj.BoxStyle(obStyle); + + // + // Store Object ... + objects.Add(iOBObj); + } + ZeroMemory(iOBObj); + + // + if (!result) + { + return result; + } + } + + // + // Draw FVG ... + if (_trigger.fvg.IsValid()) + { + // + XCBoxObject *iFVGObj; + result = drawer.DrawBox( + _trigger.fvg, + iFVGObj // + ); + if (result) + { + // + // Style Object ... + + // + color iClr = + isBullish + ? fvgBullishColor + : fvgBearishColor; + + // + iFVGObj.BoxColor(iClr); + iFVGObj.BoxWidth(fvgWidth); + iFVGObj.BoxStyle(fvgStyle); + + // + // Store Object ... + objects.Add(iFVGObj); + } + ZeroMemory(iFVGObj); + + // + if (!result) + { + return result; + } + } + + // + // Draw Trigger ... + if (_trigger.trigger.IsValid()) + { + // + XCBoxObject *iTriggerObj; + result = drawer.DrawBox( + _trigger.trigger, + iTriggerObj // + ); + if (result) + { + // + // Style Object ... + + // + color iClr = + isBullish + ? tbBullishColor + : tbBearishColor; + + // + iTriggerObj.BoxColor(iClr); + iTriggerObj.BoxWidth(tbWidth); + iTriggerObj.BoxStyle(tbStyle); + + // + // Store Object ... + objects.Add(iTriggerObj); + } + ZeroMemory(iTriggerObj); + + // + if (!result) + { + return result; + } + } + + // + // Draw Liquidities ... + + // + // Reversla Liquidity ... + if (_trigger.rLiquidity.IsValid()) + { + // + XCBoxObject *iLiqObj; + result = drawer.DrawBox( + _trigger.rLiquidity, + iLiqObj // + ); + if (result) + { + objects.Add(iLiqObj); + } + ZeroMemory(iLiqObj); + + // + if (!result) + { + return result; + } + } + + // + // Following Liquidity ... + if (_trigger.fLiquidity.IsValid()) + { + // + XCBoxObject *iLiqObj; + result = drawer.DrawBox( + _trigger.fLiquidity, + iLiqObj // + ); + if (result) + { + objects.Add(iLiqObj); + } + ZeroMemory(iLiqObj); + + // + if (!result) + { + return result; + } + } + + // + // Draw Swing Bar ... + if (_trigger.swingBar.IsValid()) + { + // + color swingColor = + _trigger.fvg.IsBullish() + ? clrAqua + : clrMagenta; + ENUM_X_PRICE swingPType = + _trigger.fvg.IsBullish() + ? X_PRICE_LOW + : X_PRICE_HIGH; + + // + XCBarArrowObject *swingObj; + result = drawer.CreateBarArrow( + _trigger.swingBar, + swingObj, + swingPType, + 159, + swingColor // + ); + if (result) + { + objects.Add(swingObj); + } + ZeroMemory(swingObj); + + // + if (!result) + { + return result; + } + } + + // + // Draw RR of Signal ... + if (_drawSignals && + _trigger.signal.IsValid() && + rrZoneLength > 0) + { + // + XCRRObject *iRRObj; + iRRObj = new XCRRObject(); + result = iRRObj.Create( + drawer.ChartIdentification(), + drawer.SubWindowIdentification(), + _trigger.signal, + rrZoneLength // + ); + if (result) + { + // + int iWidth = 2; + ENUM_LINE_STYLE iStyle = STYLE_SOLID; + + // + iRRObj.TPWidth(iWidth); + iRRObj.SLWidth(iWidth); + iRRObj.EntryWidth(iWidth); + iRRObj.TargetWidth(iWidth); + + // + iRRObj.TPStyle(iStyle); + iRRObj.SLStyle(iStyle); + iRRObj.EntryStyle(iStyle); + iRRObj.TargetStyle(iStyle); + + // + iRRObj.TPColor(clrLime); + iRRObj.SLColor(clrRed); + iRRObj.EntryColor(clrYellow); + iRRObj.TargetColor(clrLightBlue); + + // + objects.Add(iRRObj); + } + ZeroMemory(iRRObj); + + // + if (result) + { + return result; + } + } + + // + return result; +} diff --git a/BKPS/14040316/XCATBEA/Libraries/xcatbea.signaller.lib.mq5 b/BKPS/14040316/XCATBEA/Libraries/xcatbea.signaller.lib.mq5 new file mode 100644 index 0000000..6792e6b --- /dev/null +++ b/BKPS/14040316/XCATBEA/Libraries/xcatbea.signaller.lib.mq5 @@ -0,0 +1,1404 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Library +// --------------------------------------- +// Name: XCATBEASignallerLib +// Description: required Parsers for XCATBEA Signaller ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright `023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../../Helpers/x-saherelm.x121.xcatb.helper.mq5" +#include "../../Libraries/x-saherelm.common.lib.mq5" +#include "../../Libraries/x-saherelm.x-poi.lib.mq5" +#include "../../Libraries/x-saherelm.x-trade.lib.mq5" +#include "../Classes/xcatbea.x-poi.detector.class.mq5" +#include "../Classes/xcatbea.x-poi.drawer.class.mq5" +#include "../Libraries/xcatbea.lib.mq5" + +// +// Definitions ... + +// +struct XCATBEAStrategyConditions +{ + // + // Props ... + + // + string symbol; + ENUM_TIMEFRAMES period; + + // + // Setup Props ... + + // + double sl; + double tp; + double pivot; + double point; + double entry; + double reward; + string provider; + + // + XTarget targets[]; + + // + datetime time; + datetime setupTime; + datetime triggerTime; + + // + XBoxZone pivotZone; + ENUM_X_DIRECTION dir; + XTriggerBlock triggerBlock; + ENUM_X_POSITION_TYPES type; + X121XCatbConditions conditions; + + // + // Constructor ... + XCATBEAStrategyConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + sl = 0; + tp = 0; + pivot = 0; + point = 0; + entry = 0; + reward = 0; + + // + symbol = NULL; + period = NULL; + provider = NULL; + + // + time = NULL; + setupTime = NULL; + triggerTime = NULL; + + // + Clean(targets); + + // + pivotZone.Clean(); + conditions.Clean(); + triggerBlock.Clean(); + + // + dir = X_DIRECTION_NONE; + type = X_POSITION_TYPE_NONE; + + // + ZeroMemory(this); + } + + // + // Signalling ... + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = IsSpecifiedValid(symbol) && + IsSpecifiedValid(period) && + IsSpecifiedValid(time); + + // + return result; + } + + /** + * Check Conditions Has Valid Bullish Signal ... + * + * @return ( bool ) + */ + bool HasBullishSignal() + { + // + bool result = false; + + // + result = + (sl > 0 || + tp > 0) && + IsValid() && + HasDirection(dir); + if (!result) + { + return result; + } + + // + result = + IsBullish(dir); + + // + return result; + } + + /** + * Check Conditions Has Valid Bearish Signal ... + * + * @return ( bool ) + */ + bool HasBearishSignal() + { + // + bool result = false; + + // + result = + (sl > 0 || + tp > 0) && + IsValid() && + HasDirection(dir); + if (!result) + { + return result; + } + + // + result = + IsBearish(dir); + + // + return result; + } + + // + // Setting Up and Triggering Up ... + + /** + * Check Condition is Setting Up ... + * + * @param dir: ENUM_X_DIRECTION member, Setting Up Direction ... + * + * @return ( bool ) + */ + bool IsSetuped() + { + // + bool result = false; + + // + result = IsValid(setupTime) && + HasDirection(dir); + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Calculate Setup Age ... + * + * @return ( int ) + */ + int GetSetupAge() + { + // + int result = 0; + + // + if (!IsSetuped()) + { + return result; + } + + // + result = (int)(TimeCurrent() - setupTime) / PeriodSeconds(period); + + // + return result; + } + + /** + * Detect How we Can Trigger Signal ... + * + * @return ( bool ) + */ + bool CanTrigger() + { + // + bool result = false; + + // + result = + // + sl > 0 && + IsValid(symbol) && + IsValid(period) && + IsValid(triggerTime) && + type != X_POSITION_TYPE_ALL && + type != X_POSITION_TYPE_NONE + // + ; + + // + return result; + } + + // +}; + +/** + * Converts Strategy Conditions to Signal ... + */ +bool ToSignal( + XSignal &signal, + XCATBEAStrategyConditions &conditions // +) +{ + // + bool result = false; + + // + // Normalize Args ... + signal.Clean(); + + // + // Validate Args ... + result = + conditions.IsValid() && + conditions.IsSetuped() && + conditions.CanTrigger(); + if (!result) + { + return result; + } + + // + // Do Converting ... + signal.volume = 0.01; + signal.tp = conditions.tp; + signal.sl = conditions.sl; + signal.entry = conditions.entry; + signal.symbol = conditions.symbol; + signal.period = conditions.period; + signal.mode = X_ORDER_MODE_MARKET; + signal.time = conditions.triggerTime; + signal.provider = conditions.provider; + signal.type = conditions.type == + X_POSITION_TYPE_LONG + ? POSITION_TYPE_BUY + : POSITION_TYPE_SELL; + signal.conditions = conditions + .conditions + .GenerateSummary( + false, + true, + true, + false // Ignore False Conditions ... + ); + Copy( + conditions.targets, + signal.targets // + ); + + // + // Validate Result ... + result = signal.IsValid(); + + // + return result; +} + +/** + * Detect Signal Zone based on Market Conditions ... + * + * @param helper: XCX121XCatbHelper instance pointer ... + * @param barAnalyser: XCBarAnalyser instance pointer ... + * @param conditions: X121XCatbConditions instance reference, hold signalling Conditions ... + * @param signalZone: XBoxZone instance reference, hold Signal Zone ... + * @param barIndex: int, Bar Index ... + * @param loopback: int, Loopback for Market Conditions ... + * + * @return ( bool ) + */ +bool DetectSignalZone( + XCX121XCatbHelper *helper, + XCXCATBEAPOIDrawer *drawer, + XCXCATBEAPOIDetector *detector, + XCBarAnalyser *barAnalyser, + X121XCatbConditions &conditions, + XBoxZone &signalZone, + bool allowSignallingConditions1 = false, + bool allowSignallingConditions2 = false, + bool allowSignallingConditions3 = false, + bool allowSignallingConditions4 = false, + bool allowSignallingConditions5 = false, + bool allowSignallingConditions6 = false, + int barIndex = 0, + int loopback = 10 // +) +{ + // + bool result = false; + + // + // Normalize Args ... + signalZone.Clean(); + conditions.Clean(); + loopback = NormalizeInt(loopback, 0); + barIndex = NormalizeInt(barIndex, 0); + + // + // Validate Args ... + result = + helper != NULL && + detector != NULL && + barAnalyser != NULL; + if (!result) + { + return result; + } + + // + // Try to Recieve Conditions of Market ... + + // + result = helper.GetConditions( + conditions, + barIndex, + loopback // + ); + + // + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + int p3IDX = p2IDX + 1; + int p4IDX = p3IDX + 1; + + // + int idx = -1; + bool has = false; + bool isBullish = false; + bool isBearish = false; + double bullishScore = 0; + double bearishScore = 0; + + // + double iUpper = 0; + double iLower = 0; + string iType = NULL; + datetime iTo = NULL; + string iSymbol = NULL; + datetime iFrom = NULL; + ENUM_TIMEFRAMES iPeriod = NULL; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + + // + // Signalling ... + if (result) + { + // + iSymbol = conditions.symbol; + iPeriod = conditions.period; + + // + // Looking For Conditions ... + + // + // Reading Values ... + + // + // Readng Scores ... + conditions.GenerateScore( + bullishScore, + bearishScore // + ); + + // + // Prepared Conditions ... + + // + // SCORES ... + bool isScoreBullish = bullishScore > bearishScore; + bool isScoreBearish = bearishScore > bullishScore; + + // + // SAR ... + + // + bool isSarBullishStart = + // + ( + // + // Current SAR is Directional ... + conditions.isSarBullish && + // + // Previous InDirectional Sar Exists ... + helper.lastSarBearish.IsValid() && + // + // Current Close is Over previous Sar ... + conditions.bars[cIDX].close > helper.lastSarBearish.after && + // + // Before Close is not Over previous Sar ... + conditions.bars[pIDX].close <= helper.lastSarBearish.after + // + ) + // + ; + + // + bool isSarBearishStart = + // + ( + // + // Current SAR is Directional ... + conditions.isSarBearish && + // + // Previous InDirectional Sar Exists ... + helper.lastSarBullish.IsValid() && + // + // Current Close is Under previous ... + conditions.bars[cIDX].close < helper.lastSarBullish.after && + // + // Before Close is not Under previous ... + conditions.bars[pIDX].close >= helper.lastSarBullish.after + // + ) + // + ; + + // + // TREND ... + + // + bool isTrendBullishStart = + // + ( + // + // Current Trend is Directional ... + conditions.isTrendBullish && + // + // Previous InDirectiona; Trend Exists ... + helper.lastTrendBearish.IsValid() && + // + // Current Close is Over previous ... + conditions.bars[cIDX].close > helper.lastTrendBearish.after && + // + // Before close is not Over previous ... + conditions.bars[pIDX].close <= helper.lastTrendBearish.after + // + ) + // + ; + + // + bool isTrendBearishStart = + // + ( + // + // Current Trend is Directional ... + conditions.isTrendBearish && + // + // Previous InDirectiona; Trend Exists ... + helper.lastTrendBullish.IsValid() && + // + // Current Close is Under previous ... + conditions.bars[cIDX].close < helper.lastTrendBullish.after && + // + // Before close is not Under previous ... + conditions.bars[pIDX].close >= helper.lastTrendBullish.after + // + ) + // + ; + + // + // ADX ... + + // + bool isADXBullishStart = + // + ( + // + // ADX Value is Switched to Strong ... + conditions.adxBuffer[cIDX] > conditions.adxThreshold && + conditions.adxBuffer[pIDX] <= conditions.adxThreshold && + // + // ADX must Up ... + conditions.adxBuffer[cIDX] > conditions.adxBuffer[pIDX] && + // + // ADX +DI is Bigger than -DI ... + conditions.adxpBuffer[cIDX] > conditions.adxnBuffer[cIDX] && + // + // ADX +DI is Up ... + conditions.adxpBuffer[cIDX] > conditions.adxpBuffer[pIDX] + // + ) + // + ; + + // + bool isADXBearishStart = + // + ( + // + // ADX Value is Switched to Strong ... + conditions.adxBuffer[cIDX] > conditions.adxThreshold && + conditions.adxBuffer[pIDX] <= conditions.adxThreshold && + // + // ADX must Up ... + conditions.adxBuffer[cIDX] > conditions.adxBuffer[pIDX] && + // + // ADX -DI is Bigger than +DI ... + conditions.adxnBuffer[cIDX] > conditions.adxpBuffer[cIDX] && + // + // ADX -DI is Up ... + conditions.adxnBuffer[cIDX] > conditions.adxnBuffer[pIDX] + // + ) + // + ; + + // + // DELTA ... + + // + bool isDeltaBullishStart = + // + // Check State ... + ( + // + // Delta is Up ... + conditions.deltaBuffer[cIDX] > conditions.deltaBuffer[pIDX] && + // + // Delta Signal is Up ... + conditions.deltaSignalBuffer[cIDX] > conditions.deltaSignalBuffer[pIDX] && + // + // Delta Crossed Over Delta Signal ... + conditions.deltaBuffer[cIDX] > conditions.deltaSignalBuffer[cIDX] + // + ) + // + && + // + // Check Last InDirectional Exists ... + helper.lastDeltaBearish.IsValid() && + // + // Current Close is Over last ... + conditions.bars[cIDX].close > helper.lastDeltaBearish.after && + // + // Before Close is not Over last ... + conditions.bars[pIDX].close <= helper.lastDeltaBearish.after + // + ; + + // + bool isDeltaBearishStart = + // + // Check State ... + ( + // + // Delta is Down ... + conditions.deltaBuffer[cIDX] < conditions.deltaBuffer[pIDX] && + // + // Delta Signal is Down ... + conditions.deltaSignalBuffer[cIDX] < conditions.deltaSignalBuffer[pIDX] && + // + // Delta Crossed Under Delta Signal ... + conditions.deltaBuffer[cIDX] < conditions.deltaSignalBuffer[cIDX] + // + ) + // + && + // + // Check Last InDirectional Exists ... + helper.lastDeltaBullish.IsValid() && + // + // Current Close is Under last ... + conditions.bars[cIDX].close < helper.lastDeltaBullish.after && + // + // Before Close is not Under last ... + conditions.bars[pIDX].close >= helper.lastDeltaBullish.after + // + ; + + // + // VOLUME ... + + // + bool isVolumeBullishStart = + // + ( + // + // + // Volume is Up ... + conditions.bullishVolumeBuffer[1] > conditions.bullishVolumeBuffer[2] && + // + // Volume Signal is Up ... + conditions.bullishVolumeSignalBuffer[1] > conditions.bullishVolumeSignalBuffer[2] && + // + // Volume Signals Crossed Over ... + conditions.bullishVolumeSignalBuffer[1] > conditions.bearishVolumeSignalBuffer[1] + // + ) + // + && + // + // Check Last InDirectional Exists ... + helper.lastVolumeBearish.IsValid() && + // + // Current Close is Over last ... + conditions.bars[cIDX].close > helper.lastVolumeBearish.after && + // + // Before Close is not Over last ... + conditions.bars[pIDX].close <= helper.lastVolumeBearish.after + // + ; + + // + bool isVolumeBearishStart = + // + ( + // + // + // Volume is Up ... + conditions.bearishVolumeBuffer[1] > conditions.bearishVolumeBuffer[2] && + // + // Volume Signal is Up ... + conditions.bearishVolumeSignalBuffer[1] > conditions.bearishVolumeSignalBuffer[2] && + // + // Volume Signals Crossed Over ... + conditions.bearishVolumeSignalBuffer[1] > conditions.bullishVolumeSignalBuffer[1] + // + ) + // + && + // + // Check Last InDirectional Exists ... + helper.lastVolumeBullish.IsValid() && + // + // Current Close is Over last ... + conditions.bars[cIDX].close < helper.lastVolumeBullish.after && + // + // Before Close is not Over last ... + conditions.bars[pIDX].close >= helper.lastVolumeBullish.after + // + ; + + // + // SIGNAL Bar ... + + // + bool isSBarBullishStart = + // + ( + // + // Check Direction ... + conditions.isSBarBullish && + // + // Previous InDirectional Exists ... + helper.lastSignalBarBearish.IsValid() && + // + // Current Signal Bar close over prev ... + conditions.sBarCloseBuffer[cIDX] > helper.lastSignalBarBearish.after && + // + // Prev Signal Bar not close over prev ... + conditions.sBarCloseBuffer[pIDX] <= helper.lastSignalBarBearish.after + // + ) + // + ; + + // + bool isSBarBearishStart = + // + ( + // + // Check Direction ... + conditions.isSBarBearish && + // + // Previous InDirectional Exists ... + helper.lastSignalBarBullish.IsValid() && + // + // Current Signal Bar close over prev ... + conditions.sBarCloseBuffer[cIDX] < helper.lastSignalBarBullish.after && + // + // Prev Signal Bar not close over prev ... + conditions.sBarCloseBuffer[pIDX] >= helper.lastSignalBarBullish.after + // + ) + // + ; + + // + // HKSIGNAL Bar ... + + // + bool isHKSBarBullishStart = + // + ( + // + // Check Direction ... + conditions.isHKSBarBullish && + // + // Previous InDirectional Exists ... + helper.lastHKSignalBarBearish.IsValid() && + // + // Current Signal Bar close over prev ... + conditions.hkSBarCloseBuffer[cIDX] > helper.lastHKSignalBarBearish.after && + // + // Prev Signal Bar not close over prev ... + conditions.hkSBarCloseBuffer[pIDX] <= helper.lastHKSignalBarBearish.after + // + ) + // + ; + + // + bool isHKSBarBearishStart = + // + ( + // + // Check Direction ... + conditions.isHKSBarBearish && + // + // Previous InDirectional Exists ... + helper.lastHKSignalBarBullish.IsValid() && + // + // Current Signal Bar close over prev ... + conditions.hkSBarCloseBuffer[cIDX] < helper.lastHKSignalBarBullish.after && + // + // Prev Signal Bar not close over prev ... + conditions.hkSBarCloseBuffer[pIDX] >= helper.lastHKSignalBarBullish.after + // + ) + // + ; + + // + // Detect Bar Verifications ... + + // + ENUM_X_DIRECTION iBDir; + + // + // Rejected ... + bool isRejected = + barAnalyser + .IsRejected( + conditions.bars[cIDX], + iBDir // + ); + bool isBullishRejected = + isRejected && + IsBullish(iBDir); + bool isBearishRejected = + isRejected && + IsBearish(iBDir); + + // + // Engulfed ... + bool isEngulfed = + barAnalyser + .IsEngulfed( + conditions.bars[cIDX], + iBDir // + ); + bool isBullishEngulfed = + isEngulfed && + IsBullish(iBDir); + bool isBearishEngulfed = + isEngulfed && + IsBearish(iBDir); + + // + // Momentum ... + bool isMomentum = + barAnalyser + .IsMomentum( + conditions.bars[cIDX], + iBDir // + ); + bool isBullishMomentum = + isMomentum && + IsBullish(iBDir); + bool isBearishMomentum = + isMomentum && + IsBearish(iBDir); + + // + bool isBarBullishPressured = + isBullishRejected || + isBullishEngulfed || + isBullishMomentum; + + // + bool isBarBearishPressured = + isBearishRejected || + isBearishEngulfed || + isBearishMomentum; + + // + // Implement Signalling Conditions ... + + // + // -------------- + // Conditions 1: + // -------------- + // Descriptions: + // - [] Detect Parabolic Sar Direction Change ... + // - [] Check Some others Conditions based on Changed Direction ... + // - [] Generate Direction Change Zone ... + // - [] Use it to Fill Signal Zone ... + // ------------------------------------ + + // + bool isCond1Bullish = false; + bool isCond1Bearish = false; + if (allowSignallingConditions1) + { + // + isCond1Bullish = + // + // Start ... + (isSarBullishStart && + !isSarBearishStart) && + // + // SCORE ... + isScoreBullish && + // + // BAR ... + isBarBullishPressured && + // + // KI ... + // conditions.isKIUp && + conditions.isKIBullish && + // + // ATR ... + conditions.isATRUp && + // + // TREND ... + conditions.isTrendUp // && + // conditions.isTrendBullish + // + ; + + // + isCond1Bearish = + // + // Start ... + (isSarBearishStart && + !isSarBullishStart) && + // + // SCORE ... + isScoreBearish && + // + // BAR ... + isBarBearishPressured && + // + // KI ... + // conditions.isKIDown && + conditions.isKIBearish && + // + // ATR ... + conditions.isATRDown && + // + // TREND ... + conditions.isTrendDown // && + // conditions.isTrendBearish + // + ; + } + + // + bool isCond1 = + isCond1Bullish || + isCond1Bearish; + if (isCond1) + { + // + // Generate Direction Shift Zone ... + has = GenerateSarDirectionShiftBox( + signalZone, + helper, + conditions // + ); + if (has) + { + // + iTo = signalZone.to; + iDir = signalZone.dir; + iType = signalZone.type; + iFrom = signalZone.from; + iUpper = signalZone.upper; + iLower = signalZone.lower; + } + } + // ---------------------------------- + + // + // -------------- + // Conditions 2: + // -------------- + // Descriptions: + // - [] Detect Trend Direction Change ... + // - [] Check Some others Conditions based on Changed Direction ... + // - [] Generate Direction Change Zone ... + // - [] Use it to Fill Signal Zone ... + // ------------------------------------ + + // + bool isCond2Bullish = false; + bool isCond2Bearish = false; + if (allowSignallingConditions2) + { + // + isCond2Bullish = + // + // Start ... + (isTrendBullishStart && + !isTrendBearishStart) + // + ; + + // + isCond2Bearish = + // + // Start ... + (isTrendBearishStart && + !isTrendBullishStart) + // + ; + } + + // + bool isCond2 = + isCond2Bullish || + isCond2Bearish; + if (isCond2) + { + // + // Generate Direction Shift Zone ... + has = GenerateTrendDirectionShiftBox( + signalZone, + helper, + conditions // + ); + if (has) + { + // + iTo = signalZone.to; + iDir = signalZone.dir; + iType = signalZone.type; + iFrom = signalZone.from; + iUpper = signalZone.upper; + iLower = signalZone.lower; + } + } + // ------------------------------------ + + // + // -------------- + // Conditions 3: + // -------------- + // Descriptions: + // - [] Detect Delta Direction Change ... + // - [] Check Some others Conditions based on Changed Direction ... + // - [] Generate Direction Change Zone ... + // - [] Use it to Fill Signal Zone ... + // ------------------------------------ + + // + bool isCond3Bullish = false; + bool isCond3Bearish = false; + if (allowSignallingConditions3) + { + // + isCond3Bullish = + // + // Start ... + (isDeltaBullishStart && + !isDeltaBearishStart) + // + ; + + // + isCond3Bearish = + // + // Start ... + (isDeltaBearishStart && + !isDeltaBullishStart) + // + ; + } + + // + bool isCond3 = + isCond3Bullish || + isCond3Bearish; + if (isCond3) + { + // + // Generate Direction Shift Zone ... + has = GenerateDeltaDirectionShiftBox( + signalZone, + helper, + conditions // + ); + if (has) + { + // + iTo = signalZone.to; + iDir = signalZone.dir; + iType = signalZone.type; + iFrom = signalZone.from; + iUpper = signalZone.upper; + iLower = signalZone.lower; + } + } + // ------------------------------------ + + // + // -------------- + // Conditions 4: + // -------------- + // Descriptions: + // - [] Detect Volume Direction Change ... + // - [] Check Some others Conditions based on Changed Direction ... + // - [] Generate Direction Change Zone ... + // - [] Use it to Fill Signal Zone ... + // ------------------------------------ + + // + bool isCond4Bullish = false; + bool isCond4Bearish = false; + if (allowSignallingConditions4) + { + // + isCond4Bullish = + // + // Start ... + (isVolumeBullishStart && + !isVolumeBearishStart) + // + ; + + // + isCond4Bearish = + // + // Start ... + (isVolumeBearishStart && + !isVolumeBullishStart) + // + ; + } + + // + bool isCond4 = + isCond4Bullish || + isCond4Bearish; + if (isCond4) + { + // + // Generate Direction Shift Zone ... + has = GenerateVolumeDirectionShiftBox( + signalZone, + helper, + conditions // + ); + if (has) + { + // + iTo = signalZone.to; + iDir = signalZone.dir; + iType = signalZone.type; + iFrom = signalZone.from; + iUpper = signalZone.upper; + iLower = signalZone.lower; + } + } + // ------------------------------------ + + // + // -------------- + // Conditions 5: + // -------------- + // Descriptions: + // - [] Detect Signal Bar Direction Change ... + // - [] Check Some others Conditions based on Changed Direction ... + // - [] Generate Direction Change Zone ... + // - [] Use it to Fill Signal Zone ... + // ------------------------------------ + + // + bool isCond5Bullish = false; + bool isCond5Bearish = false; + if (allowSignallingConditions5) + { + // + isCond5Bullish = + // + // Start ... + (isSBarBullishStart && + !isSBarBearishStart) + // + ; + + // + isCond5Bearish = + // + // Start ... + (isSBarBearishStart && + !isSBarBullishStart) + // + ; + } + + // + bool isCond5 = + isCond5Bullish || + isCond5Bearish; + if (isCond5) + { + // + // Generate Direction Shift Zone ... + has = GenerateSignalBarDirectionShiftBox( + signalZone, + helper, + conditions // + ); + if (has) + { + // + iTo = signalZone.to; + iDir = signalZone.dir; + iType = signalZone.type; + iFrom = signalZone.from; + iUpper = signalZone.upper; + iLower = signalZone.lower; + } + } + // ------------------------------------ + + // + // -------------- + // Conditions 6: + // -------------- + // Descriptions: + // - [] Detect HK Signal Bar Direction Change ... + // - [] Check Some others Conditions based on Changed Direction ... + // - [] Generate Direction Change Zone ... + // - [] Use it to Fill Signal Zone ... + // ------------------------------------ + + // + bool isCond6Bullish = false; + bool isCond6Bearish = false; + if (allowSignallingConditions6) + { + // + isCond6Bullish = + // + // Start ... + (isHKSBarBullishStart && + !isHKSBarBearishStart) + // + ; + + // + isCond6Bearish = + // + // Start ... + (isHKSBarBearishStart && + !isHKSBarBullishStart) + // + ; + } + + // + bool isCond6 = + isCond6Bullish || + isCond6Bearish; + if (isCond6) + { + // + // Generate Direction Shift Zone ... + has = GenerateHKSignalBarDirectionShiftBox( + signalZone, + helper, + conditions // + ); + if (has) + { + // + iTo = signalZone.to; + iDir = signalZone.dir; + iType = signalZone.type; + iFrom = signalZone.from; + iUpper = signalZone.upper; + iLower = signalZone.lower; + } + } + // ------------------------------------ + + // + // Summarizing Signalling Results ... + + // + isBullish = + // + isCond1Bullish || + isCond2Bullish || + isCond3Bullish || + isCond4Bullish || + isCond5Bullish || + isCond6Bullish + // + ; + + // + isBearish = + // + isCond1Bearish || + isCond2Bearish || + isCond3Bearish || + isCond4Bearish || + isCond5Bearish || + isCond6Bearish + // + ; + } + + // + // Summarize Result ... + result = + isBullish || + isBearish; + + // + // Preparing Signal Zone ... + if (result) + { + // + iDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Preparing Signal Zone ... + signalZone.to = iTo; + signalZone.dir = iDir; + signalZone.from = iFrom; + signalZone.type = iType; + signalZone.upper = iUpper; + signalZone.lower = iLower; + signalZone.symbol = iSymbol; + signalZone.period = iPeriod; + + // + // Temparory Object ... + color iColor = + isBullish + ? clrAqua + : clrMagenta; + string iName = signalZone.type + "_Conditions_" + ToString(iDir) + "_" + ToString(((int)conditions.time)); + + // + CChartObjectVLine *iObj = new CChartObjectVLine(); + has = iObj.Create( + 0, + iName, + 0, + conditions.bars[zIDX].time // + ); + if (has) + { + // + iObj.Color(iColor); + } + + // + // Validate Signal Zone and Draw it ... + has = signalZone.IsValid(); + if (has) + { + // + XCATBPivotStyle iStyle; + iStyle.width = 2; + iStyle.clr = isBullish + ? clrYellow + : clrOrange; + iStyle.style = STYLE_SOLID; + + // + XCBoxObject *iObj; + has = drawer + .drawer + .DrawBox( + signalZone, + iObj // + ); + if (has) + { + drawer.ApplyPivotStyle(iObj, iStyle); + } + } + + // + Print("Conditions ..."); + // signalZone.Clean(); + } + + // + // Validate Result ... + result = signalZone.IsValid(); + + // + // Cleanup Resources ... + + // + if (!result) + { + // + signalZone.Clean(); + conditions.Clean(); + } + + // + return result; +} + +// \ No newline at end of file diff --git a/BKPS/14040316/XCATBEA/Libraries/xcatbea.x-poi.extensions.lib.mq5 b/BKPS/14040316/XCATBEA/Libraries/xcatbea.x-poi.extensions.lib.mq5 new file mode 100644 index 0000000..9e828f0 --- /dev/null +++ b/BKPS/14040316/XCATBEA/Libraries/xcatbea.x-poi.extensions.lib.mq5 @@ -0,0 +1,83 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Library +// ------------------------------------------------- +// Name: XCATBEAPOIExtension Lib +// Description: Library for Adding Extensions on +// XCATBEA POI(s) ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm Extensions Library for XCATBEA POI(s)" +#property strict + +// +// Imports ... +#include "../Classes/xcatbea.x-poi.detector.class.mq5" + +// +// Extensions ... + +// +int ExtractPivots( + XBoxZone &extracted[], + ENUM_XCATB_PIVOTS type, + XBoxZone &source[] // +) +{ + // + int result = 0; + + // + Clean(extracted); + + // + bool has = + IsValid(type) && + HasChild(source); + if (!has) + { + return result; + } + + // + int count = ArraySize(source); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = source[i]; + + // + ENUM_XCATB_PIVOTS iType = GetPivotType(iBox); + + // + has = iType == type; + if (has) + { + // + AddRef( + iBox, + extracted // + ); + } + + // + iBox.Clean(); + } + + // + result = ArraySize(extracted); + + // + return result; +} diff --git a/BKPS/14040316/compile.cmd b/BKPS/14040316/compile.cmd new file mode 100644 index 0000000..0015d25 --- /dev/null +++ b/BKPS/14040316/compile.cmd @@ -0,0 +1,26 @@ +@echo off + + set METAEDITOR="C:\Program Files\MetaTrader 5 Main\MetaEditor64.exe" + set "LOGFILE=%~dpn1.log" + + if "%~1"=="" ( + echo "You must specify the first parameter to this batch file." + goto end + ) + + :: Compile the MQL5 way + %METAEDITOR% /compile:%1 /log + :: 0 = failed + :: 1 = everything good + echo "Error level %ERRORLEVEL%" + + :: This dumps the log file to stdout so it can be seen. + :: It's assumed to be in the same directory as the expert file. + type "%LOGFILE%" + + :: Once shown, get rid of the .log file. + erase "%LOGFILE%" + +:end + :: If I want the CMD.exe window to go away, use exit + ::exit %ERRORLEVEL% \ No newline at end of file diff --git a/BKPS/14040316/mqlHelper.js b/BKPS/14040316/mqlHelper.js new file mode 100644 index 0000000..8fe4e41 --- /dev/null +++ b/BKPS/14040316/mqlHelper.js @@ -0,0 +1,19 @@ +/** + * XMQL Helper CLI Tools ... + * a module for handle MQL5 Commands running ... + * + * Maintainer + * + * Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) + */ + +// +// Import Requirements ... +const XProjectTools = require("./x-mql-project.tools"); + +// +// Read Command Arguments ... +let cmdName = process.argv[2]; + +// +XProjectTools.runCommand(cmdName); diff --git a/BKPS/14040316/package.json b/BKPS/14040316/package.json new file mode 100644 index 0000000..f6dc8c2 --- /dev/null +++ b/BKPS/14040316/package.json @@ -0,0 +1,30 @@ +{ + "name": "mql5", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "true": "", + "aaa": "|----------|", + "aab": "| Commons |", + "aac": "|----------|", + "mqlHelper": "node mqlHelper.js", + "cleanupEx": "npm run mqlHelper cleanup", + "compileWorkspace": "npm run mqlHelper *", + "compileExperts": "npm run mqlHelper experts", + "compileLibraries": "npm run mqlHelper libraries", + "compileHelpers": "npm run mqlHelper helpers", + "compileClasses": "npm run mqlHelper classes", + "compileIndicators": "npm run mqlHelper indicators", + "repackXCATBEA": "node prepareXCATBEA.js" + }, + "repository": { + "type": "git", + "url": "https://git.saherelmhub.ir/saherelm/MQL5TestWorkspace.git" + }, + "author": "Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)", + "license": "ISC", + "devDependencies": { + "shx": "^0.3.4" + } +} diff --git a/BKPS/14040316/prepareXCATBEA.js b/BKPS/14040316/prepareXCATBEA.js new file mode 100644 index 0000000..797e213 --- /dev/null +++ b/BKPS/14040316/prepareXCATBEA.js @@ -0,0 +1,35 @@ +// +// Import Requirements ... +const XProjectTools = require("./x-mql-project.tools"); + +// +// define constants ... +const projectName = "XCATBEA"; + +// +// Projects Resources ... +const projectResources = [ + "Libraries/*", // Required Libraries + "Classes/*", // Required Classes + "XCATBEA/*", // XCATBEA Projects ... + "Indicators/x-saherelm.x121.xcatb", // Required Indicators + "Helpers/x-saherelm.x121.xcatb.helper", // Indicator's Helpers Classes + "Experts/x-saherelm.x121.xcatb.ea", // Expert Advisers +]; + +// +run(); + +/** + * Main Project Function ... + */ +async function run() { + // + await XProjectTools.prepareProject( + projectName, + projectResources + ); +} + + + diff --git a/BKPS/14040316/x-mql-project.tools.js b/BKPS/14040316/x-mql-project.tools.js new file mode 100644 index 0000000..05d4223 --- /dev/null +++ b/BKPS/14040316/x-mql-project.tools.js @@ -0,0 +1,494 @@ +/** + * XProject Tools Module ... + * a module for handle MQL5 Projects Compile and Packing ... + * + * Maintainer + * + * Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) + */ + +// +// Import Requirements ... +const execSync = require("child_process").execSync; +const XFileTools = require("./Documents/JsModules/x-file.tools"); +const XShellTools = require("./Documents/JsModules/x-shell.tools"); +const XColorTools = require("./Documents/JsModules/x-color.tools"); +const XTypeTools = require("./Documents/JsModules/x-type-detector.tools"); + +// +// Definitions ... +const packsPath = XFileTools.joinPath(".", "Packs"); +const workspacePaths = [ + "Classes", // Required Classes + "Experts", // Expert Advisers + "Helpers", // Indicator's Helpers Classes + "Indicators", // Required Indicators + "Libraries", // Required Libraries + "XCATBEA", // XCATBEA Projects ... +]; + +// +//#region Tools ... + +/** + * Handle Compile and Pack Projects ... + * + * @param {string} projectName + * @param {string[]} resources + * @param {boolean} forceCleanup + * @param {boolean} forceCompileIndicators + */ +async function prepareProject( + projectName = "", + resources = [], + forceCleanup = true, + forceCompileIndicators = true +) { + // + // Check Resources Has Child ... + let isValidArgs = + resources.length > 0 && + XTypeTools.isArray(resources); + if (!isValidArgs) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("Invalid Resource List ...", XColorTools.COLOR_NAMES.Red) + ); + } + + // + // Check Project Name is Valid ... + isValidArgs = + projectName.length > 0 && + XTypeTools.isString(projectName); + if (!isValidArgs) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("Empty Project Name ...", XColorTools.COLOR_NAMES.Red) + ); + } + + // + // Prepare Pack Folder Exists ... + let isExists = XFileTools.isDirectoryExists(packsPath); + if (!isExists) { + XFileTools.createDirectory(packsPath); + } + + // + // Check Folder Exists or not ... + // if Exists Remove it ... + // Create Project Folder on Packs ... + const prjFolderOnPacks = XFileTools.joinPath(packsPath, projectName); + isExists = XFileTools.isDirectoryExists(prjFolderOnPacks); + if (isExists) { + await XFileTools.removeDirectory(prjFolderOnPacks, true); + } + XFileTools.createDirectory(prjFolderOnPacks); + + // + // Extract Required to Compile Resources List ... + let compileList = await extractResources(resources, true); + if (!compileList || compileList.length == 0) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("Resource List Extraction to Compile Failed ...", XColorTools.COLOR_NAMES.Red) + ); + + // + return; + } + + // + // Compile Resources Files ... + for (const f of compileList) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("try to Compile: ", XColorTools.COLOR_NAMES.Yellow), + XColorTools.applyForegroundColor(f, XColorTools.COLOR_NAMES.Blue) + ); + + // + await recursiveTriesToCompileFile(f, 0); + } + + // + // Extract Required to Pack Resources List ... + let packList = await extractResources(resources, false); + if (!packList || packList.length == 0) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("Resource List Extraction to Pack Failed ...", XColorTools.COLOR_NAMES.Red) + ); + + // + return; + } + + // + // Loop through Files ... + for (const f of packList) { + // + // Prepare Destination Path ... + const fBasePath = XFileTools.basename(f); + let fDestPath = f.replace(fBasePath, ""); + fDestPath = fDestPath.substring(0, fDestPath.length - 1); + fDestPath = XFileTools.joinPath(prjFolderOnPacks, fDestPath); + + // + const isFDestPathExists = XFileTools.isDirectoryExists(fDestPath); + if (!isFDestPathExists) { + XFileTools.createDirectory(fDestPath); + } + + // + // Log ... + console.log( + XColorTools.applyForegroundColor("try to copy: ", XColorTools.COLOR_NAMES.Yellow), + XColorTools.applyForegroundColor(f, XColorTools.COLOR_NAMES.Blue), + XColorTools.applyForegroundColor(" to : ", XColorTools.COLOR_NAMES.Yellow), + XColorTools.applyForegroundColor(fDestPath, XColorTools.COLOR_NAMES.Magenta) + ); + + // + let result = await XFileTools.copyFile(f, fDestPath); + if (result) { + // + const msg = "copy successfully ..."; + console.log( + XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Green) + ); + } else { + // + const msg = "copy failed ..."; + console.log(XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Red)); + throw msg; + } + } + + // + // Log ... + console.log( + XColorTools.applyForegroundColor("Project: ", XColorTools.COLOR_NAMES.Green), + XColorTools.applyForegroundColor(projectName, XColorTools.COLOR_NAMES.Yellow), + XColorTools.applyForegroundColor(" Compiled and Packed Successfully ...", XColorTools.COLOR_NAMES.Green), + ); + + // + // Cleanup WorkSpace if Provided ... + if (forceCleanup) { + await cleanupWorkSpace(); + } + + // + // Compile Indicators ... + if (forceCompileIndicators) { + await runCommand("Indicators"); + } +} + +/** + * Extract required Files List ... + * + * @param {boolean} forCompile + * + * @returns Promise + */ +async function extractResources( + resources = [], + forCompile = true +) { + // + let result = []; + + // + // Loop Through Project Resources and Extract Files List to Compile ... + for (const resource of resources) { + // + // Prepare Normalized Resource Path ... + let resourcePath = XFileTools.joinPath(".", resource); + + // + // Handle Wild Card Resources ... + if (resourcePath.endsWith("//*") || + resourcePath.endsWith("\\*")) { + // + resourcePath = resourcePath.substring(0, resourcePath.length - 2); + const files = await XFileTools.extractFiles( + resourcePath, + forCompile ? [".mq5", ".mq4"] : [".ex5", ".ex4"] + ); + + // + result = result.concat(files); + } + // + // Handle Direct File Resources ... + else { + // + // Check MQL 5 Version ... + let fileResourcePath = resourcePath + (forCompile ? ".mq5" : ".ex5"); + + // + // Check File Exists ... + let isExists = XFileTools.isFileExists(fileResourcePath); + if (!isExists) { + // + // Check MQL 4 Version ... + fileResourcePath = resourcePath + (forCompile ? ".mq4" : ".ex4"); + isExists = XFileTools.isFileExists(fileResourcePath); + } + + // + // Add File Path to Files List if Exists ... + if (isExists) { + result.push(fileResourcePath); + } + } + } + + // + return result; +} + +/** + * try to compile a file ... + * @param {string} f + * @param {number} numberOfTries + */ +async function recursiveTriesToCompileFile(f = "", numberOfTries = 0) { + // + let result = await handleFileCompile(f); + if (result) { + // + const msg = "compiled successfully ..."; + console.log(XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Green)); + return result; + } else { + // + if (numberOfTries < 10) { + // + numberOfTries++; + + // + const msg = "retry (" + (numberOfTries + 1) + ") ..."; + console.log(XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.LightMagenta)); + await recursiveTriesToCompileFile(f, numberOfTries); + } else { + // + const msg = "failed ..."; + console.log(XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Red)); + throw msg; + + // + return false; + } + } +} + +/** + * execute compile task on Specific File ... + * @param {string} f file path to Execute Compile task ... + * @returns + */ +async function handleFileCompile(f = "") { + // + let result = false; + + // + let exResult = await compileMQLFile(f); + if (exResult.includes("0 errors")) { + result = true; + } else { + result = false; + } + + // + return result; +} + +/** + * Compile Specific MQL File ... + * + * @param {string} path MQL file path ... + * @returns + */ +async function compileMQLFile(path = "") { + // + // Check File Exists ... + const isExists = XFileTools.isFileExists(path); + if (!isExists) { + // + const msg = "file not found ..."; + console.log(XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Red)); + throw msg; + } + + // + const ext = XFileTools.getFileExtension(path); + if (ext !== ".mq5" && ext !== "mq4") { + // + const msg = "invalid file extension ..."; + console.log(XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Red)); + throw msg; + } + + // + const cwd = __dirname; + const cmd = "compile.cmd " + path; + + // + const result = await XShellTools.execute(cmd, cwd); + return result; +} + +/** + * Run Specified Command in workspace ... + * + * @param {string} cmd + * @returns + */ +async function runCommand(cmd = "") { + // + // Validate Args ... + let isValidArgs = cmd.length > 0 && + XTypeTools.isString(cmd); + + // + // Validate Commands ... + if (isValidArgs) { + // + // Check Available Commands ... + isValidArgs = + cmd === "*" || + cmd === "cleanup" || + workspacePaths.includes(cmd) || + workspacePaths.map(x => x.toLowerCase(x)).includes(cmd.toLowerCase()); + } + if (!isValidArgs) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("Invalid Command ...", XColorTools.COLOR_NAMES.Red) + ); + } + + // + // Compile ... + if (cmd == "*") { + await compileWorkSpace(); + } else if (cmd == "cleanup") { + await cleanupWorkSpace(); + } else { + // + // Select Workspace to Compile ... + const folder = workspacePaths + .find(x => x.toLowerCase() === cmd.toLowerCase()); + isValidArgs = + XTypeTools.isString(folder) && + folder.length > 0; + if (!isValidArgs) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("Invalid Command ...", XColorTools.COLOR_NAMES.Red) + ); + } + + // + // Extract Required to Compile Resources List ... + let compileList = await XFileTools.extractFiles( + folder, + [".mq5", ".mq4"] + ); + if (!compileList || compileList.length == 0) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("Extraction to Compile Failed ...", XColorTools.COLOR_NAMES.Red) + ); + + // + return; + } + + // + // Compile Resources Files ... + for (const f of compileList) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("try to Compile: ", XColorTools.COLOR_NAMES.Yellow), + XColorTools.applyForegroundColor(f, XColorTools.COLOR_NAMES.Blue) + ); + + // + await recursiveTriesToCompileFile(f, 0); + } + } +} + +/** + * Cleanup Workspace compiled files ... + */ +async function cleanupWorkSpace() { + // + for (const path of workspacePaths) { + // + const fSourcePath = XFileTools.joinPath(".", path); + const filesToRemove = await XFileTools.extractFiles(fSourcePath, [".ex5", ".ex4"]); + for (const f of filesToRemove) { + // + // Log ... + console.log( + XColorTools.applyForegroundColor("try to Remove: ", XColorTools.COLOR_NAMES.Yellow), + XColorTools.applyForegroundColor(f, XColorTools.COLOR_NAMES.Blue) + ); + + // + let result = await XFileTools.removeFile(f); + if (result) { + // + const msg = "removed successfully ..."; + console.log( + XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Green) + ); + } else { + // + const msg = "removed failed ..."; + console.log(XColorTools.applyForegroundColor(msg, XColorTools.COLOR_NAMES.Red)); + throw msg; + } + } + } +} + +/** + * Compile Workspace ... + */ +async function compileWorkSpace() { + // + for (const path of workspacePaths) { + await runCommand(path); + } +} +//#endregion + +// +//#region Module Exports ... +module.exports = { + extractResources, + recursiveTriesToCompileFile, + handleFileCompile, + compileMQLFile, + runCommand, + cleanupWorkSpace, + compileWorkSpace, + prepareProject +} +//#endregion \ No newline at end of file

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�ghm4#$*k8MNg6eiL=n+a_Q=G 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�)3Vdp3Y6T`Nw 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%0Aqa5 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