From 898e6af837d24d8cc2e7bc1f1c6c63a61e56fd1a Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Thu, 8 May 2025 14:17:59 +0330 Subject: [PATCH] last backup XCAEA --- .../Classes/x-saherelm.base.class.mq5 | 101 + .../Classes/x-saherelm.x-account.class.mq5 | 398 + .../Classes/x-saherelm.x-alert.class.mq5 | 1580 ++++ .../Classes/x-saherelm.x-app-dialog.class.mq5 | 278 + .../x-saherelm.x-bar.analyser.class.mq5 | 3018 +++++++ .../Classes/x-saherelm.x-cobject.class.mq5 | 3178 +++++++ .../Classes/x-saherelm.x-expert.class.mq5 | 967 +++ .../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.class.mq5 | 3513 ++++++++ .../Classes/x-saherelm.x-poi.drawer.class.mq5 | 4356 ++++++++++ .../Classes/x-saherelm.x-rm.panel.class.mq5 | 1162 +++ .../Classes/x-saherelm.x-trade.class.mq5 | 3934 +++++++++ .../Classes/x-saherelm.x-volume.class.mq5 | 792 ++ .../Documents/BKP/1/signallers.tmp.mq5 | 124 + .../Documents/BKP/1/xcaea.signaller.class.mq5 | 853 ++ .../Documents/BKP/1/xcaea.signaller.lib.mq5 | 1334 +++ BKPS/14040218 XCAEA/Documents/BKP/2.mq5 | 1087 +++ .../BKP/Indicators/x-saherelm.x121.xca.v1.mq5 | 2452 ++++++ .../BKP/Indicators/x-saherelm.x121.xca.v2.mq5 | 2487 ++++++ .../BKP/Indicators/x-saherelm.x121.xswlh.mq5 | 573 ++ .../BKP/signallers1/xcaea.signaller.class.mq5 | 1070 +++ .../BKP/signallers1/xcaea.signaller.lib.mq5 | 2810 ++++++ .../14040218 XCAEA/Documents/BKP/test.tmp.mq5 | 273 + .../Documents/BKP/xcaea.signaller.class.mq5 | 878 ++ .../BKP/xcaea.x-poi.detector.class.bkp.mq5 | 4936 +++++++++++ .../BKP/xcaea.x-poi.detector.class.mq5 | 7731 +++++++++++++++++ .../BKP/xcaea.x-poi.drawer.class.bkp.mq5 | 2329 +++++ .../BKP/xcaea.x-poi.drawer.class.mq5 | 2424 ++++++ .../Diagrams/Position Protection.drawio | 279 + .../Documents/JsModules/x-color.tools.js | 506 ++ .../Documents/JsModules/x-file.tools.js | 887 ++ .../Documents/JsModules/x-shell.tools.js | 219 + .../JsModules/x-type-detector.tools.js | 268 + .../Documents/JsModules/x-value.tools.js | 1528 ++++ .../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 + BKPS/14040218 XCAEA/Experts/test.mq5 | 816 ++ .../Experts/x-saherelm.rr.tools.mq5 | 431 + .../Experts/x-saherelm.xcaea.ea.mq5 | 745 ++ .../Helpers/x-saherelm.x121.x3ma.helper.mq5 | 1546 ++++ .../Helpers/x-saherelm.x121.xca.helper.mq5 | 5245 +++++++++++ .../Helpers/x-saherelm.x121.xcc.helper.mq5 | 252 + .../Helpers/x-saherelm.x121.xct.helper.mq5 | 234 + .../Helpers/x-saherelm.x121.xoscs.helper.mq5 | 3498 ++++++++ .../Indicators/x-saherelm.x121.x3ma.mq5 | 788 ++ .../Indicators/x-saherelm.x121.xca.mq5 | 2601 ++++++ .../Indicators/x-saherelm.x121.xcc.mq5 | 437 + .../Indicators/x-saherelm.x121.xct.mq5 | 262 + .../Indicators/x-saherelm.x121.xoscs.mq5 | 1026 +++ .../x-saherelm.common.extensions.lib.mq5 | 6426 ++++++++++++++ .../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 | 3471 ++++++++ .../Libraries/x-saherelm.x-poi.lib.mq5 | 5796 ++++++++++++ .../Libraries/x-saherelm.x-poi.state.lib.mq5 | 4680 ++++++++++ .../Libraries/x-saherelm.x-trade.lib.mq5 | 6329 ++++++++++++++ .../Classes/xcaea.x-data.collector.class.mq5 | 167 + .../Classes/xcaea.x-poi.detector.class.mq5 | 3402 ++++++++ .../Classes/xcaea.x-poi.drawer.class.mq5 | 932 ++ .../Classes/xcaea.x-trade.manager.class.mq5 | 1419 +++ .../XCAEA/Helpers/xcaea.helper.mq5 | 4175 +++++++++ .../XCAEA/Libraries/xcaea.signaller.lib.mq5 | 2495 ++++++ .../XCAEA/Signals/xcaea.signaller.class.mq5 | 900 ++ .../XCAEA/Tests/xcaea.cond2.script.mq5 | 647 ++ 72 files changed, 126051 insertions(+) create mode 100644 BKPS/14040218 XCAEA/Classes/x-saherelm.base.class.mq5 create mode 100644 BKPS/14040218 XCAEA/Classes/x-saherelm.x-account.class.mq5 create mode 100644 BKPS/14040218 XCAEA/Classes/x-saherelm.x-alert.class.mq5 create mode 100644 BKPS/14040218 XCAEA/Classes/x-saherelm.x-app-dialog.class.mq5 create mode 100644 BKPS/14040218 XCAEA/Classes/x-saherelm.x-bar.analyser.class.mq5 create mode 100644 BKPS/14040218 XCAEA/Classes/x-saherelm.x-cobject.class.mq5 create mode 100644 BKPS/14040218 XCAEA/Classes/x-saherelm.x-expert.class.mq5 create mode 100644 BKPS/14040218 XCAEA/Classes/x-saherelm.x-helper.class.mq5 create mode 100644 BKPS/14040218 XCAEA/Classes/x-saherelm.x-http.class.mq5 create mode 100644 BKPS/14040218 XCAEA/Classes/x-saherelm.x-md5.class.mq5 create mode 100644 BKPS/14040218 XCAEA/Classes/x-saherelm.x-poi.class.mq5 create mode 100644 BKPS/14040218 XCAEA/Classes/x-saherelm.x-poi.drawer.class.mq5 create mode 100644 BKPS/14040218 XCAEA/Classes/x-saherelm.x-rm.panel.class.mq5 create mode 100644 BKPS/14040218 XCAEA/Classes/x-saherelm.x-trade.class.mq5 create mode 100644 BKPS/14040218 XCAEA/Classes/x-saherelm.x-volume.class.mq5 create mode 100644 BKPS/14040218 XCAEA/Documents/BKP/1/signallers.tmp.mq5 create mode 100644 BKPS/14040218 XCAEA/Documents/BKP/1/xcaea.signaller.class.mq5 create mode 100644 BKPS/14040218 XCAEA/Documents/BKP/1/xcaea.signaller.lib.mq5 create mode 100644 BKPS/14040218 XCAEA/Documents/BKP/2.mq5 create mode 100644 BKPS/14040218 XCAEA/Documents/BKP/Indicators/x-saherelm.x121.xca.v1.mq5 create mode 100644 BKPS/14040218 XCAEA/Documents/BKP/Indicators/x-saherelm.x121.xca.v2.mq5 create mode 100644 BKPS/14040218 XCAEA/Documents/BKP/Indicators/x-saherelm.x121.xswlh.mq5 create mode 100644 BKPS/14040218 XCAEA/Documents/BKP/signallers1/xcaea.signaller.class.mq5 create mode 100644 BKPS/14040218 XCAEA/Documents/BKP/signallers1/xcaea.signaller.lib.mq5 create mode 100644 BKPS/14040218 XCAEA/Documents/BKP/test.tmp.mq5 create mode 100644 BKPS/14040218 XCAEA/Documents/BKP/xcaea.signaller.class.mq5 create mode 100644 BKPS/14040218 XCAEA/Documents/BKP/xcaea.x-poi.detector.class.bkp.mq5 create mode 100644 BKPS/14040218 XCAEA/Documents/BKP/xcaea.x-poi.detector.class.mq5 create mode 100644 BKPS/14040218 XCAEA/Documents/BKP/xcaea.x-poi.drawer.class.bkp.mq5 create mode 100644 BKPS/14040218 XCAEA/Documents/BKP/xcaea.x-poi.drawer.class.mq5 create mode 100644 BKPS/14040218 XCAEA/Documents/Diagrams/Position Protection.drawio create mode 100644 BKPS/14040218 XCAEA/Documents/JsModules/x-color.tools.js create mode 100644 BKPS/14040218 XCAEA/Documents/JsModules/x-file.tools.js create mode 100644 BKPS/14040218 XCAEA/Documents/JsModules/x-shell.tools.js create mode 100644 BKPS/14040218 XCAEA/Documents/JsModules/x-type-detector.tools.js create mode 100644 BKPS/14040218 XCAEA/Documents/JsModules/x-value.tools.js create mode 100644 BKPS/14040218 XCAEA/Documents/Temlates/signalling.function.template.mq5 create mode 100644 BKPS/14040218 XCAEA/Documents/Temlates/temp.pivot.detect.mq5 create mode 100644 BKPS/14040218 XCAEA/Documents/Temlates/x-saherelm.x-ea.template.ea.mq5 create mode 100644 BKPS/14040218 XCAEA/Documents/Temlates/x-saherelm.x-panel.ea.mq5 create mode 100644 BKPS/14040218 XCAEA/Documents/Temlates/xwz.signal.senario.template.mq5 create mode 100644 BKPS/14040218 XCAEA/Experts/test.mq5 create mode 100644 BKPS/14040218 XCAEA/Experts/x-saherelm.rr.tools.mq5 create mode 100644 BKPS/14040218 XCAEA/Experts/x-saherelm.xcaea.ea.mq5 create mode 100644 BKPS/14040218 XCAEA/Helpers/x-saherelm.x121.x3ma.helper.mq5 create mode 100644 BKPS/14040218 XCAEA/Helpers/x-saherelm.x121.xca.helper.mq5 create mode 100644 BKPS/14040218 XCAEA/Helpers/x-saherelm.x121.xcc.helper.mq5 create mode 100644 BKPS/14040218 XCAEA/Helpers/x-saherelm.x121.xct.helper.mq5 create mode 100644 BKPS/14040218 XCAEA/Helpers/x-saherelm.x121.xoscs.helper.mq5 create mode 100644 BKPS/14040218 XCAEA/Indicators/x-saherelm.x121.x3ma.mq5 create mode 100644 BKPS/14040218 XCAEA/Indicators/x-saherelm.x121.xca.mq5 create mode 100644 BKPS/14040218 XCAEA/Indicators/x-saherelm.x121.xcc.mq5 create mode 100644 BKPS/14040218 XCAEA/Indicators/x-saherelm.x121.xct.mq5 create mode 100644 BKPS/14040218 XCAEA/Indicators/x-saherelm.x121.xoscs.mq5 create mode 100644 BKPS/14040218 XCAEA/Libraries/x-saherelm.common.extensions.lib.mq5 create mode 100644 BKPS/14040218 XCAEA/Libraries/x-saherelm.common.lib.mq5 create mode 100644 BKPS/14040218 XCAEA/Libraries/x-saherelm.common.models.lib.mq5 create mode 100644 BKPS/14040218 XCAEA/Libraries/x-saherelm.draw.lib.mq5 create mode 100644 BKPS/14040218 XCAEA/Libraries/x-saherelm.x-enums.lib.mq5 create mode 100644 BKPS/14040218 XCAEA/Libraries/x-saherelm.x-ohcl.lib.mq5 create mode 100644 BKPS/14040218 XCAEA/Libraries/x-saherelm.x-poi.extensions.lib.mq5 create mode 100644 BKPS/14040218 XCAEA/Libraries/x-saherelm.x-poi.lib.mq5 create mode 100644 BKPS/14040218 XCAEA/Libraries/x-saherelm.x-poi.state.lib.mq5 create mode 100644 BKPS/14040218 XCAEA/Libraries/x-saherelm.x-trade.lib.mq5 create mode 100644 BKPS/14040218 XCAEA/XCAEA/Classes/xcaea.x-data.collector.class.mq5 create mode 100644 BKPS/14040218 XCAEA/XCAEA/Classes/xcaea.x-poi.detector.class.mq5 create mode 100644 BKPS/14040218 XCAEA/XCAEA/Classes/xcaea.x-poi.drawer.class.mq5 create mode 100644 BKPS/14040218 XCAEA/XCAEA/Classes/xcaea.x-trade.manager.class.mq5 create mode 100644 BKPS/14040218 XCAEA/XCAEA/Helpers/xcaea.helper.mq5 create mode 100644 BKPS/14040218 XCAEA/XCAEA/Libraries/xcaea.signaller.lib.mq5 create mode 100644 BKPS/14040218 XCAEA/XCAEA/Signals/xcaea.signaller.class.mq5 create mode 100644 BKPS/14040218 XCAEA/XCAEA/Tests/xcaea.cond2.script.mq5 diff --git a/BKPS/14040218 XCAEA/Classes/x-saherelm.base.class.mq5 b/BKPS/14040218 XCAEA/Classes/x-saherelm.base.class.mq5 new file mode 100644 index 0000000..0e7557f --- /dev/null +++ b/BKPS/14040218 XCAEA/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/14040218 XCAEA/Classes/x-saherelm.x-account.class.mq5 b/BKPS/14040218 XCAEA/Classes/x-saherelm.x-account.class.mq5 new file mode 100644 index 0000000..c451091 --- /dev/null +++ b/BKPS/14040218 XCAEA/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/14040218 XCAEA/Classes/x-saherelm.x-alert.class.mq5 b/BKPS/14040218 XCAEA/Classes/x-saherelm.x-alert.class.mq5 new file mode 100644 index 0000000..c92a6d5 --- /dev/null +++ b/BKPS/14040218 XCAEA/Classes/x-saherelm.x-alert.class.mq5 @@ -0,0 +1,1580 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCAlert +// Description: provides all Alerts requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.base.class.mq5" + +// +// Class Definition ... + +class 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 + ) + { + // + mPrefix = prefix; + mLogAlerts = logAlerts; + mMailAlerts = mailAlerts; + mPushAlerts = pushAlerts; + mEnableAlerts = enableAlerts; + mTerminalAlerts = terminalAlerts; + + // + // Normalize Prefix if Not Provided ... + if (!IsValid(mPrefix)) + { + mPrefix = GetTag(); + } + } + + // + // Deconstructor ... + ~XCAlert() + { + } + + // + // Override ... + string GetTag() override + { + return GetSpecificToken(this); + } + + // + // Properties Getter(s) / Setter(s) ... + + // + string GetPrefix() + { + return mPrefix; + } + + // + void SetPrefix(string value) + { + mPrefix = value; + } + + // + bool GetLogAlerts() + { + return mLogAlerts; + } + + // + void SetLogAlerts(bool value) + { + mLogAlerts = value; + } + + // + bool GetEnableAlerts() + { + return mEnableAlerts; + } + + // + void SetEnableAlerts(bool value) + { + mEnableAlerts = value; + } + + // + bool GetPushAlerts() + { + return mPushAlerts; + } + + // + void SetPushAlerts(bool value) + { + mPushAlerts = value; + } + + // + bool GetMailAlerts() + { + return mMailAlerts; + } + + // + void SetMailAlerts(bool value) + { + mMailAlerts = value; + } + + // + bool GetTerminalAlerts() + { + return mTerminalAlerts; + } + + // + void SetTerminalAlerts(bool value) + { + mTerminalAlerts = value; + } + + // + // Tools Funtions ... + + // + // Alerts ... + + // + // Logging an Alert ... + void LogAlert(string message) + { + // + // Validate Args ... + if (!CanLogAlert()) + { + return; + } + + // + Log(message); + } + + // + // Terminal Alert ... + void TerminalAlert(string message) + { + // + // Validate Args ... + if (!CanTerminalAlert()) + { + return; + } + + // + // Prepare Message ... + message = PrepareMessage(message); + + // Send Terminal Alert ... + Alert(message); + } + + // + // Mail Alert ... + void MailAlert(string message) + { + // + // Validate Args ... + if (!CanMailAlert()) + { + return; + } + + // + // Send Mail Alert ... + SendMail(GetPrefix(), message); + } + + // + // Send Push Notification ... + void PushAlert(string message) + { + // + // Validate Args ... + if (!CanPushAlert()) + { + return; + } + + // + // Prepare Message ... + message = PrepareMessage(message); + + // + // Send Push Notification Alert ... + SendNotification(message); + } + + // + // Send an Alert by Handling all Different Specified + // type's of Alert's if they are Enabled ... + void Alert(string message) + { + // + // Handle Log, if Enabled ... + LogAlert(message); + + // + // Handle Mail if Enabled ... + MailAlert(message); + + // + // Handle Push if Enabled ... + PushAlert(message); + + // + // Handle Terminal if Enabled ... + TerminalAlert(message); + } + + // + // Logs ... + + // + // Log a Message ... + void Log(string message) + { + // + if (!CanLog()) + { + return; + } + + // + Print(GetPrefix(), " > ", message); + } + void Log(string tag, string message) + { + // + if (!CanLog()) + { + return; + } + + // + Print(GetPrefix(), "_", tag, " > ", message); + } + void LogEmpty() + { + // + if (!CanLog()) + { + return; + } + + // + Print(" "); + } + + // + // Log Specific Array ... + template + void LogArray( + T &array[], // Array to Log + string label = NULL // Array Label + ) + { + // + if (!CanLog()) + { + return; + } + + // + Print(GetPrefix(), ">", (IsValid(label) ? label : "")); + ArrayPrint(array); + } + + // + // Error ... + + // + // Log an Error ... + void LogError( + int error = -1 // Specific Error, if it's equal to -1, use Last Error ... + ) + { + // + if (!CanLog()) + { + return; + } + + // + if (error <= -1) + { + error = GetLastError(); + } + + // + string errorMsg = GetErrorDescription(error); + + // + Log("Error: " + errorMsg); + } + + // + // Retrieve Specified Error Code Description ... + string GetErrorDescription(int err_code) + { + // + string result = ""; + + // + switch (err_code) + { + // + //--- Constant Description + + // + case ERR_SUCCESS: + result = "The operation completed successfully"; + break; + + // + case ERR_INTERNAL_ERROR: + result = "Unexpected internal error"; + break; + + // + case ERR_WRONG_INTERNAL_PARAMETER: + result = "Wrong parameter in the inner call of the client terminal function"; + break; + + // + case ERR_INVALID_PARAMETER: + result = "Wrong parameter when calling the system function"; + break; + + // + case ERR_NOT_ENOUGH_MEMORY: + result = "Not enough memory to perform the system function"; + break; + + // + case ERR_STRUCT_WITHOBJECTS_ORCLASS: + result = "The structure contains objects of strings and/or dynamic arrays and/or structure of such objects and/or classes"; + break; + + // + case ERR_INVALID_ARRAY: + result = "Array of a wrong type, wrong size, or a damaged object of a dynamic array"; + break; + + // + case ERR_ARRAY_RESIZE_ERROR: + result = "Not enough memory for the relocation of an array, or an attempt to change the size of a static array"; + break; + + // + case ERR_STRING_RESIZE_ERROR: + result = "Not enough memory for the relocation of string"; + break; + + // + case ERR_NOTINITIALIZED_STRING: + result = "Not initialized string"; + break; + + // + case ERR_INVALID_DATETIME: + result = "Invalid date and/or time"; + break; + + // + case ERR_ARRAY_BAD_SIZE: + result = "Requested array size exceeds 2 GB"; + break; + + // + case ERR_INVALID_POINTER: + result = "Wrong pointer"; + break; + + // + case ERR_INVALID_POINTER_TYPE: + result = "Wrong type of pointer"; + break; + + // + case ERR_FUNCTION_NOT_ALLOWED: + result = "System function is not allowed to call"; + break; + + // + //--- Charts + + // + case ERR_CHART_WRONG_ID: + result = "Wrong chart ID"; + break; + + // + case ERR_CHART_NO_REPLY: + result = "Chart does not respond"; + break; + + // + case ERR_CHART_NOT_FOUND: + result = "Chart not found"; + break; + + // + case ERR_CHART_NO_EXPERT: + result = "No Expert Advisor in the chart that could handle the event"; + break; + + // + case ERR_CHART_CANNOT_OPEN: + result = "Chart opening error"; + break; + + // + case ERR_CHART_CANNOT_CHANGE: + result = "Failed to change chart symbol and period"; + break; + + // + case ERR_CHART_CANNOT_CREATE_TIMER: + result = "Failed to create timer"; + break; + + // + case ERR_CHART_WRONG_PROPERTY: + result = "Wrong chart property ID"; + break; + + // + case ERR_CHART_SCREENSHOT_FAILED: + result = "Error creating screenshots"; + break; + + // + case ERR_CHART_NAVIGATE_FAILED: + result = "Error navigating through chart"; + break; + + // + case ERR_CHART_TEMPLATE_FAILED: + result = "Error applying template"; + break; + + // + case ERR_CHART_WINDOW_NOT_FOUND: + result = "Subwindow containing the indicator was not found"; + break; + + // + case ERR_CHART_INDICATOR_CANNOT_ADD: + result = "Error adding an indicator to chart"; + break; + + // + case ERR_CHART_INDICATOR_CANNOT_DEL: + result = "Error deleting an indicator from the chart"; + break; + + // + case ERR_CHART_INDICATOR_NOT_FOUND: + result = "Indicator not found on the specified chart"; + break; + + // + //--- Graphical Objects + case ERR_OBJECT_ERROR: + result = "Error working with a graphical object"; + break; + + // + case ERR_OBJECT_NOT_FOUND: + result = "Graphical object was not found"; + break; + + // + case ERR_OBJECT_WRONG_PROPERTY: + result = "Wrong ID of a graphical object property"; + break; + + // + case ERR_OBJECT_GETDATE_FAILED: + result = "Unable to get date corresponding to the value"; + break; + + // + case ERR_OBJECT_GETVALUE_FAILED: + result = "Unable to get value corresponding to the date"; + break; + + // + //--- MarketInfo + + // + case ERR_MARKET_UNKNOWN_SYMBOL: + result = "Unknown symbol"; + break; + + // + case ERR_MARKET_NOT_SELECTED: + result = "Symbol is not selected in MarketWatch"; + break; + + // + case ERR_MARKET_WRONG_PROPERTY: + result = "Wrong identifier of a symbol property"; + break; + + // + case ERR_MARKET_LASTTIME_UNKNOWN: + result = "Time of the last tick is not known (no ticks)"; + break; + + // + case ERR_MARKET_SELECT_ERROR: + result = "Error adding or deleting a symbol in MarketWatch"; + break; + + // + //--- History Access + + // + case ERR_HISTORY_NOT_FOUND: + result = "Requested history not found"; + break; + + // + case ERR_HISTORY_WRONG_PROPERTY: + result = "Wrong ID of the history property"; + break; + + // + //--- Global_Variables + + // + case ERR_GLOBALVARIABLE_NOT_FOUND: + result = "Global variable of the client terminal is not found"; + break; + + // + case ERR_GLOBALVARIABLE_EXISTS: + result = "Global variable of the client terminal with the same name already exists"; + break; + + // + case ERR_MAIL_SEND_FAILED: + result = "Email sending failed"; + break; + + // + case ERR_PLAY_SOUND_FAILED: + result = "Sound playing failed"; + break; + + // + case ERR_MQL5_WRONG_PROPERTY: + result = "Wrong identifier of the program property"; + break; + + // + case ERR_TERMINAL_WRONG_PROPERTY: + result = "Wrong identifier of the terminal property"; + break; + + // + case ERR_FTP_SEND_FAILED: + result = "File sending via ftp failed"; + break; + + // + case ERR_NOTIFICATION_SEND_FAILED: + result = "Error in sending notification"; + break; + + // + //--- Custom Indicator Buffers + + // + case ERR_BUFFERS_NO_MEMORY: + result = "Not enough memory for the distribution of indicator buffers"; + break; + + // + case ERR_BUFFERS_WRONG_INDEX: + result = "Wrong indicator buffer index"; + break; + + // + //--- Custom Indicator Properties + + // + case ERR_CUSTOM_WRONG_PROPERTY: + result = "Wrong ID of the custom indicator property"; + break; + + // + //--- Account + + // + case ERR_ACCOUNT_WRONG_PROPERTY: + result = "Wrong account property ID"; + break; + + // + case ERR_TRADE_WRONG_PROPERTY: + result = "Wrong trade property ID"; + break; + + // + case ERR_TRADE_DISABLED: + result = "Trading by Expert Advisors prohibited"; + break; + + // + case ERR_TRADE_POSITION_NOT_FOUND: + result = "Position not found"; + break; + + // + case ERR_TRADE_ORDER_NOT_FOUND: + result = "Order not found"; + break; + + // + case ERR_TRADE_DEAL_NOT_FOUND: + result = "Deal not found"; + break; + + // + case ERR_TRADE_SEND_FAILED: + result = "Trade request sending failed"; + break; + + // + //--- Indicators + + // + case ERR_INDICATOR_UNKNOWN_SYMBOL: + result = "Unknown symbol"; + break; + + // + case ERR_INDICATOR_CANNOT_CREATE: + result = "Indicator cannot be created"; + break; + + // + case ERR_INDICATOR_NO_MEMORY: + result = "Not enough memory to add the indicator"; + break; + + // + case ERR_INDICATOR_CANNOT_APPLY: + result = "The indicator cannot be applied to another indicator"; + break; + + // + case ERR_INDICATOR_CANNOT_ADD: + result = "Error applying an indicator to chart"; + break; + + // + case ERR_INDICATOR_DATA_NOT_FOUND: + result = "Requested data not found"; + break; + + // + case ERR_INDICATOR_WRONG_HANDLE: + result = "Wrong indicator handle"; + break; + + // + case ERR_INDICATOR_WRONG_PARAMETERS: + result = "Wrong number of parameters when creating an indicator"; + break; + + // + case ERR_INDICATOR_PARAMETERS_MISSING: + result = "No parameters when creating an indicator"; + break; + + // + case ERR_INDICATOR_CUSTOM_NAME: + result = "The first parameter in the array must be the name of the custom indicator"; + break; + + // + case ERR_INDICATOR_PARAMETER_TYPE: + result = "Invalid parameter type in the array when creating an indicator"; + break; + + // + case ERR_INDICATOR_WRONG_INDEX: + result = "Wrong index of the requested indicator buffer"; + break; + + // + //--- Depth of Market + + // + case ERR_BOOKS_CANNOT_ADD: + result = "Depth Of Market can not be added"; + break; + + // + case ERR_BOOKS_CANNOT_DELETE: + result = "Depth Of Market can not be removed"; + break; + + // + case ERR_BOOKS_CANNOT_GET: + result = "The data from Depth Of Market can not be obtained"; + break; + + // + case ERR_BOOKS_CANNOT_SUBSCRIBE: + result = "Error in subscribing to receive new data from Depth Of Market"; + break; + + // + //--- File Operations + + // + case ERR_TOO_MANY_FILES: + result = "More than 64 files cannot be opened at the same time"; + break; + + // + case ERR_WRONG_FILENAME: + result = "Invalid file name"; + break; + + // + case ERR_TOO_LONG_FILENAME: + result = "Too long file name"; + break; + + // + case ERR_CANNOT_OPEN_FILE: + result = "File opening error"; + break; + + // + case ERR_FILE_CACHEBUFFER_ERROR: + result = "Not enough memory for cache to read"; + break; + + // + case ERR_CANNOT_DELETE_FILE: + result = "File deleting error"; + break; + + // + case ERR_INVALID_FILEHANDLE: + result = "A file with this handle was closed, or was not opening at all"; + break; + + // + case ERR_WRONG_FILEHANDLE: + result = "Wrong file handle"; + break; + + // + case ERR_FILE_NOTTOWRITE: + result = "The file must be opened for writing"; + break; + + // + case ERR_FILE_NOTTOREAD: + result = "The file must be opened for reading"; + break; + + // + case ERR_FILE_NOTBIN: + result = "The file must be opened as a binary one"; + break; + + // + case ERR_FILE_NOTTXT: + result = "The file must be opened as a text"; + break; + + // + case ERR_FILE_NOTTXTORCSV: + result = "The file must be opened as a text or CSV"; + break; + + // + case ERR_FILE_NOTCSV: + result = "The file must be opened as CSV"; + break; + + // + case ERR_FILE_READERROR: + result = "File reading error"; + break; + + // + case ERR_FILE_BINSTRINGSIZE: + result = "String size must be specified, because the file is opened as binary"; + break; + + // + case ERR_INCOMPATIBLE_FILE: + result = "A text file must be for string arrays, for other arrays - binary"; + break; + + // + case ERR_FILE_IS_DIRECTORY: + result = "This is not a file, this is a directory"; + break; + + // + case ERR_FILE_NOT_EXIST: + result = "File does not exist"; + break; + + // + case ERR_FILE_CANNOT_REWRITE: + result = "File can not be rewritten"; + break; + + // + case ERR_WRONG_DIRECTORYNAME: + result = "Wrong directory name"; + break; + + // + case ERR_DIRECTORY_NOT_EXIST: + result = "Directory does not exist"; + break; + + // + case ERR_FILE_ISNOT_DIRECTORY: + result = "This is a file, not a directory"; + break; + + // + case ERR_CANNOT_DELETE_DIRECTORY: + result = "The directory cannot be removed"; + break; + + // + case ERR_CANNOT_CLEAN_DIRECTORY: + result = "Failed to clear the directory (probably one or more files are blocked and removal operation failed)"; + break; + + // + case ERR_FILE_WRITEERROR: + result = "Failed to write a resource to a file"; + break; + + // + //--- String Casting + + // + case ERR_NO_STRING_DATE: + result = "No date in the string"; + break; + + // + case ERR_WRONG_STRING_DATE: + result = "Wrong date in the string"; + break; + + // + case ERR_WRONG_STRING_TIME: + result = "Wrong time in the string"; + break; + + // + case ERR_STRING_TIME_ERROR: + result = "Error converting string to date"; + break; + + // + case ERR_STRING_OUT_OF_MEMORY: + result = "Not enough memory for the string"; + break; + + // + case ERR_STRING_SMALL_LEN: + result = "The string length is less than expected"; + break; + + // + case ERR_STRING_TOO_BIGNUMBER: + result = "Too large number, more than ULONG_MAX"; + break; + + // + case ERR_WRONG_FORMATSTRING: + result = "Invalid format string"; + break; + + // + case ERR_TOO_MANY_FORMATTERS: + result = "Amount of format specifiers more than the parameters"; + break; + + // + case ERR_TOO_MANY_PARAMETERS: + result = "Amount of parameters more than the format specifiers"; + break; + + // + case ERR_WRONG_STRING_PARAMETER: + result = "Damaged parameter of string type"; + break; + + // + case ERR_STRINGPOS_OUTOFRANGE: + result = "Position outside the string"; + break; + + // + case ERR_STRING_ZEROADDED: + result = "0 added to the string end, a useless operation"; + break; + + // + case ERR_STRING_UNKNOWNTYPE: + result = "Unknown data type when converting to a string"; + break; + + // + case ERR_WRONG_STRING_OBJECT: + result = "Damaged string object"; + break; + + // + //--- Operations with Arrays + + // + case ERR_INCOMPATIBLE_ARRAYS: + result = "Copying incompatible arrays. String array can be copied only to a string array, and a numeric array - in numeric array only"; + break; + + // + case ERR_SMALL_ASSERIES_ARRAY: + result = "The receiving array is declared as AS_SERIES, and it is of insufficient size"; + break; + + // + case ERR_SMALL_ARRAY: + result = "Too small array, the starting position is outside the array"; + break; + + // + case ERR_ZEROSIZE_ARRAY: + result = "An array of zero length"; + break; + + // + case ERR_NUMBER_ARRAYS_ONLY: + result = "Must be a numeric array"; + break; + + // + case ERR_ONEDIM_ARRAYS_ONLY: + result = "Must be a one-dimensional array"; + break; + + // + case ERR_SERIES_ARRAY: + result = "Timeseries cannot be used"; + break; + + // + case ERR_DOUBLE_ARRAY_ONLY: + result = "Must be an array of type double"; + break; + + // + case ERR_FLOAT_ARRAY_ONLY: + result = "Must be an array of type float"; + break; + + // + case ERR_LONG_ARRAY_ONLY: + result = "Must be an array of type long"; + break; + + // + case ERR_INT_ARRAY_ONLY: + result = "Must be an array of type int"; + break; + + // + case ERR_SHORT_ARRAY_ONLY: + result = "Must be an array of type short"; + break; + + // + case ERR_CHAR_ARRAY_ONLY: + result = "Must be an array of type char"; + break; + + // + //--- Operations with OpenCL + + // + case ERR_OPENCL_NOT_SUPPORTED: + result = "OpenCL functions are not supported on this computer"; + break; + + // + case ERR_OPENCL_INTERNAL: + result = "Internal error occurred when running OpenCL"; + break; + + // + case ERR_OPENCL_INVALID_HANDLE: + result = "Invalid OpenCL handle"; + break; + + // + case ERR_OPENCL_CONTEXT_CREATE: + result = "Error creating the OpenCL context"; + break; + + // + case ERR_OPENCL_QUEUE_CREATE: + result = "Failed to create a run queue in OpenCL"; + break; + + // + case ERR_OPENCL_PROGRAM_CREATE: + result = "Error occurred when compiling an OpenCL program"; + break; + + // + case ERR_OPENCL_TOO_LONG_KERNEL_NAME: + result = "Too long kernel name (OpenCL kernel)"; + break; + + // + case ERR_OPENCL_KERNEL_CREATE: + result = "Error creating an OpenCL kernel"; + break; + + // + case ERR_OPENCL_SET_KERNEL_PARAMETER: + result = "Error occurred when setting parameters for the OpenCL kernel"; + break; + + // + case ERR_OPENCL_EXECUTE: + result = "OpenCL program runtime error"; + break; + + // + case ERR_OPENCL_WRONG_BUFFER_SIZE: + result = "Invalid size of the OpenCL buffer"; + break; + + // + case ERR_OPENCL_WRONG_BUFFER_OFFSET: + result = "Invalid offset in the OpenCL buffer"; + break; + + // + case ERR_OPENCL_BUFFER_CREATE: + result = "Failed to create and OpenCL buffer"; + break; + + // + //--- User-Defined Errors + default: + result = "UNKNOWN Erro ..."; + break; + } + + // + return result; + } + + // + // Retrieve Specified Error Code Description ... + string GetTradeServerReturnCodeDescription(int return_code) + { + // + string result = ""; + + // + switch (return_code) + { + // + case TRADE_RETCODE_REQUOTE: + result = "Requote"; + break; + + // + case TRADE_RETCODE_REJECT: + result = "Request rejected"; + break; + + // + case TRADE_RETCODE_CANCEL: + result = "Request canceled by trader"; + break; + + // + case TRADE_RETCODE_PLACED: + result = "Order placed"; + break; + + // + case TRADE_RETCODE_DONE: + result = "Request completed"; + break; + + // + case TRADE_RETCODE_DONE_PARTIAL: + result = "Only part of the request was completed"; + break; + + // + case TRADE_RETCODE_ERROR: + result = "Request processing error"; + break; + + // + case TRADE_RETCODE_TIMEOUT: + result = "Request canceled by timeout"; + break; + + // + case TRADE_RETCODE_INVALID: + result = "Invalid request"; + break; + + // + case TRADE_RETCODE_INVALID_VOLUME: + result = "Invalid volume in the request"; + break; + + // + case TRADE_RETCODE_INVALID_PRICE: + result = "Invalid price in the request"; + break; + + // + case TRADE_RETCODE_INVALID_STOPS: + result = "Invalid stops in the request"; + break; + + // + case TRADE_RETCODE_TRADE_DISABLED: + result = "Trade is disabled"; + break; + + // + case TRADE_RETCODE_MARKET_CLOSED: + result = "Market is closed"; + break; + + // + case TRADE_RETCODE_NO_MONEY: + result = "There is not enough money to complete the request"; + break; + + // + case TRADE_RETCODE_PRICE_CHANGED: + result = "Prices changed"; + break; + + // + case TRADE_RETCODE_PRICE_OFF: + result = "There are no quotes to process the request"; + break; + + // + case TRADE_RETCODE_INVALID_EXPIRATION: + result = "Invalid order expiration date in the request"; + break; + + // + case TRADE_RETCODE_ORDER_CHANGED: + result = "Order state changed"; + break; + + // + case TRADE_RETCODE_TOO_MANY_REQUESTS: + result = "Too frequent requests"; + break; + + // + case TRADE_RETCODE_NO_CHANGES: + result = "No changes in request"; + break; + + // + case TRADE_RETCODE_SERVER_DISABLES_AT: + result = "Autotrading disabled by server"; + break; + + // + case TRADE_RETCODE_CLIENT_DISABLES_AT: + result = "Autotrading disabled by client terminal"; + break; + + // + case TRADE_RETCODE_LOCKED: + result = "Request locked for processing"; + break; + + // + case TRADE_RETCODE_FROZEN: + result = "Order or position frozen"; + break; + + // + case TRADE_RETCODE_INVALID_FILL: + result = "Invalid order filling type"; + break; + + // + case TRADE_RETCODE_CONNECTION: + result = "No connection with the trade server"; + break; + + // + case TRADE_RETCODE_ONLY_REAL: + result = "Operation is allowed only for live accounts"; + break; + + // + case TRADE_RETCODE_LIMIT_ORDERS: + result = "The number of pending orders has reached the limit"; + break; + + // + case TRADE_RETCODE_LIMIT_VOLUME: + result = "The volume of orders and positions for the symbol has reached the limit"; + break; + + // + default: + result = "Invalid return code of the trade server"; + break; + } + + // + return result; + } + + // + // Protected ... + protected: + // + // Private ... + + // + bool CanLog() + { + return mLogAlerts; + } + + // + bool CanLogAlert() + { + // + bool result = GetEnableAlerts() && GetLogAlerts(); + + // + return result; + } + + // + bool CanTerminalAlert() + { + // + bool result = GetEnableAlerts() && GetTerminalAlerts(); + + // + return result; + } + + // + bool CanMailAlert() + { + // + bool result = GetEnableAlerts() && GetMailAlerts(); + + // + return result; + } + + // + bool CanPushAlert() + { + // + bool result = GetEnableAlerts() && GetPushAlerts(); + + // + return result; + } + + private: + // + // Props ... + string mPrefix; // Alerts Prefixe + bool mEnableAlerts; // Enable Alerts + bool mLogAlerts; // Log Alerts + bool mTerminalAlerts; // Terminal Alerts + bool mMailAlerts; // Mail Alerts + bool mPushAlerts; // Push Alerts + + // + // Tools ... + + // + // Clear Escape String and + // Attach Alert Prefix to Message ... + string PrepareMessage(string message) + { + // + StringReplace(message, "\n", " | "); + + // + StringConcatenate(message, GetPrefix(), " > ", message); + + // + return message; + } +}; + +// +// a Base Class by Support Alert ... +class 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 Alert(string message) + { + mAlert.Alert(message); + } + + // + // Logs ... + + // + // Log a Message ... + void Log(string message) + { + mAlert.Log(message); + } + void Log(string tag, string message) + { + mAlert.Log(tag, message); + } + void LogEmpty() + { + mAlert.LogEmpty(); + } + + // + // Log Specific Array ... + template + void LogArray( + T &array[], // Array to Log + string label = NULL // Array Label + ) + { + mAlert.LogArray(array, label); + } + + // + // Error ... + + // + // Log an Error ... + void LogError( + int error = -1 // Specific Error, if it's equal to -1, use Last Error ... + ) + { + mAlert.LogError(error); + } + + // + // Retrieve Specified Error Code Description ... + string GetErrorDescription(int err_code) + { + return mAlert.GetErrorDescription(err_code); + } + + // + // Retrieve Specified Error Code Description ... + string GetTradeServerReturnCodeDescription(int return_code) + { + return mAlert.GetTradeServerReturnCodeDescription(return_code); + } + + // + // Protected ... + protected: + // + // Alert ... + XCAlert *mAlert; + + // + // Private ... + private: +}; + +// \ No newline at end of file diff --git a/BKPS/14040218 XCAEA/Classes/x-saherelm.x-app-dialog.class.mq5 b/BKPS/14040218 XCAEA/Classes/x-saherelm.x-app-dialog.class.mq5 new file mode 100644 index 0000000..fc3de5e --- /dev/null +++ b/BKPS/14040218 XCAEA/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/14040218 XCAEA/Classes/x-saherelm.x-bar.analyser.class.mq5 b/BKPS/14040218 XCAEA/Classes/x-saherelm.x-bar.analyser.class.mq5 new file mode 100644 index 0000000..2008825 --- /dev/null +++ b/BKPS/14040218 XCAEA/Classes/x-saherelm.x-bar.analyser.class.mq5 @@ -0,0 +1,3018 @@ +/////////////////////////////////////////////////////// +// +// 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 ... + +// +// 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 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 ... + + /** + * 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; + } + + // + // Custom Logics ... + + /** + * 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 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 IsOrderBlock( + 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; + + // + int barIndex = bar.Index(); + int fvgLastBarIndex = barIndex + 3; + result = fvgLastBar.Init( + bar.symbol, + bar.period, + fvgLastBarIndex // + ); + result = + result && + fvgLastBar.GetPreviousBar(fvgLastBarPrev); + if (!result) + { + // + box.Clean(); + fvgLastBar.Clean(); + fvgLastBarPrev.Clean(); + + // + return result; + } + + // + // Check FVG Last Bar ... + + // + bool isBullishBlock = + isBullish && + fvgLastBar.IsBearish(); + + // + bool isBearishBlock = + isBearish && + fvgLastBar.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; + } + + // + // 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 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 ... + * + * @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 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 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 IsValidForPosition( + XOHCL &bar, + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + int loopback = 3; + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + // DOJI ... + ENUM_X_DIRECTION dojiDir; + bool isDoji = IsDoji( + bar, + dojiDir // + ); + bool isBullishDoji = + isDoji && + IsBullish(dojiDir); + bool isBearishDoji = + isDoji && + IsBearish(dojiDir); + + // + // SWING ... + ENUM_X_DIRECTION swingDir; + bool isSwing = IsSwing( + bar, + swingDir // + ); + bool isBullishSwing = + isSwing && + IsBullish(swingDir); + bool isBearishSwing = + isSwing && + IsBearish(swingDir); + + // + // HAMMER ... + ENUM_X_DIRECTION hammerDir; + bool isHammer = IsHammer( + bar, + hammerDir // + ); + bool isBullishHammer = + isHammer && + IsBullish(hammerDir); + bool isBearishHammer = + isHammer && + IsBearish(hammerDir); + + // + // ENGULF ... + ENUM_X_DIRECTION engulfDir; + bool isEngulfed = IsEngulfed( + bar, + engulfDir // + ); + bool isBullishEngulfed = + isEngulfed && + IsBullish(engulfDir); + bool isBearishEngulfed = + isEngulfed && + IsBearish(engulfDir); + + // + // REJECTED ... + ENUM_X_DIRECTION rejectedDir; + bool isRejected = IsRejected( + bar, + rejectedDir // + ); + bool isBullishRejected = + isRejected && + IsBullish(rejectedDir); + bool isBearishRejected = + isRejected && + IsBearish(rejectedDir); + + // + // MOMENTUM ... + ENUM_X_DIRECTION momentumDir; + bool isMomentum = IsMomentum( + bar, + momentumDir // + ); + bool isBullishMomentum = + isMomentum && + IsBullish(momentumDir); + bool isBearishMomentum = + isMomentum && + IsBearish(momentumDir); + + // + // PULLBACK ... + ENUM_X_DIRECTION pullbackDir; + bool isPullback = IsPullback( + bar, + pullbackDir // + ); + bool isBullishPullback = + isPullback && + IsBullish(pullbackDir); + bool isBearishPullback = + isPullback && + IsBearish(pullbackDir); + + // + // Summarize Conditions ... + + // + bool isBullishOr = + isBullishDoji || + isBullishSwing || + isBullishHammer || + isBullishEngulfed || + isBullishRejected || + isBullishMomentum || + isBullishPullback; + + // + bool isBearishOr = + isBearishDoji || + isBearishSwing || + isBearishHammer || + isBearishEngulfed || + isBearishRejected || + isBearishMomentum || + isBearishPullback; + + // + bool isBullish = + isBullishOr && + !isBearishOr; + + // + bool isBearish = + !isBullishOr && + isBearishOr; + + // + result = isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + return result; + } + + // + // Implement Some Custom Senarios ... + + /** + * 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; + } + + // + protected: + // + + // + private: + // + + // + // Props ... + + // + // Actions ... + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14040218 XCAEA/Classes/x-saherelm.x-cobject.class.mq5 b/BKPS/14040218 XCAEA/Classes/x-saherelm.x-cobject.class.mq5 new file mode 100644 index 0000000..0cac5cd --- /dev/null +++ b/BKPS/14040218 XCAEA/Classes/x-saherelm.x-cobject.class.mq5 @@ -0,0 +1,3178 @@ +/////////////////////////////////////////////////////// +// +// 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; +} + +// +// 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 // + ) + { + // + bool result = false; + + // + result = + // + bar.IsValid() && + IsValid(name) + // + ; + if (!result) + { + return result; + } + + // + datetime time = bar.time; + double price = bar.GetPrice(priceType); + + // + 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 ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + const int window, + XSignal &signal, + string prefix = NULL // + ) + { + // + bool result = false; + + // + 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) * 2); + 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], + time2, + signal.targets[i] // + ); + 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; +}; + +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/14040218 XCAEA/Classes/x-saherelm.x-expert.class.mq5 b/BKPS/14040218 XCAEA/Classes/x-saherelm.x-expert.class.mq5 new file mode 100644 index 0000000..db922b4 --- /dev/null +++ b/BKPS/14040218 XCAEA/Classes/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 ...."; + + // + Alert(message); + } + + // + // Initial All Requirements ... + result = InitEA(); + if (!result) + { + return result; + } + + // + // Initial All GUI Requirements ... + result = InitGUI(); + if (!result) + { + return result; + } + + // + message = "Initialized Successfully ..."; + Alert(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; + Alert(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 ..."; + + // + Alert(msg); + } + } + + // + // Weekly Report .... + if (mTimeTracker.IsNewWeek()) + { + // + HandleOnNewWeek(); + + // + if (mReportNewWeeks) + { + // + string msg = "New Week ..."; + + // + Alert(msg); + } + } + + // + // Daily Report .... + if (mTimeTracker.IsNewDay()) + { + // + HandleOnNewDay(); + + // + if (mReportNewDays) + { + // + string msg = "New Day ..."; + + // + Alert(msg); + } + } + + // + // Hourly Report .... + if (mTimeTracker.IsNewHour()) + { + // + HandleOnNewHour(); + + // + if (mReportNewHours) + { + // + string msg = "New Hour ..."; + + // + Alert(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/14040218 XCAEA/Classes/x-saherelm.x-helper.class.mq5 b/BKPS/14040218 XCAEA/Classes/x-saherelm.x-helper.class.mq5 new file mode 100644 index 0000000..945ba69 --- /dev/null +++ b/BKPS/14040218 XCAEA/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/14040218 XCAEA/Classes/x-saherelm.x-http.class.mq5 b/BKPS/14040218 XCAEA/Classes/x-saherelm.x-http.class.mq5 new file mode 100644 index 0000000..631532f --- /dev/null +++ b/BKPS/14040218 XCAEA/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/14040218 XCAEA/Classes/x-saherelm.x-md5.class.mq5 b/BKPS/14040218 XCAEA/Classes/x-saherelm.x-md5.class.mq5 new file mode 100644 index 0000000..e5cc201 --- /dev/null +++ b/BKPS/14040218 XCAEA/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/14040218 XCAEA/Classes/x-saherelm.x-poi.class.mq5 b/BKPS/14040218 XCAEA/Classes/x-saherelm.x-poi.class.mq5 new file mode 100644 index 0000000..d3338fa --- /dev/null +++ b/BKPS/14040218 XCAEA/Classes/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/14040218 XCAEA/Classes/x-saherelm.x-poi.drawer.class.mq5 b/BKPS/14040218 XCAEA/Classes/x-saherelm.x-poi.drawer.class.mq5 new file mode 100644 index 0000000..5a31af8 --- /dev/null +++ b/BKPS/14040218 XCAEA/Classes/x-saherelm.x-poi.drawer.class.mq5 @@ -0,0 +1,4356 @@ +/////////////////////////////////////////////////////// +// +// 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 ... +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 // + ) + { + // + bool result = false; + + // + object = NULL; + + // + 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, + 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/14040218 XCAEA/Classes/x-saherelm.x-rm.panel.class.mq5 b/BKPS/14040218 XCAEA/Classes/x-saherelm.x-rm.panel.class.mq5 new file mode 100644 index 0000000..d3808dc --- /dev/null +++ b/BKPS/14040218 XCAEA/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/14040218 XCAEA/Classes/x-saherelm.x-trade.class.mq5 b/BKPS/14040218 XCAEA/Classes/x-saherelm.x-trade.class.mq5 new file mode 100644 index 0000000..7bdd19f --- /dev/null +++ b/BKPS/14040218 XCAEA/Classes/x-saherelm.x-trade.class.mq5 @@ -0,0 +1,3934 @@ +/////////////////////////////////////////////////////// +// +// 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 ... + } + + // + // Handle Executing Support Signals ... + int supportsCount = ArraySize(mSignal.supports); + if (supportsCount > 0) + { + // + int executed = 0; + for (int i = 0; i < supportsCount; i++) + { + // + XSignal iSupport = mSignal.supports[i]; + + // + int supIndex = i + 1; + string iComment = GenerateSupportTag(ticket); + iSupport.comment = iComment; + + // + bool isExecuted = ExecuteSignal( + iSupport, + state, + lifetime, + expiration + // + ); + if (isExecuted) + { + executed++; + } + } + + // + result = executed == supportsCount; + } + } + + // + return result; + } + + // + // Execute a Collection Of Signals ... + int ExecuteSignals( + XSignal &signals[], // Collection of Signal for Execution + ENUM_X_SIGNAL_EXECUTION_RESULT &states[], // Signal Execution Result + ENUM_ORDER_TYPE_TIME lifetime = ORDER_TIME_GTC, // Order LifeTime + datetime expiration = NULL, // order expiration time + bool checkPolicies = true // Check Account Policies + ) + { + // + int result = 0; + + // + Clean(states); + + // + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return result; + } + + // + ArrayResize(states, signalsCount); + ArrayInitialize(states, X_SIGNAL_EXECUTION_UNKNOWN); + for (int i = 0; i < signalsCount; i++) + { + // + bool isExecuted = ExecuteSignal( + signals[i], + states[i], + lifetime, + expiration, + checkPolicies + // + ); + + // + if (isExecuted) + { + result++; + } + } + + // + return result; + } + + // + int ExecuteSpecifiedSignals( + XSignal &signals[], // Collection of Signal for Execution + XSignal ¬Executeds[], // Not Executed Signal + ENUM_X_SIGNAL_EXECUTION_RESULT &states[], // Signal Execution Result + ENUM_ORDER_TYPE_TIME lifetime = ORDER_TIME_GTC, // Order LifeTime + datetime expiration = NULL, // order expiration time + bool checkPolicies = true // Check Account Policies + ) + { + // + int result = 0; + + // + Clean(states); + Clean(notExecuteds); + + // + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return result; + } + + // + ArrayResize(states, signalsCount); + ArrayInitialize(states, X_SIGNAL_EXECUTION_UNKNOWN); + for (int i = 0; i < signalsCount; i++) + { + // + bool isExecuted = ExecuteSignal( + signals[i], + states[i], + lifetime, + expiration + // + ); + + // + if (isExecuted) + { + result++; + } + else + { + // + AddRef( + signals[i], + notExecuteds // + ); + } + } + + // + return result; + } + + // + // Regular Trade Actions ... + + // + // Buy ... + + // + // Force Open a Buy/Long Position ... + bool Buy( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // position volume + double price, // execution price + double sl = 0, // stop loss price + double tp = 0, // take profit price + string comment = NULL // comment + ) + { + // + bool result = false; + + // + ENUM_TIMEFRAMES mPeriod = ExtractPeriod(comment); + if (!IsValid(comment) || + !IsValid(mPeriod)) + { + // + string mPeriodStr = GeneratePeriodTag(period); + + // + comment += mPeriodStr; + } + + // + result = mTrader.Buy( + volume, + symbol, + price, + sl, + tp, + comment + // + ); + + // + return result; + } + + // + // Send BUY LIMIT order ... + bool BuyLimit( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // order volume + double price, // order price + double sl = 0.0, // stop loss price + double tp = 0.0, // take profit price + ENUM_ORDER_TYPE_TIME typeTime = ORDER_TIME_GTC, // order lifetime + datetime expiration = 0, // order expiration time + string comment = NULL // comment + ) + { + // + bool result = false; + + // + ENUM_TIMEFRAMES mPeriod = ExtractPeriod(comment); + if (!IsValid(comment) || + !IsValid(mPeriod)) + { + // + string mPeriodStr = GeneratePeriodTag(period); + + // + comment += mPeriodStr; + } + + // + result = mTrader.BuyLimit( + volume, + price, + symbol, + sl, + tp, + typeTime, + expiration, + comment + // + ); + + // + return result; + } + + // + // Send BUY STOP order ... + bool BuyStop( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // order volume + double price, // order price + double sl = 0.0, // stop loss price + double tp = 0.0, // take profit price + ENUM_ORDER_TYPE_TIME typeTime = ORDER_TIME_GTC, // order lifetime + datetime expiration = 0, // order expiration time + string comment = NULL // comment + ) + { + // + bool result = false; + + // + ENUM_TIMEFRAMES mPeriod = ExtractPeriod(comment); + if (!IsValid(comment) || + !IsValid(mPeriod)) + { + // + string mPeriodStr = GeneratePeriodTag(period); + + // + comment += mPeriodStr; + } + + // + result = mTrader.BuyStop( + volume, + price, + symbol, + sl, + tp, + typeTime, + expiration, + comment + // + ); + + // + return result; + } + + // + // Sell ... + + // + // Force Open a Sell/Short Position ... + bool Sell( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // position volume + double price, // execution price + double sl = 0, // stop loss price + double tp = 0, // take profit price + string comment = NULL // comment + ) + { + // + bool result = false; + + // + ENUM_TIMEFRAMES mPeriod = ExtractPeriod(comment); + if (!IsValid(comment) || + !IsValid(mPeriod)) + { + // + string mPeriodStr = GeneratePeriodTag(period); + + // + comment += mPeriodStr; + } + + // + result = mTrader.Sell( + volume, + symbol, + price, + sl, + tp, + comment + // + ); + + // + return result; + } + + // + // Send SELL LIMIT order ... + bool SellLimit( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // order volume + double price, // order price + double sl = 0.0, // stop loss price + double tp = 0.0, // take profit price + ENUM_ORDER_TYPE_TIME typeTime = ORDER_TIME_GTC, // order lifetime + datetime expiration = 0, // order expiration time + string comment = NULL // comment + ) + { + // + bool result = false; + + // + ENUM_TIMEFRAMES mPeriod = ExtractPeriod(comment); + if (!IsValid(comment) || + !IsValid(mPeriod)) + { + // + string mPeriodStr = GeneratePeriodTag(period); + + // + comment += mPeriodStr; + } + + // + result = mTrader.SellLimit( + volume, + price, + symbol, + sl, + tp, + typeTime, + expiration, + comment + // + ); + + // + return result; + } + + // + // Send SELL STOP order ... + bool SellStop( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // order volume + double price, // order price + double sl = 0.0, // stop loss price + double tp = 0.0, // take profit price + ENUM_ORDER_TYPE_TIME typeTime = ORDER_TIME_GTC, // order lifetime + datetime expiration = 0, // order expiration time + string comment = NULL // comment + ) + { + // + bool result = false; + + // + ENUM_TIMEFRAMES mPeriod = ExtractPeriod(comment); + if (!IsValid(comment) || + !IsValid(mPeriod)) + { + // + string mPeriodStr = GeneratePeriodTag(period); + + // + comment += mPeriodStr; + } + + // + result = mTrader.SellStop( + volume, + price, + symbol, + sl, + tp, + typeTime, + expiration, + comment + // + ); + + // + return result; + } + + // + // Check a Position is Exists Open or not ... + bool IsOpen( + ulong ticket // Specified Position Ticket + ) + { + // + bool result = false; + + // + result = mPositionInfo + .SelectByTicket(ticket); + + // + return result; + } + + // + // Modify Position ... + bool Modify( + const ulong ticket, // position ticket + double sl = 0, // stop loss price + double tp = 0, // take profit + string comment = NULL // comment + ) + { + // + bool result = false; + + // + // Validate Args ... + 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/14040218 XCAEA/Classes/x-saherelm.x-volume.class.mq5 b/BKPS/14040218 XCAEA/Classes/x-saherelm.x-volume.class.mq5 new file mode 100644 index 0000000..09720c3 --- /dev/null +++ b/BKPS/14040218 XCAEA/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/14040218 XCAEA/Documents/BKP/1/signallers.tmp.mq5 b/BKPS/14040218 XCAEA/Documents/BKP/1/signallers.tmp.mq5 new file mode 100644 index 0000000..f030068 --- /dev/null +++ b/BKPS/14040218 XCAEA/Documents/BKP/1/signallers.tmp.mq5 @@ -0,0 +1,124 @@ + // + // Parsing Pivots ... + + // + // Detect Selected Pivot ... + XBoxZone lastOSCPivot; + double providedSL = 0; + bool hasNewOSC = false; + bool hasPivots = HasChild(pivots); + if (hasPivots) + { + // + // Detect Selected Pivots ... + count = ArraySize(pivots); + for (int i = 0; i < count; i++) + { + // + XBoxZone iPivot = pivots[i]; + + // + // Detect Selected Last OSC Pivots ... + bool isOSC = + Contains( + "XCA_RSI", + iPivot.type // + ) || + Contains( + "XCA_CCI", + iPivot.type // + ); + bool canSetOSC = + !isOSC + ? false + : !lastOSCPivot.IsValid() + ? true + : lastOSCPivot.from < iPivot.from; + if (canSetOSC) + { + // + lastOSCPivot = iPivot; + + // + // Detect New OSC Pivot Happens ... + hasNewOSC = lastOSCPivot.IsValid() && + cBar.time == lastOSCPivot.to; + } + + // + // Check Pivot Box Type ... + bool isPVPivot = + Contains( + "XCA_PEAKSWHRES", + iPivot.type // + ) || + Contains( + "XCA_VALESWLSUP", + iPivot.type // + ); + if (isPVPivot) + { + // + // Select Box for OSC ... + if (hasNewOSC) + { + // + bool canSelectBox = + pivotBox.IsValid() + ? false + : lastOSCPivot.dir == iPivot.dir && + (IsBullish(iPivot.dir) + ? lastOSCPivot.upper > iPivot.upper && + lastOSCPivot.lower < iPivot.upper && + lastOSCPivot.lower <= iPivot.lower + : lastOSCPivot.lower < iPivot.lower && + lastOSCPivot.upper > iPivot.lower && + lastOSCPivot.upper >= iPivot.upper); + if (canSelectBox) + { + pivotBox = iPivot; + } + } + } + + // + iPivot.Clean(); + + // + } + } + + // + // Signaller Summarization ... + + // + // Cond1 Act Using PEAK VALE Box Activation or Rejection ... + + // + bool isCond1Bullish = + // + hasNewOSC && + (cVale < pVale || + pVale < p2Vale) && + pivotBox.IsValid() && + pivotBox.IsBullish() && + lastOSCPivot.IsBullish() && + conditions.isValeIsPivot + // + ; + + // + bool isCond1Bearish = + // + hasNewOSC && + (cPeak > pPeak || + pPeak > p2Peak) && + pivotBox.IsValid() && + pivotBox.IsBearish() && + lastOSCPivot.IsBearish() && + conditions.isPeakIsPivot + // + ; + +//////////////////////////////////////////////////////////////////// + diff --git a/BKPS/14040218 XCAEA/Documents/BKP/1/xcaea.signaller.class.mq5 b/BKPS/14040218 XCAEA/Documents/BKP/1/xcaea.signaller.class.mq5 new file mode 100644 index 0000000..71f8c5f --- /dev/null +++ b/BKPS/14040218 XCAEA/Documents/BKP/1/xcaea.signaller.class.mq5 @@ -0,0 +1,853 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XCXCAEASignaller ... +// Description: Class for XCAEA 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 Class for XCAEA Signaller" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.base.class.mq5" +#include "../../Classes/x-saherelm.x-cobject.class.mq5" +#include "../Classes/xcaea.x-poi.detector.class.mq5" +#include "../Classes/xcaea.x-poi.drawer.class.mq5" +#include "../Helpers/xcaea.helper.mq5" +#include "../Libraries/xcaea.signaller.lib.mq5" + +// +// Definitions ... + +class XCXCAEASignaller : XCBase +{ + // + // Public ... + public: + // + // Props ... + bool useGuards; + XCAEAInputs inputs; + XBarTracker barTraker; + XCXCAEAHelper *helper; + XCXCAEAPOIDrawer *drawer; + bool continuesRFTillTarget; + XBoxZone unAvailableBoxes[]; + XCXCAEAPOIDetector *detector; + XCAEAStrategyConditions mConditions; + XCAEAStrategyConditions mConditionsCollection[]; + + // + // Constructor ... + XCXCAEASignaller( + string _symbol, + ENUM_TIMEFRAMES _period // + ) + { + // + symbol = _symbol; + period = _period; + + // + Init(); + } + + // + // Deconstructor ... + ~XCXCAEASignaller() + { + DeInit(); + } + + // + // Properties ... + + string GetSymbol() + { + return symbol; + } + + ENUM_TIMEFRAMES GetPeriod() + { + return period; + } + + // + // Signaller 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( + double tpReward = 3, + double maxAllowedSLDistanceInPoint = 100 // + ) + { + // + bool result = false; + + // + // Check Bar Processing ... + if (!barTraker.CanProcessBar()) + { + return result; + } + + // + bool isBullish = false; + bool isBearish = false; + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + int loopback = 10; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + double points = GetPoints(symbol); + + // + XOHCL zBar; + XOHCL cBar; + XOHCL pBar; + XOHCL pPBar; + result = zBar.Init( + symbol, + period, + zIndex // + ); + result = + result && + zBar.GetPreviousBar(cBar); + result = + result && + cBar.GetPreviousBar(pBar); + result = + result && + pBar.GetPreviousBar(pPBar); + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + pPBar.Clean(); + + // + return result; + } + + // + // Setup Conditions ... + XBoxZone boxes[]; + XBoxZone pivotBox; + XBoxZone signalBox; + double additionalSL = 0; + XBoxZone bullishBoxes[]; + XBoxZone bearishBoxes[]; + bool hasSignalBox = false; + XCAEAConditions conditions; + ENUM_X_DIRECTION signalBoxDir = X_DIRECTION_NONE; + + // + // Detecting Pivots ... + detector.Update( + zIndex // + ); + + // + // Validate Pivots ... + detector.Validate( + unAvailableBoxes, + zIndex // + ); + + // + // Draw Founded Pivots ... + drawer.Draw(cTime); + + // + // Retrieve Valid Boxes ... + + // // + // // Bullish ... + // int bullishBoxesCount = + // detector + // .FillBullishBoxes(bullishBoxes); + + // // + // // Bearish ... + // int bearishBoxesCount = + // detector + // .FillBearishBoxes(bearishBoxes); + + // // + // Copy( + // bullishBoxes, + // boxes, + // false // + // ); + // Copy( + // bearishBoxes, + // boxes, + // false // + // ); + int boxesCount = ArraySize(boxes); + bool hasBoxes = IsValidSize(boxesCount); + + // + // Filter UnAvailable Boxes ... + if (hasBoxes) + { + // + // Remove UnAvailable Boxes ... + has = HasChild(unAvailableBoxes); + if (has) + { + // + count = ArraySize(unAvailableBoxes); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = unAvailableBoxes[i]; + + // + has = FindBoxIndex( + idx, + iBox, + boxes // + ); + if (has) + { + // + ArrayRemove( + boxes, + idx, + 1 // + ); + } + } + } + + // + hasBoxes = HasChild(boxes); + boxesCount = ArraySize(boxes); + } + + // + // + // + + // + // if (hasBoxes) + // { + // } + + // + // Detect Sinal Box ... + hasSignalBox = DetectXCAEAConditions( + boxes, + conditions, + pivotBox, + signalBox, + additionalSL, + signalBoxDir, + helper, + zIndex, + loopback // + ); + + // + // Make Pivot Box UnAvailable ... + if (pivotBox.IsValid()) + { + // + AddRef( + pivotBox, + unAvailableBoxes // + ); + } + + // + isBullish = hasSignalBox && + IsBullish(signalBoxDir); + + // + isBearish = hasSignalBox && + IsBearish(signalBoxDir); + + // + result = isBullish || + isBearish; + if (result) + { + // + // Do What we Want ... + barTraker.Waits(); + + // + // Draw Signal Box ... + XCBoxObject *iObj; + bool isCreated = helper.poiDrawer.DrawBox( + signalBox, + iObj // + ); + if (isCreated) + { + // + mObjects.Add(iObj); + ZeroMemory(iObj); + + // + Print("Signal Box ..."); + } + + // + // Prepare Conditions ... + mConditions.symbol = symbol; + mConditions.period = period; + + // + double spread = GetSpread(symbol); + + // + double entry = + isBullish + ? signalBox.upper + : signalBox.lower; + + // + double sl = + isBullish + ? signalBox.lower + : signalBox.upper; + if (additionalSL > 0) + { + // + sl = + isBullish + ? sl - additionalSL + : sl + additionalSL; + } + + // + double risk = + isBullish + ? entry - sl + : sl - entry; + risk += spread; + if (risk >= maxAllowedSLDistanceInPoint * points) + { + // + // Fix Risk in Big Distances ... + double hh5 = zBar.FindHighest(5, MODE_HIGH); + double ll5 = zBar.FindLowest(5, MODE_LOW); + + // + double hhll5Delta = hh5 - ll5; + double riskDelta = hhll5Delta / 2; + risk = riskDelta; + } + + // + double rewardTP = risk * tpReward; + + // + double tp = + isBullish + ? entry + rewardTP + : entry - rewardTP; + + // + // Filling ... + mConditions.sl = sl; + mConditions.tp = tp; + mConditions.pivot = + isBullish + ? sl + : entry; + mConditions.point = + isBullish + ? entry + : sl; + mConditions.dir = signalBoxDir; + mConditions.provider = "XCAEA"; + mConditions.signalBox = signalBox; + mConditions.setupTime = zBar.time; + mConditions.conditions = conditions; + + // + // Select RF Rewards ... + if (continuesRFTillTarget) + { + // + double rfReward = 1; + while (rfReward < tpReward) + { + // + double rewardRF = risk * rfReward; + double rfTP = + isBullish + ? entry + rewardRF + : entry - rewardRF; + + // + Add( + rfTP, + mConditions.targets // + ); + + // + rfReward++; + } + } + else + { + // + double rfReward = 1; + + // + double rewardRF = risk * rfReward; + double rfTP = + isBullish + ? entry + rewardRF + : entry - rewardRF; + + // + Add( + rfTP, + mConditions.targets // + ); + } + } + + // + // Cleanup Resource ... + + // + Clean(boxes); + Clean(bullishBoxes); + Clean(bearishBoxes); + + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + pPBar.Clean(); + + // + pivotBox.Clean(); + signalBox.Clean(); + conditions.Clean(); + + // + return result; + } + + /** + * Detect Trigger Conditions for Specified Signal ... + * + * @param conditions: XCAEAStrategyConditions instance Reference, Specified Signal Conditions ... + * @param maxAllowedSetupAge: specified Setup Age for Expiration (if bigger than Zero) ... + * + * @return ( bool ) + */ + bool DetectSignalTrigger( + XCAEAStrategyConditions &conditions, + int maxAllowedSetupAge = 60 // + ) + { + // + bool result = false; + + // + result = conditions.IsSetuped(); + if (!result) + { + return result; + } + + // + datetime setupTime = conditions.setupTime; + ENUM_X_DIRECTION setupDir = conditions.dir; + + // + bool isBullish = IsBullish(setupDir); + bool isBearish = IsBearish(setupDir); + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + int loopback = 10; + + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + double points = GetPoints(symbol); + + // + // Check Signal Validation ... + // IMPORTANT: since all Validations done in SetUp Process ... + // here we only Execute Signal ... + + // + result = isBullish || + isBearish; + + // + if (result) + { + // + conditions.triggerTime = cTime; + conditions.type = isBullish + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_SHORT; + + // + } + + // + // Cleanup ... + + // + 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( + XCAEAGuard &guards[], + const XPosition &positions[] // + ) + { + // + bool result = false; + + // + return result; + } + + /** + * Add Conditions to Conditions Collection if not Exists ... + * + * @param maxAllowed: int, Specified Max Allowed Holding Conditions ... + * + * @return ( int ) + */ + int AddConditionsIfNotExists( + int maxAllowed = 10 // + ) + { + // + int result = 0; + + // + bool isSetuped = IsValid(mConditions.setupTime) && + HasDirection(mConditions.dir); + if (!isSetuped) + { + return result; + } + + // + int count = ArraySize(mConditionsCollection); + if (IsValidSize(count)) + { + // + // Copy Original Items ... + XCAEAStrategyConditions tmpItems[]; + Copy( + mConditionsCollection, + tmpItems // + ); + + // + // Prese Item Data ... + bool isBullish = IsBullish(mConditions.dir); + + // + for (int i = 0; i < count; i++) + { + // + XCAEAStrategyConditions 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; + } + + // + // Protected ... + protected: + // + + // + // Private ... + private: + // + // Props ... + string symbol; + ENUM_TIMEFRAMES period; + CArrayObj mObjects; + CArrayObj mBarObjects; + + /** + * Initialize ... + */ + void Init() + { + // + useGuards = false; + continuesRFTillTarget = true; + + // + barTraker.Init( + symbol, + period // + ); + + // + inputs.Default(); + + // + // Configure Indicators ... + + // + // XCC ... + inputs.ccInputs.showCandles = true; + + // + // XCT ... + inputs.ctInputs.showCandleTime = true; + + // + // XCA ... + + // + inputs.caInputs.supResSmoothingLength = 7; + inputs.caInputs.supResSmoothingMode = X_MA_MODE_NONE; + + // + inputs.caInputs.showKI = true; + inputs.caInputs.showTKI = false; + inputs.caInputs.showSar = false; + inputs.caInputs.showVidya = true; + inputs.caInputs.showTrend = false; + inputs.caInputs.showSwings = false; + inputs.caInputs.showLongCycle = false; + inputs.caInputs.showHindCycle = false; + inputs.caInputs.showFiboLevel1 = false; + inputs.caInputs.showFiboLevel2 = false; + inputs.caInputs.showFiboLevel3 = false; + inputs.caInputs.showShortCycle = false; + inputs.caInputs.showMediumCycle = false; + inputs.caInputs.showPeaksAndVales = true; + inputs.caInputs.showPeakAndValeGolden = false; + inputs.caInputs.showSupportAndResistance = false; + + // + // XOSCS ... + // inputs.oscsInputs.rsiLength = 5; + // inputs.oscsInputs.cciLength = 5; + // inputs.oscsInputs.mfiLength = 5; + // inputs.oscsInputs.rviLength = 5; + + // + // Oscillators Views ... + inputs.showCCI = false; + inputs.showRSI = false; + inputs.showMFI = false; + inputs.showRVI = false; + inputs.showADX = false; + inputs.showMACD = false; + + // + // XCAEA Helper ... + helper = new XCXCAEAHelper(); + helper.Init( + symbol, + period, + inputs // + ); + + // + // Initialize and Configure Detector ... + detector = new XCXCAEAPOIDetector(helper); + + // + // Configure Detector ... + detector.detectRSIPeakPivots = true; + detector.detectRSIValePivots = true; + detector.detectCCIPeakPivots = true; + detector.detectCCIValePivots = true; + detector.detectFVGBullishPivots = true; + detector.detectFVGBearishPivots = true; + detector.detectValeSupSWLPivots = true; + detector.detectPeakResSWHPivots = true; + detector.detectPVFVGBullishPivots = true; + detector.detectPVFVGBearishPivots = true; + + // + // Initialize and Configure Drawer ... + drawer = new XCXCAEAPOIDrawer(detector); + + // + drawer.ignoreUpdateOSCTos = true; + + // + // Configure Drawer ... + drawer.drawRSIPeakPivots = true; + drawer.drawRSIValePivots = true; + drawer.drawCCIPeakPivots = true; + drawer.drawCCIValePivots = true; + drawer.drawFVGBullishPivots = false; + drawer.drawFVGBearishPivots = false; + drawer.drawValeSupSWLPivots = true; + drawer.drawPeakResSWHPivots = true; + drawer.drawPVFVGBullishPivots = true; + drawer.drawPVFVGBearishPivots = true; + + // + // Configure Widths ... + drawer.rsiPeakPivotsWidth = 4; + drawer.rsiValePivotsWidth = 4; + drawer.cciPeakPivotsWidth = 4; + drawer.cciValePivotsWidth = 4; + drawer.fvgBullishPivotsWidth = 2; + drawer.fvgBearishPivotsWidth = 2; + drawer.valeSupSWLPivotsWidth = 1; + drawer.peakResSWHPivotsWidth = 1; + drawer.pvFVGBullishPivotsWidth = 1; + drawer.pvFVGBearishPivotsWidth = 1; + + // + // Configure Colors ... + drawer.rsiPeakPivotsColor = clrMagenta; + drawer.rsiValePivotsColor = clrAqua; + drawer.cciPeakPivotsColor = clrMagenta; + drawer.cciValePivotsColor = clrAqua; + drawer.fvgBullishPivotsColor = clrLime; + drawer.fvgBearishPivotsColor = clrRed; + drawer.valeSupSWLPivotsColor = clrAqua; + drawer.peakResSWHPivotsColor = clrMagenta; + drawer.pvFVGBullishPivotsColor = clrLime; + drawer.pvFVGBearishPivotsColor = clrRed; + + // + // Configures Styles ... + drawer.rsiPeakPivotsStyle = STYLE_DASH; + drawer.rsiValePivotsStyle = STYLE_DASH; + drawer.cciPeakPivotsStyle = STYLE_DASH; + drawer.cciValePivotsStyle = STYLE_DASH; + drawer.fvgBullishPivotsStyle = STYLE_DASHDOTDOT; + drawer.fvgBearishPivotsStyle = STYLE_DASHDOTDOT; + drawer.valeSupSWLPivotsStyle = STYLE_SOLID; + drawer.peakResSWHPivotsStyle = STYLE_SOLID; + drawer.pvFVGBullishPivotsStyle = STYLE_DASHDOTDOT; + drawer.pvFVGBearishPivotsStyle = STYLE_DASHDOTDOT; + + // + } + + /** + * DeInitialize ... + */ + void DeInit() + { + // + inputs.Clean(); + + // + ZeroMemory(drawer); + ZeroMemory(helper); + ZeroMemory(detector); + + // + mConditions.Clean(); + Clean(mConditionsCollection); + + // + mObjects.Clear(); + mBarObjects.Clear(); + + // + barTraker.Clean(); + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14040218 XCAEA/Documents/BKP/1/xcaea.signaller.lib.mq5 b/BKPS/14040218 XCAEA/Documents/BKP/1/xcaea.signaller.lib.mq5 new file mode 100644 index 0000000..cd29c16 --- /dev/null +++ b/BKPS/14040218 XCAEA/Documents/BKP/1/xcaea.signaller.lib.mq5 @@ -0,0 +1,1334 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XCAEASignaller Lib +// Description: Library for XCAEA 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 Library for XCAEA Signaller" +#property strict + +// +// Imports ... +#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/xcaea.x-poi.detector.class.mq5" +#include "../Helpers/xcaea.helper.mq5" + +// +// Enumeration ... + +// +// Guard Actions ... +enum ENUM_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_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 ... + +// +// Conditions Struct ... +struct XCAEAStrategyConditions +{ + // + // Props ... + + // + string symbol; + ENUM_TIMEFRAMES period; + + // + // Setup Props ... + + // + double sl; + double tp; + double pivot; + double point; + string provider; + double targets[]; + + // + datetime time; + datetime setupTime; + datetime triggerTime; + + // + XBoxZone signalBox; + ENUM_X_DIRECTION dir; + ENUM_X_POSITION_TYPES type; + XCAEAConditions conditions; + + // + // Constructor ... + XCAEAStrategyConditions() + { + Default(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + sl = 0; + tp = 0; + pivot = 0; + point = 0; + + // + symbol = NULL; + period = NULL; + provider = NULL; + + // + time = NULL; + setupTime = NULL; + triggerTime = NULL; + + // + Clean(targets); + + // + signalBox.Clean(); + conditions.Clean(); + + // + dir = X_DIRECTION_NONE; + type = X_POSITION_TYPE_NONE; + + // + ZeroMemory(this); + } + + /** + * Default ... + */ + void Default() + { + // + sl = 0; + tp = 0; + pivot = 0; + point = 0; + + // + symbol = NULL; + period = NULL; + provider = NULL; + + // + time = NULL; + setupTime = NULL; + triggerTime = NULL; + + // + Clean(targets); + + // + signalBox.Clean(); + conditions.Clean(); + + // + dir = X_DIRECTION_NONE; + type = X_POSITION_TYPE_NONE; + } + + // + // 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; + } + + // +}; + +// +// Model a Guard Action ... +struct XCAEAGuard +{ + // + // Props ... + ENUM_GUARD_ACTIONS action; + datetime time; + + // + string symbol; + string provider; + + // + // Specified Position ... + ulong ticket; + + // + // Partial Close ... + double volumeMultiplier; + + // + // SL Trial ... + double sl; + + // + // TP Trial ... + double tp; + + // + // Constructor ... + XCAEAGuard() + { + Default(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + time = NULL; + action = X_GUARD_ACTION_NONE; + + // + symbol = NULL; + provider = NULL; + + // + ticket = 0; + + // + volumeMultiplier = 0; + + // + sl = 0; + tp = 0; + + // + ZeroMemory(this); + } + + /** + * Default ... + */ + void Default() { + // + time = NULL; + action = X_GUARD_ACTION_NONE; + + // + symbol = NULL; + provider = NULL; + + // + ticket = 0; + + // + volumeMultiplier = 0; + + // + sl = 0; + tp = 0; + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsValid(time) && + IsValid(symbol) && + IsValid(provider) && + action != X_GUARD_ACTION_NONE + // + ; + if (!result) + { + return result; + } + + // + // Validate Model Based On Specified Guard Actions ... + + // + return result; + } +}; + +/** + * Add Guard to Collection ... + * + * @param guard: XCAEAGuard instance ... + * @param guards: XCAEAGuard instance Collection ... + * + * @return ( int ) + */ +int AddGuard( + XCAEAGuard &guard, + XCAEAGuard &guards[] // +) +{ + // + int result = 0; + + // + if (!guard.IsValid()) + { + return result; + } + + // + AddRef( + guard, + guards // + ); + + // + result = ArraySize(guards); + + // + return result; +} + +// +bool DetectXCAEAConditions( + XBoxZone &boxes[], + XCAEAConditions &conditions, + XBoxZone &pivotBox, + XBoxZone &box, + double &additionalSL, + ENUM_X_DIRECTION &dir, + XCXCAEAHelper *helper, + int barIndex = 0, + int loopback = 10 // +) +{ + // + bool result = false; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + box.Clean(); + additionalSL = 0; + conditions.Clean(); + dir = X_DIRECTION_NONE; + + // + if (barIndex < 0) + { + barIndex = 0; + } + loopback = NormalizeInt(loopback, 5); + + // + string symbol = helper.GetSymbol(); + ENUM_TIMEFRAMES period = helper.GetPeriod(); + double points = GetPoints(symbol); + + // + XCAEAConditions pConditions; + result = helper.GetConditions( + conditions, + barIndex, + loopback // + ); + result = result && + helper.GetConditions( + pConditions, + barIndex + 1, + loopback // + ); + if (!result) + { + // + conditions.Clean(); + pConditions.Clean(); + + // + return result; + } + + // + int zIDX = barIndex; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + int p3IDX = p2IDX + 1; + int p4IDX = p3IDX + 1; + + // + // Reading Parameters ... + + // + // 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]; + + // + // 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]; + + // + // TREND ... + + // + double cTrend = conditions.trendBuffer[cIDX]; + double pTrend = conditions.trendBuffer[pIDX]; + double p2Trend = conditions.trendBuffer[p2IDX]; + + // + double ctrendState = conditions.trendStateBuffer[cIDX]; + double ptrendState = conditions.trendStateBuffer[pIDX]; + double p2trendState = conditions.trendStateBuffer[p2IDX]; + + // + // SWING Low ... + double cSWL = conditions.swingLowBuffer[cIDX]; + double pSWL = conditions.swingLowBuffer[pIDX]; + double p2SWL = conditions.swingLowBuffer[p2IDX]; + + // + // SWING High ... + double cSWH = conditions.swingHighBuffer[cIDX]; + double pSWH = conditions.swingHighBuffer[pIDX]; + double p2SWH = conditions.swingHighBuffer[p2IDX]; + + // + // PEAK ... + 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]; + + // + // VALE ... + 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]; + + // + // VIDYA ... + double zVidya = conditions.vidyaBuffer[zIDX]; + double cVidya = conditions.vidyaBuffer[cIDX]; + double pVidya = conditions.vidyaBuffer[pIDX]; + double p2Vidya = conditions.vidyaBuffer[p2IDX]; + double p3Vidya = conditions.vidyaBuffer[p3IDX]; + + // + double zVidyaState = conditions.vidyaStateBuffer[zIDX]; + double cVidyaState = conditions.vidyaStateBuffer[cIDX]; + double pVidyaState = conditions.vidyaStateBuffer[pIDX]; + double p2VidyaState = conditions.vidyaStateBuffer[p2IDX]; + double p3VidyaState = conditions.vidyaStateBuffer[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]; + + // + // CCI ... + double zCCI = conditions.cciBuffer[zIDX]; + double cCCI = conditions.cciBuffer[cIDX]; + double pCCI = conditions.cciBuffer[pIDX]; + double p2CCI = conditions.cciBuffer[p2IDX]; + double p3CCI = conditions.cciBuffer[p3IDX]; + + // + // RVI ... + + // + double zRVI = conditions.rviBuffer[zIDX]; + double cRVI = conditions.rviBuffer[cIDX]; + double pRVI = conditions.rviBuffer[pIDX]; + double p2RVI = conditions.rviBuffer[p2IDX]; + double p3RVI = conditions.rviBuffer[p3IDX]; + + // + double zRVISignal = conditions.rviSignalBuffer[zIDX]; + double cRVISignal = conditions.rviSignalBuffer[cIDX]; + double pRVISignal = conditions.rviSignalBuffer[pIDX]; + double p2RVISignal = conditions.rviSignalBuffer[p2IDX]; + double p3RVISignal = conditions.rviSignalBuffer[p3IDX]; + + // + // Reading Bars ... + + // + XOHCL zBar; + XOHCL cBar; + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + XOHCL p4Bar; + result = zBar.Init( + symbol, + period, + zIDX // + ); + result = + result && + zBar.GetPreviousBar(cBar); + result = + result && + cBar.GetPreviousBar(pBar); + result = + result && + pBar.GetPreviousBar(p2Bar); + result = + result && + p2Bar.GetPreviousBar(p3Bar); + result = + result && + p3Bar.GetPreviousBar(p4Bar); + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + box.Clean(); + conditions.Clean(); + pConditions.Clean(); + + // + return result; + } + + // + // Bars Conditions ... + + // + ENUM_X_DIRECTION cBarDir; + + // + // Hammer ... + bool isCBarHammer = helper + .barAnalyser + .IsHammer( + cBar, + cBarDir // + ); + bool isCBarBullishHammer = + isCBarHammer && + IsBullish(cBarDir); + bool isCBarBearishHammer = + isCBarHammer && + IsBearish(cBarDir); + + // + // Rejected ... + bool isCBarRejected = helper + .barAnalyser + .IsRejected( + cBar, + cBarDir, + false, // Force Type ... + true // Force Fibo Pressure ... + ); + bool isCBarBullishRejected = + isCBarRejected && + IsBullish(cBarDir); + bool isCBarBearishRejected = + isCBarRejected && + IsBearish(cBarDir); + + // + // Engulfed ... + bool isCBarEngulfed = helper + .barAnalyser + .IsEngulfed( + cBar, + cBarDir // + ); + bool isCBarBullishEngulfed = + isCBarEngulfed && + IsBullish(cBarDir); + bool isCBarBearishEngulfed = + isCBarEngulfed && + IsBearish(cBarDir); + + // + // Momentum ... + bool isCBarMomentum = helper + .barAnalyser + .IsMomentum( + cBar, + cBarDir, + 1 // + ); + bool isCBarBullishMomentum = + isCBarMomentum && + IsBullish(cBarDir); + bool isCBarBearishMomentum = + isCBarMomentum && + IsBearish(cBarDir); + + // + // Bar Sumarise ... + + // + bool isCBarValidForBullish = + (isCBarBullishHammer || + isCBarBullishRejected || + isCBarBullishMomentum || + isCBarBullishEngulfed); + + // + bool isCBarValidForBearish = + (isCBarBearishHammer || + isCBarBearishRejected || + isCBarBearishMomentum || + isCBarBearishEngulfed); + + // + // Score ... + + // + double bullishScore = 0; + double bearishScore = 0; + conditions.GenerateScore( + bullishScore, + bearishScore // + ); + + // + bool isScoreBullish = + bullishScore > bearishScore; + + // + bool isScoreBearish = + bearishScore > bullishScore; + + // + string summary = + conditions + .GenerateSummary(); + + // + // Conditions ... + + // + bool isRSIBullish = + zRSI >= cRSI && + cRSI > pRSI; + bool isRSIBearish = + zRSI <= cRSI && + cRSI < pRSI; + + // + bool isCCIBullish = + zCCI >= cCCI && + cCCI > pCCI && + (zCCI > conditions.cciOSLevel || + cCCI > conditions.cciOSLevel); + bool isCCIBearish = + zCCI >= cCCI && + cCCI > pCCI && + (zCCI < conditions.cciOBLevel || + cCCI < conditions.cciOBLevel); + + // + // Detect Selected Box ... + XBoxZone oscBoxes[]; + XBoxZone lastOSCBox; + double providedSL = 0; + bool isBoxFVG = false; + bool hasOSCBox = false; + bool hasPivotBox = false; + bool isBoxPeakVale = false; + bool isBoxRejected = false; + bool isBoxActivated = false; + bool isBoxFullSifeRejected = false; + bool hasBoxes = HasChild(boxes); + if (hasBoxes) + { + // + // Detect Selected Boxes ... + XBoxZone tmp[]; + Copy( + boxes, + tmp // + ); + while (HasChild(tmp)) + { + // + idx = GetYoungest(tmp); + has = IsValidIndex(idx); + if (!has) + { + break; + } + + // + XBoxZone iBox; + iBox = tmp[idx]; + ArrayRemove( + tmp, + idx, + 1 // + ); + + // + // Check Selected Box not RSI or CCI ... + isBoxFVG = Contains( + "XCA_FVG", + iBox.type // + ); + isBoxPeakVale = + Contains( + "XCA_PEAKSWHRES", + iBox.type // + ) || + Contains( + "XCA_VALESWLSUP", + iBox.type // + ); + has = isBoxFVG || + isBoxPeakVale; + if (!has) + { + // + bool isOSC = Contains( + "XCA_CCI_VALE", + iBox.type // + ) || + Contains( + "XCA_CCI_PEAK", + iBox.type // + ) || + Contains( + "XCA_RSI_VALE", + iBox.type // + ) || + Contains( + "XCA_RSI_PEAK", + iBox.type // + ); + if (isOSC) + { + // + AddRef( + iBox, + oscBoxes // + ); + } + + // + iBox.Clean(); + + // + continue; + } + + // + bool isBullish = iBox.IsBullish(); + bool isBearish = iBox.IsBearish(); + + // + double rejectedCheckPrice = + isBullish + ? iBox.upper + : iBox.lower; + double rejectedFullCheckPrice = + isBullish + ? iBox.lower + : iBox.upper; + + // + // Check Box Selecting Senarios ... + + // + // Selecting Rejected Boxes ... + isBoxRejected = cBar.IsRejected( + rejectedCheckPrice, + iBox.dir, + false, + false // + ); + + // + // Selecting Rejected Boxes ... + isBoxFullSifeRejected = cBar.IsRejected( + rejectedFullCheckPrice, + iBox.dir, + false, + false // + ); + + // + // Selecting Activation Boxes ... + + // + bool isBullishActivated = + isBullish && + cBar.IsBullish() && + cBar.GetUp() > rejectedCheckPrice && + cBar.GetDown() < rejectedCheckPrice; + + // + bool isBearishActivated = + isBearish && + cBar.IsBearish() && + cBar.GetUp() > rejectedCheckPrice && + cBar.GetDown() < rejectedCheckPrice; + + // + isBoxActivated = isBullishActivated || + isBearishActivated; + + // + // Detect Box is Selected or not ... + has = + isBoxRejected || + isBoxActivated || + isBoxFullSifeRejected; + if (has) + { + // + pivotBox = iBox; + + // + iBox.Clean(); + break; + } + + // + iBox.Clean(); + } + + // + Clean(tmp); + } + + // + // Check OSC Boxes ... + bool hasOSCBoxes = HasChild(oscBoxes); + if (hasOSCBoxes) + { + // + // Detect Newest OSC Box ... + idx = GetYoungest(oscBoxes); + has = IsValidIndex(idx); + if (has) + { + lastOSCBox = oscBoxes[idx]; + } + + // + // Validate OSC Box is Valid or not ... + has = lastOSCBox.IsValid(); + if (has) + { + // + // Check Bar is Inside OSC Box or not ... + has = cBar.time > lastOSCBox.from && + cBar.time <= lastOSCBox.to; + if (!has) + { + lastOSCBox.Clean(); + } + } + + // + hasOSCBox = lastOSCBox.IsValid(); + if (hasOSCBox) + { + // // + // XCBoxObject *iObj; + // has = helper.poiDrawer.DrawBox( + // lastOSCBox, + // iObj // + // ); + // if (has) { + // iObj.BoxWidth(4); + // } + } + } + + // + // Force Conditions to Have Selected Box ... + hasPivotBox = hasBoxes && + pivotBox.IsValid(); + if (hasPivotBox) + { + // // + // pivotBox.to = TimeCurrent(); + + // // + // // Draw Pivot Box Here ... + // if (isBoxPeakVale) + // { + // // + // XCBoxObject *iObj; + // has = helper.poiDrawer.DrawBox( + // pivotBox, + // iObj // + // ); + // if (has) + // { + // // + // iObj.BoxWidth(5); + // iObj.BoxColor(clrDodgerBlue); + // Print("Draw Pivot Box ..."); + // } + // } + } + + // + // If all Conditions required Boxes ... + // if (!result) + // { + // // + // zBar.Clean(); + // cBar.Clean(); + // pBar.Clean(); + // p2Bar.Clean(); + // p3Bar.Clean(); + // p4Bar.Clean(); + + // // + // box.Clean(); + // pivotBox.Clean(); + // conditions.Clean(); + + // // + // return result; + // } + + // + // Signaller Summarization ... + + // + // Cond1 Act Using PEAK VALE Box Activation or Rejection ... + + // + bool isCond1Bullish = + // + false && + hasPivotBox && + isBoxPeakVale && + isScoreBullish && + pivotBox.IsBullish() && + (conditions.isValeUnderLast || + (conditions.isValeSameLast && + pConditions.isValeUnderLast)) && + conditions.isRSICrossedOverOS && + conditions.isCCICrossedOverOS + // + ; + + // + bool isCond1Bearish = + // + false && + hasPivotBox && + isBoxPeakVale && + isScoreBearish && + pivotBox.IsBearish() && + (conditions.isPeakOverLast || + (conditions.isPeakSameLast && + pConditions.isPeakOverLast)) && + conditions.isRSICrossedUnderOB && + conditions.isCCICrossedUnderOB + // + ; + + // + bool isCond1 = isCond1Bullish || + isCond1Bearish; + if (isCond1) + { + // + providedSL = + isCond1Bullish + ? MathMin(pBar.low, pivotBox.lower) + : MathMax(pBar.high, pivotBox.upper); + + // + additionalSL = 0.5 * conditions.atrBuffer[cIDX]; + + // + Print("Cond1"); + } + + // + // Cond2 Act Using OSC Box and Vydia ... + + // + bool isCond2Bullish = + // + hasOSCBox && + // cVidyaState < 0 && + lastOSCBox.IsBullish() // && + // lastOSCBox.upper < cVidya + // + ; + + // + bool isCond2Bearish = + // + hasOSCBox && + // cVidyaState > 0 && + lastOSCBox.IsBearish() // && + // lastOSCBox.lower > cVidya + // + ; + + // + bool isCond2 = isCond2Bullish || + isCond2Bearish; + if (isCond2) + { + // + providedSL = + isCond1Bullish + ? MathMin(pBar.low, pivotBox.lower) + : MathMax(pBar.high, pivotBox.upper); + + // + Print("Cond2"); + isCond2Bullish = false; + isCond2Bearish = false; + } + + // + // Cond3 Act Using CCi Peaks and Vales ... + + // + bool isCond3Bullish = false; + + // + bool isCond3Bearish = false; + + // + bool isCond3 = isCond3Bullish || + isCond3Bearish; + if (isCond3) + { + // + + // + Print("Cond3"); + } + + // + // Summarise Conditions ... + + // + bool isBullish = + // + isCond1Bullish || + isCond2Bullish || + isCond3Bullish; + // + ; + + // + bool isBearish = + // + isCond1Bearish || + isCond2Bearish || + isCond3Bearish + // + ; + + // + result = isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + double entry = GetEntry( + conditions.symbol, + dir // + ); + + // + double sl = + providedSL > 0 + ? providedSL + : isBullish + ? pivotBox.lower + : pivotBox.upper; + + // + box.dir = dir; + box.symbol = conditions.symbol; + box.period = conditions.period; + + // + box.upper = + isBullish + ? entry + : sl; + + // + box.lower = + isBullish + ? sl + : entry; + + // + box.to = zBar.time; + box.from = p4Bar.time; + + // + box.type = "XCASignal"; + } + + // + result = box.IsValid() && + HasDirection(dir); + + // + // Cleanup Resources ... + + // + if (!result) + { + // + box.Clean(); + pivotBox.Clean(); + conditions.Clean(); + } + + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + Clean(oscBoxes); + pConditions.Clean(); + + // + return result; +} + +// \ No newline at end of file diff --git a/BKPS/14040218 XCAEA/Documents/BKP/2.mq5 b/BKPS/14040218 XCAEA/Documents/BKP/2.mq5 new file mode 100644 index 0000000..db7e47c --- /dev/null +++ b/BKPS/14040218 XCAEA/Documents/BKP/2.mq5 @@ -0,0 +1,1087 @@ + // + void ApplyManalyswerValidation( + XBoxZone &pivots[], + int barIndex = 0 // + ) + { + // + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + + // + barIndex = NormalizeInt(barIndex, 0); + + // + bool has = HasChild(pivots); + if (!has) + { + return; + } + + // + XBoxZone tmp[]; + Copy( + pivots, + tmp // + ); + Clean(pivots); + while (HasChild(tmp)) + { + // + XBoxZone iPivot = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + // Retrieve Pivot info ... + // int toIDX = iPivot.ToIndex(); + // int fromIDX = iPivot.FromIndex(); + // bool isBullish = iPivot.IsBullish(); + + // + // Retrieve Conditions ... + // XCAEAConditions conditions; + // has = helper.GetConditions( + // conditions, + // toIDX, + // 5 // + // ); + + // + // Retrieve Bars ... + + // + // XOHCL cBar; + // XOHCL pBar; + // XOHCL p2Bar; + + // // + // has = + // has && + // cBar.Init( + // conditions.symbol, + // conditions.period, + // toIDX // + // ); + // has = has && + // cBar.GetPreviousBar(pBar); + // has = has && + // pBar.GetPreviousBar(p2Bar); + // if (!has) + // { + // // + // cBar.Clean(); + // pBar.Clean(); + // p2Bar.Clean(); + // iPivot.Clean(); + // conditions.Clean(); + + // // + // continue; + // } + + // + // Reading Conditions ... + + // // + // // MAL ... + // double zMAL = conditions.malBuffer[zIDX]; + // double cMAL = conditions.malBuffer[cIDX]; + // double pMAL = conditions.malBuffer[pIDX]; + // double p2MAL = conditions.malBuffer[p2IDX]; + + // // + // // MAC ... + // double zMAC = conditions.macBuffer[zIDX]; + // double cMAC = conditions.macBuffer[cIDX]; + // double pMAC = conditions.macBuffer[pIDX]; + // double p2MAC = conditions.macBuffer[p2IDX]; + + // // + // // MAH ... + // double zMAH = conditions.mahBuffer[zIDX]; + // double cMAH = conditions.mahBuffer[cIDX]; + // double pMAH = conditions.mahBuffer[pIDX]; + // double p2MAH = conditions.mahBuffer[p2IDX]; + + // + // Checking Conditions ... + // has = isBullish + // ? cBar.high < cMAL || + // pBar.high < pMAL + // : cBar.low < cMAH || + // pBar.low < pMAL; + + // + has = + isBullish + ? iPivot. + if (has) + { + // + AddRef( + iPivot, + pivots // + ); + } + + // + // Cleanup Resources ... + // cBar.Clean(); + // pBar.Clean(); + // p2Bar.Clean(); + iPivot.Clean(); + // conditions.Clean(); + } + + // + Clean(tmp); + } + + +////////////////////////////////////////////////////////////// + + + // + // Parsing Pivots ... + XBoxZone rciPivot; + double providedSL = 0; + XBoxZone rejectedPivot; + XBoxZone insidePivots[]; + XBoxZone rciContainers[]; + int insidePivotsCount = 0; + bool isRejectedOnMid = false; + bool hasInsidePivots = false; + bool hasRCIContainers = false; + bool hasPivots = HasChild(pivots); + if (hasPivots) + { + // + // drawer.DrawBoxes( + // pivots, + // TimeCurrent() // + // ); + + // + // Select Inside Boxes ... + + // + ENUM_XCA_PIVOTS allowedInsidePivots[] = { + XCA_FVG_BULL, + XCA_FVG_BEAR, + XCA_PEAKSWHRES, + XCA_VALESWLSUP, + XCA_TREND_BULL, + XCA_TREND_BEAR, + }; + insidePivotsCount = SelectInsideBoxes( + allowedInsidePivots, + insidePivots, + pivots, + zBar, + cBar, + pBar, + p2Bar // + ); + hasInsidePivots = IsValidSize(insidePivotsCount); + if (hasInsidePivots) + { + // + // drawer.DrawBoxes( + // insidePivots, + // zBar.time // + // ); + } + + // + // Detect Rejected Pivot ... + ENUM_XCA_PIVOTS allowedRejectedPivots[] = { + XCA_FVG_BULL, + XCA_FVG_BEAR, + // XCA_PEAKSWHRES, + // XCA_VALESWLSUP, + // XCA_TREND_BULL, + // XCA_TREND_BEAR, + }; + has = SelectRejectedBox( + allowedRejectedPivots, + rejectedPivot, + isRejectedOnMid, + pivots, + zBar, + cBar, + pBar, + p2Bar, + false, // Ignore Mid Rejection ... + true, + true // + ); + + // + // Select CCI/RSI Cross Object ... + count = ArraySize(pivots); + for (int i = 0; i < count; i++) + { + // + XBoxZone iPivot = pivots[i]; + + // + ENUM_XCA_PIVOTS iType = GetPivotType(iPivot); + + // + // Checking Type is Passed ... + has = + // + iType == XCA_RSI_COOS || + iType == XCA_CCI_COOS || + iType == XCA_RSI_CUOB || + iType == XCA_CCI_CUOB + // + ; + + // + // Checking cBar is Pivots' Last Bar ... + has = + has && + cBar.time <= iPivot.to && + cBar.time > iPivot.from; + if (has) + { + // + rciPivot = iPivot; + + // + iPivot.Clean(); + + // + break; + } + + // + iPivot.Clean(); + } + + // + // Detect RCI Pivot Containers Pivots ... + count = ArraySize(pivots); + has = rciPivot.IsValid(); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + XBoxZone iPivot = pivots[i]; + + // + ENUM_XCA_PIVOTS iType = GetPivotType(iPivot); + + // + // Checking Type is Passed ... + has = + // + IsValid(iType) && + (iType == XCA_PEAKSWHRES || + iType == XCA_VALESWLSUP) + // + ; + + // + // Check Dir is Passed ... + has = + has && + rciPivot.dir == iPivot.dir; + + // + // Check RCI Pivot is Inside Pivot ... + has = + has && + // + ( + // + (rciPivot.lower >= iPivot.lower && + rciPivot.lower < iPivot.upper) + // + || + // + (rciPivot.upper <= iPivot.upper && + rciPivot.upper > iPivot.lower) + // + || + // + (rciPivot.upper > iPivot.upper && + rciPivot.lower < iPivot.lower) + // + ) + // + ; + + // + if (has) + { + // + AddRef( + iPivot, + rciContainers // + ); + } + + // + iPivot.Clean(); + } + + // + hasRCIContainers = HasChild(rciContainers); + } + } + +///////////////////////////////////////////////////////////////////// + + + // + // Box Based Conditions ... + + // + // if (isCBarHasStrongATR) + // { + // // + // Print(ToString(cBar.GetDirection()), " ATR Growing ..."); + // } + + // + // bool isZeroVScore = isScoreNeutural || + // isVolumeNeutural; + + // // + // bool isBullishTested = + // isZeroVScore && + // isCBarValidForBullish // && + // // rejectedPivot.IsValid() && + // // rejectedPivot.IsBullish() + // ; + // bool isBearishTested = + // isZeroVScore && + // isCBarValidForBearish // && + // // rejectedPivot.IsValid() && + // // rejectedPivot.IsBearish() + // ; + + // // + // bool isTested = + // // + // isBullishTested || + // isBearishTested + // // + // ; + // if (isTested) + // { + // // + // Print("Zero Volume ..."); + // } + + +///////////////////////////////////////////////////////////////////// + + + // + bool isCond2Bullish = + // + false // && + // + // conditions. + // + // zPeak > cPeak && + // zBar.close > cPeak && + // ((zPeak - cPeak) > 2 * points) && + // + // z3MAFastState > 0 && + // isValeGoldenRejected && + // isCBarBullishRejected && + // conditions.isValeIsPivot + // + // isPCCIOS && + // isRSIBullish && + // conditions.isCloseUnderMal + // rciPivot.IsValid() && + // rciPivot.IsBullish() && + // isCCIBullish && + // cBar.close > c3MAFast + // isADXBullish && + // hasRCIContainers && + // conditions.isValeIsPivot && + // (conditions.isRSICrossedOverOS || + // conditions.isCCICrossedOverOS) // && + // conditions.swingLowBuffer[cIDX] < conditions.fiboLevel3Buffer[cIDX] + // // + ; + + // + bool isCond2Bearish = + // + false // && + // + // z3MAFastState < 0 && + // isPeakGoldenRejected && + // isCBarBullishRejected && + // conditions.isPeakIsPivot + // + // isPCCIOB && + // isRSIBearish && + // c3MAFastState < 0 && + // conditions.isCloseOverMah + // rciPivot.IsValid() && + // rciPivot.IsBearish() && + // conditions.isRSIOB && + // isCCIBearish && + // cBar.close < c3MAFast + // isADXBearish && + // hasRCIContainers && + // conditions.isPeakIsPivot && + // (conditions.isRSICrossedUnderOB || + // conditions.isCCICrossedUnderOB) // && + // conditions.swingHighBuffer[cIDX] > conditions.fiboLevel1Buffer[cIDX] + // // + ; + + + /////////////////////////////////////////////////////////////////////////////////// + + + // + // bool DetectPeakPivot( + // 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() && + // detectPeakPivots + // // + // ; + // 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]; + + // // + // // SWING High .. + // double zSwingHigh = conditions.swingHighBuffer[zIDX]; + // double cSwingHigh = conditions.swingHighBuffer[cIDX]; + // double pSwingHigh = conditions.swingHighBuffer[pIDX]; + // double p2SwingHigh = conditions.swingHighBuffer[p2IDX]; + + // // + // // SWING Low ... + // double zSwingLow = conditions.swingLowBuffer[zIDX]; + // double cSwingLow = conditions.swingLowBuffer[cIDX]; + // double pSwingLow = conditions.swingLowBuffer[pIDX]; + // double p2SwingLow = conditions.swingLowBuffer[p2IDX]; + + // // + // // SUPPORT ... + // double zSupport = conditions.supportBuffer[zIDX]; + // double cSupport = conditions.supportBuffer[cIDX]; + // double pSupport = conditions.supportBuffer[pIDX]; + // double p2Support = conditions.supportBuffer[p2IDX]; + + // // + // // RESISTANCE ... + // double zResistance = conditions.resistanceBuffer[zIDX]; + // double cResistance = conditions.resistanceBuffer[cIDX]; + // double pResistance = conditions.resistanceBuffer[pIDX]; + // double p2Resistance = conditions.resistanceBuffer[p2IDX]; + + // // + // // Detecting Bar Conditions ... + + // // + // ENUM_X_DIRECTION cBarDir; + + // // + // // Rejected ... + // bool isCBarRejected = helper + // .barAnalyser + // .IsRejected( + // cBar, + // cBarDir, + // false, // Force Type ... + // true // Force Fibo Pressure ... + // ); + // bool isCBarBullishRejected = + // isCBarRejected && + // IsBullish(cBarDir); + // bool isCBarBearishRejected = + // isCBarRejected && + // IsBearish(cBarDir); + + // // + // // Engulfed ... + // bool isCBarEngulfed = helper + // .barAnalyser + // .IsEngulfed( + // cBar, + // cBarDir // + // ); + // bool isCBarBullishEngulfed = + // isCBarEngulfed && + // IsBullish(cBarDir); + // bool isCBarBearishEngulfed = + // isCBarEngulfed && + // IsBearish(cBarDir); + + // // + // // Prepare Conditinal Conditions ... + + // // + // bool isPeakSameLast = cPeak == pPeak; + // bool isPeakSameLastPrev = pPeak == p2Peak; + + // // + // if (applySwingsOnPVPivots) + // { + // // + // isPeakSameLast = + // isPeakSameLast && + // cSwingHigh == cPeak && + // cSwingHigh == pSwingHigh; + + // // + // isPeakSameLastPrev = + // isPeakSameLastPrev && + // pSwingHigh == pPeak && + // pSwingHigh == p2SwingHigh; + // } + + // // + // if (applySupportAndResistanceOnPVPivots) + // { + // // + // isPeakSameLast = + // isPeakSameLast && + // cResistance == cPeak && + // cResistance == pResistance; + + // // + // isPeakSameLastPrev = + // isPeakSameLastPrev && + // pResistance == pPeak && + // pResistance == p2Resistance; + // } + + // // + // bool isPeakSwitchedToSameLast = isPeakSameLast && + // !isPeakSameLastPrev; + // bool isPeakFinishedFromSameLast = !isPeakSameLast && + // isPeakSameLastPrev; + + // // + // // ZERO ... + // // Default Peak and Vale Selection ... + // bool isTypeZeroStart = isPeakFinishedFromSameLast; + // bool isTypeZeroContinue = isPeakSameLast; + // bool isTypeZeroFinished = isPeakSwitchedToSameLast; + // if (isTypeZeroFinished) + // { + // // + // bool hasSelectionType = selectRejectedPVPivots || + // selectEngulfedPVPivots; + + // // + // bool isPVRejected = + // isCBarBearishRejected && + // selectRejectedPVPivots; + + // // + // bool isPVEngulfed = + // isCBarBearishEngulfed && + // selectEngulfedPVPivots; + + // // + // bool isBarPassed = + // !hasSelectionType + // ? true + // : isPVRejected || + // isPVEngulfed; + + // // + // isTypeZeroFinished = + // isBarPassed && + // isTypeZeroFinished; + // if (!isTypeZeroFinished) + // { + // peakPivot.Clean(); + // } + // } + + // // + // // Summarizing Conditions ... + + // // + // result = false; + + // // + // bool hasStartCondition = + // // + // isTypeZeroStart + // // + // ; + // bool hasContinuationCondition = + // // + // isTypeZeroContinue + // // + // ; + // bool hasEndCondition = + // // + // isTypeZeroFinished + // // + // ; + + // // + // // ReInstance Pivot ... + // if (hasStartCondition) + // { + // // + // peakPivot.Clean(); + + // // + // peakPivot.type = XCA_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) + // { + // // + // peakPivot.from = pBar.time; + + // // + // peakPivot.reserve = + // peakPivot.reserve == 0 + // ? pPeakGolden + // : MathMax(peakPivot.reserve, pPeakGolden); + // } + + // // + // // End up Pivot and Store it ... + // if (hasEndCondition) + // { + // // + // 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; + // } + + + + // // + // bool DetectValePivot( + // 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() && + // detectValePivots + // // + // ; + // 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]; + + // // + // // SWING High .. + // double zSwingHigh = conditions.swingHighBuffer[zIDX]; + // double cSwingHigh = conditions.swingHighBuffer[cIDX]; + // double pSwingHigh = conditions.swingHighBuffer[pIDX]; + // double p2SwingHigh = conditions.swingHighBuffer[p2IDX]; + + // // + // // SWING Low ... + // double zSwingLow = conditions.swingLowBuffer[zIDX]; + // double cSwingLow = conditions.swingLowBuffer[cIDX]; + // double pSwingLow = conditions.swingLowBuffer[pIDX]; + // double p2SwingLow = conditions.swingLowBuffer[p2IDX]; + + // // + // // SUPPORT ... + // double zSupport = conditions.supportBuffer[zIDX]; + // double cSupport = conditions.supportBuffer[cIDX]; + // double pSupport = conditions.supportBuffer[pIDX]; + // double p2Support = conditions.supportBuffer[p2IDX]; + + // // + // // RESISTANCE ... + // double zResistance = conditions.resistanceBuffer[zIDX]; + // double cResistance = conditions.resistanceBuffer[cIDX]; + // double pResistance = conditions.resistanceBuffer[pIDX]; + // double p2Resistance = conditions.resistanceBuffer[p2IDX]; + + // // + // // Detecting Bar Conditions ... + + // // + // ENUM_X_DIRECTION cBarDir; + + // // + // // Rejected ... + // bool isCBarRejected = helper + // .barAnalyser + // .IsRejected( + // cBar, + // cBarDir, + // false, // Force Type ... + // true // Force Fibo Pressure ... + // ); + // bool isCBarBullishRejected = + // isCBarRejected && + // IsBullish(cBarDir); + // bool isCBarBearishRejected = + // isCBarRejected && + // IsBearish(cBarDir); + + // // + // // Engulfed ... + // bool isCBarEngulfed = helper + // .barAnalyser + // .IsEngulfed( + // cBar, + // cBarDir // + // ); + // bool isCBarBullishEngulfed = + // isCBarEngulfed && + // IsBullish(cBarDir); + // bool isCBarBearishEngulfed = + // isCBarEngulfed && + // IsBearish(cBarDir); + + // // + // // Prepare Conditinal Conditions ... + + // // + // bool isValeSameLast = cVale == pVale; + // bool isValeSameLastPrev = pVale == p2Vale; + + // // + // if (applySwingsOnPVPivots) + // { + // // + // isValeSameLast = + // isValeSameLast && + // cSwingLow == cVale && + // cSwingLow == pSwingLow; + + // // + // isValeSameLastPrev = + // isValeSameLastPrev && + // pSwingLow == pVale && + // pSwingLow == p2SwingLow; + // } + + // // + // if (applySupportAndResistanceOnPVPivots) + // { + // // + // isValeSameLast = + // isValeSameLast && + // cSupport == cVale && + // cSupport == pSupport; + + // // + // isValeSameLastPrev = + // isValeSameLastPrev && + // pSupport == pVale && + // pSupport == p2Support; + // } + + // // + // bool isValeSwitchedToSameLast = isValeSameLast && + // !isValeSameLastPrev; + // bool isValeFinishedFromSameLast = !isValeSameLast && + // isValeSameLastPrev; + + // // + // // ZERO ... + // // Default Peak and Vale Selection ... + // bool isTypeZeroStart = isValeFinishedFromSameLast; + // bool isTypeZeroContinue = isValeSameLast; + // bool isTypeZeroFinished = isValeSwitchedToSameLast; + // if (isTypeZeroFinished) + // { + // // + // bool hasSelectionType = selectRejectedPVPivots || + // selectEngulfedPVPivots; + + // // + // bool isPVRejected = + // isCBarBullishRejected && + // selectRejectedPVPivots; + + // // + // bool isPVEngulfed = + // isCBarBullishEngulfed && + // selectEngulfedPVPivots; + + // // + // bool isBarPassed = + // !hasSelectionType + // ? true + // : isPVRejected || + // isPVEngulfed; + + // // + // isTypeZeroFinished = + // isBarPassed && + // isTypeZeroFinished; + // if (!isTypeZeroFinished) + // { + // valePivot.Clean(); + // } + // } + + // // + // // Summarizing Conditions ... + + // // + // result = false; + + // // + // bool hasStartCondition = + // // + // isTypeZeroStart + // // + // ; + // bool hasContinuationCondition = + // // + // isTypeZeroContinue + // // + // ; + // bool hasEndCondition = + // // + // isTypeZeroFinished + // // + // ; + + // // + // // ReInstance Pivot ... + // if (hasStartCondition) + // { + // // + // valePivot.Clean(); + + // // + // valePivot.type = XCA_VALE; + // valePivot.symbol = symbol; + // valePivot.period = period; + + // // + // valePivot.to = pBar.time; + // valePivot.from = pBar.time; + // valePivot.value = pVale; + // valePivot.reserve = pValeGolden; + // } + + // // + // // Calculate and Fill Pivot Requirements ... + // if (hasContinuationCondition) + // { + // // + // valePivot.from = pBar.time; + + // // + // valePivot.reserve = + // valePivot.reserve == 0 + // ? pValeGolden + // : MathMin(valePivot.reserve, pValeGolden); + // } + + // // + // // End up Pivot and Store it ... + // if (hasEndCondition) + // { + // // + // result = + // valePivot.IsValid() && + // valePivot.GetAge() >= pivotVerifications; + // if (result) + // { + // // + // XBoxZone iBox; + // result = valePivot.AsBox(iBox); + // if (result) + // { + // // + // newPeakPivotDetected = AddBox( + // iBox, + // valePivots // + // ); + // } + + // // + // iBox.Clean(); + // } + + // // + // valePivot.Clean(); + // } + + // // + // return result; + // } diff --git a/BKPS/14040218 XCAEA/Documents/BKP/Indicators/x-saherelm.x121.xca.v1.mq5 b/BKPS/14040218 XCAEA/Documents/BKP/Indicators/x-saherelm.x121.xca.v1.mq5 new file mode 100644 index 0000000..4169373 --- /dev/null +++ b/BKPS/14040218 XCAEA/Documents/BKP/Indicators/x-saherelm.x121.xca.v1.mq5 @@ -0,0 +1,2452 @@ +/////////////////////////////////////////////////////// +// +// 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_500; // Fibo Level 2 +input ENUM_X_FIBO_LEVELS fiboLevel3 = X_FIBO_LEVEL_764; // Fibo Level 3 + +// +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_SMA; // 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 showPeaksAndVales = true; // Show Peaks And Vales +input bool showPeakAndValeGolden = true; // Show Peak and Vale Golden +input bool showSupportAndResistance = true; // Show Support and Resistance +input bool showShortCycle = true; // Show Short Cycle +input bool showMediumCycle = true; // Show Medium Cycle +input bool showLongCycle = true; // Show Long Cycle +input bool showHindCycle = true; // 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 37 +#property indicator_plots 27 + +// +// 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 clrYellow +#property indicator_style16 STYLE_DASH +#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 clrGold +#property indicator_style17 STYLE_DOT +#property indicator_width17 1 + +// +// SAR ... + +// +#define sarBufferIndex 17 +double sarBuffer[]; + +// +#property indicator_label18 "SAR" +#property indicator_type18 DRAW_ARROW +#property indicator_color18 clrYellow +#property indicator_width18 1 + +// +// TREND ... + +// +#define trendBufferIndex 18 +#define trendBufferPlotIndex 18 +double trendBuffer[]; + +// +#define trendColorBufferIndex 19 +double trendColorBuffer[]; + +// +#property indicator_label19 "TRND" +#property indicator_type19 DRAW_COLOR_LINE +#property indicator_color19 CLR_NONE, clrAqua, clrMagenta, clrGray +#property indicator_style19 STYLE_DASH +#property indicator_width19 2 + +// +// KI ... + +// +#define kiBufferIndex 20 +#define kiBufferPlotIndex 19 +double kiBuffer[]; + +// +#define kiColorBufferIndex 21 +double kiColorBuffer[]; + +// +#property indicator_label20 "KI" +#property indicator_type20 DRAW_COLOR_LINE +#property indicator_color20 CLR_NONE, clrGreen, clrRed, clrGray +#property indicator_style20 STYLE_DASHDOTDOT +#property indicator_width20 2 + +// +// SWING Low ... + +// +#define swingLowBufferIndex 22 +#define swingLowBufferPlotIndex 20 +double swingLowBuffer[]; + +// +#property indicator_label21 "SWL" +#property indicator_type21 DRAW_ARROW +#property indicator_color21 clrGreen +#property indicator_width21 1 + +// +// SWING High ... + +// +#define swingHighBufferIndex 23 +#define swingHighBufferPlotIndex 21 +double swingHighBuffer[]; + +// +#property indicator_label22 "SWH" +#property indicator_type22 DRAW_ARROW +#property indicator_color22 clrRed +#property indicator_width22 1 + +// +// TKI ... + +// +#define tkiBufferIndex 24 +#define tkiBufferPlotIndex 22 +double tkiBuffer[]; + +// +#define tkiColorBufferIndex 25 +double tkiColorBuffer[]; + +// +#property indicator_label23 "TKI" +#property indicator_type23 DRAW_COLOR_LINE +#property indicator_color23 CLR_NONE, clrGreen, clrRed, clrGray +#property indicator_style23 STYLE_DASHDOTDOT +#property indicator_width23 2 + +// +// VIDYA ... + +// +#define vidyaBufferIndex 26 +#define vidyaBufferPlotIndex 23 +double vidyaBuffer[]; + +// +#define vidyaColorBufferIndex 27 +double vidyaColorBuffer[]; + +// +#property indicator_label24 "VIDYA" +#property indicator_type24 DRAW_COLOR_LINE +#property indicator_color24 CLR_NONE, clrAqua, clrMagenta, clrGray +#property indicator_style24 STYLE_SOLID +#property indicator_width24 1 + +// +// MAH ... + +// +#define mahBufferIndex 28 +#define mahBufferPlotIndex 24 +double mahBuffer[]; + +// +#property indicator_label25 "MAH" +#property indicator_type25 DRAW_LINE +#property indicator_color25 clrMagenta +#property indicator_style25 STYLE_SOLID +#property indicator_width25 1 + +// +// MAL ... + +// +#define malBufferIndex 29 +#define malBufferPlotIndex 25 +double malBuffer[]; + +// +#property indicator_label26 "MAL" +#property indicator_type26 DRAW_LINE +#property indicator_color26 clrAqua +#property indicator_style26 STYLE_SOLID +#property indicator_width26 1 + +// +// MAC ... + +// +#define macBufferIndex 30 +#define macBufferPlotIndex 26 +double macBuffer[]; + +// +#property indicator_label27 "MAC" +#property indicator_type27 DRAW_LINE +#property indicator_color27 clrYellow +#property indicator_style27 STYLE_SOLID +#property indicator_width27 1 + +// +// Data Buffers ... + +#define mLastBufferIndex 30 + +// +#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); + + // + // 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; + + // + // 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 BOS ... + + // + // Calculate CHOCH ... + + // + // 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 Fibo Levels ... + + // + double iFiboUpper = peakBuffer[bar_index]; + double iFiboLower = valeBuffer[bar_index]; + + // + double iFiboLevel1 = GetFibonacciLevel( + iFiboUpper, + iFiboLower, + fiboLevel1, + X_DIRECTION_BEARISH // + ); + fiboLevel1Buffer[bar_index] = iFiboLevel1; + + // + double iFiboLevel2 = GetFibonacciLevel( + iFiboUpper, + iFiboLower, + fiboLevel2, + X_DIRECTION_BEARISH // + ); + fiboLevel2Buffer[bar_index] = iFiboLevel2; + + // + double iFiboLevel3 = GetFibonacciLevel( + iFiboUpper, + iFiboLower, + fiboLevel3, + X_DIRECTION_BEARISH // + ); + fiboLevel3Buffer[bar_index] = iFiboLevel3; + + // + // 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; + + // + // Calculate Swings ... + + // + double lastSwingLow = + isFirstBar + ? emptyValue + : swingLowBuffer[lastBarIndex]; + bool isSwingLow = IsSwingLow( + high, + low, + bar_index, + swingLength // + ); + double iSwingLow = + isSwingLow + ? low[bar_index] + : lastSwingLow; + swingLowBuffer[bar_index] = iSwingLow; + + // + double lastSwingHigh = + isFirstBar + ? emptyValue + : swingHighBuffer[lastBarIndex]; + bool isSwingHigh = IsSwingHigh( + high, + low, + bar_index, + swingLength // + ); + double iSwingHigh = + isSwingHigh + ? high[bar_index] + : lastSwingHigh; + swingHighBuffer[bar_index] = iSwingHigh; + + // + // 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/14040218 XCAEA/Documents/BKP/Indicators/x-saherelm.x121.xca.v2.mq5 b/BKPS/14040218 XCAEA/Documents/BKP/Indicators/x-saherelm.x121.xca.v2.mq5 new file mode 100644 index 0000000..bfa86fc --- /dev/null +++ b/BKPS/14040218 XCAEA/Documents/BKP/Indicators/x-saherelm.x121.xca.v2.mq5 @@ -0,0 +1,2487 @@ +/////////////////////////////////////////////////////// +// +// 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_500; // Fibo Level 2 +input ENUM_X_FIBO_LEVELS fiboLevel3 = X_FIBO_LEVEL_764; // Fibo Level 3 + +// +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_SMA; // 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 showPeaksAndVales = true; // Show Peaks And Vales +input bool showPeakAndValeGolden = true; // Show Peak and Vale Golden +input bool showSupportAndResistance = true; // Show Support and Resistance +input bool showShortCycle = true; // Show Short Cycle +input bool showMediumCycle = true; // Show Medium Cycle +input bool showLongCycle = true; // Show Long Cycle +input bool showHindCycle = true; // 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 37 +#property indicator_plots 27 + +// +// 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 clrYellow +#property indicator_style16 STYLE_DASH +#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 clrGold +#property indicator_style17 STYLE_DOT +#property indicator_width17 1 + +// +// SAR ... + +// +#define sarBufferIndex 17 +double sarBuffer[]; + +// +#property indicator_label18 "SAR" +#property indicator_type18 DRAW_ARROW +#property indicator_color18 clrYellow +#property indicator_width18 1 + +// +// TREND ... + +// +#define trendBufferIndex 18 +#define trendBufferPlotIndex 18 +double trendBuffer[]; + +// +#define trendColorBufferIndex 19 +double trendColorBuffer[]; + +// +#property indicator_label19 "TRND" +#property indicator_type19 DRAW_COLOR_LINE +#property indicator_color19 CLR_NONE, clrAqua, clrMagenta, clrGray +#property indicator_style19 STYLE_DASH +#property indicator_width19 2 + +// +// KI ... + +// +#define kiBufferIndex 20 +#define kiBufferPlotIndex 19 +double kiBuffer[]; + +// +#define kiColorBufferIndex 21 +double kiColorBuffer[]; + +// +#property indicator_label20 "KI" +#property indicator_type20 DRAW_COLOR_LINE +#property indicator_color20 CLR_NONE, clrGreen, clrRed, clrGray +#property indicator_style20 STYLE_DASHDOTDOT +#property indicator_width20 2 + +// +// SWING Low ... + +// +#define swingLowBufferIndex 22 +#define swingLowBufferPlotIndex 20 +double swingLowBuffer[]; + +// +#property indicator_label21 "SWL" +#property indicator_type21 DRAW_ARROW +#property indicator_color21 clrGreen +#property indicator_width21 1 + +// +// SWING High ... + +// +#define swingHighBufferIndex 23 +#define swingHighBufferPlotIndex 21 +double swingHighBuffer[]; + +// +#property indicator_label22 "SWH" +#property indicator_type22 DRAW_ARROW +#property indicator_color22 clrRed +#property indicator_width22 1 + +// +// TKI ... + +// +#define tkiBufferIndex 24 +#define tkiBufferPlotIndex 22 +double tkiBuffer[]; + +// +#define tkiColorBufferIndex 25 +double tkiColorBuffer[]; + +// +#property indicator_label23 "TKI" +#property indicator_type23 DRAW_COLOR_LINE +#property indicator_color23 CLR_NONE, clrGreen, clrRed, clrGray +#property indicator_style23 STYLE_DASHDOTDOT +#property indicator_width23 2 + +// +// VIDYA ... + +// +#define vidyaBufferIndex 26 +#define vidyaBufferPlotIndex 23 +double vidyaBuffer[]; + +// +#define vidyaColorBufferIndex 27 +double vidyaColorBuffer[]; + +// +#property indicator_label24 "VIDYA" +#property indicator_type24 DRAW_COLOR_LINE +#property indicator_color24 CLR_NONE, clrAqua, clrMagenta, clrGray +#property indicator_style24 STYLE_SOLID +#property indicator_width24 1 + +// +// MAH ... + +// +#define mahBufferIndex 28 +#define mahBufferPlotIndex 24 +double mahBuffer[]; + +// +#property indicator_label25 "MAH" +#property indicator_type25 DRAW_LINE +#property indicator_color25 clrMagenta +#property indicator_style25 STYLE_SOLID +#property indicator_width25 1 + +// +// MAL ... + +// +#define malBufferIndex 29 +#define malBufferPlotIndex 25 +double malBuffer[]; + +// +#property indicator_label26 "MAL" +#property indicator_type26 DRAW_LINE +#property indicator_color26 clrAqua +#property indicator_style26 STYLE_SOLID +#property indicator_width26 1 + +// +// MAC ... + +// +#define macBufferIndex 30 +#define macBufferPlotIndex 26 +double macBuffer[]; + +// +#property indicator_label27 "MAC" +#property indicator_type27 DRAW_LINE +#property indicator_color27 clrYellow +#property indicator_style27 STYLE_SOLID +#property indicator_width27 1 + +// +// Data Buffers ... + +#define mLastBufferIndex 30 + +// +#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); + + // + // 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; + + // + // 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 BOS ... + + // + // Calculate CHOCH ... + + // + // 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 Fibo Levels ... + + // + double iFiboUpper = peakBuffer[bar_index]; + double iFiboLower = valeBuffer[bar_index]; + + // + double iFiboLevel1 = GetFibonacciLevel( + iFiboUpper, + iFiboLower, + fiboLevel1, + X_DIRECTION_BEARISH // + ); + fiboLevel1Buffer[bar_index] = iFiboLevel1; + + // + double iFiboLevel2 = GetFibonacciLevel( + iFiboUpper, + iFiboLower, + fiboLevel2, + X_DIRECTION_BEARISH // + ); + fiboLevel2Buffer[bar_index] = iFiboLevel2; + + // + double iFiboLevel3 = GetFibonacciLevel( + iFiboUpper, + iFiboLower, + fiboLevel3, + X_DIRECTION_BEARISH // + ); + fiboLevel3Buffer[bar_index] = iFiboLevel3; + + // + // 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; + + // + // 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; + if (!hasSwing) + { + // + // FillBuffersZero(bar_index); + + // + swingLowBuffer[bar_index] = lastSwingLow; + swingHighBuffer[bar_index] = lastSwingHigh; + } + else + { + // + double 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; + } + + // + // 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/14040218 XCAEA/Documents/BKP/Indicators/x-saherelm.x121.xswlh.mq5 b/BKPS/14040218 XCAEA/Documents/BKP/Indicators/x-saherelm.x121.xswlh.mq5 new file mode 100644 index 0000000..7564000 --- /dev/null +++ b/BKPS/14040218 XCAEA/Documents/BKP/Indicators/x-saherelm.x121.xswlh.mq5 @@ -0,0 +1,573 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XSWLH +// Description: XSWLH ... +// +// +// 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 XSWLH Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121 XSWLH" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +input int swingLength; // Swing Length + +// +input int startCalculationForLastBars = 1000; // Calculate Last n Bars + +// +input bool showSwingLow; // Show Swing Low +input bool showSwingHigh; // Show Swing High + +// +input int swingLowArrowCode = 225; // Swing Low Arrow Code +input int swingHighArrowCode = 226; // Swing High Arrow Code + +// +#define emptyValue 0.0 + +// +// Buffers ... + +// +#property indicator_chart_window + +// +#property indicator_buffers 2 +#property indicator_plots 2 + +// +// SWING LOW ... + +// +#define swingLowBufferIndex 0 +double swingLowBuffer[]; + +// +#property indicator_label1 "SWL" +#property indicator_type1 DRAW_ARROW +#property indicator_color1 clrGreen +#property indicator_width1 1 + +// +// SWING HIGH ... + +// +#define swingHighBufferIndex 1 +double swingHighBuffer[]; + +// +#property indicator_label2 "SWH" +#property indicator_type2 DRAW_ARROW +#property indicator_color2 clrRed +#property indicator_width2 1 + +// +// Data Buffers ... + +// +#define lastBufferIndex 1 + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int firstBarIndex; + +// +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); + + // + 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 = + // + swingLength > 0 + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(result, swingLength); + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + + // + // SWING Low ... + + // + ENUM_DRAW_TYPE swingLowDrawType = showSwingLow ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(swingLowBuffer, true); + SetIndexBuffer(swingLowBufferIndex, swingLowBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(swingLowBufferIndex, PLOT_SHOW_DATA, showSwingLow); + PlotIndexSetInteger(swingLowBufferIndex, PLOT_DRAW_TYPE, swingLowDrawType); + + // + PlotIndexSetDouble(swingLowBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(swingLowBufferIndex, PLOT_ARROW, swingLowArrowCode); + + // + // SWING High ... + + // + ENUM_DRAW_TYPE swingHighDrawType = showSwingHigh ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(swingHighBuffer, true); + SetIndexBuffer(swingHighBufferIndex, swingHighBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(swingHighBufferIndex, PLOT_SHOW_DATA, showSwingHigh); + PlotIndexSetInteger(swingHighBufferIndex, PLOT_DRAW_TYPE, swingHighDrawType); + + // + PlotIndexSetDouble(swingHighBufferIndex, PLOT_EMPTY_VALUE, emptyValue); + PlotIndexSetInteger(swingHighBufferIndex, PLOT_ARROW, swingHighArrowCode); +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + // + IndicatorSetInteger(INDICATOR_DIGITS, _Digits); + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + swingLowBuffer[barIndex] = emptyValue; + swingHighBuffer[barIndex] = emptyValue; +} + +/** + * 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 Support nad Resistance ... + CalculateValues( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + else + { + FillBuffersZero(bar_index); + } +} + +/** + * 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; + + // + // Reading Last Values ... + + // + double iSWLPrev = + isFirstBar + ? emptyValue + : swingLowBuffer[lastBarIndex]; + + // + double iSWHPrev = + isFirstBar + ? emptyValue + : swingHighBuffer[lastBarIndex]; + + // + // Checking Swings ... + bool isSwingLow = IsSwingLow(high, low, bar_index, swingLength); + bool isSwingHigh = IsSwingHigh(high, low, bar_index, swingLength); + bool hasSwing = isSwingLow || + isSwingHigh; + if (!hasSwing) + { + // + // FillBuffersZero(bar_index); + + // + swingLowBuffer[bar_index] = iSWLPrev; + swingHighBuffer[bar_index] = iSWHPrev; + return; + } + + // + double iSWL = low[bar_index]; + double iSWH = high[bar_index]; + + // + // Act Based on Swing High or Swing Low Detection ... + if (isSwingLow && !isSwingHigh) + { + // + // Detect Swing High based On swing Low ... + iSWH = iSWHPrev; + } + else if (isSwingHigh && !isSwingLow) + { + // + // Detect Swing Low Based On Swing High ... + iSWL = iSWLPrev; + } + + // + if (iSWL > iSWLPrev && iSWH == iSWHPrev) + { + iSWL = iSWLPrev; + } + + // + if (iSWH < iSWHPrev && iSWL == iSWLPrev) + { + iSWH = iSWHPrev; + } + + // + swingLowBuffer[bar_index] = iSWL; + swingHighBuffer[bar_index] = iSWH; +} + +// +// Helpers ... + +// +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; +} diff --git a/BKPS/14040218 XCAEA/Documents/BKP/signallers1/xcaea.signaller.class.mq5 b/BKPS/14040218 XCAEA/Documents/BKP/signallers1/xcaea.signaller.class.mq5 new file mode 100644 index 0000000..9c4b114 --- /dev/null +++ b/BKPS/14040218 XCAEA/Documents/BKP/signallers1/xcaea.signaller.class.mq5 @@ -0,0 +1,1070 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XCXCAEASignaller ... +// Description: Class for XCAEA 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 Class for XCAEA Signaller" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.base.class.mq5" +#include "../../Classes/x-saherelm.x-cobject.class.mq5" +#include "../Classes/xcaea.x-poi.detector.class.mq5" +#include "../Classes/xcaea.x-poi.drawer.class.mq5" +#include "../Helpers/xcaea.helper.mq5" +#include "../Libraries/xcaea.signaller.lib.mq5" + +// +// Definitions ... + +class XCXCAEASignaller : XCBase +{ + // + // Public ... + public: + // + // Props ... + bool useGuards; + bool useTargets; + int poiLoopback; + XCAEAInputs inputs; + XBarTracker barTraker; + XCXCAEAHelper *helper; + bool rfOnInvalidPivots; + XCXCAEAPOIDrawer *drawer; + bool continuesRFTillTarget; + XBoxZone unAvailableBoxes[]; + XCXCAEAPOIDetector *detector; + XCAEAStrategyConditions mConditions; + XCAEAStrategyConditions mConditionsCollection[]; + + // + // Constructor ... + XCXCAEASignaller( + string _symbol, + ENUM_TIMEFRAMES _period // + ) + { + // + symbol = _symbol; + period = _period; + + // + Init(); + } + + // + // Deconstructor ... + ~XCXCAEASignaller() + { + DeInit(); + } + + // + // Properties ... + + /** + * Initialize ... + */ + void Init() + { + // + useGuards = false; + useTargets = true; + rfOnInvalidPivots = false; + continuesRFTillTarget = false; + + // + barTraker.Init( + symbol, + period // + ); + + // + inputs.Default(); + + // + // Configure Indicators ... + + // + // XCC ... + inputs.ccInputs.showCandles = true; + + // + // XCT ... + inputs.ctInputs.showCandleTime = true; + + // + // XCA ... + + // + inputs.caInputs.supResSmoothingLength = 7; + inputs.caInputs.supResSmoothingMode = X_MA_MODE_NONE; + + // + inputs.x3maInputs.applyColor = true; + + // + inputs.x3maInputs.fastLength = 5; + + // + inputs.x3maInputs.showFast = true; + inputs.x3maInputs.showSlow = false; + inputs.x3maInputs.showMedium = false; + + // + inputs.caInputs.showMAH = true; + inputs.caInputs.showMAL = true; + inputs.caInputs.showMAC = true; + inputs.caInputs.showSar = true; + inputs.caInputs.showSwings = true; + inputs.caInputs.showFiboLevel1 = true; + inputs.caInputs.showFiboLevel2 = true; + inputs.caInputs.showFiboLevel3 = true; + inputs.caInputs.showFiboLevel4 = true; + inputs.caInputs.showFiboLevel5 = true; + inputs.caInputs.showPeaksAndVales = true; + + // + inputs.caInputs.showKI = false; + inputs.caInputs.showTKI = false; + inputs.caInputs.showVidya = false; + inputs.caInputs.showTrend = false; + inputs.caInputs.showPeakAndValeGolden = false; + inputs.caInputs.showSupportAndResistance = false; + + // + // XOSCS ... + // inputs.oscsInputs.rsiLength = 5; + // inputs.oscsInputs.rsiOBLevel = 90; + // inputs.oscsInputs.rsiOSLevel = 10; + // inputs.oscsInputs.cciLength = 7; + // inputs.oscsInputs.cciOBLevel = 130; + // inputs.oscsInputs.cciOSLevel = -130; + // inputs.oscsInputs.mfiLength = 5; + // inputs.oscsInputs.rviLength = 5; + + // + // Oscillators Views ... + inputs.showRSI = false; + inputs.showCCI = false; + inputs.showMFI = false; + inputs.showRVI = false; + inputs.showADX = false; + inputs.showMACD = false; + + // + // XCAEA Helper ... + helper = new XCXCAEAHelper(); + helper.Init( + symbol, + period, + inputs // + ); + + // + // Initialize and Configure Detector ... + detector = new XCXCAEAPOIDetector(helper); + + // + // Common Configurations ... + detector.maxAllowedPivots = 0; + detector.pivotVerifications = 5; + detector.ticksDividerInPoints = 15; + detector.pivotDetectionLoopbac = 1000; + + // + // Configure Detector ... + + // + // PV ... + + // + detector.maxAllowedPVLifetime = 0; + detector.applySwingsOnPVPivots = true; + detector.selectRejectedPVPivots = true; + detector.selectEngulfedPVPivots = true; + detector.applySupportAndResistanceOnPVPivots = true; + + // + // PEAK ... + detector.detectPeakPivots = true; + + // + // VALE ... + detector.detectValePivots = true; + + // + // FVG ... + + // + detector.selectSameBarFVGs = false; + detector.maxAllowedFVGLifetime = 0; + detector.validateFVGUsingPV = false; + detector.applyPVToFVGBoundary = false; + detector.selectRejectedFVGPivots = false; + detector.selectEngulfedFVGPivots = false; + detector.validateFVGUsingManalyser = true; + detector.applyLastBarToFVGBoundary = false; + detector.selectOnlyFVGWhichHasIndirectionalLastBar = true; + + // + // Bullish ... + detector.detectFVGBullishPivots = true; + + // + // Bearish ... + detector.detectFVGBearishPivots = true; + + // + // TREND ... + + // + detector.maxAllowedTrendLifetime = 0; + + // + // Bullish ... + detector.detectTrendBullishPivots = true; + + // + // Bearish ... + detector.detectTrendBearishPivots = true; + + // + // DRAWER ... + + // + // Initialize and Configure Drawer ... + drawer = new XCXCAEAPOIDrawer(detector); + + // + drawer.ignoreUpdateOSCTos = true; + + // + // Configure Drawer ... + drawer.drawPeakPivots = true; + drawer.drawValePivots = true; + drawer.drawFVGBullishPivots = true; + drawer.drawFVGBearishPivots = true; + drawer.drawTrendBullishPivots = true; + drawer.drawTrendBearishPivots = true; + + // + // Configure Styles ... + + // + // PV ... + + // + // PEAK ... + XCAPivotStyle peakStyle; + peakStyle.width = 2; + peakStyle.clr = clrMagenta; + peakStyle.style = STYLE_SOLID; + drawer.peakPivotStyle = peakStyle; + peakStyle.Clean(); + + // + // VALE ... + XCAPivotStyle valeStyle; + valeStyle.width = 2; + valeStyle.clr = clrAqua; + valeStyle.style = STYLE_SOLID; + drawer.valePivotStyle = valeStyle; + valeStyle.Clean(); + + // + // FVG ... + + // + // Bullish ... + XCAPivotStyle fvgBullishStyle; + fvgBullishStyle.width = 2; + fvgBullishStyle.clr = clrLime; + fvgBullishStyle.style = STYLE_DASH; + drawer.fvgBullishPivotStyle = fvgBullishStyle; + fvgBullishStyle.Clean(); + + // + // Bearish ... + XCAPivotStyle fvgBearishStyle; + fvgBearishStyle.width = 2; + fvgBearishStyle.clr = clrRed; + fvgBearishStyle.style = STYLE_DASH; + drawer.fvgBearishPivotStyle = fvgBearishStyle; + fvgBearishStyle.Clean(); + + // + // TREND ... + + // + // Bullish ... + XCAPivotStyle trendBullishStyle; + trendBullishStyle.width = 2; + trendBullishStyle.clr = clrLime; + trendBullishStyle.style = STYLE_DOT; + drawer.trendBullishPivotStyle = trendBullishStyle; + trendBullishStyle.Clean(); + + // + // Bearish ... + XCAPivotStyle trendBearishStyle; + trendBearishStyle.width = 2; + trendBearishStyle.clr = clrRed; + trendBearishStyle.style = STYLE_DOT; + drawer.trendBearishPivotStyle = trendBearishStyle; + trendBearishStyle.Clean(); + + // + } + + /** + * DeInitialize ... + */ + void DeInit() + { + // + inputs.Clean(); + + // + // Cleaning Draws ... + drawer.Clear(); + + // + ZeroMemory(drawer); + ZeroMemory(helper); + ZeroMemory(detector); + + // + mConditions.Clean(); + Clean(mConditionsCollection); + + // + mObjects.Clear(); + mBarObjects.Clear(); + + // + barTraker.Clean(); + } + + // + string GetSymbol() + { + return symbol; + } + + // + ENUM_TIMEFRAMES GetPeriod() + { + return period; + } + + // + // Signaller 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( + double tpReward = 3, + double maxAllowedSLDistanceInPoint = 100 // + ) + { + // + bool result = false; + + // + // Check Bar Processing ... + if (!barTraker.CanProcessBar()) + { + return result; + } + + // + bool isBullish = false; + bool isBearish = false; + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + int loopback = 10; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + double points = GetPoints(symbol); + + // + XOHCL zBar; + XOHCL cBar; + XOHCL pBar; + XOHCL pPBar; + result = zBar.Init( + symbol, + period, + zIndex // + ); + result = + result && + zBar.GetPreviousBar(cBar); + result = + result && + cBar.GetPreviousBar(pBar); + result = + result && + pBar.GetPreviousBar(pPBar); + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + pPBar.Clean(); + + // + return result; + } + + // + // Setup Conditions ... + double targets[]; + XBoxZone pivots[]; + XBoxZone pivotBox; + XBoxZone signalBox; + int pivotsCount = 0; + bool hasTrend = false; + bool hasPivots = false; + double additionalSL = 0; + bool hasSignalBox = false; + XCAEAConditions conditions; + ENUM_X_DIRECTION trend = X_DIRECTION_NONE; + ENUM_X_DIRECTION signalBoxDir = X_DIRECTION_NONE; + + // + // Detecting Pivots ... + // detector.Detect( + // zIndex // + // ); + + // + // Validate Pivots ... + // detector.Validate( + // unAvailableBoxes, + // zIndex // + // ); + + // + // if (detector.pivotDetectionLoopbac > 100) + // { + // detector.pivotDetectionLoopbac = 100; + // } + + // + // Draw Founded Pivots ... + // drawer.Draw(cTime); + + // + // drawer.DrawPeakPivots(cTime); + // drawer.DrawValePivots(cTime); + // drawer.DrawFVGBullishPivots(cTime); + // drawer.DrawFVGBearishPivots(cTime); + // drawer.DrawTrendBullishPivots(cTime); + // drawer.DrawTrendBearishPivots(cTime); + + // + // Retrieve Valid Pviots ... + // pivotsCount = detector.FillPivots(pivots); + // hasPivots = IsValidSize(pivotsCount); + + // + // Filter UnAvailable Boxes ... + // if (hasPivots) + // { + // // + // // Remove UnAvailable Boxes ... + // has = HasChild(unAvailableBoxes); + // if (has) + // { + // // + // count = ArraySize(unAvailableBoxes); + // for (int i = 0; i < count; i++) + // { + // // + // XBoxZone iBox = unAvailableBoxes[i]; + + // // + // has = FindBoxIndex( + // idx, + // iBox, + // pivots // + // ); + // if (has) + // { + // // + // ArrayRemove( + // pivots, + // idx, + // 1 // + // ); + // } + // } + // } + + // // + // hasPivots = HasChild(pivots); + // pivotsCount = ArraySize(pivots); + // } + + // + // + // + + // + TestDetectSignal( + helper, + drawer, + signalBox, + signalBoxDir, + conditions, + zIndex, + loopback // + ); + + // // + // // Detect Sinal Box ... + // hasSignalBox = DetectXCAEAConditions( + // drawer, + // trend, + // pivots, + // conditions, + // pivotBox, + // signalBox, + // targets, + // additionalSL, + // signalBoxDir, + // helper, + // zIndex, + // loopback // + // ); + + // + // Make Pivot Box UnAvailable ... + if (pivotBox.IsValid()) + { + // + AddRef( + pivotBox, + unAvailableBoxes // + ); + } + + // + // Make Signal Box UnAvailable ... + if (signalBox.IsValid()) + { + // + AddRef( + signalBox, + unAvailableBoxes // + ); + } + + // + isBullish = hasSignalBox && + IsBullish(signalBoxDir); + + // + isBearish = hasSignalBox && + IsBearish(signalBoxDir); + + // + result = isBullish || + isBearish; + if (result) + { + // + // Do What we Want ... + barTraker.Waits(); + + // + // Draw Signal Box ... + XCBoxObject *iObj; + bool isCreated = helper.poiDrawer.DrawBox( + signalBox, + iObj // + ); + if (isCreated) + { + // + mObjects.Add(iObj); + ZeroMemory(iObj); + + // + // Print("Signal Box ..."); + } + + // + // Prepare Conditions ... + mConditions.symbol = symbol; + mConditions.period = period; + + // + double spread = GetSpread(symbol); + + // + double entry = + isBullish + ? signalBox.upper + : signalBox.lower; + + // + double sl = + isBullish + ? signalBox.lower + : signalBox.upper; + if (additionalSL > 0) + { + // + sl = + isBullish + ? sl - additionalSL + : sl + additionalSL; + } + + // + double risk = + isBullish + ? entry - sl + : sl - entry; + risk += spread; + if (risk >= maxAllowedSLDistanceInPoint * points) + { + // + // Fix Risk in Big Distances ... + double hh5 = zBar.FindHighest(5, MODE_HIGH); + double ll5 = zBar.FindLowest(5, MODE_LOW); + + // + double hhll5Delta = hh5 - ll5; + double riskDelta = hhll5Delta / 2; + risk = riskDelta; + } + + // + double rewardTP = risk * tpReward; + + // + double tp = + isBullish + ? entry + rewardTP + : entry - rewardTP; + + // + // Filling ... + mConditions.sl = sl; + mConditions.tp = tp; + mConditions.pivot = + isBullish + ? sl + : entry; + mConditions.point = + isBullish + ? entry + : sl; + mConditions.dir = signalBoxDir; + mConditions.provider = "XCAEA"; + mConditions.signalBox = signalBox; + mConditions.setupTime = zBar.time; + mConditions.conditions = conditions; + + // + // Targets Preparing ... + if (useTargets) + { + // + Copy( + targets, + mConditions.targets // + ); + + // + // Select RF Rewards ... + if (continuesRFTillTarget) + { + // + double rfReward = 1; + while (rfReward < tpReward) + { + // + double rewardRF = risk * rfReward; + double rfTP = + isBullish + ? entry + rewardRF + : entry - rewardRF; + + // + Add( + rfTP, + mConditions.targets // + ); + + // + rfReward++; + } + } + else + { + // + double rfReward = 2; + + // + double rewardRF = risk * rfReward; + double rfTP = + isBullish + ? entry + rewardRF + : entry - rewardRF; + + // + Add( + rfTP, + mConditions.targets // + ); + } + + // + // Detect Rf on Invalid Pivots ... + if (rfOnInvalidPivots) + { + // + has = detector.HasInvalidPivots(); + if (has) + { + // + XBoxZone targetBox; + double targetBoxPrice = 0; + count = detector.CountInvalidPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iPivot = detector.invalidPivots[i]; + + // + bool isValidPivot = + Contains( + "XCA_PEAKSWHRES", + iPivot.type // + ) || + Contains( + "XCA_VALESWLSUP", + iPivot.type // + ) || + Contains( + "XCA_FVG", + iPivot.type // + ); + if (!isValidPivot) + { + // + iPivot.Clean(); + continue; + } + + // + double selectedPrice = + isBullish + ? iPivot.lower - (5 * points) + : iPivot.upper + (5 * points); + + // + double targetBoxSelectedPrice = + isBullish + ? targetBox.lower - (5 * points) + : targetBox.upper + (5 * points); + + // + bool isDirPassed = iPivot.dir = signalBoxDir; + bool isPricePassed = + isBullish + ? entry < selectedPrice + : entry > selectedPrice; + bool canSetTarget = + !targetBox.IsValid() + ? true + : isBullish + ? targetBoxSelectedPrice > selectedPrice + : targetBoxSelectedPrice < selectedPrice; + if (canSetTarget) + { + // + targetBox = iPivot; + targetBoxPrice = targetBoxSelectedPrice; + } + + // + iPivot.Clean(); + } + + // + if (targetBox.IsValid() && + targetBoxPrice > 0) + { + // + Add( + targetBoxPrice, + mConditions.targets // + ); + } + + // + targetBox.Clean(); + } + } + } + } + + // + // Cleanup Resource ... + + // + Clean(pivots); + + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + pPBar.Clean(); + + // + pivotBox.Clean(); + signalBox.Clean(); + conditions.Clean(); + + // + return result; + } + + /** + * Detect Trigger Conditions for Specified Signal ... + * + * @param conditions: XCAEAStrategyConditions instance Reference, Specified Signal Conditions ... + * @param maxAllowedSetupAge: specified Setup Age for Expiration (if bigger than Zero) ... + * + * @return ( bool ) + */ + bool DetectSignalTrigger( + XCAEAStrategyConditions &conditions, + int maxAllowedSetupAge = 60 // + ) + { + // + bool result = false; + + // + result = conditions.IsSetuped(); + if (!result) + { + return result; + } + + // + datetime setupTime = conditions.setupTime; + ENUM_X_DIRECTION setupDir = conditions.dir; + + // + bool isBullish = IsBullish(setupDir); + bool isBearish = IsBearish(setupDir); + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + int loopback = 10; + + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + double points = GetPoints(symbol); + + // + // Check Signal Validation ... + // IMPORTANT: since all Validations done in SetUp Process ... + // here we only Execute Signal ... + + // + result = isBullish || + isBearish; + + // + if (result) + { + // + conditions.triggerTime = cTime; + conditions.type = isBullish + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_SHORT; + + // + } + + // + // Cleanup ... + + // + 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( + XCAEAGuard &guards[], + const XPosition &positions[] // + ) + { + // + bool result = false; + + // + return result; + } + + /** + * Add Conditions to Conditions Collection if not Exists ... + * + * @param maxAllowed: int, Specified Max Allowed Holding Conditions ... + * + * @return ( int ) + */ + int AddConditionsIfNotExists( + int maxAllowed = 10 // + ) + { + // + int result = 0; + + // + bool isSetuped = IsValid(mConditions.setupTime) && + HasDirection(mConditions.dir); + if (!isSetuped) + { + return result; + } + + // + int count = ArraySize(mConditionsCollection); + if (IsValidSize(count)) + { + // + // Copy Original Items ... + XCAEAStrategyConditions tmpItems[]; + Copy( + mConditionsCollection, + tmpItems // + ); + + // + // Prese Item Data ... + bool isBullish = IsBullish(mConditions.dir); + + // + for (int i = 0; i < count; i++) + { + // + XCAEAStrategyConditions 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; + } + + // + // Protected ... + protected: + // + + // + // Private ... + private: + // + // Props ... + string symbol; + ENUM_TIMEFRAMES period; + CArrayObj mObjects; + CArrayObj mBarObjects; + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14040218 XCAEA/Documents/BKP/signallers1/xcaea.signaller.lib.mq5 b/BKPS/14040218 XCAEA/Documents/BKP/signallers1/xcaea.signaller.lib.mq5 new file mode 100644 index 0000000..91ae70d --- /dev/null +++ b/BKPS/14040218 XCAEA/Documents/BKP/signallers1/xcaea.signaller.lib.mq5 @@ -0,0 +1,2810 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XCAEASignaller Lib +// Description: Library for XCAEA 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 Library for XCAEA Signaller" +#property strict + +// +// Imports ... +#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/xcaea.x-poi.detector.class.mq5" +#include "../Classes/xcaea.x-poi.drawer.class.mq5" +#include "../Helpers/xcaea.helper.mq5" + +// +// Enumeration ... + +// +// Guard Actions ... +enum ENUM_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_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 ... + +// +// Conditions Struct ... +struct XCAEAStrategyConditions +{ + // + // Props ... + + // + string symbol; + ENUM_TIMEFRAMES period; + + // + // Setup Props ... + + // + double sl; + double tp; + double pivot; + double point; + string provider; + double targets[]; + + // + datetime time; + datetime setupTime; + datetime triggerTime; + + // + XBoxZone signalBox; + ENUM_X_DIRECTION dir; + ENUM_X_POSITION_TYPES type; + XCAEAConditions conditions; + + // + // Constructor ... + XCAEAStrategyConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + sl = 0; + tp = 0; + pivot = 0; + point = 0; + + // + symbol = NULL; + period = NULL; + provider = NULL; + + // + time = NULL; + setupTime = NULL; + triggerTime = NULL; + + // + Clean(targets); + + // + signalBox.Clean(); + conditions.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; + } + + // +}; + +// +// Model a Guard Action ... +struct XCAEAGuard +{ + // + // Props ... + ENUM_GUARD_ACTIONS action; + datetime time; + + // + string symbol; + string provider; + + // + // Specified Position ... + ulong ticket; + + // + // Partial Close ... + double volumeMultiplier; + + // + // SL Trial ... + double sl; + + // + // TP Trial ... + double tp; + + // + // Constructor ... + XCAEAGuard() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + time = NULL; + action = X_GUARD_ACTION_NONE; + + // + symbol = NULL; + provider = NULL; + + // + ticket = 0; + + // + volumeMultiplier = 0; + + // + sl = 0; + tp = 0; + + // + ZeroMemory(this); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsValid(time) && + IsValid(symbol) && + IsValid(provider) && + action != X_GUARD_ACTION_NONE + // + ; + if (!result) + { + return result; + } + + // + // Validate Model Based On Specified Guard Actions ... + + // + return result; + } +}; + +/** + * Add Guard to Collection ... + * + * @param guard: XCAEAGuard instance ... + * @param guards: XCAEAGuard instance Collection ... + * + * @return ( int ) + */ +int AddGuard( + XCAEAGuard &guard, + XCAEAGuard &guards[] // +) +{ + // + int result = 0; + + // + if (!guard.IsValid()) + { + return result; + } + + // + AddRef( + guard, + guards // + ); + + // + result = ArraySize(guards); + + // + return result; +} + +// +bool TestDetectSignal( + XCXCAEAHelper *helper, + XCXCAEAPOIDrawer *drawer, + XBoxZone &box, + ENUM_X_DIRECTION &dir, + XCAEAConditions &conditions, + int barIndex = 0, + int loopback = 10 // +) +{ + // + bool result = false; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + box.Clean(); + conditions.Clean(); + dir = X_DIRECTION_NONE; + barIndex = NormalizeInt(barIndex, 0); + loopback = NormalizeInt(loopback, 5); + + // + // Retrieve Some Requirements ... + string symbol = helper.GetSymbol(); + ENUM_TIMEFRAMES period = helper.GetPeriod(); + double points = GetPoints(symbol); + + // + // Retrieve Conditions for Processing ... + result = helper.GetConditions( + conditions, + barIndex, + loopback // + ); + if (!result) + { + // + box.Clean(); + conditions.Clean(); + + // + return result; + } + + // + // Define IDXses ... + int zIDX = barIndex; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + int p3IDX = p2IDX + 1; + int p4IDX = p3IDX + 1; + + // + XOHCL zBar; + XOHCL cBar; + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + XOHCL p4Bar; + result = zBar.Init( + symbol, + period, + zIDX // + ); + result = + result && + zBar.GetPreviousBar(cBar); + result = + result && + cBar.GetPreviousBar(pBar); + result = + result && + pBar.GetPreviousBar(p2Bar); + result = + result && + p2Bar.GetPreviousBar(p3Bar); + result = + result && + p3Bar.GetPreviousBar(p4Bar); + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + box.Clean(); + conditions.Clean(); + + // + return result; + } + + // + // Bars Conditions ... + + // + // Score ... + + // + double bullishScore = 0; + double bearishScore = 0; + conditions.GenerateScore( + bullishScore, + bearishScore // + ); + + // + bool isScoreBullish = + bullishScore > bearishScore; + + // + bool isScoreBearish = + bearishScore > bullishScore; + + // + bool isScoreNeutural = MathAbs(bullishScore - bearishScore) == 0; + + // + // Calculating Range Volumes ... + + // + double bullishVolume = 0; + double bearishVolume = 0; + helper.barAnalyser.CalculateRangeVolume( + cBar, + bullishVolume, + bearishVolume, + loopback // + ); + + // + bool isVolumeNeutural = MathAbs(bullishVolume - bearishVolume) == 0; + + // + // Reading Values ... + + // + // 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]; + + // + // PEAK ... + 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 p4Peak = conditions.peakBuffer[p4IDX]; + + // + // VALE ... + 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]; + double p4Vale = conditions.valeBuffer[p4IDX]; + + // + // SWING Low ... + double zSWL = conditions.swingLowBuffer[zIDX]; + double cSWL = conditions.swingLowBuffer[cIDX]; + double pSWL = conditions.swingLowBuffer[pIDX]; + double p2SWL = conditions.swingLowBuffer[p2IDX]; + double p3SWL = conditions.swingLowBuffer[p3IDX]; + + // + // SWING High ... + double zSWH = conditions.swingHighBuffer[zIDX]; + double cSWH = conditions.swingHighBuffer[cIDX]; + double pSWH = conditions.swingHighBuffer[pIDX]; + double p2SWH = conditions.swingHighBuffer[p2IDX]; + double p3SWH = conditions.swingHighBuffer[p3IDX]; + + // + // SUPPORT ... + double zSupport = conditions.supportBuffer[zIDX]; + double cSupport = conditions.supportBuffer[cIDX]; + double pSupport = conditions.supportBuffer[pIDX]; + double p2Support = conditions.supportBuffer[p2IDX]; + double p3Support = conditions.supportBuffer[p3IDX]; + + // + // RESISTANCE ... + double zResistance = conditions.resistanceBuffer[zIDX]; + double cResistance = conditions.resistanceBuffer[cIDX]; + double pResistance = conditions.resistanceBuffer[pIDX]; + double p2Resistance = conditions.resistanceBuffer[p2IDX]; + double p3Resistance = conditions.resistanceBuffer[p3IDX]; + + // + // MAH ... + double zMAH = conditions.mahBuffer[zIDX]; + double cMAH = conditions.mahBuffer[cIDX]; + double pMAH = conditions.mahBuffer[pIDX]; + double p2MAH = conditions.mahBuffer[p2IDX]; + double p3MAH = conditions.mahBuffer[p3IDX]; + + // + // MAL ... + double zMAL = conditions.malBuffer[zIDX]; + double cMAL = conditions.malBuffer[cIDX]; + double pMAL = conditions.malBuffer[pIDX]; + double p2MAL = conditions.malBuffer[p2IDX]; + double p3MAL = conditions.malBuffer[p3IDX]; + + // + // MAC ... + double zMAC = conditions.macBuffer[zIDX]; + double cMAC = conditions.macBuffer[cIDX]; + double pMAC = conditions.macBuffer[pIDX]; + double p2MAC = conditions.macBuffer[p2IDX]; + double p3MAC = conditions.macBuffer[p3IDX]; + + // + // FIBO Level 1 ... + double zFib1 = conditions.fiboLevel1Buffer[zIDX]; + double cFib1 = conditions.fiboLevel1Buffer[cIDX]; + double pFib1 = conditions.fiboLevel1Buffer[pIDX]; + double p2Fib1 = conditions.fiboLevel1Buffer[p2IDX]; + double p3Fib1 = conditions.fiboLevel1Buffer[p3IDX]; + + // + // FIBO Level 2 ... + double zFib2 = conditions.fiboLevel2Buffer[zIDX]; + double cFib2 = conditions.fiboLevel2Buffer[cIDX]; + double pFib2 = conditions.fiboLevel2Buffer[pIDX]; + double p2Fib2 = conditions.fiboLevel2Buffer[p2IDX]; + double p3Fib2 = conditions.fiboLevel2Buffer[p3IDX]; + + // + // FIBO Level 3 ... + double zFib3 = conditions.fiboLevel3Buffer[zIDX]; + double cFib3 = conditions.fiboLevel3Buffer[cIDX]; + double pFib3 = conditions.fiboLevel3Buffer[pIDX]; + double p2Fib3 = conditions.fiboLevel3Buffer[p2IDX]; + double p3Fib3 = conditions.fiboLevel3Buffer[p3IDX]; + + // + // FIBO Level 4 ... + double zFib4 = conditions.fiboLevel4Buffer[zIDX]; + double cFib4 = conditions.fiboLevel4Buffer[cIDX]; + double pFib4 = conditions.fiboLevel4Buffer[pIDX]; + double p2Fib4 = conditions.fiboLevel4Buffer[p2IDX]; + double p3Fib4 = conditions.fiboLevel4Buffer[p3IDX]; + + // + // FIBO Level 5 ... + double zFib5 = conditions.fiboLevel5Buffer[zIDX]; + double cFib5 = conditions.fiboLevel5Buffer[cIDX]; + double pFib5 = conditions.fiboLevel5Buffer[pIDX]; + double p2Fib5 = conditions.fiboLevel5Buffer[p2IDX]; + double p3Fib5 = conditions.fiboLevel5Buffer[p3IDX]; + + // + // FAST ... + double zFast = conditions.fastBuffer[zIDX]; + double cFast = conditions.fastBuffer[cIDX]; + double pFast = conditions.fastBuffer[pIDX]; + double p2Fast = conditions.fastBuffer[p2IDX]; + double p3Fast = conditions.fastBuffer[p3IDX]; + + // + // FAST State ... + double zFastState = conditions.fastStateBuffer[zIDX]; + double cFastState = conditions.fastStateBuffer[cIDX]; + double pFastState = conditions.fastStateBuffer[pIDX]; + double p2FastState = conditions.fastStateBuffer[p2IDX]; + double p3FastState = conditions.fastStateBuffer[p3IDX]; + + // + // Create Custom Conditions ... + + // + // Bar and Fibo Conditions ... + + // + // Bearish ... + + // + // Strong Reversal ... + bool isZBarOnFiboStrongBearish = zBar.low > zFib5; + bool isCBarOnFiboStrongBearish = cBar.low > cFib5; + bool isPBarOnFiboStrongBearish = pBar.low > pFib5; + bool isP2BarOnFiboStrongBearish = p2Bar.low > p2Fib5; + bool isP3BarOnFiboStrongBearish = p3Bar.low > p3Fib5; + + // + // Golden Zone Reversal ... + bool isZBarOnFiboGoldenBearish = zBar.low > zFib3 && + zBar.high < zFib4; + bool isCBarOnFiboGoldenBearish = cBar.low > cFib3 && + cBar.high < cFib4; + bool isPBarOnFiboGoldenBearish = pBar.low > pFib3 && + pBar.high < pFib4; + bool isP2BarOnFiboGoldenBearish = p2Bar.low > p2Fib3 && + p2Bar.high < p2Fib4; + bool isP3BarOnFiboGoldenBearish = p3Bar.low > p3Fib3 && + p3Bar.high < p3Fib4; + + // + // Bullish ... + + // + // Strong Reversal ... + bool isZBarOnFiboStrongBullish = zBar.high < zFib1; + bool isCBarOnFiboStrongBullish = cBar.high < cFib1; + bool isPBarOnFiboStrongBullish = pBar.high < pFib1; + bool isP2BarOnFiboStrongBullish = p2Bar.high < p2Fib1; + bool isP3BarOnFiboStrongBullish = p3Bar.high < p3Fib1; + + // + // Golden Zone Reversal ... + bool isZBarOnFiboGoldenBullish = zBar.low > zFib2 && + zBar.high < zFib3; + bool isCBarOnFiboGoldenBullish = cBar.low > cFib2 && + cBar.high < cFib3; + bool isPBarOnFiboGoldenBullish = pBar.low > pFib2 && + pBar.high < pFib3; + bool isP2BarOnFiboGoldenBullish = p2Bar.low > p2Fib2 && + p2Bar.high < p2Fib3; + bool isP3BarOnFiboGoldenBullish = p3Bar.low > p3Fib2 && + p3Bar.high < p3Fib3; + + // + // Score and Volume Conditions ... + + // + bool isScoreVolumeNeutural = isScoreNeutural || + isVolumeNeutural; + + // + bool isScoreVolumeNeuturalInFiboStrongBullish = + isScoreNeutural && + isCBarOnFiboStrongBullish; + + // + bool isScoreVolumeNeuturalInFiboGoldenBullish = + isScoreNeutural && + isCBarOnFiboGoldenBullish; + + // + bool isScoreVolumeNeuturalInFiboStrongBearish = + isScoreNeutural && + isCBarOnFiboStrongBearish; + + // + bool isScoreVolumeNeuturalInFiboGoldenBearish = + isScoreNeutural && + isCBarOnFiboGoldenBearish; + + // + bool isScoreVolumeNeuturalBullishPowered = + isScoreVolumeNeuturalInFiboStrongBullish || + isScoreVolumeNeuturalInFiboGoldenBullish; + + // + bool isScoreVolumeNeuturalBearishPowered = + isScoreVolumeNeuturalInFiboStrongBearish || + isScoreVolumeNeuturalInFiboGoldenBearish; + + // + // PEAK and VALES ... + + // + // PEAK Pivot ... + bool isZIsPeakPivot = + zPeak == cPeak && + zPeak == zSWH && + zPeak == zResistance && + isZBarOnFiboStrongBearish; + bool isCIsPeakPivot = + cPeak == pPeak && + cPeak == cSWH && + cPeak == cResistance && + isCBarOnFiboStrongBearish; + bool isPIsPeakPivot = + pPeak == p2Peak && + pPeak == pSWH && + pPeak == pResistance && + isPBarOnFiboStrongBearish; + bool isP2IsPeakPivot = + p2Peak == p3Peak && + p2Peak == p2SWH && + p2Peak == p2Resistance && + isP2BarOnFiboStrongBearish; + bool isP3IsPeakPivot = + p3Peak == p4Peak && + p3Peak == p3SWH && + p3Peak == p3Resistance && + isP3BarOnFiboStrongBearish; + + // + // VALE Pivot ... + bool isZIsValePivot = + zVale == cVale && + zVale == zSWL && + zVale == zSupport && + isZBarOnFiboStrongBullish; + bool isCIsValePivot = + cVale == pVale && + cVale == cSWL && + cVale == cSupport && + isCBarOnFiboStrongBullish; + bool isPIsValePivot = + pVale == p2Vale && + pVale == pSWL && + pVale == pSupport && + isPBarOnFiboStrongBullish; + bool isP2IsValePivot = + p2Vale == p3Vale && + p2Vale == p2SWL && + p2Vale == p2Support && + isP2BarOnFiboStrongBullish; + bool isP3IsValePivot = + p3Vale == p4Vale && + p3Vale == p3SWL && + p3Vale == p3Support && + isP3BarOnFiboStrongBullish; + + // + // FIBO Section Change Detection ... + bool isFiboSectionChanged = + // + (cFib1 != pFib1 && + cFib2 != pFib2 && + cFib3 != pFib3 && + cFib4 != pFib4 && + cFib5 != pFib5) + // + && + // + (conditions.isPeakUnderLast || + conditions.isValeOverLast || + conditions.isSwingLowOverLast || + conditions.isSwingHighUnderLast) + // + ; + + // + // SAR Change ... + + // + bool isSarSwitchedInFiboStrongBullish = + isCBarOnFiboStrongBullish && + conditions.isSarSwitchedToBullish; + + // + bool isSarSwitchedInFiboGoldenBullish = + isCBarOnFiboGoldenBullish && + conditions.isSarSwitchedToBullish; + + // + bool isSarSwitchedInFiboStrongBearish = + isCBarOnFiboStrongBearish && + conditions.isSarSwitchedToBearish; + + // + bool isSarSwitchedInFiboGoldenBearish = + isCBarOnFiboGoldenBearish && + conditions.isSarSwitchedToBearish; + + // + bool isSarSwitchedToBullish = + cFastState > 0 && + isSarSwitchedInFiboStrongBullish; + + // + bool isSarSwitchedToBearish = + cFastState < 0 && + isSarSwitchedInFiboStrongBearish; + ; + + // + // Testing Conditions ... + + // + // Detect Fibo Section Changed ... + if (isFiboSectionChanged) + { + // Print("Fibo Section Changed ..."); + } + + // + // PVPivot Conditions ... + if (isCIsPeakPivot || + isCIsValePivot) + { + // // + // ENUM_X_DIRECTION iPVPivotDir = + // isCIsValePivot + // ? X_DIRECTION_BULLISH + // : X_DIRECTION_BEARISH; + + // // + // int timeOffset = (int)cBar.time; + // string iName = ToString(iPVPivotDir) + "_PVPVT_" + ToString(timeOffset); + // color iColor = isCIsValePivot + // ? clrAqua + // : clrMagenta; + // ENUM_LINE_STYLE iStyle = STYLE_DOT; + + // // + // CChartObjectVLine *iObj; + // iObj = new CChartObjectVLine(); + // has = iObj.Create( + // 0, + // iName, + // 0, + // cBar.time // + // ); + // if (has) + // { + // // + // iObj.Color(iColor); + // iObj.Style(iStyle); + // } + + // // + // Print("Conditions Finder ..."); + } + + // + // Testing Sar Changes ... + if (isSarSwitchedToBullish || + isSarSwitchedToBearish) + { + // + // ENUM_X_DIRECTION iSarChangeDir = + // isSarSwitchedToBullish + // ? X_DIRECTION_BULLISH + // : X_DIRECTION_BEARISH; + + // // + // int timeOffset = (int)cBar.time; + // string iName = ToString(iSarChangeDir) + "_SAR_" + ToString(timeOffset); + // color iColor = isSarSwitchedToBullish + // ? clrAqua + // : clrMagenta; + // ENUM_LINE_STYLE iStyle = STYLE_DOT; + + // // + // CChartObjectVLine *iObj; + // iObj = new CChartObjectVLine(); + // has = iObj.Create( + // 0, + // iName, + // 0, + // cBar.time // + // ); + // if (has) + // { + // // + // iObj.Color(iColor); + // iObj.Style(iStyle); + // } + + // + // Print("Conditions Finder ..."); + } + + // + // Score and Volume Conditions ... + if (isScoreVolumeNeuturalBullishPowered || + isScoreVolumeNeuturalBearishPowered) + { + // + // ENUM_X_DIRECTION iScoreVolumeDir = + // isScoreVolumeNeuturalBullishPowered + // ? X_DIRECTION_BULLISH + // : X_DIRECTION_BEARISH; + + // // + // int timeOffset = (int)cBar.time; + // string iName = ToString(iScoreVolumeDir) + "_SCVM_" + ToString(timeOffset); + // color iColor = isScoreVolumeNeuturalBullishPowered + // ? clrAqua + // : clrMagenta; + // ENUM_LINE_STYLE iStyle = STYLE_DOT; + + // + // CChartObjectVLine *iObj; + // iObj = new CChartObjectVLine(); + // has = iObj.Create( + // 0, + // iName, + // 0, + // cBar.time // + // ); + // if (has) + // { + // // + // iObj.Color(iColor); + // iObj.Style(iStyle); + // } + + // // + // Print("Conditions Finder ..."); + } + + // + // Custom Senarios ... + + // + bool isCond1Bullish = + isCIsValePivot && + !isFiboSectionChanged && + isSarSwitchedToBullish; + + // + bool isCond1Bearish = + isCIsPeakPivot && + !isFiboSectionChanged && + isSarSwitchedToBearish; + + // + bool isCond1 = + isCond1Bullish || + isCond1Bearish; + if (isCond1) + { + // + ENUM_X_DIRECTION iCond1Dir = + isCond1Bullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + int timeOffset = (int)cBar.time; + string iName = ToString(iCond1Dir) + "_COND1_" + ToString(timeOffset); + color iColor = isCond1Bullish + ? clrAqua + : clrMagenta; + ENUM_LINE_STYLE iStyle = STYLE_DOT; + + // + CChartObjectVLine *iObj; + iObj = new CChartObjectVLine(); + has = iObj.Create( + 0, + iName, + 0, + cBar.time // + ); + if (has) + { + // + iObj.Color(iColor); + iObj.Style(iStyle); + } + + // + // Create Signal Box Based on Cond1 ... + + // + double upper = + isCond1Bullish + ? cBar.FindHighest(5, MODE_HIGH) + : MathMax(cPeak, cSWH); + + // + double lower = + isCond1Bullish + ? MathMin(cVale, cSWL) + : cBar.FindLowest(5, MODE_LOW); + + // + int toIDX = cBar.Index(); + int fromIDX = cBar.Index() + 5; + + // + datetime toTime = GetBarTime( + symbol, + period, + toIDX // + ); + datetime fromTime = GetBarTime( + symbol, + period, + fromIDX // + ); + + // + XBoxZone iBox; + + // + iBox.to = toTime; + iBox.upper = upper; + iBox.lower = lower; + iBox.type = "COND1"; + iBox.symbol = symbol; + iBox.period = period; + iBox.dir = iCond1Dir; + iBox.from = fromTime; + + // + has = iBox.IsValid(); + if (has) + { + // + XCBoxObject *iObj; + has = helper + .poiDrawer + .DrawBox( + iBox, + iObj // + ); + if (has) + { + // + // Style Object ... + } + } + + // + iBox.Clean(); + + // + // Print("Conditions Finder ..."); + } + + // + // Summarise Result ... + + // + bool isBullish = false; + bool isBearish = false; + + // + result = isBullish || + isBearish; + if (result) + { + // + // Do Signal Preparing ... + + // + // Check Box is Prepared or Not ... + result = box.IsValid(); + } + + // + // Cleaning Up ... + + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + if (!result) + { + // + box.Clean(); + conditions.Clean(); + } + + // + return result; +} + +// +// Cond 2 ... +// - a PV Box is Sweep Liquidity; +// - a Directional FVg Occures Exactly after Liquidity Sweep; +// - Price Action Go Inside FVG; +// - SL behind FVG; + +// +bool DetectXCAEAConditions( + XCXCAEAPOIDrawer *drawer, + XBoxZone &pivots[], + XCAEAConditions &conditions, + XBoxZone &pivotBox, + XBoxZone &box, + double &targets[], + double &additionalSL, + ENUM_X_DIRECTION &dir, + XCXCAEAHelper *helper, + int barIndex = 0, + int loopback = 10 // +) +{ + // + bool result = false; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + box.Clean(); + additionalSL = 0; + conditions.Clean(); + dir = X_DIRECTION_NONE; + + // + if (barIndex < 0) + { + barIndex = 0; + } + loopback = NormalizeInt(loopback, 5); + + // + // Retrieve Some Requirements ... + string symbol = helper.GetSymbol(); + ENUM_TIMEFRAMES period = helper.GetPeriod(); + double points = GetPoints(symbol); + + // + // Trend Parsing ... + // bool hasTrend = HasDirection(trend); + // bool hasBullishTrend = hasTrend && + // IsBullish(trend); + // bool hasBearishTrend = hasTrend && + // IsBearish(trend); + + // + // Retrieve Previous and Current Bar Conditions ... + XCAEAConditions pConditions; + result = helper.GetConditions( + conditions, + barIndex, + loopback // + ); + result = result && + helper.GetConditions( + pConditions, + barIndex + 1, + loopback // + ); + if (!result) + { + // + conditions.Clean(); + pConditions.Clean(); + + // + return result; + } + + // + // Define IDXses ... + int zIDX = barIndex; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + int p3IDX = p2IDX + 1; + int p4IDX = p3IDX + 1; + + // + // Reading Bars ... + + // + XOHCL zBar; + XOHCL cBar; + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + XOHCL p4Bar; + result = zBar.Init( + symbol, + period, + zIDX // + ); + result = + result && + zBar.GetPreviousBar(cBar); + result = + result && + cBar.GetPreviousBar(pBar); + result = + result && + pBar.GetPreviousBar(p2Bar); + result = + result && + p2Bar.GetPreviousBar(p3Bar); + result = + result && + p3Bar.GetPreviousBar(p4Bar); + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + box.Clean(); + conditions.Clean(); + pConditions.Clean(); + + // + return result; + } + + // + // Bars Conditions ... + + // + // Temparory Bar Direction ... + ENUM_X_DIRECTION cBarDir; + + // + // Hammer ... + bool isCBarHammer = helper + .barAnalyser + .IsHammer( + cBar, + cBarDir // + ); + bool isCBarBullishHammer = + isCBarHammer && + IsBullish(cBarDir); + bool isCBarBearishHammer = + isCBarHammer && + IsBearish(cBarDir); + + // + // Rejected ... + bool isCBarRejected = helper + .barAnalyser + .IsRejected( + cBar, + cBarDir, + false, // Force Type ... + true // Force Fibo Pressure ... + ); + bool isCBarBullishRejected = + isCBarRejected && + IsBullish(cBarDir); + bool isCBarBearishRejected = + isCBarRejected && + IsBearish(cBarDir); + + // + // Engulfed ... + bool isCBarEngulfed = helper + .barAnalyser + .IsEngulfed( + cBar, + cBarDir // + ); + bool isCBarBullishEngulfed = + isCBarEngulfed && + IsBullish(cBarDir); + bool isCBarBearishEngulfed = + isCBarEngulfed && + IsBearish(cBarDir); + + // + // Momentum ... + bool isCBarMomentum = helper + .barAnalyser + .IsMomentum( + cBar, + cBarDir, + 1 // + ); + bool isCBarBullishMomentum = + isCBarMomentum && + IsBullish(cBarDir); + bool isCBarBearishMomentum = + isCBarMomentum && + IsBearish(cBarDir); + + // + // Bar Sumarise ... + + // + bool isCBarValidForBullish = + (isCBarBullishHammer || + isCBarBullishRejected || + isCBarBullishMomentum || + isCBarBullishEngulfed); + + // + bool isCBarValidForBearish = + (isCBarBearishHammer || + isCBarBearishRejected || + isCBarBearishMomentum || + isCBarBearishEngulfed); + + // + // Score ... + + // + double bullishScore = 0; + double bearishScore = 0; + conditions.GenerateScore( + bullishScore, + bearishScore // + ); + + // + bool isScoreBullish = + bullishScore > bearishScore; + + // + bool isScoreBearish = + bearishScore > bullishScore; + + // + bool isScoreNeutural = MathAbs(bullishScore - bearishScore) == 0; + + // + // Calculating Range Volumes ... + + // + double bullishVolume = 0; + double bearishVolume = 0; + int volumeRangeLoopback = loopback; + helper.barAnalyser.CalculateRangeVolume( + cBar, + bullishVolume, + bearishVolume, + volumeRangeLoopback // + ); + + // + bool isVolumeNeutural = MathAbs(bullishVolume - bearishVolume) == 0; + + // + double rangeVolume = bullishVolume == bearishVolume; + double rangeVolumeAvg = rangeVolume / volumeRangeLoopback; + + // + bool isVolumeBullish = bullishVolume > bearishVolume; + bool isVolumeBearish = bullishVolume < bearishVolume; + bool isVolumeOverLast = cBar.volume > pBar.volume; + bool isVolumeOverAvg = cBar.volume > rangeVolumeAvg; + + // + // Conditions ... + + // + // SAR ... + double zSar = conditions.sarBuffer[zIDX]; + double cSar = conditions.sarBuffer[cIDX]; + double pSar = conditions.sarBuffer[pIDX]; + double p2Sar = conditions.sarBuffer[p2IDX]; + + // + // PEAK ... + double zPeak = conditions.peakBuffer[zIDX]; + double cPeak = conditions.peakBuffer[cIDX]; + double pPeak = conditions.peakBuffer[pIDX]; + double p2Peak = conditions.peakBuffer[p2IDX]; + + // + // VALE ... + double zVale = conditions.valeBuffer[zIDX]; + double cVale = conditions.valeBuffer[cIDX]; + double pVale = conditions.valeBuffer[pIDX]; + double p2Vale = conditions.valeBuffer[p2IDX]; + + // + // PEAKGOLDEN ... + double zPeakGolden = conditions.peakGoldenBuffer[zIDX]; + double cPeakGolden = conditions.peakGoldenBuffer[cIDX]; + double pPeakGolden = conditions.peakGoldenBuffer[pIDX]; + double p2PeakGolden = conditions.peakGoldenBuffer[p2IDX]; + + // + // VALEGOLDEN ... + double zValeGolden = conditions.valeGoldenBuffer[zIDX]; + double cValeGolden = conditions.valeGoldenBuffer[cIDX]; + double pValeGolden = conditions.valeGoldenBuffer[pIDX]; + double p2ValeGolden = conditions.valeGoldenBuffer[p2IDX]; + + // + // SUPPORT ... + double zSupport = conditions.supportBuffer[zIDX]; + double cSupport = conditions.supportBuffer[cIDX]; + double pSupport = conditions.supportBuffer[pIDX]; + double p2Support = conditions.supportBuffer[p2IDX]; + + // + // RESISTANCE ... + double zResistance = conditions.resistanceBuffer[zIDX]; + double cResistance = conditions.resistanceBuffer[cIDX]; + double pResistance = conditions.resistanceBuffer[pIDX]; + double p2Resistance = conditions.resistanceBuffer[p2IDX]; + + // + // SWING LOW ... + double zSwingLow = conditions.swingLowBuffer[zIDX]; + double cSwingLow = conditions.swingLowBuffer[cIDX]; + double pSwingLow = conditions.swingLowBuffer[pIDX]; + double p2SwingLow = conditions.swingLowBuffer[p2IDX]; + + // + // SWING HIGH ... + double zSwingHigh = conditions.swingHighBuffer[zIDX]; + double cSwingHigh = conditions.swingHighBuffer[cIDX]; + double pSwingHigh = conditions.swingHighBuffer[pIDX]; + double p2SwingHigh = conditions.swingHighBuffer[p2IDX]; + + // + // TREND ... + double zTrend = conditions.trendBuffer[zIDX]; + double cTrend = conditions.trendBuffer[cIDX]; + double pTrend = conditions.trendBuffer[pIDX]; + double p2Trend = conditions.trendBuffer[p2IDX]; + + // + // KI ... + double zKI = conditions.kiBuffer[zIDX]; + double cKI = conditions.kiBuffer[cIDX]; + double pKI = conditions.kiBuffer[pIDX]; + double p2KI = conditions.kiBuffer[p2IDX]; + + // + // TKI ... + double zTKI = conditions.tkiBuffer[zIDX]; + double cTKI = conditions.tkiBuffer[cIDX]; + double pTKI = conditions.tkiBuffer[pIDX]; + double p2TKI = conditions.tkiBuffer[p2IDX]; + + // + // VIDYA ... + double zVIDYA = conditions.vidyaBuffer[zIDX]; + double cVIDYA = conditions.vidyaBuffer[cIDX]; + double pVIDYA = conditions.vidyaBuffer[pIDX]; + double p2VIDYA = conditions.vidyaBuffer[p2IDX]; + + // + // RSI ... + double zRSI = conditions.rsiBuffer[zIDX]; + double cRSI = conditions.rsiBuffer[cIDX]; + double pRSI = conditions.rsiBuffer[pIDX]; + double p2RSI = conditions.rsiBuffer[p2IDX]; + + // + // CCI ... + double zCCI = conditions.cciBuffer[zIDX]; + double cCCI = conditions.cciBuffer[cIDX]; + double pCCI = conditions.cciBuffer[pIDX]; + double p2CCI = conditions.cciBuffer[p2IDX]; + + // + // ATR ... + double zATR = conditions.atrBuffer[zIDX]; + double cATR = conditions.atrBuffer[cIDX]; + double pATR = conditions.atrBuffer[pIDX]; + double p2ATR = conditions.atrBuffer[p2IDX]; + + // + // ADX ... + double zADX = conditions.adxBuffer[zIDX]; + double cADX = conditions.adxBuffer[cIDX]; + double pADX = conditions.adxBuffer[pIDX]; + double p2ADX = conditions.adxBuffer[p2IDX]; + + // + // ADX P ... + double zADXP = conditions.adxpBuffer[zIDX]; + double cADXP = conditions.adxpBuffer[cIDX]; + double pADXP = conditions.adxpBuffer[pIDX]; + double p2ADXP = conditions.adxpBuffer[p2IDX]; + + // + // ADX N ... + double zADXN = conditions.adxnBuffer[zIDX]; + double cADXN = conditions.adxnBuffer[cIDX]; + double pADXN = conditions.adxnBuffer[pIDX]; + double p2ADXN = conditions.adxnBuffer[p2IDX]; + + // + // X3MA ... + + // + // FAST ... + + // + double z3MAFast = conditions.fastBuffer[zIDX]; + double c3MAFast = conditions.fastBuffer[cIDX]; + double p3MAFast = conditions.fastBuffer[pIDX]; + double p23MAFast = conditions.fastBuffer[p2IDX]; + + // + double z3MAFastState = conditions.fastStateBuffer[zIDX]; + double c3MAFastState = conditions.fastStateBuffer[cIDX]; + double p3MAFastState = conditions.fastStateBuffer[pIDX]; + double p23MAFastState = conditions.fastStateBuffer[p2IDX]; + + // + // MEDIUM ... + + // + double z3MAMedium = conditions.mediumBuffer[zIDX]; + double c3MAMedium = conditions.mediumBuffer[cIDX]; + double p3MAMedium = conditions.mediumBuffer[pIDX]; + double p23MAMedium = conditions.mediumBuffer[p2IDX]; + + // + double z3MAMediumState = conditions.mediumStateBuffer[zIDX]; + double c3MAMediumState = conditions.mediumStateBuffer[cIDX]; + double p3MAMediumState = conditions.mediumStateBuffer[pIDX]; + double p23MAMediumState = conditions.mediumStateBuffer[p2IDX]; + + // + // SLOW ... + + // + double z3MASlow = conditions.slowBuffer[zIDX]; + double c3MASlow = conditions.slowBuffer[cIDX]; + double p3MASlow = conditions.slowBuffer[pIDX]; + double p23MASlow = conditions.slowBuffer[p2IDX]; + + // + double z3MASlowState = conditions.slowStateBuffer[zIDX]; + double c3MASlowState = conditions.slowStateBuffer[cIDX]; + double p3MASlowState = conditions.slowStateBuffer[pIDX]; + double p23MASlowState = conditions.slowStateBuffer[p2IDX]; + + // + double x3maBullishGapUpper = c3MAMedium; + double x3maBullishGapLower = c3MASlow; + + // + double x3maBearishGapUpper = c3MASlow; + double x3maBearishGapLower = c3MAMedium; + + // + double cTrendValues[7] = { + cKI, + cTKI, + cTrend, + cVIDYA, + c3MAFast, + c3MASlow, + c3MAMedium, + }; + double pTrendValues[7] = { + pKI, + pTKI, + pTrend, + pVIDYA, + p3MAFast, + p3MASlow, + p3MAMedium, + }; + + // + double minCTrendValue = GetMin(cTrendValues); + double maxCTrendValue = GetMax(cTrendValues); + + // + double minPTrendValue = GetMin(pTrendValues); + double maxPTrendValue = GetMax(pTrendValues); + + // + double cTrendValuesRange = (maxCTrendValue - minCTrendValue); + double cTrendValuesRangePoint = (cTrendValuesRange / points); + + // + double pTrendValuesRange = (maxPTrendValue - minPTrendValue); + double pTrendValuesRangePoint = (pTrendValuesRange / points); + + // + // Create Conditions ... + + // + bool isPRSIOB = + pRSI > conditions.rsiOBLevel; + + // + bool isPRSIOS = + pRSI < conditions.rsiOSLevel; + + // + bool isRSIBullish = + cRSI > pRSI && + !conditions.isRSIOB; + + // + bool isRSIBearish = + cRSI < pRSI && + !conditions.isRSIOS; + + // + bool isPCCIOB = + pCCI > conditions.cciOBLevel; + + // + bool isPCCIOS = + pCCI < conditions.cciOSLevel; + + // + bool isCCIBullish = + cCCI > pCCI && + !conditions.isCCIOB; + + // + bool isCCIBearish = + cCCI < pCCI && + !conditions.isCCIOS; + + // + bool isADXBullish = + cADX > cADXN; + bool isADXBullishPrev = + pADX > pADXN; + + // + bool isADXSwitchedToBullish = isADXBullish && + !isADXBullishPrev; + + // + bool isADXBearish = + cADX > cADXN; + bool isADXBearishPrev = + pADX > pADXN; + + // + bool isADXSwitchedToBearish = isADXBearish && + !isADXBearishPrev; + + // + double barStrongAtrMult = 1.5; + + // + bool isCBarRangeHasStrongATR = + cBar.GetRange() > cATR * barStrongAtrMult; + + // + bool isCBarBodyHasStrongATR = + cBar.GetBody() > cATR * barStrongAtrMult; + + // + bool isCBarHasStrongATR = isCBarRangeHasStrongATR && + isCBarBodyHasStrongATR; + + // + bool isCBarIsStrongBullish = + isCBarHasStrongATR && + cBar.IsBullish(); + + // + bool isCBarIsStrongBearish = + isCBarHasStrongATR && + cBar.IsBearish(); + + // + bool isLowOverMax = cBar.low > maxCTrendValue; + bool isHighUnderMin = cBar.high < minCTrendValue; + bool isCloseOverMax = cBar.close > maxCTrendValue; + bool isCloseUnderMin = cBar.close < minCTrendValue; + + // + bool isCTrendRangeValid = cTrendValuesRangePoint <= 50; + bool isPTrendRangeValid = pTrendValuesRangePoint <= 50; + + // + bool isTrendRangeSwitchedToValid = isCTrendRangeValid && + !isPTrendRangeValid; + bool isTrendRangeFinishedFromValid = !isCTrendRangeValid && + isPTrendRangeValid; + + // + bool isPeakGoldenRejected = + cBar.high > cPeakGolden && + cBar.GetUp() <= cPeakGolden; + + // + bool isValeGoldenRejected = + cBar.low < cValeGolden && + cBar.GetDown() >= cValeGolden; + + // + bool isX3MaBullishState = + // + z3MAFast > z3MAMedium && + c3MAFast > c3MAMedium && + z3MAMedium > z3MASlow && + c3MAMedium > c3MASlow + // + ; + + // + bool isX3MaBearishState = + // + z3MAFast < z3MAMedium && + c3MAFast < c3MAMedium && + z3MAMedium < z3MASlow && + c3MAMedium < c3MASlow + // + ; + + // + bool isX3MaValidForBullishRejection = + // + c3MASlowState > 0 && + z3MASlowState > 0 && + z3MAMediumState > 0 && + c3MAMediumState > 0 && + z3MAMedium > z3MASlow && + c3MAMedium > c3MASlow && + conditions.isVidyaBullish + // + ; + + // + bool isX3MaValidForBearishRejection = + // + c3MASlowState < 0 && + z3MASlowState < 0 && + z3MAMediumState < 0 && + c3MAMediumState < 0 && + z3MAMedium < z3MASlow && + c3MAMedium < c3MASlow && + conditions.isVidyaBearish + // + ; + + // + // Parsing Pivots ... + XBoxZone upperPivot; + XBoxZone lowerPivot; + double providedSL = 0; + XBoxZone rejectedPivot; + XBoxZone insidePivots[]; + int insidePivotsCount = 0; + XBoxZone fakeBreakedPivot; + bool isRejectedOnMid = false; + bool hasInsidePivots = false; + bool hasPivots = HasChild(pivots); + if (hasPivots) + { + // + // Select Inside Boxes ... + ENUM_XCA_PIVOTS allowedInsidePivots[] = { + XCA_FVG_BULL, + XCA_FVG_BEAR, + }; + insidePivotsCount = SelectInsideBoxes( + allowedInsidePivots, + insidePivots, + pivots, + zBar, + cBar, + pBar, + p2Bar // + ); + Clean(allowedInsidePivots); + hasInsidePivots = IsValidSize(insidePivotsCount); + + // + // Detect Rejected Pivot ... + ENUM_XCA_PIVOTS allowedRejectedPivots[] = { + XCA_FVG_BULL, + XCA_FVG_BEAR, + }; + has = SelectRejectedBox( + allowedRejectedPivots, + rejectedPivot, + isRejectedOnMid, + pivots, + zBar, + cBar, + pBar, + p2Bar, + false, // Ignore Mid Rejection ... + true, + true // + ); + Clean(allowedRejectedPivots); + + // + // Select Fake Breakout Box ... + ENUM_XCA_PIVOTS allowedFakeBreakedPivots[] = { + XCA_PEAK, + XCA_VALE, + }; + has = SelectFakeBreakedBox( + allowedFakeBreakedPivots, + fakeBreakedPivot, + pivots, + helper, + zBar, + cBar, + pBar, + p2Bar // + ); + Clean(allowedFakeBreakedPivots); + + // + // Select Boundary Boxes ... + ENUM_XCA_PIVOTS allowedBoundarydPivots[] = { + XCA_PEAK, + XCA_VALE, + }; + has = SelectBoundaryBoxes( + allowedBoundarydPivots, + upperPivot, + lowerPivot, + pivots, + helper, + zBar, + cBar, + pBar, + p2Bar // + ); + Clean(allowedBoundarydPivots); + } + + // + // Signaller Summarization ... + + // + // Cond1 Act Using FVG Rejections ... + + // + bool isCond1Bullish = + // + false && // TODO: Remove this ... + isRSIBullish && + isVolumeOverAvg && + isVolumeOverLast && + conditions.isSarBullish && + rejectedPivot.IsValid() && + rejectedPivot.IsBullish() && + isX3MaValidForBullishRejection + // + ; + + // + bool isCond1Bearish = + // + false && // TODO: Remove this ... + isRSIBearish && + isVolumeOverAvg && + isVolumeOverLast && + conditions.isSarBearish && + rejectedPivot.IsValid() && + rejectedPivot.IsBearish() && + isX3MaValidForBearishRejection + // + ; + + // + bool isCond1 = isCond1Bullish || + isCond1Bearish; + if (isCond1) + { + pivotBox = rejectedPivot; + } + + // + // Cond2 Act Using OSC Box and Vydia ... + + // + bool isCond2Bullish = + // + upperPivot.IsValid() && + lowerPivot.IsValid() && + fakeBreakedPivot.IsValid() && + fakeBreakedPivot.IsBullish() + // + ; + + // + bool isCond2Bearish = + // + upperPivot.IsValid() && + lowerPivot.IsValid() && + fakeBreakedPivot.IsValid() && + fakeBreakedPivot.IsBearish() + // + ; + + // + bool isCond2 = isCond2Bullish || + isCond2Bearish; + if (isCond2) + { + Print("Cond2 ..."); + } + + // + // Cond3 Act Using CCi Peaks and Vales ... + + // + bool isCond3Bullish = + // + false + // + ; + + // + bool isCond3Bearish = + // + false + // + ; + + // + bool isCond3 = isCond3Bullish || + isCond3Bearish; + if (isCond3) + { + } + + // + // Summarise Conditions ... + + // + bool isBullish = + // + isCond1Bullish || + isCond2Bullish || + isCond3Bullish; + // + ; + + // + bool isBearish = + // + isCond1Bearish || + isCond2Bearish || + isCond3Bearish + // + ; + + // + result = isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + double entry = GetEntry( + conditions.symbol, + dir // + ); + + // + double sls[]; + + // + // Preparing SLs ... + + // + // For Cond 1 ... + // For Cond 2 ... + if (isCond1 || + isCond2) + { + // + if (isCond1Bullish) + { + // + // Rejected Pivot ... + Add( + rejectedPivot.lower, + sls // + ); + + // + if (!isRejectedOnMid) + { + // + Add( + rejectedPivot.GetMid(), + sls // + ); + } + } + else + { + // + // Rejected Pivot ... + Add( + rejectedPivot.upper, + sls // + ); + + // + if (!isRejectedOnMid) + { + // + Add( + rejectedPivot.GetMid(), + sls // + ); + } + } + + // + providedSL = + isCond1Bullish + ? GetMax(sls) + : GetMin(sls); + // + } + + // + double risk = MathAbs(providedSL - entry); + double riskPoint = risk / points; + + // + double sl = + providedSL > 0 + ? providedSL + : isBullish + ? pivotBox.lower + : pivotBox.upper; + + // + box.dir = dir; + box.symbol = conditions.symbol; + box.period = conditions.period; + + // + box.upper = + isBullish + ? entry + : sl; + + // + box.lower = + isBullish + ? sl + : entry; + + // + box.to = zBar.time; + box.from = p4Bar.time; + + // + box.type = "XCASignal"; + + // + // Preparing Targets ... + if (isCond1 || + isCond2) + { + // + // Add Reward 1 ... + + // + double rewardPrice = 1 * risk; + double rewardTP = + isBullish + ? entry + rewardPrice + : entry - rewardPrice; + + // + Add( + rewardTP, + targets // + ); + } + + // + Clean(sls); + } + + // + result = box.IsValid() && + HasDirection(dir); + + // + // Cleanup Resources ... + + // + if (!result) + { + // + box.Clean(); + pivotBox.Clean(); + conditions.Clean(); + } + + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + upperPivot.Clean(); + lowerPivot.Clean(); + Clean(cTrendValues); + Clean(pTrendValues); + Clean(insidePivots); + pConditions.Clean(); + rejectedPivot.Clean(); + fakeBreakedPivot.Clean(); + + // + return result; +} + +// +// Select Inside Boxes ... +int SelectInsideBoxes( + ENUM_XCA_PIVOTS &allowedTypes[], + XBoxZone &insideBoxes[], + XBoxZone &boxes[], + XOHCL &zBar, + XOHCL &cBar, + XOHCL &pBar, + XOHCL &p2Bar // +) +{ + // + int result = 0; + + // + Clean(insideBoxes); + + // + bool has = + zBar.IsValid() && + cBar.IsValid() && + pBar.IsValid() && + p2Bar.IsValid() && + HasChild(boxes); + if (!has) + { + return result; + } + + // + int count = ArraySize(boxes); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = boxes[i]; + + // + ENUM_XCA_PIVOTS iType = GetPivotType(iBox); + bool isAllowedType = IsValid(iType) && + !HasChild(allowedTypes) + ? true + : Contains( + iType, + allowedTypes // + ); + if (!isAllowedType) + { + // + iBox.Clean(); + + // + continue; + } + + // + bool isBullish = iBox.IsBullish(); + bool isBearish = iBox.IsBearish(); + + // + // Check Inside Conditions ... + + // + bool isBullishInside = + // + isBullish && + // + ((cBar.low < iBox.upper && + cBar.low > iBox.lower) || + (cBar.GetDown() < iBox.upper && + cBar.GetDown() > iBox.lower)) + // + ; + + // + bool isBearishInside = + // + isBearish && + // + ((cBar.high > iBox.lower && + cBar.high < iBox.upper) || + (cBar.GetUp() > iBox.lower && + cBar.GetUp() < iBox.upper)) + // + ; + + // + has = isBullishInside || + isBearishInside; + if (has) + { + // + AddRef( + iBox, + insideBoxes // + ); + } + + // + iBox.Clean(); + } + + // + result = ArraySize(insideBoxes); + + // + return result; +} + +// +bool SelectRejectedBox( + ENUM_XCA_PIVOTS &allowedTypes[], + XBoxZone &box, + bool &rejectOnMid, + XBoxZone &boxes[], + XOHCL &zBar, + XOHCL &cBar, + XOHCL &pBar, + XOHCL &p2Bar, + bool ignoreMidRejection = true, + bool forceBarType = false, + bool forcePressure = false // +) +{ + // + bool result = false; + + // + box.Clean(); + rejectOnMid = false; + + // + // Validate ... + result = HasChild(boxes) && + zBar.IsValid() && + cBar.IsValid() && + pBar.IsValid() && + p2Bar.IsValid(); + if (!result) + { + return result; + } + + // + int count = ArraySize(boxes); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = boxes[i]; + + // + ENUM_XCA_PIVOTS iType = GetPivotType(iBox); + bool isAllowedType = IsValid(iType) && + !HasChild(allowedTypes) + ? true + : Contains( + iType, + allowedTypes // + ); + if (!isAllowedType) + { + // + iBox.Clean(); + + // + continue; + } + + // + bool isBullish = iBox.IsBullish(); + bool isBearish = iBox.IsBearish(); + + // + double boundaryPrice = iBox.GetRejection(); + + // + double midPrice = iBox.GetMid(); + + // + bool isMidBullishRejected = cBar.IsRejected( + midPrice, + X_DIRECTION_BULLISH, + forceBarType, + forcePressure // + ); + + // + bool isBoundaryBullishRejected = cBar.IsRejected( + boundaryPrice, + X_DIRECTION_BULLISH, + forceBarType, + forcePressure // + ); + + // + bool isMidBearishRejected = cBar.IsRejected( + midPrice, + X_DIRECTION_BEARISH, + forceBarType, + forcePressure // + ); + + // + bool isBoundaryBearishRejected = cBar.IsRejected( + boundaryPrice, + X_DIRECTION_BEARISH, + forceBarType, + forcePressure // + ); + + // + if (ignoreMidRejection) + { + // + isMidBullishRejected = false; + isMidBearishRejected = false; + } + + // + bool isBullishRejected = + isBullish && + (isMidBullishRejected || + isBoundaryBullishRejected); + + // + bool isBearishRejected = + isBearish && + (isMidBearishRejected || + isBoundaryBearishRejected); + + // + bool isRejected = + isBullishRejected || + isBearishRejected; + if (isRejected) + { + // + box = iBox; + rejectOnMid = isBullishRejected + ? isMidBullishRejected + : isMidBearishRejected; + break; + } + + // + iBox.Clean(); + } + + // + result = box.IsValid(); + + // + return result; +} + +// +bool SelectFakeBreakedBox( + ENUM_XCA_PIVOTS &allowedTypes[], + XBoxZone &box, + XBoxZone &boxes[], + XCXCAEAHelper *helper, + XOHCL &zBar, + XOHCL &cBar, + XOHCL &pBar, + XOHCL &p2Bar // +) +{ + // + bool result = false; + + // + box.Clean(); + + // + // Validate ... + result = + zBar.IsValid() && + cBar.IsValid() && + pBar.IsValid() && + p2Bar.IsValid() && + HasChild(boxes); + if (!result) + { + return result; + } + + // + XBoxZone tmp[]; + Copy( + boxes, + tmp // + ); + + // + int idx = -1; + XBoxZone iBox; + while (HasChild(tmp)) + { + // + idx = GetYoungest(tmp); + result = IsValidIndex(idx); + if (!result) + { + break; + } + + // + iBox = tmp[idx]; + ArrayRemove( + tmp, + idx, + 1 // + ); + + // + // Checking Box Type Allowed ... + ENUM_XCA_PIVOTS iType = GetPivotType(iBox); + result = IsValid(iType) && + (!HasChild(allowedTypes) + ? true + : Contains( + iType, + allowedTypes // + )); + if (!result) + { + // + iBox.Clean(); + continue; + } + + // + // Check Box Fake Breakeout ... + result = IsFakeBreakeout( + iBox, + helper, + cBar.Index() // + ); + if (result) + { + // + box = iBox; + break; + } + + // + iBox.Clean(); + } + + // + Clean(tmp); + iBox.Clean(); + + // + result = box.IsValid(); + + // + return result; +} + +// +bool SelectBoundaryBoxes( + ENUM_XCA_PIVOTS &allowedTypes[], + XBoxZone &upperBox, + XBoxZone &lowerBox, + XBoxZone &boxes[], + XCXCAEAHelper *helper, + XOHCL &zBar, + XOHCL &cBar, + XOHCL &pBar, + XOHCL &p2Bar // +) +{ + // + bool result = false; + + // + upperBox.Clean(); + lowerBox.Clean(); + + // + // Validate ... + result = + zBar.IsValid() && + cBar.IsValid() && + pBar.IsValid() && + p2Bar.IsValid() && + HasChild(boxes); + if (!result) + { + return result; + } + + // + XBoxZone tmp[]; + Copy( + boxes, + tmp // + ); + + // + int idx = -1; + XBoxZone iBox; + while (HasChild(tmp)) + { + // + idx = GetYoungest(tmp); + result = IsValidIndex(idx); + if (!result) + { + break; + } + + // + iBox = tmp[idx]; + ArrayRemove( + tmp, + idx, + 1 // + ); + + // + // Checking Box Type Allowed ... + ENUM_XCA_PIVOTS iType = GetPivotType(iBox); + result = IsValid(iType) && + (!HasChild(allowedTypes) + ? true + : Contains( + iType, + allowedTypes // + )); + if (!result) + { + // + iBox.Clean(); + continue; + } + + // + // Upper ... + bool canSetUpper = + iType == XCA_PEAK && + (!upperBox.IsValid() + ? true + : upperBox.lower > iBox.lower); + if (canSetUpper) + { + upperBox = iBox; + } + + // + // Lower ... + bool canSetLower = + iType == XCA_VALE && + (!lowerBox.IsValid() + ? true + : lowerBox.upper < iBox.upper); + if (canSetLower) + { + lowerBox = iBox; + } + + // + iBox.Clean(); + } + + // + Clean(tmp); + iBox.Clean(); + + // + result = upperBox.IsValid() && + lowerBox.IsValid(); + + // + return result; +} + +// +int ExtractValues( + double &values[], + XBoxZone &pivots[], + bool forceClean = true // +) +{ + // + int result = 0; + + // + if (forceClean) + { + Clean(values); + } + + // + int count = ArraySize(pivots); + for (int i = 0; i < count; i++) + { + // + XBoxZone iPivot = pivots[i]; + + // + Add( + iPivot.upper, + values // + ); + + // + Add( + iPivot.lower, + values // + ); + + // + iPivot.Clean(); + } + + // + result = ArraySize(values); + + // + return result; +} + +// +double GetMax(XBoxZone &pivots[]) +{ + // + double values[]; + ExtractValues( + values, + pivots // + ); + + // + double result = GetMax(values); + + // + Clean(values); + + // + return result; +} + +// +double GetMin(XBoxZone &pivots[]) +{ + // + double values[]; + ExtractValues( + values, + pivots // + ); + + // + double result = GetMin(values); + + // + Clean(values); + + // + return result; +} + +// \ No newline at end of file diff --git a/BKPS/14040218 XCAEA/Documents/BKP/test.tmp.mq5 b/BKPS/14040218 XCAEA/Documents/BKP/test.tmp.mq5 new file mode 100644 index 0000000..295565c --- /dev/null +++ b/BKPS/14040218 XCAEA/Documents/BKP/test.tmp.mq5 @@ -0,0 +1,273 @@ +// +// Detect SignalBox Trigger ... +// Cond1: +// - Close Under Min / Max ... +// - All Trendings in Direction ... +// - Consolidating Trendings ... +// - ... +bool CanTriggerCond1( + XCXCAEAHelper *helper, + XBoxZone &box, + ENUM_X_DIRECTION &dir, + double &sls[], + int barIndex = 0, + int loopback = 10 // +) +{ + // + bool result = false; + + // + // Normalize Args ... + Clean(sls); + dir = X_DIRECTION_NONE; + loopback = NormalizeInt(loopback, 5); + barIndex = NormalizeInt(barIndex, 0); + + // + // Validate Decision Box ... + result = box.IsValid(); + if (!result) + { + return result; + } + + // + // Retrieve Market Conditions ... + XCAEAConditions conditions; + result = helper.GetConditions( + conditions, + barIndex, + loopback // + ); + + // + // Extract CBar ... + XOHCL cBar; + result = cBar.Init( + conditions.symbol, + conditions.period, + barIndex // + ); + if (!result) + { + // + cBar.Clean(); + conditions.Clean(); + + // + return result; + } + + // + // Bar Conditions ... + + // + ENUM_X_DIRECTION barDir; + + // + // ENGULF ... + + // + bool isCBarEngulfed = helper + .barAnalyser + .IsEngulfed( + cBar, + barDir // + ); + + // + bool isCBarBullishEngulfed = + isCBarEngulfed && + IsBullish(barDir); + + // + bool isCBarBearishEngulfed = + isCBarEngulfed && + IsBearish(barDir); + + // + bool isBullish = box.IsBullish(); + bool isBearish = box.IsBearish(); + + // + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + int p3IDX = p2IDX + 1; + int p4IDX = p3IDX + 1; + + // + // Reading Values ... + + // + // SAR ... + double cSAR = conditions.sarBuffer[cIDX]; + + // + // SWH ... + double cSWH = conditions.swingHighBuffer[cIDX]; + + // + // SWL ... + double cSWL = conditions.swingLowBuffer[cIDX]; + + // + // PEAK ... + double cPeak = conditions.peakBuffer[cIDX]; + + // + // VALE ... + double cVale = conditions.valeBuffer[cIDX]; + + // + // MAH ... + double cMAH = conditions.mahBuffer[cIDX]; + + // + // MAC ... + double cMAC = conditions.macBuffer[cIDX]; + + // + // MAL ... + double cMAL = conditions.malBuffer[cIDX]; + + // + // KI ... + double cKI = conditions.kiBuffer[cIDX]; + double cKIState = conditions.kiStateBuffer[cIDX]; + + // + // TKI ... + double cTKI = conditions.tkiBuffer[cIDX]; + double cTKIState = conditions.tkiStateBuffer[cIDX]; + + // + // FAST ... + double cFast = conditions.fastBuffer[cIDX]; + double cFastState = conditions.fastStateBuffer[cIDX]; + + // + // VIDYA ... + double cVidya = conditions.vidyaBuffer[cIDX]; + double cVidyaState = conditions.vidyaStateBuffer[cIDX]; + + // + // TREND ... + double cTrend = conditions.trendBuffer[cIDX]; + double cTrendState = conditions.trendStateBuffer[cIDX]; + + // + // Generating Conditions ... + + // + bool isSWLOverBox = cSWL > box.lower; + bool isSWHUnderBox = cSWH < box.upper; + + // + bool isValeOverBox = cVale > box.lower; + bool isPeakUnderBox = cPeak < box.upper; + + // + bool hasBullishPress = + // isBullish && + (isSWLOverBox || + isValeOverBox); + + // + bool hasBearishPress = + // isBearish && + (isSWHUnderBox || + isPeakUnderBox); + + // + double trends[] = { + cMAH, + cMAC, + cMAL, + cKI, + cTKI, + cFast, + cVidya, + cTrend // + }; + double trendMax = GetMax(trends); + double trendMin = GetMin(trends); + Copy( + trends, + sls // + ); + + // + bool isCloseOverMax = cBar.close > trendMax; + bool isCloseUnderMin = cBar.close < trendMin; + + // + bool isStateBullish = + cKIState > 0 && + cTKIState > 0 && + cFastState > 0 && + cTrendState > 0 && + cVidyaState > 0; + + // + bool isStateBearish = + cKIState < 0 && + cTKIState < 0 && + cFastState < 0 && + cTrendState < 0 && + cVidyaState < 0; + + // + bool hasBullishTrend = + // isBullish && + isStateBullish && + isCloseOverMax; + + // + bool hasBearishTrend = + // isBearish && + isStateBearish && + isCloseUnderMin; + + // + // Summarizing ... + + // + bool canTriggerLong = + // isBullish && + hasBullishPress && + hasBullishTrend; + + // + bool canTriggerShort = + // isBearish && + hasBearishPress && + hasBearishTrend; + + // + result = canTriggerLong || + canTriggerShort; + if (result) + { + // + dir = canTriggerLong + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + Print("Triggered ..."); + } + + // + // Cleanup Resources ... + + // + cBar.Clean(); + Clean(trends); + conditions.Clean(); + + // + return result; +} diff --git a/BKPS/14040218 XCAEA/Documents/BKP/xcaea.signaller.class.mq5 b/BKPS/14040218 XCAEA/Documents/BKP/xcaea.signaller.class.mq5 new file mode 100644 index 0000000..e240ea0 --- /dev/null +++ b/BKPS/14040218 XCAEA/Documents/BKP/xcaea.signaller.class.mq5 @@ -0,0 +1,878 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XCXCAEASignaller ... +// Description: Class for XCAEA 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 Class for XCAEA Signaller" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.base.class.mq5" +#include "../../Classes/x-saherelm.x-cobject.class.mq5" +#include "../Classes/xcaea.x-poi.detector.class.mq5" +#include "../Classes/xcaea.x-poi.drawer.class.mq5" +#include "../Helpers/xcaea.helper.mq5" +#include "../Libraries/xcaea.signaller.lib.mq5" + +// +// Definitions ... + +class XCXCAEASignaller : XCBase +{ + // + // Public ... + public: + // + // Props ... + bool useGuards; + XCAEAInputs inputs; + XBarTracker barTraker; + XCXCAEAHelper *helper; + XCXCAEAPOIDrawer *drawer; + bool continuesRFTillTarget; + XBoxZone unAvailableBoxes[]; + XCXCAEAPOIDetector *detector; + XCAEAStrategyConditions mConditions; + XCAEAStrategyConditions mConditionsCollection[]; + + // + // Constructor ... + XCXCAEASignaller( + string _symbol, + ENUM_TIMEFRAMES _period // + ) + { + // + symbol = _symbol; + period = _period; + + // + Init(); + } + + // + // Deconstructor ... + ~XCXCAEASignaller() + { + DeInit(); + } + + // + // Properties ... + + string GetSymbol() + { + return symbol; + } + + ENUM_TIMEFRAMES GetPeriod() + { + return period; + } + + // + // Signaller 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( + double tpReward = 3, + double maxAllowedSLDistanceInPoint = 100 // + ) + { + // + bool result = false; + + // + // Check Bar Processing ... + if (!barTraker.CanProcessBar()) + { + return result; + } + + // + bool isBullish = false; + bool isBearish = false; + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + int loopback = 10; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + double points = GetPoints(symbol); + + // + XOHCL zBar; + XOHCL cBar; + XOHCL pBar; + XOHCL pPBar; + result = zBar.Init( + symbol, + period, + zIndex // + ); + result = + result && + zBar.GetPreviousBar(cBar); + result = + result && + cBar.GetPreviousBar(pBar); + result = + result && + pBar.GetPreviousBar(pPBar); + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + pPBar.Clean(); + + // + return result; + } + + // + // Setup Conditions ... + XBoxZone boxes[]; + XBoxZone pivotBox; + XBoxZone signalBox; + double additionalSL = 0; + XBoxZone bullishBoxes[]; + XBoxZone bearishBoxes[]; + bool hasSignalBox = false; + XCAEAConditions conditions; + ENUM_X_DIRECTION signalBoxDir = X_DIRECTION_NONE; + + // + // Detecting Pivots ... + detector.Update( + zIndex // + ); + + // + // Validate Pivots ... + detector.Validate( + unAvailableBoxes, + zIndex // + ); + + // + // Draw Founded Pivots ... + drawer.Draw(cTime); + + // + // Retrieve Valid Boxes ... + + // + // Bullish ... + int bullishBoxesCount = + detector + .FillBullishBoxes(bullishBoxes); + + // + // Bearish ... + int bearishBoxesCount = + detector + .FillBearishBoxes(bearishBoxes); + + // + Copy( + bullishBoxes, + boxes, + false // + ); + Copy( + bearishBoxes, + boxes, + false // + ); + int boxesCount = ArraySize(boxes); + bool hasBoxes = IsValidSize(boxesCount); + + // + // Filter UnAvailable Boxes ... + if (hasBoxes) + { + // + // Remove UnAvailable Boxes ... + has = HasChild(unAvailableBoxes); + if (has) + { + // + count = ArraySize(unAvailableBoxes); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = unAvailableBoxes[i]; + + // + has = FindBoxIndex( + idx, + iBox, + boxes // + ); + if (has) + { + // + ArrayRemove( + boxes, + idx, + 1 // + ); + } + } + } + + // + hasBoxes = HasChild(boxes); + boxesCount = ArraySize(boxes); + } + + // + // + // + + // + // if (hasBoxes) + // { + // } + + // + // Detect Sinal Box ... + hasSignalBox = DetectXCAEAConditions( + boxes, + conditions, + pivotBox, + signalBox, + additionalSL, + signalBoxDir, + helper, + zIndex, + loopback // + ); + + // + // Make Pivot Box UnAvailable ... + if (pivotBox.IsValid()) + { + // + AddRef( + pivotBox, + unAvailableBoxes // + ); + } + + // + isBullish = hasSignalBox && + IsBullish(signalBoxDir); + + // + isBearish = hasSignalBox && + IsBearish(signalBoxDir); + + // + result = isBullish || + isBearish; + if (result) + { + // + // Do What we Want ... + barTraker.Waits(); + + // + // Draw Signal Box ... + XCBoxObject *iObj; + bool isCreated = helper.poiDrawer.DrawBox( + signalBox, + iObj // + ); + if (isCreated) + { + // + mObjects.Add(iObj); + ZeroMemory(iObj); + + // + Print("Signal Box ..."); + } + + // + // Prepare Conditions ... + mConditions.symbol = symbol; + mConditions.period = period; + + // + double spread = GetSpread(symbol); + + // + double entry = + isBullish + ? signalBox.upper + : signalBox.lower; + + // + double sl = + isBullish + ? signalBox.lower + : signalBox.upper; + if (additionalSL > 0) + { + // + sl = + isBullish + ? sl - additionalSL + : sl + additionalSL; + } + + // + double risk = + isBullish + ? entry - sl + : sl - entry; + risk += spread; + if (risk >= maxAllowedSLDistanceInPoint * points) + { + // + // Fix Risk in Big Distances ... + double hh5 = zBar.FindHighest(5, MODE_HIGH); + double ll5 = zBar.FindLowest(5, MODE_LOW); + + // + double hhll5Delta = hh5 - ll5; + double riskDelta = hhll5Delta / 2; + risk = riskDelta; + } + + // + double rewardTP = risk * tpReward; + + // + double tp = + isBullish + ? entry + rewardTP + : entry - rewardTP; + + // + // Filling ... + mConditions.sl = sl; + mConditions.tp = tp; + mConditions.pivot = + isBullish + ? sl + : entry; + mConditions.point = + isBullish + ? entry + : sl; + mConditions.dir = signalBoxDir; + mConditions.provider = "XCAEA"; + mConditions.signalBox = signalBox; + mConditions.setupTime = zBar.time; + mConditions.conditions = conditions; + + // + // Select RF Rewards ... + if (continuesRFTillTarget) + { + // + double rfReward = 1; + while (rfReward < tpReward) + { + // + double rewardRF = risk * rfReward; + double rfTP = + isBullish + ? entry + rewardRF + : entry - rewardRF; + + // + Add( + rfTP, + mConditions.targets // + ); + + // + rfReward++; + } + } + else + { + // + double rfReward = 1; + + // + double rewardRF = risk * rfReward; + double rfTP = + isBullish + ? entry + rewardRF + : entry - rewardRF; + + // + Add( + rfTP, + mConditions.targets // + ); + } + } + + // + // Cleanup Resource ... + + // + Clean(boxes); + Clean(bullishBoxes); + Clean(bearishBoxes); + + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + pPBar.Clean(); + + // + pivotBox.Clean(); + signalBox.Clean(); + conditions.Clean(); + + // + return result; + } + + /** + * Detect Trigger Conditions for Specified Signal ... + * + * @param conditions: XCAEAStrategyConditions instance Reference, Specified Signal Conditions ... + * @param maxAllowedSetupAge: specified Setup Age for Expiration (if bigger than Zero) ... + * + * @return ( bool ) + */ + bool DetectSignalTrigger( + XCAEAStrategyConditions &conditions, + int maxAllowedSetupAge = 60 // + ) + { + // + bool result = false; + + // + result = conditions.IsSetuped(); + if (!result) + { + return result; + } + + // + datetime setupTime = conditions.setupTime; + ENUM_X_DIRECTION setupDir = conditions.dir; + + // + bool isBullish = IsBullish(setupDir); + bool isBearish = IsBearish(setupDir); + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + int loopback = 10; + + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + double points = GetPoints(symbol); + + // + // Check Signal Validation ... + // IMPORTANT: since all Validations done in SetUp Process ... + // here we only Execute Signal ... + + // + result = isBullish || + isBearish; + + // + if (result) + { + // + conditions.triggerTime = cTime; + conditions.type = isBullish + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_SHORT; + + // + } + + // + // Cleanup ... + + // + 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( + XCAEAGuard &guards[], + const XPosition &positions[] // + ) + { + // + bool result = false; + + // + return result; + } + + /** + * Add Conditions to Conditions Collection if not Exists ... + * + * @param maxAllowed: int, Specified Max Allowed Holding Conditions ... + * + * @return ( int ) + */ + int AddConditionsIfNotExists( + int maxAllowed = 10 // + ) + { + // + int result = 0; + + // + bool isSetuped = IsValid(mConditions.setupTime) && + HasDirection(mConditions.dir); + if (!isSetuped) + { + return result; + } + + // + int count = ArraySize(mConditionsCollection); + if (IsValidSize(count)) + { + // + // Copy Original Items ... + XCAEAStrategyConditions tmpItems[]; + Copy( + mConditionsCollection, + tmpItems // + ); + + // + // Prese Item Data ... + bool isBullish = IsBullish(mConditions.dir); + + // + for (int i = 0; i < count; i++) + { + // + XCAEAStrategyConditions 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; + } + + // + // Protected ... + protected: + // + + // + // Private ... + private: + // + // Props ... + string symbol; + ENUM_TIMEFRAMES period; + CArrayObj mObjects; + CArrayObj mBarObjects; + + /** + * Initialize ... + */ + void Init() + { + // + useGuards = false; + continuesRFTillTarget = true; + + // + barTraker.Init( + symbol, + period // + ); + + // + inputs.Default(); + + // + // Configure Indicators ... + + // + // XCC ... + inputs.ccInputs.showCandles = true; + + // + // XCT ... + inputs.ctInputs.showCandleTime = true; + + // + // XCA ... + + // + inputs.caInputs.supResSmoothingLength = 7; + inputs.caInputs.supResSmoothingMode = X_MA_MODE_NONE; + + // + inputs.caInputs.showKI = true; + inputs.caInputs.showTKI = false; + inputs.caInputs.showSar = false; + inputs.caInputs.showVidya = true; + inputs.caInputs.showTrend = false; + inputs.caInputs.showSwings = false; + inputs.caInputs.showLongCycle = false; + inputs.caInputs.showHindCycle = false; + inputs.caInputs.showFiboLevel1 = false; + inputs.caInputs.showFiboLevel2 = false; + inputs.caInputs.showFiboLevel3 = false; + inputs.caInputs.showShortCycle = false; + inputs.caInputs.showMediumCycle = false; + inputs.caInputs.showPeaksAndVales = true; + inputs.caInputs.showPeakAndValeGolden = false; + inputs.caInputs.showSupportAndResistance = false; + + // + // XOSCS ... + // inputs.oscsInputs.rsiLength = 5; + // inputs.oscsInputs.cciLength = 5; + // inputs.oscsInputs.mfiLength = 5; + // inputs.oscsInputs.rviLength = 5; + + // + // Oscillators Views ... + inputs.showCCI = false; + inputs.showRSI = false; + inputs.showMFI = false; + inputs.showRVI = false; + inputs.showADX = false; + inputs.showMACD = false; + + // + // XCAEA Helper ... + helper = new XCXCAEAHelper(); + helper.Init( + symbol, + period, + inputs // + ); + + // + // Initialize and Configure Detector ... + detector = new XCXCAEAPOIDetector(helper); + + // + detector.detectSWHPivot = false; + detector.detectSWLPivot = false; + detector.detectPeakPivot = false; + detector.detectValePivot = false; + detector.detectRSIPeakPivot = true; + detector.detectRSIValePivot = true; + detector.detectCCIPeakPivot = true; + detector.detectCCIValePivot = true; + detector.detectKIBullishPivot = false; + detector.detectKIBearishPivot = false; + detector.detectFVGBullishPivot = true; + detector.detectFVGBearishPivot = true; + detector.detectPeakSWHResPivot = true; + detector.detectValeSWLSupPivot = true; + detector.detectTKIBullishPivot = false; + detector.detectCycleSameLLPivot = false; + detector.detectCycleSameHHPivot = false; + detector.detectTKIBearishPivot = false; + detector.detectTrendBullishPivot = false; + detector.detectTrendBearishPivot = false; + detector.detectTKITRNDBullishPivot = false; + detector.detectTKITRNDBearishPivot = false; + detector.detectRSICrossedOverOSPivot = false; + detector.detectRSICrossedUnderOBPivot = false; + detector.detectCCICrossedOverOSPivot = false; + detector.detectCCICrossedUnderOBPivot = false; + + // + // Initialize and Configure Drawer ... + drawer = new XCXCAEAPOIDrawer(detector); + + // + // UnActive Pivots ... + drawer.drawSWHPivots = false; + drawer.drawSWLPivots = false; + drawer.drawPeakPivots = false; + drawer.drawValePivots = false; + drawer.drawRSIPeakPivots = true; // true; + drawer.drawRSIValePivots = true; // true; + drawer.drawCCIPeakPivots = false; // true; + drawer.drawCCIValePivots = false; // true; + drawer.drawKIBullishPivots = false; + drawer.drawKIBearishPivots = false; + drawer.drawFVGBullishPivots = false; + drawer.drawFVGBearishPivots = false; + drawer.drawPeakSWHResPivots = false; // true; + drawer.drawValeSWLSupPivots = false; // true; + drawer.drawTKIBullishPivots = false; + drawer.drawTKIBearishPivots = false; + drawer.drawPVFVGBullishPivots = false; // true; + drawer.drawPVFVGBearishPivots = false; // true; + drawer.drawCycleSameLLPivots = false; + drawer.drawCycleSameHHPivots = false; + drawer.drawTrendBullishPivots = false; + drawer.drawTrendBearishPivots = false; + drawer.drawTKITRNDBullishPivots = false; + drawer.drawTKITRNDBearishPivots = false; + drawer.drawRSICrossedOverOSPivots = false; + drawer.drawRSICrossedUnderOBPivots = false; + drawer.drawCCICrossedOverOSPivots = false; + drawer.drawCCICrossedUnderOBPivots = false; + + // + drawer.drawTicks = false; + + // + // Configure Width ... + drawer.peakPivotWidth = 1; + drawer.valePivotWidth = 1; + drawer.ticksBullishWidth = 2; + drawer.ticksBearishWidth = 2; + drawer.fvgBullishPivotWidth = 1; + drawer.fvgBearishPivotWidth = 1; + drawer.oscsBullishPivotWidth = 2; + drawer.oscsBearishPivotWidth = 2; + + // + // Configure Colors ... + drawer.peakPivotColor = clrMagenta; + drawer.valePivotColor = clrAqua; + drawer.ticksBullishColor = clrYellow; + drawer.ticksBearishColor = clrOrange; + drawer.fvgBullishPivotColor = clrLime; + drawer.fvgBearishPivotColor = clrRed; + drawer.oscsBullishPivotColor = clrAqua; + drawer.oscsBearishPivotColor = clrMagenta; + + // + // Configure Style ... + drawer.peakPivotStyle = STYLE_SOLID; + drawer.valePivotStyle = STYLE_SOLID; + drawer.ticksBullishStyle = STYLE_DOT; + drawer.ticksBearishStyle = STYLE_DOT; + drawer.fvgBullishPivotStyle = STYLE_DASH; + drawer.fvgBearishPivotStyle = STYLE_DASH; + drawer.oscsBullishPivotStyle = STYLE_SOLID; + drawer.oscsBearishPivotStyle = STYLE_SOLID; + } + + /** + * DeInitialize ... + */ + void DeInit() + { + // + inputs.Clean(); + + // + ZeroMemory(drawer); + ZeroMemory(helper); + ZeroMemory(detector); + + // + mConditions.Clean(); + Clean(mConditionsCollection); + + // + mObjects.Clear(); + mBarObjects.Clear(); + + // + barTraker.Clean(); + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14040218 XCAEA/Documents/BKP/xcaea.x-poi.detector.class.bkp.mq5 b/BKPS/14040218 XCAEA/Documents/BKP/xcaea.x-poi.detector.class.bkp.mq5 new file mode 100644 index 0000000..7fc68ec --- /dev/null +++ b/BKPS/14040218 XCAEA/Documents/BKP/xcaea.x-poi.detector.class.bkp.mq5 @@ -0,0 +1,4936 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XCXCAEAPOIDetector ... +// Description: Class for XCAEA 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 XCAEA POI Detector" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-bar.analyser.class.mq5" +#include "../../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../Helpers/xcaea.helper.mq5" + +// +// Definitions ... + +// +enum ENUM_XCA_PIVOTS +{ + XCA_NONE, // None + XCA_TICK, // Tick + XCA_VOLUME, // Volume + XCA_FVG_BULL, // FVGBull + XCA_FVG_BEAR, // FVGBear + XCA_RSI_COOS, // RSICOOS + XCA_RSI_CUOB, // RSICUOB + XCA_RSI_PEAK, // RSIPeak + XCA_RSI_VALE, // RSIVale + XCA_CCI_COOS, // CCICOOS + XCA_CCI_CUOB, // CCICUOB + XCA_CCI_PEAK, // CCIPeak + XCA_CCI_VALE, // CCIVale + XCA_PEAKSWHRES, // PeakSWHRes + XCA_VALESWLSUP, // ValeSWLSup + XCA_TREND_BULL, // TrendBull + XCA_TREND_BEAR, // TrendBear +}; + +// +bool IsValid(ENUM_XCA_PIVOTS value) +{ + // + bool result = false; + + // + result = value != XCA_NONE; + + // + return result; +} + +// +string ToString(ENUM_XCA_PIVOTS value) +{ + // + string result = NULL; + + // + result = EnumToString(value); + + // + return result; +} + +// +ENUM_X_DIRECTION GetDirection(ENUM_XCA_PIVOTS value) +{ + // + ENUM_X_DIRECTION result = X_DIRECTION_NONE; + + // + switch (value) + { + // + case XCA_FVG_BULL: + case XCA_RSI_COOS: + case XCA_RSI_VALE: + case XCA_CCI_COOS: + case XCA_CCI_VALE: + case XCA_TREND_BULL: + case XCA_VALESWLSUP: + result = X_DIRECTION_BULLISH; + break; + + // + case XCA_FVG_BEAR: + case XCA_RSI_CUOB: + case XCA_RSI_PEAK: + case XCA_CCI_CUOB: + case XCA_CCI_PEAK: + case XCA_TREND_BEAR: + case XCA_PEAKSWHRES: + result = X_DIRECTION_BEARISH; + break; + } + + // + return result; +} + +// +string GetBoxType(ENUM_XCA_PIVOTS value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case XCA_TICK: + case XCA_VOLUME: + case XCA_RSI_COOS: + case XCA_RSI_VALE: + case XCA_CCI_COOS: + case XCA_CCI_VALE: + case XCA_RSI_CUOB: + case XCA_RSI_PEAK: + case XCA_CCI_CUOB: + case XCA_CCI_PEAK: + case XCA_VALESWLSUP: + case XCA_PEAKSWHRES: + result = ToString(value); + break; + // + case XCA_FVG_BULL: + case XCA_FVG_BEAR: + result = "XCA_FVG"; + break; + + // + case XCA_TREND_BULL: + case XCA_TREND_BEAR: + result = "XCA_TREND"; + break; + } + + // + return result; +} + +// +ENUM_XCA_PIVOTS GetPivotType(XBoxZone &value) +{ + // + ENUM_XCA_PIVOTS result = XCA_NONE; + + // + bool has = value.IsValid(); + if (!has) + { + return result; + } + + // + bool isTick = value.type == GetBoxType(XCA_TICK); + bool isVolume = value.type == GetBoxType(XCA_VOLUME); + bool isFVGBull = value.type == GetBoxType(XCA_FVG_BULL) && + value.dir == GetDirection(XCA_FVG_BULL); + bool isFVGBear = value.type == GetBoxType(XCA_FVG_BEAR) && + value.dir == GetDirection(XCA_FVG_BEAR); + bool isRSIPeak = value.type == GetBoxType(XCA_RSI_PEAK) && + value.dir == GetDirection(XCA_RSI_PEAK); + bool isRSIVale = value.type == GetBoxType(XCA_RSI_VALE) && + value.dir == GetDirection(XCA_RSI_VALE); + bool isCCIPeak = value.type == GetBoxType(XCA_CCI_PEAK) && + value.dir == GetDirection(XCA_CCI_PEAK); + bool isCCIVale = value.type == GetBoxType(XCA_CCI_VALE) && + value.dir == GetDirection(XCA_CCI_VALE); + bool isRSICrossedOverOS = value.type == GetBoxType(XCA_RSI_COOS) && + value.dir == GetDirection(XCA_RSI_COOS); + bool isRSICrossedUnderOB = value.type == GetBoxType(XCA_RSI_CUOB) && + value.dir == GetDirection(XCA_RSI_CUOB); + bool isCCICrossedOverOS = value.type == GetBoxType(XCA_CCI_COOS) && + value.dir == GetDirection(XCA_CCI_COOS); + bool isCCICrossedUnderOB = value.type == GetBoxType(XCA_CCI_CUOB) && + value.dir == GetDirection(XCA_CCI_CUOB); + bool isTrendBullish = value.type == GetBoxType(XCA_TREND_BULL) && + value.dir == GetDirection(XCA_TREND_BULL); + bool isTrendBearish = value.type == GetBoxType(XCA_TREND_BEAR) && + value.dir == GetDirection(XCA_TREND_BEAR); + bool isPeakSWHRes = value.type == GetBoxType(XCA_PEAKSWHRES) && + value.dir == GetDirection(XCA_PEAKSWHRES); + bool isValeSWLSup = value.type == GetBoxType(XCA_VALESWLSUP) && + value.dir == GetDirection(XCA_VALESWLSUP); + + // + if (isTick) + { + result = XCA_TICK; + } + else if (isVolume) + { + result = XCA_VOLUME; + } + else if (isFVGBull) + { + result = XCA_FVG_BULL; + } + else if (isFVGBear) + { + result = XCA_FVG_BEAR; + } + else if (isRSIPeak) + { + result = XCA_RSI_PEAK; + } + else if (isRSIVale) + { + result = XCA_RSI_VALE; + } + else if (isCCIPeak) + { + result = XCA_CCI_PEAK; + } + else if (isCCIVale) + { + result = XCA_CCI_VALE; + } + else if (isRSICrossedOverOS) + { + result = XCA_RSI_COOS; + } + else if (isRSICrossedUnderOB) + { + result = XCA_RSI_CUOB; + } + else if (isCCICrossedOverOS) + { + result = XCA_CCI_COOS; + } + else if (isCCICrossedUnderOB) + { + result = XCA_CCI_CUOB; + } + else if (isTrendBullish) + { + result = XCA_TREND_BULL; + } + else if (isTrendBearish) + { + result = XCA_TREND_BEAR; + } + else if (isPeakSWHRes) + { + result = XCA_PEAKSWHRES; + } + else if (isValeSWLSup) + { + result = XCA_VALESWLSUP; + } + + // + return result; +} + +// +int ExtractPivots( + XBoxZone &extracted[], + ENUM_XCA_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_XCA_PIVOTS iType = GetPivotType(iBox); + + // + has = iType == type; + if (has) + { + // + AddRef( + iBox, + extracted // + ); + } + + // + iBox.Clean(); + } + + // + result = ArraySize(extracted); + + // + return result; +} + +// +struct XCAPivot +{ + // + // Props ... + datetime to; + double value; + string symbol; + datetime from; + double reserve; + ENUM_XCA_PIVOTS type; + ENUM_TIMEFRAMES period; + + // + double values[]; + + // + // Constructor ... + XCAPivot() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + value = 0; + to = NULL; + reserve = 0; + from = NULL; + symbol = NULL; + period = NULL; + type = XCA_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: XCAPivot ... + * + * @return ( bool ) + */ + bool IsSameAs(XCAPivot &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; + } + + // +}; + +// +struct XCATRENDFVG +{ + // + XBoxZone trend; + XBoxZone fvgs[]; + + // + XCATRENDFVG() + { + Clean(); + } + + // + // Tools ... + + // + void Clean() + { + // + Clean(fvgs); + trend.Clean(); + + // + ZeroMemory(this); + } + + // + bool IsValid() + { + // + bool result = false; + + // + result = trend.IsValid(); + + // + return result; + } + + // + void AddFVG(XBoxZone &fvg) + { + // + bool has = trend.IsValid() && + fvg.IsValid() && + fvg.dir == trend.dir; + if (!has) + { + return; + } + + // + int idx = -1; + has = FindBoxIndex( + idx, + fvg, + fvgs // + ); + if (has) + { + return; + } + + // + AddRef( + fvg, + fvgs // + ); + } + + // + bool IsBullish() + { + return IsValid() && + trend.IsBullish(); + } + + // + bool IsBearish() + { + return IsValid() && + trend.IsBearish(); + } + + // + bool GetSelectedFVG(XBoxZone &fvg) + { + // + bool result = false; + + // + fvg.Clean(); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int idx = -1; + if (IsBullish()) + { + idx = GetLowest(fvgs); + } + else if (IsBearish()) + { + idx = GetHighest(fvgs); + } + result = IsValidIndex(idx); + if (!result) + { + return result; + } + + // + fvg = fvgs[idx]; + + // + result = fvg.IsValid(); + + // + return result; + } + + // +}; + +// +int ExtractTrendFVGs( + XBoxZone &extracteds[], + XBoxZone &trend, + XBoxZone &fvgs[] // +) +{ + // + int result = 0; + + // + Clean(extracteds); + + // + bool has = HasChild(fvgs) && + trend.IsValid(); + if (!has) + { + return result; + } + + // + // Check Trend Box Pivot is Valid Trend ... + ENUM_XCA_PIVOTS iType = GetPivotType(trend); + has = iType == XCA_TREND_BULL || + iType == XCA_TREND_BEAR; + if (!has) + { + return result; + } + + // + int count = ArraySize(fvgs); + for (int i = 0; i < count; i++) + { + // + XBoxZone iFVG = fvgs[i]; + + // + bool isDirPassed = iFVG.dir == trend.dir; + bool isPricePassed = iFVG.upper <= trend.upper && + iFVG.lower >= trend.lower; + bool isFromPassed = iFVG.from > trend.from; + has = + isDirPassed && + isFromPassed && + isPricePassed; + if (has) + { + // + AddRef( + iFVG, + extracteds // + ); + } + + // + iFVG.Clean(); + } + + // + result = ArraySize(extracteds); + + // + return result; +} + +// +int ExtractTrendPivots( + XCATRENDFVG &items[], + XBoxZone &boxes[] // +) +{ + // + int result = 0; + + // + Clean(items); + + // + bool has = HasChild(boxes); + if (!has) + { + return result; + } + + // + // Extract Trend Boxes ... + XBoxZone tmp[]; + XBoxZone trendBoxes[]; + ExtractPivots( + tmp, + XCA_TREND_BULL, + boxes // + ); + Copy( + tmp, + trendBoxes, + false // + ); + Clean(tmp); + ExtractPivots( + tmp, + XCA_TREND_BEAR, + boxes // + ); + Copy( + tmp, + trendBoxes, + false // + ); + Clean(tmp); + + // + // Check Trend Boxes Exists ... + has = HasChild(trendBoxes); + if (!has) + { + // + Clean(trendBoxes); + return result; + } + + // + // Extract FVG Boxes ... + XBoxZone fvgBoxes[]; + + // + ExtractPivots( + tmp, + XCA_FVG_BULL, + boxes // + ); + Copy( + tmp, + fvgBoxes, + false // + ); + Clean(tmp); + ExtractPivots( + tmp, + XCA_FVG_BEAR, + boxes // + ); + Copy( + tmp, + fvgBoxes, + false // + ); + Clean(tmp); + bool hasFVGs = HasChild(fvgBoxes); + int fvgsCount = ArraySize(fvgBoxes); + + // + // Loop through Trend Boxes to Extract XCATRENDFVG Models ... + int count = ArraySize(trendBoxes); + for (int i = 0; i < count; i++) + { + // + XBoxZone iTrendBox = trendBoxes[i]; + + // + XCATRENDFVG iTrendFVG; + iTrendFVG.trend = iTrendBox; + + // + XBoxZone fvgs[]; + if (hasFVGs) + { + // + int fvgsCount = ExtractTrendFVGs( + fvgs, + iTrendBox, + fvgBoxes // + ); + + // + Copy( + fvgs, + iTrendFVG.fvgs // + ); + } + + // + has = iTrendFVG.IsValid(); + if (has) + { + // + AddRef( + iTrendFVG, + items // + ); + } + + // + iTrendBox.Clean(); + iTrendFVG.Clean(); + } + + // + Clean(tmp); + Clean(fvgBoxes); + Clean(trendBoxes); + + // + result = ArraySize(items); + + // + return result; +} + +// +int GetOldest(XCATRENDFVG &items[]) +{ + // + int result = -1; + + // + bool has = HasChild(items); + if (!has) + { + return result; + } + + // + XCATRENDFVG item; + int count = ArraySize(items); + for (int i = 0; i < count; i++) + { + // + XCATRENDFVG iTrendFVG = items[i]; + + // + bool canSet = + !item.IsValid() + ? true + : item.trend.from > iTrendFVG.trend.from; + if (canSet) + { + // + result = i; + item = iTrendFVG; + } + + // + iTrendFVG.Clean(); + } + + // + has = IsValidIndex(result); + item.Clean(); + + // + return result; +} + +// +// Implementations ... +class XCXCAEAPOIDetector : public XCBase +{ + // + // Public ... + public: + // + // Props ... + + // + // Pivot Verifications and Max Allowed Holding Items ... + int maxAllowedPivots; // Max Allowed Holding Pibots ... + int pivotVerifications; // Pivots Verifications ... + int pivotDetectionLoopbac; // Pivots Detection Loopback ... + double ticksDividerInPoints; // Ticks and Volume Detection Divider in Point ... + ENUM_TIMEFRAMES ticksDetectionPerid; // Ticks and Volume Detection Loopback ... + + // + // FVG Validations ... + int maxAllowedFVGsAge; + bool validateFVGsUsingPV; + bool validateFVGsUsingMANALYSER; + + // + // TREND ... + XBoxZone trendPivotP; // Prev Pivot of Market Trend ... + XBoxZone trendPivotC; // Current Pivot of Market Trend ... + ENUM_X_DIRECTION trendDir; // Trend Direction ... + + // + // Breaked Pivots ... + XBoxZone invalidPivots[]; + + // + // TICK Pivots ... + + // + bool detectTickPivots; + XBoxZone tickPivots[]; + + // + // VOLUME Pivots ... + + // + bool detectVolumePivots; + XBoxZone volumePivots[]; + + // + // RSI Peak Pivot ... + + // + bool detectRSIPeakPivots; + XBoxZone rsiPeakPivots[]; + bool newRSIPeakPivotDetected; + + // + // RSI Vale Pivot ... + + // + bool detectRSIValePivots; + XBoxZone rsiValePivots[]; + bool newRSIValePivotDetected; + + // + // CCI Peak Pivot ... + + // + bool detectCCIPeakPivots; + XBoxZone cciPeakPivots[]; + bool newCCIPeakPivotDetected; + + // + // CCI Vale Pivot ... + + // + bool detectCCIValePivots; + XBoxZone cciValePivots[]; + bool newCCIValePivotDetected; + + // + // FVG Bullish Pivots ... + + // + bool detectFVGBullishPivots; + XBoxZone fvgBullishPivots[]; + bool newFVGBullishPivotDetected; + + // + // FVG Bearish Pivots ... + + // + bool detectFVGBearishPivots; + XBoxZone fvgBearishPivots[]; + bool newFVGBearishPivotDetected; + + // + // VALE Pivot Support Swing Low ... + + // + XCAPivot valeSupSWLPivot; + bool detectValeSupSWLPivots; + XBoxZone valeSupSWLPivots[]; + bool newValeSupSWLPivotDetected; + + // + // PEAK Pivot Resistance Swing High ... + + // + XCAPivot peakResSWHPivot; + bool detectPeakResSWHPivots; + XBoxZone peakResSWHPivots[]; + bool newPeakResSWHPivotDetected; + + // + // TREND Bullish ... + + // + XCAPivot trendBullishPivot; + XBoxZone trendBullishFVGs[]; + bool detectTrendBullishPivots; + XCATRENDFVG trendBullishPivots[]; + bool newTrendBullishPivotDetected; + + // + // TREND Bearish ... + + // + XCAPivot trendBearishPivot; + XBoxZone trendBearishFVGs[]; + bool detectTrendBearishPivots; + XCATRENDFVG trendBearishPivots[]; + bool newTrendBearishPivotDetected; + + // + // RSI Crossed Over OS Pivot ... + + // + bool detectRSICrossedOverOSPivots; + XBoxZone rsiCrossedOverOSPivots[]; + bool newRSICrossedOverOSPivotDetected; + + // + // RSI Crossed Under OB Pivot ... + + // + bool detectRSICrossedUnderOBPivots; + XBoxZone rsiCrossedUnderOBPivots[]; + bool newRSICrossedUnderOBPivotDetected; + + // + // CCI Crossed Over OS Pivot ... + + // + bool detectCCICrossedOverOSPivots; + XBoxZone cciCrossedOverOSPivots[]; + bool newCCICrossedOverOSPivotDetected; + + // + // CCI Crossed Under OB Pivot ... + + // + bool detectCCICrossedUnderOBPivots; + XBoxZone cciCrossedUnderOBPivots[]; + bool newCCICrossedUnderOBPivotDetected; + + // + // Constructors ... + XCXCAEAPOIDetector( + XCXCAEAHelper *_helper // + ) + { + // + helper = _helper; + drawer = new XCPOIDrawer(); + barAnalyser = new XCBarAnalyser(); + + // + Default(); + } + + // + // De Constructors ... + ~XCXCAEAPOIDetector() + { + // + valeSupSWLPivot.Clean(); + peakResSWHPivot.Clean(); + + // + Clean(trendBullishFVGs); + trendBullishPivot.Clean(); + + // + Clean(trendBearishFVGs); + trendBearishPivot.Clean(); + + // + trendPivotP.Clean(); + trendPivotC.Clean(); + trendDir = X_DIRECTION_NONE; + + // + CleanPivots(); + + // + ZeroMemory(helper); + ZeroMemory(drawer); + ZeroMemory(barAnalyser); + } + + // + // Properties ... + + // + // Tools ... + + // + virtual void Default() + { + // + maxAllowedPivots = 50; + pivotVerifications = 5; + ticksDividerInPoints = 15; + pivotDetectionLoopbac = 100; + ticksDetectionPerid = PERIOD_D1; + + // + maxAllowedFVGsAge = 0; + validateFVGsUsingPV = false; + validateFVGsUsingMANALYSER = false; + + // + detectTickPivots = true; + detectVolumePivots = true; + detectRSIPeakPivots = true; + detectRSIValePivots = true; + detectCCIPeakPivots = true; + detectCCIValePivots = true; + detectFVGBullishPivots = true; + detectFVGBearishPivots = true; + detectValeSupSWLPivots = true; + detectPeakResSWHPivots = true; + detectTrendBullishPivots = true; + detectTrendBearishPivots = true; + detectRSICrossedOverOSPivots = true; + detectRSICrossedUnderOBPivots = true; + detectCCICrossedOverOSPivots = true; + detectCCICrossedUnderOBPivots = true; + + // + trendDir = X_DIRECTION_NONE; + } + + // + void Update( + int barIndex = 0 // + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int loopback = pivotDetectionLoopbac; + loopback = NormalizeInt(loopback, 50); + + // + int idx = -1; + int count = 0; + bool has = false; + + // + newRSIPeakPivotDetected = false; + newRSIValePivotDetected = false; + newCCIPeakPivotDetected = false; + newCCIValePivotDetected = false; + newFVGBullishPivotDetected = false; + newFVGBearishPivotDetected = false; + newValeSupSWLPivotDetected = false; + newPeakResSWHPivotDetected = false; + newTrendBullishPivotDetected = false; + newTrendBearishPivotDetected = false; + newRSICrossedOverOSPivotDetected = false; + newRSICrossedUnderOBPivotDetected = false; + newCCICrossedOverOSPivotDetected = false; + newCCICrossedUnderOBPivotDetected = false; + + // + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + int p3IDX = p2IDX + 1; + + // + int index = barIndex; + int start = index; + int end = index + loopback; + while (start < end) + { + // + // Retrieve Conditions ... + XCAEAConditions 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; + } + + // + // Bars Conditions ... + + // + // Bars Conditions ... + + // + ENUM_X_DIRECTION cBarDir; + + // + // Hammer ... + bool isCBarHammer = helper + .barAnalyser + .IsHammer( + cBar, + cBarDir // + ); + bool isCBarBullishHammer = + isCBarHammer && + IsBullish(cBarDir); + bool isCBarBearishHammer = + isCBarHammer && + IsBearish(cBarDir); + + // + // Rejected ... + bool isCBarRejected = helper + .barAnalyser + .IsRejected( + cBar, + cBarDir, + false, // Force Type ... + true // Force Fibo Pressure ... + ); + bool isCBarBullishRejected = + isCBarRejected && + IsBullish(cBarDir); + bool isCBarBearishRejected = + isCBarRejected && + IsBearish(cBarDir); + + // + // Engulfed ... + bool isCBarEngulfed = helper + .barAnalyser + .IsEngulfed( + cBar, + cBarDir // + ); + bool isCBarBullishEngulfed = + isCBarEngulfed && + IsBullish(cBarDir); + bool isCBarBearishEngulfed = + isCBarEngulfed && + IsBearish(cBarDir); + + // + // Momentum ... + bool isCBarMomentum = helper + .barAnalyser + .IsMomentum( + cBar, + cBarDir, + 1 // + ); + bool isCBarBullishMomentum = + isCBarMomentum && + IsBullish(cBarDir); + bool isCBarBearishMomentum = + isCBarMomentum && + IsBearish(cBarDir); + + // + // FVG ... + + // + XBoxZone fvgBox; + bool isFVG = barAnalyser.IsFVG( + cBar, + fvgBox // + ); + bool isBullishFVG = + isFVG && + fvgBox.IsBullish(); + bool isBearishFVG = + isFVG && + fvgBox.IsBearish(); + + // + bool isCBarHasBullishPower = isBullishFVG || + isCBarBullishRejected || + isCBarBullishEngulfed || + isCBarBullishMomentum; + + // + bool isCBarHasBearishPower = isBearishFVG || + isCBarBearishRejected || + isCBarBearishEngulfed || + isCBarBearishMomentum; + + // + // Reading Values from Conditions and + // Create Customized Conditions if required ... + + // + // PEAK ... + double zPeak = conditions.peakBuffer[zIDX]; + double cPeak = conditions.peakBuffer[cIDX]; + double pPeak = conditions.peakBuffer[pIDX]; + double p2Peak = conditions.peakBuffer[p2IDX]; + + // + // VALE ... + double zVale = conditions.valeBuffer[zIDX]; + double cVale = conditions.valeBuffer[cIDX]; + double pVale = conditions.valeBuffer[pIDX]; + double p2Vale = conditions.valeBuffer[p2IDX]; + + // + // MANALYSER ... + + // + // MAH ... + double zMAH = conditions.mahBuffer[zIDX]; + double cMAH = conditions.mahBuffer[cIDX]; + double pMAH = conditions.mahBuffer[pIDX]; + double p2MAH = conditions.mahBuffer[p2IDX]; + + // + // MAL ... + double zMAL = conditions.malBuffer[zIDX]; + double cMAL = conditions.malBuffer[cIDX]; + double pMAL = conditions.malBuffer[pIDX]; + double p2MAL = conditions.malBuffer[p2IDX]; + + // + // MAC ... + double zMAC = conditions.macBuffer[zIDX]; + double cMAC = conditions.macBuffer[cIDX]; + double pMAC = conditions.macBuffer[pIDX]; + double p2MAC = conditions.macBuffer[p2IDX]; + + // + // RSI ... + + // + double zRSI = conditions.rsiBuffer[zIDX]; + double cRSI = conditions.rsiBuffer[cIDX]; + double pRSI = conditions.rsiBuffer[pIDX]; + double p2RSI = conditions.rsiBuffer[p2IDX]; + + // + bool isRSIPeak = + pRSI > cRSI && + pRSI > p2RSI && + pRSI > zRSI; + + // + bool isRSIVale = + pRSI < cRSI && + pRSI < p2RSI && + pRSI < zRSI; + + // + // CCI ... + + // + double zCCI = conditions.cciBuffer[zIDX]; + double cCCI = conditions.cciBuffer[cIDX]; + double pCCI = conditions.cciBuffer[pIDX]; + double p2CCI = conditions.cciBuffer[p2IDX]; + + // + bool isCCIPeak = + pCCI > cCCI && + pCCI > p2CCI && + pCCI > zCCI; + + // + bool isCCIVale = + pCCI < cCCI && + pCCI < p2CCI && + pCCI < zCCI; + + // + // ATR ... + double zATR = conditions.atrBuffer[zIDX]; + double cATR = conditions.atrBuffer[cIDX]; + double pATR = conditions.atrBuffer[pIDX]; + double p2ATR = conditions.atrBuffer[p2IDX]; + + // + double atrSum = GetSum(conditions.atrBuffer); + double atrMax = GetMax(conditions.atrBuffer); + double atrMin = GetMin(conditions.atrBuffer); + double atrAvg = GetAverage(conditions.atrBuffer); + + // + // Extracting Required Data about Trending ... + + // + double zFast = conditions.fastBuffer[zIDX]; + double cFast = conditions.fastBuffer[cIDX]; + double pFast = conditions.fastBuffer[pIDX]; + double p2Fast = conditions.fastBuffer[p2IDX]; + + // + double zMedium = conditions.mediumBuffer[zIDX]; + double cMedium = conditions.mediumBuffer[cIDX]; + double pMedium = conditions.mediumBuffer[pIDX]; + double p2Medium = conditions.mediumBuffer[p2IDX]; + + // + double zSlow = conditions.slowBuffer[zIDX]; + double cSlow = conditions.slowBuffer[cIDX]; + double pSlow = conditions.slowBuffer[pIDX]; + double p2Slow = conditions.slowBuffer[p2IDX]; + + // + double z3Mas[] = { + zFast, + zMedium, + zSlow, + }; + double z3MasMin = GetMin(z3Mas); + double z3MasMax = GetMax(z3Mas); + + // + double c3Mas[] = { + cFast, + cMedium, + cSlow, + }; + double c3MasMin = GetMin(c3Mas); + double c3MasMax = GetMax(c3Mas); + + // + double p3Mas[] = { + pFast, + pMedium, + pSlow, + }; + double p3MasMin = GetMin(p3Mas); + double p3MasMax = GetMax(p3Mas); + + // + double p23Mas[] = { + p2Fast, + p2Medium, + p2Slow, + }; + double p23MasMin = GetMin(p23Mas); + double p23MasMax = GetMax(p23Mas); + + // + // Try to Custom Mechanism for Trend Detection ... + + // + bool is3MaBullish = + cFast > cSlow && + cMedium > cSlow; + bool is3MaBullishPrev = + pFast > pSlow && + pMedium > pSlow; + + // + bool is3MaBearish = + cFast < cSlow && + cMedium < cSlow; + bool is3MaBearishPrev = + pFast < pSlow && + pMedium < pSlow; + + // + bool is3MaSwitchedToBullish = is3MaBullish && + !is3MaBullishPrev; + bool is3MaSwitchedToBearish = is3MaBearish && + !is3MaBearishPrev; + + // + bool is3MaFinishedFromBullish = !is3MaBullish && + is3MaBullishPrev; + bool is3MaFinishedFromBearish = !is3MaBearish && + is3MaBearishPrev; + + // + // TREND BULLISH Conditions ... + + // + bool trendBullishStartPivotCondition = + // + // One ... + // conditions.is3MaFinishedFromBullish + // // + // || + // + // Two ... + is3MaFinishedFromBullish + // + ; + + // + bool trendBullishPivotContinuationCondition = + // + // One ... + // conditions.is3MaBullish + // // + // || + // + // Two ... + is3MaBullish + // + ; + + // + bool trendBullisPivothFinishedCondition = + // + // One ... + // conditions.is3MaSwitchedToBullish + // // + // || + // + // Two ... + is3MaSwitchedToBullish + // + ; + + // + // TREND BEARISH Conditions ... + + // + bool trendBearishStartPivotCondition = + // + // One ... + // conditions.is3MaFinishedFromBearish + // // + // || + // + // Two ... + is3MaFinishedFromBearish + // + ; + + // + bool trendBearishPivotContinuationCondition = + // + // One ... + // conditions.is3MaBearish + // // + // || + // + // Two ... + is3MaBearish + // + ; + + // + bool trendBearishivothFinishedCondition = + // + // One ... + // conditions.is3MaSwitchedToBearish + // // + // || + // + // Two ... + is3MaSwitchedToBearish + // + ; + + // + // Checking Pivots ... + + // + // Detect TICK and VOLUME Pivots ... + if (detectTickPivots || detectVolumePivots) + { + // + XOHCL ticksToBar; + XOHCL ticksFromBar; + XCTicksZone *ticksZone = NULL; + + // + datetime ticksTo = GetPeriodStartTime( + zBar.symbol, + ticksDetectionPerid, + zBar.time // + ); + bool isTicksBarInited = ticksToBar.Init( + zBar.symbol, + zBar.period, + ticksTo // + ); + datetime ticksFrom = ticksTo - PeriodSeconds(ticksDetectionPerid); + isTicksBarInited = isTicksBarInited && + ticksFromBar.Init( + zBar.symbol, + zBar.period, + ticksFrom // + ); + bool hasValidTicksTimeRange = IsValid(ticksTo) && + isTicksBarInited && + IsValid(ticksFrom) && + ticksFrom < ticksTo; + + // + bool isTickPivotExists = + hasValidTicksTimeRange && + IsExistsTickPivot( + ticksTo, + ticksFrom // + ); + + // + bool isVolumePivotExists = + hasValidTicksTimeRange && + IsExistsVolumePivot( + ticksTo, + ticksFrom // + ); + + // + bool isInitializedZone = !isTickPivotExists || + !isVolumePivotExists; + if (isInitializedZone) + { + // + isInitializedZone = InitializeTicksZone( + ticksZone, + ticksToBar, + ticksFromBar // + ); + } + + // + // TICK Pivots ... + if (detectTickPivots) + { + // + // Check Current Zone Exists or Not ... + if (isInitializedZone && !isTickPivotExists) + { + // + XBoxZone iBox; + XCTickZone *iZone; + has = ticksZone.GetMaxTickZone(iZone); + if (has) + { + // + // Try to Converts a Tick Zone to XBoxZone ... + iBox.to = ticksTo; + iBox.from = ticksFrom; + iBox.lower = iZone.low; + iBox.upper = iZone.high; + iBox.symbol = iZone.symbol; + iBox.period = iZone.period; + iBox.type = GetBoxType(XCA_TICK); + iBox.dir = X_DIRECTION_BULLISH; // Temparory ... + + // + has = iBox.IsValid(); + if (has) + { + // + AddBox( + iBox, + tickPivots // + ); + } + } + + // + iBox.Clean(); + ZeroMemory(iZone); + } + } + + // + // VOLUME Pivots ... + if (detectVolumePivots) + { + // + // Check Current Zone Exists or Not ... + if (isInitializedZone && !isVolumePivotExists) + { + // + XBoxZone iBox; + XCTickZone *iZone; + has = ticksZone.GetMaxVolumeZone(iZone); + if (has) + { + // + // Try to Converts a Tick Zone to XBoxZone ... + iBox.to = ticksTo; + iBox.from = ticksFrom; + iBox.lower = iZone.low; + iBox.upper = iZone.high; + iBox.symbol = iZone.symbol; + iBox.period = iZone.period; + iBox.type = GetBoxType(XCA_VOLUME); + iBox.dir = X_DIRECTION_BULLISH; // Temparory ... + + // + has = iBox.IsValid(); + if (has) + { + // + AddBox( + iBox, + volumePivots // + ); + } + } + + // + iBox.Clean(); + ZeroMemory(iZone); + } + } + + // + ticksToBar.Clean(); + ticksFromBar.Clean(); + ZeroMemory(ticksZone); + + // + } + + // + // RSI Peak Pivot ... + if (detectRSIPeakPivots) + { + // + bool checkingCondition = + isRSIPeak && + isCBarHasBearishPower // && + // conditions.isRSICrossedUnderOB + ; + + // + if (checkingCondition) + { + // + XCAPivot iPivot; + + // + iPivot.to = cBar.time; + iPivot.from = p2Bar.time; + iPivot.value = pBar.high; + iPivot.type = XCA_RSI_PEAK; + iPivot.symbol = cBar.symbol; + iPivot.period = cBar.period; + + // + Add( + cBar.high, + iPivot.values // + ); + Add( + pBar.high, + iPivot.values // + ); + Add( + p2Bar.high, + iPivot.values // + ); + Add( + cBar.close, + iPivot.values // + ); + Add( + pBar.close, + iPivot.values // + ); + Add( + p2Bar.close, + iPivot.values // + ); + + // + iPivot.reserve = GetMin(iPivot.values); + + // + XBoxZone iBox; + has = iPivot.IsValid(); + if (has) + { + // + has = iPivot.AsBox(iBox); + if (has) + { + // + newRSIPeakPivotDetected = AddBox( + iBox, + rsiPeakPivots // + ); + } + } + + // + iBox.Clean(); + iPivot.Clean(); + } + } + + // + // RSI Vale Pivot ... + if (detectRSIValePivots) + { + // + bool checkingCondition = + isRSIVale && + isCBarHasBullishPower // && + // conditions.isRSICrossedOverOS + ; + + // + if (checkingCondition) + { + // + XCAPivot iPivot; + + // + iPivot.to = cBar.time; + iPivot.from = p2Bar.time; + iPivot.value = pBar.low; + iPivot.type = XCA_RSI_VALE; + iPivot.symbol = cBar.symbol; + iPivot.period = cBar.period; + + // + Add( + cBar.low, + iPivot.values // + ); + Add( + pBar.low, + iPivot.values // + ); + Add( + p2Bar.low, + iPivot.values // + ); + Add( + cBar.close, + iPivot.values // + ); + Add( + pBar.close, + iPivot.values // + ); + Add( + p2Bar.close, + iPivot.values // + ); + + // + iPivot.reserve = GetMax(iPivot.values); + + // + XBoxZone iBox; + has = iPivot.IsValid(); + if (has) + { + // + has = iPivot.AsBox(iBox); + if (has) + { + // + newRSIValePivotDetected = AddBox( + iBox, + rsiValePivots // + ); + } + } + + // + iBox.Clean(); + iPivot.Clean(); + } + } + + // + // CCI Peak Pivot ... + if (detectCCIPeakPivots) + { + // + bool checkingCondition = + isCCIPeak && + isCBarHasBearishPower // && + // conditions.isCCICrossedUnderOB + ; + + // + if (checkingCondition) + { + // + XCAPivot iPivot; + + // + iPivot.to = cBar.time; + iPivot.from = p2Bar.time; + iPivot.value = pBar.high; + iPivot.type = XCA_CCI_PEAK; + iPivot.symbol = cBar.symbol; + iPivot.period = cBar.period; + + // + Add( + cBar.high, + iPivot.values // + ); + Add( + pBar.high, + iPivot.values // + ); + Add( + p2Bar.high, + iPivot.values // + ); + Add( + cBar.close, + iPivot.values // + ); + Add( + pBar.close, + iPivot.values // + ); + Add( + p2Bar.close, + iPivot.values // + ); + + // + iPivot.reserve = GetMin(iPivot.values); + + // + XBoxZone iBox; + has = iPivot.IsValid(); + if (has) + { + // + has = iPivot.AsBox(iBox); + if (has) + { + // + newCCIPeakPivotDetected = AddBox( + iBox, + cciPeakPivots // + ); + } + } + + // + iBox.Clean(); + iPivot.Clean(); + } + } + + // + // CCI Vale Pivot ... + if (detectCCIValePivots) + { + // + bool checkingCondition = + isCCIVale && + isCBarHasBullishPower // && + // conditions.isCCICrossedOverOS + ; + + // + if (checkingCondition) + { + // + XCAPivot iPivot; + + // + iPivot.to = cBar.time; + iPivot.from = p2Bar.time; + iPivot.value = pBar.low; + iPivot.type = XCA_CCI_VALE; + iPivot.symbol = cBar.symbol; + iPivot.period = cBar.period; + + // + Add( + cBar.low, + iPivot.values // + ); + Add( + pBar.low, + iPivot.values // + ); + Add( + p2Bar.low, + iPivot.values // + ); + Add( + cBar.close, + iPivot.values // + ); + Add( + pBar.close, + iPivot.values // + ); + Add( + p2Bar.close, + iPivot.values // + ); + + // + iPivot.reserve = GetMax(iPivot.values); + + // + XBoxZone iBox; + has = iPivot.IsValid(); + if (has) + { + // + has = iPivot.AsBox(iBox); + if (has) + { + // + newCCIValePivotDetected = AddBox( + iBox, + cciValePivots // + ); + } + } + + // + iBox.Clean(); + iPivot.Clean(); + } + } + + // + // FVG Bullish ... + if (detectFVGBullishPivots) + { + // + bool checkingCondition = + // + isBullishFVG && + // + fvgBox.upper < cMAL + // + // (cPeak > pPeak || + // pPeak > p2Peak) + // + ; + + // + if (checkingCondition) + { + // + XBoxZone iBox; + XCAPivot iPivot; + + // + iPivot.to = fvgBox.to; + iPivot.from = fvgBox.from; + iPivot.type = XCA_FVG_BULL; + iPivot.value = fvgBox.lower; + iPivot.reserve = fvgBox.upper; + iPivot.symbol = fvgBox.symbol; + iPivot.period = fvgBox.period; + + // + has = iPivot.IsValid(); + if (has) + { + // + has = iPivot.AsBox(iBox); + if (has) + { + // + newFVGBullishPivotDetected = AddBox( + iBox, + fvgBullishPivots // + ); + } + } + + // + iBox.Clean(); + iPivot.Clean(); + } + } + + // + // FVG Bearish ... + if (detectFVGBearishPivots) + { + // + bool checkingCondition = + // + isBearishFVG && + // + fvgBox.lower > cMAH + // + // (cVale < pVale || + // pVale < p2Vale) + // + ; + + // + if (checkingCondition) + { + // + XBoxZone iBox; + XCAPivot iPivot; + + // + iPivot.to = fvgBox.to; + iPivot.from = fvgBox.from; + iPivot.type = XCA_FVG_BEAR; + iPivot.value = fvgBox.upper; + iPivot.reserve = fvgBox.lower; + iPivot.symbol = fvgBox.symbol; + iPivot.period = fvgBox.period; + + // + has = iPivot.IsValid(); + if (has) + { + // + has = iPivot.AsBox(iBox); + if (has) + { + // + newFVGBearishPivotDetected = AddBox( + iBox, + fvgBearishPivots // + ); + } + } + + // + iBox.Clean(); + iPivot.Clean(); + } + } + + // + // VALE Pivot Support Swing Low ... + if (detectValeSupSWLPivots) + { + // + if (conditions.isValeFinishedFromPivot) + { + // + valeSupSWLPivot.Clean(); + + // + valeSupSWLPivot.type = XCA_VALESWLSUP; + valeSupSWLPivot.symbol = conditions.symbol; + valeSupSWLPivot.period = conditions.period; + + // + valeSupSWLPivot.to = pBar.time; + valeSupSWLPivot.from = pBar.time; + valeSupSWLPivot.value = conditions.valeBuffer[pIDX]; + valeSupSWLPivot.reserve = conditions.valeGoldenBuffer[pIDX]; + } + + // + if (conditions.isValeIsPivot) + { + // + valeSupSWLPivot.from = pBar.time; + + // + valeSupSWLPivot.reserve = + valeSupSWLPivot.reserve == 0 + ? conditions.valeGoldenBuffer[cIDX] + : MathMin(valeSupSWLPivot.reserve, conditions.valeGoldenBuffer[cIDX]); + } + + // + if (conditions.isValeSwitchedToPivot) + { + // + has = + valeSupSWLPivot.IsValid() && + valeSupSWLPivot.GetAge() >= pivotVerifications; + if (has) + { + // + XBoxZone iBox; + has = valeSupSWLPivot.AsBox(iBox); + if (has) + { + // + newValeSupSWLPivotDetected = AddBox( + iBox, + valeSupSWLPivots // + ); + } + + // + iBox.Clean(); + } + + // + valeSupSWLPivot.Clean(); + } + } + + // + // PEAK Pivot Resistance Swing High ... + if (detectPeakResSWHPivots) + { + // + if (conditions.isPeakFinishedFromPivot) + { + // + peakResSWHPivot.Clean(); + + // + peakResSWHPivot.type = XCA_PEAKSWHRES; + peakResSWHPivot.symbol = conditions.symbol; + peakResSWHPivot.period = conditions.period; + + // + peakResSWHPivot.to = pBar.time; + peakResSWHPivot.from = pBar.time; + peakResSWHPivot.value = conditions.peakBuffer[pIDX]; + peakResSWHPivot.reserve = conditions.peakGoldenBuffer[pIDX]; + } + + // + if (conditions.isPeakIsPivot) + { + // + peakResSWHPivot.from = pBar.time; + + // + peakResSWHPivot.reserve = + peakResSWHPivot.reserve == 0 + ? conditions.peakGoldenBuffer[cIDX] + : MathMax(peakResSWHPivot.reserve, conditions.peakGoldenBuffer[cIDX]); + } + + // + if (conditions.isPeakSwitchedToPivot) + { + // + has = + peakResSWHPivot.IsValid() && + peakResSWHPivot.GetAge() >= pivotVerifications; + if (has) + { + // + XBoxZone iBox; + has = peakResSWHPivot.AsBox(iBox); + if (has) + { + // + newPeakResSWHPivotDetected = AddBox( + iBox, + peakResSWHPivots // + ); + } + + // + iBox.Clean(); + } + + // + peakResSWHPivot.Clean(); + } + } + + // + // TREND Bullish ... + if (detectTrendBullishPivots) + { + // + if (trendBullishStartPivotCondition) + { + // + Clean(trendBullishFVGs); + trendBullishPivot.Clean(); + + // + trendBullishPivot.type = XCA_TREND_BULL; + trendBullishPivot.symbol = conditions.symbol; + trendBullishPivot.period = conditions.period; + + // + trendBullishPivot.to = pBar.time; + trendBullishPivot.from = pBar.time; + trendBullishPivot.value = p3MasMin; + trendBullishPivot.reserve = p3MasMax; + } + + // + if (trendBullishPivotContinuationCondition) + { + // + trendBullishPivot.from = pBar.time; + + // + Add( + p3MasMin, + trendBullishPivot.values // + ); + Add( + p3MasMax, + trendBullishPivot.values // + ); + + // + trendBullishPivot.reserve = + trendBullishPivot.reserve == 0 + ? p3MasMax + : MathMax(trendBullishPivot.reserve, p3MasMax); + + // + // Handling FVGs Here ... + if (isBullishFVG) + { + // + fvgBox.type = GetBoxType(XCA_FVG_BULL); + + // + AddBox( + fvgBox, + trendBullishFVGs // + ); + } + } + + // + if (trendBullisPivothFinishedCondition) + { + // + // Update Values ... + trendBullishPivot.value = GetMin(trendBullishPivot.values); + trendBullishPivot.reserve = GetMax(trendBullishPivot.values); + + // + has = + trendBullishPivot.IsValid() && + trendBullishPivot.GetAge() >= pivotVerifications; + if (has) + { + // + XBoxZone iBox; + has = trendBullishPivot.AsBox(iBox); + if (has) + { + // + XCATRENDFVG iTrendFVG; + + // + iTrendFVG.trend = iBox; + Copy( + trendBullishFVGs, + iTrendFVG.fvgs // + ); + + // + newTrendBullishPivotDetected = iTrendFVG.IsValid(); + if (newTrendBullishPivotDetected) + { + // + AddRef( + iTrendFVG, + trendBullishPivots // + ); + } + + // + iTrendFVG.Clean(); + } + + // + iBox.Clean(); + } + + // + Clean(trendBullishFVGs); + trendBullishPivot.Clean(); + } + } + + // + // TREND Bearish ... + if (detectTrendBearishPivots) + { + // + if (trendBearishStartPivotCondition) + { + // + Clean(trendBearishFVGs); + trendBearishPivot.Clean(); + + // + trendBearishPivot.type = XCA_TREND_BEAR; + trendBearishPivot.symbol = conditions.symbol; + trendBearishPivot.period = conditions.period; + + // + trendBearishPivot.to = pBar.time; + trendBearishPivot.from = pBar.time; + trendBearishPivot.value = p3MasMax; + trendBearishPivot.reserve = p3MasMin; + } + + // + if (trendBearishPivotContinuationCondition) + { + // + trendBearishPivot.from = pBar.time; + + // + Add( + p3MasMin, + trendBearishPivot.values // + ); + Add( + p3MasMax, + trendBearishPivot.values // + ); + + // + trendBearishPivot.reserve = + trendBearishPivot.reserve == 0 + ? p3MasMin + : MathMin(trendBearishPivot.reserve, p3MasMin); + + // + // Handling FVGs Here ... + if (isBearishFVG) + { + // + fvgBox.type = GetBoxType(XCA_FVG_BEAR); + + // + AddBox( + fvgBox, + trendBearishFVGs // + ); + } + } + + // + if (trendBearishivothFinishedCondition) + { + // + // Update Values ... + trendBearishPivot.value = GetMax(trendBearishPivot.values); + trendBearishPivot.reserve = GetMin(trendBearishPivot.values); + + // + has = + trendBearishPivot.IsValid() && + trendBearishPivot.GetAge() >= pivotVerifications; + if (has) + { + // + XBoxZone iBox; + has = trendBearishPivot.AsBox(iBox); + if (has) + { + // + XCATRENDFVG iTrendFVG; + + // + iTrendFVG.trend = iBox; + Copy( + trendBearishFVGs, + iTrendFVG.fvgs // + ); + + // + newTrendBearishPivotDetected = iTrendFVG.IsValid(); + if (newTrendBearishPivotDetected) + { + // + AddRef( + iTrendFVG, + trendBearishPivots // + ); + } + + // + iTrendFVG.Clean(); + } + + // + iBox.Clean(); + } + + // + Clean(trendBearishFVGs); + trendBearishPivot.Clean(); + } + } + + // + // RSI Crossed Over OS ... + if (detectRSICrossedOverOSPivots) + { + // + bool checkingCondition = + // isRSIVale && + // isCBarHasBullishPower && + conditions.isRSICrossedOverOS; + + // + if (checkingCondition) + { + // + XCAPivot iPivot; + + // + iPivot.to = cBar.time; + iPivot.value = pBar.low; + iPivot.from = p2Bar.time; + iPivot.type = XCA_RSI_COOS; + iPivot.symbol = cBar.symbol; + iPivot.period = cBar.period; + + // + Add( + cBar.high, + iPivot.values // + ); + Add( + pBar.high, + iPivot.values // + ); + Add( + p2Bar.high, + iPivot.values // + ); + Add( + cBar.low, + iPivot.values // + ); + Add( + pBar.low, + iPivot.values // + ); + Add( + p2Bar.low, + iPivot.values // + ); + + // + iPivot.value = GetMin(iPivot.values); + iPivot.reserve = GetMax(iPivot.values); + + // + XBoxZone iBox; + has = iPivot.IsValid(); + if (has) + { + // + has = iPivot.AsBox(iBox); + if (has) + { + // + newRSICrossedOverOSPivotDetected = AddBox( + iBox, + rsiCrossedOverOSPivots // + ); + } + } + + // + iBox.Clean(); + iPivot.Clean(); + } + } + + // + // RSI Crossed Under OB ... + if (detectRSICrossedUnderOBPivots) + { + // + bool checkingCondition = + // isRSIPeak && + // isCBarHasBearishPower && + conditions.isRSICrossedUnderOB; + + // + if (checkingCondition) + { + // + XCAPivot iPivot; + + // + iPivot.to = cBar.time; + iPivot.from = p2Bar.time; + iPivot.value = pBar.high; + iPivot.type = XCA_RSI_CUOB; + iPivot.symbol = cBar.symbol; + iPivot.period = cBar.period; + + // + Add( + cBar.high, + iPivot.values // + ); + Add( + pBar.high, + iPivot.values // + ); + Add( + p2Bar.high, + iPivot.values // + ); + Add( + cBar.low, + iPivot.values // + ); + Add( + pBar.low, + iPivot.values // + ); + Add( + p2Bar.low, + iPivot.values // + ); + + // + iPivot.value = GetMax(iPivot.values); + iPivot.reserve = GetMin(iPivot.values); + + // + XBoxZone iBox; + has = iPivot.IsValid(); + if (has) + { + // + has = iPivot.AsBox(iBox); + if (has) + { + // + newRSICrossedUnderOBPivotDetected = AddBox( + iBox, + rsiCrossedUnderOBPivots // + ); + } + } + + // + iBox.Clean(); + iPivot.Clean(); + } + } + + // + // CCI Crossed Over OS ... + if (detectCCICrossedOverOSPivots) + { + // + bool checkingCondition = + isCCIVale && + // isCBarHasBullishPower && + conditions.isCCICrossedOverOS; + + // + if (checkingCondition) + { + // + XCAPivot iPivot; + + // + iPivot.to = cBar.time; + iPivot.value = pBar.low; + iPivot.from = p2Bar.time; + iPivot.type = XCA_CCI_COOS; + iPivot.symbol = cBar.symbol; + iPivot.period = cBar.period; + + // + Add( + cBar.high, + iPivot.values // + ); + Add( + pBar.high, + iPivot.values // + ); + Add( + p2Bar.high, + iPivot.values // + ); + Add( + cBar.low, + iPivot.values // + ); + Add( + pBar.low, + iPivot.values // + ); + Add( + p2Bar.low, + iPivot.values // + ); + + // + iPivot.value = GetMin(iPivot.values); + iPivot.reserve = GetMax(iPivot.values); + + // + XBoxZone iBox; + has = iPivot.IsValid(); + if (has) + { + // + has = iPivot.AsBox(iBox); + if (has) + { + // + newCCICrossedOverOSPivotDetected = AddBox( + iBox, + cciCrossedOverOSPivots // + ); + } + } + + // + iBox.Clean(); + iPivot.Clean(); + } + } + + // + // CCI Crossed Under OB ... + if (detectCCICrossedUnderOBPivots) + { + // + bool checkingCondition = + isCCIPeak && + // isCBarHasBearishPower && + conditions.isCCICrossedUnderOB; + + // + if (checkingCondition) + { + // + XCAPivot iPivot; + + // + iPivot.to = cBar.time; + iPivot.from = p2Bar.time; + iPivot.value = pBar.high; + iPivot.type = XCA_CCI_CUOB; + iPivot.symbol = cBar.symbol; + iPivot.period = cBar.period; + + // + Add( + cBar.high, + iPivot.values // + ); + Add( + pBar.high, + iPivot.values // + ); + Add( + p2Bar.high, + iPivot.values // + ); + Add( + cBar.low, + iPivot.values // + ); + Add( + pBar.low, + iPivot.values // + ); + Add( + p2Bar.low, + iPivot.values // + ); + + // + iPivot.value = GetMax(iPivot.values); + iPivot.reserve = GetMin(iPivot.values); + + // + XBoxZone iBox; + has = iPivot.IsValid(); + if (has) + { + // + has = iPivot.AsBox(iBox); + if (has) + { + // + newCCICrossedUnderOBPivotDetected = AddBox( + iBox, + cciCrossedUnderOBPivots // + ); + } + } + + // + iBox.Clean(); + iPivot.Clean(); + } + } + + // + // SPIKE Bullish ... + + // + bool detectSpikeBullisPivots = true; + if (detectSpikeBullisPivots) + { + // + // For Spike Detection ... + // [] 80% of Bars Must be Same as Direction ... + // [] Price Range of Bars Must be Passed of atr mult ... + // [] Required Volume Processing if Neccessary ... + + // + bool startCondition = false; + bool continuationCondition = false; + bool endCondition = false; + + // + // TODO: Complete this ... + } + + // + start++; + + // + Clean(z3Mas); + Clean(c3Mas); + Clean(p3Mas); + Clean(p23Mas); + + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + fvgBox.Clean(); + conditions.Clean(); + } + + // + SortPivots(); + } + + // + void Validate( + XBoxZone &unAvailableBoxes[], + int barIndex = 0 // + ) + { + // + // Do All Pivots Validation ... + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + bool has = false; + + // + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + + // + // Retrieve Conditions ... + XCAEAConditions conditions; + has = helper.GetConditions( + conditions, + barIndex, + 5 // + ); + if (!has) + { + conditions.Clean(); + return; + } + + // + // Implement Validation Senarios ... + + // + // TICK Pivots ... + + // + // TODO: Complete this ... + has = HasTickPivots(); + if (has) + { + // + } + + // + // VOLUME Pivots ... + + // + // TODO: Complete this ... + has = HasVolumePivots(); + if (has) + { + // + } + + // + // RSI Peak Pivot ... + + // + has = HasRSIPeakPivots(); + if (has) + { + // + ApplyValidationOnBox( + rsiPeakPivots, + unAvailableBoxes, + barIndex // + ); + } + + // + // RSI Vale Pivot ... + + // + has = HasRSIValePivots(); + if (has) + { + // + ApplyValidationOnBox( + rsiValePivots, + unAvailableBoxes, + barIndex // + ); + } + + // + // CCI Peak Pivot ... + + // + has = HasCCIPeakPivots(); + if (has) + { + // + ApplyValidationOnBox( + cciPeakPivots, + unAvailableBoxes, + barIndex // + ); + } + + // + // CCI Vale Pivot ... + + // + has = HasCCIValePivots(); + if (has) + { + // + ApplyValidationOnBox( + cciValePivots, + unAvailableBoxes, + barIndex // + ); + } + + // + // FVG Bullish ... + + // + has = HasFVGBullishPivots(); + if (has) + { + // + ApplyValidationOnBox( + fvgBullishPivots, + unAvailableBoxes, + barIndex // + ); + + // + // Validate FVG Ages ... + if (maxAllowedFVGsAge > 0) + { + // + ApplyAgeVerification( + fvgBullishPivots, + maxAllowedFVGsAge // + ); + } + + // + // Validate FVG using PV ... + if (validateFVGsUsingPV) + { + // + ApplyFVGPVValidation( + fvgBullishPivots, + conditions // + ); + } + + // + // Validating FVGs using MANALYSER ... + // if (validateFVGsUsingMANALYSER) + // { + // // + // ApplyManalyswerValidation( + // fvgBullishPivots, + // barIndex // + // ); + // } + } + + // + // FVG Bearish ... + + // + has = HasFVGBearishPivots(); + if (has) + { + // + ApplyValidationOnBox( + fvgBearishPivots, + unAvailableBoxes, + barIndex // + ); + + // + // Validate FVG Ages ... + if (maxAllowedFVGsAge > 0) + { + // + ApplyAgeVerification( + fvgBearishPivots, + maxAllowedFVGsAge // + ); + } + + // + // Validate FVG using PV ... + if (validateFVGsUsingPV) + { + // + ApplyFVGPVValidation( + fvgBearishPivots, + conditions // + ); + } + + // + // Validating FVGs using MANALYSER ... + // if (validateFVGsUsingMANALYSER) + // { + // // + // ApplyManalyswerValidation( + // fvgBearishPivots, + // barIndex // + // ); + // } + } + + // + // VALE Pivot Support Swing Low ... + + // + has = HasValeSupSWLPivots(); + if (has) + { + // + ApplyValidationOnBox( + valeSupSWLPivots, + unAvailableBoxes, + barIndex // + ); + } + + // + // PEAK Pivot Resistance Swing High ... + + // + has = HasPeakResSWHPivots(); + if (has) + { + // + ApplyValidationOnBox( + peakResSWHPivots, + unAvailableBoxes, + barIndex // + ); + } + + // + // TREND Bullish ... + + // + has = HasTrendBullishPivots(); + if (has) + { + // + ApplyValidationOnTrendFVG( + trendBullishPivots, + unAvailableBoxes, + barIndex // + ); + } + + // + // TREND Bearish ... + + // + has = HasTrendBearishPivots(); + if (has) + { + // + ApplyValidationOnTrendFVG( + trendBearishPivots, + unAvailableBoxes, + barIndex // + ); + } + + // + // RSI Crossed Over OS ... + + // + has = HasRSICrossedOverOSPivots(); + if (has) + { + // + ApplyValidationOnBox( + rsiCrossedOverOSPivots, + unAvailableBoxes, + barIndex // + ); + } + + // + // RSI Crossed Under OB ... + + // + has = HasRSICrossedUnderOBPivots(); + if (has) + { + // + ApplyValidationOnBox( + rsiCrossedUnderOBPivots, + unAvailableBoxes, + barIndex // + ); + } + + // + // CCI Crossed Over OS ... + + // + has = HasCCICrossedOverOSPivots(); + if (has) + { + // + ApplyValidationOnBox( + cciCrossedOverOSPivots, + unAvailableBoxes, + barIndex // + ); + } + + // + // CCI Crossed Under OB ... + + // + has = HasCCICrossedUnderOBPivots(); + if (has) + { + // + ApplyValidationOnBox( + cciCrossedUnderOBPivots, + unAvailableBoxes, + barIndex // + ); + } + + // + conditions.Clean(); + + // + SortPivots(); + } + + // + int FillPivots( + XBoxZone &pivots[], + ENUM_X_DIRECTION forDir = X_DIRECTION_ALL // + ) + { + // + int result = 0; + + // + Clean(pivots); + + // + if (forDir == X_DIRECTION_NONE) + { + return result; + } + + // + int count = 0; + bool has = false; + + // + bool canFillBullish = + forDir == X_DIRECTION_ALL || + forDir == X_DIRECTION_BULLISH; + + // + bool canFillBearish = + forDir == X_DIRECTION_ALL || + forDir == X_DIRECTION_BEARISH; + + // + // Bullish ... + if (canFillBullish) + { + // + Copy( + rsiValePivots, + pivots, + false // + ); + + // + Copy( + cciValePivots, + pivots, + false // + ); + + // + Copy( + fvgBullishPivots, + pivots, + false // + ); + + // + Copy( + valeSupSWLPivots, + pivots, + false // + ); + + // + Copy( + rsiCrossedOverOSPivots, + pivots, + false // + ); + + // + Copy( + cciCrossedOverOSPivots, + pivots, + false // + ); + + // + has = HasTrendBullishPivots(); + if (has) + { + // + count = CountTrendBullishPivots(); + for (int i = 0; i < count; i++) + { + // + AddRef( + trendBullishPivots[i].trend, + pivots // + ); + + // + XBoxZone iBox; + has = trendBullishPivots[i].GetSelectedFVG(iBox); + if (has) + { + // + AddRef( + iBox, + pivots // + ); + } + + // + iBox.Clean(); + } + } + } + + // + // Bearish ... + if (canFillBearish) + { + // + Copy( + rsiPeakPivots, + pivots, + false // + ); + + // + Copy( + cciPeakPivots, + pivots, + false // + ); + + // + Copy( + fvgBearishPivots, + pivots, + false // + ); + + // + Copy( + peakResSWHPivots, + pivots, + false // + ); + + // + Copy( + rsiCrossedUnderOBPivots, + pivots, + false // + ); + + // + Copy( + cciCrossedUnderOBPivots, + pivots, + false // + ); + + // + has = HasTrendBearishPivots(); + if (has) + { + // + count = CountTrendBearishPivots(); + for (int i = 0; i < count; i++) + { + // + AddRef( + trendBearishPivots[i].trend, + pivots // + ); + + // + XBoxZone iBox; + has = trendBearishPivots[i].GetSelectedFVG(iBox); + if (has) + { + // + AddRef( + iBox, + pivots // + ); + } + + // + iBox.Clean(); + } + } + } + + // + result = ArraySize(pivots); + + // + return result; + } + + // + bool MarketTrend(ENUM_X_DIRECTION &trend) + { + // + bool result = false; + + // + // Update Market Trend ... + DetectMarketTrend(); + + // + trend = trendDir; + result = HasDirection(trend); + + // + return result; + } + + // + // Counters ... + + // + // INVALID Pivots ... + + // + bool HasInvalidPivots() + { + return HasChild(invalidPivots); + } + + // + int CountInvalidPivots() + { + return ArraySize(invalidPivots); + } + + // + // TICK Pivot ... + + // + bool HasTickPivots() + { + return HasChild(tickPivots); + } + + // + int CountTickPivots() + { + return ArraySize(tickPivots); + } + + // + // VOLUME Pivots ... + + // + bool HasVolumePivots() + { + return HasChild(volumePivots); + } + + // + int CountVolumePivots() + { + return ArraySize(volumePivots); + } + + // + // RSI Peak Pivot ... + + // + bool HasRSIPeakPivots() + { + return HasChild(rsiPeakPivots); + } + + // + int CountRSIPeakPivots() + { + return ArraySize(rsiPeakPivots); + } + + // + // RSI Vale Pivot ... + + // + bool HasRSIValePivots() + { + return HasChild(rsiValePivots); + } + + // + int CountRSIValePivots() + { + return ArraySize(rsiValePivots); + } + + // + // CCI Peak Pivot ... + + // + bool HasCCIPeakPivots() + { + return HasChild(cciPeakPivots); + } + + // + int CountCCIPeakPivots() + { + return ArraySize(cciPeakPivots); + } + + // + // CCI Vale Pivot ... + + // + bool HasCCIValePivots() + { + return HasChild(cciValePivots); + } + + // + int CountCCIValePivots() + { + return ArraySize(cciValePivots); + } + + // + // FVG Bullish ... + + // + bool HasFVGBullishPivots() + { + return HasChild(fvgBullishPivots); + } + + // + int CountFVGBullishPivots() + { + return ArraySize(fvgBullishPivots); + } + + // + // FVG Bearish ... + + // + bool HasFVGBearishPivots() + { + return HasChild(fvgBearishPivots); + } + + // + int CountFVGBearishPivots() + { + return ArraySize(fvgBearishPivots); + } + + // + // VALE Pivot Support Swing Low ... + + // + bool HasValeSupSWLPivots() + { + return HasChild(valeSupSWLPivots); + } + + // + int CountValeSupSWLPivots() + { + return ArraySize(valeSupSWLPivots); + } + + // + // PEAK Pivot Resistance Swing High ... + + // + bool HasPeakResSWHPivots() + { + return HasChild(peakResSWHPivots); + } + + // + int CountPeakResSWHPivots() + { + return ArraySize(peakResSWHPivots); + } + + // + // TREND Bullish ... + + // + bool HasTrendBullishPivots() + { + return HasChild(trendBullishPivots); + } + + // + int CountTrendBullishPivots() + { + return ArraySize(trendBullishPivots); + } + + // + // TREND Bearish ... + + // + bool HasTrendBearishPivots() + { + return HasChild(trendBearishPivots); + } + + // + int CountTrendBearishPivots() + { + return ArraySize(trendBearishPivots); + } + + // + // RSI Crossed Over OS Pivots ... + + // + bool HasRSICrossedOverOSPivots() + { + return HasChild(rsiCrossedOverOSPivots); + } + + // + int CountRSICrossedOverOSPivots() + { + return ArraySize(rsiCrossedOverOSPivots); + } + + // + // RSI Crossed Under OB Pivots ... + + // + bool HasRSICrossedUnderOBPivots() + { + return HasChild(rsiCrossedUnderOBPivots); + } + + // + int CountRSICrossedUnderOBPivots() + { + return ArraySize(rsiCrossedUnderOBPivots); + } + + // + // CCI Crossed Over OS Pivots ... + + // + bool HasCCICrossedOverOSPivots() + { + return HasChild(cciCrossedOverOSPivots); + } + + // + int CountCCICrossedOverOSPivots() + { + return ArraySize(rsiCrossedOverOSPivots); + } + + // + // CCI Crossed Under OB Pivots ... + + // + bool HasCCICrossedUnderOBPivots() + { + return HasChild(cciCrossedUnderOBPivots); + } + + // + int CountCCICrossedUnderOBPivots() + { + return ArraySize(cciCrossedUnderOBPivots); + } + + // + // Protected ... + protected: + // + // Props ... + + // + // Prrivate ... + private: + // + // Props ... + + // + XCPOIDrawer *drawer; + XCXCAEAHelper *helper; + XCBarAnalyser *barAnalyser; + + // + 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 &unAvailableBoxes[], + 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(unAvailableBoxes); + if (canCheckUnAvailableBoxes) + { + // + int idx = -1; + bool isUnAvailable = FindBoxIndex( + idx, + box, + unAvailableBoxes // + ); + 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; + + // + // Cleanup Resource ... + + // + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + // + void CleanPivots() + { + // + Clean(invalidPivots); + + // + Clean(tickPivots); + Clean(volumePivots); + Clean(rsiPeakPivots); + Clean(rsiValePivots); + Clean(cciPeakPivots); + Clean(cciValePivots); + Clean(fvgBullishPivots); + Clean(fvgBearishPivots); + Clean(valeSupSWLPivots); + Clean(peakResSWHPivots); + Clean(trendBullishPivots); + Clean(trendBearishPivots); + Clean(rsiCrossedOverOSPivots); + Clean(rsiCrossedUnderOBPivots); + Clean(cciCrossedOverOSPivots); + Clean(cciCrossedUnderOBPivots); + } + + // + void SortPivots() + { + // + bool has = false; + + // + // RSI Peak ... + has = HasRSIPeakPivots(); + if (has) + { + ApplySortOnBox(rsiPeakPivots); + } + + // + // RSI Vale ... + has = HasRSIValePivots(); + if (has) + { + ApplySortOnBox(rsiValePivots); + } + + // + // CCI Peak ... + has = HasCCIPeakPivots(); + if (has) + { + ApplySortOnBox(cciPeakPivots); + } + + // + // CCI Vale ... + has = HasCCIValePivots(); + if (has) + { + ApplySortOnBox(cciValePivots); + } + + // + // FVG Bullish ... + has = HasFVGBullishPivots(); + if (has) + { + ApplySortOnBox(fvgBullishPivots); + } + + // + // FVG Bearish ... + has = HasFVGBearishPivots(); + if (has) + { + ApplySortOnBox(fvgBearishPivots); + } + + // + // VALE SUP SWL ... + has = HasValeSupSWLPivots(); + if (has) + { + ApplySortOnBox(valeSupSWLPivots); + } + + // + // PEAK REs SWH ... + has = HasPeakResSWHPivots(); + if (has) + { + ApplySortOnBox(peakResSWHPivots); + } + + // + // PVFVG Bullish ... + has = HasTrendBullishPivots(); + if (has) + { + ApplySortOnTrendFVG(trendBullishPivots); + } + + // + // PVFVG Bearish ... + has = HasTrendBearishPivots(); + if (has) + { + ApplySortOnTrendFVG(trendBearishPivots); + } + + // + // RSI Crossed Over OS ... + has = HasRSICrossedOverOSPivots(); + if (has) + { + ApplySortOnBox(rsiCrossedOverOSPivots); + } + + // + // RSI Crossed Under OB ... + has = HasRSICrossedUnderOBPivots(); + if (has) + { + ApplySortOnBox(rsiCrossedUnderOBPivots); + } + + // + // CCI Crossed Over OS ... + has = HasCCICrossedOverOSPivots(); + if (has) + { + ApplySortOnBox(cciCrossedOverOSPivots); + } + + // + // CCI Crossed Under OB ... + has = HasCCICrossedUnderOBPivots(); + if (has) + { + ApplySortOnBox(cciCrossedUnderOBPivots); + } + + // + // INVALID Pivots ... + has = HasInvalidPivots(); + if (has) + { + ApplySortOnBox(invalidPivots); + } + } + + // + // Sorting ... + + // + void ApplySortOnBox( + 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 ApplySortOnTrendFVG( + XCATRENDFVG &items[] // + ) + { + // + int idx = -1; + bool has = false; + + // + has = HasChild(items); + if (!has) + { + return; + } + + // + XCATRENDFVG tmp[]; + Copy( + items, + tmp // + ); + Clean(items); + + // + while (HasChild(tmp)) + { + // + idx = GetOldest(tmp); + has = IsValidIndex(idx); + if (!has) + { + break; + } + + // + XCATRENDFVG iTrendFVG = tmp[idx]; + ArrayRemove( + tmp, + idx, + 1 // + ); + + // + AddRef( + iTrendFVG, + items // + ); + } + + // + CleanupArray( + items, + maxAllowedPivots // + ); + + // + Clean(tmp); + } + + // + // Validators ... + + // + void ApplyValidationOnBox( + XBoxZone &items[], + XBoxZone &unAvailableItems[], + 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, + unAvailableItems, + barIndex // + ); + if (has) + { + // + AddRef( + iBox, + items // + ); + } + + // + iBox.Clean(); + // + } + + // + Clean(tmp); + } + + // + void ApplyAgeVerification( + XBoxZone &pivots[], + int maxAllowedAge // + ) + { + // + bool has = HasChild(pivots) && + maxAllowedAge > 0; + if (!has) + { + return; + } + + // + XBoxZone tmp[]; + Copy( + pivots, + tmp // + ); + Clean(pivots); + + // + while (HasChild(tmp)) + { + // + XBoxZone iPivot = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + iPivot.to = TimeCurrent(); + + // + int iAge = iPivot.GetAge(); + has = iAge <= maxAllowedAge; + if (has) + { + // + AddRef( + iPivot, + pivots // + ); + } + + // + iPivot.Clean(); + } + + // + Clean(tmp); + } + + // + void ApplyFVGPVValidation( + XBoxZone &fvgs[], + XCAEAConditions &conditions // + ) + { + // + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + + // + bool has = HasChild(fvgs); + if (!has) + { + return; + } + + // + // Reading Values ... + + // + // PEAK ... + double zPeak = conditions.peakBuffer[zIDX]; + double cPeak = conditions.peakBuffer[cIDX]; + double pPeak = conditions.peakBuffer[pIDX]; + double p2Peak = conditions.peakBuffer[p2IDX]; + + // + // VALE ... + double zVale = conditions.valeBuffer[zIDX]; + double cVale = conditions.valeBuffer[cIDX]; + double pVale = conditions.valeBuffer[pIDX]; + double p2Vale = conditions.valeBuffer[p2IDX]; + + // + XBoxZone tmp[]; + Copy( + fvgs, + tmp // + ); + Clean(fvgs); + while (HasChild(tmp)) + { + // + XBoxZone iBox = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + bool isBullish = iBox.IsBullish(); + + // + bool isPVBreaked = + isBullish + ? cVale > iBox.upper + : cPeak < iBox.lower; + + // + has = !isPVBreaked; + if (has) + { + // + AddRef( + iBox, + fvgs // + ); + } + + // + iBox.Clean(); + } + + // + Clean(tmp); + } + + // + void ApplyValidationOnTrendFVG( + XCATRENDFVG &items[], + XBoxZone &unAvailableItems[], + int barIndex = 0 // + ) + { + // + bool has = false; + + // + has = HasChild(items); + if (!has) + { + return; + } + + // + XCATRENDFVG tmp[]; + Copy( + items, + tmp // + ); + Clean(items); + while (HasChild(tmp)) + { + // + XCATRENDFVG iTrendFVG = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + // Validate TMP Trend Box ... + has = ValidateBox( + iTrendFVG.trend, + unAvailableItems, + barIndex // + ); + if (has) + { + // + // Now we Have to Validate FVGS ... + ApplyValidationOnBox( + iTrendFVG.fvgs, + unAvailableItems, + barIndex // + ); + + // + has = iTrendFVG.IsValid(); + if (has) + { + // + AddRef( + iTrendFVG, + items // + ); + } + } + + // + iTrendFVG.Clean(); + } + + // + Clean(tmp); + } + + // + // + // + + // + bool IsExistsTickPivot( + datetime to, + datetime from // + ) + { + // + bool result = false; + + // + // Validate Args ... + result = IsValid(to) && + IsValid(from) && + to > from; + if (!result) + { + return result; + } + + // + result = HasTickPivots(); + if (!result) + { + return result; + } + + // + int idx = -1; + int count = CountTickPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = tickPivots[i]; + + // + result = iBox.to == to && + iBox.from == from; + if (result) + { + // + idx = i; + iBox.Clean(); + + // + break; + } + + // + iBox.Clean(); + } + + // + result = IsValidIndex(idx); + + // + return result; + } + + // + bool IsExistsVolumePivot( + datetime to, + datetime from // + ) + { + // + bool result = false; + + // + // Validate Args ... + result = IsValid(to) && + IsValid(from) && + to > from; + if (!result) + { + return result; + } + + // + result = HasVolumePivots(); + if (!result) + { + return result; + } + + // + int idx = -1; + int count = CountVolumePivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = volumePivots[i]; + + // + result = iBox.to == to && + iBox.from == from; + if (result) + { + // + idx = i; + iBox.Clean(); + + // + break; + } + + // + iBox.Clean(); + } + + // + result = IsValidIndex(idx); + + // + return result; + } + + // + bool InitializeTicksZone( + XCTicksZone *&zone, + XOHCL &toBar, + XOHCL &fromBar // + ) + { + // + bool result = false; + + // + result = zone == NULL; + if (!result) + { + return result; + } + + // + int toIDX = toBar.Index(); + int fromIDX = fromBar.Index(); + int rangeLength = fromIDX - toIDX; + double rangeDivider = ticksDividerInPoints * GetPoints(toBar.symbol); + double rangeL = toBar.FindLowest(rangeLength, MODE_LOW); + double rangeH = toBar.FindHighest(rangeLength, MODE_HIGH); + double rangeDiff = (rangeH - rangeL); + int zoneLevels = (int)(rangeDiff / rangeDivider); + + // + zone = new XCTicksZone(); + zone.Levels(zoneLevels); + + // + result = zone.Init( + fromBar, + toBar // + ); + if (!result) + { + ZeroMemory(zone); + } + + // + return result; + } + + // + void DetectMarketTrend() + { + // + int idx = -1; + int count = 0; + bool has = false; + + // + XBoxZone tmp[]; + has = HasPeakResSWHPivots(); + if (has) + { + // + Copy( + peakResSWHPivots, + tmp, + false // + ); + } + has = HasValeSupSWLPivots(); + if (has) + { + // + Copy( + valeSupSWLPivots, + tmp, + false // + ); + } + count = ArraySize(tmp); + has = HasChild(tmp); + if (!has) + { + return; + } + + // + has = HasDirection(trendDir); + if (!has) + { + // + trendPivotC.Clean(); + trendPivotP.Clean(); + } + + // + XBoxZone cPivot; + XBoxZone pPivot; + ENUM_X_DIRECTION dir = X_DIRECTION_NONE; + while (HasChild(tmp)) + { + // + XBoxZone iPivot; + idx = GetYoungest(tmp); + has = IsValidIndex(idx); + if (!has) + { + // + iPivot.Clean(); + break; + } + + // + iPivot = tmp[idx]; + ArrayRemove( + tmp, + idx, + 1 // + ); + + // + // Check Can Set CPivot ... + bool canSetCPivot = + !cPivot.IsValid() + ? true + : iPivot.from > cPivot.from; + if (canSetCPivot) + { + // + if (cPivot.IsValid()) + { + pPivot = cPivot; + } + + // + cPivot = iPivot; + } + + // + // Check Can Set PPivot ... + bool canSetPPivot = + !cPivot.IsValid() + ? false + : iPivot.from < cPivot.from + ? !pPivot.IsValid() + ? true + : iPivot.from > pPivot.from + : false; + if (canSetPPivot) + { + pPivot = iPivot; + } + + // + has = cPivot.IsValid() && + pPivot.IsValid(); + if (has) + { + // + iPivot.Clean(); + break; + } + + // + iPivot.Clean(); + } + + // + // Check Resources for Detecting Conditions ... + bool hasTrend = + // + cPivot.IsValid() && + pPivot.IsValid() && + cPivot.dir == pPivot.dir && + cPivot.from > pPivot.from && + (IsBullish(cPivot.dir) + ? cPivot.lower > pPivot.lower + : cPivot.upper < pPivot.upper); + // + ; + if (hasTrend) + { + // + trendPivotC = cPivot; + trendPivotP = pPivot; + trendDir = cPivot.dir; + } + + // + Clean(tmp); + cPivot.Clean(); + pPivot.Clean(); + + // + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14040218 XCAEA/Documents/BKP/xcaea.x-poi.detector.class.mq5 b/BKPS/14040218 XCAEA/Documents/BKP/xcaea.x-poi.detector.class.mq5 new file mode 100644 index 0000000..97cb01e --- /dev/null +++ b/BKPS/14040218 XCAEA/Documents/BKP/xcaea.x-poi.detector.class.mq5 @@ -0,0 +1,7731 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XCXCAEAPOIDetector ... +// Description: Class for XCAEA 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 XCAEA POI Detector" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-bar.analyser.class.mq5" +#include "../../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../Helpers/xcaea.helper.mq5" + +// +// Definitions ... + +// +enum ENUM_XCA_PIVOTS +{ + XCA_NONE, // None + XCA_LL, // LowestLow + XCA_HH, // HighestHigh + XCA_KI, // KI + XCA_SWL, // SWL + XCA_SWH, // SWH + XCA_VALE, // VALE + XCA_PEAK, // PEAK + XCA_FVG_BULL, // FVGBull + XCA_FVG_BEAR, // FVGBear + XCA_RSI_COOS, // RSICOOS + XCA_RSI_CUOB, // RSICUOB + XCA_RSI_PEAK, // RSIPeak + XCA_RSI_VALE, // RSIVale + XCA_CCI_COOS, // CCICOOS + XCA_CCI_CUOB, // CCICUOB + XCA_CCI_PEAK, // CCIPeak + XCA_CCI_VALE, // CCIVale + XCA_KI_BULL, // KIBull + XCA_KI_BEAR, // KIBear + XCA_TKI_BULL, // TKIBull + XCA_TKI_BEAR, // TKIBear + XCA_PEAKSWHRES, // PeakSWHRes + XCA_VALESWLSUP, // ValeSWLSup + XCA_TREND_BULL, // TrendBull + XCA_TREND_BEAR, // TrendBear + XCA_TKITRND_BULL, // TKITRNDBull + XCA_TKITRND_BEAR, // TKITRNDBear +}; + +// +bool IsValid(ENUM_XCA_PIVOTS value) +{ + // + bool result = false; + + // + result = value != XCA_NONE; + + // + return result; +} + +// +string ToString(ENUM_XCA_PIVOTS value) +{ + // + string result = NULL; + + // + result = EnumToString(value); + + // + return result; +} + +// +struct XCAPivot +{ + // + // Props ... + datetime to; + double value; + string symbol; + datetime from; + double reserve; + ENUM_XCA_PIVOTS type; + ENUM_TIMEFRAMES period; + + // + double values[]; + + // + // Constructor ... + XCAPivot() + { + Default(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + value = 0; + to = NULL; + reserve = 0; + from = NULL; + symbol = NULL; + period = NULL; + type = XCA_NONE; + + // + Clean(values); + + // + ZeroMemory(this); + } + + /** + * Default ... + */ + void Default() + { + // + value = 0; + to = NULL; + reserve = 0; + from = NULL; + symbol = NULL; + period = NULL; + type = XCA_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: XCAPivot ... + * + * @return ( bool ) + */ + bool IsSameAs(XCAPivot &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 = X_DIRECTION_NONE; + switch (type) + { + // + case XCA_LL: + case XCA_SWL: + case XCA_VALE: + case XCA_KI_BULL: + case XCA_FVG_BULL: + case XCA_RSI_COOS: + case XCA_RSI_VALE: + case XCA_CCI_COOS: + case XCA_CCI_VALE: + case XCA_TKI_BULL: + case XCA_TREND_BULL: + case XCA_VALESWLSUP: + case XCA_TKITRND_BULL: + iDir = X_DIRECTION_BULLISH; + break; + + // + case XCA_HH: + case XCA_SWH: + case XCA_PEAK: + case XCA_KI_BEAR: + case XCA_FVG_BEAR: + case XCA_RSI_CUOB: + case XCA_RSI_PEAK: + case XCA_CCI_CUOB: + case XCA_CCI_PEAK: + case XCA_TKI_BEAR: + case XCA_TREND_BEAR: + case XCA_PEAKSWHRES: + case XCA_TKITRND_BEAR: + iDir = X_DIRECTION_BEARISH; + break; + } + + // + 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 = ToString(type); + if (type == XCA_KI_BULL || + type == XCA_KI_BEAR) + { + // + typeStr = "XCA_KI"; + } + else if (type == XCA_FVG_BULL || + type == XCA_FVG_BEAR) + { + // + typeStr = "XCA_FVG"; + } + else if (type == XCA_RSI_COOS || + type == XCA_RSI_CUOB) + { + // + typeStr = "XCA_RSI"; + } + else if (type == XCA_CCI_COOS || + type == XCA_CCI_CUOB) + { + // + typeStr = "XCA_CCI"; + } + else if (type == XCA_TKI_BULL || + type == XCA_TKI_BEAR) + { + // + typeStr = "XCA_TKI"; + } + else if (type == XCA_TREND_BULL || + type == XCA_TREND_BEAR) + { + // + typeStr = "XCA_TREND"; + } + else if (type == XCA_TKITRND_BULL || + type == XCA_TKITRND_BEAR) + { + // + typeStr = "XCA_TKITRND"; + } + box.type = typeStr; + + // + box.upper = + isBullish + ? reserve + : value; + box.lower = + isBullish + ? value + : reserve; + + // + result = box.IsValid(); + if (!result) + { + box.Clean(); + } + + // + return result; + } + + // +}; + +// +struct XCAPVPivot +{ + // + // Props ... + double value; + XCAPivot pivots[]; + ENUM_X_DIRECTION dir; + + // + // Constructor ... + XCAPVPivot() + { + Default(); + } + + // + // Tools ... + + // + void Clean() + { + // + value = 0; + Clean(pivots); + dir = X_DIRECTION_NONE; + + // + ZeroMemory(this); + } + + // + void Default() + { + // + value = 0; + Clean(pivots); + dir = X_DIRECTION_NONE; + } + + // + bool IsValid() + { + // + bool result = false; + + // + result = value != 0 && + HasDirection(dir); + + // + return result; + } + + // + void AddPivot(XCAPivot &pivot) + { + // + if (!IsValid() || + !pivot.IsValid()) + { + return; + } + + // + int idx = -1; + bool has = FindPivotIndex( + idx, + pivot, + pivots // + ); + if (has) + { + return; + } + + // + AddRef( + pivot, + pivots // + ); + } + + // + int GetPivots(XBoxZone &pivotBoxes[]) + { + // + int result = 0; + + // + Clean(pivotBoxes); + + // + bool has = false; + + // + has = IsValid() && + HasChild(pivots); + if (!has) + { + return result; + } + + // + int count = ArraySize(pivots); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = pivots[i].AsBox(iBox); + if (has) + { + // + AddRef( + iBox, + pivotBoxes // + ); + } + + // + iBox.Clean(); + } + + // + result = ArraySize(pivotBoxes); + + // + return result; + } +}; + +// +struct XCAPVTick +{ + // + XCAPivot pivot; + XCTicksZone *zone; + + // + XCAPVTick() + { + Default(); + } + + // + // Tools ... + + // + void Clean() + { + // + pivot.Clean(); + + // + ZeroMemory(zone); + ZeroMemory(this); + } + + // + void Default() + { + // + pivot.Clean(); + + // + ZeroMemory(zone); + } + + // + bool IsValid() + { + // + bool result = false; + + // + result = pivot.IsValid() && + zone != NULL; + + // + return result; + } + + // + bool Init(XCAPivot &_pivot) + { + // + bool result = false; + + // + result = _pivot.IsValid(); + if (!result) + { + return result; + } + + // + int toIDX = _pivot.ToIndex(); + int fromIDX = _pivot.FromIndex(); + int rangeLength = fromIDX - toIDX; + result = IsValidIndex(fromIDX) && + IsValidIndex(toIDX); + if (!result) + { + // + Clean(); + return result; + } + + // + XOHCL toBar; + XOHCL fromBar; + result = toBar.Init( + _pivot.symbol, + _pivot.period, + toIDX // + ); + result = result && + fromBar.Init( + _pivot.symbol, + _pivot.period, + fromIDX // + ); + if (!result) + { + // + toBar.Clean(); + fromBar.Clean(); + + // + Clean(); + + // + return result; + } + + // + double rangeDivider = 10 * GetPoints(_pivot.symbol); + double rangeL = toBar.FindLowest(rangeLength, MODE_LOW); + double rangeH = toBar.FindHighest(rangeLength, MODE_HIGH); + double rangeDiff = (rangeH - rangeL); + int zoneLevels = (int)(rangeDiff / rangeDivider); + + // + XCTicksZone *_zone; + _zone = new XCTicksZone(); + _zone.Levels(zoneLevels); + result = _zone.Init( + fromBar, + toBar // + ); + if (!result) + { + // + toBar.Clean(); + fromBar.Clean(); + ZeroMemory(_zone); + + // + Clean(); + + // + return result; + } + + // + pivot = _pivot; + zone = _zone; + + // + result = IsValid(); + if (!result) + { + Clean(); + } + + // + toBar.Clean(); + fromBar.Clean(); + ZeroMemory(_zone); + + // + return result; + } + + // + bool GetMaxVolumeBox(XBoxZone &box) + { + // + bool result = false; + + // + box.Clean(); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + // Select MAX Volume Zone ... + XCTickZone *selectedZone = NULL; + int zonesCount = zone.Count(); + for (int j = 0; j < zonesCount; j++) + { + // + XCTickZone *jZone = zone.GetZone(j); + + // + bool canSet = + selectedZone == NULL + ? true + : selectedZone.volume < jZone.volume; + if (canSet) + { + selectedZone = jZone; + } + + // + ZeroMemory(jZone); + } + + // + result = selectedZone != NULL; + if (!result) + { + // + box.Clean(); + ZeroMemory(selectedZone); + + // + return result; + } + + // + result = pivot.AsBox(box); + if (!result) + { + // + box.Clean(); + + // + return result; + } + box.upper = selectedZone.high; + box.lower = selectedZone.low; + box.type = + pivot.type == XCA_PEAKSWHRES + ? "PEAKTICK" + : pivot.type == XCA_VALESWLSUP + ? "VALETICK" + : box.type; + + // + return result; + } + + // +}; + +/** + * Find Specified Pivot Index inside a Collection of Pivots ... + * + * @param pivot: XCAPivot instance Reference ... + * @param pivots: XCAPivot instance Reference Collection ... + * + * @return ( int ) + */ +bool FindPivotIndex( + int &index, + XCAPivot &pivot, + XCAPivot &pivots[] // +) +{ + // + bool result = false; + + // + index = -1; + + // + int count = ArraySize(pivots); + result = pivot.IsValid() && + IsValidSize(count); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XCAPivot iPivot = pivots[i]; + + // + bool isSame = pivot.IsSameAs(iPivot); + if (isSame) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; +} + +/** + * Add or Update Specified Pivot to Specified Collection ... + * + * @param pivot: XCAPivot instance reference, Specified Item ... + * @param pivots: XCAPivot instance reference Collection ... + * @param maxAllowedPivots: int, Max Allowed Pivots number of Collection ... + */ +void AddPivot( + XCAPivot &pivot, + XCAPivot &pivots[], + int maxAllowedPivots = 50 // +) +{ + // + bool has = pivot.IsValid(); + if (!has) + { + return; + } + + // + int idx = -1; + has = FindPivotIndex( + idx, + pivot, + pivots // + ); + if (has) + { + return; + } + + // + int updateIDX = -1; + int count = ArraySize(pivots); + for (int i = 0; i < count; i++) + { + // + XCAPivot iPivot = pivots[i]; + + // + has = + iPivot.to > pivot.to && + iPivot.from == pivot.from && + iPivot.value == pivot.value && + iPivot.symbol == pivot.symbol && + iPivot.period == pivot.period; + if (has) + { + // + updateIDX = i; + break; + } + } + + // + has = IsValidIndex(updateIDX); + if (!has) + { + // + AddRef( + pivot, + pivots // + ); + } + else + { + pivots[updateIDX].to = pivot.to; + } + + // + // Apply Max Allowed ... + CleanupArray( + pivots, + maxAllowedPivots // + ); +} + +/** + * Add or Update PV FVG item to Specified Collection ... + * + * @param value: double, Peak or Vale Value ... + * @param fvg: XCAPivot instance reference, Specified Pivot ... + * @param collection: XCAPVPivot instance Collection ... + */ +void AddOrUpdatePVFVG( + double value, + XCAPivot &fvg, + XCAPVPivot &collection[] // +) +{ + // + // Validate Args ... + if (value < 0 && + !fvg.IsValid() && + (fvg.type == XCA_FVG_BULL || + fvg.type == XCA_FVG_BEAR)) + { + return; + } + + // + // Check Pivot is Exists or not ... + ENUM_X_DIRECTION dir = + fvg.type == XCA_FVG_BULL + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + bool isBullish = IsBullish(dir); + bool isBearish = IsBearish(dir); + + // + // Try to Findout Pivot Value in Collection ... + int idx = -1; + int count = ArraySize(collection); + for (int i = 0; i < count; i++) + { + // + XCAPVPivot iTem = collection[i]; + + // + bool isSameValue = iTem.value == value; + bool isSameDirection = iTem.dir == dir; + + // + bool isValid = isSameValue && + isSameDirection; + if (isValid) + { + // + idx = i; + iTem.Clean(); + break; + } + + // + iTem.Clean(); + } + + // + // Try to Add Or Update Pivots ... + bool hasIndex = IsValidIndex(idx); + if (!hasIndex) + { + // + // New Item ... + XCAPVPivot iPVFVG; + + // + iPVFVG.dir = dir; + iPVFVG.value = value; + + // + AddRef( + fvg, + iPVFVG.pivots // + ); + + // + AddRef( + iPVFVG, + collection // + ); + } + else + { + // + // Add Pivot to Existing Item ... + collection[idx].AddPivot(fvg); + } + + // +} + +/** + * Add Specified PVTick to Collection ... + * + * @param pvTick: XCAPVTick instance Reference ... + * @param pvTicks: XCAPVTickinstance Reference Collection ... + */ +void AddPVTick( + XCAPVTick &pvTick, + XCAPVTick &pvTicks[] // +) +{ + // + bool has = pvTick.IsValid(); + if (!has) + { + return; + } + + // + has = false; + int count = ArraySize(pvTicks); + for (int i = 0; i < count; i++) + { + // + has = pvTicks[i].pivot.IsSameAs(pvTick.pivot); + if (has) + { + break; + } + } + + // + if (has) + { + return; + } + + // + AddRef( + pvTick, + pvTicks // + ); +} + +// +// Implementations ... +class XCXCAEAPOIDetector : public XCBase +{ + // + // Public ... + public: + // + // Props ... + + // + // Pivot Verifications and Max Allowed Holding Items ... + int pivotVerifications; // Pivots Verifications ... + int maxAllowedPivots; // Max Allowed Holding Pibots ... + + // + // Detector Pivots State Properties ... + + // + // PEAK / VALES ... + bool detectPeakPivot; + bool detectValePivot; + + // + // PEAK SWH RES / VALE SWL SUP ... + bool detectPeakSWHResPivot; + bool detectValeSWLSupPivot; + + // + // SWING HIGH / LOW ... + bool detectSWHPivot; + bool detectSWLPivot; + + // + // KI ... + bool detectKIBullishPivot; + bool detectKIBearishPivot; + + // + // TKI ... + bool detectTKIBullishPivot; + bool detectTKIBearishPivot; + + // + // FVG ... + bool detectFVGBullishPivot; + bool detectFVGBearishPivot; + + // + // SAME Cycles HH / LL ... + bool detectCycleSameLLPivot; + bool detectCycleSameHHPivot; + + // + // TREND ... + bool detectTrendBullishPivot; + bool detectTrendBearishPivot; + + // + // TKITRND ... + bool detectTKITRNDBullishPivot; + bool detectTKITRNDBearishPivot; + + // + // OSCS ... + + // + // RSI ... + bool detectRSIPeakPivot; + bool detectRSIValePivot; + bool detectRSICrossedOverOSPivot; + bool detectRSICrossedUnderOBPivot; + + // + // CCI ... + bool detectCCIPeakPivot; + bool detectCCIValePivot; + bool detectCCICrossedOverOSPivot; + bool detectCCICrossedUnderOBPivot; + + // + // Active Pivots ... + XCAPivot swhPivot; + XCAPivot swlPivot; + XCAPivot peakPivot; + XCAPivot valePivot; + XCAPivot sSameHHPivot; + XCAPivot mSameHHPivot; + XCAPivot lSameHHPivot; + XCAPivot hSameHHPivot; + XCAPivot sSameLLPivot; + XCAPivot mSameLLPivot; + XCAPivot lSameLLPivot; + XCAPivot hSameLLPivot; + XCAPivot kiBullishPivot; + XCAPivot kiBearishPivot; + XCAPivot tkiBullishPivot; + XCAPivot tkiBearishPivot; + XCAPivot peakSWHResPivot; + XCAPivot valeSWLSupPivot; + XCAPivot trendBullishPivot; + XCAPivot trendBearishPivot; + XCAPivot tkitrndBullishPivot; + XCAPivot tkitrndBearishPivot; + + // + // UnActive Pivots ... + XCAPivot swhPivots[]; + XCAPivot swlPivots[]; + XCAPivot peakPivots[]; + XCAPivot valePivots[]; + XCAPivot rsiPeakPivots[]; + XCAPivot rsiValePivots[]; + XCAPivot cciPeakPivots[]; + XCAPivot cciValePivots[]; + XCAPivot sSameHHPivots[]; + XCAPivot mSameHHPivots[]; + XCAPivot lSameHHPivots[]; + XCAPivot hSameHHPivots[]; + XCAPivot sSameLLPivots[]; + XCAPivot mSameLLPivots[]; + XCAPivot lSameLLPivots[]; + XCAPivot hSameLLPivots[]; + XCAPivot kiBullishPivots[]; + XCAPivot kiBearishPivots[]; + XCAPivot fvgBullishPivots[]; + XCAPivot fvgBearishPivots[]; + XCAPivot tkiBullishPivots[]; + XCAPivot tkiBearishPivots[]; + XCAPivot peakSWHResPivots[]; + XCAPivot valeSWLSupPivots[]; + XCAPivot trendBullishPivots[]; + XCAPivot trendBearishPivots[]; + XCAPivot tkitrndBullishPivots[]; + XCAPivot tkitrndBearishPivots[]; + XCAPivot rsiCrossedOverOSPivots[]; + XCAPivot cciCrossedOverOSPivots[]; + XCAPivot rsiCrossedUnderOBPivots[]; + XCAPivot cciCrossedUnderOBPivots[]; + + // + XCAPVTick peakTicks[]; + XCAPVTick valeTicks[]; + + // + XCAPVPivot pvFVGBullishPivots[]; + XCAPVPivot pvFVGBearishPivots[]; + + // + // Constructors ... + XCXCAEAPOIDetector( + XCXCAEAHelper *_helper // + ) + { + // + helper = _helper; + drawer = new XCPOIDrawer(); + barAnalyser = new XCBarAnalyser(); + + // + Default(); + } + + // + // De Constructors ... + ~XCXCAEAPOIDetector() + { + // + swhPivot.Clean(); + swlPivot.Clean(); + peakPivot.Clean(); + valePivot.Clean(); + sSameHHPivot.Clean(); + mSameHHPivot.Clean(); + lSameHHPivot.Clean(); + hSameHHPivot.Clean(); + sSameLLPivot.Clean(); + mSameLLPivot.Clean(); + lSameLLPivot.Clean(); + hSameLLPivot.Clean(); + kiBullishPivot.Clean(); + kiBearishPivot.Clean(); + tkiBullishPivot.Clean(); + tkiBearishPivot.Clean(); + peakSWHResPivot.Clean(); + valeSWLSupPivot.Clean(); + trendBullishPivot.Clean(); + trendBearishPivot.Clean(); + tkitrndBullishPivot.Clean(); + tkitrndBearishPivot.Clean(); + + // + Clean(swhPivots); + Clean(swlPivots); + Clean(peakPivots); + Clean(valePivots); + Clean(rsiPeakPivots); + Clean(rsiValePivots); + Clean(cciPeakPivots); + Clean(cciValePivots); + Clean(sSameHHPivots); + Clean(mSameHHPivots); + Clean(lSameHHPivots); + Clean(hSameHHPivots); + Clean(sSameLLPivots); + Clean(mSameLLPivots); + Clean(lSameLLPivots); + Clean(hSameLLPivots); + Clean(kiBullishPivots); + Clean(kiBearishPivots); + Clean(fvgBullishPivots); + Clean(fvgBearishPivots); + Clean(tkiBullishPivots); + Clean(tkiBearishPivots); + Clean(peakSWHResPivots); + Clean(valeSWLSupPivots); + Clean(trendBullishPivots); + Clean(trendBearishPivots); + Clean(tkitrndBullishPivots); + Clean(tkitrndBearishPivots); + Clean(rsiCrossedOverOSPivots); + Clean(cciCrossedOverOSPivots); + Clean(rsiCrossedUnderOBPivots); + Clean(cciCrossedUnderOBPivots); + + // + ZeroMemory(helper); + ZeroMemory(drawer); + ZeroMemory(barAnalyser); + } + + // + // Properties ... + + // + // Tools ... + + // + virtual void Default() + { + // + maxAllowedPivots = 50; + pivotVerifications = 5; + + // + detectSWHPivot = true; + detectSWLPivot = true; + detectPeakPivot = true; + detectValePivot = true; + detectRSIPeakPivot = true; + detectRSIValePivot = true; + detectCCIPeakPivot = true; + detectCCIValePivot = true; + detectKIBullishPivot = true; + detectKIBearishPivot = true; + detectFVGBullishPivot = true; + detectFVGBearishPivot = true; + detectTKIBullishPivot = true; + detectTKIBearishPivot = true; + detectPeakSWHResPivot = true; + detectValeSWLSupPivot = true; + detectCycleSameLLPivot = true; + detectCycleSameHHPivot = true; + detectTrendBullishPivot = true; + detectTrendBearishPivot = true; + detectTKITRNDBullishPivot = true; + detectTKITRNDBearishPivot = true; + detectCCICrossedOverOSPivot = true; + detectCCICrossedUnderOBPivot = true; + } + + // + void Update( + int barIndex = 0, + int loopback = 400 // + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + loopback = NormalizeInt(loopback, 400); + + // + 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; + + // + int index = barIndex; + int start = index; + int end = index + loopback; + while (start < end) + { + // + // Retrieve Conditions ... + XCAEAConditions iConditions; + has = helper.GetConditions( + iConditions, + start, + 5 // + ); + + // + // Retrieve Bars ... + XOHCL zBar; + XOHCL cBar; + XOHCL pBar; + XOHCL p2Bar; + has = zBar.Init( + iConditions.symbol, + iConditions.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(); + iConditions.Clean(); + + // + continue; + } + + // + XBoxZone fvgBox; + bool isFVG = barAnalyser.IsFVG( + cBar, + fvgBox // + ); + + // + bool isBullishFVG = + isFVG && + fvgBox.IsBullish(); + + // + bool isBearishFVG = + isFVG && + fvgBox.IsBearish(); + + // + // Provide Some Conditions ... + + // + double points = GetPoints(zBar.symbol); + + // + // PEAK ... + + // + double cPeak = iConditions.peakBuffer[cIDX]; + double pPeak = iConditions.peakBuffer[pIDX]; + double p2Peak = iConditions.peakBuffer[p2IDX]; + + // + bool isPeakStartSameLast = + cPeak == pPeak && + pPeak != p2Peak; + + // + bool isPeakFinishedSameLast = + cPeak != pPeak && + pPeak == p2Peak; + + // + // VALE ... + + // + double cVale = iConditions.valeBuffer[cIDX]; + double pVale = iConditions.valeBuffer[pIDX]; + double p2Vale = iConditions.valeBuffer[p2IDX]; + + // + bool isValeStartSameLast = + cVale == pVale && + pVale != p2Vale; + + // + bool isValeFinishedSameLast = + cVale != pVale && + pVale == p2Vale; + + // + // SWH ... + + // + double cSWH = iConditions.swingHighBuffer[cIDX]; + double pSWH = iConditions.swingHighBuffer[pIDX]; + double p2SWH = iConditions.swingHighBuffer[p2IDX]; + + // + bool isSWHStartSameLast = + cSWH == pSWH && + pSWH != p2SWH; + + // + bool isSWHFinishedSameLast = + cSWH != pSWH && + pSWH == p2SWH; + + // + // SWL ... + + // + double pSWL = iConditions.swingLowBuffer[pIDX]; + double cSWL = iConditions.swingLowBuffer[cIDX]; + double p2SWL = iConditions.swingLowBuffer[p2IDX]; + + // + bool isSWLStartSameLast = + cSWL == pSWL && + pSWL != p2SWL; + + // + bool isSWLFinishedSameLast = + cSWL != pSWL && + pSWL == p2SWL; + + // + // SUPPORT ... + + // + double cSupport = iConditions.supportBuffer[cIDX]; + double pSupport = iConditions.supportBuffer[pIDX]; + double p2Support = iConditions.supportBuffer[p2IDX]; + + // + bool isSupportStartSameLast = + cSupport == pSupport && + pSupport != p2Support; + + // + bool isSupportFinishedSameLast = + cSupport != pSupport && + pSupport == p2Support; + + // + // RESISTANCE ... + + // + double pResistance = iConditions.resistanceBuffer[pIDX]; + double cResistance = iConditions.resistanceBuffer[cIDX]; + double p2Resistance = iConditions.resistanceBuffer[p2IDX]; + + // + bool isResistanceStartSameLast = + cResistance == pResistance && + pResistance != p2Resistance; + + // + bool isResistanceFinishedSameLast = + cResistance != pResistance && + pResistance == p2Resistance; + + // + // PEAK SWH RES ... + + // + bool isCPeakIsPivot = + cPeak == cSWH && + cSWH == cResistance; + + // + bool isPPeakIsPivot = + pPeak == pSWH && + pSWH == pResistance; + + // + bool isStartPeakIsPivot = + isCPeakIsPivot && + !isPPeakIsPivot; + + // + bool isFinishedPeakIsPivot = + !isCPeakIsPivot && + isPPeakIsPivot; + + // + // VALE SWL SUP ... + + // + bool isCValeIsPivot = + cVale == cSWL && + cSWL == cSupport; + + // + bool isPValeIsPivot = + pVale == pSWL && + pSWL == pSupport; + + // + bool isStartValeIsPivot = + isCValeIsPivot && + !isPValeIsPivot; + + // + bool isFinishedValeIsPivot = + !isCValeIsPivot && + isPValeIsPivot; + + // + // TKITRND ... + + // + double cKI = iConditions.kiBuffer[cIDX]; + double pKI = iConditions.kiBuffer[pIDX]; + double p2KI = iConditions.kiBuffer[p2IDX]; + + // + double cKIState = iConditions.kiStateBuffer[cIDX]; + double pKIState = iConditions.kiStateBuffer[pIDX]; + double p2KIState = iConditions.kiStateBuffer[p2IDX]; + + // + double cTKI = iConditions.tkiBuffer[cIDX]; + double pTKI = iConditions.tkiBuffer[pIDX]; + double p2TKI = iConditions.tkiBuffer[p2IDX]; + + // + double cTKIState = iConditions.tkiStateBuffer[cIDX]; + double pTKIState = iConditions.tkiStateBuffer[pIDX]; + double p2TKIState = iConditions.tkiStateBuffer[p2IDX]; + + // + double cTrend = iConditions.trendBuffer[cIDX]; + double pTrend = iConditions.trendBuffer[pIDX]; + double p2Trend = iConditions.trendBuffer[p2IDX]; + + // + double cTrendState = iConditions.trendStateBuffer[cIDX]; + double pTrendState = iConditions.trendStateBuffer[pIDX]; + double p2TrendState = iConditions.trendStateBuffer[p2IDX]; + + // + double cTKITRNDs[] = { + cKI, + cTKI, + cTrend // + }; + + // + double cTKITRNDMin = GetMin(cTKITRNDs); + double cTKITRNDMax = GetMax(cTKITRNDs); + + // + double pTKITRNDs[] = { + pKI, + pTKI, + pTrend // + }; + + // + double pTKITRNDMin = GetMin(pTKITRNDs); + double pTKITRNDMax = GetMax(pTKITRNDs); + + // + bool isCTKITRNDBullish = + cKIState > 0 && + cTKIState > 0 && + cTrendState > 0; + + // + bool isPTKITRNDBullish = + pKIState > 0 && + pTKIState > 0 && + pTrendState > 0; + + // + bool isTKITRNDSwitchedBullish = + isCTKITRNDBullish && + !isPTKITRNDBullish; + + // + bool isCTKITRNDBearish = + cKIState < 0 && + cTKIState < 0 && + cTrendState < 0; + + // + bool isPTKITRNDBearish = + pKIState < 0 && + pTKIState < 0 && + pTrendState < 0; + + // + bool isTKITRNDSwitchedBearish = + isCTKITRNDBearish && + !isPTKITRNDBearish; + + // + // CYCLES ... + + // + double cSLL = iConditions.sLLBuffer[cIDX]; + double pSLL = iConditions.sLLBuffer[pIDX]; + double p2SLL = iConditions.sLLBuffer[p2IDX]; + + // + double cSHH = iConditions.sHHBuffer[cIDX]; + double pSHH = iConditions.sHHBuffer[pIDX]; + double p2SHH = iConditions.sHHBuffer[p2IDX]; + + // + double cMLL = iConditions.mLLBuffer[cIDX]; + double pMLL = iConditions.mLLBuffer[pIDX]; + double p2MLL = iConditions.mLLBuffer[p2IDX]; + + // + double cMHH = iConditions.mHHBuffer[cIDX]; + double pMHH = iConditions.mHHBuffer[pIDX]; + double p2MHH = iConditions.mHHBuffer[p2IDX]; + + // + double cLLL = iConditions.lLLBuffer[cIDX]; + double pLLL = iConditions.lLLBuffer[pIDX]; + double p2LLL = iConditions.lLLBuffer[p2IDX]; + + // + double cLHH = iConditions.lHHBuffer[cIDX]; + double pLHH = iConditions.lHHBuffer[pIDX]; + double p2LHH = iConditions.lHHBuffer[p2IDX]; + + // + double cHLL = iConditions.hLLBuffer[cIDX]; + double pHLL = iConditions.hLLBuffer[pIDX]; + double p2HLL = iConditions.hLLBuffer[p2IDX]; + + // + double cHHH = iConditions.hHHBuffer[cIDX]; + double pHHH = iConditions.hHHBuffer[pIDX]; + double p2HHH = iConditions.hHHBuffer[p2IDX]; + + // + // Short Cycle ... + + // + // LL ... + + // + bool isCSLLSame = + cSLL == pSLL; + + // + bool isPSLLSame = + pSLL == p2SLL; + + // + bool isSLLStartSame = + isCSLLSame && + !isPSLLSame; + + // + bool isSLLFinishedSame = + !isCSLLSame && + isPSLLSame; + + // + // HH ... + + // + bool isCSHHSame = + cSHH == pSHH; + + // + bool isPSHHSame = + pSHH == p2SHH; + + // + bool isSHHStartSame = + isCSHHSame && + !isPSHHSame; + + // + bool isSHHFinishedSame = + !isCSHHSame && + isPSHHSame; + + // + // Mediu Cycle ... + + // + // LL ... + + // + bool isCMLLSame = + cMLL == pMLL; + + // + bool isPMLLSame = + pMLL == p2MLL; + + // + bool isMLLStartSame = + isCMLLSame && + !isPMLLSame; + + // + bool isMLLFinishedSame = + !isCMLLSame && + isPMLLSame; + + // + // HH ... + + // + bool isCMHHSame = + cMHH == pMHH; + + // + bool isPMHHSame = + pMHH == p2MHH; + + // + bool isMHHStartSame = + isCMHHSame && + !isPMHHSame; + + // + bool isMHHFinishedSame = + !isCMHHSame && + isPMHHSame; + + // + // Long Cycle ... + + // + // LL ... + + // + bool isCLLLSame = + cLLL == pLLL; + + // + bool isPLLLSame = + pLLL == p2LLL; + + // + bool isLLLStartSame = + isCLLLSame && + !isPLLLSame; + + // + bool isLLLFinishedSame = + !isCLLLSame && + isPLLLSame; + + // + // HH ... + + // + bool isCLHHSame = + cLHH == pLHH; + + // + bool isPLHHSame = + pLHH == p2LHH; + + // + bool isLHHStartSame = + isCLHHSame && + !isPLHHSame; + + // + bool isLHHFinishedSame = + !isCLHHSame && + isPLHHSame; + + // + // Hind Cycle ... + + // + // LL ... + + // + bool isCHLLSame = + cHLL == pHLL; + + // + bool isPHLLSame = + pHLL == p2HLL; + + // + bool isHLLStartSame = + isCHLLSame && + !isPHLLSame; + + // + bool isHLLFinishedSame = + !isCHLLSame && + isPHLLSame; + + // + // HH ... + + // + bool isCHHHSame = + cHHH == pHHH; + + // + bool isPHHHSame = + pHHH == p2HHH; + + // + bool isHHHStartSame = + isCHHHSame && + !isPHHHSame; + + // + bool isHHHFinishedSame = + !isCHHHSame && + isPHHHSame; + + // + // KI ... + + // + bool isCKISame = + cKI == pKI; + + // + bool isPKISame = + pKI == p2KI; + + // + bool isKIStartSame = + isCKISame && + !isPKISame; + + // + bool isKIFinishedSame = + !isCKISame && + isPKISame; + + // + // RSI ... + + // + double zRSI = iConditions.rsiBuffer[zIDX]; + double cRSI = iConditions.rsiBuffer[cIDX]; + double pRSI = iConditions.rsiBuffer[pIDX]; + double p2RSI = iConditions.rsiBuffer[p2IDX]; + + // + bool isRSIPeak = + pRSI > cRSI && + pRSI > p2RSI && + pRSI > zRSI; + + // + bool isRSIVale = + pRSI < cRSI && + pRSI < p2RSI && + pRSI < zRSI; + + // + bool isRSIBullishVPattern = + cRSI > pRSI && + p2RSI > pRSI && + cRSI > iConditions.rsiOSLevel && + pRSI < iConditions.rsiOSLevel; + + // + bool isRSIBearishVPattern = + cRSI < pRSI && + p2RSI < pRSI && + cRSI < iConditions.rsiOBLevel && + pRSI > iConditions.rsiOBLevel; + + // + // CCI ... + + // + double zCCI = iConditions.cciBuffer[zIDX]; + double cCCI = iConditions.cciBuffer[cIDX]; + double pCCI = iConditions.cciBuffer[pIDX]; + double p2CCI = iConditions.cciBuffer[p2IDX]; + + // + bool isCCIPeak = + pCCI > cCCI && + pCCI > p2CCI && + pCCI > zCCI; + + // + bool isCCIVale = + pCCI < cCCI && + pCCI < p2CCI && + pCCI < zCCI; + + // + bool isCCIBullishVPattern = + cCCI > pCCI && + p2CCI > pCCI && + cCCI > iConditions.cciOSLevel && + pCCI < iConditions.cciOSLevel; + + // + bool isCCIBearishVPattern = + cCCI < pCCI && + p2CCI < pCCI && + cCCI < iConditions.cciOBLevel && + pCCI > iConditions.cciOBLevel; + + // + // Checking Pivots ... + + // + // Peak Pivot ... + if (detectPeakPivot) + { + // + if (!peakPivot.IsValid()) + { + // + peakPivot.type = XCA_PEAK; + peakPivot.symbol = iConditions.symbol; + peakPivot.period = iConditions.period; + + // + if (isPeakFinishedSameLast) + { + // + peakPivot.Clean(); + + // + peakPivot.type = XCA_PEAK; + peakPivot.symbol = iConditions.symbol; + peakPivot.period = iConditions.period; + + // + peakPivot.to = pBar.time; + peakPivot.from = pBar.time; + peakPivot.value = iConditions.peakBuffer[pIDX]; + peakPivot.reserve = iConditions.peakGoldenBuffer[pIDX]; + } + } + + // + if (iConditions.isPeakSameLast) + { + // + peakPivot.from = pBar.time; + + // + peakPivot.reserve = + peakPivot.reserve == 0 + ? iConditions.peakGoldenBuffer[cIDX] + : MathMax(peakPivot.reserve, iConditions.peakGoldenBuffer[cIDX]); + } + + // + if (isPeakStartSameLast) + { + // + has = + peakPivot.IsValid() && + peakPivot.GetAge() >= pivotVerifications; + if (has) + { + // + AddPivot( + peakPivot, + peakPivots, + maxAllowedPivots // + ); + } + + // + peakPivot.Clean(); + } + } + + // + // Vale Pivot ... + if (detectValePivot) + { + // + if (!valePivot.IsValid()) + { + // + valePivot.type = XCA_VALE; + valePivot.symbol = iConditions.symbol; + valePivot.period = iConditions.period; + + // + if (isValeFinishedSameLast) + { + // + valePivot.Clean(); + + // + valePivot.type = XCA_VALE; + valePivot.symbol = iConditions.symbol; + valePivot.period = iConditions.period; + + // + valePivot.to = pBar.time; + valePivot.from = pBar.time; + valePivot.value = iConditions.valeBuffer[pIDX]; + valePivot.reserve = iConditions.valeGoldenBuffer[pIDX]; + } + } + + // + if (iConditions.isValeSameLast) + { + // + valePivot.from = pBar.time; + + // + valePivot.reserve = + valePivot.reserve == 0 + ? iConditions.valeGoldenBuffer[cIDX] + : MathMin(valePivot.reserve, iConditions.valeGoldenBuffer[cIDX]); + } + + // + if (isValeStartSameLast) + { + // + has = valePivot.IsValid() && + valePivot.GetAge() >= pivotVerifications; + if (has) + { + // + AddPivot( + valePivot, + valePivots, + maxAllowedPivots // + ); + } + + // + valePivot.Clean(); + } + } + + // + // SWH Pivot ... + if (detectSWHPivot) + { + // + if (!swhPivot.IsValid()) + { + // + swhPivot.type = XCA_SWH; + swhPivot.symbol = iConditions.symbol; + swhPivot.period = iConditions.period; + + // + if (isSWHFinishedSameLast) + { + // + swhPivot.Clean(); + + // + swhPivot.type = XCA_SWH; + swhPivot.symbol = iConditions.symbol; + swhPivot.period = iConditions.period; + + // + swhPivot.to = pBar.time; + swhPivot.from = pBar.time; + swhPivot.value = iConditions.swingHighBuffer[pIDX]; + } + } + + // + if (iConditions.isSwingHighSameLast) + { + // + swhPivot.from = pBar.time; + + // + double reserve = swhPivot.reserve; + if (pBar.high == pSWH) + { + // + reserve = + reserve == 0 + ? pBar.GetUp() + : MathMin(reserve, pBar.GetUp()); + } + swhPivot.reserve = reserve; + } + + // + if (isSWHStartSameLast) + { + // + double reserve = swhPivot.reserve; + if (cBar.high == cSWH) + { + // + reserve = + reserve == 0 + ? cBar.GetUp() + : MathMin(reserve, cBar.GetUp()); + } + if (pBar.high == pSWH) + { + // + reserve = + reserve == 0 + ? pBar.GetUp() + : MathMin(reserve, pBar.GetUp()); + } + if (reserve == 0 || reserve == swhPivot.value) + { + reserve = swhPivot.value - (5 * points); + } + swhPivot.reserve = reserve; + + // + has = + swhPivot.IsValid() && + swhPivot.GetAge() >= pivotVerifications; + if (has) + { + // + AddPivot( + swhPivot, + swhPivots, + maxAllowedPivots // + ); + } + + // + swhPivot.Clean(); + } + } + + // + // SWL Pivot ... + if (detectSWLPivot) + { + // + if (!swlPivot.IsValid()) + { + // + swlPivot.type = XCA_SWL; + swlPivot.symbol = iConditions.symbol; + swlPivot.period = iConditions.period; + + // + if (isSWLFinishedSameLast) + { + // + swlPivot.Clean(); + + // + swlPivot.type = XCA_SWL; + swlPivot.symbol = iConditions.symbol; + swlPivot.period = iConditions.period; + + // + swlPivot.to = cBar.time; + swlPivot.from = pBar.time; + swlPivot.value = iConditions.swingLowBuffer[cIDX]; + } + } + + // + if (iConditions.isSwingLowSameLast) + { + // + swlPivot.from = pBar.time; + + // + double reserve = swlPivot.reserve; + if (pBar.low == pSWL) + { + // + reserve = + reserve == 0 + ? pBar.GetDown() + : MathMax(reserve, pBar.GetDown()); + } + swlPivot.reserve = reserve; + } + + // + if (isSWLStartSameLast) + { + // + double reserve = swlPivot.reserve; + if (cBar.low == cSWL) + { + // + reserve = + reserve == 0 + ? cBar.GetDown() + : MathMax(reserve, cBar.GetDown()); + } + if (pBar.low == pSWL) + { + // + reserve = + reserve == 0 + ? pBar.GetDown() + : MathMax(reserve, pBar.GetDown()); + } + if (reserve == 0 || reserve == swlPivot.value) + { + reserve = swlPivot.value + (5 * points); + } + swlPivot.reserve = reserve; + + // + has = + swlPivot.IsValid() && + swlPivot.GetAge() >= pivotVerifications; + if (has) + { + // + AddPivot( + swlPivot, + swlPivots, + maxAllowedPivots // + ); + } + + // + swlPivot.Clean(); + } + } + + // + // Peak SWH Res Pivot ... + if (detectPeakSWHResPivot) + { + // + if (!peakSWHResPivot.IsValid()) + { + // + peakSWHResPivot.type = XCA_PEAKSWHRES; + peakSWHResPivot.symbol = iConditions.symbol; + peakSWHResPivot.period = iConditions.period; + + // + if (isFinishedPeakIsPivot) + { + // + peakSWHResPivot.Clean(); + + // + peakSWHResPivot.type = XCA_PEAKSWHRES; + peakSWHResPivot.symbol = iConditions.symbol; + peakSWHResPivot.period = iConditions.period; + + // + peakSWHResPivot.to = pBar.time; + peakSWHResPivot.from = pBar.time; + peakSWHResPivot.value = iConditions.peakBuffer[pIDX]; + peakSWHResPivot.reserve = iConditions.peakGoldenBuffer[pIDX]; + } + } + + // + if (iConditions.isPeakIsPivot) + { + // + peakSWHResPivot.from = pBar.time; + + // + peakSWHResPivot.reserve = + peakSWHResPivot.reserve == 0 + ? iConditions.peakGoldenBuffer[pIDX] + : MathMax(peakSWHResPivot.reserve, iConditions.peakGoldenBuffer[pIDX]); + } + + // + if (isStartPeakIsPivot) + { + // + has = peakSWHResPivot.IsValid() && + peakSWHResPivot.GetAge() >= pivotVerifications; + if (has) + { + // + AddPivot( + peakSWHResPivot, + peakSWHResPivots, + maxAllowedPivots // + ); + + // + XCAPVTick peakTick; + has = peakTick.Init(peakSWHResPivot); + if (has) + { + // + AddPVTick( + peakTick, + peakTicks // + ); + } + + // + peakTick.Clean(); + } + + // + peakSWHResPivot.Clean(); + } + } + + // + // Vale SWL Sup Pivot ... + if (detectValeSWLSupPivot) + { + // + if (!valeSWLSupPivot.IsValid()) + { + // + valeSWLSupPivot.type = XCA_VALESWLSUP; + valeSWLSupPivot.symbol = iConditions.symbol; + valeSWLSupPivot.period = iConditions.period; + + // + if (isFinishedValeIsPivot) + { + // + valeSWLSupPivot.Clean(); + + // + valeSWLSupPivot.type = XCA_VALESWLSUP; + valeSWLSupPivot.symbol = iConditions.symbol; + valeSWLSupPivot.period = iConditions.period; + + // + valeSWLSupPivot.to = pBar.time; + valeSWLSupPivot.from = pBar.time; + valeSWLSupPivot.value = iConditions.valeBuffer[pIDX]; + valeSWLSupPivot.reserve = iConditions.valeGoldenBuffer[pIDX]; + } + } + + // + if (iConditions.isValeIsPivot) + { + // + valeSWLSupPivot.from = pBar.time; + + // + valeSWLSupPivot.reserve = + valeSWLSupPivot.reserve == 0 + ? iConditions.valeGoldenBuffer[pIDX] + : MathMin(valeSWLSupPivot.reserve, iConditions.valeGoldenBuffer[pIDX]); + } + + // + if (isStartValeIsPivot) + { + // + has = valeSWLSupPivot.IsValid() && + valeSWLSupPivot.GetAge() >= pivotVerifications; + if (has) + { + // + AddPivot( + valeSWLSupPivot, + valeSWLSupPivots, + maxAllowedPivots // + ); + + // + XCAPVTick valeTick; + has = valeTick.Init(valeSWLSupPivot); + if (has) + { + // + AddPVTick( + valeTick, + valeTicks // + ); + } + + // + valeTick.Clean(); + } + + // + valeSWLSupPivot.Clean(); + } + } + + // + // KI Bullish ... + if (detectKIBullishPivot) + { + // + if (!kiBullishPivot.IsValid()) + { + // + kiBullishPivot.type = XCA_KI_BULL; + kiBullishPivot.symbol = iConditions.symbol; + kiBullishPivot.period = iConditions.period; + + // + if (iConditions.isKISwitchedToBearish) + { + // + kiBullishPivot.Clean(); + + // + kiBullishPivot.type = XCA_KI_BULL; + kiBullishPivot.symbol = iConditions.symbol; + kiBullishPivot.period = iConditions.period; + + // + kiBullishPivot.to = pBar.time; + kiBullishPivot.from = pBar.time; + kiBullishPivot.value = iConditions.kiBuffer[pIDX]; + kiBullishPivot.reserve = iConditions.kiBuffer[pIDX]; + } + } + + // + if (iConditions.isKIBullish) + { + // + kiBullishPivot.from = cBar.time; + + // + Add( + iConditions.kiBuffer[cIDX], + kiBullishPivot.values // + ); + + // + kiBullishPivot.value = + kiBullishPivot.value == 0 + ? iConditions.kiBuffer[cIDX] + : MathMin(iConditions.kiBuffer[cIDX], kiBullishPivot.value); + + // + kiBullishPivot.reserve = + kiBullishPivot.reserve == 0 + ? iConditions.kiBuffer[cIDX] + : MathMax(iConditions.kiBuffer[cIDX], kiBullishPivot.reserve); + } + + // + if (iConditions.isKISwitchedToBullish) + { + // + has = + kiBullishPivot.IsValid() && + kiBullishPivot.GetAge() >= pivotVerifications; + if (has) + { + // + AddPivot( + kiBullishPivot, + kiBullishPivots, + maxAllowedPivots // + ); + } + + // + kiBullishPivot.Clean(); + } + } + + // + // KI Bearish ... + if (detectKIBearishPivot) + { + // + if (!kiBearishPivot.IsValid()) + { + // + kiBearishPivot.type = XCA_KI_BEAR; + kiBearishPivot.symbol = iConditions.symbol; + kiBearishPivot.period = iConditions.period; + + // + if (iConditions.isKISwitchedToBullish) + { + // + kiBearishPivot.Clean(); + + // + kiBearishPivot.type = XCA_KI_BEAR; + kiBearishPivot.symbol = iConditions.symbol; + kiBearishPivot.period = iConditions.period; + + // + kiBearishPivot.to = pBar.time; + kiBearishPivot.from = pBar.time; + kiBearishPivot.value = iConditions.kiBuffer[pIDX]; + kiBearishPivot.reserve = iConditions.kiBuffer[pIDX]; + } + } + + // + if (iConditions.isKIBearish) + { + // + kiBearishPivot.from = cBar.time; + + // + Add( + iConditions.kiBuffer[cIDX], + kiBearishPivot.values // + ); + + // + kiBearishPivot.value = + kiBearishPivot.value == 0 + ? iConditions.kiBuffer[cIDX] + : MathMax(iConditions.kiBuffer[cIDX], kiBearishPivot.value); + + // + kiBearishPivot.reserve = + kiBearishPivot.reserve == 0 + ? iConditions.kiBuffer[cIDX] + : MathMin(iConditions.kiBuffer[cIDX], kiBearishPivot.reserve); + } + + // + if (iConditions.isKISwitchedToBearish) + { + // + has = + kiBearishPivot.IsValid() && + kiBearishPivot.GetAge() >= pivotVerifications; + if (has) + { + // + AddPivot( + kiBearishPivot, + kiBearishPivots, + maxAllowedPivots // + ); + } + + // + kiBearishPivot.Clean(); + } + } + + // + // FVG Bullish ... + if (detectFVGBullishPivot) + { + // + if (isBullishFVG) + { + // + XCAPivot iPivot; + + // + iPivot.to = fvgBox.to; + iPivot.from = fvgBox.from; + iPivot.type = XCA_FVG_BULL; + iPivot.value = fvgBox.lower; + iPivot.reserve = fvgBox.upper; + iPivot.symbol = fvgBox.symbol; + iPivot.period = fvgBox.period; + + // + AddPivot( + iPivot, + fvgBullishPivots, + maxAllowedPivots // + ); + + // + double fValue = + fvgBox.IsBullish() + ? cVale + : cPeak; + + // + // XPVFVG Handling ... + AddOrUpdatePVFVG( + fValue, + iPivot, + pvFVGBullishPivots // + ); + + // + iPivot.Clean(); + } + } + + // + // FVG Bearish ... + if (detectFVGBearishPivot) + { + // + if (isBearishFVG) + { + // + XCAPivot iPivot; + + // + iPivot.to = fvgBox.to; + iPivot.from = fvgBox.from; + iPivot.type = XCA_FVG_BEAR; + iPivot.value = fvgBox.upper; + iPivot.reserve = fvgBox.lower; + iPivot.symbol = fvgBox.symbol; + iPivot.period = fvgBox.period; + + // + AddPivot( + iPivot, + fvgBearishPivots, + maxAllowedPivots // + ); + + // + double fValue = + fvgBox.IsBullish() + ? cVale + : cPeak; + + // + // XPVFVG Handling ... + AddOrUpdatePVFVG( + fValue, + iPivot, + pvFVGBearishPivots // + ); + + // + iPivot.Clean(); + } + } + + // + // TKI Bullish ... + if (detectTKIBullishPivot) + { + // + if (!tkiBullishPivot.IsValid()) + { + // + tkiBullishPivot.type = XCA_TKI_BULL; + tkiBullishPivot.symbol = iConditions.symbol; + tkiBullishPivot.period = iConditions.period; + + // + if (iConditions.isTKISwitchedToBearish) + { + // + tkiBullishPivot.Clean(); + + // + tkiBullishPivot.type = XCA_TKI_BULL; + tkiBullishPivot.symbol = iConditions.symbol; + tkiBullishPivot.period = iConditions.period; + + // + tkiBullishPivot.to = pBar.time; + tkiBullishPivot.from = pBar.time; + tkiBullishPivot.value = iConditions.tkiBuffer[pIDX]; + tkiBullishPivot.reserve = iConditions.tkiBuffer[pIDX]; + } + } + + // + if (iConditions.isTKIBullish) + { + // + tkiBullishPivot.from = cBar.time; + + // + Add( + iConditions.tkiBuffer[cIDX], + tkiBullishPivot.values // + ); + + // + tkiBullishPivot.value = + tkiBullishPivot.value == 0 + ? iConditions.tkiBuffer[cIDX] + : MathMin(iConditions.tkiBuffer[cIDX], tkiBullishPivot.value); + + // + tkiBullishPivot.reserve = + tkiBullishPivot.reserve == 0 + ? iConditions.tkiBuffer[cIDX] + : MathMax(iConditions.tkiBuffer[cIDX], tkiBullishPivot.reserve); + } + + // + if (iConditions.isTKISwitchedToBullish) + { + // + has = + tkiBullishPivot.IsValid() && + tkiBullishPivot.GetAge() >= pivotVerifications; + if (has) + { + // + AddPivot( + tkiBullishPivot, + tkiBullishPivots, + maxAllowedPivots // + ); + } + + // + tkiBullishPivot.Clean(); + } + } + + // + // TKI Bearish ... + if (detectTKIBearishPivot) + { + // + if (!tkiBearishPivot.IsValid()) + { + // + tkiBearishPivot.type = XCA_TKI_BEAR; + tkiBearishPivot.symbol = iConditions.symbol; + tkiBearishPivot.period = iConditions.period; + + // + if (iConditions.isTKISwitchedToBullish) + { + // + tkiBearishPivot.Clean(); + + // + tkiBearishPivot.type = XCA_TKI_BEAR; + tkiBearishPivot.symbol = iConditions.symbol; + tkiBearishPivot.period = iConditions.period; + + // + tkiBearishPivot.to = pBar.time; + tkiBearishPivot.from = pBar.time; + tkiBearishPivot.value = iConditions.tkiBuffer[pIDX]; + tkiBearishPivot.reserve = iConditions.tkiBuffer[pIDX]; + } + } + + // + if (iConditions.isTKIBearish) + { + // + tkiBearishPivot.from = cBar.time; + + // + Add( + iConditions.tkiBuffer[cIDX], + tkiBearishPivot.values // + ); + + // + tkiBearishPivot.value = + tkiBearishPivot.value == 0 + ? iConditions.tkiBuffer[cIDX] + : MathMax(iConditions.tkiBuffer[cIDX], tkiBearishPivot.value); + + // + tkiBearishPivot.reserve = + tkiBearishPivot.reserve == 0 + ? iConditions.tkiBuffer[cIDX] + : MathMin(iConditions.tkiBuffer[cIDX], tkiBearishPivot.reserve); + } + + // + if (iConditions.isTKISwitchedToBearish) + { + // + has = + tkiBearishPivot.IsValid() && + tkiBearishPivot.GetAge() >= pivotVerifications; + if (has) + { + // + AddPivot( + tkiBearishPivot, + tkiBearishPivots, + maxAllowedPivots // + ); + } + + // + tkiBearishPivot.Clean(); + } + } + + // + // TREND Bullish ... + if (detectTrendBullishPivot) + { + // + if (!trendBullishPivot.IsValid()) + { + // + trendBullishPivot.type = XCA_TREND_BULL; + trendBullishPivot.symbol = iConditions.symbol; + trendBullishPivot.period = iConditions.period; + + // + if (iConditions.isTrendSwitchedToBearish) + { + // + trendBullishPivot.Clean(); + + // + trendBullishPivot.type = XCA_TREND_BULL; + trendBullishPivot.symbol = iConditions.symbol; + trendBullishPivot.period = iConditions.period; + + // + trendBullishPivot.to = pBar.time; + trendBullishPivot.from = pBar.time; + trendBullishPivot.value = iConditions.trendBuffer[pIDX]; + trendBullishPivot.reserve = iConditions.trendBuffer[pIDX]; + } + } + + // + if (iConditions.isTrendBullish) + { + // + trendBullishPivot.from = cBar.time; + + // + Add( + iConditions.trendBuffer[cIDX], + trendBullishPivot.values // + ); + + // + trendBullishPivot.value = + trendBullishPivot.value == 0 + ? iConditions.trendBuffer[cIDX] + : MathMin(iConditions.trendBuffer[cIDX], trendBullishPivot.value); + + // + trendBullishPivot.reserve = + trendBullishPivot.reserve == 0 + ? iConditions.trendBuffer[cIDX] + : MathMax(iConditions.trendBuffer[cIDX], trendBullishPivot.reserve); + } + + // + if (iConditions.isTrendSwitchedToBullish) + { + // + has = + trendBullishPivot.IsValid() && + trendBullishPivot.GetAge() >= pivotVerifications; + if (has) + { + // + AddPivot( + trendBullishPivot, + trendBullishPivots, + maxAllowedPivots // + ); + } + + // + trendBullishPivot.Clean(); + } + } + + // + // TREND Bearish ... + if (detectTrendBearishPivot) + { + // + if (!trendBearishPivot.IsValid()) + { + // + trendBearishPivot.type = XCA_TREND_BEAR; + trendBearishPivot.symbol = iConditions.symbol; + trendBearishPivot.period = iConditions.period; + + // + if (iConditions.isTrendSwitchedToBullish) + { + // + trendBearishPivot.Clean(); + + // + trendBearishPivot.type = XCA_TREND_BEAR; + trendBearishPivot.symbol = iConditions.symbol; + trendBearishPivot.period = iConditions.period; + + // + trendBearishPivot.to = pBar.time; + trendBearishPivot.from = pBar.time; + trendBearishPivot.value = iConditions.trendBuffer[pIDX]; + trendBearishPivot.reserve = iConditions.trendBuffer[pIDX]; + } + } + + // + if (iConditions.isTrendBearish) + { + // + trendBearishPivot.from = cBar.time; + + // + Add( + iConditions.trendBuffer[cIDX], + trendBearishPivot.values // + ); + + // + trendBearishPivot.value = + trendBearishPivot.value == 0 + ? iConditions.trendBuffer[cIDX] + : MathMax(iConditions.trendBuffer[cIDX], trendBearishPivot.value); + + // + trendBearishPivot.reserve = + trendBearishPivot.reserve == 0 + ? iConditions.trendBuffer[cIDX] + : MathMin(iConditions.trendBuffer[cIDX], trendBearishPivot.reserve); + } + + // + if (iConditions.isTrendSwitchedToBearish) + { + // + has = + trendBearishPivot.IsValid() && + trendBearishPivot.GetAge() >= pivotVerifications; + if (has) + { + // + AddPivot( + trendBearishPivot, + trendBearishPivots, + maxAllowedPivots // + ); + } + + // + trendBearishPivot.Clean(); + } + } + + // + // TKITRND Bullish ... + if (detectTKITRNDBullishPivot) + { + // + if (!tkitrndBullishPivot.IsValid()) + { + // + tkitrndBullishPivot.type = XCA_TKITRND_BULL; + tkitrndBullishPivot.symbol = iConditions.symbol; + tkitrndBullishPivot.period = iConditions.period; + + // + if (!isCTKITRNDBullish && isPTKITRNDBullish) + { + // + tkitrndBullishPivot.Clean(); + + // + tkitrndBullishPivot.type = XCA_TKITRND_BULL; + tkitrndBullishPivot.symbol = iConditions.symbol; + tkitrndBullishPivot.period = iConditions.period; + + // + tkitrndBullishPivot.to = pBar.time; + tkitrndBullishPivot.from = pBar.time; + tkitrndBullishPivot.value = pTKITRNDMin; + tkitrndBullishPivot.reserve = pTKITRNDMax; + } + } + + // + if (isCTKITRNDBullish) + { + // + tkitrndBullishPivot.from = cBar.time; + + // + Add( + cTKITRNDMin, + tkitrndBullishPivot.values // + ); + + // + Add( + cTKITRNDMax, + tkitrndBullishPivot.values // + ); + + // + tkitrndBullishPivot.value = + tkitrndBullishPivot.value == 0 + ? cTKITRNDMin + : MathMin(cTKITRNDMin, tkitrndBullishPivot.value); + + // + tkitrndBullishPivot.reserve = + tkitrndBullishPivot.reserve == 0 + ? cTKITRNDMax + : MathMax(cTKITRNDMax, tkitrndBullishPivot.reserve); + } + + // + if (!isCTKITRNDBullish) + { + // + has = + tkitrndBullishPivot.IsValid() && + tkitrndBullishPivot.GetAge() >= pivotVerifications; + if (has) + { + // + AddPivot( + tkitrndBullishPivot, + tkitrndBullishPivots, + maxAllowedPivots // + ); + } + + // + trendBullishPivot.Clean(); + } + } + + // + // TKITRND Bearish ... + if (detectTKITRNDBearishPivot) + { + // + if (!tkitrndBearishPivot.IsValid()) + { + // + tkitrndBearishPivot.type = XCA_TKITRND_BEAR; + tkitrndBearishPivot.symbol = iConditions.symbol; + tkitrndBearishPivot.period = iConditions.period; + + // + if (!isCTKITRNDBearish && isPTKITRNDBearish) + { + // + tkitrndBearishPivot.Clean(); + + // + tkitrndBearishPivot.type = XCA_TKITRND_BEAR; + tkitrndBearishPivot.symbol = iConditions.symbol; + tkitrndBearishPivot.period = iConditions.period; + + // + tkitrndBearishPivot.to = pBar.time; + tkitrndBearishPivot.from = pBar.time; + tkitrndBearishPivot.value = pTKITRNDMax; + tkitrndBearishPivot.reserve = pTKITRNDMin; + } + } + + // + if (isCTKITRNDBearish) + { + // + tkitrndBearishPivot.from = cBar.time; + + // + Add( + cTKITRNDMin, + tkitrndBearishPivot.values // + ); + + // + Add( + cTKITRNDMax, + tkitrndBearishPivot.values // + ); + + // + tkitrndBearishPivot.value = + tkitrndBearishPivot.value == 0 + ? cTKITRNDMax + : MathMax(cTKITRNDMax, tkitrndBearishPivot.value); + + // + tkitrndBearishPivot.reserve = + tkitrndBearishPivot.reserve == 0 + ? cTKITRNDMin + : MathMin(cTKITRNDMin, tkitrndBearishPivot.reserve); + } + + // + if (!isCTKITRNDBearish) + { + // + has = + tkitrndBearishPivot.IsValid() && + tkitrndBearishPivot.GetAge() >= pivotVerifications; + if (has) + { + // + AddPivot( + tkitrndBearishPivot, + tkitrndBearishPivots, + maxAllowedPivots // + ); + } + + // + trendBearishPivot.Clean(); + } + } + + // + // Cycles LL ... + if (detectCycleSameLLPivot) + { + // + // Short Cycle ... + if (!sSameLLPivot.IsValid()) + { + // + sSameLLPivot.type = XCA_LL; + sSameLLPivot.symbol = iConditions.symbol; + sSameLLPivot.period = iConditions.period; + + // + if (isSLLFinishedSame) + { + // + sSameLLPivot.Clean(); + + // + sSameLLPivot.type = XCA_LL; + sSameLLPivot.symbol = iConditions.symbol; + sSameLLPivot.period = iConditions.period; + + // + sSameLLPivot.to = pBar.time; + sSameLLPivot.from = pBar.time; + sSameLLPivot.value = pSLL; + sSameLLPivot.reserve = pSLL; + } + } + + // + if (isCSLLSame) + { + // + sSameLLPivot.from = pBar.time; + + // + double reserve = sSameLLPivot.reserve; + if (pBar.low == pSLL) + { + // + reserve = + reserve == 0 + ? pBar.GetDown() + : MathMax(reserve, pBar.GetDown()); + } + sSameLLPivot.reserve = reserve; + } + + // + if (isSLLStartSame) + { + // + double reserve = sSameLLPivot.reserve; + if (cBar.low == cSLL) + { + // + reserve = + reserve == 0 + ? cBar.GetDown() + : MathMax(reserve, cBar.GetDown()); + } + if (pBar.low == pSLL) + { + // + reserve = + reserve == 0 + ? pBar.GetDown() + : MathMax(reserve, pBar.GetDown()); + } + if (reserve == 0 || reserve == sSameLLPivot.value) + { + reserve = sSameLLPivot.value + (5 * points); + } + sSameLLPivot.reserve = reserve; + + // + has = + sSameLLPivot.IsValid() && + sSameLLPivot.GetAge() >= pivotVerifications; + if (has) + { + // + AddPivot( + sSameLLPivot, + sSameLLPivots, + maxAllowedPivots // + ); + } + + // + sSameLLPivot.Clean(); + } + + // + // Medium Cycle ... + if (!mSameLLPivot.IsValid()) + { + // + mSameLLPivot.type = XCA_LL; + mSameLLPivot.symbol = iConditions.symbol; + mSameLLPivot.period = iConditions.period; + + // + if (isMLLFinishedSame) + { + // + mSameLLPivot.Clean(); + + // + mSameLLPivot.type = XCA_LL; + mSameLLPivot.symbol = iConditions.symbol; + mSameLLPivot.period = iConditions.period; + + // + mSameLLPivot.to = pBar.time; + mSameLLPivot.from = pBar.time; + mSameLLPivot.value = pMLL; + mSameLLPivot.reserve = pMLL; + } + } + + // + if (isCMLLSame) + { + // + mSameLLPivot.from = pBar.time; + + // + double reserve = mSameLLPivot.reserve; + if (pBar.low == pMLL) + { + // + reserve = + reserve == 0 + ? pBar.GetDown() + : MathMax(reserve, pBar.GetDown()); + } + mSameLLPivot.reserve = reserve; + } + + // + if (isMLLStartSame) + { + // + double reserve = mSameLLPivot.reserve; + if (cBar.low == cMLL) + { + // + reserve = + reserve == 0 + ? cBar.GetDown() + : MathMax(reserve, cBar.GetDown()); + } + if (pBar.low == pMLL) + { + // + reserve = + reserve == 0 + ? pBar.GetDown() + : MathMax(reserve, pBar.GetDown()); + } + if (reserve == 0 || reserve == mSameLLPivot.value) + { + reserve = mSameLLPivot.value + (5 * points); + } + mSameLLPivot.reserve = reserve; + + // + has = + mSameLLPivot.IsValid() && + mSameLLPivot.GetAge() >= pivotVerifications; + if (has) + { + // + AddPivot( + mSameLLPivot, + mSameLLPivots, + maxAllowedPivots // + ); + } + + // + mSameLLPivot.Clean(); + } + + // + // Long Cycle ... + if (!lSameLLPivot.IsValid()) + { + // + lSameLLPivot.type = XCA_LL; + lSameLLPivot.symbol = iConditions.symbol; + lSameLLPivot.period = iConditions.period; + + // + if (isLLLFinishedSame) + { + // + lSameLLPivot.Clean(); + + // + lSameLLPivot.type = XCA_LL; + lSameLLPivot.symbol = iConditions.symbol; + lSameLLPivot.period = iConditions.period; + + // + lSameLLPivot.to = pBar.time; + lSameLLPivot.from = pBar.time; + lSameLLPivot.value = pLLL; + lSameLLPivot.reserve = pLLL; + } + } + + // + if (isCLLLSame) + { + // + lSameLLPivot.from = pBar.time; + + // + double reserve = lSameLLPivot.reserve; + if (pBar.low == pLLL) + { + // + reserve = + reserve == 0 + ? pBar.GetDown() + : MathMax(reserve, pBar.GetDown()); + } + lSameLLPivot.reserve = reserve; + } + + // + if (isLLLStartSame) + { + // + double reserve = lSameLLPivot.reserve; + if (cBar.low == cLLL) + { + // + reserve = + reserve == 0 + ? cBar.GetDown() + : MathMax(reserve, cBar.GetDown()); + } + if (pBar.low == pLLL) + { + // + reserve = + reserve == 0 + ? pBar.GetDown() + : MathMax(reserve, pBar.GetDown()); + } + if (reserve == 0 || reserve == lSameLLPivot.value) + { + reserve = lSameLLPivot.value + (5 * points); + } + lSameLLPivot.reserve = reserve; + + // + has = + lSameLLPivot.IsValid() && + lSameLLPivot.GetAge() >= pivotVerifications; + if (has) + { + // + AddPivot( + lSameLLPivot, + lSameLLPivots, + maxAllowedPivots // + ); + } + + // + lSameLLPivot.Clean(); + } + + // + // Hind Cycle ... + if (!hSameLLPivot.IsValid()) + { + // + hSameLLPivot.type = XCA_LL; + hSameLLPivot.symbol = iConditions.symbol; + hSameLLPivot.period = iConditions.period; + + // + if (isHLLFinishedSame) + { + // + hSameLLPivot.Clean(); + + // + hSameLLPivot.type = XCA_LL; + hSameLLPivot.symbol = iConditions.symbol; + hSameLLPivot.period = iConditions.period; + + // + hSameLLPivot.to = pBar.time; + hSameLLPivot.from = pBar.time; + hSameLLPivot.value = pHLL; + hSameLLPivot.reserve = pHLL; + } + } + + // + if (isCHLLSame) + { + // + hSameLLPivot.from = pBar.time; + + // + double reserve = hSameLLPivot.reserve; + if (pBar.low == pHLL) + { + // + reserve = + reserve == 0 + ? pBar.GetDown() + : MathMax(reserve, pBar.GetDown()); + } + hSameLLPivot.reserve = reserve; + } + + // + if (isHLLStartSame) + { + // + double reserve = hSameLLPivot.reserve; + if (cBar.low == cHLL) + { + // + reserve = + reserve == 0 + ? cBar.GetDown() + : MathMax(reserve, cBar.GetDown()); + } + if (pBar.low == pHLL) + { + // + reserve = + reserve == 0 + ? pBar.GetDown() + : MathMax(reserve, pBar.GetDown()); + } + if (reserve == 0 || reserve == hSameLLPivot.value) + { + reserve = hSameLLPivot.value + (5 * points); + } + hSameLLPivot.reserve = reserve; + + // + has = + hSameLLPivot.IsValid() && + hSameLLPivot.GetAge() >= pivotVerifications; + if (has) + { + // + AddPivot( + hSameLLPivot, + hSameLLPivots, + maxAllowedPivots // + ); + } + + // + hSameLLPivot.Clean(); + } + } + + // + // Cycles HH ... + if (detectCycleSameHHPivot) + { + // + // Short Cycle ... + if (!sSameHHPivot.IsValid()) + { + // + sSameHHPivot.type = XCA_HH; + sSameHHPivot.symbol = iConditions.symbol; + sSameHHPivot.period = iConditions.period; + + // + if (isSHHFinishedSame) + { + // + sSameHHPivot.Clean(); + + // + sSameHHPivot.type = XCA_HH; + sSameHHPivot.symbol = iConditions.symbol; + sSameHHPivot.period = iConditions.period; + + // + sSameHHPivot.to = pBar.time; + sSameHHPivot.from = pBar.time; + sSameHHPivot.value = pSHH; + sSameHHPivot.reserve = pSHH; + } + } + + // + if (isCSHHSame) + { + // + sSameHHPivot.from = pBar.time; + + // + double reserve = sSameHHPivot.reserve; + if (pBar.high == pSHH) + { + // + reserve = + reserve == 0 + ? pBar.GetUp() + : MathMin(reserve, pBar.GetUp()); + } + sSameHHPivot.reserve = reserve; + } + + // + if (isSHHStartSame) + { + // + double reserve = sSameHHPivot.reserve; + if (cBar.high == cSHH) + { + // + reserve = + reserve == 0 + ? cBar.GetUp() + : MathMin(reserve, cBar.GetUp()); + } + if (pBar.high == pSHH) + { + // + reserve = + reserve == 0 + ? pBar.GetUp() + : MathMin(reserve, pBar.GetUp()); + } + if (reserve == 0 || reserve == sSameHHPivot.value) + { + reserve = sSameHHPivot.value + (5 * points); + } + sSameHHPivot.reserve = reserve; + + // + has = + sSameHHPivot.IsValid() && + sSameHHPivot.GetAge() >= pivotVerifications; + if (has) + { + // + AddPivot( + sSameHHPivot, + sSameHHPivots, + maxAllowedPivots // + ); + } + + // + sSameHHPivot.Clean(); + } + + // + // Medium Cycle ... + if (!mSameHHPivot.IsValid()) + { + // + mSameHHPivot.type = XCA_HH; + mSameHHPivot.symbol = iConditions.symbol; + mSameHHPivot.period = iConditions.period; + + // + if (isMHHFinishedSame) + { + // + mSameHHPivot.Clean(); + + // + mSameHHPivot.type = XCA_HH; + mSameHHPivot.symbol = iConditions.symbol; + mSameHHPivot.period = iConditions.period; + + // + mSameHHPivot.to = pBar.time; + mSameHHPivot.from = pBar.time; + mSameHHPivot.value = pMHH; + mSameHHPivot.reserve = pMHH; + } + } + + // + if (isCMHHSame) + { + // + mSameHHPivot.from = pBar.time; + + // + double reserve = mSameHHPivot.reserve; + if (pBar.high == pMHH) + { + // + reserve = + reserve == 0 + ? pBar.GetUp() + : MathMin(reserve, pBar.GetUp()); + } + mSameHHPivot.reserve = reserve; + } + + // + if (isMHHStartSame) + { + // + double reserve = mSameHHPivot.reserve; + if (cBar.high == cMHH) + { + // + reserve = + reserve == 0 + ? cBar.GetUp() + : MathMin(reserve, cBar.GetUp()); + } + if (pBar.high == pMHH) + { + // + reserve = + reserve == 0 + ? pBar.GetUp() + : MathMin(reserve, pBar.GetUp()); + } + if (reserve == 0 || reserve == mSameHHPivot.value) + { + reserve = mSameHHPivot.value + (5 * points); + } + mSameHHPivot.reserve = reserve; + + // + has = + mSameHHPivot.IsValid() && + mSameHHPivot.GetAge() >= pivotVerifications; + if (has) + { + // + AddPivot( + mSameHHPivot, + mSameHHPivots, + maxAllowedPivots // + ); + } + + // + mSameHHPivot.Clean(); + } + + // + // Long Cycle ... + if (!lSameHHPivot.IsValid()) + { + // + lSameHHPivot.type = XCA_HH; + lSameHHPivot.symbol = iConditions.symbol; + lSameHHPivot.period = iConditions.period; + + // + if (isLHHFinishedSame) + { + // + lSameHHPivot.Clean(); + + // + lSameHHPivot.type = XCA_HH; + lSameHHPivot.symbol = iConditions.symbol; + lSameHHPivot.period = iConditions.period; + + // + lSameHHPivot.to = pBar.time; + lSameHHPivot.from = pBar.time; + lSameHHPivot.value = pLHH; + lSameHHPivot.reserve = pLHH; + } + } + + // + if (isCLHHSame) + { + // + lSameHHPivot.from = pBar.time; + + // + double reserve = lSameHHPivot.reserve; + if (pBar.high == pLHH) + { + // + reserve = + reserve == 0 + ? pBar.GetUp() + : MathMin(reserve, pBar.GetUp()); + } + lSameHHPivot.reserve = reserve; + } + + // + if (isLHHStartSame) + { + // + double reserve = lSameHHPivot.reserve; + if (cBar.high == cLHH) + { + // + reserve = + reserve == 0 + ? cBar.GetUp() + : MathMin(reserve, cBar.GetUp()); + } + if (pBar.high == pLHH) + { + // + reserve = + reserve == 0 + ? pBar.GetUp() + : MathMin(reserve, pBar.GetUp()); + } + if (reserve == 0 || reserve == lSameHHPivot.value) + { + reserve = lSameHHPivot.value + (5 * points); + } + lSameHHPivot.reserve = reserve; + + // + has = + lSameHHPivot.IsValid() && + lSameHHPivot.GetAge() >= pivotVerifications; + if (has) + { + // + AddPivot( + lSameHHPivot, + lSameHHPivots, + maxAllowedPivots // + ); + } + + // + lSameHHPivot.Clean(); + } + + // + // Hind Cycle ... + if (!hSameHHPivot.IsValid()) + { + // + hSameHHPivot.type = XCA_HH; + hSameHHPivot.symbol = iConditions.symbol; + hSameHHPivot.period = iConditions.period; + + // + if (isHHHFinishedSame) + { + // + hSameHHPivot.Clean(); + + // + hSameHHPivot.type = XCA_HH; + hSameHHPivot.symbol = iConditions.symbol; + hSameHHPivot.period = iConditions.period; + + // + hSameHHPivot.to = pBar.time; + hSameHHPivot.from = pBar.time; + hSameHHPivot.value = pHHH; + hSameHHPivot.reserve = pHHH; + } + } + + // + if (isCHHHSame) + { + // + hSameHHPivot.from = pBar.time; + + // + double reserve = hSameHHPivot.reserve; + if (pBar.high == pHHH) + { + // + reserve = + reserve == 0 + ? pBar.GetUp() + : MathMin(reserve, pBar.GetUp()); + } + hSameHHPivot.reserve = reserve; + } + + // + if (isHHHStartSame) + { + // + double reserve = hSameHHPivot.reserve; + if (cBar.high == cHHH) + { + // + reserve = + reserve == 0 + ? cBar.GetUp() + : MathMin(reserve, cBar.GetUp()); + } + if (pBar.high == pHHH) + { + // + reserve = + reserve == 0 + ? pBar.GetUp() + : MathMin(reserve, pBar.GetUp()); + } + if (reserve == 0 || reserve == hSameHHPivot.value) + { + reserve = hSameHHPivot.value + (5 * points); + } + hSameHHPivot.reserve = reserve; + + // + has = + hSameHHPivot.IsValid() && + hSameHHPivot.GetAge() >= pivotVerifications; + if (has) + { + // + AddPivot( + hSameHHPivot, + hSameHHPivots, + maxAllowedPivots // + ); + } + + // + hSameHHPivot.Clean(); + } + } + + // + // RSI Peak ... + if (detectRSIPeakPivot) + { + // + if (isRSIPeak) + { + // + XCAPivot iPivot; + + // + iPivot.to = cBar.time; + iPivot.from = p2Bar.time; + iPivot.value = pBar.high; + iPivot.type = XCA_RSI_PEAK; + iPivot.symbol = cBar.symbol; + iPivot.period = cBar.period; + + // + Add( + cBar.high, + iPivot.values // + ); + Add( + pBar.high, + iPivot.values // + ); + Add( + p2Bar.high, + iPivot.values // + ); + Add( + cBar.close, + iPivot.values // + ); + Add( + pBar.close, + iPivot.values // + ); + Add( + p2Bar.close, + iPivot.values // + ); + + // + iPivot.reserve = GetMin(iPivot.values); + + // + AddPivot( + iPivot, + rsiPeakPivots, + maxAllowedPivots // + ); + + // + iPivot.Clean(); + } + } + + // + // RSI Vale ... + if (detectRSIValePivot) + { + // + if (isRSIVale) + { + // + XCAPivot iPivot; + + // + iPivot.to = cBar.time; + iPivot.from = p2Bar.time; + iPivot.value = pBar.low; + iPivot.type = XCA_RSI_VALE; + iPivot.symbol = cBar.symbol; + iPivot.period = cBar.period; + + // + Add( + cBar.low, + iPivot.values // + ); + Add( + pBar.low, + iPivot.values // + ); + Add( + p2Bar.low, + iPivot.values // + ); + Add( + cBar.close, + iPivot.values // + ); + Add( + pBar.close, + iPivot.values // + ); + Add( + p2Bar.close, + iPivot.values // + ); + + // + iPivot.reserve = GetMax(iPivot.values); + + // + AddPivot( + iPivot, + rsiValePivots, + maxAllowedPivots // + ); + + // + iPivot.Clean(); + } + } + + // + // RSI Crossed Over OS ... + if (detectRSICrossedOverOSPivot) + { + // + if (isRSIBullishVPattern) + { + // + XCAPivot iPivot; + + // + iPivot.to = cBar.time; + iPivot.from = p2Bar.time; + iPivot.value = pBar.low; + iPivot.type = XCA_RSI_COOS; + iPivot.symbol = cBar.symbol; + iPivot.period = cBar.period; + + // + Add( + cBar.low, + iPivot.values // + ); + Add( + pBar.low, + iPivot.values // + ); + Add( + p2Bar.low, + iPivot.values // + ); + Add( + cBar.close, + iPivot.values // + ); + Add( + pBar.close, + iPivot.values // + ); + Add( + p2Bar.close, + iPivot.values // + ); + + // + iPivot.reserve = GetMax(iPivot.values); + + // + AddPivot( + iPivot, + rsiCrossedOverOSPivots, + maxAllowedPivots // + ); + + // + iPivot.Clean(); + } + } + + // + // RSI Crossed Under OS ... + if (detectRSICrossedUnderOBPivot) + { + // + if (isRSIBearishVPattern) + { + // + XCAPivot iPivot; + + // + iPivot.to = cBar.time; + iPivot.from = p2Bar.time; + iPivot.value = pBar.high; + iPivot.type = XCA_RSI_CUOB; + iPivot.symbol = cBar.symbol; + iPivot.period = cBar.period; + + // + Add( + cBar.high, + iPivot.values // + ); + Add( + pBar.high, + iPivot.values // + ); + Add( + p2Bar.high, + iPivot.values // + ); + Add( + cBar.close, + iPivot.values // + ); + Add( + pBar.close, + iPivot.values // + ); + Add( + p2Bar.close, + iPivot.values // + ); + + // + iPivot.reserve = GetMin(iPivot.values); + + // + AddPivot( + iPivot, + rsiCrossedUnderOBPivots, + maxAllowedPivots // + ); + + // + iPivot.Clean(); + } + } + + // + // CCI Peak ... + if (detectCCIPeakPivot) + { + // + if (isCCIPeak) + { + // + XCAPivot iPivot; + + // + iPivot.to = cBar.time; + iPivot.from = p2Bar.time; + iPivot.value = pBar.high; + iPivot.type = XCA_CCI_PEAK; + iPivot.symbol = cBar.symbol; + iPivot.period = cBar.period; + + // + Add( + cBar.high, + iPivot.values // + ); + Add( + pBar.high, + iPivot.values // + ); + Add( + p2Bar.high, + iPivot.values // + ); + Add( + cBar.close, + iPivot.values // + ); + Add( + pBar.close, + iPivot.values // + ); + Add( + p2Bar.close, + iPivot.values // + ); + + // + iPivot.reserve = GetMin(iPivot.values); + + // + AddPivot( + iPivot, + cciPeakPivots, + maxAllowedPivots // + ); + + // + iPivot.Clean(); + } + } + + // + // CCI Vale ... + if (detectCCIValePivot) + { + // + if (isCCIVale) + { + // + XCAPivot iPivot; + + // + iPivot.to = cBar.time; + iPivot.from = p2Bar.time; + iPivot.value = pBar.low; + iPivot.type = XCA_CCI_VALE; + iPivot.symbol = cBar.symbol; + iPivot.period = cBar.period; + + // + Add( + cBar.low, + iPivot.values // + ); + Add( + pBar.low, + iPivot.values // + ); + Add( + p2Bar.low, + iPivot.values // + ); + Add( + cBar.close, + iPivot.values // + ); + Add( + pBar.close, + iPivot.values // + ); + Add( + p2Bar.close, + iPivot.values // + ); + + // + iPivot.reserve = GetMax(iPivot.values); + + // + AddPivot( + iPivot, + cciValePivots, + maxAllowedPivots // + ); + + // + iPivot.Clean(); + } + } + + // + // CCI Crossed Over OS ... + if (detectCCICrossedOverOSPivot) + { + // + if (isCCIBullishVPattern) + { + // + XCAPivot iPivot; + + // + iPivot.to = cBar.time; + iPivot.from = p2Bar.time; + iPivot.value = pBar.low; + iPivot.type = XCA_CCI_COOS; + iPivot.symbol = cBar.symbol; + iPivot.period = cBar.period; + + // + Add( + cBar.low, + iPivot.values // + ); + Add( + pBar.low, + iPivot.values // + ); + Add( + p2Bar.low, + iPivot.values // + ); + Add( + cBar.close, + iPivot.values // + ); + Add( + pBar.close, + iPivot.values // + ); + Add( + p2Bar.close, + iPivot.values // + ); + + // + iPivot.reserve = GetMax(iPivot.values); + + // + AddPivot( + iPivot, + cciCrossedOverOSPivots, + maxAllowedPivots // + ); + + // + iPivot.Clean(); + } + } + + // + // CCI Crossed Under OS ... + if (detectCCICrossedUnderOBPivot) + { + // + if (isCCIBearishVPattern) + { + // + XCAPivot iPivot; + + // + iPivot.to = cBar.time; + iPivot.from = p2Bar.time; + iPivot.value = pBar.high; + iPivot.type = XCA_CCI_CUOB; + iPivot.symbol = cBar.symbol; + iPivot.period = cBar.period; + + // + Add( + cBar.high, + iPivot.values // + ); + Add( + pBar.high, + iPivot.values // + ); + Add( + p2Bar.high, + iPivot.values // + ); + Add( + cBar.close, + iPivot.values // + ); + Add( + pBar.close, + iPivot.values // + ); + Add( + p2Bar.close, + iPivot.values // + ); + + // + iPivot.reserve = GetMin(iPivot.values); + + // + AddPivot( + iPivot, + cciCrossedUnderOBPivots, + maxAllowedPivots // + ); + + // + iPivot.Clean(); + } + } + + // + start++; + + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + fvgBox.Clean(); + iConditions.Clean(); + } + + // + } + + // + void Validate( + XBoxZone &unAvailableBoxes[], + int barIndex = 0 // + ) + { + // + // Do All Pivots Validation ... + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + XCAPivot tmp[]; + bool has = false; + + // + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + + // + // Implement Validation Senarios ... + + // + // PEAKS ... + + // + has = HasPeakPivots(); + if (has) + { + // + Copy( + peakPivots, + tmp // + ); + Clean(peakPivots); + while (HasChild(tmp)) + { + // + XCAPivot iPivot = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + has = IsPivotBreaked( + iPivot, + unAvailableBoxes, + barIndex // + ); + if (!has) + { + // + AddRef( + iPivot, + peakPivots // + ); + } + } + Clean(tmp); + } + + // + // VALES ... + + // + has = HasValePivots(); + if (has) + { + // + Copy( + valePivots, + tmp // + ); + Clean(valePivots); + while (HasChild(tmp)) + { + // + XCAPivot iPivot = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + has = IsPivotBreaked( + iPivot, + unAvailableBoxes, + barIndex // + ); + if (!has) + { + // + AddRef( + iPivot, + valePivots // + ); + } + } + Clean(tmp); + } + + // + // PEAK SWH RES ... + + // + has = HasPeakSWHResPivots(); + if (has) + { + // + Copy( + peakSWHResPivots, + tmp // + ); + Clean(peakSWHResPivots); + while (HasChild(tmp)) + { + // + XCAPivot iPivot = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + has = IsPivotBreaked( + iPivot, + unAvailableBoxes, + barIndex // + ); + if (!has) + { + // + AddRef( + iPivot, + peakSWHResPivots // + ); + } + } + Clean(tmp); + } + + // + // VALE SWL SUP ... + + // + has = HasValeSWLSupPivots(); + if (has) + { + // + Copy( + valeSWLSupPivots, + tmp // + ); + Clean(valeSWLSupPivots); + while (HasChild(tmp)) + { + // + XCAPivot iPivot = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + has = IsPivotBreaked( + iPivot, + unAvailableBoxes, + barIndex // + ); + if (!has) + { + // + AddRef( + iPivot, + valeSWLSupPivots // + ); + } + } + Clean(tmp); + } + + // + // SWING HIGH ... + + // + has = HasSWHPivots(); + if (has) + { + // + Copy( + swhPivots, + tmp // + ); + Clean(swhPivots); + while (HasChild(tmp)) + { + // + XCAPivot iPivot = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + has = IsPivotBreaked( + iPivot, + unAvailableBoxes, + barIndex // + ); + if (!has) + { + // + AddRef( + iPivot, + swhPivots // + ); + } + } + Clean(tmp); + } + + // + // SWING LOW ... + + // + has = HasSWLPivots(); + if (has) + { + // + Copy( + swlPivots, + tmp // + ); + Clean(swlPivots); + while (HasChild(tmp)) + { + // + XCAPivot iPivot = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + has = IsPivotBreaked( + iPivot, + unAvailableBoxes, + barIndex // + ); + if (!has) + { + // + AddRef( + iPivot, + swlPivots // + ); + } + } + Clean(tmp); + } + + // + // KI ... + + // + has = HasKIBullishPivots(); + if (has) + { + // + Copy( + kiBullishPivots, + tmp // + ); + Clean(kiBullishPivots); + while (HasChild(tmp)) + { + // + XCAPivot iPivot = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + has = IsPivotBreaked( + iPivot, + unAvailableBoxes, + barIndex // + ); + if (!has) + { + // + AddRef( + iPivot, + kiBullishPivots // + ); + } + } + Clean(tmp); + } + + // + has = HasKIBearishPivots(); + if (has) + { + // + Copy( + kiBearishPivots, + tmp // + ); + Clean(kiBearishPivots); + while (HasChild(tmp)) + { + // + XCAPivot iPivot = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + has = IsPivotBreaked( + iPivot, + unAvailableBoxes, + barIndex // + ); + if (!has) + { + // + AddRef( + iPivot, + kiBearishPivots // + ); + } + } + Clean(tmp); + } + + // + // TKI ... + + // + has = HasTKIBullishPivots(); + if (has) + { + // + Copy( + tkiBullishPivots, + tmp // + ); + Clean(tkiBullishPivots); + while (HasChild(tmp)) + { + // + XCAPivot iPivot = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + has = IsPivotBreaked( + iPivot, + unAvailableBoxes, + barIndex // + ); + if (!has) + { + // + AddRef( + iPivot, + tkiBullishPivots // + ); + } + } + Clean(tmp); + } + + // + has = HasTKIBearishPivots(); + if (has) + { + // + Copy( + tkiBearishPivots, + tmp // + ); + Clean(tkiBearishPivots); + while (HasChild(tmp)) + { + // + XCAPivot iPivot = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + has = IsPivotBreaked( + iPivot, + unAvailableBoxes, + barIndex // + ); + if (!has) + { + // + AddRef( + iPivot, + tkiBearishPivots // + ); + } + } + Clean(tmp); + } + + // + // FVG ... + + // + has = HasFVGBullishPivots(); + if (has) + { + // + Copy( + fvgBullishPivots, + tmp // + ); + Clean(fvgBullishPivots); + while (HasChild(tmp)) + { + // + XCAPivot iPivot = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + has = IsPivotBreaked( + iPivot, + unAvailableBoxes, + barIndex // + ); + if (!has) + { + // + AddRef( + iPivot, + fvgBullishPivots // + ); + } + } + Clean(tmp); + } + + // + has = HasFVGBearishPivots(); + if (has) + { + // + Copy( + fvgBearishPivots, + tmp // + ); + Clean(fvgBearishPivots); + while (HasChild(tmp)) + { + // + XCAPivot iPivot = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + has = IsPivotBreaked( + iPivot, + unAvailableBoxes, + barIndex // + ); + if (!has) + { + // + AddRef( + iPivot, + fvgBearishPivots // + ); + } + } + Clean(tmp); + } + + // + // PVFVG ... + XCAPVPivot tmpPVFVG[]; + + // + has = HasPVFVGBullishPivots(); + if (has) + { + // + Copy( + pvFVGBullishPivots, + tmpPVFVG // + ); + Clean(pvFVGBullishPivots); + while (HasChild(tmpPVFVG)) + { + // + XCAPVPivot iPVFVG = tmpPVFVG[0]; + ArrayRemove( + tmpPVFVG, + 0, + 1 // + ); + + // + XCAPivot tmpFVGs[]; + Copy( + iPVFVG.pivots, + tmpFVGs // + ); + Clean(iPVFVG.pivots); + while (HasChild(tmpFVGs)) + { + // + XCAPivot iPivot = tmpFVGs[0]; + ArrayRemove( + tmpFVGs, + 0, + 1 // + ); + + // + has = IsPivotBreaked( + iPivot, + unAvailableBoxes, + barIndex // + ); + if (!has) + { + // + AddRef( + iPivot, + iPVFVG.pivots // + ); + } + } + Clean(tmpFVGs); + + // + if (HasChild(iPVFVG.pivots)) + { + // + AddRef( + iPVFVG, + pvFVGBullishPivots // + ); + } + } + Clean(tmp); + Clean(tmpPVFVG); + } + + // + has = HasPVFVGBearishPivots(); + if (has) + { + // + Copy( + pvFVGBearishPivots, + tmpPVFVG // + ); + Clean(pvFVGBearishPivots); + while (HasChild(tmpPVFVG)) + { + // + XCAPVPivot iPVFVG = tmpPVFVG[0]; + ArrayRemove( + tmpPVFVG, + 0, + 1 // + ); + + // + XCAPivot tmpFVGs[]; + Copy( + iPVFVG.pivots, + tmpFVGs // + ); + Clean(iPVFVG.pivots); + while (HasChild(tmpFVGs)) + { + // + XCAPivot iPivot = tmpFVGs[0]; + ArrayRemove( + tmpFVGs, + 0, + 1 // + ); + + // + has = IsPivotBreaked( + iPivot, + unAvailableBoxes, + barIndex // + ); + if (!has) + { + // + AddRef( + iPivot, + iPVFVG.pivots // + ); + } + } + Clean(tmpFVGs); + + // + if (HasChild(iPVFVG.pivots)) + { + // + AddRef( + iPVFVG, + pvFVGBearishPivots // + ); + } + } + Clean(tmp); + Clean(tmpPVFVG); + } + + // + // TREND ... + + // + has = HasTrendBullishPivots(); + if (has) + { + // + Copy( + trendBullishPivots, + tmp // + ); + Clean(trendBullishPivots); + while (HasChild(tmp)) + { + // + XCAPivot iPivot = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + has = IsPivotBreaked( + iPivot, + unAvailableBoxes, + barIndex // + ); + if (!has) + { + // + AddRef( + iPivot, + trendBullishPivots // + ); + } + } + Clean(tmp); + } + + // + has = HasTrendBearishPivots(); + if (has) + { + // + Copy( + trendBearishPivots, + tmp // + ); + Clean(trendBearishPivots); + while (HasChild(tmp)) + { + // + XCAPivot iPivot = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + has = IsPivotBreaked( + iPivot, + unAvailableBoxes, + barIndex // + ); + if (!has) + { + // + AddRef( + iPivot, + trendBearishPivots // + ); + } + } + Clean(tmp); + } + + // + // TKITRND ... + + // + has = HasTKITRNDBullishPivots(); + if (has) + { + // + Copy( + tkitrndBullishPivots, + tmp // + ); + Clean(tkitrndBullishPivots); + while (HasChild(tmp)) + { + // + XCAPivot iPivot = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + has = IsPivotBreaked( + iPivot, + unAvailableBoxes, + barIndex // + ); + if (!has) + { + // + AddRef( + iPivot, + tkitrndBullishPivots // + ); + } + } + Clean(tmp); + } + + // + has = HasTKITRNDBearishPivots(); + if (has) + { + // + Copy( + tkitrndBearishPivots, + tmp // + ); + Clean(tkitrndBearishPivots); + while (HasChild(tmp)) + { + // + XCAPivot iPivot = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + has = IsPivotBreaked( + iPivot, + unAvailableBoxes, + barIndex // + ); + if (!has) + { + // + AddRef( + iPivot, + tkitrndBearishPivots // + ); + } + } + Clean(tmp); + } + + // + // SAME CYCLES HH / LL ... + + // + has = HasSSameLLPivots(); + if (has) + { + // + Copy( + sSameLLPivots, + tmp // + ); + Clean(sSameLLPivots); + while (HasChild(tmp)) + { + // + XCAPivot iPivot = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + has = IsPivotBreaked( + iPivot, + unAvailableBoxes, + barIndex // + ); + if (!has) + { + // + AddRef( + iPivot, + sSameLLPivots // + ); + } + } + Clean(tmp); + } + + // + has = HasSSameHHPivots(); + if (has) + { + // + Copy( + sSameHHPivots, + tmp // + ); + Clean(sSameHHPivots); + while (HasChild(tmp)) + { + // + XCAPivot iPivot = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + has = IsPivotBreaked( + iPivot, + unAvailableBoxes, + barIndex // + ); + if (!has) + { + // + AddRef( + iPivot, + sSameHHPivots // + ); + } + } + Clean(tmp); + } + + // + has = HasMSameLLPivots(); + if (has) + { + // + Copy( + mSameLLPivots, + tmp // + ); + Clean(mSameLLPivots); + while (HasChild(tmp)) + { + // + XCAPivot iPivot = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + has = IsPivotBreaked( + iPivot, + unAvailableBoxes, + barIndex // + ); + if (!has) + { + // + AddRef( + iPivot, + mSameLLPivots // + ); + } + } + Clean(tmp); + } + + // + has = HasMSameHHPivots(); + if (has) + { + // + Copy( + mSameHHPivots, + tmp // + ); + Clean(mSameHHPivots); + while (HasChild(tmp)) + { + // + XCAPivot iPivot = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + has = IsPivotBreaked( + iPivot, + unAvailableBoxes, + barIndex // + ); + if (!has) + { + // + AddRef( + iPivot, + mSameHHPivots // + ); + } + } + Clean(tmp); + } + + // + has = HasLSameLLPivots(); + if (has) + { + // + Copy( + lSameLLPivots, + tmp // + ); + Clean(lSameLLPivots); + while (HasChild(tmp)) + { + // + XCAPivot iPivot = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + has = IsPivotBreaked( + iPivot, + unAvailableBoxes, + barIndex // + ); + if (!has) + { + // + AddRef( + iPivot, + lSameLLPivots // + ); + } + } + Clean(tmp); + } + + // + has = HasLSameHHPivots(); + if (has) + { + // + Copy( + lSameHHPivots, + tmp // + ); + Clean(lSameHHPivots); + while (HasChild(tmp)) + { + // + XCAPivot iPivot = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + has = IsPivotBreaked( + iPivot, + unAvailableBoxes, + barIndex // + ); + if (!has) + { + // + AddRef( + iPivot, + lSameHHPivots // + ); + } + } + Clean(tmp); + } + + // + has = HasHSameLLPivots(); + if (has) + { + // + Copy( + hSameLLPivots, + tmp // + ); + Clean(hSameLLPivots); + while (HasChild(tmp)) + { + // + XCAPivot iPivot = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + has = IsPivotBreaked( + iPivot, + unAvailableBoxes, + barIndex // + ); + if (!has) + { + // + AddRef( + iPivot, + hSameLLPivots // + ); + } + } + Clean(tmp); + } + + // + has = HasHSameHHPivots(); + if (has) + { + // + Copy( + hSameHHPivots, + tmp // + ); + Clean(hSameHHPivots); + while (HasChild(tmp)) + { + // + XCAPivot iPivot = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + has = IsPivotBreaked( + iPivot, + unAvailableBoxes, + barIndex // + ); + if (!has) + { + // + AddRef( + iPivot, + hSameHHPivots // + ); + } + } + Clean(tmp); + } + + // + // OSCS ... + + // + // RSI ... + + // + has = HasRSIPeakPivots(); + if (has) + { + // + Copy( + rsiPeakPivots, + tmp // + ); + Clean(rsiPeakPivots); + while (HasChild(tmp)) + { + // + XCAPivot iPivot = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + has = IsPivotBreaked( + iPivot, + unAvailableBoxes, + barIndex // + ); + if (!has) + { + // + AddRef( + iPivot, + rsiPeakPivots // + ); + } + } + Clean(tmp); + } + + // + has = HasRSIValePivots(); + if (has) + { + // + Copy( + rsiValePivots, + tmp // + ); + Clean(rsiValePivots); + while (HasChild(tmp)) + { + // + XCAPivot iPivot = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + has = IsPivotBreaked( + iPivot, + unAvailableBoxes, + barIndex // + ); + if (!has) + { + // + AddRef( + iPivot, + rsiValePivots // + ); + } + } + Clean(tmp); + } + + // + has = HasRSICrossedOverOSPivots(); + if (has) + { + // + Copy( + rsiCrossedOverOSPivots, + tmp // + ); + Clean(rsiCrossedOverOSPivots); + while (HasChild(tmp)) + { + // + XCAPivot iPivot = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + has = IsPivotBreaked( + iPivot, + unAvailableBoxes, + barIndex // + ); + if (!has) + { + // + AddRef( + iPivot, + rsiCrossedOverOSPivots // + ); + } + } + Clean(tmp); + } + + // + has = HasRSICrossedUnderOBPivots(); + if (has) + { + // + Copy( + rsiCrossedUnderOBPivots, + tmp // + ); + Clean(rsiCrossedUnderOBPivots); + while (HasChild(tmp)) + { + // + XCAPivot iPivot = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + has = IsPivotBreaked( + iPivot, + unAvailableBoxes, + barIndex // + ); + if (!has) + { + // + AddRef( + iPivot, + rsiCrossedUnderOBPivots // + ); + } + } + Clean(tmp); + } + + // + // CCI ... + + // + has = HasCCIPeakPivots(); + if (has) + { + // + Copy( + cciPeakPivots, + tmp // + ); + Clean(cciPeakPivots); + while (HasChild(tmp)) + { + // + XCAPivot iPivot = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + has = IsPivotBreaked( + iPivot, + unAvailableBoxes, + barIndex // + ); + if (!has) + { + // + AddRef( + iPivot, + cciPeakPivots // + ); + } + } + Clean(tmp); + } + + // + has = HasCCIValePivots(); + if (has) + { + // + Copy( + cciValePivots, + tmp // + ); + Clean(cciValePivots); + while (HasChild(tmp)) + { + // + XCAPivot iPivot = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + has = IsPivotBreaked( + iPivot, + unAvailableBoxes, + barIndex // + ); + if (!has) + { + // + AddRef( + iPivot, + cciValePivots // + ); + } + } + Clean(tmp); + } + + // + has = HasCCICrossedOverOSPivots(); + if (has) + { + // + Copy( + cciCrossedOverOSPivots, + tmp // + ); + Clean(cciCrossedOverOSPivots); + while (HasChild(tmp)) + { + // + XCAPivot iPivot = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + has = IsPivotBreaked( + iPivot, + unAvailableBoxes, + barIndex // + ); + if (!has) + { + // + AddRef( + iPivot, + cciCrossedOverOSPivots // + ); + } + } + Clean(tmp); + } + + // + has = HasCCICrossedUnderOBPivots(); + if (has) + { + // + Copy( + cciCrossedUnderOBPivots, + tmp // + ); + Clean(cciCrossedUnderOBPivots); + while (HasChild(tmp)) + { + // + XCAPivot iPivot = tmp[0]; + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + has = IsPivotBreaked( + iPivot, + unAvailableBoxes, + barIndex // + ); + if (!has) + { + // + AddRef( + iPivot, + cciCrossedUnderOBPivots // + ); + } + } + Clean(tmp); + } + + // + // PVTICKS ... + + // + XCAPVTick tmpTicks[]; + + // + has = HasPeakTicks(); + if (has) + { + // + Copy( + peakTicks, + tmpTicks // + ); + Clean(peakTicks); + while (HasChild(tmpTicks)) + { + // + XCAPVTick iPVTick = tmpTicks[0]; + ArrayRemove( + tmpTicks, + 0, + 1 // + ); + + // + XBoxZone iBox; + bool isBoxBreaked = false; + has = iPVTick.GetMaxVolumeBox(iBox); + if (has) + { + // + isBoxBreaked = IsBoxBreaked( + iBox, + unAvailableBoxes, + barIndex // + ); + } + + // + has = IsPivotBreaked( + iPVTick.pivot, + unAvailableBoxes, + barIndex // + ); + if (!has && !isBoxBreaked) + { + // + AddRef( + iPVTick, + peakTicks // + ); + } + } + Clean(tmpTicks); + } + + // + has = HasValeTicks(); + if (has) + { + // + Copy( + valeTicks, + tmpTicks // + ); + Clean(valeTicks); + while (HasChild(tmpTicks)) + { + // + XCAPVTick iPVTick = tmpTicks[0]; + ArrayRemove( + tmpTicks, + 0, + 1 // + ); + + // + XBoxZone iBox; + bool isBoxBreaked = false; + has = iPVTick.GetMaxVolumeBox(iBox); + if (has) + { + // + isBoxBreaked = IsBoxBreaked( + iBox, + unAvailableBoxes, + barIndex // + ); + } + + // + has = IsPivotBreaked( + iPVTick.pivot, + unAvailableBoxes, + barIndex // + ); + if (!has && !isBoxBreaked) + { + // + AddRef( + iPVTick, + valeTicks // + ); + } + } + Clean(tmpTicks); + } + + // + Clean(tmp); + Clean(tmpPVFVG); + Clean(tmpTicks); + } + + // + int FillBullishBoxes( + XBoxZone &boxes[] // + ) + { + // + int result = 0; + + // + int count = 0; + bool has = false; + + // + Clean(boxes); + + // + has = HasSWLPivots(); + if (has) + { + // + count = CountSWLPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = swlPivots[i].AsBox(iBox); + if (has) + { + // + AddRef( + iBox, + boxes // + ); + } + + // + iBox.Clean(); + } + } + + // + has = HasValePivots(); + if (has) + { + // + count = CountValePivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = valePivots[i].AsBox(iBox); + if (has) + { + // + AddRef( + iBox, + boxes // + ); + } + + // + iBox.Clean(); + } + } + + // + has = HasSSameLLPivots(); + if (has) + { + // + count = CountSSameLLPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = sSameLLPivots[i].AsBox(iBox); + if (has) + { + // + AddRef( + iBox, + boxes // + ); + } + + // + iBox.Clean(); + } + } + + // + has = HasMSameLLPivots(); + if (has) + { + // + count = CountMSameLLPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = mSameLLPivots[i].AsBox(iBox); + if (has) + { + // + AddRef( + iBox, + boxes // + ); + } + + // + iBox.Clean(); + } + } + + // + has = HasLSameLLPivots(); + if (has) + { + // + count = CountLSameLLPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = lSameLLPivots[i].AsBox(iBox); + if (has) + { + // + AddRef( + iBox, + boxes // + ); + } + + // + iBox.Clean(); + } + } + + // + has = HasHSameLLPivots(); + if (has) + { + // + count = CountHSameLLPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = hSameLLPivots[i].AsBox(iBox); + if (has) + { + // + AddRef( + iBox, + boxes // + ); + } + + // + iBox.Clean(); + } + } + + // + has = HasKIBullishPivots(); + if (has) + { + // + count = CountKIBullishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = kiBullishPivots[i].AsBox(iBox); + if (has) + { + // + AddRef( + iBox, + boxes // + ); + } + + // + iBox.Clean(); + } + } + + // + has = HasFVGBullishPivots(); + if (has) + { + // + count = CountFVGBullishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = fvgBullishPivots[i].AsBox(iBox); + if (has) + { + // + AddRef( + iBox, + boxes // + ); + } + + // + iBox.Clean(); + } + } + + // + has = HasValeSWLSupPivots(); + if (has) + { + // + count = CountValeSWLSupPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = valeSWLSupPivots[i].AsBox(iBox); + if (has) + { + // + AddRef( + iBox, + boxes // + ); + } + + // + iBox.Clean(); + } + } + + // + has = HasTKIBullishPivots(); + if (has) + { + // + count = CountTKIBullishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = tkiBullishPivots[i].AsBox(iBox); + if (has) + { + // + AddRef( + iBox, + boxes // + ); + } + + // + iBox.Clean(); + } + } + + // + has = HasTrendBullishPivots(); + if (has) + { + // + count = CountTrendBullishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = trendBullishPivots[i].AsBox(iBox); + if (has) + { + // + AddRef( + iBox, + boxes // + ); + } + + // + iBox.Clean(); + } + } + + // + has = HasTKITRNDBullishPivots(); + if (has) + { + // + count = CountTKITRNDBullishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = tkitrndBullishPivots[i].AsBox(iBox); + if (has) + { + // + AddRef( + iBox, + boxes // + ); + } + + // + iBox.Clean(); + } + } + + // + has = HasRSIValePivots(); + if (has) + { + // + count = CountRSIValePivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = rsiValePivots[i].AsBox(iBox); + if (has) + { + // + AddRef( + iBox, + boxes // + ); + } + + // + iBox.Clean(); + } + } + + // + has = HasRSICrossedOverOSPivots(); + if (has) + { + // + count = CountRSICrossedOverOSPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = rsiCrossedOverOSPivots[i].AsBox(iBox); + if (has) + { + // + AddRef( + iBox, + boxes // + ); + } + + // + iBox.Clean(); + } + } + + // + has = HasCCIValePivots(); + if (has) + { + // + count = CountCCIValePivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = cciValePivots[i].AsBox(iBox); + if (has) + { + // + AddRef( + iBox, + boxes // + ); + } + + // + iBox.Clean(); + } + } + + // + has = HasCCICrossedOverOSPivots(); + if (has) + { + // + count = CountCCICrossedOverOSPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = cciCrossedOverOSPivots[i].AsBox(iBox); + if (has) + { + // + AddRef( + iBox, + boxes // + ); + } + + // + iBox.Clean(); + } + } + + // + result = ArraySize(boxes); + + // + return result; + } + + // + int FillBearishBoxes( + XBoxZone &boxes[] // + ) + { + // + int result = 0; + + // + int count = 0; + bool has = false; + + // + Clean(boxes); + + // + has = HasSWHPivots(); + if (has) + { + // + count = CountSWHPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = swhPivots[i].AsBox(iBox); + if (has) + { + // + AddRef( + iBox, + boxes // + ); + } + + // + iBox.Clean(); + } + } + + // + has = HasPeakPivots(); + if (has) + { + // + count = CountPeakPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = peakPivots[i].AsBox(iBox); + if (has) + { + // + AddRef( + iBox, + boxes // + ); + } + + // + iBox.Clean(); + } + } + + // + has = HasSSameHHPivots(); + if (has) + { + // + count = CountSSameHHPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = sSameHHPivots[i].AsBox(iBox); + if (has) + { + // + AddRef( + iBox, + boxes // + ); + } + + // + iBox.Clean(); + } + } + + // + has = HasMSameHHPivots(); + if (has) + { + // + count = CountMSameHHPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = mSameHHPivots[i].AsBox(iBox); + if (has) + { + // + AddRef( + iBox, + boxes // + ); + } + + // + iBox.Clean(); + } + } + + // + has = HasLSameHHPivots(); + if (has) + { + // + count = CountLSameHHPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = lSameHHPivots[i].AsBox(iBox); + if (has) + { + // + AddRef( + iBox, + boxes // + ); + } + + // + iBox.Clean(); + } + } + + // + has = HasHSameHHPivots(); + if (has) + { + // + count = CountHSameHHPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = hSameHHPivots[i].AsBox(iBox); + if (has) + { + // + AddRef( + iBox, + boxes // + ); + } + + // + iBox.Clean(); + } + } + + // + has = HasKIBearishPivots(); + if (has) + { + // + count = CountKIBearishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = kiBearishPivots[i].AsBox(iBox); + if (has) + { + // + AddRef( + iBox, + boxes // + ); + } + + // + iBox.Clean(); + } + } + + // + has = HasFVGBearishPivots(); + if (has) + { + // + count = CountFVGBearishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = fvgBearishPivots[i].AsBox(iBox); + if (has) + { + // + AddRef( + iBox, + boxes // + ); + } + + // + iBox.Clean(); + } + } + + // + has = HasPeakSWHResPivots(); + if (has) + { + // + count = CountPeakSWHResPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = peakSWHResPivots[i].AsBox(iBox); + if (has) + { + // + AddRef( + iBox, + boxes // + ); + } + + // + iBox.Clean(); + } + } + + // + has = HasTKIBearishPivots(); + if (has) + { + // + count = CountTKIBearishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = tkiBearishPivots[i].AsBox(iBox); + if (has) + { + // + AddRef( + iBox, + boxes // + ); + } + + // + iBox.Clean(); + } + } + + // + has = HasTrendBearishPivots(); + if (has) + { + // + count = CountTrendBearishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = trendBearishPivots[i].AsBox(iBox); + if (has) + { + // + AddRef( + iBox, + boxes // + ); + } + + // + iBox.Clean(); + } + } + + // + has = HasTKITRNDBearishPivots(); + if (has) + { + // + count = CountTKITRNDBearishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = tkitrndBearishPivots[i].AsBox(iBox); + if (has) + { + // + AddRef( + iBox, + boxes // + ); + } + + // + iBox.Clean(); + } + } + + // + has = HasRSIPeakPivots(); + if (has) + { + // + count = CountRSIPeakPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = rsiPeakPivots[i].AsBox(iBox); + if (has) + { + // + AddRef( + iBox, + boxes // + ); + } + + // + iBox.Clean(); + } + } + + // + has = HasRSICrossedUnderOBPivots(); + if (has) + { + // + count = CountRSICrossedUnderOBPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = rsiCrossedUnderOBPivots[i].AsBox(iBox); + if (has) + { + // + AddRef( + iBox, + boxes // + ); + } + + // + iBox.Clean(); + } + } + + // + has = HasCCIPeakPivots(); + if (has) + { + // + count = CountCCIPeakPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = cciPeakPivots[i].AsBox(iBox); + if (has) + { + // + AddRef( + iBox, + boxes // + ); + } + + // + iBox.Clean(); + } + } + + // + has = HasCCICrossedUnderOBPivots(); + if (has) + { + // + count = CountCCICrossedUnderOBPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = cciCrossedUnderOBPivots[i].AsBox(iBox); + if (has) + { + // + AddRef( + iBox, + boxes // + ); + } + + // + iBox.Clean(); + } + } + + // + result = ArraySize(boxes); + + // + return result; + } + + // + // POI Handlers ... + + // + // PEAK ... + + // + bool HasPeakPivots() + { + return HasChild(peakPivots); + } + + // + int CountPeakPivots() + { + return ArraySize(peakPivots); + } + + // + // VALE ... + + // + bool HasValePivots() + { + return HasChild(valePivots); + } + + // + int CountValePivots() + { + return ArraySize(valePivots); + } + + // + // PEAK SWH Res ... + + // + bool HasPeakSWHResPivots() + { + return HasChild(peakSWHResPivots); + } + + // + int CountPeakSWHResPivots() + { + return ArraySize(peakSWHResPivots); + } + + // + // VALE SWL Sup ... + + // + bool HasValeSWLSupPivots() + { + return HasChild(valeSWLSupPivots); + } + + // + int CountValeSWLSupPivots() + { + return ArraySize(valeSWLSupPivots); + } + + // + // SWING High ... + + // + bool HasSWHPivots() + { + return HasChild(swhPivots); + } + + // + int CountSWHPivots() + { + return ArraySize(swhPivots); + } + + // + // SWING Low ... + + // + bool HasSWLPivots() + { + return HasChild(swlPivots); + } + + // + int CountSWLPivots() + { + return ArraySize(swlPivots); + } + + // + // KI ... + + // + bool HasKIBullishPivots() + { + return HasChild(kiBullishPivots); + } + + // + int CountKIBullishPivots() + { + return ArraySize(kiBullishPivots); + } + + // + bool HasKIBearishPivots() + { + return HasChild(kiBearishPivots); + } + + // + int CountKIBearishPivots() + { + return ArraySize(kiBearishPivots); + } + + // + // TKI ... + + // + bool HasTKIBullishPivots() + { + return HasChild(tkiBullishPivots); + } + + // + int CountTKIBullishPivots() + { + return ArraySize(tkiBullishPivots); + } + + // + bool HasTKIBearishPivots() + { + return HasChild(tkiBearishPivots); + } + + // + int CountTKIBearishPivots() + { + return ArraySize(tkiBearishPivots); + } + + // + // FVG ... + + // + bool HasFVGBullishPivots() + { + return HasChild(fvgBullishPivots); + } + + // + int CountFVGBullishPivots() + { + return ArraySize(fvgBullishPivots); + } + + // + bool HasFVGBearishPivots() + { + return HasChild(fvgBearishPivots); + } + + // + int CountFVGBearishPivots() + { + return ArraySize(fvgBearishPivots); + } + + // + // PVFVG ... + + // + bool HasPVFVGBullishPivots() + { + return HasChild(pvFVGBullishPivots); + } + + // + int CountPVFVGBullishPivots() + { + return ArraySize(pvFVGBullishPivots); + } + + // + bool HasPVFVGBearishPivots() + { + return HasChild(pvFVGBearishPivots); + } + + // + int CountPVFVGBearishPivots() + { + return ArraySize(pvFVGBearishPivots); + } + + // + // TREND ... + + // + bool HasTrendBullishPivots() + { + return HasChild(trendBullishPivots); + } + + // + int CountTrendBullishPivots() + { + return ArraySize(trendBullishPivots); + } + + // + bool HasTrendBearishPivots() + { + return HasChild(trendBearishPivots); + } + + // + int CountTrendBearishPivots() + { + return ArraySize(trendBearishPivots); + } + + // + // TKITRND ... + + // + bool HasTKITRNDBullishPivots() + { + return HasChild(tkitrndBullishPivots); + } + + // + int CountTKITRNDBullishPivots() + { + return ArraySize(tkitrndBullishPivots); + } + + // + bool HasTKITRNDBearishPivots() + { + return HasChild(tkitrndBearishPivots); + } + + // + int CountTKITRNDBearishPivots() + { + return ArraySize(tkitrndBearishPivots); + } + + // + // SAME CYCLES HH / LL ... + + // + bool HasSSameLLPivots() + { + return HasChild(sSameLLPivots); + } + + // + int CountSSameLLPivots() + { + return ArraySize(sSameLLPivots); + } + + // + bool HasMSameLLPivots() + { + return HasChild(mSameLLPivots); + } + + // + int CountMSameLLPivots() + { + return ArraySize(mSameLLPivots); + } + + // + bool HasLSameLLPivots() + { + return HasChild(lSameLLPivots); + } + + // + int CountLSameLLPivots() + { + return ArraySize(lSameLLPivots); + } + + // + bool HasHSameLLPivots() + { + return HasChild(hSameLLPivots); + } + + // + int CountHSameLLPivots() + { + return ArraySize(hSameLLPivots); + } + + // + bool HasSSameHHPivots() + { + return HasChild(sSameHHPivots); + } + + // + int CountSSameHHPivots() + { + return ArraySize(sSameHHPivots); + } + + // + bool HasMSameHHPivots() + { + return HasChild(mSameHHPivots); + } + + // + int CountMSameHHPivots() + { + return ArraySize(mSameHHPivots); + } + + // + bool HasLSameHHPivots() + { + return HasChild(lSameHHPivots); + } + + // + int CountLSameHHPivots() + { + return ArraySize(lSameHHPivots); + } + + // + bool HasHSameHHPivots() + { + return HasChild(hSameHHPivots); + } + + // + int CountHSameHHPivots() + { + return ArraySize(hSameHHPivots); + } + + // + // OSCS ... + + // + // RSI ... + + // + bool HasRSIPeakPivots() + { + return HasChild(rsiPeakPivots); + } + + // + int CountRSIPeakPivots() + { + return ArraySize(rsiPeakPivots); + } + + // + bool HasRSIValePivots() + { + return HasChild(rsiValePivots); + } + + // + int CountRSIValePivots() + { + return ArraySize(rsiValePivots); + } + + // + bool HasRSICrossedOverOSPivots() + { + return HasChild(rsiCrossedOverOSPivots); + } + + // + int CountRSICrossedOverOSPivots() + { + return ArraySize(rsiCrossedOverOSPivots); + } + + // + bool HasRSICrossedUnderOBPivots() + { + return HasChild(rsiCrossedUnderOBPivots); + } + + // + int CountRSICrossedUnderOBPivots() + { + return ArraySize(rsiCrossedUnderOBPivots); + } + + // + // CCI ... + + // + bool HasCCIPeakPivots() + { + return HasChild(cciPeakPivots); + } + + // + int CountCCIPeakPivots() + { + return ArraySize(cciPeakPivots); + } + + // + bool HasCCIValePivots() + { + return HasChild(cciValePivots); + } + + // + int CountCCIValePivots() + { + return ArraySize(cciValePivots); + } + + // + bool HasCCICrossedOverOSPivots() + { + return HasChild(cciCrossedOverOSPivots); + } + + // + int CountCCICrossedOverOSPivots() + { + return ArraySize(cciCrossedOverOSPivots); + } + + // + bool HasCCICrossedUnderOBPivots() + { + return HasChild(cciCrossedUnderOBPivots); + } + + // + int CountCCICrossedUnderOBPivots() + { + return ArraySize(cciCrossedUnderOBPivots); + } + + // + // PVTICKS ... + + // + bool HasPeakTicks() + { + return HasChild(peakTicks); + } + + // + int CountPeakTicks() + { + return ArraySize(peakTicks); + } + + // + bool HasValeTicks() + { + return HasChild(valeTicks); + } + + // + int CountValeTicks() + { + return ArraySize(valeTicks); + } + + // + // Protected ... + protected: + // + // Props ... + + // + // Prrivate ... + private: + // + // Props ... + + // + XCPOIDrawer *drawer; + XCXCAEAHelper *helper; + XCBarAnalyser *barAnalyser; + + // + bool CheckPivotCommons( + XCAPivot &pivot, + XBoxZone &box, + XBoxZone &unAvailableBoxes[], + int barIndex = 0 // + ) + { + // + bool result = false; + + // + box.Clean(); + + // + barIndex = NormalizeInt(barIndex, 0); + + // + result = pivot.IsValid(); + if (!result) + { + return result; + } + + // + int pivotToIDX = pivot.ToIndex(); + + // + result = pivotToIDX > barIndex; + if (!result) + { + return result; + } + + // + result = pivot.AsBox(box); + if (!result) + { + // + box.Clean(); + return result; + } + + // + return result; + } + + // + bool CheckPivotIsAvailable( + XBoxZone &pivotBox, + XBoxZone &unAvailableBoxes[] // + ) + { + // + bool result = false; + + // + result = pivotBox.IsValid(); + if (!result) + { + return result; + } + + // + int idx = -1; + bool isExists = FindBoxIndex( + idx, + pivotBox, + unAvailableBoxes // + ); + result = !isExists; + + // + return result; + } + + // + bool IsPivotBreaked( + XCAPivot &pivot, + XBoxZone &unAvailableBoxes[], + int barIndex = 0 // + ) + { + // + bool result = false; + + // + XBoxZone iBox; + result = CheckPivotCommons( + pivot, + iBox, + unAvailableBoxes, + barIndex // + ); + if (!result) + { + // + iBox.Clean(); + return result; + } + + // + // Check Box is Available Or Not ... + bool isAvailable = CheckPivotIsAvailable( + iBox, + unAvailableBoxes // + ); + if (!isAvailable) + { + // + iBox.Clean(); + + // + // Assume UnAvailable Boes as Breaked ... + result = true; + return result; + } + + // + bool isBullish = iBox.IsBullish(); + double boundary = + isBullish + ? iBox.lower + : iBox.upper; + + // + int toIDX = iBox.ToIndex(); + + // + // for validating Box Break we have to wait At Least 3 Bars Close + // out of Box Boundary ... + int barsLength = 3; + + // + int startCheckBreaktionBarIndex = toIDX - barsLength; + result = startCheckBreaktionBarIndex > 0 && + barIndex < startCheckBreaktionBarIndex; + if (!result) + { + // + iBox.Clean(); + return result; + } + + // + XOHCL cBar; + XOHCL pBar; + XOHCL p2Bar; + for (int i = barIndex; i < startCheckBreaktionBarIndex; i++) + { + // + result = cBar.Init( + iBox.symbol, + iBox.period, + i + 1 // + ); + result = + result && + cBar.GetPreviousBar(pBar); + result = + result && + pBar.GetPreviousBar(p2Bar); + if (!result) + { + // + iBox.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + + // + break; + } + + // + bool isBullishBreaked = + isBullish && + cBar.close < boundary && + pBar.close < boundary && + p2Bar.close < boundary; + + // + bool isBearishBreaked = + !isBullish && + cBar.close > boundary && + pBar.close > boundary && + p2Bar.close > boundary; + + // + result = isBullishBreaked || + isBearishBreaked; + if (result) + { + break; + } + + // + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + } + + // + iBox.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + // + bool IsBoxBreaked( + XBoxZone &box, + XBoxZone &unAvailableBoxes[], + int barIndex = 0 // + ) + { + // + bool result = false; + + // + barIndex = NormalizeInt(barIndex, 0); + + // + result = box.IsValid(); + if (!result) + { + // + // Assume Invalid Boxes as Broken ... + return true; + } + + // + int idx = -1; + result = FindBoxIndex( + idx, + box, + unAvailableBoxes // + ); + if (result) + { + // + // Assume UnAvailable Boxes as Broken ... + return result; + } + + // + int toIDX = box.ToIndex(); + result = toIDX > barIndex; + if (!result) + { + return result; + } + + // + 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; + + // + int startCheckBreaktionBarIndex = toIDX - barsLength; + result = startCheckBreaktionBarIndex > 0 && + barIndex < startCheckBreaktionBarIndex; + if (!result) + { + return result; + } + + // + XOHCL cBar; + XOHCL pBar; + XOHCL p2Bar; + for (int i = barIndex; i < startCheckBreaktionBarIndex; i++) + { + // + result = cBar.Init( + box.symbol, + box.period, + i + 1 // + ); + result = + result && + cBar.GetPreviousBar(pBar); + result = + result && + pBar.GetPreviousBar(p2Bar); + if (!result) + { + // + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + + // + break; + } + + // + bool isBullishBreaked = + isBullish && + cBar.close < boundary && + pBar.close < boundary && + p2Bar.close < boundary; + + // + bool isBearishBreaked = + !isBullish && + cBar.close > boundary && + pBar.close > boundary && + p2Bar.close > boundary; + + // + result = isBullishBreaked || + isBearishBreaked; + if (result) + { + break; + } + + // + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + } + + // + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + + // + return result; + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14040218 XCAEA/Documents/BKP/xcaea.x-poi.drawer.class.bkp.mq5 b/BKPS/14040218 XCAEA/Documents/BKP/xcaea.x-poi.drawer.class.bkp.mq5 new file mode 100644 index 0000000..f0f59a7 --- /dev/null +++ b/BKPS/14040218 XCAEA/Documents/BKP/xcaea.x-poi.drawer.class.bkp.mq5 @@ -0,0 +1,2329 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XCXCAEAPOIDrawer ... +// Description: Class for XCAEA POI Drawer ... +// +// +// 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 XCAEA POI Drawer" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../Classes/xcaea.x-poi.detector.class.mq5" + +// +// Definitions ... + +// +// Implementations ... +class XCXCAEAPOIDrawer : public XCBase +{ + // + // Public ... + public: + // + // Props ... + + // + bool ignoreUpdateOSCTos; + bool drawTrendPivotsOnlySelectedFVG; + + // + // Drawers ... + bool drawTrendLine; + bool drawTickPivots; + bool drawVolumePivots; + bool drawRSIPeakPivots; + bool drawRSIValePivots; + bool drawCCIPeakPivots; + bool drawCCIValePivots; + bool drawFVGBullishPivots; + bool drawFVGBearishPivots; + bool drawValeSupSWLPivots; + bool drawPeakResSWHPivots; + bool drawTrendBullishPivots; + bool drawTrendBearishPivots; + bool drawRSICrossedOverOSPivots; + bool drawRSICrossedUnderOBPivots; + bool drawCCICrossedOverOSPivots; + bool drawCCICrossedUnderOBPivots; + + // + // Colors ... + + // + color defaultBullishColor; + color defaultBearishColor; + + // + color tickPivotsColor; + color volumePivotsColor; + color rsiPeakPivotsColor; + color rsiValePivotsColor; + color cciPeakPivotsColor; + color cciValePivotsColor; + color fvgBullishPivotsColor; + color fvgBearishPivotsColor; + color valeSupSWLPivotsColor; + color peakResSWHPivotsColor; + color trendLineBullishColor; + color trendLineBearishColor; + color trendBullishPivotsColor; + color trendBearishPivotsColor; + color rsiCrossedOverOSPivotsColor; + color rsiCrossedUnderOBPivotsColor; + color cciCrossedOverOSPivotsColor; + color cciCrossedUnderOBPivotsColor; + + // + // Width ... + + // + int defaultBullishWidth; + int defaultBearishWidth; + + // + int tickPivotsWidth; + int volumePivotsWidth; + int rsiPeakPivotsWidth; + int rsiValePivotsWidth; + int cciPeakPivotsWidth; + int cciValePivotsWidth; + int fvgBullishPivotsWidth; + int fvgBearishPivotsWidth; + int valeSupSWLPivotsWidth; + int peakResSWHPivotsWidth; + int trendLineBullishWidth; + int trendLineBearishWidth; + int trendBullishPivotsWidth; + int trendBearishPivotsWidth; + int rsiCrossedOverOSPivotsWidth; + int rsiCrossedUnderOBPivotsWidth; + int cciCrossedOverOSPivotsWidth; + int cciCrossedUnderOBPivotsWidth; + + // + // Style ... + + // + ENUM_LINE_STYLE defaultBullishStyle; + ENUM_LINE_STYLE defaultBearishStyle; + + // + ENUM_LINE_STYLE tickPivotsStyle; + ENUM_LINE_STYLE volumePivotsStyle; + ENUM_LINE_STYLE rsiPeakPivotsStyle; + ENUM_LINE_STYLE rsiValePivotsStyle; + ENUM_LINE_STYLE cciPeakPivotsStyle; + ENUM_LINE_STYLE cciValePivotsStyle; + ENUM_LINE_STYLE fvgBullishPivotsStyle; + ENUM_LINE_STYLE fvgBearishPivotsStyle; + ENUM_LINE_STYLE valeSupSWLPivotsStyle; + ENUM_LINE_STYLE peakResSWHPivotsStyle; + ENUM_LINE_STYLE trendLineBullishStyle; + ENUM_LINE_STYLE trendLineBearishStyle; + ENUM_LINE_STYLE trendBullishPivotsStyle; + ENUM_LINE_STYLE trendBearishPivotsStyle; + ENUM_LINE_STYLE rsiCrossedOverOSPivotsStyle; + ENUM_LINE_STYLE rsiCrossedUnderOBPivotsStyle; + ENUM_LINE_STYLE cciCrossedOverOSPivotsStyle; + ENUM_LINE_STYLE cciCrossedUnderOBPivotsStyle; + + // + // Colorize Props ... + + // + // Width Props ... + + // + // Style Props ... + + // + // Constructors ... + XCXCAEAPOIDrawer( + XCXCAEAPOIDetector *_detector // + ) + { + // + detector = _detector; + drawer = new XCPOIDrawer(); + + // + Default(); + } + + // + // De Constructors ... + ~XCXCAEAPOIDrawer() + { + // + Clear(); + + // + ZeroMemory(drawer); + ZeroMemory(detector); + } + + // + // Properties ... + + // + // Tools ... + + // + virtual void Default() + { + // + ignoreUpdateOSCTos = true; + drawTrendPivotsOnlySelectedFVG = true; + + // + drawTrendLine = false; + drawTickPivots = false; + drawVolumePivots = false; + drawRSIPeakPivots = false; + drawRSIValePivots = false; + drawCCIPeakPivots = false; + drawCCIValePivots = false; + drawFVGBullishPivots = false; + drawFVGBearishPivots = false; + drawValeSupSWLPivots = false; + drawPeakResSWHPivots = false; + drawTrendBullishPivots = false; + drawTrendBearishPivots = false; + drawRSICrossedOverOSPivots = false; + drawRSICrossedUnderOBPivots = false; + drawCCICrossedOverOSPivots = false; + drawCCICrossedUnderOBPivots = false; + + // + defaultBullishColor = clrLime; + defaultBearishColor = clrRed; + + // + tickPivotsColor = defaultBullishColor; + volumePivotsColor = defaultBearishColor; + + // + rsiValePivotsColor = defaultBullishColor; + cciValePivotsColor = defaultBullishColor; + fvgBullishPivotsColor = defaultBullishColor; + valeSupSWLPivotsColor = defaultBullishColor; + trendLineBullishColor = defaultBullishColor; + trendBullishPivotsColor = defaultBullishColor; + rsiCrossedOverOSPivotsColor = defaultBullishColor; + cciCrossedOverOSPivotsColor = defaultBullishColor; + + // + rsiPeakPivotsColor = defaultBearishColor; + cciPeakPivotsColor = defaultBearishColor; + fvgBearishPivotsColor = defaultBearishColor; + peakResSWHPivotsColor = defaultBearishColor; + trendLineBearishColor = defaultBearishColor; + trendBearishPivotsColor = defaultBearishColor; + rsiCrossedUnderOBPivotsColor = defaultBearishColor; + cciCrossedUnderOBPivotsColor = defaultBearishColor; + + // + defaultBullishWidth = 1; + defaultBearishWidth = 1; + + // + tickPivotsWidth = defaultBullishWidth; + volumePivotsWidth = defaultBearishWidth; + + // + rsiValePivotsWidth = defaultBullishWidth; + cciValePivotsWidth = defaultBullishWidth; + fvgBullishPivotsWidth = defaultBullishWidth; + valeSupSWLPivotsWidth = defaultBullishWidth; + trendLineBullishWidth = defaultBullishWidth; + trendBullishPivotsWidth = defaultBullishWidth; + rsiCrossedOverOSPivotsWidth = defaultBullishWidth; + cciCrossedOverOSPivotsWidth = defaultBullishWidth; + + // + rsiPeakPivotsWidth = defaultBearishWidth; + cciPeakPivotsWidth = defaultBearishWidth; + fvgBearishPivotsWidth = defaultBearishWidth; + peakResSWHPivotsWidth = defaultBearishWidth; + trendLineBearishWidth = defaultBearishWidth; + trendBearishPivotsWidth = defaultBearishWidth; + rsiCrossedUnderOBPivotsWidth = defaultBearishWidth; + cciCrossedUnderOBPivotsWidth = defaultBearishWidth; + + // + defaultBullishStyle = STYLE_SOLID; + defaultBearishStyle = STYLE_SOLID; + + // + tickPivotsStyle = defaultBullishStyle; + volumePivotsStyle = defaultBearishStyle; + + // + rsiValePivotsStyle = defaultBullishStyle; + cciValePivotsStyle = defaultBullishStyle; + fvgBullishPivotsStyle = defaultBullishStyle; + valeSupSWLPivotsStyle = defaultBullishStyle; + trendLineBullishStyle = defaultBullishStyle; + trendBullishPivotsStyle = defaultBullishStyle; + rsiCrossedOverOSPivotsStyle = defaultBullishStyle; + cciCrossedOverOSPivotsStyle = defaultBullishStyle; + + // + rsiPeakPivotsStyle = defaultBearishStyle; + cciPeakPivotsStyle = defaultBearishStyle; + fvgBearishPivotsStyle = defaultBearishStyle; + peakResSWHPivotsStyle = defaultBearishStyle; + trendLineBearishStyle = defaultBearishStyle; + trendBearishPivotsStyle = defaultBearishStyle; + rsiCrossedUnderOBPivotsStyle = defaultBearishStyle; + cciCrossedUnderOBPivotsStyle = defaultBearishStyle; + } + + // + void Draw(datetime to = NULL) + { + // + DrawTrendLine(); + DrawTickPivots(to); + DrawVolumePivots(to); + DrawRSIPeakPivots(to); + DrawRSIValePivots(to); + DrawCCIPeakPivots(to); + DrawCCIValePivots(to); + DrawFVGBullishPivots(to); + DrawFVGBearishPivots(to); + DrawValeSupSWLPivots(to); + DrawPeakResSWHPivots(to); + DrawTrendBullishPivots(to); + DrawTrendBearishPivots(to); + DrawRSICrossedOverOSPivots(to); + DrawRSICrossedUnderOBPivots(to); + DrawCCICrossedOverOSPivots(to); + DrawCCICrossedUnderOBPivots(to); + } + + // + void DrawBox( + XBoxZone &box, + datetime to = NULL // + ) + { + // + bool has = box.IsValid(); + if (!has) + { + return; + } + // + // Detect Pivot Type ... + ENUM_XCA_PIVOTS iType = GetPivotType(box); + has = IsValid(iType); + if (!has) + { + return; + } + + // + switch (iType) + { + // + case XCA_TICK: + // + DrawTickPivot( + box, + to // + ); + break; + + // + case XCA_VOLUME: + // + DrawVolumePivot( + box, + to // + ); + break; + + // + case XCA_FVG_BULL: + // + DrawFVGBullishPivot( + box, + to // + ); + break; + + // + case XCA_FVG_BEAR: + // + DrawFVGBearishPivot( + box, + to // + ); + break; + + // + case XCA_RSI_COOS: + // + DrawRSICrossedOverOSPivot( + box, + to // + ); + break; + + // + case XCA_RSI_CUOB: + // + DrawRSICrossedUnderOBPivot( + box, + to // + ); + break; + + // + case XCA_RSI_PEAK: + // + DrawRSIPeakPivot( + box, + to // + ); + break; + + // + case XCA_RSI_VALE: + // + DrawRSIValePivot( + box, + to // + ); + break; + + // + case XCA_CCI_COOS: + // + DrawCCICrossedOverOSPivot( + box, + to // + ); + break; + + // + case XCA_CCI_CUOB: + // + DrawCCICrossedUnderOBPivot( + box, + to // + ); + break; + + // + case XCA_CCI_PEAK: + // + DrawCCIPeakPivot( + box, + to // + ); + break; + + // + case XCA_CCI_VALE: + // + DrawCCIValePivot( + box, + to // + ); + break; + + // + case XCA_PEAKSWHRES: + // + DrawPeakResSWHPivot( + box, + to // + ); + break; + + // + case XCA_VALESWLSUP: + // + DrawValeSupSWLPivot( + box, + to // + ); + break; + } + } + + // + void DrawBoxes( + XBoxZone &boxes[], + datetime to = NULL // + ) + { + // + 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 // + ); + + // + iBox.Clean(); + }; + + // + // Trend Items ... + XCATRENDFVG trendFVGs[]; + count = ExtractTrendPivots( + trendFVGs, + boxes // + ); + has = IsValidSize(count); + if (!has) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + XCATRENDFVG iTrendFVG = trendFVGs[i]; + + // + bool isBullish = iTrendFVG.IsBullish(); + if (isBullish) + { + // + DrawTrendBullishPivot( + iTrendFVG, + to // + ); + } + else + { + // + DrawTrendBearishPivot( + iTrendFVG, + to // + ); + } + + // + iTrendFVG.Clean(); + } + + // + Clean(trendFVGs); + } + + // + void Clear() + { + // + mTrendLineObjects.Clear(); + mTickPivotObjects.Clear(); + mVolumePivotObjects.Clear(); + mRSIPeakPivotObjects.Clear(); + mRSIValePivotObjects.Clear(); + mCCIPeakPivotObjects.Clear(); + mCCIValePivotObjects.Clear(); + mFVGBullishPivotObjects.Clear(); + mFVGBearishPivotObjects.Clear(); + mValeSupSWLPivotObjects.Clear(); + mPeakResSWHPivotObjects.Clear(); + mTrendBullishPivotObjects.Clear(); + mTrendBearishPivotObjects.Clear(); + mRSICrossedOverOSPivotObjects.Clear(); + mRSICrossedUnderOBPivotObjects.Clear(); + mCCICrossedOverOSPivotObjects.Clear(); + mCCICrossedUnderOBPivotObjects.Clear(); + } + + // + // Collection Drawers ... + + // + void DrawTrendLine() + { + // + if (!drawTrendLine) + { + return; + } + + // + mTrendLineObjects.Clear(); + + // + ENUM_X_DIRECTION trend = X_DIRECTION_NONE; + bool has = detector.MarketTrend(trend); + if (!has) + { + return; + } + + // + long chartID = drawer.ChartIdentification(); + int subWindow = drawer.SubWindowIdentification(); + + // + bool hasBullishTrend = IsBullish(trend); + + // + double pPrice = hasBullishTrend + ? detector.trendPivotP.lower + : detector.trendPivotP.upper; + + // + datetime pTime = detector.trendPivotP.from; + + // + double cPrice = hasBullishTrend + ? detector.trendPivotC.lower + : detector.trendPivotC.upper; + + // + datetime cTime = detector.trendPivotC.from; + + // + string tlName = ToString(trend) + + "_TL_" + + ToString(pPrice) + + "_" + + ToString(cPrice); + + // + int tlWidth = hasBullishTrend + ? trendLineBullishWidth + : trendLineBearishWidth; + + // + color tlColor = hasBullishTrend + ? trendLineBullishColor + : trendLineBearishColor; + + // + ENUM_LINE_STYLE tlStyle = hasBullishTrend + ? trendLineBullishStyle + : trendLineBearishStyle; + + // + CChartObjectTrend *iObj; + iObj = new CChartObjectTrend(); + has = iObj.Create( + chartID, + tlName, + subWindow, + pTime, + pPrice, + cTime, + cPrice // + ); + if (has) + { + // + // Style Object ... + iObj.Color(tlColor); + iObj.Width(tlWidth); + iObj.Style(tlStyle); + iObj.RayRight(true); + + // + // Store Object ... + mTrendLineObjects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + void DrawTickPivots(datetime to = NULL) + { + // + bool has = drawTickPivots; + if (!has) + { + return; + } + + // + has = detector.HasTickPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountTickPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = detector.tickPivots[i]; + + // + DrawTickPivot( + iBox, + to // + ); + + // + iBox.Clean(); + } + } + + // + void DrawVolumePivots(datetime to = NULL) + { + // + bool has = drawVolumePivots; + if (!has) + { + return; + } + + // + has = detector.HasVolumePivots(); + if (!has) + { + return; + } + + // + int count = detector.CountVolumePivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = detector.volumePivots[i]; + + // + DrawVolumePivot( + iBox, + to // + ); + + // + iBox.Clean(); + } + } + + // + void DrawRSIPeakPivots(datetime to = NULL) + { + // + bool has = drawRSIPeakPivots; + if (!has) + { + return; + } + + // + has = detector.HasRSIPeakPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountRSIPeakPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = detector.rsiPeakPivots[i]; + + // + DrawRSIPeakPivot( + iBox, + to // + ); + + // + iBox.Clean(); + } + } + + // + void DrawRSIValePivots(datetime to = NULL) + { + // + bool has = drawRSIValePivots; + if (!has) + { + return; + } + + // + has = detector.HasRSIValePivots(); + if (!has) + { + return; + } + + // + int count = detector.CountRSIValePivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = detector.rsiValePivots[i]; + + // + DrawRSIValePivot( + iBox, + to // + ); + + // + iBox.Clean(); + } + } + + // + void DrawCCIPeakPivots(datetime to = NULL) + { + // + bool has = drawCCIPeakPivots; + if (!has) + { + return; + } + + // + has = detector.HasCCIPeakPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountCCIPeakPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = detector.cciPeakPivots[i]; + + // + DrawCCIPeakPivot( + iBox, + to // + ); + + // + iBox.Clean(); + } + } + + // + void DrawCCIValePivots(datetime to = NULL) + { + // + bool has = drawCCIValePivots; + if (!has) + { + return; + } + + // + has = detector.HasCCIValePivots(); + if (!has) + { + return; + } + + // + int count = detector.CountCCIValePivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = detector.cciValePivots[i]; + + // + DrawCCIValePivot( + iBox, + to // + ); + + // + iBox.Clean(); + } + } + + // + void DrawFVGBullishPivots(datetime to = NULL) + { + // + bool has = drawFVGBullishPivots; + if (!has) + { + return; + } + + // + has = detector.HasFVGBullishPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountFVGBullishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = detector.fvgBullishPivots[i]; + + // + DrawFVGBullishPivot( + iBox, + to // + ); + + // + iBox.Clean(); + } + } + + // + void DrawFVGBearishPivots(datetime to = NULL) + { + // + bool has = drawFVGBearishPivots; + if (!has) + { + return; + } + + // + has = detector.HasFVGBearishPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountFVGBearishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = detector.fvgBearishPivots[i]; + + // + DrawFVGBearishPivot( + iBox, + to // + ); + + // + iBox.Clean(); + } + } + + // + void DrawValeSupSWLPivots(datetime to = NULL) + { + // + bool has = drawValeSupSWLPivots; + if (!has) + { + return; + } + + // + has = detector.HasValeSupSWLPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountValeSupSWLPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = detector.valeSupSWLPivots[i]; + + // + DrawValeSupSWLPivot( + iBox, + to // + ); + + // + iBox.Clean(); + } + } + + // + void DrawPeakResSWHPivots(datetime to = NULL) + { + // + bool has = drawPeakResSWHPivots; + if (!has) + { + return; + } + + // + has = detector.HasPeakResSWHPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountPeakResSWHPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = detector.peakResSWHPivots[i]; + + // + DrawPeakResSWHPivot( + iBox, + to // + ); + + // + iBox.Clean(); + } + } + + // + void DrawTrendBullishPivots(datetime to = NULL) + { + // + bool has = drawTrendBullishPivots; + if (!has) + { + return; + } + + // + has = detector.HasTrendBullishPivots(); + if (!has) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + + // + int count = detector.CountTrendBullishPivots(); + for (int i = 0; i < count; i++) + { + // + XCATRENDFVG iTrendFVG = detector.trendBullishPivots[i]; + + // + DrawTrendBullishPivot( + iTrendFVG, + to // + ); + + // + iTrendFVG.Clean(); + } + } + + // + void DrawTrendBearishPivots(datetime to = NULL) + { + // + bool has = drawTrendBearishPivots; + if (!has) + { + return; + } + + // + has = detector.HasTrendBearishPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountTrendBearishPivots(); + for (int i = 0; i < count; i++) + { + // + XCATRENDFVG iTrendFVG = detector.trendBearishPivots[i]; + + // + DrawTrendBearishPivot( + iTrendFVG, + to // + ); + + // + iTrendFVG.Clean(); + } + } + + // + void DrawRSICrossedOverOSPivots(datetime to = NULL) + { + // + bool has = drawRSICrossedOverOSPivots; + if (!has) + { + return; + } + + // + has = detector.HasRSICrossedOverOSPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountRSICrossedOverOSPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = detector.rsiCrossedOverOSPivots[i]; + + // + DrawRSICrossedOverOSPivot( + iBox, + to // + ); + + // + iBox.Clean(); + } + } + + // + void DrawRSICrossedUnderOBPivots(datetime to = NULL) + { + // + bool has = drawRSICrossedUnderOBPivots; + if (!has) + { + return; + } + + // + has = detector.HasRSICrossedUnderOBPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountRSICrossedUnderOBPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = detector.rsiCrossedUnderOBPivots[i]; + + // + DrawRSICrossedUnderOBPivot( + iBox, + to // + ); + + // + iBox.Clean(); + } + } + + // + void DrawCCICrossedOverOSPivots(datetime to = NULL) + { + // + bool has = drawCCICrossedOverOSPivots; + if (!has) + { + return; + } + + // + has = detector.HasCCICrossedOverOSPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountCCICrossedOverOSPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = detector.cciCrossedOverOSPivots[i]; + + // + DrawCCICrossedOverOSPivot( + iBox, + to // + ); + + // + iBox.Clean(); + } + } + + // + void DrawCCICrossedUnderOBPivots(datetime to = NULL) + { + // + bool has = drawCCICrossedUnderOBPivots; + if (!has) + { + return; + } + + // + has = detector.HasCCICrossedUnderOBPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountCCICrossedUnderOBPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = detector.cciCrossedUnderOBPivots[i]; + + // + DrawCCICrossedUnderOBPivot( + iBox, + to // + ); + + // + iBox.Clean(); + } + } + + // + // One Item Drawers ... + + // + void DrawTickPivot( + XBoxZone &item, + datetime to = NULL // + ) + { + // + bool has = drawTickPivots; + if (!has) + { + return; + } + + // + has = item.IsValid() && + item.type == GetBoxType(XCA_TICK); + if (!has) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + if (canUpdateTo) + { + item.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + item, + iObj // + ); + if (has) + { + // + // Style Pivot ... + iObj.BoxColor(tickPivotsColor); + iObj.BoxWidth(tickPivotsWidth); + iObj.BoxStyle(tickPivotsStyle); + + // + // Store Pivot ... + mTickPivotObjects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + void DrawVolumePivot( + XBoxZone &item, + datetime to = NULL // + ) + { + // + bool has = drawVolumePivots; + if (!has) + { + return; + } + + // + has = item.IsValid() && + item.type == GetBoxType(XCA_VOLUME); + if (!has) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + if (canUpdateTo) + { + item.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + item, + iObj // + ); + if (has) + { + // + // Style Pivot ... + iObj.BoxColor(volumePivotsColor); + iObj.BoxWidth(volumePivotsWidth); + iObj.BoxStyle(volumePivotsStyle); + + // + // Store Pivot ... + mVolumePivotObjects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + void DrawRSIPeakPivot( + XBoxZone &item, + datetime to = NULL // + ) + { + // + bool has = drawRSIPeakPivots; + if (!has) + { + return; + } + + // + has = item.IsValid() && + item.type == GetBoxType(XCA_RSI_PEAK) && + item.dir == GetDirection(XCA_RSI_PEAK); + if (!has) + { + return; + } + + // + if (ignoreUpdateOSCTos) + { + to = NULL; + } + bool canUpdateTo = IsValid(to); + if (canUpdateTo) + { + item.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + item, + iObj // + ); + if (has) + { + // + // Style Object ... + iObj.BoxColor(rsiPeakPivotsColor); + iObj.BoxWidth(rsiPeakPivotsWidth); + iObj.BoxStyle(rsiPeakPivotsStyle); + + // + // Store Object ... + mRSIPeakPivotObjects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + void DrawRSIValePivot( + XBoxZone &item, + datetime to = NULL // + ) + { + // + bool has = drawRSIValePivots; + if (!has) + { + return; + } + + // + has = item.IsValid() && + item.type == GetBoxType(XCA_RSI_VALE) && + item.dir == GetDirection(XCA_RSI_VALE); + if (!has) + { + return; + } + + // + if (ignoreUpdateOSCTos) + { + to = NULL; + } + bool canUpdateTo = IsValid(to); + if (canUpdateTo) + { + item.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + item, + iObj // + ); + if (has) + { + // + // Style Object ... + iObj.BoxColor(rsiValePivotsColor); + iObj.BoxWidth(rsiValePivotsWidth); + iObj.BoxStyle(rsiValePivotsStyle); + + // + // Store Object ... + mRSIValePivotObjects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + void DrawCCIPeakPivot( + XBoxZone &item, + datetime to = NULL // + ) + { + // + bool has = drawCCIPeakPivots; + if (!has) + { + return; + } + + // + has = item.IsValid() && + item.type == GetBoxType(XCA_CCI_PEAK) && + item.dir == GetDirection(XCA_CCI_PEAK); + if (!has) + { + return; + } + + // + if (ignoreUpdateOSCTos) + { + to = NULL; + } + bool canUpdateTo = IsValid(to); + if (canUpdateTo) + { + item.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + item, + iObj // + ); + if (has) + { + // + // Style Object ... + iObj.BoxColor(cciPeakPivotsColor); + iObj.BoxWidth(cciPeakPivotsWidth); + iObj.BoxStyle(cciPeakPivotsStyle); + + // + // Store Object ... + mCCIPeakPivotObjects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + void DrawCCIValePivot( + XBoxZone &item, + datetime to = NULL // + ) + { + // + bool has = drawCCIValePivots; + if (!has) + { + return; + } + + // + has = item.IsValid() && + item.type == GetBoxType(XCA_CCI_VALE) && + item.dir == GetDirection(XCA_CCI_VALE); + if (!has) + { + return; + } + + // + if (ignoreUpdateOSCTos) + { + to = NULL; + } + bool canUpdateTo = IsValid(to); + if (canUpdateTo) + { + item.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + item, + iObj // + ); + if (has) + { + // + // Style Object ... + iObj.BoxColor(cciValePivotsColor); + iObj.BoxWidth(cciValePivotsWidth); + iObj.BoxStyle(cciValePivotsStyle); + + // + // Store Object ... + mCCIValePivotObjects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + void DrawFVGBullishPivot( + XBoxZone &item, + datetime to = NULL // + ) + { + // + bool has = drawFVGBullishPivots; + if (!has) + { + return; + } + + // + has = item.IsValid() && + item.type == GetBoxType(XCA_FVG_BULL) && + item.dir == GetDirection(XCA_FVG_BULL); + if (!has) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + if (canUpdateTo) + { + item.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + item, + iObj // + ); + if (has) + { + // + // Style Object ... + iObj.BoxColor(fvgBullishPivotsColor); + iObj.BoxWidth(fvgBullishPivotsWidth); + iObj.BoxStyle(fvgBullishPivotsStyle); + + // + // Store Object ... + mFVGBullishPivotObjects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + void DrawFVGBearishPivot( + XBoxZone &item, + datetime to = NULL // + ) + { + // + bool has = drawFVGBearishPivots; + if (!has) + { + return; + } + + // + has = item.IsValid() && + item.type == GetBoxType(XCA_FVG_BEAR) && + item.dir == GetDirection(XCA_FVG_BEAR); + if (!has) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + if (canUpdateTo) + { + item.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + item, + iObj // + ); + if (has) + { + // + // Style Object ... + iObj.BoxColor(fvgBearishPivotsColor); + iObj.BoxWidth(fvgBearishPivotsWidth); + iObj.BoxStyle(fvgBearishPivotsStyle); + + // + // Store Object ... + mFVGBearishPivotObjects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + void DrawValeSupSWLPivot( + XBoxZone &item, + datetime to = NULL // + ) + { + // + bool has = drawValeSupSWLPivots; + if (!has) + { + return; + } + + // + has = item.IsValid() && + item.type == GetBoxType(XCA_VALESWLSUP) && + item.dir == GetDirection(XCA_VALESWLSUP); + if (!has) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + if (canUpdateTo) + { + item.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + item, + iObj // + ); + if (has) + { + // + // Style Object ... + iObj.BoxColor(valeSupSWLPivotsColor); + iObj.BoxWidth(valeSupSWLPivotsWidth); + iObj.BoxStyle(valeSupSWLPivotsStyle); + + // + // Store Object ... + mValeSupSWLPivotObjects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + void DrawPeakResSWHPivot( + XBoxZone &item, + datetime to = NULL // + ) + { + // + bool has = drawPeakResSWHPivots; + if (!has) + { + return; + } + + // + has = item.IsValid() && + item.type == GetBoxType(XCA_PEAKSWHRES) && + item.dir == GetDirection(XCA_PEAKSWHRES); + if (!has) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + if (canUpdateTo) + { + item.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + item, + iObj // + ); + if (has) + { + // + // Style Object ... + iObj.BoxColor(peakResSWHPivotsColor); + iObj.BoxWidth(peakResSWHPivotsWidth); + iObj.BoxStyle(peakResSWHPivotsStyle); + + // + // Store Object ... + mPeakResSWHPivotObjects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + void DrawTrendBullishPivot( + XCATRENDFVG &item, + datetime to = NULL // + ) + { + // + bool has = drawTrendBullishPivots; + if (!has) + { + return; + } + + // + has = item.IsValid() && + item.trend.type == GetBoxType(XCA_TREND_BULL) && + item.trend.dir == GetDirection(XCA_TREND_BULL); + if (!has) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + + // + // Draw Trend Box ... + + // + if (canUpdateTo) + { + item.trend.to = to; + } + + // + XCBoxObject *iTrendBoxObj; + has = drawer.DrawBox( + item.trend, + iTrendBoxObj // + ); + if (has) + { + // + // Style Object ... + iTrendBoxObj.BoxColor(trendBullishPivotsColor); + iTrendBoxObj.BoxWidth(trendBullishPivotsWidth); + iTrendBoxObj.BoxStyle(trendBullishPivotsStyle); + + // + // Store Object ... + mTrendBullishPivotObjects.Add(iTrendBoxObj); + } + + // + // Draw ITrendFVG FVGS ... + if (drawTrendPivotsOnlySelectedFVG) + { + // + XBoxZone iBox; + has = item.GetSelectedFVG(iBox); + if (!has) + { + // + iBox.Clean(); + return; + } + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + + // + if (has) + { + // + // Style Object ... + iObj.BoxColor(fvgBullishPivotsColor); + iObj.BoxWidth(fvgBullishPivotsWidth); + iObj.BoxStyle(fvgBullishPivotsStyle); + + // + // Store Object ... + mTrendBullishPivotObjects.Add(iObj); + } + + // + iBox.Clean(); + ZeroMemory(iObj); + } + else + { + // + // Draw All FVGs ... + has = HasChild(item.fvgs); + if (has) + { + // + int jCount = ArraySize(item.fvgs); + for (int j = 0; j < jCount; j++) + { + // + XBoxZone iBox = item.fvgs[j]; + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + // Style Object ... + iObj.BoxColor(fvgBullishPivotsColor); + iObj.BoxWidth(fvgBullishPivotsWidth); + iObj.BoxStyle(fvgBullishPivotsStyle); + + // + // Store Object ... + mTrendBullishPivotObjects.Add(iObj); + } + + // + iBox.Clean(); + ZeroMemory(iObj); + } + } + } + + // + ZeroMemory(iTrendBoxObj); + } + + // + void DrawTrendBearishPivot( + XCATRENDFVG &item, + datetime to = NULL // + ) + { + // + bool has = drawTrendBearishPivots; + if (!has) + { + return; + } + + // + has = item.IsValid() && + item.trend.type == GetBoxType(XCA_TREND_BEAR) && + item.trend.dir == GetDirection(XCA_TREND_BEAR); + if (!has) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + + // + // Draw Trend Box ... + + // + if (canUpdateTo) + { + item.trend.to = to; + } + + // + XCBoxObject *iTrendBoxObj; + has = drawer.DrawBox( + item.trend, + iTrendBoxObj // + ); + if (has) + { + // + // Style Object ... + iTrendBoxObj.BoxColor(trendBearishPivotsColor); + iTrendBoxObj.BoxWidth(trendBearishPivotsWidth); + iTrendBoxObj.BoxStyle(trendBearishPivotsStyle); + + // + // Store Object ... + mTrendBearishPivotObjects.Add(iTrendBoxObj); + } + + // + // Draw ITrendFVG FVGS ... + if (drawTrendPivotsOnlySelectedFVG) + { + // + XBoxZone iBox; + has = item.GetSelectedFVG(iBox); + if (!has) + { + // + iBox.Clean(); + return; + } + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + + // + if (has) + { + // + // Style Object ... + iObj.BoxColor(fvgBearishPivotsColor); + iObj.BoxWidth(fvgBearishPivotsWidth); + iObj.BoxStyle(fvgBearishPivotsStyle); + + // + // Store Object ... + mTrendBearishPivotObjects.Add(iObj); + } + + // + iBox.Clean(); + ZeroMemory(iObj); + } + else + { + // + // Draw All FVGs ... + has = HasChild(item.fvgs); + if (has) + { + // + int jCount = ArraySize(item.fvgs); + for (int j = 0; j < jCount; j++) + { + // + XBoxZone iBox = item.fvgs[j]; + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + // Style Object ... + iObj.BoxColor(fvgBearishPivotsColor); + iObj.BoxWidth(fvgBearishPivotsWidth); + iObj.BoxStyle(fvgBearishPivotsStyle); + + // + // Store Object ... + mTrendBearishPivotObjects.Add(iObj); + } + + // + iBox.Clean(); + ZeroMemory(iObj); + } + } + } + + // + ZeroMemory(iTrendBoxObj); + } + + // + void DrawRSICrossedOverOSPivot( + XBoxZone &item, + datetime to = NULL // + ) + { + // + bool has = drawRSICrossedOverOSPivots; + if (!has) + { + return; + } + + // + has = item.IsValid() && + item.type == GetBoxType(XCA_RSI_COOS) && + item.dir == GetDirection(XCA_RSI_COOS); + if (!has) + { + return; + } + + // + if (ignoreUpdateOSCTos) + { + to = NULL; + } + bool canUpdateTo = IsValid(to); + if (canUpdateTo) + { + item.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + item, + iObj // + ); + if (has) + { + // + // Style Object ... + iObj.BoxColor(rsiCrossedOverOSPivotsColor); + iObj.BoxWidth(rsiCrossedOverOSPivotsWidth); + iObj.BoxStyle(rsiCrossedOverOSPivotsStyle); + + // + // Store Object ... + mRSICrossedOverOSPivotObjects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + void DrawRSICrossedUnderOBPivot( + XBoxZone &item, + datetime to = NULL // + ) + { + // + bool has = drawRSICrossedUnderOBPivots; + if (!has) + { + return; + } + + // + has = item.IsValid() && + item.type == GetBoxType(XCA_RSI_CUOB) && + item.dir == GetDirection(XCA_RSI_CUOB); + if (!has) + { + return; + } + + // + if (ignoreUpdateOSCTos) + { + to = NULL; + } + bool canUpdateTo = IsValid(to); + if (canUpdateTo) + { + item.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + item, + iObj // + ); + if (has) + { + // + // Style Object ... + iObj.BoxColor(rsiCrossedUnderOBPivotsColor); + iObj.BoxWidth(rsiCrossedUnderOBPivotsWidth); + iObj.BoxStyle(rsiCrossedUnderOBPivotsStyle); + + // + // Store Object ... + mRSICrossedUnderOBPivotObjects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + void DrawCCICrossedOverOSPivot( + XBoxZone &item, + datetime to = NULL // + ) + { + // + bool has = drawCCICrossedOverOSPivots; + if (!has) + { + return; + } + + // + has = item.IsValid() && + item.type == GetBoxType(XCA_CCI_COOS) && + item.dir == GetDirection(XCA_CCI_COOS); + if (!has) + { + return; + } + + // + if (ignoreUpdateOSCTos) + { + to = NULL; + } + bool canUpdateTo = IsValid(to); + if (canUpdateTo) + { + item.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + item, + iObj // + ); + if (has) + { + // + // Style Object ... + iObj.BoxColor(cciCrossedOverOSPivotsColor); + iObj.BoxWidth(cciCrossedOverOSPivotsWidth); + iObj.BoxStyle(cciCrossedOverOSPivotsStyle); + + // + // Store Object ... + mCCICrossedOverOSPivotObjects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + void DrawCCICrossedUnderOBPivot( + XBoxZone &item, + datetime to = NULL // + ) + { + // + bool has = drawCCICrossedUnderOBPivots; + if (!has) + { + return; + } + + // + has = item.IsValid() && + item.type == GetBoxType(XCA_CCI_CUOB) && + item.dir == GetDirection(XCA_CCI_CUOB); + if (!has) + { + return; + } + + // + if (ignoreUpdateOSCTos) + { + to = NULL; + } + bool canUpdateTo = IsValid(to); + if (canUpdateTo) + { + item.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + item, + iObj // + ); + if (has) + { + // + // Style Object ... + iObj.BoxColor(cciCrossedUnderOBPivotsColor); + iObj.BoxWidth(cciCrossedUnderOBPivotsWidth); + iObj.BoxStyle(cciCrossedUnderOBPivotsStyle); + + // + // Store Object ... + mCCICrossedUnderOBPivotObjects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + // Protected ... + protected: + // + // Props ... + + // + // Prrivate ... + private: + // + // Props ... + + // + XCPOIDrawer *drawer; + XCXCAEAPOIDetector *detector; + + // + CArrayObj mTickPivotObjects; + CArrayObj mTrendLineObjects; + CArrayObj mVolumePivotObjects; + CArrayObj mRSIPeakPivotObjects; + CArrayObj mRSIValePivotObjects; + CArrayObj mCCIPeakPivotObjects; + CArrayObj mCCIValePivotObjects; + CArrayObj mFVGBullishPivotObjects; + CArrayObj mFVGBearishPivotObjects; + CArrayObj mValeSupSWLPivotObjects; + CArrayObj mPeakResSWHPivotObjects; + CArrayObj mTrendBullishPivotObjects; + CArrayObj mTrendBearishPivotObjects; + CArrayObj mRSICrossedOverOSPivotObjects; + CArrayObj mRSICrossedUnderOBPivotObjects; + CArrayObj mCCICrossedOverOSPivotObjects; + CArrayObj mCCICrossedUnderOBPivotObjects; + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14040218 XCAEA/Documents/BKP/xcaea.x-poi.drawer.class.mq5 b/BKPS/14040218 XCAEA/Documents/BKP/xcaea.x-poi.drawer.class.mq5 new file mode 100644 index 0000000..14d0bfd --- /dev/null +++ b/BKPS/14040218 XCAEA/Documents/BKP/xcaea.x-poi.drawer.class.mq5 @@ -0,0 +1,2424 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XCXCAEAPOIDrawer ... +// Description: Class for XCAEA POI Drawer ... +// +// +// 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 XCAEA POI Drawer" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../Classes/xcaea.x-poi.detector.class.mq5" + +// +// Definitions ... + +// +// Implementations ... +class XCXCAEAPOIDrawer : public XCBase +{ + // + // Public ... + public: + // + // Props ... + bool drawSWHPivots; + bool drawSWLPivots; + bool drawPeakPivots; + bool drawValePivots; + bool drawRSIPeakPivots; + bool drawRSIValePivots; + bool drawCCIPeakPivots; + bool drawCCIValePivots; + bool drawKIBullishPivots; + bool drawKIBearishPivots; + bool drawFVGBullishPivots; + bool drawFVGBearishPivots; + bool drawPeakSWHResPivots; + bool drawValeSWLSupPivots; + bool drawTKIBullishPivots; + bool drawTKIBearishPivots; + bool drawCycleSameLLPivots; + bool drawCycleSameHHPivots; + bool drawTrendBullishPivots; + bool drawTrendBearishPivots; + bool drawPVFVGBullishPivots; + bool drawPVFVGBearishPivots; + bool drawTKITRNDBullishPivots; + bool drawTKITRNDBearishPivots; + bool drawRSICrossedOverOSPivots; + bool drawRSICrossedUnderOBPivots; + bool drawCCICrossedOverOSPivots; + bool drawCCICrossedUnderOBPivots; + + // + bool drawTicks; + + // + // Colorize Props ... + + // + color peakPivotColor; + color valePivotColor; + color sameHHPivotColor; + color sameLLPivotColor; + color ticksBullishColor; + color ticksBearishColor; + color kiBullishPivotColor; + color kiBearishPivotColor; + color fvgBullishPivotColor; + color fvgBearishPivotColor; + color defBullishPivotColor; + color defBearishPivotColor; + color oscsBullishPivotColor; + color oscsBearishPivotColor; + color trendBullishPivotColor; + color trendBearishPivotColor; + + // + // Width Props ... + + // + int peakPivotWidth; + int valePivotWidth; + int sameHHPivotWidth; + int sameLLPivotWidth; + int ticksBullishWidth; + int ticksBearishWidth; + int kiBullishPivotWidth; + int kiBearishPivotWidth; + int fvgBullishPivotWidth; + int fvgBearishPivotWidth; + int defBullishPivotWidth; + int defBearishPivotWidth; + int oscsBullishPivotWidth; + int oscsBearishPivotWidth; + int trendBullishPivotWidth; + int trendBearishPivotWidth; + + // + // Style Props ... + + // + ENUM_LINE_STYLE peakPivotStyle; + ENUM_LINE_STYLE valePivotStyle; + ENUM_LINE_STYLE sameHHPivotStyle; + ENUM_LINE_STYLE sameLLPivotStyle; + ENUM_LINE_STYLE ticksBullishStyle; + ENUM_LINE_STYLE ticksBearishStyle; + ENUM_LINE_STYLE kiBullishPivotStyle; + ENUM_LINE_STYLE kiBearishPivotStyle; + ENUM_LINE_STYLE fvgBullishPivotStyle; + ENUM_LINE_STYLE fvgBearishPivotStyle; + ENUM_LINE_STYLE defBullishPivotStyle; + ENUM_LINE_STYLE defBearishPivotStyle; + ENUM_LINE_STYLE oscsBullishPivotStyle; + ENUM_LINE_STYLE oscsBearishPivotStyle; + ENUM_LINE_STYLE trendBullishPivotStyle; + ENUM_LINE_STYLE trendBearishPivotStyle; + // + // Constructors ... + XCXCAEAPOIDrawer( + XCXCAEAPOIDetector *_detector // + ) + { + // + detector = _detector; + drawer = new XCPOIDrawer(); + + // + Default(); + } + + // + // De Constructors ... + ~XCXCAEAPOIDrawer() + { + // + mSWHPivotObjects.Clear(); + mSWLPivotObjects.Clear(); + mPeakPivotObjects.Clear(); + mValePivotObjects.Clear(); + mRSIPeakPivotObjects.Clear(); + mRSIValePivotObjects.Clear(); + mCCIPeakPivotObjects.Clear(); + mCCIValePivotObjects.Clear(); + mKIBullishPivotObjects.Clear(); + mKIBearishPivotObjects.Clear(); + mFVGBullishPivotObjects.Clear(); + mFVGBearishPivotObjects.Clear(); + mPeakSWHResPivotObjects.Clear(); + mValeSWLSupPivotObjects.Clear(); + mTKIBullishPivotObjects.Clear(); + mTKIBearishPivotObjects.Clear(); + mTrendBullishPivotObjects.Clear(); + mTrendBearishPivotObjects.Clear(); + mCycleSameLLPivotObjects.Clear(); + mCycleSameHHPivotObjects.Clear(); + mTKITRNDBullishPivotObjects.Clear(); + mTKITRNDBearishPivotObjects.Clear(); + mRSICrossedOverOSPivotObjects.Clear(); + mRSICrossedUnderOBPivotObjects.Clear(); + mCCICrossedOverOSPivotObjects.Clear(); + mCCICrossedUnderOBPivotObjects.Clear(); + + // + ZeroMemory(drawer); + ZeroMemory(detector); + } + + // + // Properties ... + + // + // Tools ... + + // + virtual void Default() + { + // + drawSWHPivots = false; + drawSWLPivots = false; + drawPeakPivots = false; + drawValePivots = false; + drawRSIPeakPivots = false; + drawRSIValePivots = false; + drawCCIPeakPivots = false; + drawCCIValePivots = false; + drawKIBullishPivots = false; + drawKIBearishPivots = false; + drawFVGBullishPivots = false; + drawFVGBearishPivots = false; + drawPeakSWHResPivots = false; + drawValeSWLSupPivots = false; + drawTKIBullishPivots = false; + drawTKIBearishPivots = false; + drawCycleSameLLPivots = false; + drawCycleSameHHPivots = false; + drawPVFVGBullishPivots = false; + drawPVFVGBearishPivots = false; + drawTrendBullishPivots = false; + drawTrendBearishPivots = false; + drawTKITRNDBullishPivots = false; + drawTKITRNDBearishPivots = false; + drawRSICrossedOverOSPivots = false; + drawRSICrossedUnderOBPivots = false; + drawCCICrossedOverOSPivots = false; + drawCCICrossedUnderOBPivots = false; + + // + drawTicks = false; + + // + // Color ... + defBullishPivotColor = clrLime; + defBearishPivotColor = clrRed; + + // + peakPivotColor = defBearishPivotColor; + valePivotColor = defBullishPivotColor; + sameHHPivotColor = defBearishPivotColor; + sameLLPivotColor = defBullishPivotColor; + ticksBullishColor = defBearishPivotColor; + ticksBearishColor = defBullishPivotColor; + kiBullishPivotColor = defBullishPivotColor; + kiBearishPivotColor = defBearishPivotColor; + fvgBullishPivotColor = defBullishPivotColor; + fvgBearishPivotColor = defBearishPivotColor; + oscsBullishPivotColor = defBullishPivotColor; + oscsBearishPivotColor = defBearishPivotColor; + trendBullishPivotColor = defBullishPivotColor; + trendBearishPivotColor = defBearishPivotColor; + + // + // Width ... + defBullishPivotWidth = 1; + defBearishPivotWidth = 1; + + // + peakPivotWidth = defBearishPivotWidth; + valePivotWidth = defBullishPivotWidth; + sameHHPivotWidth = defBearishPivotWidth; + sameLLPivotWidth = defBullishPivotWidth; + ticksBullishWidth = defBearishPivotWidth; + ticksBearishWidth = defBullishPivotWidth; + kiBullishPivotWidth = defBullishPivotWidth; + kiBearishPivotWidth = defBearishPivotWidth; + fvgBullishPivotWidth = defBullishPivotWidth; + fvgBearishPivotWidth = defBearishPivotWidth; + oscsBullishPivotWidth = defBullishPivotWidth; + oscsBearishPivotWidth = defBearishPivotWidth; + trendBullishPivotWidth = defBullishPivotWidth; + trendBearishPivotWidth = defBearishPivotWidth; + + // + // Style ... + defBullishPivotStyle = STYLE_DOT; + defBearishPivotStyle = STYLE_DOT; + + // + peakPivotStyle = defBearishPivotStyle; + valePivotStyle = defBullishPivotStyle; + sameHHPivotStyle = defBearishPivotStyle; + sameLLPivotStyle = defBullishPivotStyle; + ticksBullishStyle = defBearishPivotStyle; + ticksBearishStyle = defBullishPivotStyle; + kiBullishPivotStyle = defBullishPivotStyle; + kiBearishPivotStyle = defBearishPivotStyle; + fvgBullishPivotStyle = defBullishPivotStyle; + fvgBearishPivotStyle = defBearishPivotStyle; + oscsBullishPivotStyle = defBullishPivotStyle; + oscsBearishPivotStyle = defBearishPivotStyle; + trendBullishPivotStyle = defBullishPivotStyle; + trendBearishPivotStyle = defBearishPivotStyle; + } + + // + void Draw(datetime to = NULL) + { + // + DrawTicks(to); + DrawSWHPivots(to); + DrawSWLPivots(to); + DrawPeakPivots(to); + DrawValePivots(to); + DrawRSIPeakPivots(to); + DrawRSIValePivots(to); + DrawCCIPeakPivots(to); + DrawCCIValePivots(to); + DrawKIBullishPivots(to); + DrawKIBearishPivots(to); + DrawFVGBullishPivots(to); + DrawFVGBearishPivots(to); + DrawPeakSWHResPivots(to); + DrawValeSWLSupPivots(to); + DrawTKIBullishPivots(to); + DrawTKIBearishPivots(to); + DrawCycleSameLLPivots(to); + DrawCycleSameHHPivots(to); + DrawTrendBullishPivots(to); + DrawTrendBearishPivots(to); + DrawTKITRNDBullishPivots(to); + DrawTKITRNDBearishPivots(to); + DrawRSICrossedOverOSPivots(to); + DrawRSICrossedUnderOBPivots(to); + DrawCCICrossedOverOSPivots(to); + DrawCCICrossedUnderOBPivots(to); + } + + // + // + // + + // + void DrawTicks(datetime to = NULL) + { + // + if (!drawTicks) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + + // + // PEAK TICKS ... + bool has = detector.HasPeakTicks(); + if (has) + { + // + int count = detector.CountPeakTicks(); + for (int i = 0; i < count; i++) + { + // + XCAPVTick iPVTick = detector.peakTicks[i]; + + // + // Converts Zone to Box ... + XBoxZone iBox; + has = iPVTick.GetMaxVolumeBox(iBox); + if (!has) + { + // + iBox.Clean(); + iPVTick.Clean(); + + // + continue; + } + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxColor(ticksBearishColor); + iObj.BoxWidth(ticksBearishWidth); + iObj.BoxStyle(ticksBearishStyle); + + // + mPeakSWHResPivotObjects.Add(iObj); + } + + // + iBox.Clean(); + iPVTick.Clean(); + ZeroMemory(iObj); + } + } + + // + // VALE TICKS ... + has = detector.HasValeTicks(); + if (has) + { + // + int count = detector.CountValeTicks(); + for (int i = 0; i < count; i++) + { + // + XCAPVTick iPVTick = detector.valeTicks[i]; + + // + // Converts Zone to Box ... + XBoxZone iBox; + has = iPVTick.GetMaxVolumeBox(iBox); + if (!has) + { + // + iBox.Clean(); + iPVTick.Clean(); + + // + continue; + } + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxColor(ticksBullishColor); + iObj.BoxWidth(ticksBullishWidth); + iObj.BoxStyle(ticksBullishStyle); + + // + mValeSWLSupPivotObjects.Add(iObj); + } + + // + iBox.Clean(); + iPVTick.Clean(); + ZeroMemory(iObj); + } + } + } + + // + void DrawSWHPivots(datetime to = NULL) + { + // + if (!drawSWHPivots) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + + // + bool has = detector.HasSWHPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountSWHPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = detector.swhPivots[i].AsBox(iBox); + if (!has) + { + continue; + } + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxColor(peakPivotColor); + iObj.BoxWidth(peakPivotWidth); + iObj.BoxStyle(peakPivotStyle); + + // + mSWHPivotObjects.Add(iObj); + } + + // + iBox.Clean(); + } + } + + // + void DrawSWLPivots(datetime to = NULL) + { + // + if (!drawSWLPivots) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + + // + bool has = detector.HasSWLPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountSWLPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = detector.swlPivots[i].AsBox(iBox); + if (!has) + { + continue; + } + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxColor(valePivotColor); + iObj.BoxWidth(valePivotWidth); + iObj.BoxStyle(valePivotStyle); + + // + mSWLPivotObjects.Add(iObj); + } + + // + iBox.Clean(); + } + } + + // + void DrawPeakPivots(datetime to = NULL) + { + // + if (!drawPeakPivots) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + + // + bool has = detector.HasPeakPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountPeakPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = detector.peakPivots[i].AsBox(iBox); + if (!has) + { + continue; + } + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxColor(peakPivotColor); + iObj.BoxWidth(peakPivotWidth); + iObj.BoxStyle(peakPivotStyle); + + // + mPeakPivotObjects.Add(iObj); + } + + // + iBox.Clean(); + } + } + + // + void DrawValePivots(datetime to = NULL) + { + // + if (!drawValePivots) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + + // + bool has = detector.HasValePivots(); + if (!has) + { + return; + } + + // + int count = detector.CountValePivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = detector.valePivots[i].AsBox(iBox); + if (!has) + { + continue; + } + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxColor(valePivotColor); + iObj.BoxWidth(valePivotWidth); + iObj.BoxStyle(valePivotStyle); + + // + mValePivotObjects.Add(iObj); + } + + // + iBox.Clean(); + } + } + + // + void DrawKIBullishPivots(datetime to = NULL) + { + // + if (!drawKIBullishPivots) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + + // + bool has = detector.HasKIBullishPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountKIBullishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = detector.kiBullishPivots[i].AsBox(iBox); + if (!has) + { + continue; + } + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxColor(kiBullishPivotColor); + iObj.BoxWidth(kiBullishPivotWidth); + iObj.BoxStyle(kiBullishPivotStyle); + + // + mKIBullishPivotObjects.Add(iObj); + } + + // + iBox.Clean(); + } + } + + // + void DrawKIBearishPivots(datetime to = NULL) + { + // + if (!drawKIBearishPivots) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + + // + bool has = detector.HasKIBearishPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountKIBearishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = detector.kiBearishPivots[i].AsBox(iBox); + if (!has) + { + continue; + } + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxColor(kiBearishPivotColor); + iObj.BoxWidth(kiBearishPivotWidth); + iObj.BoxStyle(kiBearishPivotStyle); + + // + mKIBearishPivotObjects.Add(iObj); + } + + // + iBox.Clean(); + } + } + + // + void DrawFVGBullishPivots(datetime to = NULL) + { + // + bool canUpdateTo = IsValid(to); + + // + if (drawFVGBullishPivots) + { + // + bool has = detector.HasFVGBullishPivots(); + if (has) + { + // + int count = detector.CountFVGBullishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = detector.fvgBullishPivots[i].AsBox(iBox); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxColor(fvgBullishPivotColor); + iObj.BoxWidth(fvgBullishPivotWidth); + iObj.BoxStyle(fvgBullishPivotStyle); + + // + mFVGBullishPivotObjects.Add(iObj); + } + } + } + } + + // + if (drawPVFVGBullishPivots) + { + // + bool has = detector.HasPVFVGBullishPivots(); + if (has) + { + // + int count = detector.CountPVFVGBullishPivots(); + for (int i = 0; i < count; i++) + { + // + XCAPVPivot iPVFVG = detector.pvFVGBullishPivots[i]; + + // + XBoxZone fvgBoxes[]; + int fvgBoxesCount = iPVFVG.GetPivots(fvgBoxes); + has = IsValidSize(fvgBoxesCount); + if (has) + { + // + int idx = GetLowest(fvgBoxes); + if (IsValidIndex(idx)) + { + // + XBoxZone iBox = fvgBoxes[idx]; + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + + // + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxColor(fvgBullishPivotColor); + iObj.BoxWidth(fvgBullishPivotWidth); + iObj.BoxStyle(fvgBullishPivotStyle); + + // + mFVGBullishPivotObjects.Add(iObj); + } + + // + iBox.Clean(); + ZeroMemory(iObj); + } + } + } + } + } + } + + // + void DrawFVGBearishPivots(datetime to = NULL) + { + // + bool canUpdateTo = IsValid(to); + + // + if (drawFVGBearishPivots) + { + // + bool has = detector.HasFVGBearishPivots(); + if (has) + { + // + int count = detector.CountFVGBearishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = detector.fvgBearishPivots[i].AsBox(iBox); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxColor(fvgBearishPivotColor); + iObj.BoxWidth(fvgBearishPivotWidth); + iObj.BoxStyle(fvgBearishPivotStyle); + + // + mFVGBearishPivotObjects.Add(iObj); + } + } + } + } + + // + if (drawPVFVGBullishPivots) + { + // + bool has = detector.HasPVFVGBearishPivots(); + if (has) + { + // + int count = detector.CountPVFVGBearishPivots(); + for (int i = 0; i < count; i++) + { + // + XCAPVPivot iPVFVG = detector.pvFVGBearishPivots[i]; + + // + XBoxZone fvgBoxes[]; + int fvgBoxesCount = iPVFVG.GetPivots(fvgBoxes); + has = IsValidSize(fvgBoxesCount); + if (has) + { + // + int idx = GetHighest(fvgBoxes); + if (IsValidIndex(idx)) + { + // + XBoxZone iBox = fvgBoxes[idx]; + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + + // + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxColor(fvgBearishPivotColor); + iObj.BoxWidth(fvgBearishPivotWidth); + iObj.BoxStyle(fvgBearishPivotStyle); + + // + mFVGBearishPivotObjects.Add(iObj); + } + + // + iBox.Clean(); + ZeroMemory(iObj); + } + } + } + } + } + } + + // + void DrawPeakSWHResPivots(datetime to = NULL) + { + // + if (!drawPeakSWHResPivots) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + + // + bool has = detector.HasPeakSWHResPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountPeakSWHResPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = detector.peakSWHResPivots[i].AsBox(iBox); + if (!has) + { + continue; + } + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxColor(peakPivotColor); + iObj.BoxWidth(peakPivotWidth); + iObj.BoxStyle(peakPivotStyle); + + // + mPeakSWHResPivotObjects.Add(iObj); + } + + // + iBox.Clean(); + } + } + + // + void DrawValeSWLSupPivots(datetime to = NULL) + { + // + if (!drawValeSWLSupPivots) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + + // + bool has = detector.HasValeSWLSupPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountValeSWLSupPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = detector.valeSWLSupPivots[i].AsBox(iBox); + if (!has) + { + continue; + } + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxColor(valePivotColor); + iObj.BoxWidth(valePivotWidth); + iObj.BoxStyle(valePivotStyle); + + // + mValeSWLSupPivotObjects.Add(iObj); + } + + // + iBox.Clean(); + } + } + + // + void DrawTKIBullishPivots(datetime to = NULL) + { + // + if (!drawTKIBullishPivots) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + + // + bool has = detector.HasTKIBullishPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountTKIBullishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = detector.tkiBullishPivots[i].AsBox(iBox); + if (!has) + { + continue; + } + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxColor(kiBullishPivotColor); + iObj.BoxWidth(kiBullishPivotWidth); + iObj.BoxStyle(kiBullishPivotStyle); + + // + mTKIBullishPivotObjects.Add(iObj); + } + + // + iBox.Clean(); + } + } + + // + void DrawTKIBearishPivots(datetime to = NULL) + { + // + if (!drawTKIBearishPivots) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + + // + bool has = detector.HasTKIBearishPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountTKIBearishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = detector.tkiBearishPivots[i].AsBox(iBox); + if (!has) + { + continue; + } + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxColor(kiBearishPivotColor); + iObj.BoxWidth(kiBearishPivotWidth); + iObj.BoxStyle(kiBearishPivotStyle); + + // + mTKIBearishPivotObjects.Add(iObj); + } + + // + iBox.Clean(); + } + } + + // + void DrawTrendBullishPivots(datetime to = NULL) + { + // + if (!drawTrendBullishPivots) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + + // + bool has = detector.HasTrendBullishPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountTrendBullishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = detector.trendBullishPivots[i].AsBox(iBox); + if (!has) + { + continue; + } + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxColor(trendBullishPivotColor); + iObj.BoxWidth(trendBullishPivotWidth); + iObj.BoxStyle(trendBullishPivotStyle); + + // + mTrendBullishPivotObjects.Add(iObj); + } + + // + iBox.Clean(); + } + } + + // + void DrawTrendBearishPivots(datetime to = NULL) + { + // + if (!drawTrendBearishPivots) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + + // + bool has = detector.HasTrendBearishPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountTrendBearishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = detector.trendBearishPivots[i].AsBox(iBox); + if (!has) + { + continue; + } + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxColor(trendBearishPivotColor); + iObj.BoxWidth(trendBearishPivotWidth); + iObj.BoxStyle(trendBearishPivotStyle); + + // + mTrendBearishPivotObjects.Add(iObj); + } + + // + iBox.Clean(); + } + } + + // + void DrawTKITRNDBullishPivots(datetime to = NULL) + { + // + if (!drawTKITRNDBullishPivots) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + + // + bool has = detector.HasTKITRNDBullishPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountTKITRNDBullishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = detector.tkitrndBullishPivots[i].AsBox(iBox); + if (!has) + { + continue; + } + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxColor(trendBullishPivotColor); + iObj.BoxWidth(trendBullishPivotWidth); + iObj.BoxStyle(trendBullishPivotStyle); + + // + mTKITRNDBullishPivotObjects.Add(iObj); + } + + // + iBox.Clean(); + } + } + + // + void DrawTKITRNDBearishPivots(datetime to = NULL) + { + // + if (!drawTKITRNDBearishPivots) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + + // + bool has = detector.HasTKITRNDBearishPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountTKITRNDBearishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = detector.tkitrndBearishPivots[i].AsBox(iBox); + if (!has) + { + continue; + } + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxColor(trendBearishPivotColor); + iObj.BoxWidth(trendBearishPivotWidth); + iObj.BoxStyle(trendBearishPivotStyle); + + // + mTKITRNDBearishPivotObjects.Add(iObj); + } + + // + iBox.Clean(); + } + } + + // + void DrawCycleSameLLPivots(datetime to = NULL) + { + // + if (!drawCycleSameLLPivots) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + + // + int count = 0; + + // + // SHORT ... + bool has = detector.HasSSameLLPivots(); + if (has) + { + // + count = detector.CountSSameLLPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = detector.sSameLLPivots[i].AsBox(iBox); + if (!has) + { + continue; + } + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxColor(sameLLPivotColor); + iObj.BoxWidth(sameLLPivotWidth); + iObj.BoxStyle(sameLLPivotStyle); + + // + mCycleSameLLPivotObjects.Add(iObj); + } + + // + iBox.Clean(); + } + } + + // + // MEDIUM ... + has = detector.HasMSameLLPivots(); + if (has) + { + // + count = detector.CountMSameLLPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = detector.mSameLLPivots[i].AsBox(iBox); + if (!has) + { + continue; + } + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxColor(sameLLPivotColor); + iObj.BoxWidth(sameLLPivotWidth); + iObj.BoxStyle(sameLLPivotStyle); + + // + mCycleSameLLPivotObjects.Add(iObj); + } + + // + iBox.Clean(); + } + } + + // + // LONG ... + has = detector.HasLSameLLPivots(); + if (has) + { + // + count = detector.CountLSameLLPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = detector.lSameLLPivots[i].AsBox(iBox); + if (!has) + { + continue; + } + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxColor(sameLLPivotColor); + iObj.BoxWidth(sameLLPivotWidth); + iObj.BoxStyle(sameLLPivotStyle); + + // + mCycleSameLLPivotObjects.Add(iObj); + } + + // + iBox.Clean(); + } + } + + // + // HIND ... + has = detector.HasHSameLLPivots(); + if (has) + { + // + count = detector.CountHSameLLPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = detector.hSameLLPivots[i].AsBox(iBox); + if (!has) + { + continue; + } + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxColor(sameLLPivotColor); + iObj.BoxWidth(sameLLPivotWidth); + iObj.BoxStyle(sameLLPivotStyle); + + // + mCycleSameLLPivotObjects.Add(iObj); + } + + // + iBox.Clean(); + } + } + } + + // + void DrawCycleSameHHPivots(datetime to = NULL) + { + // + if (!drawCycleSameHHPivots) + { + return; + } + + // + bool canUpdateTo = IsValid(to); + + // + int count = 0; + + // + // SHORT ... + bool has = detector.HasSSameHHPivots(); + if (has) + { + // + count = detector.CountSSameHHPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = detector.sSameHHPivots[i].AsBox(iBox); + if (!has) + { + continue; + } + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxColor(sameHHPivotColor); + iObj.BoxWidth(sameHHPivotWidth); + iObj.BoxStyle(sameHHPivotStyle); + + // + mCycleSameHHPivotObjects.Add(iObj); + } + + // + iBox.Clean(); + } + } + + // + // MEDIUM ... + has = detector.HasMSameHHPivots(); + if (has) + { + // + count = detector.CountMSameHHPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = detector.mSameHHPivots[i].AsBox(iBox); + if (!has) + { + continue; + } + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxColor(sameHHPivotColor); + iObj.BoxWidth(sameHHPivotWidth); + iObj.BoxStyle(sameHHPivotStyle); + + // + mCycleSameHHPivotObjects.Add(iObj); + } + + // + iBox.Clean(); + } + } + + // + // LONG ... + has = detector.HasLSameHHPivots(); + if (has) + { + // + count = detector.CountLSameHHPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = detector.lSameHHPivots[i].AsBox(iBox); + if (!has) + { + continue; + } + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxColor(sameHHPivotColor); + iObj.BoxWidth(sameHHPivotWidth); + iObj.BoxStyle(sameHHPivotStyle); + + // + mCycleSameHHPivotObjects.Add(iObj); + } + + // + iBox.Clean(); + } + } + + // + // HIND ... + has = detector.HasHSameHHPivots(); + if (has) + { + // + count = detector.CountHSameHHPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = detector.hSameHHPivots[i].AsBox(iBox); + if (!has) + { + continue; + } + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxColor(sameHHPivotColor); + iObj.BoxWidth(sameHHPivotWidth); + iObj.BoxStyle(sameHHPivotStyle); + + // + mCycleSameHHPivotObjects.Add(iObj); + } + + // + iBox.Clean(); + } + } + } + + // + void DrawRSIPeakPivots(datetime to = NULL) + { + // + if (!drawRSIPeakPivots) + { + return; + } + + // + to = NULL; + bool canUpdateTo = IsValid(to); + + // + int count = 0; + bool has = detector.HasRSIPeakPivots(); + if (has) + { + // + count = detector.CountRSIPeakPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = detector.rsiPeakPivots[i].AsBox(iBox); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxColor(oscsBearishPivotColor); + iObj.BoxWidth(oscsBearishPivotWidth); + iObj.BoxStyle(oscsBearishPivotStyle); + + // + mRSIPeakPivotObjects.Add(iObj); + } + + // + iBox.Clean(); + } + } + } + + // + void DrawRSIValePivots(datetime to = NULL) + { + // + if (!drawRSIValePivots) + { + return; + } + + // + to = NULL; + bool canUpdateTo = IsValid(to); + + // + int count = 0; + bool has = detector.HasRSIValePivots(); + if (has) + { + // + count = detector.CountRSIValePivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = detector.rsiValePivots[i].AsBox(iBox); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxColor(oscsBullishPivotColor); + iObj.BoxWidth(oscsBullishPivotWidth); + iObj.BoxStyle(oscsBullishPivotStyle); + + // + mRSIValePivotObjects.Add(iObj); + } + + // + iBox.Clean(); + } + } + } + + // + void DrawRSICrossedOverOSPivots(datetime to = NULL) + { + // + if (!drawRSICrossedOverOSPivots) + { + return; + } + + // + to = NULL; + bool canUpdateTo = IsValid(to); + + // + int count = 0; + bool has = detector.HasRSICrossedOverOSPivots(); + if (has) + { + // + count = detector.CountRSICrossedOverOSPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = detector.rsiCrossedOverOSPivots[i].AsBox(iBox); + if (!has) + { + continue; + } + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxColor(oscsBullishPivotColor); + iObj.BoxWidth(oscsBullishPivotWidth); + iObj.BoxStyle(oscsBullishPivotStyle); + + // + mRSICrossedOverOSPivotObjects.Add(iObj); + } + + // + iBox.Clean(); + } + } + } + + // + void DrawRSICrossedUnderOBPivots(datetime to = NULL) + { + // + if (!drawRSICrossedUnderOBPivots) + { + return; + } + + // + to = NULL; + bool canUpdateTo = IsValid(to); + + // + int count = 0; + bool has = detector.HasRSICrossedUnderOBPivots(); + if (has) + { + // + count = detector.CountRSICrossedUnderOBPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = detector.rsiCrossedUnderOBPivots[i].AsBox(iBox); + if (!has) + { + continue; + } + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxColor(oscsBearishPivotColor); + iObj.BoxWidth(oscsBearishPivotWidth); + iObj.BoxStyle(oscsBearishPivotStyle); + + // + mRSICrossedUnderOBPivotObjects.Add(iObj); + } + + // + iBox.Clean(); + } + } + } + + // + void DrawCCIPeakPivots(datetime to = NULL) + { + // + if (!drawCCIPeakPivots) + { + return; + } + + // + to = NULL; + bool canUpdateTo = IsValid(to); + + // + int count = 0; + bool has = detector.HasCCIPeakPivots(); + if (has) + { + // + count = detector.CountCCIPeakPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = detector.cciPeakPivots[i].AsBox(iBox); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxColor(oscsBearishPivotColor); + iObj.BoxWidth(oscsBearishPivotWidth); + iObj.BoxStyle(oscsBearishPivotStyle); + + // + mCCIPeakPivotObjects.Add(iObj); + } + + // + iBox.Clean(); + } + } + } + + // + void DrawCCIValePivots(datetime to = NULL) + { + // + if (!drawCCIValePivots) + { + return; + } + + // + to = NULL; + bool canUpdateTo = IsValid(to); + + // + int count = 0; + bool has = detector.HasCCIValePivots(); + if (has) + { + // + count = detector.CountCCIValePivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = detector.cciValePivots[i].AsBox(iBox); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxColor(oscsBullishPivotColor); + iObj.BoxWidth(oscsBullishPivotWidth); + iObj.BoxStyle(oscsBullishPivotStyle); + + // + mCCIValePivotObjects.Add(iObj); + } + + // + iBox.Clean(); + } + } + } + + // + void DrawCCICrossedOverOSPivots(datetime to = NULL) + { + // + if (!drawCCICrossedOverOSPivots) + { + return; + } + + // + to = NULL; + bool canUpdateTo = IsValid(to); + + // + int count = 0; + bool has = detector.HasCCICrossedOverOSPivots(); + if (has) + { + // + count = detector.CountCCICrossedOverOSPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = detector.cciCrossedOverOSPivots[i].AsBox(iBox); + if (!has) + { + continue; + } + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxColor(oscsBullishPivotColor); + iObj.BoxWidth(oscsBullishPivotWidth); + iObj.BoxStyle(oscsBullishPivotStyle); + + // + mCCICrossedOverOSPivotObjects.Add(iObj); + } + + // + iBox.Clean(); + } + } + } + + // + void DrawCCICrossedUnderOBPivots(datetime to = NULL) + { + // + if (!drawCCICrossedUnderOBPivots) + { + return; + } + + // + to = NULL; + bool canUpdateTo = IsValid(to); + + // + int count = 0; + bool has = detector.HasCCICrossedUnderOBPivots(); + if (has) + { + // + count = detector.CountCCICrossedUnderOBPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = detector.cciCrossedUnderOBPivots[i].AsBox(iBox); + if (!has) + { + continue; + } + + // + if (canUpdateTo) + { + iBox.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxColor(oscsBearishPivotColor); + iObj.BoxWidth(oscsBearishPivotWidth); + iObj.BoxStyle(oscsBearishPivotStyle); + + // + mCCICrossedUnderOBPivotObjects.Add(iObj); + } + + // + iBox.Clean(); + } + } + } + + // + // Protected ... + protected: + // + // Props ... + + // + // Prrivate ... + private: + // + // Props ... + + // + XCPOIDrawer *drawer; + XCXCAEAPOIDetector *detector; + + // + CArrayObj mSWHPivotObjects; + CArrayObj mSWLPivotObjects; + CArrayObj mPeakPivotObjects; + CArrayObj mValePivotObjects; + CArrayObj mRSIPeakPivotObjects; + CArrayObj mRSIValePivotObjects; + CArrayObj mCCIPeakPivotObjects; + CArrayObj mCCIValePivotObjects; + CArrayObj mKIBullishPivotObjects; + CArrayObj mKIBearishPivotObjects; + CArrayObj mFVGBullishPivotObjects; + CArrayObj mFVGBearishPivotObjects; + CArrayObj mPeakSWHResPivotObjects; + CArrayObj mValeSWLSupPivotObjects; + CArrayObj mTKIBullishPivotObjects; + CArrayObj mTKIBearishPivotObjects; + CArrayObj mCycleSameLLPivotObjects; + CArrayObj mCycleSameHHPivotObjects; + CArrayObj mTrendBullishPivotObjects; + CArrayObj mTrendBearishPivotObjects; + CArrayObj mTKITRNDBullishPivotObjects; + CArrayObj mTKITRNDBearishPivotObjects; + CArrayObj mRSICrossedOverOSPivotObjects; + CArrayObj mRSICrossedUnderOBPivotObjects; + CArrayObj mCCICrossedOverOSPivotObjects; + CArrayObj mCCICrossedUnderOBPivotObjects; + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14040218 XCAEA/Documents/Diagrams/Position Protection.drawio b/BKPS/14040218 XCAEA/Documents/Diagrams/Position Protection.drawio new file mode 100644 index 0000000..d425cb2 --- /dev/null +++ b/BKPS/14040218 XCAEA/Documents/Diagrams/Position Protection.drawio @@ -0,0 +1,279 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/BKPS/14040218 XCAEA/Documents/JsModules/x-color.tools.js b/BKPS/14040218 XCAEA/Documents/JsModules/x-color.tools.js new file mode 100644 index 0000000..c3ac5f9 --- /dev/null +++ b/BKPS/14040218 XCAEA/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/14040218 XCAEA/Documents/JsModules/x-file.tools.js b/BKPS/14040218 XCAEA/Documents/JsModules/x-file.tools.js new file mode 100644 index 0000000..2a3535d --- /dev/null +++ b/BKPS/14040218 XCAEA/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/14040218 XCAEA/Documents/JsModules/x-shell.tools.js b/BKPS/14040218 XCAEA/Documents/JsModules/x-shell.tools.js new file mode 100644 index 0000000..0ee13de --- /dev/null +++ b/BKPS/14040218 XCAEA/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/14040218 XCAEA/Documents/JsModules/x-type-detector.tools.js b/BKPS/14040218 XCAEA/Documents/JsModules/x-type-detector.tools.js new file mode 100644 index 0000000..86ed3d8 --- /dev/null +++ b/BKPS/14040218 XCAEA/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/14040218 XCAEA/Documents/JsModules/x-value.tools.js b/BKPS/14040218 XCAEA/Documents/JsModules/x-value.tools.js new file mode 100644 index 0000000..81cfcc4 --- /dev/null +++ b/BKPS/14040218 XCAEA/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/14040218 XCAEA/Documents/Temlates/signalling.function.template.mq5 b/BKPS/14040218 XCAEA/Documents/Temlates/signalling.function.template.mq5 new file mode 100644 index 0000000..3cbd45a --- /dev/null +++ b/BKPS/14040218 XCAEA/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/14040218 XCAEA/Documents/Temlates/temp.pivot.detect.mq5 b/BKPS/14040218 XCAEA/Documents/Temlates/temp.pivot.detect.mq5 new file mode 100644 index 0000000..2104084 --- /dev/null +++ b/BKPS/14040218 XCAEA/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/14040218 XCAEA/Documents/Temlates/x-saherelm.x-ea.template.ea.mq5 b/BKPS/14040218 XCAEA/Documents/Temlates/x-saherelm.x-ea.template.ea.mq5 new file mode 100644 index 0000000..ec3e257 --- /dev/null +++ b/BKPS/14040218 XCAEA/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.Alert(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.Alert(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.Alert(msg); + } + + // + // Weekly Report .... + if (eaReportNewWeeks && + eaTimeTracker.IsNewWeek()) + { + // + string msg = "New Week ..."; + + // + eaAlert.Alert(msg); + } + + // + // Daily Report .... + if (eaReportNewDays && + eaTimeTracker.IsNewDay()) + { + // + string msg = "New Day ..."; + + // + eaAlert.Alert(msg); + } + + // + // Hourly Report .... + if (eaReportNewHours && + eaTimeTracker.IsNewHour()) + { + // + string msg = "New Hour ..."; + + // + eaAlert.Alert(msg); + } +} + +// diff --git a/BKPS/14040218 XCAEA/Documents/Temlates/x-saherelm.x-panel.ea.mq5 b/BKPS/14040218 XCAEA/Documents/Temlates/x-saherelm.x-panel.ea.mq5 new file mode 100644 index 0000000..c04228d --- /dev/null +++ b/BKPS/14040218 XCAEA/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.Alert(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.Alert(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.Alert(msg); + } + + // + // Weekly Report .... + if (eaReportNewWeeks && + eaTimeTracker.IsNewWeek()) + { + // + string msg = "New Week ..."; + + // + eaAlert.Alert(msg); + } + + // + // Daily Report .... + if (eaReportNewDays && + eaTimeTracker.IsNewDay()) + { + // + string msg = "New Day ..."; + + // + eaAlert.Alert(msg); + } + + // + // Hourly Report .... + if (eaReportNewHours && + eaTimeTracker.IsNewHour()) + { + // + string msg = "New Hour ..."; + + // + eaAlert.Alert(msg); + } +} + +// diff --git a/BKPS/14040218 XCAEA/Documents/Temlates/xwz.signal.senario.template.mq5 b/BKPS/14040218 XCAEA/Documents/Temlates/xwz.signal.senario.template.mq5 new file mode 100644 index 0000000..f9f6052 --- /dev/null +++ b/BKPS/14040218 XCAEA/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/14040218 XCAEA/Experts/test.mq5 b/BKPS/14040218 XCAEA/Experts/test.mq5 new file mode 100644 index 0000000..d9cb3d3 --- /dev/null +++ b/BKPS/14040218 XCAEA/Experts/test.mq5 @@ -0,0 +1,816 @@ +//+------------------------------------------------------------------+ +//| X121_Strategy_EA.mq5 | +//| Copyright 2023, SaherElm IT | +//| https://saherelm.ir/ | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "EA based on X121 XCA and X3MA indicators" +#property strict + +// Include Common Library +#include "../Libraries/x-saherelm.common.lib.mq5" +#include + +// Indicator handles +int xcaHandle = INVALID_HANDLE; +int x3maHandle = INVALID_HANDLE; + +// Indicator buffers for XCA +double xcaTrendBuffer[]; +double xcaTrendColorBuffer[]; +double xcaKIBuffer[]; +double xcaKIColorBuffer[]; +double xcaVidyaBuffer[]; +double xcaVidyaColorBuffer[]; +double xcaSwingLowBuffer[]; +double xcaSwingHighBuffer[]; +double xcaSupportBuffer[]; +double xcaResistanceBuffer[]; +double xcaSLBuffer[]; // Short Cycle Low +double xcaSHBuffer[]; // Short Cycle High +double xcaMLBuffer[]; // Medium Cycle Low +double xcaMHBuffer[]; // Medium Cycle High +double xcaFiboLevel2Buffer[]; // 50% Fibo level + +// Indicator buffers for X3MA +double x3maFastBuffer[]; +double x3maFastColorBuffer[]; +double x3maMediumBuffer[]; +double x3maMediumColorBuffer[]; +double x3maSlowBuffer[]; +double x3maSlowColorBuffer[]; + +// Trade parameters +input group "Trade Settings" input double LotSize = 0.1; // Fixed Lot Size +input bool UseAutoLotSize = false; // Use Auto Lot Size +input double RiskPercent = 1.0; // Risk Percent (for Auto Lot) +input int StopLoss = 100; // Stop Loss in points +input int TakeProfit = 200; // Take Profit in points +input bool UseTrailingStop = true; // Use Trailing Stop +input int TrailingStop = 50; // Trailing Stop in points +input int TrailingStep = 10; // Trailing Step in points + +input group "Strategy Parameters" input bool UseSwingPoints = true; // Use Swing Points for Entry +input bool UseFiboLevels = true; // Use Fibonacci Levels +input bool UseMAAlignment = true; // Require All MAs Alignment +input bool UseKIConfirmation = true; // Require KI Confirmation +input bool UseVidyaConfirmation = true; // Require VIDYA Confirmation +input bool UseTrendConfirmation = true; // Require Trend Confirmation + +input group "Money Management" input bool UseMultipleTargets = true; // Use Multiple Profit Targets +input double Target1Percent = 33.0; // First Target Percentage +input double Target2Percent = 33.0; // Second Target Percentage +input double Target3Percent = 34.0; // Third Target Percentage + +input group "Time Filter" input bool UseTimeFilter = false; // Use Time Filter +input string StartTradeTime = "08:00"; // Start Trading Time (Server Time) +input string EndTradeTime = "16:00"; // End Trading Time (Server Time) + +// Global variables +int magicNumber = 12121; +bool isTradingAllowed = true; +datetime lastBarTime = 0; +int barsTotalPrev = 0; + +// Trade objects +CTrade trade; + +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() +{ + // Initialize trade object + trade.SetExpertMagicNumber(magicNumber); + + // Initialize XCA indicator + xcaHandle = iCustom(_Symbol, _Period, "x-saherelm.x121.xca"); + if (xcaHandle == INVALID_HANDLE) + { + Print("Failed to create handle of the XCA indicator"); + return (INIT_FAILED); + } + + // Initialize X3MA indicator + x3maHandle = iCustom(_Symbol, _Period, "x-saherelm.x121.x3ma"); + if (x3maHandle == INVALID_HANDLE) + { + Print("Failed to create handle of the X3MA indicator"); + return (INIT_FAILED); + } + + // Set up arrays as series + ArraySetAsSeries(xcaTrendBuffer, true); + ArraySetAsSeries(xcaTrendColorBuffer, true); + ArraySetAsSeries(xcaKIBuffer, true); + ArraySetAsSeries(xcaKIColorBuffer, true); + ArraySetAsSeries(xcaVidyaBuffer, true); + ArraySetAsSeries(xcaVidyaColorBuffer, true); + ArraySetAsSeries(xcaSwingLowBuffer, true); + ArraySetAsSeries(xcaSwingHighBuffer, true); + ArraySetAsSeries(xcaSupportBuffer, true); + ArraySetAsSeries(xcaResistanceBuffer, true); + ArraySetAsSeries(xcaSLBuffer, true); + ArraySetAsSeries(xcaSHBuffer, true); + ArraySetAsSeries(xcaMLBuffer, true); + ArraySetAsSeries(xcaMHBuffer, true); + ArraySetAsSeries(xcaFiboLevel2Buffer, true); + + ArraySetAsSeries(x3maFastBuffer, true); + ArraySetAsSeries(x3maFastColorBuffer, true); + ArraySetAsSeries(x3maMediumBuffer, true); + ArraySetAsSeries(x3maMediumColorBuffer, true); + ArraySetAsSeries(x3maSlowBuffer, true); + ArraySetAsSeries(x3maSlowColorBuffer, true); + + return (INIT_SUCCEEDED); +} + +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) +{ + // Release indicator handles + if (xcaHandle != INVALID_HANDLE) + IndicatorRelease(xcaHandle); + + if (x3maHandle != INVALID_HANDLE) + IndicatorRelease(x3maHandle); +} + +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() +{ + // Check if we're allowed to trade based on time filter + if (UseTimeFilter && !IsTradeTimeAllowed()) + return; + + // Get current bar time + datetime currentBarTime = iTime(_Symbol, _Period, 0); + + // Only process on new bar + if (currentBarTime == lastBarTime) + return; + + lastBarTime = currentBarTime; + + // Update indicator buffers + if (!UpdateIndicatorBuffers()) + return; + + // Check for open positions and manage them + ManageOpenPositions(); + + // Check for new trade signals + CheckForTradeSignals(); +} + +//+------------------------------------------------------------------+ +//| Update all indicator buffers | +//+------------------------------------------------------------------+ +bool UpdateIndicatorBuffers() +{ + // Copy XCA indicator buffers + if (CopyBuffer(xcaHandle, 18, 0, 3, xcaTrendBuffer) < 3) + return false; + if (CopyBuffer(xcaHandle, 19, 0, 3, xcaTrendColorBuffer) < 3) + return false; + if (CopyBuffer(xcaHandle, 20, 0, 3, xcaKIBuffer) < 3) + return false; + if (CopyBuffer(xcaHandle, 21, 0, 3, xcaKIColorBuffer) < 3) + return false; + if (CopyBuffer(xcaHandle, 26, 0, 3, xcaVidyaBuffer) < 3) + return false; + if (CopyBuffer(xcaHandle, 27, 0, 3, xcaVidyaColorBuffer) < 3) + return false; + if (CopyBuffer(xcaHandle, 22, 0, 3, xcaSwingLowBuffer) < 3) + return false; + if (CopyBuffer(xcaHandle, 23, 0, 3, xcaSwingHighBuffer) < 3) + return false; + if (CopyBuffer(xcaHandle, 8, 0, 3, xcaSupportBuffer) < 3) + return false; + if (CopyBuffer(xcaHandle, 9, 0, 3, xcaResistanceBuffer) < 3) + return false; + if (CopyBuffer(xcaHandle, 0, 0, 3, xcaSHBuffer) < 3) + return false; + if (CopyBuffer(xcaHandle, 1, 0, 3, xcaSLBuffer) < 3) + return false; + if (CopyBuffer(xcaHandle, 2, 0, 3, xcaMHBuffer) < 3) + return false; + if (CopyBuffer(xcaHandle, 3, 0, 3, xcaMLBuffer) < 3) + return false; + if (CopyBuffer(xcaHandle, 15, 0, 3, xcaFiboLevel2Buffer) < 3) + return false; + + // Copy X3MA indicator buffers + if (CopyBuffer(x3maHandle, 0, 0, 3, x3maFastBuffer) < 3) + return false; + if (CopyBuffer(x3maHandle, 1, 0, 3, x3maFastColorBuffer) < 3) + return false; + if (CopyBuffer(x3maHandle, 2, 0, 3, x3maMediumBuffer) < 3) + return false; + if (CopyBuffer(x3maHandle, 3, 0, 3, x3maMediumColorBuffer) < 3) + return false; + if (CopyBuffer(x3maHandle, 4, 0, 3, x3maSlowBuffer) < 3) + return false; + if (CopyBuffer(x3maHandle, 5, 0, 3, x3maSlowColorBuffer) < 3) + return false; + + return true; +} + +//+------------------------------------------------------------------+ +//| Check if current time is within allowed trading hours | +//+------------------------------------------------------------------+ +bool IsTradeTimeAllowed() +{ + // If time filter is not enabled, always allow trading + if (!UseTimeFilter) + return true; + + // Get current server time + datetime serverTime = TimeCurrent(); + MqlDateTime currentTime; + TimeToStruct(serverTime, currentTime); + + // Convert start and end time strings to hours and minutes + int startHour = 0, startMinute = 0; + int endHour = 0, endMinute = 0; + + // Parse start time + string startTimeParts[]; + if (StringSplit(StartTradeTime, ':', startTimeParts) == 2) + { + startHour = (int)StringToInteger(startTimeParts[0]); + startMinute = (int)StringToInteger(startTimeParts[1]); + } + + // Parse end time + string endTimeParts[]; + if (StringSplit(EndTradeTime, ':', endTimeParts) == 2) + { + endHour = (int)StringToInteger(endTimeParts[0]); + endMinute = (int)StringToInteger(endTimeParts[1]); + } + + // Convert current time, start time and end time to minutes for easy comparison + int currentTimeInMinutes = currentTime.hour * 60 + currentTime.min; + int startTimeInMinutes = startHour * 60 + startMinute; + int endTimeInMinutes = endHour * 60 + endMinute; + + // Check if current time is within trading hours + bool isAllowed = false; + + // If end time is greater than start time (same day trading session) + if (endTimeInMinutes > startTimeInMinutes) + { + isAllowed = (currentTimeInMinutes >= startTimeInMinutes && + currentTimeInMinutes <= endTimeInMinutes); + } + // If end time is less than start time (overnight trading session) + else if (endTimeInMinutes < startTimeInMinutes) + { + isAllowed = (currentTimeInMinutes >= startTimeInMinutes || + currentTimeInMinutes <= endTimeInMinutes); + } + // If start time equals end time (24-hour trading) + else + { + isAllowed = true; + } + + return isAllowed; +} + +//+------------------------------------------------------------------+ +//| Check for new trade signals | +//+------------------------------------------------------------------+ +void CheckForTradeSignals() +{ + // Don't open new trades if we already have open positions + if (CountOpenPositions() > 0) + return; + + // Check for buy signal + if (IsBuySignal()) + { + OpenBuyPosition(); + } + // Check for sell signal + else if (IsSellSignal()) + { + OpenSellPosition(); + } +} + +//+------------------------------------------------------------------+ +//| Check if we have a valid buy signal | +//+------------------------------------------------------------------+ +bool IsBuySignal() +{ + // 1. Trend Confirmation + bool trendConfirmation = true; + if (UseTrendConfirmation) + { + // X3MA: Fast MA crosses above Medium MA + bool fastCrossingAboveMedium = x3maFastBuffer[1] <= x3maMediumBuffer[1] && + x3maFastBuffer[0] > x3maMediumBuffer[0]; + + // X3MA: All three MAs are in bullish alignment + bool maAlignment = true; + if (UseMAAlignment) + { + maAlignment = x3maFastBuffer[0] > x3maMediumBuffer[0] && + x3maMediumBuffer[0] > x3maSlowBuffer[0]; + } + + // XCA: VIDYA line shows bullish color + bool vidyaBullish = true; + if (UseVidyaConfirmation) + { + vidyaBullish = xcaVidyaColorBuffer[0] == 1; // 1 is bullish color index + } + + // XCA: Trend line shows bullish color + bool trendBullish = xcaTrendColorBuffer[0] == 1; // 1 is bullish color index + + trendConfirmation = (fastCrossingAboveMedium || maAlignment) && + (vidyaBullish || !UseVidyaConfirmation) && + trendBullish; + } + + // 2. Cycle Analysis + bool cycleAnalysis = true; + { + // XCA: Price is above the Short Cycle low + double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID); + bool priceAboveSL = currentPrice > xcaSLBuffer[0]; + + // XCA: Medium Cycle is in uptrend phase + bool mediumCycleUptrend = xcaMLBuffer[0] > xcaMLBuffer[1]; + + // XCA: Support level is established and holding + bool supportHolding = currentPrice > xcaSupportBuffer[0]; + + cycleAnalysis = priceAboveSL && mediumCycleUptrend && supportHolding; + } + + // 3. Entry Timing + bool entryTiming = true; + { + // XCA: A swing low is identified + bool swingLowFound = UseSwingPoints ? xcaSwingLowBuffer[0] != 0 : true; + + // XCA: Price is near but above the Fibonacci level 2 (50% retracement) + bool nearFiboLevel = true; + if (UseFiboLevels) + { + double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID); + double fiboLevel = xcaFiboLevel2Buffer[0]; + double priceDiff = MathAbs(currentPrice - fiboLevel); + double priceRange = xcaResistanceBuffer[0] - xcaSupportBuffer[0]; + nearFiboLevel = priceDiff < priceRange * 0.1 && currentPrice > fiboLevel; + } + + // XCA: KI line shows bullish color + bool kiBullish = true; + if (UseKIConfirmation) + { + kiBullish = xcaKIColorBuffer[0] == 1; // 1 is bullish color index + } + + entryTiming = swingLowFound && (nearFiboLevel || !UseFiboLevels) && + (kiBullish || !UseKIConfirmation); + } + + return trendConfirmation && cycleAnalysis && entryTiming; +} + +//+------------------------------------------------------------------+ +//| Check if we have a valid sell signal | +//+------------------------------------------------------------------+ +bool IsSellSignal() +{ + // 1. Trend Confirmation + bool trendConfirmation = true; + if (UseTrendConfirmation) + { + // X3MA: Fast MA crosses below Medium MA + bool fastCrossingBelowMedium = x3maFastBuffer[1] >= x3maMediumBuffer[1] && + x3maFastBuffer[0] < x3maMediumBuffer[0]; + + // X3MA: All three MAs are in bearish alignment + bool maAlignment = true; + if (UseMAAlignment) + { + maAlignment = x3maFastBuffer[0] < x3maMediumBuffer[0] && + x3maMediumBuffer[0] < x3maSlowBuffer[0]; + } + + // XCA: VIDYA line shows bearish color + bool vidyaBearish = true; + if (UseVidyaConfirmation) + { + vidyaBearish = xcaVidyaColorBuffer[0] == 2; // 2 is bearish color index + } + + // XCA: Trend line shows bearish color + bool trendBearish = xcaTrendColorBuffer[0] == 2; // 2 is bearish color index + + trendConfirmation = (fastCrossingBelowMedium || maAlignment) && + (vidyaBearish || !UseVidyaConfirmation) && + trendBearish; + } + + // 2. Cycle Analysis + bool cycleAnalysis = true; + { + // XCA: Price is below the Short Cycle high + double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK); + bool priceBelowSH = currentPrice < xcaSHBuffer[0]; + + // XCA: Medium Cycle is in downtrend phase + bool mediumCycleDowntrend = xcaMHBuffer[0] < xcaMHBuffer[1]; + + // XCA: Resistance level is established and holding + bool resistanceHolding = currentPrice < xcaResistanceBuffer[0]; + + cycleAnalysis = priceBelowSH && mediumCycleDowntrend && resistanceHolding; + } + + // 3. Entry Timing + bool entryTiming = true; + { + // XCA: A swing high is identified + bool swingHighFound = UseSwingPoints ? xcaSwingHighBuffer[0] != 0 : true; + + // XCA: Price is near but below the Fibonacci level 2 (50% retracement) + bool nearFiboLevel = true; + if (UseFiboLevels) + { + double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK); + double fiboLevel = xcaFiboLevel2Buffer[0]; + double priceDiff = MathAbs(currentPrice - fiboLevel); + double priceRange = xcaResistanceBuffer[0] - xcaSupportBuffer[0]; + nearFiboLevel = priceDiff < priceRange * 0.1 && currentPrice < fiboLevel; + } + + // XCA: KI line shows bearish color + bool kiBearish = true; + if (UseKIConfirmation) + { + kiBearish = xcaKIColorBuffer[0] == 2; // 2 is bearish color index + } + + entryTiming = swingHighFound && (nearFiboLevel || !UseFiboLevels) && + (kiBearish || !UseKIConfirmation); + } + + return trendConfirmation && cycleAnalysis && entryTiming; +} + +//+------------------------------------------------------------------+ +//| Count open positions with our magic number | +//+------------------------------------------------------------------+ +int CountOpenPositions() +{ + int count = 0; + int total = PositionsTotal(); + + for (int i = 0; i < total; i++) + { + ulong ticket = PositionGetTicket(i); + if (ticket <= 0) + continue; + + // Check if position belongs to current symbol and our EA + if (PositionGetString(POSITION_SYMBOL) == _Symbol && + PositionGetInteger(POSITION_MAGIC) == magicNumber) + { + count++; + } + } + + return count; +} + +//+------------------------------------------------------------------+ +//| Manage open positions (trailing stops, partial closes) | +//+------------------------------------------------------------------+ +void ManageOpenPositions() +{ + int total = PositionsTotal(); + + // Loop through all open positions + for (int i = total - 1; i >= 0; i--) + { + ulong ticket = PositionGetTicket(i); + if (ticket <= 0) + continue; + + // Check if position belongs to current symbol and our EA + if (PositionGetString(POSITION_SYMBOL) != _Symbol || + PositionGetInteger(POSITION_MAGIC) != magicNumber) + continue; + + // Get position details + double openPrice = PositionGetDouble(POSITION_PRICE_OPEN); + double currentPrice = PositionGetDouble(POSITION_PRICE_CURRENT); + double stopLoss = PositionGetDouble(POSITION_SL); + double takeProfit = PositionGetDouble(POSITION_TP); + double positionVolume = PositionGetDouble(POSITION_VOLUME); + ENUM_POSITION_TYPE positionType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); + + // Check for exit signals + bool exitSignal = false; + + // For BUY positions + if (positionType == POSITION_TYPE_BUY) + { + // Exit if Fast MA crosses below Medium MA + if (x3maFastBuffer[1] > x3maMediumBuffer[1] && x3maFastBuffer[0] <= x3maMediumBuffer[0]) + exitSignal = true; + + // Apply trailing stop if enabled + if (UseTrailingStop && !exitSignal) + { + // Calculate new stop loss level + double newStopLoss = 0; + + // Use the most recent swing low as trailing stop if available + if (xcaSwingLowBuffer[0] > 0 && xcaSwingLowBuffer[0] < currentPrice) + { + newStopLoss = xcaSwingLowBuffer[0] - 5 * _Point; + } + else + { + // Traditional trailing stop + double trailingLevel = currentPrice - TrailingStop * _Point; + if (trailingLevel > stopLoss + TrailingStep * _Point) + newStopLoss = trailingLevel; + } + + // Update stop loss if we have a better level + if (newStopLoss > stopLoss && newStopLoss > 0) + { + trade.PositionModify(ticket, newStopLoss, takeProfit); + Print("Updated BUY trailing stop to: ", newStopLoss); + } + } + + // Handle multiple targets + if (UseMultipleTargets && positionVolume > LotSize * 0.5) + { + // First target: When price reaches resistance or initial TP + if (currentPrice >= xcaResistanceBuffer[0] && xcaResistanceBuffer[0] > openPrice) + { + double closeVolume = NormalizeDouble(positionVolume * Target1Percent / 100, 2); + if (closeVolume > 0) + { + trade.PositionClosePartial(ticket, closeVolume); + Print("First target reached for BUY position. Partially closed: ", closeVolume); + } + } + + // Second target: When price reaches Fibonacci level 3 (76.4%) + double fiboLevel3Buffer[]; + ArraySetAsSeries(fiboLevel3Buffer, true); + if (CopyBuffer(xcaHandle, 16, 0, 1, fiboLevel3Buffer) > 0) + { + double fiboLevel3 = fiboLevel3Buffer[0]; + if (fiboLevel3 > 0 && currentPrice >= fiboLevel3 && fiboLevel3 > openPrice) + { + double closeVolume = NormalizeDouble(positionVolume * Target2Percent / 100, 2); + if (closeVolume > 0) + { + trade.PositionClosePartial(ticket, closeVolume); + Print("Second target reached for BUY position. Partially closed: ", closeVolume); + } + } + } + } + } + // For SELL positions + else if (positionType == POSITION_TYPE_SELL) + { + // Exit if Fast MA crosses above Medium MA + if (x3maFastBuffer[1] < x3maMediumBuffer[1] && x3maFastBuffer[0] >= x3maMediumBuffer[0]) + exitSignal = true; + + // Apply trailing stop if enabled + if (UseTrailingStop && !exitSignal) + { + // Calculate new stop loss level + double newStopLoss = 0; + + // Use the most recent swing high as trailing stop if available + if (xcaSwingHighBuffer[0] > 0 && xcaSwingHighBuffer[0] > currentPrice) + { + newStopLoss = xcaSwingHighBuffer[0] + 5 * _Point; + } + else + { + // Traditional trailing stop + double trailingLevel = currentPrice + TrailingStop * _Point; + if (trailingLevel < stopLoss - TrailingStep * _Point || stopLoss == 0) + newStopLoss = trailingLevel; + } + + // Update stop loss if we have a better level + if ((newStopLoss < stopLoss || stopLoss == 0) && newStopLoss > 0) + { + trade.PositionModify(ticket, newStopLoss, takeProfit); + Print("Updated SELL trailing stop to: ", newStopLoss); + } + } + + // Handle multiple targets + if (UseMultipleTargets && positionVolume > LotSize * 0.5) + { + // First target: When price reaches support or initial TP + if (currentPrice <= xcaSupportBuffer[0] && xcaSupportBuffer[0] < openPrice) + { + double closeVolume = NormalizeDouble(positionVolume * Target1Percent / 100, 2); + if (closeVolume > 0) + { + trade.PositionClosePartial(ticket, closeVolume); + Print("First target reached for SELL position. Partially closed: ", closeVolume); + } + } + + // Second target: When price reaches Fibonacci level 3 (76.4%) + double fiboLevel3Buffer[]; + ArraySetAsSeries(fiboLevel3Buffer, true); + if (CopyBuffer(xcaHandle, 16, 0, 1, fiboLevel3Buffer) > 0) + { + double fiboLevel3 = fiboLevel3Buffer[0]; + if (fiboLevel3 > 0 && currentPrice <= fiboLevel3 && fiboLevel3 < openPrice) + { + double closeVolume = NormalizeDouble(positionVolume * Target2Percent / 100, 2); + if (closeVolume > 0) + { + trade.PositionClosePartial(ticket, closeVolume); + Print("Second target reached for SELL position. Partially closed: ", closeVolume); + } + } + } + } + } + + // Close position if exit signal is triggered + if (exitSignal) + { + trade.PositionClose(ticket); + Print("Exit signal triggered. Position closed."); + } + } +} + +//+------------------------------------------------------------------+ +//| Open a buy position with proper risk management | +//+------------------------------------------------------------------+ +void OpenBuyPosition() +{ + double entryPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK); + double stopLossPrice = 0; + double takeProfitPrice = 0; + + // Calculate stop loss price + if (StopLoss > 0) + { + // Use either the specified stop loss or the swing low, whichever is closer + double swingLowPrice = xcaSwingLowBuffer[0]; + double slByPoints = entryPrice - StopLoss * _Point; + + // If we have a valid swing low and it's not too far + if (swingLowPrice > 0 && entryPrice - swingLowPrice < StopLoss * 2 * _Point) + stopLossPrice = swingLowPrice - 5 * _Point; // Place SL slightly below swing low + else + stopLossPrice = slByPoints; + } + + // Calculate take profit price + if (TakeProfit > 0) + { + // If using multiple targets, we'll set the first one here and manage the rest in position management + if (UseMultipleTargets) + { + // Use resistance level as first target if available + if (xcaResistanceBuffer[0] > entryPrice) + takeProfitPrice = xcaResistanceBuffer[0]; + else + takeProfitPrice = entryPrice + TakeProfit * _Point; + } + else + { + takeProfitPrice = entryPrice + TakeProfit * _Point; + } + } + + // Calculate position size + double volume = LotSize; + if (UseAutoLotSize && stopLossPrice > 0) + { + double riskAmount = AccountInfoDouble(ACCOUNT_BALANCE) * RiskPercent / 100; + double pipValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE) * + (SymbolInfoDouble(_Symbol, SYMBOL_POINT) / SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE)); + double pipDistance = MathAbs(entryPrice - stopLossPrice) / SymbolInfoDouble(_Symbol, SYMBOL_POINT); + + if (pipDistance > 0 && pipValue > 0) + volume = NormalizeDouble(riskAmount / (pipDistance * pipValue), 2); + + // Ensure volume is within allowed limits + double minVolume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN); + double maxVolume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX); + double volumeStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP); + + volume = MathMax(minVolume, MathMin(maxVolume, volume)); + volume = NormalizeDouble(volume / volumeStep, 0) * volumeStep; + } + + // Execute the trade + trade.Buy(volume, _Symbol, 0, stopLossPrice, takeProfitPrice, "X121 Strategy Buy"); + + // Log the trade + Print("BUY Signal: Opening position at ", entryPrice, + ", SL: ", stopLossPrice, + ", TP: ", takeProfitPrice, + ", Volume: ", volume); +} + +//+------------------------------------------------------------------+ +//| Open a sell position with proper risk management | +//+------------------------------------------------------------------+ +void OpenSellPosition() +{ + double entryPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID); + double stopLossPrice = 0; + double takeProfitPrice = 0; + + // Calculate stop loss price + if (StopLoss > 0) + { + // Use either the specified stop loss or the swing high, whichever is closer + double swingHighPrice = xcaSwingHighBuffer[0]; + double slByPoints = entryPrice + StopLoss * _Point; + + // If we have a valid swing high and it's not too far + if (swingHighPrice > 0 && swingHighPrice - entryPrice < StopLoss * 2 * _Point) + stopLossPrice = swingHighPrice + 5 * _Point; // Place SL slightly above swing high + else + stopLossPrice = slByPoints; + } + + // Calculate take profit price + if (TakeProfit > 0) + { + // If using multiple targets, we'll set the first one here and manage the rest in position management + if (UseMultipleTargets) + { + // Use support level as first target if available + if (xcaSupportBuffer[0] > 0 && xcaSupportBuffer[0] < entryPrice) + takeProfitPrice = xcaSupportBuffer[0]; + else + takeProfitPrice = entryPrice - TakeProfit * _Point; + } + else + { + takeProfitPrice = entryPrice - TakeProfit * _Point; + } + } + + // Calculate position size + double volume = LotSize; + if (UseAutoLotSize && stopLossPrice > 0) + { + double riskAmount = AccountInfoDouble(ACCOUNT_BALANCE) * RiskPercent / 100; + double pipValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE) * + (SymbolInfoDouble(_Symbol, SYMBOL_POINT) / SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE)); + double pipDistance = MathAbs(entryPrice - stopLossPrice) / SymbolInfoDouble(_Symbol, SYMBOL_POINT); + + if (pipDistance > 0 && pipValue > 0) + volume = NormalizeDouble(riskAmount / (pipDistance * pipValue), 2); + + // Ensure volume is within allowed limits + double minVolume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN); + double maxVolume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX); + double volumeStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP); + + volume = MathMax(minVolume, MathMin(maxVolume, volume)); + volume = NormalizeDouble(volume / volumeStep, 0) * volumeStep; + } + + // Execute the trade + trade.Sell(volume, _Symbol, 0, stopLossPrice, takeProfitPrice, "X121 Strategy Sell"); + + // Log the trade + Print("SELL Signal: Opening position at ", entryPrice, + ", SL: ", stopLossPrice, + ", TP: ", takeProfitPrice, + ", Volume: ", volume); +} diff --git a/BKPS/14040218 XCAEA/Experts/x-saherelm.rr.tools.mq5 b/BKPS/14040218 XCAEA/Experts/x-saherelm.rr.tools.mq5 new file mode 100644 index 0000000..3166105 --- /dev/null +++ b/BKPS/14040218 XCAEA/Experts/x-saherelm.rr.tools.mq5 @@ -0,0 +1,431 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center XTest MQL5 Expert Advisor +// ------------------------------------------------- +// Name: XRRToolsEA +// 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 XRRToolsEA" +#property strict + +// +#define ShortName "XRRTools" + +// +// Imports ... +#include "../Classes/x-saherelm.x-alert.class.mq5" +#include "../Classes/x-saherelm.x-rm.panel.class.mq5" +#include "../Classes/x-saherelm.x-trade.class.mq5" +#include "../Helpers/x-saherelm.x121.xcc.helper.mq5" +#include "../Helpers/x-saherelm.x121.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 + +// +// Define Local Variables ... + +// +string eaLogTag; // EA Log Prefix ... +XCAlert *eaAlert; // Alert Provider for Expert Adviser ... +XCTrade *eaTrader; // Trader of Expert Adviser ... +XCRMPanel eaMainWindow; // Main Window ... +XCX121XCTHelper *eaCTHelper; // Bar Timer Indicator Helper class ... +XCX121XCCHelper *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.Alert(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.Alert(msg); + + // + // Destroy all EA Requirements ... + DestroyEA(); +} + +// +// On Tick Handler ... +void OnTick() +{ + // + UpdateGUI(); +} + +// +// 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); +} + +// +// Custom Event Handlers ... + +/** + * Handle StopLoss Triggered Positions ... + * + * @param deal: XDeal ... + */ +void OnStopLossTriggered(const XDeal &deal) +{ +} + +/** + * Handle Take Profit Triggered Positions ... + * + * @param deal: XDeal ... + */ +void OnTakeProfitTriggered(const XDeal &deal) +{ +} + +/** + * 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 // +) +{ +} + +// +// 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 ... + 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/14040218 XCAEA/Experts/x-saherelm.xcaea.ea.mq5 b/BKPS/14040218 XCAEA/Experts/x-saherelm.xcaea.ea.mq5 new file mode 100644 index 0000000..31da270 --- /dev/null +++ b/BKPS/14040218 XCAEA/Experts/x-saherelm.xcaea.ea.mq5 @@ -0,0 +1,745 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center XCAEA MQL5 Expert Advisor +// ------------------------------------------------- +// Name: XCAEA +// Description: an Exper Advisor which used Panels +// +// 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 XCAEA EA" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.x-alert.class.mq5" +#include "../Classes/x-saherelm.x-trade.class.mq5" +#include "../Classes/x-saherelm.x-volume.class.mq5" +#include "../XCAEA/Classes/xcaea.x-trade.manager.class.mq5" +#include "../XCAEA/Signals/xcaea.signaller.class.mq5" + +// +#define ShortName "XCAEAEA" + +// +// Inputs ... + +// +// Common ... +input group "Common"; +input long eaMagicNumber = 78692110; // Magic Number +input int eaSlippage = 10; // Slippgae +input string eaLogSuffix = ""; // Log Suffix + +// +// 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 ... +input group "Management"; +input bool eaAllowTrade = true; // Allow Trade on Signals +input bool eaAllowLongs = true; // Allow Long Trades +input bool eaAllowShorts = true; // Allow Short Trades +input int eaMaxAllowedTradesPerDay = 3; // Max Allowed Trades per Day +input int eaMaxAllowedSLsPerDay = 2; // Max Allowed SL(s) per Day +input string eaSessionStartTime = ""; // Trade Start Time +input string eaSessionEndTime = ""; // Trade End Time +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 = 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 = 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 eaReportProtector = true; // Report Protector Actions +input bool eaReportAfterTradesBalance = true; // Report Balance after a Trade Finished + +// +// Variables, Instances ... +XCAlert *eaAlert; +XCTrade *eaTrade; +XSignal eaSignal; +XCVolume *eaVolume; +XTimeTracker eaTimeTracker; +XCXCAEASignaller *eaSignaller; +XCXCAEATradeManager *eaTradeManager; +XCAEAStrategyConditions eaConditions; + +// +string eaTag = ""; + +// +// 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; + } + + // + // Initial Requirements ... + InitRequirements(); + + // + // Initialize Volume Manger ... + if (!InitVolume()) + { + return INIT_FAILED; + } + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // eaSignaller.DeInit(); + + // + ZeroMemory(eaAlert); + ZeroMemory(eaTrade); + ZeroMemory(eaVolume); + ZeroMemory(eaSignaller); + + // + eaSignal.Clean(); + eaConditions.Clean(); + eaTimeTracker.Clean(); + + // + DestroyTimer(); +} + +// +// On Tick Handler ... +void OnTick() +{ + // + int idx = -1; + int count = 0; + bool has = false; + + // + HandleTimeReport(); + + // + // Handle Position Management / Protections ... + eaTradeManager.Manage(); + + // + eaSignal.Clean(); + eaConditions.Clean(); + + // + double r2r = 4; + string provider = "XCAEA"; + ENUM_POSITION_TYPE type = POSITION_TYPE_BUY; + ENUM_X_ORDER_MODES mode = X_ORDER_MODE_MARKET; + + // + bool hasLong = false; + bool hasShort = false; + + // + // Start Calculations ... + + // + // Retrieve Common Data ... + string symbol = eaSignaller.GetSymbol(); + ENUM_TIMEFRAMES period = eaSignaller.GetPeriod(); + + // + datetime cTime = TimeCurrent(); + + // + // Required Value For SL/TP Calculations ... + double points = GetPoints(symbol); + double pip = GetPipPrice(symbol); + double pip2 = 2 * pip; + + // + has = eaSignaller.DetectSignalSetup( + r2r, + 300 // Max Allowed SL Distance ... + ); + if (has) + { + // + count = eaSignaller + .AddConditionsIfNotExists(); + + // + eaSignaller.mConditions.Clean(); + } + + // + // Check Setuped Conditions Exists ... + count = ArraySize(eaSignaller.mConditionsCollection); + has = IsValidSize(count); + if (!has) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + has = eaSignaller + .DetectSignalTrigger(eaSignaller + .mConditionsCollection[i]); + + // + // If Triggered ... + if (has) + { + // + idx = i; + eaConditions = eaSignaller.mConditionsCollection[i]; + break; + } + + // + // Check Condition Validation ... + has = eaSignaller.mConditionsCollection[i].IsValid() && + eaSignaller.mConditionsCollection[i].IsSetuped(); + if (!has) + { + idx = i; + } + } + + // + // Remove Setuped Condition if provided IDX ... + has = IsValidIndex(idx); + if (has) + { + // + ArrayRemove( + eaSignaller.mConditionsCollection, + idx, + 1 // + ); + } + + // + // Check EA Conditions is Valid or not ... + has = eaConditions.IsSetuped() && + eaConditions.CanTrigger(); + if (!has) + { + // + eaConditions.Clean(); + return; + } + + // + // Setting Time to Conditions ... + eaConditions.time = cTime; + has = ToPositionType( + type, + eaConditions.type // + ); + if (!has) + { + // + eaSignal.Clean(); + eaConditions.Clean(); + + // + return; + } + + // + // Checking Trigger Direction ... + hasLong = eaConditions.HasBullishSignal(); + hasShort = eaConditions.HasBearishSignal(); + has = hasLong || + hasShort; + if (!has) + { + // + eaSignal.Clean(); + eaConditions.Clean(); + + // + return; + } + + // + // Preparing Signal ... + // + eaSignal.mode = mode; + eaSignal.type = type; + eaSignal.entry = GetEntry( + eaConditions.symbol, + eaConditions.dir // + ); + eaSignal.provider = provider; + eaSignal.sl = eaConditions.sl; + eaSignal.tp = eaConditions.tp; + eaSignal.volume = X_MIN_VOLUME; + eaSignal.time = eaConditions.time; + eaSignal.symbol = eaConditions.symbol; + eaSignal.period = eaConditions.period; + eaSignal.partialCloseOnTPLevel = eaConditions.partialCloseOnTPLevel; + eaSignal.partialCloseMultiplier = eaConditions.partialCloseMultiplier; + + // + Copy( + eaConditions.targets, + eaSignal.targets // + ); + + // + has = eaSignal.IsValid(); + if (!has) + { + // + eaSignal.Clean(); + eaConditions.Clean(); + return; + } + + // + // Handle Volume Management ... + double iVolume = eaVolume.CalculateVolume(eaSignal); + if (iVolume > X_MIN_VOLUME && + iVolume != eaSignal.volume) + { + eaSignal.volume = iVolume; + } + + // + // Draw Signal ... + + // + // Execute Signal ... + + // + has = eaTradeManager.Execute( + eaSignal, + eaConditions // + ); + + // + eaSignal.Clean(); + eaConditions.Clean(); +} + +// +// 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 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; + + // + // EA Alert ... + eaAlert = new XCAlert( + eaTag, + eaEnableAlerts, + eaLogAlerts, + eaTerminalAlerts, + eaMailAlerts, + eaPushAlerts // + ); + + // + // EA Trade ... + eaTrade = new XCTrade( + eaSlippage, + eaMagicNumber, + eaMaxAllowedSpread, + eaMaxAllowedPositions, + eaMaxAllowedDrawdownFactor // + ); + eaTrade.AddOnStopLossEventHandler(OnStopLossTriggered); + eaTrade.AddOnTakeProfitEventHandler(OnTakeProfitTriggered); + eaTrade.AddOnForceClosePositionEventHandler(OnPositionForceClosed); + + // + // EA Trae Manager ... + eaTradeManager = new XCXCAEATradeManager( + eaTrade // + ); + eaTradeManager.SaveTrades(true); + eaTradeManager.SetAlertEnableAlerts(eaEnableAlerts); + eaTradeManager.SetAlertPrefix(eaTag); + eaTradeManager.SetAlertLogAlerts(eaLogAlerts); + eaTradeManager.SetAlertMailAlerts(eaMailAlerts); + eaTradeManager.SetAlertPushAlerts(eaPushAlerts); + eaTradeManager.SetAlertTerminalAlerts(eaTerminalAlerts); + + // + // Setting Trade Reports ... + eaTradeManager + .SetTradeReports( + eaReportTrades, + eaReportSignals, + eaReportProtector, + eaReportAfterTradesBalance // + ); + + // + // Setting Trade Permissions ... + eaTradeManager + .SetTradePermissions( + eaAllowTrade, + eaAllowLongs, + eaAllowShorts // + ); + + // + // + // + // + // eaMaxAllowedTradesPerDay + // eaMaxAllowedSLsPerDay + // eaSessionStartTime + // eaSessionEndTime + + // + // EA Signaller ... + eaSignaller = new XCXCAEASignaller( + _Symbol, + _Period // + ); + + // +} + +/** + * Handling Time Reporting ... + */ +void HandleTimeReport() +{ + // + // Monthly Report .... + if (eaReportNewMonths && + eaTimeTracker.IsNewMonth()) + { + // + string msg = "New Month ..."; + + // + eaAlert.Alert(msg); + } + + // + // Weekly Report .... + if (eaReportNewWeeks && + eaTimeTracker.IsNewWeek()) + { + // + string msg = "New Week ..."; + + // + eaAlert.Alert(msg); + } + + // + // Daily Report .... + bool isNewDay = eaTimeTracker.IsNewDay(); + if (isNewDay) + { + // + // Handle New Day on Trade Manager ... + eaTradeManager.HandleNewDay(); + + // + // Reporting New Day if Reuired ... + if (eaReportNewDays) + { + // + string msg = "New Day ..."; + + // + eaAlert.Alert(msg); + } + } + + // + // Hourly Report .... + if (eaReportNewHours && + eaTimeTracker.IsNewHour()) + { + // + string msg = "New Hour ..."; + + // + eaAlert.Alert(msg); + } +} + +// diff --git a/BKPS/14040218 XCAEA/Helpers/x-saherelm.x121.x3ma.helper.mq5 b/BKPS/14040218 XCAEA/Helpers/x-saherelm.x121.x3ma.helper.mq5 new file mode 100644 index 0000000..ac54b46 --- /dev/null +++ b/BKPS/14040218 XCAEA/Helpers/x-saherelm.x121.x3ma.helper.mq5 @@ -0,0 +1,1546 @@ +/////////////////////////////////////////////////////// +// +// 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; + } + + // + // 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/14040218 XCAEA/Helpers/x-saherelm.x121.xca.helper.mq5 b/BKPS/14040218 XCAEA/Helpers/x-saherelm.x121.xca.helper.mq5 new file mode 100644 index 0000000..0687880 --- /dev/null +++ b/BKPS/14040218 XCAEA/Helpers/x-saherelm.x121.xca.helper.mq5 @@ -0,0 +1,5245 @@ +/////////////////////////////////////////////////////// +// +// 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 + } + + // + // 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/14040218 XCAEA/Helpers/x-saherelm.x121.xcc.helper.mq5 b/BKPS/14040218 XCAEA/Helpers/x-saherelm.x121.xcc.helper.mq5 new file mode 100644 index 0000000..1663ae7 --- /dev/null +++ b/BKPS/14040218 XCAEA/Helpers/x-saherelm.x121.xcc.helper.mq5 @@ -0,0 +1,252 @@ +/////////////////////////////////////////////////////// +// +// 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; + } + + // + // 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/14040218 XCAEA/Helpers/x-saherelm.x121.xct.helper.mq5 b/BKPS/14040218 XCAEA/Helpers/x-saherelm.x121.xct.helper.mq5 new file mode 100644 index 0000000..c444481 --- /dev/null +++ b/BKPS/14040218 XCAEA/Helpers/x-saherelm.x121.xct.helper.mq5 @@ -0,0 +1,234 @@ +/////////////////////////////////////////////////////// +// +// 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; + } + + // + // 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/14040218 XCAEA/Helpers/x-saherelm.x121.xoscs.helper.mq5 b/BKPS/14040218 XCAEA/Helpers/x-saherelm.x121.xoscs.helper.mq5 new file mode 100644 index 0000000..720c8d3 --- /dev/null +++ b/BKPS/14040218 XCAEA/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/14040218 XCAEA/Indicators/x-saherelm.x121.x3ma.mq5 b/BKPS/14040218 XCAEA/Indicators/x-saherelm.x121.x3ma.mq5 new file mode 100644 index 0000000..e535571 --- /dev/null +++ b/BKPS/14040218 XCAEA/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/14040218 XCAEA/Indicators/x-saherelm.x121.xca.mq5 b/BKPS/14040218 XCAEA/Indicators/x-saherelm.x121.xca.mq5 new file mode 100644 index 0000000..7e1ec60 --- /dev/null +++ b/BKPS/14040218 XCAEA/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/14040218 XCAEA/Indicators/x-saherelm.x121.xcc.mq5 b/BKPS/14040218 XCAEA/Indicators/x-saherelm.x121.xcc.mq5 new file mode 100644 index 0000000..2f45b84 --- /dev/null +++ b/BKPS/14040218 XCAEA/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/14040218 XCAEA/Indicators/x-saherelm.x121.xct.mq5 b/BKPS/14040218 XCAEA/Indicators/x-saherelm.x121.xct.mq5 new file mode 100644 index 0000000..286882a --- /dev/null +++ b/BKPS/14040218 XCAEA/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/14040218 XCAEA/Indicators/x-saherelm.x121.xoscs.mq5 b/BKPS/14040218 XCAEA/Indicators/x-saherelm.x121.xoscs.mq5 new file mode 100644 index 0000000..4c32077 --- /dev/null +++ b/BKPS/14040218 XCAEA/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/14040218 XCAEA/Libraries/x-saherelm.common.extensions.lib.mq5 b/BKPS/14040218 XCAEA/Libraries/x-saherelm.common.extensions.lib.mq5 new file mode 100644 index 0000000..a7d7c03 --- /dev/null +++ b/BKPS/14040218 XCAEA/Libraries/x-saherelm.common.extensions.lib.mq5 @@ -0,0 +1,6426 @@ +/////////////////////////////////////////////////////// +// +// 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; +} + +// +// Used In Report or Summary Generators ... +string ToString( + string prefix, // Title + bool value, // Value + bool ignoreFalseConditions = true, // Ignore False Conditions + string lineSeparator = "\n", // Line Separator + string prefixSeparator = ":" // Title Separator +) +{ + // + string result = NULL; + + // + result = (value || !ignoreFalseConditions) + ? prefix + + prefixSeparator + " " + + ToString(value) + + lineSeparator + : ""; + + // + return result; +} + +// +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; +} + +/** + * Converts String to boolean ... + * + * @param value: string, Provided Value ... + * + * @return ( bool ) + */ +bool ToBoolean(string value) +{ + // + bool result = false; + + // + if (StringLen(value) <= 0) + { + return result; + } + + // + StringToLower(value); + result = value == "true"; + + // + return result; +} + +// +// Split an String Representation of an Array ... +int SplitContent( + string &result[], // Hold Result ... + string content, // Source ... + string separator = ",", // Separator ... + bool forceCleanResult = true // Clean Result ... +) +{ + // + int mResult = 0; + + // + if (forceCleanResult) + { + Clean(result); + } + + // + int before = ArraySize(result); + + // + if (separator == NULL || StringLen(separator) == 0) + { + separator = ","; + } + + // + if (StringLen(content) == 0) + { + return mResult; + } + + // + StringSplit( + content, + StringGetCharacter( + separator, + 0), + result); + + // + int after = ArraySize(result); + + // + mResult = after - before; + + // + return mResult; +} + +// +// Extract Data from String ... +string ExtractString( + const string source, // Source String used for Extracting + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + string result = ""; + + // + // Validate String ... + if ( + StringLen(source) == 0 || + StringLen(endString) == 0 || + StringLen(startString) == 0) + { + return result; + } + + // + // Find Start String Position ... + int sPos = StringFind( + source, + startString); + if (sPos < 0) + { + return result; + } + + // + // Find End String Position after Start String ... + int searchEndFromPos = sPos + StringLen(startString); + int ePos = StringFind( + source, + endString, + searchEndFromPos); + if (ePos < 0) + { + return result; + } + + // + // Extract Data from Source ... + int dLength = ePos - searchEndFromPos; + result = StringSubstr( + source, + searchEndFromPos, + dLength); + + // + return result; +} + +// +// Extract an Array of Contents ... +int ExtractStrings( + string &result[], // Hold Result + const string source, // Source String used for Extracting + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + int mResult = 0; + + // + Clean(result); + + // + // Validate Args ... + int sourceLength = StringLen(source); + int startLength = StringLen(startString); + int endLength = StringLen(endString); + + // + int minRequiredLength = startLength + endLength; + + // + if ( + endLength <= 0 || + startLength <= 0 || + sourceLength <= 0 || + sourceLength < minRequiredLength) + { + return mResult; + } + + // + // Make a Copy of Source for Manipulating ... + string workStr = source; + + // + // Define a Loop ... + while (StringLen(workStr) > minRequiredLength) + { + // + // Find Item ... + string item = ExtractString( + workStr, + startString, + endString); + + // + // Breakout when couldn't find anymore item ... + int itemLength = StringLen(item); + if (itemLength <= 0) + { + break; + } + + // + // Prepare Item Source String for Replacing in Work String ... + string itemSource = startString + item + endString; + + // + // Add Item to Result Array ... + Add( + item, + result); + + // + // Replace Item Soure in Work String ... + StringReplace( + workStr, + itemSource, + ""); + } + + // + // Calculate Size of Array ... + mResult = ArraySize(result); + + // + return mResult; +} + +// +string ExtractSurrounded( + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + return ExtractString( + surrounded, + mToken + startString, + endString + // + ); +} + +// +int ParseIntSurrounded( + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + int result = NULL; + + // + string strContent = ExtractSurrounded( + surrounded, + mToken, + startString, + endString + // + ); + if (!IsValid(strContent)) + { + return result; + } + + // + result = (int)strContent; + + // + return result; +} + +long ParseLongSurrounded( + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + long result = NULL; + + // + string strContent = ExtractSurrounded( + surrounded, + mToken, + startString, + endString + // + ); + if (!IsValid(strContent)) + { + return result; + } + + // + result = (long)strContent; + + // + return result; +} + +string ParseStringSurrounded( + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + string result = NULL; + + // + string strContent = ExtractSurrounded( + surrounded, + mToken, + startString, + endString + // + ); + if (!IsValid(strContent)) + { + return result; + } + + // + result = (string)strContent; + + // + return result; +} + +double ParseDoubleSurrounded( + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + double result = NULL; + + // + string strContent = ExtractSurrounded( + surrounded, + mToken, + startString, + endString + // + ); + if (!IsValid(strContent)) + { + return result; + } + + // + result = (double)strContent; + + // + return result; +} + +datetime ParseTimeSurrounded( + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + datetime result = NULL; + + // + string strContent = ExtractSurrounded( + surrounded, + mToken, + startString, + endString + // + ); + if (!IsValid(strContent)) + { + return result; + } + + // + result = (datetime)strContent; + + // + return result; +} + +// +int ParseIntArraySurrounded( + int &result[], // Holds Result + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + string separator = ",", // Separator ... + const string startString = "(", // Expression Start String must be Unique + const string endString = ")", // Where to End Extraction, usually a Sign + bool forceClean = true // Clean Result ... +) +{ + // + int count = 0; + + // + if (forceClean) + { + Clean(result); + } + + // + int before = ArraySize(result); + + // + string contentStr = ParseStringSurrounded(surrounded, mToken); + if (!IsValid(contentStr)) + { + return count; + } + + // + string tmps[]; + int tmpsCount = SplitContent( + tmps, + contentStr + // + ); + if (tmpsCount <= 0) + { + return count; + } + + // + for (int i = 0; i < tmpsCount; i++) + { + // + string iTMP = tmps[i]; + if (!IsValid(iTMP)) + { + continue; + } + + // + int iValue = (int)iTMP; + + // + Add( + iValue, + result + // + ); + } + + // + int after = ArraySize(result); + + // + count = after - before; + + // + return count; +} + +int ParseLongArraySurrounded( + long &result[], // Holds Result + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + string separator = ",", // Separator ... + const string startString = "(", // Expression Start String must be Unique + const string endString = ")", // Where to End Extraction, usually a Sign + bool forceClean = true // Clean Result ... +) +{ + // + int count = 0; + + // + if (forceClean) + { + Clean(result); + } + + // + int before = ArraySize(result); + + // + string contentStr = ParseStringSurrounded(surrounded, mToken); + if (!IsValid(contentStr)) + { + return count; + } + + // + string tmps[]; + int tmpsCount = SplitContent( + tmps, + contentStr + // + ); + if (tmpsCount <= 0) + { + return count; + } + + // + for (int i = 0; i < tmpsCount; i++) + { + // + string iTMP = tmps[i]; + if (!IsValid(iTMP)) + { + continue; + } + + // + long iValue = (long)iTMP; + + // + Add( + iValue, + result + // + ); + } + + // + int after = ArraySize(result); + + // + count = after - before; + + // + return count; +} + +int ParseDoubleArraySurrounded( + double &result[], // Holds Result + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + string separator = ",", // Separator ... + const string startString = "(", // Expression Start String must be Unique + const string endString = ")", // Where to End Extraction, usually a Sign + bool forceClean = true // Clean Result ... +) +{ + // + int count = 0; + + // + if (forceClean) + { + Clean(result); + } + + // + int before = ArraySize(result); + + // + string contentStr = ParseStringSurrounded(surrounded, mToken); + if (!IsValid(contentStr)) + { + return count; + } + + // + string tmps[]; + int tmpsCount = SplitContent( + tmps, + contentStr + // + ); + if (tmpsCount <= 0) + { + return count; + } + + // + for (int i = 0; i < tmpsCount; i++) + { + // + string iTMP = tmps[i]; + if (!IsValid(iTMP)) + { + continue; + } + + // + double iValue = (double)iTMP; + + // + Add( + iValue, + result + // + ); + } + + // + int after = ArraySize(result); + + // + count = after - before; + + // + return count; +} + +int ParseTimeArraySurrounded( + datetime &result[], // Holds Result + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + string separator = ",", // Separator ... + const string startString = "(", // Expression Start String must be Unique + const string endString = ")", // Where to End Extraction, usually a Sign + bool forceClean = true // Clean Result ... +) +{ + // + int count = 0; + + // + if (forceClean) + { + Clean(result); + } + + // + int before = ArraySize(result); + + // + string contentStr = ParseStringSurrounded(surrounded, mToken); + if (!IsValid(contentStr)) + { + return count; + } + + // + string tmps[]; + int tmpsCount = SplitContent( + tmps, + contentStr + // + ); + if (tmpsCount <= 0) + { + return count; + } + + // + for (int i = 0; i < tmpsCount; i++) + { + // + string iTMP = tmps[i]; + if (!IsValid(iTMP)) + { + continue; + } + + // + datetime iValue = (datetime)iTMP; + + // + Add( + iValue, + result + // + ); + } + + // + int after = ArraySize(result); + + // + count = after - before; + + // + return count; +} + +// +// Surround an String by Specific Token ... +template +string Surround( + string mToken, // an String which used to Tokenize + T &value, // a Value for Tokenize it + string startString = "(", // Token Start Content + string endString = ")" // Token End Content +) +{ + // + string result = NULL; + + // + string strValue = ToString(value); + if (!IsValid(strValue)) + { + return result; + } + + // + result = + // + (IsValid(mToken) + ? mToken + : "") + + // + startString + + strValue + + endString + // + ; + + // + return result; +} + +// +template +string SurroundArray( + string mToken, + T &value[], + string startString = "(", // Token Start Content + string endString = ")" // Token End Content +) +{ + // + string result = NULL; + + // + string valueStr = ToString(value); + if (!IsValid(valueStr)) + { + return result; + } + + // + result = Surround( + mToken, + valueStr, + startString, + endString + // + ); + + // + return result; +} + +// +// 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 GetMax( + 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 GetSpecifiedMax( + T &buffer[], // the Buffer which required to search + int &index, // Item Index ... + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + return GetMax( + 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 GetMin( + 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 GetSpecifiedMin( + T &buffer[], // the Buffer which required to search + int &index, // Item Index ... + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + return GetMin( + 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 FindLesserThan( + 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 FindBiggerThan( + 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 ... +// + +// diff --git a/BKPS/14040218 XCAEA/Libraries/x-saherelm.common.lib.mq5 b/BKPS/14040218 XCAEA/Libraries/x-saherelm.common.lib.mq5 new file mode 100644 index 0000000..cad150f --- /dev/null +++ b/BKPS/14040218 XCAEA/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/14040218 XCAEA/Libraries/x-saherelm.common.models.lib.mq5 b/BKPS/14040218 XCAEA/Libraries/x-saherelm.common.models.lib.mq5 new file mode 100644 index 0000000..c8e3186 --- /dev/null +++ b/BKPS/14040218 XCAEA/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/14040218 XCAEA/Libraries/x-saherelm.draw.lib.mq5 b/BKPS/14040218 XCAEA/Libraries/x-saherelm.draw.lib.mq5 new file mode 100644 index 0000000..ab7f39b --- /dev/null +++ b/BKPS/14040218 XCAEA/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/14040218 XCAEA/Libraries/x-saherelm.x-enums.lib.mq5 b/BKPS/14040218 XCAEA/Libraries/x-saherelm.x-enums.lib.mq5 new file mode 100644 index 0000000..e212425 --- /dev/null +++ b/BKPS/14040218 XCAEA/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/14040218 XCAEA/Libraries/x-saherelm.x-ohcl.lib.mq5 b/BKPS/14040218 XCAEA/Libraries/x-saherelm.x-ohcl.lib.mq5 new file mode 100644 index 0000000..943f9d7 --- /dev/null +++ b/BKPS/14040218 XCAEA/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/14040218 XCAEA/Libraries/x-saherelm.x-poi.extensions.lib.mq5 b/BKPS/14040218 XCAEA/Libraries/x-saherelm.x-poi.extensions.lib.mq5 new file mode 100644 index 0000000..9faf9f9 --- /dev/null +++ b/BKPS/14040218 XCAEA/Libraries/x-saherelm.x-poi.extensions.lib.mq5 @@ -0,0 +1,3471 @@ +/////////////////////////////////////////////////////// +// +// 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 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; +} + +/** + * 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; + } + } + + // + 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; + } + } + + // + 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; + } + } + + // + 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; + } + } + + // + 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/14040218 XCAEA/Libraries/x-saherelm.x-poi.lib.mq5 b/BKPS/14040218 XCAEA/Libraries/x-saherelm.x-poi.lib.mq5 new file mode 100644 index 0000000..070c3e0 --- /dev/null +++ b/BKPS/14040218 XCAEA/Libraries/x-saherelm.x-poi.lib.mq5 @@ -0,0 +1,5796 @@ +/////////////////////////////////////////////////////// +// +// 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); + } + + /** + * 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; + + // + 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; + } +}; + +// diff --git a/BKPS/14040218 XCAEA/Libraries/x-saherelm.x-poi.state.lib.mq5 b/BKPS/14040218 XCAEA/Libraries/x-saherelm.x-poi.state.lib.mq5 new file mode 100644 index 0000000..e52ea2b --- /dev/null +++ b/BKPS/14040218 XCAEA/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/14040218 XCAEA/Libraries/x-saherelm.x-trade.lib.mq5 b/BKPS/14040218 XCAEA/Libraries/x-saherelm.x-trade.lib.mq5 new file mode 100644 index 0000000..6fba42a --- /dev/null +++ b/BKPS/14040218 XCAEA/Libraries/x-saherelm.x-trade.lib.mq5 @@ -0,0 +1,6329 @@ +/////////////////////////////////////////////////////// +// +// 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 +}; + +// +// Available Guard Action ... +enum ENUM_X_GUARD_ACTIONS +{ + X_GUARD_ACTION_NOTHING, // Nothing + X_GUARD_ACTION_HEDGE, // Hedge + X_GUARD_PARTIAL_CLOSE, // Partial Close + X_GUARD_ACTION_TRAIL_STOP, // Trail StopLoss + X_GUARD_ACTION_FORCE_CLOSE, // Force Close + X_GUARD_ACTION_ADD_SUPPORT_SIGNAL, // Add Support Signal + X_GUARD_ACTION_CANCEL_PENDING_ORDERS, // Cancel Pending Orders +}; + +// +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, +}; + +// +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 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 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 ... + + // + XSignal supports[]; // a Collecion of Support Signals ... + + // + int pushers; // Signal Pushers ... + string conditions; // Signal Conditions ... + + // + // Additional ... + + // + // TP ... + double fullTPLevel; // Full TP ... + bool isPartiallyClosed; // Check Partially Closed Before or not ... + double partialCloseMultiplier; // Amount of Partial Close ... + double partialCloseOnTPLevel; // Do Partial Close on TP Level ... + + // + // RF ... + double tpLevelForBreakEven; // TP Level for Break Even ... + bool riskFreeOnBreakEven; // Risk Free Signal On Break Even ... + + // + // Traget ... + double targets[]; // Force Risk Free On Targets ... + bool isTargetApplied; // Target Applied ... + int appliedTargetIDX; // Last Applied Target Index ... + bool ignoreEAVolume; // Ignore EA Volume ... + + // + // SL Trail ... + bool trailSL; // Do SL Trail ... + double trailSLStartOnReachTPLevel; // Start SL Trail After Reached TP Level ... + + // + // Constructor ... + XSignal() + { + Default(); + } + + // + bool Prepare( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + ENUM_POSITION_TYPE mType, // Long (Buy) or Short (Sell) + ENUM_X_ORDER_MODES mMode, // Execution Mode + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + bool result = false; + + // + result = + // + IsValid(mMode) && + IsValid(mSymbol) && + IsValid(mPeriod) && + NotEmpty(mEntry) && + NotEmpty(mVolume) && + IsValid(mProvider) + // + ; + if (!result) + { + return result; + } + + // + if (mTP < 0) + { + mTP = 0; + } + + // + if (mSL < 0) + { + mSL = 0; + } + + // + type = mType; + mode = mMode; + symbol = mSymbol; + period = mPeriod; + provider = mProvider; + + // + // Normalization Values ... + sl = NormalizePrice(mSL, mSymbol); + tp = NormalizePrice(mTP, mSymbol); + mEntry = NormalizePrice(mEntry, mSymbol); + mVolume = NormalizeVolume(mVolume, mSymbol); + + // + entry = mEntry; + volume = mVolume; + + // + result = Normalize(); + + // + return result; + } + + // + bool PrepareComplex( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + ENUM_POSITION_TYPE mType, // Long (Buy) or Short (Sell) + ENUM_X_ORDER_MODES mMode, // Execution Mode + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + // + // TP ... + double mFullTPLevel = 0, // Full TP Level + double mPartialCloseOnTPLevel = 0, // Partial Close On TP Level + double mPartialCloseMultiplier = 0, // Partial Close Multiplier + // + // RF ... + bool mRiskFreeOnBreakEven = false, // Risk Free Signal On Break Even ... + double mTpLevelForBreakEven = 0, // TP Level for Break Even ... + // + // SL Trail ... + bool mTrailSL = false, // Trail SL + double mTrailSLStartOnReachTPLevel = 0 // Trail SL Starts after Reached TP Level + ) + { + // + bool result = false; + + // + // Validate Args ... + result = + // + // Common ... + mSL > 0 && + mEntry > 0 && + mVolume > 0 && + IsValid(mSymbol) && + IsValid(mPeriod) && + IsValid(mProvider) && + mMode != X_ORDER_MODE_NOTHING + // + && + // + // TP ... + mFullTPLevel > 0 + // + ; + if (!result) + { + return result; + } + + // + // Prepare Regular Signal Values ... + double _risk = MathAbs(mEntry - mSL); + double _reward = _risk * mFullTPLevel; + + // + bool isLong = IsLong(mType); + + // + sl = mSL; + type = mType; + mode = mMode; + entry = mEntry; + symbol = mSymbol; + period = mPeriod; + volume = mVolume; + provider = mProvider; + fullTPLevel = mFullTPLevel; + tp = isLong + ? mEntry + _reward + : mEntry - _reward; + + // + result = Normalize(); + if (!result) + { + return result; + } + + // + // Calculate Other Conditions ... + + // + bool canPartialClose = + // + mPartialCloseOnTPLevel > 0 && + mPartialCloseMultiplier > 0 && + mPartialCloseOnTPLevel < mFullTPLevel + // + ; + if (canPartialClose) + { + // + partialCloseOnTPLevel = mPartialCloseOnTPLevel; + partialCloseMultiplier = mPartialCloseMultiplier; + } + + // + bool canRFOnBEP = + // + mRiskFreeOnBreakEven && + mTpLevelForBreakEven > 0 + // + ; + if (canRFOnBEP) + { + // + riskFreeOnBreakEven = mRiskFreeOnBreakEven; + tpLevelForBreakEven = mTpLevelForBreakEven; + } + + // + bool canTrailSL = + // + mTrailSL && + mTrailSLStartOnReachTPLevel > 0 && + mTrailSLStartOnReachTPLevel < mFullTPLevel + // + ; + if (canTrailSL) + { + // + trailSL = mTrailSL; + trailSLStartOnReachTPLevel = mTrailSLStartOnReachTPLevel; + } + + // + result = IsValid(); + + // + return result; + } + + // + bool PrepareLong( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + ENUM_X_ORDER_MODES mMode, // Execution Mode + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + return Prepare( + mSymbol, + mProvider, + mPeriod, + POSITION_TYPE_BUY, + mMode, + mEntry, + mVolume, + mSL, + mTP + // + ); + } + + // + bool PrepareShort( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + ENUM_X_ORDER_MODES mMode, // Execution Mode + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + return Prepare( + mSymbol, + mProvider, + mPeriod, + POSITION_TYPE_SELL, + mMode, + mEntry, + mVolume, + mSL, + mTP + // + ); + } + + // + // Market Mode ... + + // + bool PrepareMarketLong( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + return PrepareLong( + mSymbol, + mProvider, + mPeriod, + X_ORDER_MODE_MARKET, + mEntry, + mVolume, + mSL, + mTP + // + ); + } + + // + bool PrepareMarketShort( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + return PrepareShort( + mSymbol, + mProvider, + mPeriod, + X_ORDER_MODE_MARKET, + mEntry, + mVolume, + mSL, + mTP + // + ); + } + + // + // Stop Mode ... + + // + bool PrepareStopLong( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + return PrepareLong( + mSymbol, + mProvider, + mPeriod, + X_ORDER_MODE_STOP, + mEntry, + mVolume, + mSL, + mTP + // + ); + } + + // + bool PrepareStopShort( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + return PrepareShort( + mSymbol, + mProvider, + mPeriod, + X_ORDER_MODE_STOP, + mEntry, + mVolume, + mSL, + mTP + // + ); + } + + // + // Limit Mode ... + + // + bool PrepareLimitLong( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + return PrepareLong( + mSymbol, + mProvider, + mPeriod, + X_ORDER_MODE_LIMIT, + mEntry, + mVolume, + mSL, + mTP + // + ); + } + + // + bool PrepareLimitShort( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + return PrepareShort( + mSymbol, + mProvider, + mPeriod, + X_ORDER_MODE_LIMIT, + mEntry, + mVolume, + mSL, + mTP + // + ); + } + + // + // Generate Opposit Direction ... + bool GenerateOpposit( + XSignal &mSignal // Oppsoit Signal + ) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + ENUM_POSITION_TYPE mType = Opposit(this.type); + double mEntry = GetExit(this.symbol, mType); + + // + bool isLong = IsLong(mType); + + // + // Calculate Risk Reward Ratio ... + double risk = GetRisk(); + double reward = GetReward(); + + // + double mSL = isLong + ? mEntry - risk + : mEntry + risk; + + // + double mTP = isLong + ? mEntry + reward + : mEntry - reward; + + // + result = mSignal.Prepare( + this.symbol, + this.provider, + this.period, + mType, + this.mode, + mEntry, + this.volume, + mSL, + mTP // + ); + + // + return result; + } + + // + // Prepare Opposit Signal based On a Position ... + bool PrepareOpposit( + XPosition &source // Source Data + ) + { + // + bool result = false; + + // + ENUM_POSITION_TYPE mType = Opposit(source.type); + double mEntry = GetEntry(source.symbol, mType); + + // + bool isLong = IsLong(mType); + + // + double risk = source.GetRisk(); + double reward = source.GetReward(); + + // + double mSL = isLong + ? mEntry - risk + : mEntry + risk; + + // + double mTP = isLong + ? mEntry + reward + : mEntry - reward; + + // + return Prepare( + source.symbol, + source.provider, + source.period, + mType, + X_ORDER_MODE_MARKET, + mEntry, + source.volume, + mSL, + mTP // + ); + + // + result = IsValid(); + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + entry = 0; + volume = 0; + pushers = 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; + + // + trailSL = false; + riskFreeOnBreakEven = false; + + // + fullTPLevel = 0; + tpLevelForBreakEven = 0; + partialCloseOnTPLevel = 0; + isPartiallyClosed = false; + partialCloseMultiplier = 0; + trailSLStartOnReachTPLevel = 0; + + // + Clean(supports); + + // + ZeroMemory(this); + } + + // + // Default Values ... + void Default() + { + // + entry = 0; + volume = 0; + pushers = 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; + + // + trailSL = false; + riskFreeOnBreakEven = false; + + // + fullTPLevel = 0; + tpLevelForBreakEven = 0; + isPartiallyClosed = false; + partialCloseOnTPLevel = 0; + partialCloseMultiplier = 0; + trailSLStartOnReachTPLevel = 0; + + // + Clean(supports); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsValid(period) && + IsValid(symbol) && + NotEmpty(volume) && + NotEmpty(entry) + // + ; + + // + if (!result) + { + return result; + } + + // + return result; + } + + // + // DO All Calculations and Normalizations ... + bool Normalize() + { + // + bool result = false; + + // + // Normalizations ... + symbol = NormalizeSymbol(symbol); + period = NormalizePeriod(period); + + // + time = NormalizeTime(time); + + // + sl = NormalizePrice(sl, symbol); + tp = NormalizePrice(tp, symbol); + entry = NormalizePrice(entry, symbol); + volume = NormalizeVolume(volume, symbol); + + // + result = IsValid(); + + // + return result; + } + + // + // Check Signal Executed or not ... + bool IsExecuted() + { + // + bool result = false; + + // + result = + // + IsValid() && + NotEmpty(positionId) + // + ; + + // + return result; + } + + // + // Generate Comment for Signal ... + string GenerateComment() + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + if (IsValid(provider)) + { + // + // Generate Provider Tag ... + result += GenerateProviderTag(provider); + } + + // + if (IsValid(period)) + { + // + // Generate Period Tag ... + result += GeneratePeriodTag(period); + } + + // + return result; + } + + // + int GetAge() + { + // + return GetAge( + this, + this.period // + ); + } + + // + // 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; + } + + // + // Check Can Partial Close on Specified TP Level ... + bool CanPartialClose() + { + // + bool result = false; + + // + result = + IsValid() && + fullTPLevel > 0 && + partialCloseOnTPLevel > 0 && + partialCloseMultiplier > 0 && + partialCloseOnTPLevel < fullTPLevel; + + // + return result; + } + + // + // Check Can Risk Free On Break Even Point ... + bool CanRiskFreeOnBreakEvenPoint() + { + // + bool result = false; + + // + result = + IsValid() && + riskFreeOnBreakEven && + tpLevelForBreakEven > 0; + + // + return result; + } + + // + // Check Can Trail SL ... + bool CanTrailSL() + { + // + bool result = false; + + // + result = + IsValid() && + trailSL && + fullTPLevel > 0 && + trailSLStartOnReachTPLevel > 0 && + trailSLStartOnReachTPLevel < fullTPLevel; + + // + 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; + } +}; + +// +// 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; + } +}; + +// +// Model Guard Info ... +struct XGuard +{ + // + string symbol; // Trading Symbol ... + string provider; // Signal Provider ... + ENUM_TIMEFRAMES period; // Trading Timeframe ... + ENUM_X_POSITION_TYPES type; // Position Type ... + ENUM_X_GUARD_ACTIONS action; // Which Action to Do ... + + // + double dblPayLoad; + string strPayload; + + // + // Constructor ... + XGuard() + { + Clean(); + } + + // + // Initialize ... + + // + // Global Initializer ... + bool Init( + string mSymbol, // Trading Symbol ... + ENUM_TIMEFRAMES mPeriod, // Trading Timeframe ... + ENUM_X_GUARD_ACTIONS mAction, // Which Action to Do ... + ENUM_X_POSITION_TYPES mType = NULL, // Position Type ... + string mProvider = NULL, // Signal Provider ... + double mDblPayLoad = NULL, + string mStrPayload = NULL // + ) + { + // + type = mType; + symbol = mSymbol; + period = mPeriod; + action = mAction; + provider = mProvider; + dblPayLoad = mDblPayLoad; + strPayload = mStrPayload; + + // + bool result = IsValid(); + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + symbol = NULL; + provider = NULL; + period = NULL; + action = X_GUARD_ACTION_NOTHING; + + // + strPayload = NULL; + dblPayLoad = EMPTY_VALUE; + + // + ZeroMemory(this); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + action != X_GUARD_ACTION_NOTHING + // + ; + + // + return result; + } +}; + +// +// Model a Position with all of it's Supports ... +struct XPositionPack +{ + // + ulong ticket; // Main Position's Ticket + + // + XPosition position; // Main Position (if Exists) + + // + int supportOrdersCount; // Supported Orders (Untriggered) + int supportPositionsCount; // Supported Positions + + // + XOrder supportOrders[]; // Supported Orders (Untriggered) + XPosition supportPositions[]; // Supported Positions + + // + // Constructor ... + XPositionPack() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + ticket = 0; + + // + position.Clean(); + + // + supportOrdersCount = 0; + supportPositionsCount = 0; + + // + Clean(supportOrders); + Clean(supportPositions); + + // + ZeroMemory(this); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + NotEmpty(ticket) && + ( + // + supportOrdersCount > 0 + ? ArraySize(supportOrders) == supportOrdersCount + : true + // + ) + // + && + // + ( + // + supportPositionsCount > 0 + ? ArraySize(supportPositions) == supportPositionsCount + : true + // + ) + // + ; + + // + return result; + } +}; + +// +// Check Position SL Trails Structure ... +struct XTrail +{ + // + ulong ticket; // Position Ticket ... + ENUM_POSITION_TYPE type; // Type ... + datetime time; // Trail Time ... + double before; // SL Value Before Trailing ... + double after; // SL Value After Trailing ... + int level; // Number of Trails SL ... + double profit; // Profit in SL Time ... + + // + // Constructor ... + XTrail() + { + Clean(); + } + + // + // Tools ... + + // + bool Init( + ulong mTicket, // Ticket + ENUM_POSITION_TYPE mType, // Type + double mProfit, // Profit + double mBefore, // Before + double mAfter // After + ) + { + // + Clean(); + + // + type = mType; + after = mAfter; + ticket = mTicket; + before = mBefore; + profit = mProfit; + + // + level++; + + // + time = TimeCurrent(); + + // + return IsValid(); + } + + // + bool Update( + double mSl, // new SL ... + double mProfit // Profit + ) + { + // + bool result = false; + + // + time = TimeCurrent(); + + // + double cAfter = after; + after = mSl; + before = cAfter; + profit = mProfit; + + // + level++; + + // + result = IsValid(); + + // + return result; + } + + // + string GenerateTag() + { + // + string result = NULL; + + // + string ticketLevelStr = ToString(ticket) + "," + ToString(level); + + // + result = Surround( + XSLTrailToken, + ticketLevelStr // + ); + + // + return result; + } + + // + // Cleanup ... + void Clean() + { + // + ticket = 0; + time = 0; + before = 0; + after = 0; + level = 0; + + // + ZeroMemory(this); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + ticket > 0 && + time > 0 && + level > 0 + // + ; + + // + 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 = FindMaxInDrawdownIndex( + longs // + ); + + // + if (IsValidIndex(result)) + { + _position = longs[result]; + } + } + else + { + // + result = FindMaxInDrawdownIndex( + 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 = FindMinInDrawdownIndex( + longs // + ); + + // + if (IsValidIndex(result)) + { + _position = longs[result]; + } + } + else + { + // + result = FindMinInDrawdownIndex( + shorts // + ); + + // + if (IsValidIndex(result)) + { + _position = shorts[result]; + } + } + + // + return result; + } + + // +}; + +// +struct XSymbolLastPosition +{ + // + string symbol; + string provider; + datetime time; + + // + XSymbolLastPosition() + { + Clean(); + } + + // + // Tools ... + + void Clean() + { + // + time = NULL; + symbol = NULL; + provider = NULL; + + // + ZeroMemory(this); + } +}; + +// +// an Structure for Holding Positions Data ... +struct XTradeData +{ + // + datetime time; // Issue Time (Open Position) + string symbol; // Trading Symbol + double entry; // Entry Price + double volume; // Volume + string provider; // Signaller + ENUM_TIMEFRAMES period; // Trading Timeframe + ENUM_X_POSITION_TYPES type; // Position Type + + // + ulong ticket; // Position Ticket + double swap; // Swap + double profit; // Profit on Close + double commission; // Commission + double maxDrawdown; // Max Position Drawdown + string message; // Close Reason + datetime endTime; // End Time + + // + XSignal signal; // Signal Object + int pushers; // Signal Pushers + string conditions; // Signal Conditions + + // + // Constructor ... + void XTradeInfo() + { + Clean(); + } + + // + // Filling Trade Handler ... + bool Fill(XSignal &_signal) + { + // + bool result = false; + + // + Clean(); + + // + // Check Signal Validation ... + result = _signal.IsValid(); + if (!result) + { + return result; + } + + // + signal = _signal; + time = _signal.time; + entry = _signal.entry; + symbol = _signal.symbol; + volume = _signal.volume; + period = _signal.period; + pushers = _signal.pushers; + provider = _signal.provider; + conditions = _signal.conditions; + type = ToPositionType(_signal.type); + + // + if (_signal.IsExecuted()) + { + ticket = _signal.positionId; + } + + // + return result; + } + + // + // Filling Trade Handler ... + bool Fill(XPosition &_position) + { + // + bool result = false; + + // + Clean(); + + // + // Check Signal Validation ... + result = _position.IsValid(); + if (!result) + { + return result; + } + + // + time = _position.openAt; + symbol = _position.symbol; + entry = _position.entry; + volume = _position.volume; + provider = _position.provider; + period = _position.period; + type = ToPositionType(_position.type); + + // + ticket = _position.ticket; + + // + return result; + } + + // + // Update Data ... + bool Update(XPosition &_position) + { + // + bool result = false; + + // + result = _position.IsValid(); + if (!result) + { + return result; + } + + // + profit = _position.profit; + swap = _position.swap; + + // + if (profit < 0 && + (maxDrawdown == 0 || + MathAbs(profit) > MathAbs(maxDrawdown))) + { + maxDrawdown = profit; + } + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + time = NULL; + type = NULL; + symbol = NULL; + period = NULL; + endTime = NULL; + message = NULL; + provider = NULL; + + // + swap = 0; + entry = 0; + ticket = 0; + profit = 0; + volume = 0; + commission = 0; + maxDrawdown = 0; + + // + signal.Clean(); + + // + ResetTrail(); + ResetRecovery(); + + // + ZeroMemory(this); + } + + // + // Validation ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + ticket > 0 && + IsValid(time) && + IsValid(symbol) && + IsValid(period) + // + ; + + // + return result; + } + + // + // Retrieve Trade Data Age ... + int GetAge() + { + // + int result = -1; + + // + if (!IsValid(symbol) || + !IsValid(time) || + !IsValid(endTime) || + !IsValid(period)) + { + return result; + } + + // + int startIndex = iBarShift( + symbol, + period, + time, + false // + ); + + // + int endIndex = iBarShift( + symbol, + period, + endTime, + false // + ); + + // + result = MathAbs(startIndex - endIndex); + + // + return result; + } + + // + // Check Own of Trade Data ... + // based on Ticket ... + bool IsOwn( + ulong _ticket // + ) + { + // + bool result = false; + + // + result = _ticket == ticket; + + // + return result; + } + + // + // Check Own of Trade Data ... + // based on Symbol/Provider and Period ... + bool IsOwn( + string _symbol, + string _provider, + ENUM_TIMEFRAMES _period, + ENUM_X_POSITION_TYPES _type // + ) + { + // + bool result = false; + + // + result = + // + IsValid(_symbol) && + IsValid(_period) && + IsValid(_provider) && + type != X_POSITION_TYPE_ALL && + type != X_POSITION_TYPE_NONE && + // + type == _type && + period == _period && + symbol == _symbol && + provider == _provider + // + ; + + // + return result; + } + + // + // Data Collector ... + + // + // Get Data File Name ... + string GetFileName() + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + result = + // + symbol + "\\" + + ToString(type) + "\\" + + (profit >= 0 ? "Profit" : "Loss") + "\\" + + ToString(ticket) + "_" + + ToString(period) + "_" + + ToFormatString(time) + // + ; + + // + return result; + } + + // + // Get Signal File Name ... + string GetSignalFileName() + { + // + string result = NULL; + + // + result = + // + symbol + "\\" + + ToString(type) + "\\" + + provider + "_" + + ToFormatString(time) + // + ; + + // + return result; + } + + // + // Convert(s) To String Representation(s) ... + string ToString( + bool onlySignals = false // + ) + { + // + string result = NULL; + + // + int age = GetAge(); + + // + result = + // + (onlySignals + ? "" + : ToString("Ticket", ticket)) + + ToString("Symbol", symbol) + + ToString("Period", period) + + ToString("Entry", entry) + + ToString("Provider", provider) + + ToString("Type", ToString(type)) + + ToString("Time", time) + + // + // Attach Trade Info ... + (onlySignals + ? "" + : + // + "-------------" + "\n" + + ToString("Volume", volume) + + ToString("Profit", profit) + + ToString("Commission", commission) + + ToString("Swap", swap) + + ToString("Max Drawdown", maxDrawdown) + + ToString("End Time", endTime) + + ToString("Age", age) + + ToString("Message", message) + + "" + // + ) + + // + // Attach Conditions to Signals ... + (!onlySignals + ? "" + : + // + "-------------" + "\n" + + ToString("Pushers", pushers) + + "Conditions:" + "\n" + + "-------------" + "\n" + + conditions + + "" + // + ) + + // + "" + // + ; + + // + return result; + } + + // + // There are some Controlling Situations for each Trade + // which implemented here ... + + // + // Trailing Stop .... + + // + bool allowTrailStop; // Specified Position Can Trail Stop or not + bool ignoreTPOnTrail; // Ignore TP when SL Trailed + bool trailBasedOnProfit; // Do Trail Based on Profit Points + int trailLevel; // Last Trail Level + double trailStartInPoint; // Trail Starts When Profits Growing in Point + double trailStepInPoint; // Profit Must Grows Point to do Trailling + + // + // Reset all Trailing Configurations .... + void ResetTrail() + { + // + trailLevel = 0; + trailStepInPoint = 0; + trailStartInPoint = 0; + allowTrailStop = false; + ignoreTPOnTrail = false; + trailBasedOnProfit = false; + } + + // + // Recovery ... + + // + bool allowRecover; // Allow Recover Specified Position + double recoveryTPPoint; // Recovery TP Point + double recoverySLPoint; // Recovery SL Point + int maxAllowedRecover; // Max Allowed Recovery + int recoveryLevel; // Number of Recovery Signals + double recoveryVolumeMultiplier; // Recovery Volume Multiplier + double recoveryVolume; // Next Recovery Positioin Volume + ENUM_X_POSITION_TYPES recoveryLookingType; // Looking for Next Recovery Type + + // + void ResetRecovery() + { + // + allowRecover = false; + recoveryLevel = 0; + recoveryVolume = 0; + recoveryTPPoint = 0; + recoverySLPoint = 0; + recoveryVolumeMultiplier = 0; + recoveryLookingType = X_POSITION_TYPE_NONE; + } + + // +}; + +// +// 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 FindMaxInDrawdownIndex( + 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 FindMinInDrawdownIndex( + 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; +} + +// \ No newline at end of file diff --git a/BKPS/14040218 XCAEA/XCAEA/Classes/xcaea.x-data.collector.class.mq5 b/BKPS/14040218 XCAEA/XCAEA/Classes/xcaea.x-data.collector.class.mq5 new file mode 100644 index 0000000..bbd1d2f --- /dev/null +++ b/BKPS/14040218 XCAEA/XCAEA/Classes/xcaea.x-data.collector.class.mq5 @@ -0,0 +1,167 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XCXCAEADataCollector ... +// Description: Class for XCAEA 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 XCAEA Data Collector" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.base.class.mq5" + +// +// Definitions ... + +// +// Implementation ... +class XCXCAEADataCollector : public XCBase +{ + // + // Public ... + public: + // + // Constructors ... + XCXCAEADataCollector() + { + } + + // + // Deconstructor ... + ~XCXCAEADataCollector() + { + } + + // + // Properties ... + + // + string Path() + { + return mPath; + } + + // + void Path(string value) + { + // + // Normalizing Collector Path ... + if (IsValid(value)) + { + mPath = value; + } + else + { + mPath = "XCXCAEADataCollector"; + } + } + + // + // 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; + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + + // + string mPath; // Base Collector Path ... +}; diff --git a/BKPS/14040218 XCAEA/XCAEA/Classes/xcaea.x-poi.detector.class.mq5 b/BKPS/14040218 XCAEA/XCAEA/Classes/xcaea.x-poi.detector.class.mq5 new file mode 100644 index 0000000..58f4411 --- /dev/null +++ b/BKPS/14040218 XCAEA/XCAEA/Classes/xcaea.x-poi.detector.class.mq5 @@ -0,0 +1,3402 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XCXCAEAPOIDetector ... +// Description: Class for XCAEA 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 XCAEA POI Detector" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-bar.analyser.class.mq5" +#include "../../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../Helpers/xcaea.helper.mq5" + +// +// Definitions ... + +// +enum ENUM_XCA_PIVOTS +{ + XCA_NONE, // None + XCA_PEAK, // Peak + XCA_VALE, // Vale + XCA_FVG_BULL, // FVGBull + XCA_FVG_BEAR, // FVGBear + XCA_RSI_COOS, // RSICOOS + XCA_RSI_CUOB, // RSICUOB + XCA_TREND_BULL, // TrendBull + XCA_TREND_BEAR, // TrendBear +}; + +// +bool IsValid(ENUM_XCA_PIVOTS value) +{ + // + bool result = false; + + // + result = value != XCA_NONE; + + // + return result; +} + +// +string ToString(ENUM_XCA_PIVOTS value) +{ + // + string result = NULL; + + // + result = EnumToString(value); + + // + return result; +} + +// +ENUM_X_DIRECTION GetDirection(ENUM_XCA_PIVOTS value) +{ + // + ENUM_X_DIRECTION result = X_DIRECTION_NONE; + + // + switch (value) + { + // + case XCA_VALE: + case XCA_FVG_BULL: + case XCA_RSI_COOS: + case XCA_TREND_BULL: + result = X_DIRECTION_BULLISH; + break; + + // + case XCA_PEAK: + case XCA_FVG_BEAR: + case XCA_RSI_CUOB: + case XCA_TREND_BEAR: + result = X_DIRECTION_BEARISH; + break; + } + + // + return result; +} + +// +string GetBoxType(ENUM_XCA_PIVOTS value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case XCA_VALE: + case XCA_PEAK: + case XCA_RSI_COOS: + case XCA_RSI_CUOB: + result = ToString(value); + break; + // + case XCA_FVG_BULL: + case XCA_FVG_BEAR: + result = "XCA_FVG"; + break; + + // + case XCA_TREND_BULL: + case XCA_TREND_BEAR: + result = "XCA_TREND"; + break; + } + + // + return result; +} + +// +ENUM_XCA_PIVOTS GetPivotType(XBoxZone &value) +{ + // + ENUM_XCA_PIVOTS result = XCA_NONE; + + // + bool has = value.IsValid(); + if (!has) + { + return result; + } + + // + bool isPeak = value.type == GetBoxType(XCA_PEAK) && + value.dir == GetDirection(XCA_PEAK); + bool isVale = value.type == GetBoxType(XCA_VALE) && + value.dir == GetDirection(XCA_VALE); + bool isFVGBull = value.type == GetBoxType(XCA_FVG_BULL) && + value.dir == GetDirection(XCA_FVG_BULL); + bool isFVGBear = value.type == GetBoxType(XCA_FVG_BEAR) && + value.dir == GetDirection(XCA_FVG_BEAR); + bool isRSICrossedOverOS = value.type == GetBoxType(XCA_RSI_COOS) && + value.dir == GetDirection(XCA_RSI_COOS); + bool isRSICrossedUnderOB = value.type == GetBoxType(XCA_RSI_CUOB) && + value.dir == GetDirection(XCA_RSI_CUOB); + bool isTrendBullish = value.type == GetBoxType(XCA_TREND_BULL) && + value.dir == GetDirection(XCA_TREND_BULL); + bool isTrendBearish = value.type == GetBoxType(XCA_TREND_BEAR) && + value.dir == GetDirection(XCA_TREND_BEAR); + + // + if (isPeak) + { + result = XCA_PEAK; + } + else if (isVale) + { + result = XCA_VALE; + } + else if (isFVGBull) + { + result = XCA_FVG_BULL; + } + else if (isFVGBear) + { + result = XCA_FVG_BEAR; + } + else if (isRSICrossedOverOS) + { + result = XCA_RSI_COOS; + } + else if (isRSICrossedUnderOB) + { + result = XCA_RSI_CUOB; + } + else if (isTrendBullish) + { + result = XCA_TREND_BULL; + } + else if (isTrendBearish) + { + result = XCA_TREND_BEAR; + } + + // + return result; +} + +// +int ExtractPivots( + XBoxZone &extracted[], + ENUM_XCA_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_XCA_PIVOTS iType = GetPivotType(iBox); + + // + has = iType == type; + if (has) + { + // + AddRef( + iBox, + extracted // + ); + } + + // + iBox.Clean(); + } + + // + result = ArraySize(extracted); + + // + return result; +} + +// +bool IsFakeBreakeout( + XBoxZone &pivot, + XCXCAEAHelper *helper, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + barIndex = NormalizeInt(barIndex, 0); + + // + result = pivot.IsValid(); + if (!result) + { + return result; + } + + // + int fromIDX = pivot.FromIndex(); + result = barIndex < fromIDX; + if (!result) + { + return result; + } + + // + bool isBullish = pivot.IsBullish(); + + // + // Retrieve Required Bars ... + XOHCL cBar; + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + result = cBar.Init( + pivot.symbol, + pivot.period, + barIndex // + ); + result = result && + cBar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + result = result && + p2Bar.GetPreviousBar(p3Bar); + if (!result) + { + // + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + + // + return result; + } + // + // Bars Conditions ... + + // + ENUM_X_DIRECTION cBarDir; + + // + // Hammer ... + bool isCBarHammer = helper + .barAnalyser + .IsHammer( + cBar, + cBarDir // + ); + bool isCBarBullishHammer = + isCBarHammer && + IsBullish(cBarDir); + bool isCBarBearishHammer = + isCBarHammer && + IsBearish(cBarDir); + + // + // Rejected ... + bool isCBarRejected = helper + .barAnalyser + .IsRejected( + cBar, + cBarDir, + false, // Force Type ... + true // Force Fibo Pressure ... + ); + bool isCBarBullishRejected = + isCBarRejected && + IsBullish(cBarDir); + bool isCBarBearishRejected = + isCBarRejected && + IsBearish(cBarDir); + + // + // Engulfed ... + bool isCBarEngulfed = helper + .barAnalyser + .IsEngulfed( + cBar, + cBarDir // + ); + bool isCBarBullishEngulfed = + isCBarEngulfed && + IsBullish(cBarDir); + bool isCBarBearishEngulfed = + isCBarEngulfed && + IsBearish(cBarDir); + + // + // Momentum ... + bool isCBarMomentum = helper + .barAnalyser + .IsMomentum( + cBar, + cBarDir, + 1 // + ); + bool isCBarBullishMomentum = + isCBarMomentum && + IsBullish(cBarDir); + bool isCBarBearishMomentum = + isCBarMomentum && + IsBearish(cBarDir); + + // + bool isCBarHasBullishPower = isCBarBullishRejected || + isCBarBullishEngulfed || + isCBarBullishMomentum; + + // + bool isCBarHasBearishPower = isCBarBearishRejected || + isCBarBearishEngulfed || + isCBarBearishMomentum; + + // + bool isBarPowerfull = + isBullish + ? isCBarHasBullishPower + : isCBarHasBearishPower; + + // + double breakPrice = + isBullish + ? pivot.lower + : pivot.upper; + + // + // CBar Must Go back InSide Box ... + bool isBarInside = + cBar.GetUp() > breakPrice && + cBar.GetDown() < breakPrice && + cBar.GetDirection() == pivot.dir; + + // + result = + // + // Bar Must Inside Pivot ... + isBarInside && + // + // Bar Must Has Required Direction Power ... + isBarPowerfull + // + ; + + // + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + + // + return result; +} + +// +struct XCAPivot +{ + // + // Props ... + datetime to; + double value; + string symbol; + datetime from; + double reserve; + ENUM_XCA_PIVOTS type; + ENUM_TIMEFRAMES period; + + // + double values[]; + + // + // Constructor ... + XCAPivot() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + value = 0; + to = NULL; + reserve = 0; + from = NULL; + symbol = NULL; + period = NULL; + type = XCA_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: XCAPivot ... + * + * @return ( bool ) + */ + bool IsSameAs(XCAPivot &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 XCXCAEAPOIDetector : public XCBase +{ + // + // Public ... + public: + // + // Props ... + + // + // Pivot Verifications and Max Allowed Holding Items ... + int maxAllowedPivots; // Max Allowed Holding Pibots ... + int pivotVerifications; // Pivots Verifications ... + int pivotDetectionLoopbac; // Pivots Detection Loopback ... + double ticksDividerInPoints; // Ticks and Volume Detection Divider in Point ... + + // + // TREND ... + XBoxZone trendPivotP; // Prev Pivot of Market Trend ... + XBoxZone trendPivotC; // Current Pivot of Market Trend ... + ENUM_X_DIRECTION trendDir; // Trend Direction ... + + // + // Breaked Pivots ... + XBoxZone invalidPivots[]; + + // + // Constructors ... + XCXCAEAPOIDetector( + XCXCAEAHelper *_helper // + ) + { + // + helper = _helper; + drawer = new XCPOIDrawer(); + barAnalyser = new XCBarAnalyser(); + + // + Default(); + } + + // + // De Constructors ... + ~XCXCAEAPOIDetector() + { + // + CleanPivots(); + + // + ZeroMemory(helper); + ZeroMemory(drawer); + ZeroMemory(barAnalyser); + } + + // + // Properties ... + + // + // Tools ... + + // + virtual void Default() + { + // + // COMMON ... + + // + maxAllowedPivots = 50; + pivotVerifications = 5; + ticksDividerInPoints = 15; + pivotDetectionLoopbac = 100; + + // + // PV ... + + // + detectPeakPivots = false; + detectValePivots = false; + + // + maxAllowedPVLifetime = 0; + applySwingsOnPVPivots = false; + selectRejectedPVPivots = false; + selectEngulfedPVPivots = false; + selectPVWhichStartByFVG = false; + applySupportAndResistanceOnPVPivots = false; + + // + // FVG ... + + // + detectFVGBullishPivots = false; + detectFVGBearishPivots = false; + + // + selectSameBarFVGs = false; + maxAllowedFVGLifetime = 0; + validateFVGUsingPV = false; + applyPVToFVGBoundary = false; + selectRejectedFVGPivots = false; + selectEngulfedFVGPivots = false; + validateFVGUsingManalyser = false; + applyLastBarToFVGBoundary = false; + selectOnlyFVGWhichHasIndirectionalLastBar = false; + + // + // TREND ... + + // + detectTrendBullishPivots = false; + detectTrendBearishPivots = false; + + // + } + + // + void Detect( + int barIndex = 0 // + ) + { + // + if (barIndex < 0) + { + 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; + newFVGBullishPivotDetected = false; + newFVGBearishPivotDetected = false; + newTrendBullishPivotDetected = false; + newTrendBearishPivotDetected = false; + + // + int index = barIndex; + int start = index; + int end = index + loopback; + while (start < end) + { + // + // Retrieve Conditions ... + XCAEAConditions 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 // + ); + } + + // + // FVG ... + + // + // Bullish ... + if (detectFVGBullishPivots) + { + // + newFVGBullishPivotDetected = DetectFVGPivot( + barIndex, + X_DIRECTION_BULLISH, + zBar, + cBar, + pBar, + p2Bar, + conditions // + ); + } + + // + // Bearish ... + if (detectFVGBearishPivots) + { + // + newFVGBearishPivotDetected = DetectFVGPivot( + barIndex, + X_DIRECTION_BEARISH, + zBar, + cBar, + pBar, + p2Bar, + conditions // + ); + } + + // + // TREND ... + + // + // Bullish ... + if (detectTrendBullishPivots) + { + // + newTrendBullishPivotDetected = DetectTrendPivot( + barIndex, + X_DIRECTION_BULLISH, + zBar, + cBar, + pBar, + p2Bar, + conditions // + ); + } + + // + // Bearish ... + if (detectTrendBearishPivots) + { + // + newTrendBearishPivotDetected = DetectTrendPivot( + 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 // + ); + + // + // FVG ... + ValidateFVGPivots( + unavailables, + barIndex // + ); + + // + // TREND ... + ValidateTrendPivots( + unavailables, + barIndex // + ); + + // + SortPivots(); + } + + // + int FillPivots( + XBoxZone &pivots[], + ENUM_X_DIRECTION forDir = X_DIRECTION_ALL // + ) + { + // + int result = 0; + + // + Clean(pivots); + + // + if (forDir == X_DIRECTION_NONE) + { + return result; + } + + // + int count = 0; + bool has = false; + + // + bool canFillBullish = + forDir == X_DIRECTION_ALL || + forDir == X_DIRECTION_BULLISH; + + // + bool canFillBearish = + forDir == X_DIRECTION_ALL || + forDir == X_DIRECTION_BEARISH; + + // + // Bullish ... + if (canFillBullish) + { + // + Copy( + valePivots, + pivots, + false // + ); + + // + Copy( + fvgBullishPivots, + pivots, + false // + ); + + // + Copy( + trendBullishPivots, + pivots, + false // + ); + } + + // + // Bearish ... + if (canFillBearish) + { + // + Copy( + peakPivots, + pivots, + false // + ); + + // + Copy( + fvgBearishPivots, + pivots, + false // + ); + + // + Copy( + trendBearishPivots, + pivots, + false // + ); + } + + // + result = ArraySize(pivots); + + // + return result; + } + + // + // Pivots ... + + // + // INVALID Pivots ... + + // + bool HasInvalidPivots() + { + return HasChild(invalidPivots); + } + + // + int CountInvalidPivots() + { + return ArraySize(invalidPivots); + } + + // + // PV ... + + // + int maxAllowedPVLifetime; // Max Allowed PV Life ... + bool applySwingsOnPVPivots; // Apply Swings on PV Pivots ... + bool selectRejectedPVPivots; // Select Rejected PV Pivots ... + bool selectEngulfedPVPivots; // Select Engulfed PV Pivots ... + bool selectPVWhichStartByFVG; // Select PV Pivots Which Starts by FVG ... + bool applySupportAndResistanceOnPVPivots; // Apply Support and Resistance on PV Pivots ... + + // + bool DetectPeakAndValePivot( + int barIndex, + ENUM_X_DIRECTION forDir, + XOHCL &zBar, + XOHCL &cBar, + XOHCL &pBar, + XOHCL &p2Bar, + XCAEAConditions &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]; + + // + // SWING High .. + double zSwingHigh = conditions.swingHighBuffer[zIDX]; + double cSwingHigh = conditions.swingHighBuffer[cIDX]; + double pSwingHigh = conditions.swingHighBuffer[pIDX]; + double p2SwingHigh = conditions.swingHighBuffer[p2IDX]; + + // + // SWING Low ... + double zSwingLow = conditions.swingLowBuffer[zIDX]; + double cSwingLow = conditions.swingLowBuffer[cIDX]; + double pSwingLow = conditions.swingLowBuffer[pIDX]; + double p2SwingLow = conditions.swingLowBuffer[p2IDX]; + + // + // SUPPORT ... + double zSupport = conditions.supportBuffer[zIDX]; + double cSupport = conditions.supportBuffer[cIDX]; + double pSupport = conditions.supportBuffer[pIDX]; + double p2Support = conditions.supportBuffer[p2IDX]; + + // + // RESISTANCE ... + double zResistance = conditions.resistanceBuffer[zIDX]; + double cResistance = conditions.resistanceBuffer[cIDX]; + double pResistance = conditions.resistanceBuffer[pIDX]; + double p2Resistance = conditions.resistanceBuffer[p2IDX]; + + // + // Detecting Bar Conditions ... + + // + ENUM_X_DIRECTION cBarDir; + + // + // Rejected ... + bool isCBarRejected = helper + .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 = helper + .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 = helper + .barAnalyser + .IsEngulfed( + cBar, + cBarDir // + ); + bool isCBarBullishEngulfed = + forBullish && + isCBarEngulfed && + IsBullish(cBarDir); + bool isCBarBearishEngulfed = + forBearish && + isCBarEngulfed && + IsBearish(cBarDir); + + // + bool isPBarEngulfed = helper + .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; + + // + if (applySwingsOnPVPivots) + { + // + isPeakSameLast = + isPeakSameLast && + cSwingHigh == cPeak && + cSwingHigh == pSwingHigh; + + // + isPeakSameLastPrev = + isPeakSameLastPrev && + pSwingHigh == pPeak && + pSwingHigh == p2SwingHigh; + } + + // + if (applySupportAndResistanceOnPVPivots) + { + // + isPeakSameLast = + isPeakSameLast && + cResistance == cPeak && + cResistance == pResistance; + + // + isPeakSameLastPrev = + isPeakSameLastPrev && + pResistance == pPeak && + pResistance == p2Resistance; + } + + // + bool isPeakSwitchedToSameLast = isPeakSameLast && + !isPeakSameLastPrev; + bool isPeakFinishedFromSameLast = !isPeakSameLast && + isPeakSameLastPrev; + + // + // VALE ... + + // + bool isValeSameLast = cVale == pVale; + bool isValeSameLastPrev = pVale == p2Vale; + + // + if (applySwingsOnPVPivots) + { + // + isValeSameLast = + isValeSameLast && + cSwingLow == cVale && + cSwingLow == pSwingLow; + + // + isValeSameLastPrev = + isValeSameLastPrev && + pSwingLow == pVale && + pSwingLow == p2SwingLow; + } + + // + if (applySupportAndResistanceOnPVPivots) + { + // + isValeSameLast = + isValeSameLast && + cSupport == cVale && + cSupport == pSupport; + + // + isValeSameLastPrev = + isValeSameLastPrev && + pSupport == pVale && + pSupport == p2Support; + } + + // + 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 = XCA_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 = XCA_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) + { + // + newPeakPivotDetected = 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 ... + + // + XCAPivot peakPivot; + bool detectPeakPivots; + XBoxZone peakPivots[]; + bool newPeakPivotDetected; + + // + bool HasPeakPivots() + { + return HasChild(peakPivots); + } + + // + int CountPeakPivots() + { + return ArraySize(peakPivots); + } + + // + // VALE ... + + // + XCAPivot valePivot; + bool detectValePivots; + XBoxZone valePivots[]; + bool newValePivotDetected; + + // + bool HasValePivots() + { + return HasChild(valePivots); + } + + // + int CountValePivots() + { + return ArraySize(valePivots); + } + + // + // FVG ... + + // + bool selectSameBarFVGs; // Select FVGs which has Same Type Bars ... + bool validateFVGUsingPV; // Detect FVG Type Two ( Validating Using PV ) ... + int maxAllowedFVGLifetime; // Max Allowed FVG Life ... + bool applyPVToFVGBoundary; // Apply PV to FVG Boundary ... + bool selectRejectedFVGPivots; // Select Rejected FVG Pivots ... + bool selectEngulfedFVGPivots; // Select Engulfed FVG Pivots ... + bool validateFVGUsingManalyser; // Detect FVG Type One ( Validating Using MAnalyser ) ... + bool applyLastBarToFVGBoundary; // Apply Last Bar to FVG Boundary ... + bool selectOnlyFVGWhichHasIndirectionalLastBar; // Select Only FVGs which has Indirectionsl Last Bar, uses to Order Block ... + + // + bool DetectFVGPivot( + int barIndex, + ENUM_X_DIRECTION forDir, + XOHCL &zBar, + XOHCL &cBar, + XOHCL &pBar, + XOHCL &p2Bar, + XCAEAConditions &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 + ? detectFVGBullishPivots + : detectFVGBearishPivots; + 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]; + + // + // VALE ... + double zVale = conditions.valeBuffer[zIDX]; + double cVale = conditions.valeBuffer[cIDX]; + double pVale = conditions.valeBuffer[pIDX]; + double p2Vale = conditions.valeBuffer[p2IDX]; + + // + // MANALYSER ... + + // + // MAH ... + double zMAH = conditions.mahBuffer[zIDX]; + double cMAH = conditions.mahBuffer[cIDX]; + double pMAH = conditions.mahBuffer[pIDX]; + double p2MAH = conditions.mahBuffer[p2IDX]; + + // + // MAL ... + double zMAL = conditions.malBuffer[zIDX]; + double cMAL = conditions.malBuffer[cIDX]; + double pMAL = conditions.malBuffer[pIDX]; + double p2MAL = conditions.malBuffer[p2IDX]; + + // + // MAC ... + double zMAC = conditions.macBuffer[zIDX]; + double cMAC = conditions.macBuffer[cIDX]; + double pMAC = conditions.macBuffer[pIDX]; + double p2MAC = conditions.macBuffer[p2IDX]; + + // + // Detecting Bar Conditions ... + + // + ENUM_X_DIRECTION p2BarDir; + + // + // Rejected ... + bool isP2BarRejected = helper + .barAnalyser + .IsRejected( + p2Bar, + p2BarDir, + false, // Force Type ... + true // Force Fibo Pressure ... + ); + bool isP2BarBullishRejected = + isP2BarRejected && + IsBullish(p2BarDir); + bool isP2BarBearishRejected = + isP2BarRejected && + IsBearish(p2BarDir); + + // + // Engulfed ... + bool isP2BarEngulfed = helper + .barAnalyser + .IsEngulfed( + p2Bar, + p2BarDir // + ); + bool isP2BarBullishEngulfed = + isP2BarEngulfed && + IsBullish(p2BarDir); + bool isP2BarBearishEngulfed = + isP2BarEngulfed && + IsBearish(p2BarDir); + + // + // Prepare Conditinal Conditions ... + + // + // Default FVG Detection ... + XBoxZone fvgBox; + bool isFVG = barAnalyser.IsFVG( + cBar, + fvgBox // + ); + bool isBullishFVG = + isFVG && + forBullish && + fvgBox.IsBullish(); + bool isBearishFVG = + isFVG && + forBearish && + fvgBox.IsBearish(); + + // + // Summarizing Conditions ... + + // + result = false; + + // + bool hasStartCondition = false; + bool hasContinuationCondition = false; + bool hasEndCondition = isBullishFVG || + isBearishFVG; + + // + // Apply all Filtering ... + if (hasEndCondition) + { + // + XOHCL p3Bar; + p2Bar.GetPreviousBar(p3Bar); + + // + bool isFVGValid = true; + + // + // Validate FVG Using Manalyser ... + bool isManalyserValid = false; + if (validateFVGUsingManalyser) + { + // + isManalyserValid = + hasEndCondition && + (forBullish + ? fvgBox.upper <= cMAL + : fvgBox.lower >= cMAH); + } + + // + // Validate FVG Using PV ... + bool isPVValid = false; + if (validateFVGUsingPV) + { + // + isPVValid = + hasEndCondition && + (forBullish + ? (p2Peak < pPeak || + pPeak < cPeak) + : (p2Vale > pVale || + pVale > cVale)); + } + + // + // Select Pure FVG ... + bool isPureFVGValid = + !validateFVGUsingPV && + !validateFVGUsingManalyser; + + // + // Summarise Validation ... + isFVGValid = + isPVValid || + isPureFVGValid || + isManalyserValid; + + // + bool isFVGBarPassed = false; + + // + // Select Same Bars FVGs ... + bool isFVGHasSameBar = true; + if (selectSameBarFVGs) + { + // + isFVGHasSameBar = + forBullish + ? (cBar.IsBullish() && + pBar.IsBullish() && + p2Bar.IsBullish()) + : (cBar.IsBearish() && + pBar.IsBearish() && + p2Bar.IsBearish()); + isFVGBarPassed = + isFVGBarPassed || + isFVGHasSameBar; + } + + // + // Select Rejected FVG ... + bool isFVGRejected = true; + if (selectRejectedFVGPivots) + { + // + isFVGRejected = + (forBullish + ? isP2BarBullishRejected + : isP2BarBearishRejected); + isFVGBarPassed = + isFVGBarPassed || + isFVGRejected; + } + + // + // Select Engulfed FVG ... + bool isFVGEngulfed = true; + if (selectEngulfedFVGPivots) + { + // + isFVGEngulfed = + (forBullish + ? isP2BarBullishEngulfed + : isP2BarBearishEngulfed); + isFVGBarPassed = + isFVGBarPassed || + isFVGEngulfed; + } + + // + // Select Only FVGs Which Has Indirectional Last Bar ... + bool isFVGHasIndirectionalStart = true; + if (selectOnlyFVGWhichHasIndirectionalLastBar) + { + // + isFVGHasIndirectionalStart = + p3Bar.IsValid() && + (forBullish + ? p3Bar.IsBearish() + : p3Bar.IsBullish()); + isFVGBarPassed = + isFVGBarPassed || + isFVGHasIndirectionalStart; + } + + // + // Summarise Bar Pass ... + isFVGBarPassed = + (selectSameBarFVGs || + selectRejectedFVGPivots || + selectEngulfedFVGPivots || + selectOnlyFVGWhichHasIndirectionalLastBar) + ? isFVGBarPassed + : true; + + // + hasEndCondition = isFVGValid && + isFVGBarPassed; + + // + // Apply Boundary ... + if (hasEndCondition) + { + // + double iValue = + forBullish + ? fvgBox.upper + : fvgBox.lower; + + // + if (applyPVToFVGBoundary) + { + // + fvgBox.upper = + forBullish + ? fvgBox.upper + : cPeak; + + // + fvgBox.lower = + forBullish + ? cVale + : fvgBox.lower; + } + + // + if (applyLastBarToFVGBoundary) + { + // + fvgBox.lower = MathMin(p3Bar.low, fvgBox.lower); + fvgBox.upper = MathMax(p3Bar.high, fvgBox.upper); + } + } + + // + p3Bar.Clean(); + } + + // + // ReInstance Pivot ... + if (hasStartCondition) + { + // + } + + // + // Calculate and Fill Pivot Requirements ... + if (hasContinuationCondition) + { + // + } + + // + // End up Pivot and Store it ... + if (hasEndCondition) + { + // + XBoxZone iBox; + XCAPivot iPivot; + + // + iPivot.to = fvgBox.to; + iPivot.from = fvgBox.from; + iPivot.symbol = fvgBox.symbol; + iPivot.period = fvgBox.period; + iPivot.type = forBullish + ? XCA_FVG_BULL + : XCA_FVG_BEAR; + iPivot.value = forBullish + ? fvgBox.lower + : fvgBox.upper; + iPivot.reserve = forBullish + ? fvgBox.upper + : fvgBox.lower; + + // + result = iPivot.IsValid(); + if (result) + { + // + result = iPivot.AsBox(iBox); + if (result) + { + // + if (forBullish) + { + // + result = AddBox( + iBox, + fvgBullishPivots // + ); + } + else + { + // + result = AddBox( + iBox, + fvgBearishPivots // + ); + } + } + } + + // + iBox.Clean(); + iPivot.Clean(); + } + + // + return result; + } + + // + void ValidateFVGPivots( + XBoxZone &unavailables[], + int barIndex = 0 // + ) + { + // + bool has = false; + + // + bool applyLifetimeValidating = maxAllowedFVGLifetime > 0; + + // + // Bullish ... + has = HasFVGBullishPivots(); + if (has) + { + // + ApplyValidationOnBoxes( + fvgBullishPivots, + unavailables, + barIndex // + ); + + // + if (applyLifetimeValidating) + { + // + ApplyLifeTimeValidationOnBoxes( + fvgBullishPivots, + maxAllowedFVGLifetime, + barIndex // + ); + } + } + + // + // Bearish ... + has = HasFVGBearishPivots(); + if (has) + { + // + ApplyValidationOnBoxes( + fvgBearishPivots, + unavailables, + barIndex // + ); + + // + if (applyLifetimeValidating) + { + // + ApplyLifeTimeValidationOnBoxes( + fvgBearishPivots, + maxAllowedFVGLifetime, + barIndex // + ); + } + } + } + + // + // FVG Bullish Pivots ... + + // + bool detectFVGBullishPivots; + XBoxZone fvgBullishPivots[]; + bool newFVGBullishPivotDetected; + + // + bool HasFVGBullishPivots() + { + return HasChild(fvgBullishPivots); + } + + // + int CountFVGBullishPivots() + { + return ArraySize(fvgBullishPivots); + } + + // + // FVG Bearish Pivots ... + + // + bool detectFVGBearishPivots; + XBoxZone fvgBearishPivots[]; + bool newFVGBearishPivotDetected; + + // + bool HasFVGBearishPivots() + { + return HasChild(fvgBearishPivots); + } + + // + int CountFVGBearishPivots() + { + return ArraySize(fvgBearishPivots); + } + + // + // TREND ... + + // + int maxAllowedTrendLifetime; // Max Allowed Trend Life ... + + // + bool DetectTrendPivot( + int barIndex, + ENUM_X_DIRECTION forDir, + XOHCL &zBar, + XOHCL &cBar, + XOHCL &pBar, + XOHCL &p2Bar, + XCAEAConditions &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 + ? detectTrendBullishPivots + : detectTrendBearishPivots; + 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 ... + + // + // TREND ... + double zTrend = conditions.trendBuffer[zIDX]; + double cTrend = conditions.trendBuffer[cIDX]; + double pTrend = conditions.trendBuffer[pIDX]; + double p2Trend = conditions.trendBuffer[p2IDX]; + + // + // TREND State ... + double zTrendState = conditions.trendStateBuffer[zIDX]; + double cTrendState = conditions.trendStateBuffer[cIDX]; + double pTrendState = conditions.trendStateBuffer[pIDX]; + double p2TrendState = conditions.trendStateBuffer[p2IDX]; + + // + // Prepare Conditinal Conditions ... + + // + // Bullish ... + + // + bool isTrendBullish = + cTrendState > 0; + bool isTrendBullishPrev = + pTrendState > 0; + + // + bool isTrendSwitchedToBullish = isTrendBullish && + !isTrendBullishPrev; + bool isTrendFinishedFromBullish = !isTrendBullish && + isTrendBullishPrev; + + // + // Bearish ... + + // + bool isTrendBearish = + cTrendState < 0; + bool isTrendBearishPrev = + pTrendState < 0; + + // + bool isTrendSwitchedToBearish = isTrendBearish && + !isTrendBearishPrev; + bool isTrendFinishedFromBearish = !isTrendBearish && + isTrendBearishPrev; + + // + // Summarizing Conditions ... + + // + result = false; + + // + bool hasStartCondition = + forBullish + ? isTrendFinishedFromBullish + : isTrendFinishedFromBearish; + bool hasContinuationCondition = + forBullish + ? isTrendBullish + : isTrendBearish; + bool hasEndCondition = + forBullish + ? isTrendSwitchedToBullish + : isTrendSwitchedToBearish; + + // + // ReInstance Pivot ... + if (hasStartCondition) + { + // + // Bullish ... + if (forBullish) + { + // + trendBullishPivot.Clean(); + + // + trendBullishPivot.symbol = symbol; + trendBullishPivot.period = period; + trendBullishPivot.type = XCA_TREND_BULL; + + // + trendBullishPivot.to = pBar.time; + trendBullishPivot.from = pBar.time; + trendBullishPivot.value = pTrend; + trendBullishPivot.reserve = pTrend; + } + + // + // Bearish ... + if (forBearish) + { + // + trendBearishPivot.Clean(); + + // + trendBearishPivot.symbol = symbol; + trendBearishPivot.period = period; + trendBearishPivot.type = XCA_TREND_BEAR; + + // + trendBearishPivot.to = pBar.time; + trendBearishPivot.from = pBar.time; + trendBearishPivot.value = pTrend; + trendBearishPivot.reserve = pTrend; + } + } + + // + // Calculate and Fill Pivot Requirements ... + if (hasContinuationCondition) + { + // + // Bullish ... + if (forBullish) + { + // + trendBullishPivot.from = pBar.time; + + // + Add( + pTrend, + trendBullishPivot.values // + ); + Add( + pTrend, + trendBullishPivot.values // + ); + } + + // + // Bearish ... + if (forBearish) + { + // + trendBearishPivot.from = pBar.time; + + // + Add( + pTrend, + trendBearishPivot.values // + ); + Add( + pTrend, + trendBearishPivot.values // + ); + } + } + + // + // End up Pivot and Store it ... + if (hasEndCondition) + { + // + // Bullish ... + if (forBullish) + { + // + // Update Values ... + trendBullishPivot.value = GetMin(trendBullishPivot.values); + trendBullishPivot.reserve = GetMax(trendBullishPivot.values); + + // + result = + trendBullishPivot.IsValid() && + trendBullishPivot.GetAge() >= pivotVerifications; + if (result) + { + // + XBoxZone iBox; + result = trendBullishPivot.AsBox(iBox); + if (result) + { + // + newTrendBullishPivotDetected = AddBox( + iBox, + trendBullishPivots // + ); + } + + // + iBox.Clean(); + } + + // + trendBullishPivot.Clean(); + } + + // + // Bearish ... + if (forBearish) + { + // + // Update Values ... + trendBearishPivot.value = GetMax(trendBearishPivot.values); + trendBearishPivot.reserve = GetMin(trendBearishPivot.values); + + // + result = + trendBearishPivot.IsValid() && + trendBearishPivot.GetAge() >= pivotVerifications; + if (result) + { + // + XBoxZone iBox; + result = trendBearishPivot.AsBox(iBox); + if (result) + { + // + newTrendBearishPivotDetected = AddBox( + iBox, + trendBearishPivots // + ); + } + + // + iBox.Clean(); + } + + // + trendBearishPivot.Clean(); + } + } + + // + return result; + } + + // + void ValidateTrendPivots( + XBoxZone &unavailables[], + int barIndex = 0 // + ) + { + // + bool has = false; + + // + bool applyLifetimeValidating = maxAllowedTrendLifetime > 0; + + // + // Bullish ... + has = HasTrendBullishPivots(); + if (has) + { + // + ApplyValidationOnBoxes( + trendBullishPivots, + unavailables, + barIndex // + ); + + // + if (applyLifetimeValidating) + { + // + ApplyLifeTimeValidationOnBoxes( + trendBullishPivots, + maxAllowedTrendLifetime, + barIndex // + ); + } + } + + // + // Bearish ... + has = HasTrendBearishPivots(); + if (has) + { + // + ApplyValidationOnBoxes( + trendBearishPivots, + unavailables, + barIndex // + ); + + // + if (applyLifetimeValidating) + { + // + ApplyLifeTimeValidationOnBoxes( + trendBearishPivots, + maxAllowedTrendLifetime, + barIndex // + ); + } + } + } + + // + // Bullish ... + + // + XCAPivot trendBullishPivot; + XBoxZone trendBullishPivots[]; + bool detectTrendBullishPivots; + bool newTrendBullishPivotDetected; + + // + bool HasTrendBullishPivots() + { + return HasChild(trendBullishPivots); + } + + // + int CountTrendBullishPivots() + { + return ArraySize(trendBullishPivots); + } + + // + // Bearish ... + + // + XCAPivot trendBearishPivot; + XBoxZone trendBearishPivots[]; + bool detectTrendBearishPivots; + bool newTrendBearishPivotDetected; + + // + bool HasTrendBearishPivots() + { + return HasChild(trendBearishPivots); + } + + // + int CountTrendBearishPivots() + { + return ArraySize(trendBearishPivots); + } + + // + // Protected ... + protected: + // + // Props ... + + // + // Prrivate ... + private: + // + // Props ... + + // + XCPOIDrawer *drawer; + XCXCAEAHelper *helper; + XCBarAnalyser *barAnalyser; + + // + 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 CleanPivots() + { + // + Clean(invalidPivots); + + // + peakPivot.Clean(); + valePivot.Clean(); + trendBullishPivot.Clean(); + trendBearishPivot.Clean(); + + // + Clean(peakPivots); + Clean(valePivots); + + // + Clean(fvgBullishPivots); + Clean(fvgBearishPivots); + + // + Clean(trendBullishPivots); + Clean(trendBearishPivots); + } + + // + 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); + } + + // + // FVG ... + + // + // Bullish ... + has = HasFVGBullishPivots(); + if (has) + { + ApplySortOnBoxes(fvgBullishPivots); + } + + // + // Bearish ... + has = HasFVGBearishPivots(); + if (has) + { + ApplySortOnBoxes(fvgBearishPivots); + } + + // + // TREND ... + + // + // Bullish ... + has = HasTrendBullishPivots(); + if (has) + { + ApplySortOnBoxes(trendBullishPivots); + } + + // + // Bearish ... + has = HasTrendBearishPivots(); + if (has) + { + ApplySortOnBoxes(trendBearishPivots); + } + } + + // + 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); + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14040218 XCAEA/XCAEA/Classes/xcaea.x-poi.drawer.class.mq5 b/BKPS/14040218 XCAEA/XCAEA/Classes/xcaea.x-poi.drawer.class.mq5 new file mode 100644 index 0000000..c115473 --- /dev/null +++ b/BKPS/14040218 XCAEA/XCAEA/Classes/xcaea.x-poi.drawer.class.mq5 @@ -0,0 +1,932 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XCXCAEAPOIDrawer ... +// Description: Class for XCAEA POI Drawer ... +// +// +// 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 XCAEA POI Drawer" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../Classes/xcaea.x-poi.detector.class.mq5" + +// +// Definitions ... +struct XCAPivotStyle +{ + // + // Properties ... + int width; + color clr; + ENUM_LINE_STYLE style; + + // + // Constructor ... + XCAPivotStyle() + { + 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 XCXCAEAPOIDrawer : public XCBase +{ + // + // Public ... + public: + // + // Props ... + + // + bool ignoreUpdateOSCTos; + + // + // Drawers ... + bool drawPeakPivots; + bool drawValePivots; + bool drawFVGBullishPivots; + bool drawFVGBearishPivots; + bool drawTrendBullishPivots; + bool drawTrendBearishPivots; + + // + // Styling ... + + // + XCAPivotStyle defaultBullishStyle; + XCAPivotStyle defaultBearishStyle; + + // + XCAPivotStyle peakPivotStyle; + XCAPivotStyle valePivotStyle; + + // + XCAPivotStyle fvgBullishPivotStyle; + XCAPivotStyle fvgBearishPivotStyle; + + // + XCAPivotStyle trendBullishPivotStyle; + XCAPivotStyle trendBearishPivotStyle; + + // + // Constructors ... + XCXCAEAPOIDrawer( + XCXCAEAPOIDetector *_detector // + ) + { + // + detector = _detector; + drawer = new XCPOIDrawer(); + + // + Default(); + } + + // + // De Constructors ... + ~XCXCAEAPOIDrawer() + { + // + Clear(); + + // + ZeroMemory(drawer); + ZeroMemory(detector); + } + + // + // Properties ... + + // + // Tools ... + + // + virtual void Default() + { + // + // Drawing ... + drawPeakPivots = false; + drawValePivots = false; + drawFVGBullishPivots = false; + drawFVGBearishPivots = false; + drawTrendBullishPivots = false; + drawTrendBearishPivots = 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; + + // + // FVG ... + fvgBullishPivotStyle = defaultBullishStyle; + fvgBearishPivotStyle = defaultBearishStyle; + + // + // TREND ... + trendBullishPivotStyle = defaultBullishStyle; + trendBearishPivotStyle = defaultBearishStyle; + } + + // + void Draw(datetime to = NULL) + { + // + // PV ... + DrawPeakPivots(to); + DrawValePivots(to); + + // + // FVG ... + DrawFVGBullishPivots(to); + DrawFVGBearishPivots(to); + + // + // TREND ... + DrawTrendBullishPivots(to); + DrawTrendBearishPivots(to); + } + + // + void DrawBox( + XBoxZone &box, + datetime to = NULL // + ) + { + // + bool has = box.IsValid(); + if (!has) + { + return; + } + // + // Detect Pivot Type ... + ENUM_XCA_PIVOTS iType = GetPivotType(box); + has = IsValid(iType); + if (!has) + { + return; + } + + // + switch (iType) + { + // + case XCA_PEAK: + // + DrawPeakPivot( + box, + to // + ); + break; + + // + case XCA_VALE: + // + DrawValePivot( + box, + to // + ); + break; + + // + case XCA_FVG_BULL: + // + DrawFVGBullishPivot( + box, + to // + ); + break; + + // + case XCA_FVG_BEAR: + // + DrawFVGBearishPivot( + box, + to // + ); + break; + + // + case XCA_TREND_BULL: + // + DrawTrendBullishPivot( + box, + to // + ); + break; + + // + case XCA_TREND_BEAR: + // + DrawTrendBearishPivot( + box, + to // + ); + break; + } + } + + // + void DrawBoxes( + XBoxZone &boxes[], + datetime to = NULL // + ) + { + // + 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 // + ); + + // + iBox.Clean(); + } + } + + // + void Clear() + { + // + // Cleanup Models ... + defaultBullishStyle.Clean(); + defaultBearishStyle.Clean(); + + // + // Cleanup Styles ... + peakPivotStyle.Clean(); + valePivotStyle.Clean(); + fvgBullishPivotStyle.Clean(); + fvgBearishPivotStyle.Clean(); + trendBullishPivotStyle.Clean(); + trendBearishPivotStyle.Clean(); + + // + // Cleanup Pivot Objects Holder ... + mPeakPivotObjects.Clear(); + mValePivotObjects.Clear(); + mFVGBullishPivotObjects.Clear(); + mFVGBearishPivotObjects.Clear(); + mTrendBullishPivotObjects.Clear(); + mTrendBearishPivotObjects.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 DrawFVGBullishPivots(datetime to = NULL) + { + // + bool has = drawFVGBullishPivots; + if (!has) + { + return; + } + + // + has = detector.HasFVGBullishPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountFVGBullishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = detector.fvgBullishPivots[i]; + + // + DrawFVGBullishPivot( + iBox, + to // + ); + + // + iBox.Clean(); + } + } + + // + void DrawFVGBearishPivots(datetime to = NULL) + { + // + bool has = drawFVGBearishPivots; + if (!has) + { + return; + } + + // + has = detector.HasFVGBearishPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountFVGBearishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = detector.fvgBearishPivots[i]; + + // + DrawFVGBearishPivot( + iBox, + to // + ); + + // + iBox.Clean(); + } + } + + // + void DrawTrendBullishPivots(datetime to = NULL) + { + // + bool has = drawTrendBullishPivots; + if (!has) + { + return; + } + + // + has = detector.HasTrendBullishPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountTrendBullishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = detector.trendBullishPivots[i]; + + // + DrawTrendBullishPivot( + iBox, + to // + ); + + // + iBox.Clean(); + } + } + + // + void DrawTrendBearishPivots(datetime to = NULL) + { + // + bool has = drawTrendBearishPivots; + if (!has) + { + return; + } + + // + has = detector.HasTrendBearishPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountTrendBearishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = detector.trendBearishPivots[i]; + + // + DrawTrendBearishPivot( + 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(XCA_PEAK) && + item.dir == GetDirection(XCA_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(XCA_VALE) && + item.dir == GetDirection(XCA_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 DrawFVGBullishPivot( + XBoxZone &item, + datetime to = NULL // + ) + { + // + bool has = drawFVGBullishPivots; + if (!has) + { + return; + } + + // + has = item.IsValid() && + item.type == GetBoxType(XCA_FVG_BULL) && + item.dir == GetDirection(XCA_FVG_BULL); + 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, + fvgBullishPivotStyle // + ); + + // + // Store Object ... + mFVGBullishPivotObjects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + void DrawFVGBearishPivot( + XBoxZone &item, + datetime to = NULL // + ) + { + // + bool has = drawFVGBearishPivots; + if (!has) + { + return; + } + + // + has = item.IsValid() && + item.type == GetBoxType(XCA_FVG_BEAR) && + item.dir == GetDirection(XCA_FVG_BEAR); + 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, + fvgBearishPivotStyle // + ); + + // + // Store Object ... + mFVGBearishPivotObjects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + void DrawTrendBullishPivot( + XBoxZone &item, + datetime to = NULL // + ) + { + // + bool has = drawTrendBullishPivots; + if (!has) + { + return; + } + + // + has = item.IsValid() && + item.type == GetBoxType(XCA_TREND_BULL) && + item.dir == GetDirection(XCA_TREND_BULL); + 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, + trendBullishPivotStyle // + ); + + // + // Store Object ... + mTrendBullishPivotObjects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + void DrawTrendBearishPivot( + XBoxZone &item, + datetime to = NULL // + ) + { + // + bool has = drawTrendBearishPivots; + if (!has) + { + return; + } + + // + has = item.IsValid() && + item.type == GetBoxType(XCA_TREND_BEAR) && + item.dir == GetDirection(XCA_TREND_BEAR); + 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, + trendBearishPivotStyle // + ); + + // + // Store Object ... + mTrendBearishPivotObjects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + // Protected ... + protected: + // + // Props ... + + // + void ApplyPivotStyle( + XCBoxObject *&object, + XCAPivotStyle &style // + ) + { + // + if (object == NULL) + { + return; + } + + // + object.BoxColor(style.clr); + object.BoxWidth(style.width); + object.BoxStyle(style.style); + } + + // + // Prrivate ... + private: + // + // Props ... + + // + XCPOIDrawer *drawer; + XCXCAEAPOIDetector *detector; + + // + CArrayObj mPeakPivotObjects; + CArrayObj mValePivotObjects; + + // + CArrayObj mFVGBullishPivotObjects; + CArrayObj mFVGBearishPivotObjects; + + // + CArrayObj mTrendBullishPivotObjects; + CArrayObj mTrendBearishPivotObjects; + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14040218 XCAEA/XCAEA/Classes/xcaea.x-trade.manager.class.mq5 b/BKPS/14040218 XCAEA/XCAEA/Classes/xcaea.x-trade.manager.class.mq5 new file mode 100644 index 0000000..e9c2499 --- /dev/null +++ b/BKPS/14040218 XCAEA/XCAEA/Classes/xcaea.x-trade.manager.class.mq5 @@ -0,0 +1,1419 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XCXCAEATradeManager +// 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-poi.drawer.class.mq5" +#include "../../Classes/x-saherelm.x-trade.class.mq5" +#include "../Classes/xcaea.x-data.collector.class.mq5" +#include "../Libraries/xcaea.signaller.lib.mq5" + +// +// Definitions ... + +// +enum ENUM_XCAEA_TRADE_FINALIZATION +{ + XCAEA_TRADE_FINAL_NONE, // None + XCAEA_TRADE_FINAL_TP, // TP + XCAEA_TRADE_FINAL_SL, // SL + XCAEA_TRADE_FINAL_CLOSE_IN_PROFIT, // Profit + XCAEA_TRADE_FINAL_CLOSE_IN_LOSE, // Lost +}; + +string ToString(ENUM_XCAEA_TRADE_FINALIZATION value) +{ + // + string result = NULL; + + // + result = EnumToString(value); + + // + return result; +} + +// +struct XCAEATrade +{ + // + // Props ... + double swap; + double profit; + XSignal signal; + ulong positionID; + double commission; + XCAEAStrategyConditions conditions; + ENUM_XCAEA_TRADE_FINALIZATION finalize; + + // + datetime signaledAt; + datetime executedAt; + datetime finalizedAt; + + // + // Constructor ... + XCAEATrade() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup Model ... + */ + void Clean() + { + // + swap = 0; + profit = 0; + signal.Clean(); + commission = 0; + positionID = 0; + conditions.Clean(); + finalize = XCAEA_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 != XCAEA_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( + true, + 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; + } +}; + +// +// Implementations ... +class XCXCAEATradeManager : public XCBaseAlert +{ + // + // Public ... + public: + // + // Props ... + XCTrade *trader; + bool drawSignal; + XCPOIDrawer *drawer; + XCXCAEADataCollector *collector; + + // + // Constructors ... + XCXCAEATradeManager( + XCTrade *&_trader, + string _path = NULL // Base Path + ) + { + // + trader = _trader; + drawSignal = true; + drawer = new XCPOIDrawer(); + + // + allowTrade = true; + allowLongs = true; + allowShorts = true; + + // + reportTrades = true; + reportSignals = true; + reportProtector = true; + reportAfterTradesBalance = true; + + // + SaveTrades(false); + + // + // Normalizing Collector Path ... + if (!IsValid(_path)) + { + _path = "X121XCAEATradeManager" + "\\" + trader.mAccount.GetCompany(); + } + + // + collector = new XCXCAEADataCollector(); + collector.Path(_path); + } + + // + // De Constructors ... + ~XCXCAEATradeManager() + { + // + Clean(trades); + + // + ZeroMemory(trader); + ZeroMemory(drawer); + ZeroMemory(collector); + } + + // + // Properties ... + + // + bool SaveTrades() + { + return mSaveTrades; + } + + // + void SaveTrades(bool value) + { + mSaveTrades = value; + } + + // + // TODO: Implement this ... + void SetTradeSession( + string start, + string end // + ) + { + // + bool has = IsValid(start) || + IsValid(end); + if (!has) + { + return; + } + + // + } + + // + void SetTradeReports( + bool _reportTrades, + bool _reportSignals, + bool _reportProtector, + bool _reportAfterTradesBalance // + ) + { + // + reportTrades = _reportTrades; + reportSignals = _reportSignals; + reportProtector = _reportProtector; + reportAfterTradesBalance = _reportAfterTradesBalance; + } + + // + void SetTradePermissions( + bool _allowTrade, + bool _allowLongs, + bool _allowShorts // + ) + { + // + allowTrade = _allowTrade; + allowLongs = _allowLongs; + allowShorts = _allowShorts; + } + + // + // Tools ... + + /** + * Do All Position Managing Senaros ... + */ + void Manage() + { + // + bool has = HasChild(trades); + if (!has) + { + return; + } + + // + 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; + } + + // + // After Update All Trades we can Do 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 ... + // TODO: Implement this ... + + // + // 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 ... + double targets[]; + Copy( + trades[idx].signal.targets, + targets // + ); + int targetsCount = ArraySize(targets); + has = IsValidSize(targetsCount); + if (has) + { + // + for (int j = 0; j < targetsCount; j++) + { + // + double 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 + : iPosition.sl > jTarget; + if (!has) + { + continue; + } + + // + double targetDelta = isLong + ? jTarget + (targetDistance * points) + : jTarget - (targetDistance * points); + + // + // Can Risk Free ... + bool canRF = jTarget > 0 && + (isLong + ? jTarget > iPosition.entry + : jTarget < iPosition.entry) && + (isLong + ? iPosition.price > targetDelta + : iPosition.price < targetDelta); + if (canRF) + { + // + double sl = jTarget; + double tp = iPosition.tp; + string comment = "RF On Target ..."; + bool isModified = trader.Modify( + iPosition.ticket, + sl, + tp, + comment // + ); + if (isModified) + { + // + trades[idx].signal.appliedTargetIDX = j; + trades[idx].signal.isTargetApplied = true; + + // + string message = prefix + + ToString(iPosition.type) + + " Position: " + + ToString(iPosition.ticket) + + " RF On Traget: " + ToString(jTarget) + + " Successfully ..."; + HandleReportProtector(message); + } + } + } + } + + // + // Handle Partial Close on Specified Targets ... + has = !trades[idx].signal.isPartiallyClosed && + trades[idx].signal.partialCloseOnTPLevel > 0 && + trades[idx].signal.partialCloseMultiplier > 0; + if (has) + { + // + // Check Reward Touched ... + double iCurrReward = iPosition.CalculateTouchedReward(); + has = iCurrReward >= trades[idx].signal.partialCloseOnTPLevel; + if (has) + { + // + // Check Volume Multiplier ... + double volumeMultiplier = trades[idx].signal.partialCloseMultiplier; + has = volumeMultiplier > 0 && + volumeMultiplier <= 1; + if (has) + { + // + // Do Partial Closing ... + double volume = iPosition.volume * volumeMultiplier; + + // + // Normalizing Volume ... + volume = NormalizeVolume( + volume, + iPosition.symbol // + ); + + // + string comment = "PC On Target ..."; + has = trader.ClosePartial( + iPosition.ticket, + volume, + comment // + ); + if (has) + { + // + // Update Model ... + trades[idx].signal.isPartiallyClosed = true; + + // + string message = prefix + + ToString(iPosition.type) + + " Position: " + + ToString(iPosition.ticket) + + " PC (" + ToString(volume) + ") On Traget: " + ToString(iCurrReward) + + " Successfully ..."; + HandleReportProtector(message); + } + } + } + } + } + } + } + + /** + * 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(message); + } + + // + // 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; + } + + // + // TODO: Complete this ... + // Implementing Trade Session Validating ... + + // + // TODO: Complete this ... + // Implementing Trade Permissions Based on SL(s) Count ... + + // + return result; + } + + /** + * Execute Specified Signal ... + * + * @param signal: XSignal instance reference ... + * @param conditions: XCAEAStrategyConditions instance reference ... + * + * @return ( bool ) + */ + bool Execute( + XSignal &signal, + XCAEAStrategyConditions &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(message); + } + + // + if (result) + { + // + if (drawSignal) + { + // + XCSignalObject *iObj; + isExists = drawer.DrawSignal( + signal, + iObj // + ); + + // + if (isExists) + { + // + mObjects.Add(iObj); + ZeroMemory(iObj); + } + } + + // + XCAEATrade 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; + } + + /** + * 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 = XCAEA_TRADE_FINAL_TP; + + // + tpCount++; + managedTPCount++; + + // + // Save Trade ... + Save(trades[idx]); + + // + // Handle Balance Reporting ... + string prefix = "TP: " + ToString(trades[idx].profit); + HandleReportBalance(prefix); + + // + 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 = XCAEA_TRADE_FINAL_SL; + + // + slCount++; + managedSLCount++; + + // + // Save Trade ... + Save(trades[idx]); + + // + // Handle Balance Reporting ... + string prefix = "SL: " + ToString(trades[idx].profit); + HandleReportBalance(prefix); + + // + 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 + ? XCAEA_TRADE_FINAL_CLOSE_IN_PROFIT + : XCAEA_TRADE_FINAL_CLOSE_IN_LOSE; + + // + if (isInProfit) + { + // + tpCount++; + managedTPCount++; + } + else + { + // + slCount++; + managedSLCount++; + } + + // + // Save Trade ... + Save(trades[idx]); + + // + // Handle Balance Reporting ... + string prefix = "Force Close " + + (isInProfit + ? "Profit" + : "Loss") + + ": " + + ToString(trades[idx].profit); + HandleReportBalance(prefix); + + // + RemoveTrade(idx); + } + + // + // TODO: Complete this ... + void HandleGuard() + { + } + + /** + * Handle New Day ... + */ + void HandleNewDay() + { + // + // Clean Managed SL(s) and TP(s) and Positions ... + } + + /** + * 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++) + { + // + XCAEATrade 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++) + { + // + XCAEATrade 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 GetFilePath(XCAEATrade &trade) + { + // + string fileName = trade.GetFileName(); + + // + return GetFilePath(fileName); + } + + // + string GetFilePath(string fileName) + { + // + string result = NULL; + + // + string mPath = collector.Path(); + + // + result = + // + mPath + "\\" + "Trades" + "\\" + fileName + ".x121.log" + // + ; + + // + 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 + "\n" + : "") + + "Account Balance: " + ToString(balance) + currency; + Alert(message); + } + + // + void HandleReportProtector(string message = NULL) + { + // + if (!reportProtector) + { + return; + } + + // + Alert(message); + } + + // + bool Save( + XCAEATrade &trade, + bool includeSummary = true, + bool includeSignal = true, + bool includeConditions = true // + ) + { + // + bool result = false; + + // + if (!mSaveTrades) + { + return result; + } + + // + string filePath = GetFilePath(trade); + result = IsValid(filePath); + if (!result) + { + return result; + } + + // + string content = trade.ToString( + includeSummary, + includeSignal, + includeConditions // + ); + + // + result = collector.Save( + filePath, + content // + ); + + // + return result; + } + + // + // Private ... + private: + // + // Props ... + + // + bool allowTrade; + bool allowLongs; + bool allowShorts; + + // + bool mSaveTrades; + + // + int slCount; + int tpCount; + + // + int managedSLCount; + int managedTPCount; + + // + bool reportTrades; + bool reportSignals; + bool reportProtector; + bool reportAfterTradesBalance; + + // + CArrayObj mObjects; + + // + XCAEATrade trades[]; +}; + +// diff --git a/BKPS/14040218 XCAEA/XCAEA/Helpers/xcaea.helper.mq5 b/BKPS/14040218 XCAEA/XCAEA/Helpers/xcaea.helper.mq5 new file mode 100644 index 0000000..b184578 --- /dev/null +++ b/BKPS/14040218 XCAEA/XCAEA/Helpers/xcaea.helper.mq5 @@ -0,0 +1,4175 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XCXCAEAHelper +// 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-bar.analyser.class.mq5" +#include "../../Classes/x-saherelm.x-poi.class.mq5" +#include "../../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../../Helpers/x-saherelm.x121.x3ma.helper.mq5" +#include "../../Helpers/x-saherelm.x121.xca.helper.mq5" +#include "../../Helpers/x-saherelm.x121.xcc.helper.mq5" +#include "../../Helpers/x-saherelm.x121.xct.helper.mq5" +#include "../../Helpers/x-saherelm.x121.xoscs.helper.mq5" + +// +// Input Structure ... +struct XCAEAInputs +{ + // + bool showAC; + bool showAD; + bool showADX; + bool showATR; + bool showCCI; + bool showRSI; + bool showMFI; + bool showRVI; + bool showMACD; + bool showMomentum; + bool showStochastic; + + // + X121XCTInputs ctInputs; + X121XCCInputs ccInputs; + X121XCAInputs caInputs; + X121X3MAInputs x3maInputs; + X121XOCSInputs oscsInputs; + + // + // Constructor ... + XCAEAInputs() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + showAC = false; + showAD = false; + showADX = false; + showATR = false; + showCCI = false; + showRSI = false; + showMFI = false; + showRVI = false; + showMACD = false; + showMomentum = false; + showStochastic = false; + + // + ctInputs.Clean(); + ccInputs.Clean(); + caInputs.Clean(); + x3maInputs.Clean(); + oscsInputs.Clean(); + + // + ZeroMemory(this); + } + + /** + * Set Default Values ... + */ + void Default() + { + // + ctInputs.Default(); + ccInputs.Default(); + caInputs.Default(); + x3maInputs.Default(); + oscsInputs.Default(); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + // + ctInputs.IsValid() && + ccInputs.IsValid() && + caInputs.IsValid() && + x3maInputs.IsValid() && + oscsInputs.IsValid() + // + ; + + // + return result; + } + + /** + * Extract Max Input Length ... + * + * @return ( int ) + */ + int Max() + { + // + int result = 0; + + // + int ctMax = ctInputs.Max(); + int ccMax = ccInputs.Max(); + int caMax = caInputs.Max(); + int ocsMax = oscsInputs.Max(); + int x3maMax = x3maInputs.Max(); + + // + result = MathMax(ctMax, ccMax); + result = MathMax(result, caMax); + result = MathMax(result, ocsMax); + result = MathMax(result, x3maMax); + + // + return result; + } +}; + +// +// Conditions Structure ... +struct XCAEAConditions +{ + // + // Common ... + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + datetime to; + datetime from; + + // + // Bars ... + XOHCL bars[]; + double bodies[]; + double ranges[]; + double velocities[]; + double scoreBullish; + double scoreBearish; + double volumeBullish; + double volumeBearish; + double priceChangeRate; + + // + // X3MA ... + + // + // 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; + + // + // XCA ... + + // + // 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; + + // + // XOSCS ... + + // + // 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; + double cciOBLevel; + double cciOSLevel; + double cciReversalLevel; + double rsiOBLevel; + double rsiOSLevel; + double rsiReversalLevel; + double mfiOBLevel; + double mfiOSLevel; + double mfiReversalLevel; + double rviBullishLevel; + double rviBearishLevel; + double macdBullishLevel; + double macdBearishLevel; + double momentumBullishLevel; + double momentumBearishLevel; + double stochasticOBLevel; + double stochasticOSLevel; + double stochasticReversalLevel; + + // + // 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; + + // + // Specified Conditions ... + + // + // Constructor ... + XCAEAConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + // Commons ... + symbol = NULL; + period = NULL; + + // + to = NULL; + from = NULL; + time = NULL; + + // + // Bars ... + Clean(bars); + Clean(bodies); + Clean(ranges); + scoreBullish = 0; + scoreBearish = 0; + volumeBullish = 0; + volumeBearish = 0; + Clean(velocities); + priceChangeRate = 0; + ArraySetAsSeries(bars, true); + ArraySetAsSeries(bodies, true); + ArraySetAsSeries(ranges, true); + ArraySetAsSeries(velocities, true); + + // + // X3MA ... + + // + // 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; + + // + // XCA ... + + // + // 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; + + // + // XOSCS ... + + // + // 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; + + // + // X3MA ... + + // + // XCA ... + + // + 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; + } + // + // 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; + } + + // + // XOCS ... + + // + // 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 + + "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) + + "-----------------------" + 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) + + "-----------------------" + separator + + "XOCS: " + 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) + + // + "" + // + ; + + // + if (onlyCommons && !onlyConditions) + { + result += commonStr = separator; + } + else if (onlyConditions && !onlyCommons) + { + result += conditionsStr + separator; + } + else + { + // + result += + // + commonStr + separator + + conditionsStr + separator + // + ; + } + + // + return result; + } + + /** + * Retrieve nique Tag Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + return GetTypeName(this); + } +}; + +// +// Helper Class Implementation ... +class XCXCAEAHelper : XCBase +{ + // + // Public ... + public: + // + // Props ... + + // + XCPOIDrawer *poiDrawer; + XCPOIDetector *poiDetector; + + // + XCBarAnalyser *barAnalyser; + + // + XCX121XCCHelper *ccHelper; + XCX121XCTHelper *ctHelper; + XCX121XCAHelper *caHelper; + XCX121XOCSHelper *ocsHelper; + XCX121X3MAHelper *x3maHelper; + + // + // Constructor ... + XCXCAEAHelper() + { + // + barAnalyser = new XCBarAnalyser(); + } + + // + // Deconstructor ... + ~XCXCAEAHelper() + { + // + mInputs.Clean(); + + // + ZeroMemory(ccHelper); + ZeroMemory(ctHelper); + ZeroMemory(caHelper); + ZeroMemory(ocsHelper); + ZeroMemory(x3maHelper); + + // + ZeroMemory(poiDrawer); + ZeroMemory(poiDetector); + ZeroMemory(barAnalyser); + + // + IndicatorRelease(acHandler); + IndicatorRelease(adHandler); + IndicatorRelease(adxHandler); + IndicatorRelease(atrHandler); + IndicatorRelease(cciHandler); + IndicatorRelease(rsiHandler); + IndicatorRelease(mfiHandler); + IndicatorRelease(rviHandler); + IndicatorRelease(macdHandler); + IndicatorRelease(momentumHandler); + IndicatorRelease(stochasticHandler); + } + + // + string GetSymbol() + { + return mSymbol; + } + + // + ENUM_TIMEFRAMES GetPeriod() + { + return mPeriod; + } + + // + // Tools ... + + /** + * Initialize Indicator Helper ... + * + * @param symbol: String, Symbol ... + * @param period: ENUM_TIMEFRAMES member, Period ... + * @param inputs: XCAEAInputs instance, Indicator Inputs ... + * + * @return ( bool ) + */ + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + XCAEAInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + result = + IsValid(symbol) && + IsValid(period) && + inputs.IsValid(); + if (!result) + { + return result; + } + + // + mSymbol = symbol; + mPeriod = period; + + // + poiDetector = new XCPOIDetector( + symbol, + period // + ); + poiDetector.Init(); + + // + poiDrawer = new XCPOIDrawer(); + + // + // Setting Inputs ... + + // + mInputs = inputs; + + // + // Initial Helpers ... + + // + // XCT ... + ctHelper = new XCX121XCTHelper(); + result = + result && + ctHelper.Init( + symbol, + period, + mInputs.ctInputs // + ); + + // + // XCC ... + ccHelper = new XCX121XCCHelper(); + result = + result && + ccHelper.Init( + symbol, + period, + mInputs.ccInputs // + ); + + // + // XCA ... + caHelper = new XCX121XCAHelper(); + result = + result && + caHelper.Init( + symbol, + period, + mInputs.caInputs // + ); + + // + // XOSC ... + ocsHelper = new XCX121XOCSHelper(); + result = + result && + ocsHelper.Init( + symbol, + period, + mInputs.oscsInputs // + ); + + // + // X3MA ... + x3maHelper = new XCX121X3MAHelper(); + result = + result && + x3maHelper.Init( + symbol, + period, + mInputs.x3maInputs // + ); + + // + if (!result) + { + // + ZeroMemory(ccHelper); + ZeroMemory(ctHelper); + ZeroMemory(caHelper); + ZeroMemory(ocsHelper); + ZeroMemory(x3maHelper); + + // + ZeroMemory(poiDrawer); + ZeroMemory(poiDetector); + + // + return result; + } + + // + // OSCILLATORS Viewers ... + + // + // AC ... + if (mInputs.showAC) + { + // + acHandler = iAC( + symbol, + period // + ); + + // + result = + result && + acHandler != INVALID_HANDLE; + } + + // + // AD ... + if (mInputs.showAD) + { + // + adHandler = iAD( + symbol, + period, + mInputs.oscsInputs.adAppliedTo // + ); + + // + result = + result && + adHandler != INVALID_HANDLE; + } + + // + // ADX ... + if (mInputs.showADX) + { + // + adxHandler = iADX( + symbol, + period, + mInputs.oscsInputs.adxLength // + ); + + // + result = + result && + adxHandler != INVALID_HANDLE; + } + + // + // ATR ... + if (mInputs.showATR) + { + // + atrHandler = iATR( + symbol, + period, + mInputs.oscsInputs.atrLength // + ); + + // + result = + result && + atrHandler != INVALID_HANDLE; + } + + // + // CCI ... + if (mInputs.showCCI) + { + // + cciHandler = iCCI( + symbol, + period, + mInputs.oscsInputs.cciLength, + mInputs.oscsInputs.cciAppliedTo // + ); + + // + result = + result && + cciHandler != INVALID_HANDLE; + } + + // + // RSI ... + if (mInputs.showRSI) + { + // + rsiHandler = iRSI( + symbol, + period, + mInputs.oscsInputs.rsiLength, + mInputs.oscsInputs.rsiAppliedTo // + ); + + // + result = + result && + rsiHandler != INVALID_HANDLE; + } + + // + // MFI ... + if (mInputs.showMFI) + { + // + mfiHandler = iMFI( + symbol, + period, + mInputs.oscsInputs.mfiLength, + mInputs.oscsInputs.mfiAppliedTo // + ); + + // + result = + result && + mfiHandler != INVALID_HANDLE; + } + + // + // RVI ... + if (mInputs.showRVI) + { + // + rviHandler = iRVI( + symbol, + period, + mInputs.oscsInputs.rviLength // + ); + + // + result = + result && + rviHandler != INVALID_HANDLE; + } + + // + // MACD ... + if (mInputs.showMACD) + { + // + macdHandler = iMACD( + symbol, + period, + mInputs.oscsInputs.macdFastLength, + mInputs.oscsInputs.macdSlowLength, + mInputs.oscsInputs.macdSignalLength, + mInputs.oscsInputs.macdAppliedTo // + ); + + // + result = + result && + macdHandler != INVALID_HANDLE; + } + + // + // Momentum ... + if (mInputs.showMomentum) + { + // + momentumHandler = iMomentum( + symbol, + period, + mInputs.oscsInputs.momentumLength, + mInputs.oscsInputs.momentumAppliedTo // + ); + + // + result = + result && + momentumHandler != INVALID_HANDLE; + } + + // + // Stochastic ... + if (mInputs.showStochastic) + { + // + stochasticHandler = iStochastic( + symbol, + period, + mInputs.oscsInputs.stochasticKLength, + mInputs.oscsInputs.stochasticDLength, + mInputs.oscsInputs.stochasticSmoothingLength, + mInputs.oscsInputs.stochasticSmoothingMethod, + mInputs.oscsInputs.stochasticAppliedTo // + ); + + // + result = + result && + stochasticHandler != INVALID_HANDLE; + } + + // + // If Result is False, Cleanup Resources ... + if (!result) + { + // + mInputs.Clean(); + + // + ZeroMemory(ccHelper); + ZeroMemory(ctHelper); + ZeroMemory(caHelper); + ZeroMemory(ocsHelper); + ZeroMemory(x3maHelper); + + // + IndicatorRelease(acHandler); + IndicatorRelease(adHandler); + IndicatorRelease(adxHandler); + IndicatorRelease(atrHandler); + IndicatorRelease(cciHandler); + IndicatorRelease(rsiHandler); + IndicatorRelease(mfiHandler); + IndicatorRelease(rviHandler); + IndicatorRelease(macdHandler); + IndicatorRelease(momentumHandler); + IndicatorRelease(stochasticHandler); + + // + return result; + } + + // + return result; + } + + // + // Conditions Readers ... + + /** + * Retrieve Conditions ... + * + * @param conditions: Argument 1 + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Loopback looking for others ... + * + * @return ( bool ) + */ + bool Get3MAConditions( + X121X3MAConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = false; + + // + result = x3maHelper.GetConditions( + conditions, + barIndex, + loopback // + ); + + // + return result; + } + + /** + * Retrieve Conditions ... + * + * @param conditions: Argument 1 + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Loopback looking for others ... + * + * @return ( bool ) + */ + bool GetCAConditions( + X121XCAConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = false; + + // + result = caHelper.GetConditions( + conditions, + barIndex, + loopback // + ); + + // + return result; + } + + /** + * Retrieve Conditions ... + * + * @param conditions: Argument 1 + * @param barIndex: int, Specified Bar Index ... + * @param loopback: int, Loopback looking for others ... + * + * @return ( bool ) + */ + bool GetOSCSConditions( + X121XOCSConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = false; + + // + result = ocsHelper.GetConditions( + conditions, + barIndex, + loopback // + ); + + // + return result; + } + + // + // Others ... + + // + void Free() + { + // + caHelper.Free(); + ocsHelper.Free(); + x3maHelper.Free(); + } + + // + bool GetConditions( + XCAEAConditions &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 zIndex = barIndex; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + XOHCL zBar; + XOHCL cBar; + XOHCL pBar; + XOHCL fromBar; + + // + X121XCAConditions xcaConditions; + X121XOCSConditions xocsConditions; + X121X3MAConditions x3maConditions; + + // + result = zBar.Init( + mSymbol, + mPeriod, + zIndex // + ); + result = + result && + zBar.GetPreviousBar(cBar); + result = + result && + cBar.GetPreviousBar(pBar); + result = + result && + fromBar.Init( + zBar.symbol, + zBar.period, + zIndex + loopback); + + // + // Conditions Retriever ... + + // + // XCA ... + result = + result && + GetCAConditions( + xcaConditions, + barIndex, + loopback // + ); + + // + // XOSCS ... + result = + result && + GetOSCSConditions( + xocsConditions, + barIndex, + loopback // + ); + + // + // X3MA ... + result = + result && + Get3MAConditions( + x3maConditions, + barIndex, + loopback // + ); + + // + // Check Result ... + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + fromBar.Clean(); + + // + xcaConditions.Clean(); + xocsConditions.Clean(); + x3maConditions.Clean(); + + // + return result; + } + + // + conditions.to = zBar.time; + conditions.from = fromBar.time; + + // + // Fill X121 Conditions Reference by Using + // Retrieved Conditions ... + + // + int cIDX = 1; + int pIDX = cIDX + 1; + + // + // X3MA ... + + // + // Buffers ... + + // + Copy( + x3maConditions.fastBuffer, + conditions.fastBuffer // + ); + + // + Copy( + x3maConditions.mediumBuffer, + conditions.mediumBuffer // + ); + + // + Copy( + x3maConditions.slowBuffer, + conditions.slowBuffer // + ); + + // + Copy( + x3maConditions.fastStateBuffer, + conditions.fastStateBuffer // + ); + + // + Copy( + x3maConditions.mediumStateBuffer, + conditions.mediumStateBuffer // + ); + + // + Copy( + x3maConditions.slowStateBuffer, + conditions.slowStateBuffer // + ); + + // + // Conditions ... + + // + conditions.is3MaBullish = x3maConditions.is3MaBullish; + conditions.is3MaBearish = x3maConditions.is3MaBearish; + conditions.isFastOverSlow = x3maConditions.isFastOverSlow; + conditions.isFastUnderSlow = x3maConditions.isFastUnderSlow; + conditions.isFastOverMedium = x3maConditions.isFastOverMedium; + conditions.isMediumOverSlow = x3maConditions.isMediumOverSlow; + conditions.isFastUnderMedium = x3maConditions.isFastUnderMedium; + conditions.isMediumUnderSlow = x3maConditions.isMediumUnderSlow; + conditions.is3MaBullishState = x3maConditions.is3MaBullishState; + conditions.is3MaBearishState = x3maConditions.is3MaBearishState; + conditions.is3MaBullishOrdered = x3maConditions.is3MaBullishOrdered; + conditions.is3MaBearishOrdered = x3maConditions.is3MaBearishOrdered; + conditions.isFastCrossedOverSlow = x3maConditions.isFastCrossedOverSlow; + conditions.is3MaSwitchedToBullish = x3maConditions.is3MaSwitchedToBullish; + conditions.is3MaSwitchedToBearish = x3maConditions.is3MaSwitchedToBearish; + conditions.isFastCrossedUnderSlow = x3maConditions.isFastCrossedUnderSlow; + conditions.isFastCrossedOverMedium = x3maConditions.isFastCrossedOverMedium; + conditions.isMediumCrossedOverSlow = x3maConditions.isMediumCrossedOverSlow; + conditions.is3MaFinishedFromBullish = x3maConditions.is3MaFinishedFromBullish; + conditions.is3MaFinishedFromBearish = x3maConditions.is3MaFinishedFromBearish; + conditions.isFastCrossedUnderMedium = x3maConditions.isFastCrossedUnderMedium; + conditions.isMediumCrossedUnderSlow = x3maConditions.isMediumCrossedUnderSlow; + conditions.is3MaSwitchedToBullishState = x3maConditions.is3MaSwitchedToBullishState; + conditions.is3MaSwitchedToBearishState = x3maConditions.is3MaSwitchedToBearishState; + conditions.is3MaSwitchedToBullishOrdered = x3maConditions.is3MaSwitchedToBullishOrdered; + conditions.is3MaSwitchedToBearishOrdered = x3maConditions.is3MaSwitchedToBearishOrdered; + + // + // XCA ... + + // + // Buffers ... + + // + Copy( + xcaConditions.kiBuffer, + conditions.kiBuffer // + ); + + // + Copy( + xcaConditions.tkiBuffer, + conditions.tkiBuffer // + ); + + // + Copy( + xcaConditions.vidyaBuffer, + conditions.vidyaBuffer // + ); + + // + Copy( + xcaConditions.sHHBuffer, + conditions.sHHBuffer // + ); + + // + Copy( + xcaConditions.sLLBuffer, + conditions.sLLBuffer // + ); + + // + Copy( + xcaConditions.mHHBuffer, + conditions.mHHBuffer // + ); + + // + Copy( + xcaConditions.mLLBuffer, + conditions.mLLBuffer // + ); + + // + Copy( + xcaConditions.lHHBuffer, + conditions.lHHBuffer // + ); + + // + Copy( + xcaConditions.lLLBuffer, + conditions.lLLBuffer // + ); + + // + Copy( + xcaConditions.hHHBuffer, + conditions.hHHBuffer // + ); + + // + Copy( + xcaConditions.hLLBuffer, + conditions.hLLBuffer // + ); + + // + Copy( + xcaConditions.sarBuffer, + conditions.sarBuffer // + ); + + // + Copy( + xcaConditions.mahBuffer, + conditions.mahBuffer // + ); + + // + Copy( + xcaConditions.malBuffer, + conditions.malBuffer // + ); + + // + Copy( + xcaConditions.macBuffer, + conditions.macBuffer // + ); + + // + Copy( + xcaConditions.peakBuffer, + conditions.peakBuffer // + ); + + // + Copy( + xcaConditions.valeBuffer, + conditions.valeBuffer // + ); + + // + Copy( + xcaConditions.trendBuffer, + conditions.trendBuffer // + ); + + // + Copy( + xcaConditions.kiStateBuffer, + conditions.kiStateBuffer // + ); + + // + Copy( + xcaConditions.tkiStateBuffer, + conditions.tkiStateBuffer // + ); + + // + Copy( + xcaConditions.vidyaStateBuffer, + conditions.vidyaStateBuffer // + ); + + // + Copy( + xcaConditions.supportBuffer, + conditions.supportBuffer // + ); + + // + Copy( + xcaConditions.swingLowBuffer, + conditions.swingLowBuffer // + ); + + // + Copy( + xcaConditions.swingHighBuffer, + conditions.swingHighBuffer // + ); + + // + Copy( + xcaConditions.resistanceBuffer, + conditions.resistanceBuffer // + ); + + // + Copy( + xcaConditions.peakGoldenBuffer, + conditions.peakGoldenBuffer // + ); + + // + Copy( + xcaConditions.valeGoldenBuffer, + conditions.valeGoldenBuffer // + ); + + // + Copy( + xcaConditions.fiboLevel1Buffer, + conditions.fiboLevel1Buffer // + ); + + // + Copy( + xcaConditions.fiboLevel2Buffer, + conditions.fiboLevel2Buffer // + ); + + // + Copy( + xcaConditions.fiboLevel3Buffer, + conditions.fiboLevel3Buffer // + ); + + // + Copy( + xcaConditions.fiboLevel4Buffer, + conditions.fiboLevel4Buffer // + ); + + // + Copy( + xcaConditions.fiboLevel5Buffer, + conditions.fiboLevel5Buffer // + ); + + // + Copy( + xcaConditions.trendStateBuffer, + conditions.trendStateBuffer // + ); + + // + // Conditions ... + + // + conditions.isOverMah = xcaConditions.isOverMah; + conditions.isOverMal = xcaConditions.isOverMal; + conditions.isOverMac = xcaConditions.isOverMac; + conditions.isUnderMah = xcaConditions.isUnderMah; + conditions.isUnderMal = xcaConditions.isUnderMal; + conditions.isUnderMac = xcaConditions.isUnderMac; + conditions.isKIBullish = xcaConditions.isKIBullish; + conditions.isKIBearish = xcaConditions.isKIBearish; + conditions.isKIRejectUp = xcaConditions.isKIRejectUp; + conditions.isTKIBullish = xcaConditions.isTKIBullish; + conditions.isTKIBearish = xcaConditions.isTKIBearish; + conditions.isSarBullish = xcaConditions.isSarBullish; + conditions.isSarBearish = xcaConditions.isSarBearish; + conditions.isTKIRejectUp = xcaConditions.isTKIRejectUp; + conditions.isPeakIsPivot = xcaConditions.isPeakIsPivot; + conditions.isValeIsPivot = xcaConditions.isValeIsPivot; + conditions.isCloseOverMah = xcaConditions.isCloseOverMah; + conditions.isCloseOverMal = xcaConditions.isCloseOverMal; + conditions.isCloseOverMac = xcaConditions.isCloseOverMac; + conditions.isVidyaBullish = xcaConditions.isVidyaBullish; + conditions.isVidyaBearish = xcaConditions.isVidyaBearish; + conditions.isKIRejectDown = xcaConditions.isKIRejectDown; + conditions.isPeakSameLast = xcaConditions.isPeakSameLast; + conditions.isPeakOverLast = xcaConditions.isPeakOverLast; + conditions.isValeSameLast = xcaConditions.isValeSameLast; + conditions.isValeOverLast = xcaConditions.isValeOverLast; + conditions.isTrendBullish = xcaConditions.isTrendBullish; + conditions.isTrendBearish = xcaConditions.isTrendBearish; + conditions.isCloseUnderMah = xcaConditions.isCloseUnderMah; + conditions.isCloseUnderMal = xcaConditions.isCloseUnderMal; + conditions.isCloseUnderMac = xcaConditions.isCloseUnderMac; + conditions.isTKIRejectDown = xcaConditions.isTKIRejectDown; + conditions.isPeakUnderLast = xcaConditions.isPeakUnderLast; + conditions.isValeUnderLast = xcaConditions.isValeUnderLast; + conditions.isTrendRejectUp = xcaConditions.isTrendRejectUp; + conditions.isCrossedOverMah = xcaConditions.isCrossedOverMah; + conditions.isCrossedOverMal = xcaConditions.isCrossedOverMal; + conditions.isCrossedOverMac = xcaConditions.isCrossedOverMac; + conditions.isCrossedUnderMah = xcaConditions.isCrossedUnderMah; + conditions.isCrossedUnderMal = xcaConditions.isCrossedUnderMal; + conditions.isCrossedUnderMac = xcaConditions.isCrossedUnderMac; + conditions.isTrendRejectDown = xcaConditions.isTrendRejectDown; + conditions.isSupportSameLast = xcaConditions.isSupportSameLast; + conditions.isSupportOverLast = xcaConditions.isSupportOverLast; + conditions.isSupportUnderLast = xcaConditions.isSupportUnderLast; + conditions.isSwingLowSameLast = xcaConditions.isSwingLowSameLast; + conditions.isSwingLowOverLast = xcaConditions.isSwingLowOverLast; + conditions.isSwingLowUnderLast = xcaConditions.isSwingLowUnderLast; + conditions.isSwingHighSameLast = xcaConditions.isSwingHighSameLast; + conditions.isSwingHighOverLast = xcaConditions.isSwingHighOverLast; + conditions.isSupportSameAsVale = xcaConditions.isSupportSameAsVale; + conditions.isMahBullishRejected = xcaConditions.isMahBullishRejected; + conditions.isMahBearishRejected = xcaConditions.isMahBearishRejected; + conditions.isMalBullishRejected = xcaConditions.isMalBullishRejected; + conditions.isMalBearishRejected = xcaConditions.isMalBearishRejected; + conditions.isMacBullishRejected = xcaConditions.isMacBullishRejected; + conditions.isMacBearishRejected = xcaConditions.isMacBearishRejected; + conditions.isLastSupportBreaked = xcaConditions.isLastSupportBreaked; + conditions.isResistanceSameLast = xcaConditions.isResistanceSameLast; + conditions.isResistanceOverLast = xcaConditions.isResistanceOverLast; + conditions.isSwingHighUnderLast = xcaConditions.isSwingHighUnderLast; + conditions.isSwingLowSameAsVale = xcaConditions.isSwingLowSameAsVale; + conditions.isCloseCrossedOverMah = xcaConditions.isCloseCrossedOverMah; + conditions.isCloseCrossedOverMal = xcaConditions.isCloseCrossedOverMal; + conditions.isCloseCrossedOverMac = xcaConditions.isCloseCrossedOverMac; + conditions.isLastSupportRejected = xcaConditions.isLastSupportRejected; + conditions.isResistanceUnderLast = xcaConditions.isResistanceUnderLast; + conditions.isKISwitchedToBullish = xcaConditions.isKISwitchedToBullish; + conditions.isKISwitchedToBearish = xcaConditions.isKISwitchedToBearish; + conditions.isLastSwingLowBreaked = xcaConditions.isLastSwingLowBreaked; + conditions.isSwingHighSameAsPeak = xcaConditions.isSwingHighSameAsPeak; + conditions.isPeakSwitchedToPivot = xcaConditions.isPeakSwitchedToPivot; + conditions.isValeSwitchedToPivot = xcaConditions.isValeSwitchedToPivot; + conditions.isCloseCrossedUnderMah = xcaConditions.isCloseCrossedUnderMah; + conditions.isCloseCrossedUnderMal = xcaConditions.isCloseCrossedUnderMal; + conditions.isCloseCrossedUnderMac = xcaConditions.isCloseCrossedUnderMac; + conditions.isTKISwitchedToBullish = xcaConditions.isTKISwitchedToBullish; + conditions.isTKISwitchedToBearish = xcaConditions.isTKISwitchedToBearish; + conditions.isLastSwingLowRejected = xcaConditions.isLastSwingLowRejected; + conditions.isSarSwitchedToBullish = xcaConditions.isSarSwitchedToBullish; + conditions.isSarSwitchedToBearish = xcaConditions.isSarSwitchedToBearish; + conditions.isLastSwingHighBreaked = xcaConditions.isLastSwingHighBreaked; + conditions.isResistanceSameAsPeak = xcaConditions.isResistanceSameAsPeak; + conditions.isPeakFinishedFromPivot = xcaConditions.isPeakFinishedFromPivot; + conditions.isValeFinishedFromPivot = xcaConditions.isValeFinishedFromPivot; + conditions.isLastSwingHighRejected = xcaConditions.isLastSwingHighRejected; + conditions.isLastResistanceBreaked = xcaConditions.isLastResistanceBreaked; + conditions.isSupportSameAsSwingLow = xcaConditions.isSupportSameAsSwingLow; + conditions.isKIFinishedFromBullish = xcaConditions.isKIFinishedFromBullish; + conditions.isKIFinishedFromBearish = xcaConditions.isKIFinishedFromBearish; + conditions.isTKIFinishedFromBullish = xcaConditions.isTKIFinishedFromBullish; + conditions.isTKIFinishedFromBearish = xcaConditions.isTKIFinishedFromBearish; + conditions.isSarFinishedFromBullish = xcaConditions.isSarFinishedFromBullish; + conditions.isSarFinishedFromBearish = xcaConditions.isSarFinishedFromBearish; + conditions.isVidyaSwitchedToBullish = xcaConditions.isVidyaSwitchedToBullish; + conditions.isVidyaSwitchedToBearish = xcaConditions.isVidyaSwitchedToBearish; + conditions.isLastResistanceRejected = xcaConditions.isLastResistanceRejected; + conditions.isTrendSwitchedToBullish = xcaConditions.isTrendSwitchedToBullish; + conditions.isTrendSwitchedToBearish = xcaConditions.isTrendSwitchedToBearish; + conditions.isVidyaFinishedFromBullish = xcaConditions.isVidyaFinishedFromBullish; + conditions.isVidyaFinishedFromBearish = xcaConditions.isVidyaFinishedFromBearish; + conditions.isTrendFinishedFromBullish = xcaConditions.isTrendFinishedFromBullish; + conditions.isTrendFinishedFromBearish = xcaConditions.isTrendFinishedFromBearish; + conditions.isResistanceSameAsSwingHigh = xcaConditions.isResistanceSameAsSwingHigh; + + // + // XOSCS ... + + // + // Buffers ... + + // + Copy( + xocsConditions.acBuffer, + conditions.acBuffer // + ); + + // + Copy( + xocsConditions.adBuffer, + conditions.adBuffer // + ); + + // + Copy( + xocsConditions.atrBuffer, + conditions.atrBuffer // + ); + + // + Copy( + xocsConditions.cciBuffer, + conditions.cciBuffer // + ); + + // + Copy( + xocsConditions.rsiBuffer, + conditions.rsiBuffer // + ); + + // + Copy( + xocsConditions.mfiBuffer, + conditions.mfiBuffer // + ); + + // + Copy( + xocsConditions.rviBuffer, + conditions.rviBuffer // + ); + + // + Copy( + xocsConditions.adxBuffer, + conditions.adxBuffer // + ); + + // + Copy( + xocsConditions.adxpBuffer, + conditions.adxpBuffer // + ); + + // + Copy( + xocsConditions.adxnBuffer, + conditions.adxnBuffer // + ); + + // + Copy( + xocsConditions.macdBuffer, + conditions.macdBuffer // + ); + + // + Copy( + xocsConditions.momentumBuffer, + conditions.momentumBuffer // + ); + + // + Copy( + xocsConditions.rviSignalBuffer, + conditions.rviSignalBuffer // + ); + + // + Copy( + xocsConditions.macdSignalBuffer, + conditions.macdSignalBuffer // + ); + + // + Copy( + xocsConditions.stochasticBuffer, + conditions.stochasticBuffer // + ); + + // + Copy( + xocsConditions.stochasticSignalBuffer, + conditions.stochasticSignalBuffer // + ); + + // + // Values ... + + // + conditions.adxThreshold = xocsConditions.adxThreshold; + conditions.cciOBLevel = xocsConditions.cciOBLevel; + conditions.cciOSLevel = xocsConditions.cciOSLevel; + conditions.cciReversalLevel = xocsConditions.cciReversalLevel; + conditions.rsiOBLevel = xocsConditions.rsiOBLevel; + conditions.rsiOSLevel = xocsConditions.rsiOSLevel; + conditions.rsiReversalLevel = xocsConditions.rsiReversalLevel; + conditions.mfiOBLevel = xocsConditions.mfiOBLevel; + conditions.mfiOSLevel = xocsConditions.mfiOSLevel; + conditions.mfiReversalLevel = xocsConditions.mfiReversalLevel; + conditions.rviBullishLevel = xocsConditions.rviBullishLevel; + conditions.rviBearishLevel = xocsConditions.rviBearishLevel; + conditions.macdBullishLevel = xocsConditions.macdBullishLevel; + conditions.macdBearishLevel = xocsConditions.macdBearishLevel; + conditions.momentumBullishLevel = xocsConditions.momentumBullishLevel; + conditions.momentumBearishLevel = xocsConditions.momentumBearishLevel; + conditions.stochasticOBLevel = xocsConditions.stochasticOBLevel; + conditions.stochasticOSLevel = xocsConditions.stochasticOSLevel; + conditions.stochasticReversalLevel = xocsConditions.stochasticReversalLevel; + + // + // Conditions ... + + // + conditions.isCCIOB = xocsConditions.isCCIOB; + conditions.isCCIOS = xocsConditions.isCCIOS; + conditions.isRSIOB = xocsConditions.isRSIOB; + conditions.isRSIOS = xocsConditions.isRSIOS; + conditions.isMFIOB = xocsConditions.isMFIOB; + conditions.isMFIOS = xocsConditions.isMFIOS; + conditions.isACBullish = xocsConditions.isACBullish; + conditions.isACBearish = xocsConditions.isACBearish; + conditions.isACOverMax = xocsConditions.isACOverMax; + conditions.isADOverMax = xocsConditions.isADOverMax; + conditions.isACUnderMin = xocsConditions.isACUnderMin; + conditions.isADUnderMin = xocsConditions.isADUnderMin; + conditions.isADXBullish = xocsConditions.isADXBullish; + conditions.isADXBearish = xocsConditions.isADXBearish; + conditions.isCCIBullish = xocsConditions.isCCIBullish; + conditions.isCCIBearish = xocsConditions.isCCIBearish; + conditions.isRSIBullish = xocsConditions.isRSIBullish; + conditions.isRSIBearish = xocsConditions.isRSIBearish; + conditions.isMFIBullish = xocsConditions.isMFIBullish; + conditions.isMFIBearish = xocsConditions.isMFIBearish; + conditions.isRVIBullish = xocsConditions.isRVIBullish; + conditions.isRVIBearish = xocsConditions.isRVIBearish; + conditions.isATROverLast = xocsConditions.isATROverLast; + conditions.isMACDBullish = xocsConditions.isMACDBullish; + conditions.isMACDBearish = xocsConditions.isMACDBearish; + conditions.isATRUnderLast = xocsConditions.isATRUnderLast; + conditions.isADBiggerLast = xocsConditions.isADBiggerLast; + conditions.isADLesserLast = xocsConditions.isADLesserLast; + conditions.isStochasticOB = xocsConditions.isStochasticOB; + conditions.isStochasticOS = xocsConditions.isStochasticOS; + conditions.isADXBiggerLast = xocsConditions.isADXBiggerLast; + conditions.isADXLesserLast = xocsConditions.isADXLesserLast; + conditions.isRVIOverSignal = xocsConditions.isRVIOverSignal; + conditions.isRVIUnderSignal = xocsConditions.isRVIUnderSignal; + conditions.isMACDOverSignal = xocsConditions.isMACDOverSignal; + conditions.isMACDUnderSignal = xocsConditions.isMACDUnderSignal; + conditions.isMomentumBullish = xocsConditions.isMomentumBullish; + conditions.isMomentumBearish = xocsConditions.isMomentumBearish; + conditions.isADXOverThreshold = xocsConditions.isADXOverThreshold; + conditions.isDXPBiggerThanDXN = xocsConditions.isDXPBiggerThanDXN; + conditions.isDXNBiggerThanDXP = xocsConditions.isDXNBiggerThanDXP; + conditions.isCCICrossedOverOB = xocsConditions.isCCICrossedOverOB; + conditions.isCCICrossedOverOS = xocsConditions.isCCICrossedOverOS; + conditions.isRSICrossedOverOB = xocsConditions.isRSICrossedOverOB; + conditions.isRSICrossedOverOS = xocsConditions.isRSICrossedOverOS; + conditions.isMFICrossedOverOB = xocsConditions.isMFICrossedOverOB; + conditions.isMFICrossedOverOS = xocsConditions.isMFICrossedOverOS; + conditions.isADXUnderThreshold = xocsConditions.isADXUnderThreshold; + conditions.isCCICrossedUnderOB = xocsConditions.isCCICrossedUnderOB; + conditions.isCCICrossedUnderOS = xocsConditions.isCCICrossedUnderOS; + conditions.isRSICrossedUnderOB = xocsConditions.isRSICrossedUnderOB; + conditions.isRSICrossedUnderOS = xocsConditions.isRSICrossedUnderOS; + conditions.isMFICrossedUnderOB = xocsConditions.isMFICrossedUnderOB; + conditions.isMFICrossedUnderOS = xocsConditions.isMFICrossedUnderOS; + conditions.isStochasticBullish = xocsConditions.isStochasticBullish; + conditions.isStochasticBearish = xocsConditions.isStochasticBearish; + conditions.isACSwitchedToBullish = xocsConditions.isACSwitchedToBullish; + conditions.isACSwitchedToBearish = xocsConditions.isACSwitchedToBearish; + conditions.isADXSwitchedToBullish = xocsConditions.isADXSwitchedToBullish; + conditions.isADXSwitchedToBearish = xocsConditions.isADXSwitchedToBearish; + conditions.isCCISwitchedToBullish = xocsConditions.isCCISwitchedToBullish; + conditions.isCCISwitchedToBearish = xocsConditions.isCCISwitchedToBearish; + conditions.isRSISwitchedToBullish = xocsConditions.isRSISwitchedToBullish; + conditions.isRSISwitchedToBearish = xocsConditions.isRSISwitchedToBearish; + conditions.isMFISwitchedToBullish = xocsConditions.isMFISwitchedToBullish; + conditions.isMFISwitchedToBearish = xocsConditions.isMFISwitchedToBearish; + conditions.isRVISwitchedToBullish = xocsConditions.isRVISwitchedToBullish; + conditions.isRVISwitchedToBearish = xocsConditions.isRVISwitchedToBearish; + conditions.isRVICrossedOverSignal = xocsConditions.isRVICrossedOverSignal; + conditions.isStochasticOverSignal = xocsConditions.isStochasticOverSignal; + conditions.isStochasticUnderSignal = xocsConditions.isStochasticUnderSignal; + conditions.isRVICrossedUnderSignal = xocsConditions.isRVICrossedUnderSignal; + conditions.isMACDSwitchedToBullish = xocsConditions.isMACDSwitchedToBullish; + conditions.isMACDSwitchedToBearish = xocsConditions.isMACDSwitchedToBearish; + conditions.isMACDCrossedOverSignal = xocsConditions.isMACDCrossedOverSignal; + conditions.isMACDCrossedUnderSignal = xocsConditions.isMACDCrossedUnderSignal; + conditions.isStochasticCrossedOverOB = xocsConditions.isStochasticCrossedOverOB; + conditions.isStochasticCrossedOverOS = xocsConditions.isStochasticCrossedOverOS; + conditions.isStochasticCrossedUnderOB = xocsConditions.isStochasticCrossedUnderOB; + conditions.isStochasticCrossedUnderOS = xocsConditions.isStochasticCrossedUnderOS; + conditions.isMomentumSwitchedToBullish = xocsConditions.isMomentumSwitchedToBullish; + conditions.isMomentumSwitchedToBearish = xocsConditions.isMomentumSwitchedToBearish; + conditions.isStochasticSwitchedToBullish = xocsConditions.isStochasticSwitchedToBullish; + conditions.isStochasticSwitchedToBearish = xocsConditions.isStochasticSwitchedToBearish; + conditions.isStochasticCrossedOverSignal = xocsConditions.isStochasticCrossedOverSignal; + conditions.isStochasticCrossedUnderSignal = xocsConditions.isStochasticCrossedUnderSignal; + + // + int bodiesCount = barAnalyser.GetPriceRange( + conditions.bodies, + zBar, + true, // Force Body ... + true, // Force Price Diff ... + loopback // + ); + int rangesCount = barAnalyser.GetPriceRange( + conditions.ranges, + zBar, + true, // Force Body ... + true, // Force Price Diff ... + loopback // + ); + + // + int velocitiesCount = + barAnalyser + .GetPriceVelocity( + conditions.velocities, + zBar, + X_PRICE_CLOSE, + loopback // + ); + + // + double bullishVolume = 0.0; + double bearishVolume = 0.0; + barAnalyser + .CalculateRangeVolume( + zBar, + bullishVolume, + bearishVolume, + loopback // + ); + conditions.scoreBullish = bullishVolume; + conditions.scoreBearish = bearishVolume; + + // + double bullishScore = 0.0; + double bearishScore = 0.0; + conditions.GenerateScore( + bullishScore, + bearishScore // + ); + conditions.volumeBullish = bullishScore; + conditions.volumeBearish = bearishScore; + + // + double priceChangeRate = + barAnalyser + .GetPriceChangeRate( + zBar, + X_PRICE_CLOSE, + loopback // + ); + conditions.priceChangeRate = priceChangeRate; + + // + // Cleanup Resource ... + + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + fromBar.Clean(); + + // + xcaConditions.Clean(); + xocsConditions.Clean(); + x3maConditions.Clean(); + + // + Free(); + + // + return result; + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + + // + string mSymbol; // Trading Symbol + ENUM_TIMEFRAMES mPeriod; // Trading Period + + // + // Inputs ... + XCAEAInputs mInputs; + + // + // Handlers ... + int acHandler; + int adHandler; + int adxHandler; + int atrHandler; + int cciHandler; + int rsiHandler; + int mfiHandler; + int rviHandler; + int macdHandler; + int momentumHandler; + int stochasticHandler; +}; + +// \ No newline at end of file diff --git a/BKPS/14040218 XCAEA/XCAEA/Libraries/xcaea.signaller.lib.mq5 b/BKPS/14040218 XCAEA/XCAEA/Libraries/xcaea.signaller.lib.mq5 new file mode 100644 index 0000000..a398c87 --- /dev/null +++ b/BKPS/14040218 XCAEA/XCAEA/Libraries/xcaea.signaller.lib.mq5 @@ -0,0 +1,2495 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XCAEASignaller Lib +// Description: Library for XCAEA 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 Library for XCAEA Signaller" +#property strict + +// +// Imports ... +#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/xcaea.x-poi.detector.class.mq5" +#include "../Classes/xcaea.x-poi.drawer.class.mq5" +#include "../Helpers/xcaea.helper.mq5" + +// +// Enumeration ... + +// +// Guard Actions ... +enum ENUM_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_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 ... + +// +// Conditions Struct ... +struct XCAEAStrategyConditions +{ + // + // Props ... + + // + string symbol; + ENUM_TIMEFRAMES period; + + // + // Setup Props ... + + // + double sl; + double tp; + double pivot; + double point; + double entry; + double reward; + string provider; + double targets[]; + + // + datetime time; + datetime setupTime; + datetime triggerTime; + + // + double partialCloseOnTPLevel; + double partialCloseMultiplier; + + // + ENUM_X_DIRECTION dir; + XBoxZone decisionZone; + ENUM_X_POSITION_TYPES type; + XCAEAConditions conditions; + + // + // Constructor ... + XCAEAStrategyConditions() + { + 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; + + // + partialCloseOnTPLevel = 0; + partialCloseMultiplier = 0; + + // + Clean(targets); + + // + conditions.Clean(); + decisionZone.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; + } + + // +}; + +// +// Model a Guard Action ... +struct XCAEAGuard +{ + // + // Props ... + ENUM_GUARD_ACTIONS action; + datetime time; + + // + string symbol; + string provider; + + // + // Specified Position ... + ulong ticket; + + // + // Partial Close ... + double volumeMultiplier; + + // + // SL Trial ... + double sl; + + // + // TP Trial ... + double tp; + + // + // Constructor ... + XCAEAGuard() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + time = NULL; + action = X_GUARD_ACTION_NONE; + + // + symbol = NULL; + provider = NULL; + + // + ticket = 0; + + // + volumeMultiplier = 0; + + // + sl = 0; + tp = 0; + + // + ZeroMemory(this); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsValid(time) && + IsValid(symbol) && + IsValid(provider) && + action != X_GUARD_ACTION_NONE + // + ; + if (!result) + { + return result; + } + + // + // Validate Model Based On Specified Guard Actions ... + + // + return result; + } +}; + +/** + * Add Guard to Collection ... + * + * @param guard: XCAEAGuard instance ... + * @param guards: XCAEAGuard instance Collection ... + * + * @return ( int ) + */ +int AddGuard( + XCAEAGuard &guard, + XCAEAGuard &guards[] // +) +{ + // + int result = 0; + + // + if (!guard.IsValid()) + { + return result; + } + + // + AddRef( + guard, + guards // + ); + + // + result = ArraySize(guards); + + // + return result; +} + +// +// Detect Decision Zone ... +bool DetectDecisionZone( + XCXCAEAHelper *helper, + XCXCAEAPOIDrawer *drawer, + XBoxZone &box, + ENUM_X_DIRECTION &dir, + XCAEAConditions &conditions, + int barIndex = 0, + int loopback = 10 // +) +{ + // + bool result = false; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + box.Clean(); + conditions.Clean(); + dir = X_DIRECTION_NONE; + barIndex = NormalizeInt(barIndex, 0); + loopback = NormalizeInt(loopback, 5); + + // + // Retrieve Some Requirements ... + string symbol = helper.GetSymbol(); + ENUM_TIMEFRAMES period = helper.GetPeriod(); + double points = GetPoints(symbol); + + // + // Retrieve Conditions for Processing ... + result = helper.GetConditions( + conditions, + barIndex, + loopback // + ); + if (!result) + { + // + box.Clean(); + conditions.Clean(); + + // + return result; + } + + // + // Define IDXses ... + int zIDX = barIndex; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + int p3IDX = p2IDX + 1; + int p4IDX = p3IDX + 1; + + // + XOHCL zBar; + XOHCL cBar; + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + XOHCL p4Bar; + result = zBar.Init( + symbol, + period, + zIDX // + ); + result = + result && + zBar.GetPreviousBar(cBar); + result = + result && + cBar.GetPreviousBar(pBar); + result = + result && + pBar.GetPreviousBar(p2Bar); + result = + result && + p2Bar.GetPreviousBar(p3Bar); + result = + result && + p3Bar.GetPreviousBar(p4Bar); + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + box.Clean(); + conditions.Clean(); + + // + return result; + } + + // + // Bars Conditions ... + + // + // Score ... + + // + double bullishScore = 0; + double bearishScore = 0; + conditions.GenerateScore( + bullishScore, + bearishScore // + ); + + // + bool isScoreBullish = + bullishScore > bearishScore; + + // + bool isScoreBearish = + bearishScore > bullishScore; + + // + bool isScoreNeutural = MathAbs(bullishScore - bearishScore) == 0; + + // + // Calculating Range Volumes ... + + // + double bullishVolume = 0; + double bearishVolume = 0; + helper.barAnalyser.CalculateRangeVolume( + cBar, + bullishVolume, + bearishVolume, + loopback // + ); + + // + bool isVolumeNeutural = MathAbs(bullishVolume - bearishVolume) == 0; + + // + // Checking OB ... + XBoxZone ob; + bool isOB = helper + .barAnalyser + .IsOrderBlock( + cBar, + ob, + false, // Force FVG Bar Type + true // Force Two Bar Start ... + ); + bool isBullishOB = + isOB && + ob.IsBullish(); + bool isBearishOB = + isOB && + ob.IsBearish(); + + // + // Reading Values ... + + // + // 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]; + + // + // PEAK ... + 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 p4Peak = conditions.peakBuffer[p4IDX]; + + // + // VALE ... + 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]; + double p4Vale = conditions.valeBuffer[p4IDX]; + + // + // SWING Low ... + double zSWL = conditions.swingLowBuffer[zIDX]; + double cSWL = conditions.swingLowBuffer[cIDX]; + double pSWL = conditions.swingLowBuffer[pIDX]; + double p2SWL = conditions.swingLowBuffer[p2IDX]; + double p3SWL = conditions.swingLowBuffer[p3IDX]; + + // + // SWING High ... + double zSWH = conditions.swingHighBuffer[zIDX]; + double cSWH = conditions.swingHighBuffer[cIDX]; + double pSWH = conditions.swingHighBuffer[pIDX]; + double p2SWH = conditions.swingHighBuffer[p2IDX]; + double p3SWH = conditions.swingHighBuffer[p3IDX]; + + // + // SUPPORT ... + double zSupport = conditions.supportBuffer[zIDX]; + double cSupport = conditions.supportBuffer[cIDX]; + double pSupport = conditions.supportBuffer[pIDX]; + double p2Support = conditions.supportBuffer[p2IDX]; + double p3Support = conditions.supportBuffer[p3IDX]; + + // + // RESISTANCE ... + double zResistance = conditions.resistanceBuffer[zIDX]; + double cResistance = conditions.resistanceBuffer[cIDX]; + double pResistance = conditions.resistanceBuffer[pIDX]; + double p2Resistance = conditions.resistanceBuffer[p2IDX]; + double p3Resistance = conditions.resistanceBuffer[p3IDX]; + + // + // MAH ... + double zMAH = conditions.mahBuffer[zIDX]; + double cMAH = conditions.mahBuffer[cIDX]; + double pMAH = conditions.mahBuffer[pIDX]; + double p2MAH = conditions.mahBuffer[p2IDX]; + double p3MAH = conditions.mahBuffer[p3IDX]; + + // + // MAL ... + double zMAL = conditions.malBuffer[zIDX]; + double cMAL = conditions.malBuffer[cIDX]; + double pMAL = conditions.malBuffer[pIDX]; + double p2MAL = conditions.malBuffer[p2IDX]; + double p3MAL = conditions.malBuffer[p3IDX]; + + // + // MAC ... + double zMAC = conditions.macBuffer[zIDX]; + double cMAC = conditions.macBuffer[cIDX]; + double pMAC = conditions.macBuffer[pIDX]; + double p2MAC = conditions.macBuffer[p2IDX]; + double p3MAC = conditions.macBuffer[p3IDX]; + + // + // FIBO Level 1 ... + double zFib1 = conditions.fiboLevel1Buffer[zIDX]; + double cFib1 = conditions.fiboLevel1Buffer[cIDX]; + double pFib1 = conditions.fiboLevel1Buffer[pIDX]; + double p2Fib1 = conditions.fiboLevel1Buffer[p2IDX]; + double p3Fib1 = conditions.fiboLevel1Buffer[p3IDX]; + + // + // FIBO Level 2 ... + double zFib2 = conditions.fiboLevel2Buffer[zIDX]; + double cFib2 = conditions.fiboLevel2Buffer[cIDX]; + double pFib2 = conditions.fiboLevel2Buffer[pIDX]; + double p2Fib2 = conditions.fiboLevel2Buffer[p2IDX]; + double p3Fib2 = conditions.fiboLevel2Buffer[p3IDX]; + + // + // FIBO Level 3 ... + double zFib3 = conditions.fiboLevel3Buffer[zIDX]; + double cFib3 = conditions.fiboLevel3Buffer[cIDX]; + double pFib3 = conditions.fiboLevel3Buffer[pIDX]; + double p2Fib3 = conditions.fiboLevel3Buffer[p2IDX]; + double p3Fib3 = conditions.fiboLevel3Buffer[p3IDX]; + + // + // FIBO Level 4 ... + double zFib4 = conditions.fiboLevel4Buffer[zIDX]; + double cFib4 = conditions.fiboLevel4Buffer[cIDX]; + double pFib4 = conditions.fiboLevel4Buffer[pIDX]; + double p2Fib4 = conditions.fiboLevel4Buffer[p2IDX]; + double p3Fib4 = conditions.fiboLevel4Buffer[p3IDX]; + + // + // FIBO Level 5 ... + double zFib5 = conditions.fiboLevel5Buffer[zIDX]; + double cFib5 = conditions.fiboLevel5Buffer[cIDX]; + double pFib5 = conditions.fiboLevel5Buffer[pIDX]; + double p2Fib5 = conditions.fiboLevel5Buffer[p2IDX]; + double p3Fib5 = conditions.fiboLevel5Buffer[p3IDX]; + + // + // FAST ... + double zFast = conditions.fastBuffer[zIDX]; + double cFast = conditions.fastBuffer[cIDX]; + double pFast = conditions.fastBuffer[pIDX]; + double p2Fast = conditions.fastBuffer[p2IDX]; + double p3Fast = conditions.fastBuffer[p3IDX]; + + // + // FAST State ... + double zFastState = conditions.fastStateBuffer[zIDX]; + double cFastState = conditions.fastStateBuffer[cIDX]; + double pFastState = conditions.fastStateBuffer[pIDX]; + double p2FastState = conditions.fastStateBuffer[p2IDX]; + double p3FastState = conditions.fastStateBuffer[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]; + + // + // Create Custom Conditions ... + + // + // Bar and Fibo Conditions ... + + // + // Bearish ... + + // + // Strong Reversal ... + bool isZBarOnFiboStrongBearish = zBar.low > zFib5; + bool isCBarOnFiboStrongBearish = cBar.low > cFib5; + bool isPBarOnFiboStrongBearish = pBar.low > pFib5; + bool isP2BarOnFiboStrongBearish = p2Bar.low > p2Fib5; + bool isP3BarOnFiboStrongBearish = p3Bar.low > p3Fib5; + + // + // Golden Zone Reversal ... + bool isZBarOnFiboGoldenBearish = zBar.low > zFib3 && + zBar.high < zFib4; + bool isCBarOnFiboGoldenBearish = cBar.low > cFib3 && + cBar.high < cFib4; + bool isPBarOnFiboGoldenBearish = pBar.low > pFib3 && + pBar.high < pFib4; + bool isP2BarOnFiboGoldenBearish = p2Bar.low > p2Fib3 && + p2Bar.high < p2Fib4; + bool isP3BarOnFiboGoldenBearish = p3Bar.low > p3Fib3 && + p3Bar.high < p3Fib4; + + // + // Bullish ... + + // + // Strong Reversal ... + bool isZBarOnFiboStrongBullish = zBar.high < zFib1; + bool isCBarOnFiboStrongBullish = cBar.high < cFib1; + bool isPBarOnFiboStrongBullish = pBar.high < pFib1; + bool isP2BarOnFiboStrongBullish = p2Bar.high < p2Fib1; + bool isP3BarOnFiboStrongBullish = p3Bar.high < p3Fib1; + + // + // Golden Zone Reversal ... + bool isZBarOnFiboGoldenBullish = zBar.low > zFib2 && + zBar.high < zFib3; + bool isCBarOnFiboGoldenBullish = cBar.low > cFib2 && + cBar.high < cFib3; + bool isPBarOnFiboGoldenBullish = pBar.low > pFib2 && + pBar.high < pFib3; + bool isP2BarOnFiboGoldenBullish = p2Bar.low > p2Fib2 && + p2Bar.high < p2Fib3; + bool isP3BarOnFiboGoldenBullish = p3Bar.low > p3Fib2 && + p3Bar.high < p3Fib3; + + // + // Score and Volume Conditions ... + + // + bool isScoreVolumeNeutural = isScoreNeutural || + isVolumeNeutural; + + // + bool isScoreVolumeNeuturalInFiboStrongBullish = + isScoreNeutural && + isCBarOnFiboStrongBullish; + + // + bool isScoreVolumeNeuturalInFiboGoldenBullish = + isScoreNeutural && + isCBarOnFiboGoldenBullish; + + // + bool isScoreVolumeNeuturalInFiboStrongBearish = + isScoreNeutural && + isCBarOnFiboStrongBearish; + + // + bool isScoreVolumeNeuturalInFiboGoldenBearish = + isScoreNeutural && + isCBarOnFiboGoldenBearish; + + // + bool isScoreVolumeNeuturalBullishPowered = + isScoreVolumeNeuturalInFiboStrongBullish || + isScoreVolumeNeuturalInFiboGoldenBullish; + + // + bool isScoreVolumeNeuturalBearishPowered = + isScoreVolumeNeuturalInFiboStrongBearish || + isScoreVolumeNeuturalInFiboGoldenBearish; + + // + // PEAK and VALES ... + + // + // PEAK Pivot ... + bool isZIsPeakPivot = + zPeak == cPeak && + zPeak == zSWH && + zPeak == zResistance && + isZBarOnFiboStrongBearish; + bool isCIsPeakPivot = + cPeak == pPeak && + cPeak == cSWH && + cPeak == cResistance && + isCBarOnFiboStrongBearish; + bool isPIsPeakPivot = + pPeak == p2Peak && + pPeak == pSWH && + pPeak == pResistance && + isPBarOnFiboStrongBearish; + bool isP2IsPeakPivot = + p2Peak == p3Peak && + p2Peak == p2SWH && + p2Peak == p2Resistance && + isP2BarOnFiboStrongBearish; + bool isP3IsPeakPivot = + p3Peak == p4Peak && + p3Peak == p3SWH && + p3Peak == p3Resistance && + isP3BarOnFiboStrongBearish; + + // + // VALE Pivot ... + bool isZIsValePivot = + zVale == cVale && + zVale == zSWL && + zVale == zSupport && + isZBarOnFiboStrongBullish; + bool isCIsValePivot = + cVale == pVale && + cVale == cSWL && + cVale == cSupport && + isCBarOnFiboStrongBullish; + bool isPIsValePivot = + pVale == p2Vale && + pVale == pSWL && + pVale == pSupport && + isPBarOnFiboStrongBullish; + bool isP2IsValePivot = + p2Vale == p3Vale && + p2Vale == p2SWL && + p2Vale == p2Support && + isP2BarOnFiboStrongBullish; + bool isP3IsValePivot = + p3Vale == p4Vale && + p3Vale == p3SWL && + p3Vale == p3Support && + isP3BarOnFiboStrongBullish; + + // + // FIBO Section Change Detection ... + bool isFiboSectionChanged = + // + (cFib1 != pFib1 && + cFib2 != pFib2 && + cFib3 != pFib3 && + cFib4 != pFib4 && + cFib5 != pFib5) + // + && + // + (conditions.isPeakUnderLast || + conditions.isValeOverLast || + conditions.isSwingLowOverLast || + conditions.isSwingHighUnderLast) + // + ; + + // + // SAR Change ... + + // + bool isSarSwitchedInFiboStrongBullish = + isCBarOnFiboStrongBullish && + conditions.isSarSwitchedToBullish; + + // + bool isSarSwitchedInFiboGoldenBullish = + isCBarOnFiboGoldenBullish && + conditions.isSarSwitchedToBullish; + + // + bool isSarSwitchedInFiboStrongBearish = + isCBarOnFiboStrongBearish && + conditions.isSarSwitchedToBearish; + + // + bool isSarSwitchedInFiboGoldenBearish = + isCBarOnFiboGoldenBearish && + conditions.isSarSwitchedToBearish; + + // + bool isSarSwitchedToBullish = + cFastState > 0 && + isSarSwitchedInFiboStrongBullish; + + // + bool isSarSwitchedToBearish = + cFastState < 0 && + isSarSwitchedInFiboStrongBearish; + + // + // RSI Conditions ... + + // + bool isRSICrossedOverOS = + p3RSI < conditions.rsiOSLevel && + cRSI > conditions.rsiOSLevel; + + // + bool isRSICrossedUnderOB = + p3RSI > conditions.rsiOBLevel && + cRSI < conditions.rsiOBLevel; + + // + // Testing Conditions ... + + // + // Detect Fibo Section Changed ... + if (isFiboSectionChanged) + { + // Print("Fibo Section Changed ..."); + } + + // + // PVPivot Conditions ... + if (isCIsPeakPivot || + isCIsValePivot) + { + // // + // ENUM_X_DIRECTION iPVPivotDir = + // isCIsValePivot + // ? X_DIRECTION_BULLISH + // : X_DIRECTION_BEARISH; + + // // + // int timeOffset = (int)cBar.time; + // string iName = ToString(iPVPivotDir) + "_PVPVT_" + ToString(timeOffset); + // color iColor = isCIsValePivot + // ? clrAqua + // : clrMagenta; + // ENUM_LINE_STYLE iStyle = STYLE_DOT; + + // // + // CChartObjectVLine *iObj; + // iObj = new CChartObjectVLine(); + // has = iObj.Create( + // 0, + // iName, + // 0, + // cBar.time // + // ); + // if (has) + // { + // // + // iObj.Color(iColor); + // iObj.Style(iStyle); + // } + + // // + // Print("Conditions Finder ..."); + } + + // + // Testing Sar Changes ... + if (isSarSwitchedToBullish || + isSarSwitchedToBearish) + { + // + // ENUM_X_DIRECTION iSarChangeDir = + // isSarSwitchedToBullish + // ? X_DIRECTION_BULLISH + // : X_DIRECTION_BEARISH; + + // // + // int timeOffset = (int)cBar.time; + // string iName = ToString(iSarChangeDir) + "_SAR_" + ToString(timeOffset); + // color iColor = isSarSwitchedToBullish + // ? clrAqua + // : clrMagenta; + // ENUM_LINE_STYLE iStyle = STYLE_DOT; + + // // + // CChartObjectVLine *iObj; + // iObj = new CChartObjectVLine(); + // has = iObj.Create( + // 0, + // iName, + // 0, + // cBar.time // + // ); + // if (has) + // { + // // + // iObj.Color(iColor); + // iObj.Style(iStyle); + // } + + // + // Print("Conditions Finder ..."); + } + + // + // Score and Volume Conditions ... + if (isScoreVolumeNeuturalBullishPowered || + isScoreVolumeNeuturalBearishPowered) + { + // + // ENUM_X_DIRECTION iScoreVolumeDir = + // isScoreVolumeNeuturalBullishPowered + // ? X_DIRECTION_BULLISH + // : X_DIRECTION_BEARISH; + + // // + // int timeOffset = (int)cBar.time; + // string iName = ToString(iScoreVolumeDir) + "_SCVM_" + ToString(timeOffset); + // color iColor = isScoreVolumeNeuturalBullishPowered + // ? clrAqua + // : clrMagenta; + // ENUM_LINE_STYLE iStyle = STYLE_DOT; + + // + // CChartObjectVLine *iObj; + // iObj = new CChartObjectVLine(); + // has = iObj.Create( + // 0, + // iName, + // 0, + // cBar.time // + // ); + // if (has) + // { + // // + // iObj.Color(iColor); + // iObj.Style(iStyle); + // } + + // // + // Print("Conditions Finder ..."); + } + + // + // Custom Senarios ... + + // + bool isCond1Bullish = + isBullishOB && + isCIsValePivot && + isRSICrossedOverOS && + !isFiboSectionChanged && + isSarSwitchedToBullish; + + // + bool isCond1Bearish = + isBearishOB && + isCIsPeakPivot && + isRSICrossedUnderOB && + !isFiboSectionChanged && + isSarSwitchedToBearish; + + // + bool isCond1 = + isCond1Bullish || + isCond1Bearish; + if (isCond1) + { + // + ENUM_X_DIRECTION iCond1Dir = + isCond1Bullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + int timeOffset = (int)cBar.time; + string iName = ToString(iCond1Dir) + "_COND1_" + ToString(timeOffset); + color iColor = isCond1Bullish + ? clrAqua + : clrMagenta; + ENUM_LINE_STYLE iStyle = STYLE_DOT; + + // + CChartObjectVLine *iObj; + iObj = new CChartObjectVLine(); + has = iObj.Create( + 0, + iName, + 0, + cBar.time // + ); + if (has) + { + // + iObj.Color(iColor); + iObj.Style(iStyle); + } + + // + // Create Signal Box Based on Cond1 ... + + // + double upper = + isCond1Bullish + ? cBar.FindHighest(5, MODE_HIGH) + : MathMax(cPeak, cSWH); + + // + double lower = + isCond1Bullish + ? MathMin(cVale, cSWL) + : cBar.FindLowest(5, MODE_LOW); + + // + int toIDX = cBar.Index(); + int fromIDX = cBar.Index() + 5; + + // + datetime toTime = GetBarTime( + symbol, + period, + toIDX // + ); + datetime fromTime = GetBarTime( + symbol, + period, + fromIDX // + ); + + // + XBoxZone iBox; + + // + iBox.to = toTime; + iBox.upper = upper; + iBox.lower = lower; + iBox.type = "COND1"; + iBox.symbol = symbol; + iBox.period = period; + iBox.dir = iCond1Dir; + iBox.from = fromTime; + + // + has = iBox.IsValid(); + if (has) + { + // + XCBoxObject *iObj; + has = helper + .poiDrawer + .DrawBox( + iBox, + iObj // + ); + if (has) + { + // + // Style Object ... + } + } + + // + box = iBox; + dir = iBox.dir; + + // + iBox.Clean(); + + // + // Print("Conditions Finder ..."); + } + + // + // bool isCond2 = isFiboSectionChanged; + // if (isCond2) + // { + // // + // Print("Decision Zone Full Cond1"); + // } + + // + // Summarise Result ... + + // + bool isBullish = + false || + isCond1Bullish; + + // + bool isBearish = + false || + isCond1Bearish; + + // + result = isBullish || + isBearish; + if (result) + { + // + // Do Signal Preparing ... + + // + // Check Box is Prepared or Not ... + result = box.IsValid(); + } + + // + // Cleaning Up ... + + // + ob.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + if (!result) + { + // + box.Clean(); + conditions.Clean(); + } + + // + return result; +} + +// +// Trigger Conditions ... + +// +// Detect Trigger Based On Decision Zone's +// Volume and Score ... +bool CanTriggerCond0( + XCXCAEAHelper *helper, + XBoxZone &box, + ENUM_X_DIRECTION &dir, + double &sl, + double &tp, + int barIndex = 0, + int loopback = 5, + double scorePassMultiplier = 1 // +) +{ + // + bool result = false; + + // + // Normalize Args ... + sl = 0; + tp = 0; + dir = X_DIRECTION_NONE; + loopback = NormalizeInt(loopback, 5); + barIndex = NormalizeInt(barIndex, 0); + + // + // Validate Decision Box ... + result = box.IsValid() && + helper != NULL; + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + bool isBullish = box.IsBullish(); + bool isBearish = box.IsBearish(); + + // + // Scores ... + double bullScores[]; + double bearScores[]; + + // + // Volumes ... + double bullVolumes[]; + double bearVolumes[]; + + // + // Create a Loop through Loopack ... + XOHCL iBar; + bool has = false; + int start = barIndex; + XCAEAConditions iConditions; + int end = barIndex + loopback; + for (int i = end; i >= start; i--) + { + // + // Retrieve Bar ... + has = iBar.Init( + box.symbol, + box.period, + i // + ); + if (!has) + { + // + iBar.Clean(); + iConditions.Clean(); + + // + continue; + } + + // + // Retrieve Conditions ... + has = helper.GetConditions( + iConditions, + i // + ); + if (!has) + { + // + iBar.Clean(); + iConditions.Clean(); + + // + continue; + } + + // + // Retrieve Scores ... + double iBullScore = 0; + double iBearScore = 0; + iConditions + .GenerateScore( + iBullScore, + iBearScore // + ); + Add( + iBullScore, + bullScores // + ); + Add( + iBearScore, + bearScores // + ); + + // + // Retrieve Volumes ... + double iBullVolume = 0; + double iBearVolume = 0; + helper + .barAnalyser + .CalculateRangeVolume( + iBar, + iBullVolume, + iBearVolume, + 2 // Loopback ... + ); + Add( + iBullVolume, + bullVolumes // + ); + Add( + iBearVolume, + bearVolumes // + ); + + // + iBar.Clean(); + iConditions.Clean(); + } + + // + // Calculating Requirements ... + + // + // Scores ... + + // + // Bullish ... + double bullScore = GetSum(bullScores); + double bullScoreMax = GetMax(bullScores); + double bullScoreMin = GetMin(bullScores); + + // + // Bearish ... + double bearScore = GetSum(bearScores); + double bearScoreMax = GetMax(bearScores); + double bearScoreMin = GetMin(bearScores); + + // + // Volumes ... + + // + // Bullish ... + double bullVolume = GetSum(bullVolumes); + double bullVolumeMax = GetMax(bullVolumes); + double bullVolumeMin = GetMin(bullVolumes); + + // + // Bearish ... + double bearVolume = GetSum(bearVolumes); + double bearVolumeMax = GetMax(bearVolumes); + double bearVolumeMin = GetMin(bearVolumes); + + // + // Creating Result Conditions ... + + // + bool isBullishPassed = + isBullish && + bullScore >= (scorePassMultiplier * bearScore) && + bullVolume >= (scorePassMultiplier * bearVolume); + + // + bool isBearishPassed = + isBearish && + bearScore >= (scorePassMultiplier * bullScore) && + bearVolume >= (scorePassMultiplier * bullVolume); + + // + result = isBullishPassed || + isBearishPassed; + if (!result) + { + // + iBar.Clean(); + Clean(bullScores); + Clean(bearScores); + Clean(bullVolumes); + Clean(bearVolumes); + iConditions.Clean(); + + // + return result; + } + + // + // Validating Box to Find a Rejection ... + + // + // Validating Box to Has a Gap ... + + // + // Validating Box to Has a Block ... + + // + bool isPassed = + isBullishPassed || + isBearishPassed; + if (isPassed) + { + // + // Preparing TP and SL ... + + // + sl = isBullishPassed + ? box.lower + : box.upper; + + // + tp = 0; + } + + // + // Summarizing ... + + // + bool canTriggerLong = + isBullishPassed; + + // + bool canTriggerShort = + isBearishPassed; + + // + result = canTriggerLong || + canTriggerShort; + if (result) + { + // + dir = canTriggerLong + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + // Cleanup Resources ... + + // + iBar.Clean(); + Clean(bullScores); + Clean(bearScores); + Clean(bullVolumes); + Clean(bearVolumes); + iConditions.Clean(); + + // + return result; +} + +// +// Detect Trigger Based On Decision Zone's +// Fake Breaked out ... +bool CanTriggerCond1( + XCXCAEAHelper *helper, + XBoxZone &box, + ENUM_X_DIRECTION &dir, + double &sl, + double &tp, + int barIndex = 0, + int loopback = 10 // +) +{ + // + bool result = false; + + // + // Normalize Args ... + sl = 0; + tp = 0; + dir = X_DIRECTION_NONE; + loopback = NormalizeInt(loopback, 5); + barIndex = NormalizeInt(barIndex, 0); + + // + // Validate Decision Box ... + result = box.IsValid() && + helper != NULL; + if (!result) + { + return result; + } + + // + // Check Box is Faked Breaked Out ... + + // + XBoxZone validatorFVG; + + // + bool isBullishFakedBreakedOut = IsBoxFakedBreakout( + helper, + box, + validatorFVG, + X_DIRECTION_BULLISH, + barIndex, + 100, // Loopback For FVG ... + true, // Force FVg Validation ... + true // Force FVG Bar Type ... + ); + + // + bool isBearishFakedBreakedOut = IsBoxFakedBreakout( + helper, + box, + validatorFVG, + X_DIRECTION_BEARISH, + barIndex, + 100, // Loopback For FVG ... + true, // Force FVg Validation ... + true // Force FVG Bar Type ... + ); + + // + bool isFakeBreaked = + isBullishFakedBreakedOut || + isBearishFakedBreakedOut; + if (isFakeBreaked) + { + // + // Preparing TP and SL ... + + // + sl = isBullishFakedBreakedOut + ? validatorFVG.lower + : validatorFVG.upper; + + // + tp = isBullishFakedBreakedOut + ? box.upper + : box.lower; + } + + // + // Summarizing ... + + // + bool canTriggerLong = + isBullishFakedBreakedOut; + + // + bool canTriggerShort = + isBearishFakedBreakedOut; + + // + result = canTriggerLong || + canTriggerShort; + if (result) + { + // + dir = canTriggerLong + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + // Cleanup Resources ... + validatorFVG.Clean(); + + // + return result; +} + +// +// Detect Trigger Based On Decision Zone's +// Box Starts With FVG ... +bool CanTriggerCond2( + XCXCAEAHelper *helper, + XBoxZone &box, + ENUM_X_DIRECTION &dir, + double &sl, + double &tp, + int barIndex = 0, + int loopback = 10 // +) +{ + // + bool result = false; + + // + // Normalize Args ... + sl = 0; + tp = 0; + dir = X_DIRECTION_NONE; + loopback = NormalizeInt(loopback, 5); + barIndex = NormalizeInt(barIndex, 0); + + // + // Validate Decision Box ... + result = box.IsValid() && + helper != NULL; + if (!result) + { + return result; + } + + // + XBoxZone activatedFVG; + bool hasActivatedFVG = IsBoxHasActivatedFVG( + helper, + box, + activatedFVG, + barIndex, + loopback // + ); + + // + bool hasBullishActivatedFVG = + hasActivatedFVG && + activatedFVG.IsBullish(); + + // + bool hasBearishActivatedFVG = + hasActivatedFVG && + activatedFVG.IsBearish(); + + // + if (hasActivatedFVG) + { + // + // Preparing TP and SL ... + + // + sl = hasBullishActivatedFVG + ? box.lower // activatedFVG.lower + : box.upper; // activatedFVG.upper; + + // + // Since Here TP Must Calculated + // Using R2R we Ignore Target ... + tp = 0; + } + + // + // Summarizing ... + + // + bool canTriggerLong = + hasBullishActivatedFVG; + + // + bool canTriggerShort = + hasBearishActivatedFVG; + + // + result = canTriggerLong || + canTriggerShort; + if (result) + { + // + dir = canTriggerLong + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + // Cleanup Resources ... + + // + return result; +} + +// +// Helper Functions ... + +// +// Check a Box is Breaked or Not ... +bool IsBoxBreaked( + XCXCAEAHelper *helper, + XBoxZone &box, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + // Normalize Args ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Validate Args ... + result = + box.IsValid() && + helper != NULL; + if (!result) + { + // + // Assume Box Invalid and Breaked + // When Args not Valid ... + result = true; + return result; + } + + // + bool isBullish = box.IsBullish(); + bool isBearish = box.IsBearish(); + + // + // Extract Bars ... + + // + XOHCL cBar; + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + + // + result = cBar.Init( + box.symbol, + box.period, + barIndex + 1 // + ); + result = result && + cBar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + result = result && + p2Bar.GetPreviousBar(p3Bar); + if (!result) + { + // + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + + // + // Assume Box Invalid and Breaked + // When Args not Valid ... + result = true; + + // + return result; + } + + // + // Check Box is Breaked or not ... + // a Box Assume Breakes when at least 3 Bars Close over / under applied Price ... + + // + double appliedPrice = + isBullish + ? box.lower + : box.upper; + + // + bool isBullishBreaked = + isBullish && + cBar.close < appliedPrice && + pBar.close < appliedPrice && + p2Bar.close < appliedPrice; + + // + bool isBearishBreaked = + isBearish && + cBar.close > appliedPrice && + pBar.close > appliedPrice && + p2Bar.close > appliedPrice; + + // + result = isBullishBreaked || + isBearishBreaked; + + // + // Cleanup Resources ... + + // + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + + // + return result; +} + +// +// Detect Fake Breakout ... +bool IsBoxFakedBreakout( + XCXCAEAHelper *helper, + XBoxZone &box, + XBoxZone &validatorFVG, + ENUM_X_DIRECTION forDir, + int barIndex = 0, + int loopback = 100, + bool forceFVGValidating = false, + bool forceFVGBarType = false // +) +{ + // + bool result = false; + + // + validatorFVG.Clean(); + + // + // Normalizing Args ... + barIndex = NormalizeInt(barIndex, 0); + loopback = NormalizeInt(loopback, 10); + + // + // Validate Decision Box ... + result = box.IsValid() && + helper != NULL && + (HasDirection(forDir)); + if (!result) + { + return result; + } + + // + double points = GetPoints(box.symbol); + + // + // Extract Bars ... + + // + XOHCL cBar; + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + + // + result = cBar.Init( + box.symbol, + box.period, + barIndex + 1 // + ); + result = result && + cBar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + result = result && + p2Bar.GetPreviousBar(p3Bar); + if (!result) + { + // + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + + // + return result; + } + + // + // Bar Conditions ... + + // + ENUM_X_DIRECTION barDir; + + // + // Engulfed ... + bool isCBarEngulfed = helper + .barAnalyser + .IsEngulfed( + cBar, + barDir // + ); + bool isCBarBullishEngulfed = + isCBarEngulfed && + IsBullish(barDir); + bool isCBarBearishEngulfed = + isCBarEngulfed && + IsBearish(barDir); + + // + // Rejected ... + bool isCBarRejected = helper + .barAnalyser + .IsRejected( + cBar, + barDir, + false, // Force Type ... + true // Force Fibo Pressure ... + ); + bool isCBarBullishRejected = + isCBarRejected && + IsBullish(barDir); + bool isCBarBearishRejected = + isCBarRejected && + IsBearish(barDir); + + // + bool isCBarHasBullishPower = isCBarBullishRejected || + isCBarBullishEngulfed; + + // + bool isCBarHasBearishPower = isCBarBearishRejected || + isCBarBearishEngulfed; + + // + bool isBullish = box.IsBullish(); + bool isBearish = box.IsBearish(); + + // + bool lookForBullish = IsBullish(forDir); + bool lookForBearish = IsBearish(forDir); + + // + // Calculate each Direction Breake Price ... + double bullishAppliedPrice = box.lower; + double bearishAppliedPrice = box.upper; + + // + bool isCBarPressedForBullish = + // + isCBarHasBullishPower && + cBar.low < bullishAppliedPrice && + cBar.close > bullishAppliedPrice + // + ; + + // + bool isCBarPressedForBearish = + // + isCBarHasBearishPower && + cBar.high > bearishAppliedPrice && + cBar.close < bearishAppliedPrice + // + ; + + // + bool isPBarBreakedBullishAppliedPrice = + pBar.low < bullishAppliedPrice && + pBar.high > bullishAppliedPrice; + + // + bool isPBarBreakedBearishAppliedPrice = + pBar.low < bearishAppliedPrice && + pBar.high > bearishAppliedPrice; + + // + bool isP2BarBreakedBullishAppliedPrice = + p2Bar.low < bullishAppliedPrice && + p2Bar.high > bullishAppliedPrice; + + // + bool isP2BarBreakedBearishAppliedPrice = + p2Bar.low < bearishAppliedPrice && + p2Bar.high > bearishAppliedPrice; + + // + bool isBullishAppliedPriceBreaked = + isPBarBreakedBullishAppliedPrice || + isP2BarBreakedBullishAppliedPrice; + + // + bool isBearishAppliedPriceBreaked = + isPBarBreakedBearishAppliedPrice || + isP2BarBreakedBearishAppliedPrice; + + // + bool isBullishFakeBreakedOut = + lookForBullish && + isCBarPressedForBullish && + isBullishAppliedPriceBreaked; + + // + bool isBearishFakeBreakedOut = + lookForBearish && + isCBarPressedForBearish && + isBearishAppliedPriceBreaked; + + // + result = isBullishFakeBreakedOut || + isBearishFakeBreakedOut; + + // + // Validating Using FVG if necessary ... + if (forceFVGValidating) + { + // + // Detecting All FVGs Which Placed in Box till Loopback ... + XBoxZone fvg; + + // + XOHCL iBar; + bool has = false; + int start = cBar.Index(); + int end = start + loopback; + for (int i = start; i < end; i++) + { + // + // Initialize Bar ... + has = iBar.Init( + cBar.symbol, + cBar.period, + i // + ); + if (!has) + { + // + fvg.Clean(); + iBar.Clean(); + + // + continue; + } + + // + // Check FVG ... + has = helper + .barAnalyser + .IsFVG( + iBar, + fvg, + forceFVGBarType // + ); + if (!has) + { + // + fvg.Clean(); + iBar.Clean(); + + // + continue; + } + + // + bool isBullishFVG = + fvg.IsBullish() && + isBullishFakeBreakedOut; + + // + bool isBearishFVG = + fvg.IsBearish() && + isBearishFakeBreakedOut; + + // + // Checking FVG Dir ... + has = isBullishFVG || + isBearishFVG; + if (!has) + { + // + fvg.Clean(); + iBar.Clean(); + + // + continue; + } + + // + // Check CBar Must Inside FVG ... + + // + bool isFVGBullishBreaked = + isBullishFVG && + cBar.low < fvg.upper && + cBar.close > fvg.upper && + isBullishFakeBreakedOut; + + // + bool isFVGBearishBreaked = + isBearishFVG && + cBar.high > fvg.lower && + cBar.close < fvg.lower && + isBearishFakeBreakedOut; + + // + has = + isFVGBullishBreaked || + isFVGBearishBreaked; + if (has) + { + // + iBar.Clean(); + + // + break; + } + + // + fvg.Clean(); + iBar.Clean(); + } + + // + result = + result && + fvg.IsValid(); + if (result) + { + // + fvg.to = cBar.time; + + // + // Check FVG Size ... + double fvgRange = fvg.upper - fvg.lower; + bool canApplyLastBar = fvgRange < (5 * points); + if (canApplyLastBar) + { + // + // Retrieve FVG Start Bar ... + XOHCL fvgStartBar; + has = fvgStartBar.Init( + cBar.symbol, + cBar.period, + cBar.Index() + 3 // + ); + if (has) + { + // + if (fvg.IsBullish()) + { + fvg.lower = fvgStartBar.low; + } + else + { + fvg.upper = fvgStartBar.high; + } + } + + // + fvgStartBar.Clean(); + } + + // + validatorFVG = fvg; + + // + XCBoxObject *iObj; + has = helper.poiDrawer.DrawBox( + fvg, + iObj // + ); + ZeroMemory(iObj); + } + + // + fvg.Clean(); + iBar.Clean(); + } + + // + // Cleanup Resources ... + + // + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + + // + return result; +} + +// +// Detect Activated FVG ... +bool IsBoxHasActivatedFVG( + XCXCAEAHelper *helper, + XBoxZone &box, + XBoxZone &fvg, + int barIndex = 0, + int loopback = 10, + bool forceFVGBarType = false // +) +{ + // + bool result = false; + + // + fvg.Clean(); + + // + // Normalize Args ... + barIndex = NormalizeInt(barIndex, 0); + loopback = NormalizeInt(loopback, 10); + + // + // Validate Decision Box ... + result = box.IsValid() && + helper != NULL; + if (!result) + { + return result; + } + + // + bool isBullish = box.IsBullish(); + bool isBearish = box.IsBearish(); + double points = GetPoints(box.symbol); + + // + // Retrieve Conditions ... + XCAEAConditions conditions; + result = helper.GetConditions( + conditions, + barIndex, + loopback // + ); + if (!result) + { + // + conditions.Clean(); + + // + return result; + } + + // + // Extract Bars ... + + // + XOHCL cBar; + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + + // + result = cBar.Init( + box.symbol, + box.period, + barIndex + 1 // + ); + result = result && + cBar.GetPreviousBar(pBar); + result = result && + pBar.GetPreviousBar(p2Bar); + result = result && + p2Bar.GetPreviousBar(p3Bar); + if (!result) + { + // + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + conditions.Clean(); + + // + return result; + } + + // + // Find FVG ... + + // + XOHCL iBar; + bool has = false; + int start = cBar.Index(); + int end = start + loopback; + for (int i = start; i < end; i++) + { + // + // Initialize Bar ... + has = iBar.Init( + cBar.symbol, + cBar.period, + i // + ); + if (!has) + { + // + fvg.Clean(); + iBar.Clean(); + + // + continue; + }; + + // + // Check FVG ... + has = helper + .barAnalyser + .IsFVG( + iBar, + fvg, + forceFVGBarType // + ); + if (!has) + { + // + fvg.Clean(); + iBar.Clean(); + + // + continue; + } + + // + // Validate FVG ... + has = + // + fvg.IsValid() && + fvg.dir == box.dir && + fvg.from > box.from && + fvg.upper <= box.upper && + fvg.lower >= box.lower + // + ; + if (!has) + { + // + fvg.Clean(); + iBar.Clean(); + + // + continue; + } + + // + // Check CBar FVG Validations ... + + // + bool isCBarBullishRejected = + isBullish && + cBar.low < fvg.upper && + cBar.close > fvg.upper; + + // + bool isCBarBearishRejected = + isBearish && + cBar.high > fvg.lower && + cBar.close < fvg.lower; + + // + has = isCBarBullishRejected || + isCBarBearishRejected; + if (has) + { + // + iBar.Clean(); + + // + break; + } + + // + fvg.Clean(); + iBar.Clean(); + } + + // + result = fvg.IsValid(); + if (result) + { + // + fvg.to = cBar.time; + + // + // Check FVG Size ... + double fvgRange = fvg.upper - fvg.lower; + bool canApplyLastBar = true; + // fvgRange < (5 * points); + if (canApplyLastBar) + { + // + // Retrieve FVG Start Bar ... + XOHCL fvgStartBar; + has = fvgStartBar.Init( + cBar.symbol, + cBar.period, + cBar.Index() + 4 // + ); + if (has) + { + // + if (fvg.IsBullish()) + { + fvg.lower = fvgStartBar.low; + } + else + { + fvg.upper = fvgStartBar.high; + } + } + + // + fvgStartBar.Clean(); + } + + // + XCBoxObject *iObj; + helper.poiDrawer.DrawBox( + fvg, + iObj // + ); + ZeroMemory(iObj); + } + + // + // Cleanup Resources ... + + // + iBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + conditions.Clean(); + + // + return result; +} + +// \ No newline at end of file diff --git a/BKPS/14040218 XCAEA/XCAEA/Signals/xcaea.signaller.class.mq5 b/BKPS/14040218 XCAEA/XCAEA/Signals/xcaea.signaller.class.mq5 new file mode 100644 index 0000000..fdb9cb6 --- /dev/null +++ b/BKPS/14040218 XCAEA/XCAEA/Signals/xcaea.signaller.class.mq5 @@ -0,0 +1,900 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XCXCAEASignaller ... +// Description: Class for XCAEA 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 Class for XCAEA Signaller" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.base.class.mq5" +#include "../../Classes/x-saherelm.x-cobject.class.mq5" +#include "../Classes/xcaea.x-poi.detector.class.mq5" +#include "../Classes/xcaea.x-poi.drawer.class.mq5" +#include "../Helpers/xcaea.helper.mq5" +#include "../Libraries/xcaea.signaller.lib.mq5" + +// +// Definitions ... + +class XCXCAEASignaller : XCBase +{ + // + // Public ... + public: + // + // Props ... + bool useGuards; + bool useTargets; + int poiLoopback; + XCAEAInputs inputs; + XBarTracker barTraker; + XCXCAEAHelper *helper; + XCXCAEAPOIDrawer *drawer; + bool continuesRFTillTarget; + XBoxZone unAvailableBoxes[]; + XCXCAEAPOIDetector *detector; + XCAEAStrategyConditions mConditions; + XCAEAStrategyConditions mConditionsCollection[]; + + // + // Constructor ... + XCXCAEASignaller( + string _symbol, + ENUM_TIMEFRAMES _period // + ) + { + // + symbol = _symbol; + period = _period; + + // + Init(); + } + + // + // Deconstructor ... + ~XCXCAEASignaller() + { + DeInit(); + } + + // + // Properties ... + + /** + * Initialize ... + */ + void Init() + { + // + useGuards = false; + useTargets = true; + continuesRFTillTarget = false; + + // + barTraker.Init( + symbol, + period // + ); + + // + inputs.Default(); + + // + // Configure Indicators ... + + // + // XCC ... + inputs.ccInputs.showCandles = true; + + // + // XCT ... + inputs.ctInputs.showCandleTime = true; + + // + // XCA ... + + // + inputs.caInputs.supResSmoothingLength = 7; + inputs.caInputs.supResSmoothingMode = X_MA_MODE_NONE; + + // + inputs.x3maInputs.applyColor = true; + + // + inputs.x3maInputs.fastLength = 5; + + // + inputs.x3maInputs.showFast = false; + inputs.x3maInputs.showSlow = false; + inputs.x3maInputs.showMedium = false; + + // + inputs.caInputs.showMAH = false; + inputs.caInputs.showMAL = false; + inputs.caInputs.showMAC = false; + inputs.caInputs.showSar = false; + inputs.caInputs.showSwings = true; + inputs.caInputs.showFiboLevel1 = false; + inputs.caInputs.showFiboLevel2 = false; + inputs.caInputs.showFiboLevel3 = false; + inputs.caInputs.showFiboLevel4 = false; + inputs.caInputs.showFiboLevel5 = false; + inputs.caInputs.showPeaksAndVales = true; + + // + inputs.caInputs.showKI = false; + inputs.caInputs.showTKI = false; + inputs.caInputs.showVidya = false; + inputs.caInputs.showTrend = false; + inputs.caInputs.showPeakAndValeGolden = false; + inputs.caInputs.showSupportAndResistance = false; + + // + // XOSCS ... + // inputs.oscsInputs.rsiLength = 5; + // inputs.oscsInputs.rsiOBLevel = 90; + // inputs.oscsInputs.rsiOSLevel = 10; + // inputs.oscsInputs.cciLength = 7; + // inputs.oscsInputs.cciOBLevel = 130; + // inputs.oscsInputs.cciOSLevel = -130; + // inputs.oscsInputs.mfiLength = 5; + // inputs.oscsInputs.rviLength = 5; + + // + // Oscillators Views ... + inputs.showRSI = false; + inputs.showCCI = false; + inputs.showMFI = false; + inputs.showRVI = false; + inputs.showADX = false; + inputs.showMACD = false; + + // + // XCAEA Helper ... + helper = new XCXCAEAHelper(); + helper.Init( + symbol, + period, + inputs // + ); + + // + // Initialize and Configure Detector ... + detector = new XCXCAEAPOIDetector(helper); + + // + // Common Configurations ... + detector.maxAllowedPivots = 0; + detector.pivotVerifications = 5; + detector.ticksDividerInPoints = 15; + detector.pivotDetectionLoopbac = 1000; + + // + // Configure Detector ... + + // + // PV ... + + // + detector.maxAllowedPVLifetime = 0; + detector.applySwingsOnPVPivots = true; + detector.selectRejectedPVPivots = true; + detector.selectEngulfedPVPivots = true; + detector.applySupportAndResistanceOnPVPivots = true; + + // + // PEAK ... + detector.detectPeakPivots = true; + + // + // VALE ... + detector.detectValePivots = true; + + // + // FVG ... + + // + detector.selectSameBarFVGs = false; + detector.maxAllowedFVGLifetime = 0; + detector.validateFVGUsingPV = false; + detector.applyPVToFVGBoundary = false; + detector.selectRejectedFVGPivots = false; + detector.selectEngulfedFVGPivots = false; + detector.validateFVGUsingManalyser = true; + detector.applyLastBarToFVGBoundary = false; + detector.selectOnlyFVGWhichHasIndirectionalLastBar = true; + + // + // Bullish ... + detector.detectFVGBullishPivots = true; + + // + // Bearish ... + detector.detectFVGBearishPivots = true; + + // + // TREND ... + + // + detector.maxAllowedTrendLifetime = 0; + + // + // Bullish ... + detector.detectTrendBullishPivots = true; + + // + // Bearish ... + detector.detectTrendBearishPivots = true; + + // + // DRAWER ... + + // + // Initialize and Configure Drawer ... + drawer = new XCXCAEAPOIDrawer(detector); + + // + drawer.ignoreUpdateOSCTos = true; + + // + // Configure Drawer ... + drawer.drawPeakPivots = true; + drawer.drawValePivots = true; + drawer.drawFVGBullishPivots = true; + drawer.drawFVGBearishPivots = true; + drawer.drawTrendBullishPivots = true; + drawer.drawTrendBearishPivots = true; + + // + // Configure Styles ... + + // + // PV ... + + // + // PEAK ... + XCAPivotStyle peakStyle; + peakStyle.width = 2; + peakStyle.clr = clrMagenta; + peakStyle.style = STYLE_SOLID; + drawer.peakPivotStyle = peakStyle; + peakStyle.Clean(); + + // + // VALE ... + XCAPivotStyle valeStyle; + valeStyle.width = 2; + valeStyle.clr = clrAqua; + valeStyle.style = STYLE_SOLID; + drawer.valePivotStyle = valeStyle; + valeStyle.Clean(); + + // + // FVG ... + + // + // Bullish ... + XCAPivotStyle fvgBullishStyle; + fvgBullishStyle.width = 2; + fvgBullishStyle.clr = clrLime; + fvgBullishStyle.style = STYLE_DASH; + drawer.fvgBullishPivotStyle = fvgBullishStyle; + fvgBullishStyle.Clean(); + + // + // Bearish ... + XCAPivotStyle fvgBearishStyle; + fvgBearishStyle.width = 2; + fvgBearishStyle.clr = clrRed; + fvgBearishStyle.style = STYLE_DASH; + drawer.fvgBearishPivotStyle = fvgBearishStyle; + fvgBearishStyle.Clean(); + + // + // TREND ... + + // + // Bullish ... + XCAPivotStyle trendBullishStyle; + trendBullishStyle.width = 2; + trendBullishStyle.clr = clrLime; + trendBullishStyle.style = STYLE_DOT; + drawer.trendBullishPivotStyle = trendBullishStyle; + trendBullishStyle.Clean(); + + // + // Bearish ... + XCAPivotStyle trendBearishStyle; + trendBearishStyle.width = 2; + trendBearishStyle.clr = clrRed; + trendBearishStyle.style = STYLE_DOT; + drawer.trendBearishPivotStyle = trendBearishStyle; + trendBearishStyle.Clean(); + + // + } + + /** + * DeInitialize ... + */ + void DeInit() + { + // + inputs.Clean(); + + // + // Cleaning Draws ... + drawer.Clear(); + + // + ZeroMemory(drawer); + ZeroMemory(helper); + ZeroMemory(detector); + + // + mConditions.Clean(); + Clean(mConditionsCollection); + + // + mObjects.Clear(); + mBarObjects.Clear(); + + // + barTraker.Clean(); + } + + // + string GetSymbol() + { + return symbol; + } + + // + ENUM_TIMEFRAMES GetPeriod() + { + return period; + } + + // + // Signaller 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( + double tpReward = 3, + double maxAllowedSLDistanceInPoint = 100 // + ) + { + // + bool result = false; + + // + // Check Bar Processing ... + if (!barTraker.CanProcessBar()) + { + return result; + } + + // + bool isBullish = false; + bool isBearish = false; + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + int loopback = 10; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + double points = GetPoints(symbol); + + // + XOHCL zBar; + XOHCL cBar; + XOHCL pBar; + XOHCL pPBar; + result = zBar.Init( + symbol, + period, + zIndex // + ); + result = + result && + zBar.GetPreviousBar(cBar); + result = + result && + cBar.GetPreviousBar(pBar); + result = + result && + pBar.GetPreviousBar(pPBar); + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + pPBar.Clean(); + + // + return result; + } + + // + // Setup Conditions ... + XBoxZone decisionZone; + bool hasDecisionZone = false; + XCAEAConditions conditions; + ENUM_X_DIRECTION decisionZoneDir = X_DIRECTION_NONE; + + // + // Checking Signal's Decision Zone ... + hasDecisionZone = DetectDecisionZone( + helper, + drawer, + decisionZone, + decisionZoneDir, + conditions, + zIndex, + loopback // + ); + + // + // Make Signal Box UnAvailable ... + if (hasDecisionZone) + { + // + AddRef( + decisionZone, + unAvailableBoxes // + ); + } + + // + isBullish = hasDecisionZone && + IsBullish(decisionZoneDir); + + // + isBearish = hasDecisionZone && + IsBearish(decisionZoneDir); + + // + result = isBullish || + isBearish; + if (result) + { + // + // Do What we Want ... + barTraker.Waits(); + + // + // Prepare Conditions ... + mConditions.symbol = symbol; + mConditions.period = period; + mConditions.time = zBar.time; + mConditions.reward = tpReward; + mConditions.provider = "XCAEA"; + mConditions.setupTime = zBar.time; + mConditions.dir = decisionZoneDir; + mConditions.conditions = conditions; + mConditions.decisionZone = decisionZone; + } + + // + // Cleanup Resource ... + + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + pPBar.Clean(); + + // + conditions.Clean(); + decisionZone.Clean(); + + // + return result; + } + + /** + * Detect Trigger Conditions for Specified Signal ... + * + * @param conditions: XCAEAStrategyConditions instance Reference, Specified Signal Conditions ... + * @param maxAllowedSetupAge: specified Setup Age for Expiration (if bigger than Zero) ... + * + * @return ( bool ) + */ + bool DetectSignalTrigger( + XCAEAStrategyConditions &conditions, + int barIndex = 0, + int maxAllowedSetupAge = 200 // + ) + { + // + bool result = false; + + // + barIndex = NormalizeInt(barIndex, 0); + + // + result = conditions.IsSetuped(); + if (!result) + { + return result; + } + + // + datetime setupTime = conditions.setupTime; + ENUM_X_DIRECTION setupDir = conditions.dir; + + // + helper.GetConditions( + conditions.conditions, + barIndex // + ); + + // + bool isBullish = IsBullish(setupDir); + bool isBearish = IsBearish(setupDir); + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + int loopback = 10; + + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + double points = GetPoints(symbol); + + // + // Check Signal Validation ... + // IMPORTANT: since all Validations done in SetUp Process ... + // here we only Execute Signal ... + + // + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + // Checking Trigger Conditions ... + double sl = 0; + double tp = 0; + ENUM_X_DIRECTION triggerDir = X_DIRECTION_NONE; + + // + // Checking Trigger Cond 0 ... + bool canTriggerCond0 = CanTriggerCond0( + helper, + conditions.decisionZone, + triggerDir, + sl, + tp, + barIndex // + ); + + // + // Checking Trigger Cond 1 ... + bool canTriggerCond1 = false; + // CanTriggerCond1( + // helper, + // conditions.decisionZone, + // triggerDir, + // sl, + // tp, + // barIndex // + // ); + + // + // Checking Trigger Cond 2 ... + bool canTriggerCond2 = false; + // CanTriggerCond2( + // helper, + // conditions.decisionZone, + // triggerDir, + // sl, + // tp, + // barIndex // + // ); + + // + // Update Signal Box To ... + conditions.decisionZone.to = cTime; + + // + XCBoxObject *iObj; + bool has = helper.poiDrawer.DrawBox( + conditions.decisionZone, + iObj // + ); + if (has) + { + mObjects.Add(iObj); + } + ZeroMemory(iObj); + + // + // Summarizing Result ... + result = + canTriggerCond0 || + canTriggerCond1 || + canTriggerCond2; + + // + isBullish = result && + IsBullish(triggerDir); + isBearish = result && + IsBearish(triggerDir); + + // + // Configure Conditions for Preparing Signal ... + if (result) + { + // + // Reconfigure Position TP/SL Entry and etc ... + + // + double entry = GetEntry( + conditions.symbol, + triggerDir // + ); + conditions.entry = entry; + + // + if (tp > 0.0) + { + // + Add( + tp, + conditions.targets // + ); + } + + // + double spred = GetSpread(conditions.symbol); + + // + double risk = MathAbs(entry - sl) + spred; + double reward = (risk * conditions.reward); + tp = + isBullish + ? entry + reward + : entry - reward; + + // + // Handling RF ... + double rfReward = risk * 1.85; + double rfPrice = + isBullish + ? entry + rfReward + : entry - rfReward; + Add( + rfPrice, + conditions.targets // + ); + + // + rfReward = risk * 2.85; + rfPrice = + isBullish + ? entry + rfReward + : entry - rfReward; + Add( + rfPrice, + conditions.targets // + ); + + // + // Handling Partial Close ... + // conditions.partialCloseOnTPLevel = 1; + // conditions.partialCloseMultiplier = 0.5; + + // + conditions.sl = sl; + conditions.tp = tp; + conditions.dir = triggerDir; + conditions.triggerTime = cTime; + conditions.type = isBullish + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_SHORT; + + // + } + + // + // Validating Conditions if not Triggered ... + if (!result) + { + // + // Check Box Age ... + int age = conditions.GetSetupAge(); + bool has = age <= maxAllowedSetupAge; + if (!has) + { + conditions.Clean(); + } + + // + // Check Box Price ... + has = IsBoxBreaked( + helper, + conditions.decisionZone, + barIndex // + ); + if (has) + { + conditions.Clean(); + } + } + + // + // Cleanup ... + + // + 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( + XCAEAGuard &guards[], + const XPosition &positions[] // + ) + { + // + bool result = false; + + // + return result; + } + + /** + * Add Conditions to Conditions Collection if not Exists ... + * + * @param maxAllowed: int, Specified Max Allowed Holding Conditions ... + * + * @return ( int ) + */ + int AddConditionsIfNotExists( + int maxAllowed = 10 // + ) + { + // + int result = 0; + + // + bool isSetuped = IsValid(mConditions.setupTime) && + HasDirection(mConditions.dir); + if (!isSetuped) + { + return result; + } + + // + int count = ArraySize(mConditionsCollection); + if (IsValidSize(count)) + { + // + // Copy Original Items ... + XCAEAStrategyConditions tmpItems[]; + Copy( + mConditionsCollection, + tmpItems // + ); + + // + // Prese Item Data ... + bool isBullish = IsBullish(mConditions.dir); + + // + for (int i = 0; i < count; i++) + { + // + XCAEAStrategyConditions 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; + } + + // + // Protected ... + protected: + // + + // + // Private ... + private: + // + // Props ... + string symbol; + ENUM_TIMEFRAMES period; + CArrayObj mObjects; + CArrayObj mBarObjects; + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14040218 XCAEA/XCAEA/Tests/xcaea.cond2.script.mq5 b/BKPS/14040218 XCAEA/XCAEA/Tests/xcaea.cond2.script.mq5 new file mode 100644 index 0000000..d2a626f --- /dev/null +++ b/BKPS/14040218 XCAEA/XCAEA/Tests/xcaea.cond2.script.mq5 @@ -0,0 +1,647 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center XCond2 MQL5 Script +// ------------------------------------------------- +// Name: XCAEA +// Description: an Exper Advisor which used Panels +// +// 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 XCAEA Cond2 Script" +#property strict + +// +// Imports ... + +// +// Classes ... +#include "../../Classes/x-saherelm.x-poi.class.mq5" + +// +// Libraries ... +#include "../../Libraries/x-saherelm.common.lib.mq5" +#include "../../Libraries/x-saherelm.x-poi.lib.mq5" + +// +// Helpers ... +#include "../Helpers/xcaea.helper.mq5"; + +// +// Definitions ... + +// +// Holds Drawn Objects ... +CArrayObj mObjects; + +// +// Required Objects ... +int mLoopback = 10; +XCAEAInputs mInputs; +XBarTracker mBarTracker; +XCAEAConditions mConditions; +XCXCAEAHelper *helper = NULL; + +// +// Event Handlers ... + +/** + * Initialize Script ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Initialize Helper ... + bool isInited = InitHelper(); + if (!isInited) + { + return INIT_FAILED; + } + + // + return INIT_SUCCEEDED; +} + +/** + * De Initialize Script ... + * + * @param reason: Argument 1 + */ +void OnDeinit(const int reason) +{ + // + mInputs.Clean(); + mConditions.Clean(); + + // + ZeroMemory(helper); +} + +/** + * Handle Tick Event ... + */ +void OnTick() +{ + // + bool has = false; + + // + // Run on New Bar ... + bool isNewBar = mBarTracker.IsNewBar(); + if (!isNewBar) + { + return; + } + + // + // Setting Bar Index ... + int barIndex = 0; + + // + // Retrieve Conditions ... + has = helper.GetConditions( + mConditions, + barIndex, + mLoopback // + ); + if (!has) + { + return; + } + + // + // Handling Logic ... + HandleLogic(); +} + +// +// Custom Functions ... + +/** + * Initialize Helper ... + * + * @return ( bool ) + */ +bool InitHelper() +{ + // + bool result = false; + + // + mInputs.Default(); + + // + // Configure Inputs ... + + // + // Oscilators ... + mInputs.showAC = false; + mInputs.showAD = false; + mInputs.showADX = false; + mInputs.showATR = false; + mInputs.showCCI = false; + mInputs.showRSI = false; + mInputs.showMFI = false; + mInputs.showRVI = false; + mInputs.showMACD = false; + mInputs.showMomentum = false; + mInputs.showStochastic = false; + + // + // XCT ... + mInputs.ctInputs.showCandleTime = true; + + // + // XCC ... + mInputs.ccInputs.showCandles = true; + + // + // X3MA ... + mInputs.x3maInputs.showFast = false; + mInputs.x3maInputs.showSlow = false; + mInputs.x3maInputs.showMedium = false; + + // + // XOSC ... + // mInputs.oscsInputs; + + // + // XCA ... + mInputs.caInputs.showKI = false; + mInputs.caInputs.showSar = false; + mInputs.caInputs.showTKI = false; + mInputs.caInputs.showMAH = true; + mInputs.caInputs.showMAL = true; + mInputs.caInputs.showMAC = true; + mInputs.caInputs.showVidya = false; + mInputs.caInputs.showTrend = false; + mInputs.caInputs.showSwings = false; + mInputs.caInputs.showLongCycle = false; + mInputs.caInputs.showHindCycle = false; + mInputs.caInputs.showShortCycle = false; + mInputs.caInputs.showFiboLevel1 = true; + mInputs.caInputs.showFiboLevel2 = false; + mInputs.caInputs.showFiboLevel3 = true; + mInputs.caInputs.showMediumCycle = false; + mInputs.caInputs.showPeaksAndVales = false; + mInputs.caInputs.showPeakAndValeGolden = false; + mInputs.caInputs.showSupportAndResistance = true; + + // + // Initialize Helper ... + helper = new XCXCAEAHelper(); + result = helper.Init( + _Symbol, + _Period, + mInputs // + ); + if (!result) + { + return result; + } + + // + // Initialize Bar Tracker ... + result = mBarTracker.Init( + _Symbol, + _Period // + ); + if (!result) + { + return result; + } + + // + return result; +} + +/** + * Handle Logic of Script ... + */ +void HandleLogic() +{ + // + // Defining Requirements ... + + // + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + + // + bool has = false; + + // + // Reading Required Values ... + + // + // PEAK ... + double zPeak = mConditions.peakBuffer[zIDX]; + double cPeak = mConditions.peakBuffer[cIDX]; + double pPeak = mConditions.peakBuffer[pIDX]; + double p2Peak = mConditions.peakBuffer[p2IDX]; + + // + // VALE ... + double zVale = mConditions.valeBuffer[zIDX]; + double cVale = mConditions.valeBuffer[cIDX]; + double pVale = mConditions.valeBuffer[pIDX]; + double p2Vale = mConditions.valeBuffer[p2IDX]; + + // + // SAR ... + double zSar = mConditions.sarBuffer[zIDX]; + double cSar = mConditions.sarBuffer[cIDX]; + double pSar = mConditions.sarBuffer[pIDX]; + double p2Sar = mConditions.sarBuffer[p2IDX]; + + // + // KI ... + double zKI = mConditions.kiBuffer[zIDX]; + double cKI = mConditions.kiBuffer[cIDX]; + double pKI = mConditions.kiBuffer[pIDX]; + double p2KI = mConditions.kiBuffer[p2IDX]; + + // + // KI State ... + double zKIState = mConditions.kiStateBuffer[zIDX]; + double cKIState = mConditions.kiStateBuffer[cIDX]; + double pKIState = mConditions.kiStateBuffer[pIDX]; + double p2KIState = mConditions.kiStateBuffer[p2IDX]; + + // + // TKI ... + double zTKI = mConditions.tkiBuffer[zIDX]; + double cTKI = mConditions.tkiBuffer[cIDX]; + double pTKI = mConditions.tkiBuffer[pIDX]; + double p2TKI = mConditions.tkiBuffer[p2IDX]; + + // + // TKI State ... + double zTKIState = mConditions.tkiStateBuffer[zIDX]; + double cTKIState = mConditions.tkiStateBuffer[cIDX]; + double pTKIState = mConditions.tkiStateBuffer[pIDX]; + double p2TKIState = mConditions.tkiStateBuffer[p2IDX]; + + // + // MAH ... + double zMAH = mConditions.mahBuffer[zIDX]; + double cMAH = mConditions.mahBuffer[cIDX]; + double pMAH = mConditions.mahBuffer[pIDX]; + double p2MAH = mConditions.mahBuffer[p2IDX]; + + // + // MAL ... + double zMAL = mConditions.malBuffer[zIDX]; + double cMAL = mConditions.malBuffer[cIDX]; + double pMAL = mConditions.malBuffer[pIDX]; + double p2MAL = mConditions.malBuffer[p2IDX]; + + // + // MAC ... + double zMAC = mConditions.macBuffer[zIDX]; + double cMAC = mConditions.macBuffer[cIDX]; + double pMAC = mConditions.macBuffer[pIDX]; + double p2MAC = mConditions.macBuffer[p2IDX]; + + // + // TREND ... + double zTrend = mConditions.trendBuffer[zIDX]; + double cTrend = mConditions.trendBuffer[cIDX]; + double pTrend = mConditions.trendBuffer[pIDX]; + double p2Trend = mConditions.trendBuffer[p2IDX]; + + // + // TREND State ... + double zTrendState = mConditions.trendStateBuffer[zIDX]; + double cTrendState = mConditions.trendStateBuffer[cIDX]; + double pTrendState = mConditions.trendStateBuffer[pIDX]; + double p2TrendState = mConditions.trendStateBuffer[p2IDX]; + + // + // RESISTANCE ... + double zResistance = mConditions.resistanceBuffer[zIDX]; + double cResistance = mConditions.resistanceBuffer[cIDX]; + double pResistance = mConditions.resistanceBuffer[pIDX]; + double p2Resistance = mConditions.resistanceBuffer[p2IDX]; + + // + // SUPPORT ... + double zSupport = mConditions.supportBuffer[zIDX]; + double cSupport = mConditions.supportBuffer[cIDX]; + double pSupport = mConditions.supportBuffer[pIDX]; + double p2Support = mConditions.supportBuffer[p2IDX]; + + // + // VIDYA ... + double zVIDYA = mConditions.vidyaBuffer[zIDX]; + double cVIDYA = mConditions.vidyaBuffer[cIDX]; + double pVIDYA = mConditions.vidyaBuffer[pIDX]; + double p2VIDYA = mConditions.vidyaBuffer[p2IDX]; + + // + // VIDYA State ... + double zVIDYAState = mConditions.vidyaStateBuffer[zIDX]; + double cVIDYAState = mConditions.vidyaStateBuffer[cIDX]; + double pVIDYAState = mConditions.vidyaStateBuffer[pIDX]; + double p2VIDYAState = mConditions.vidyaStateBuffer[p2IDX]; + + // + // SWING Low ... + double zSwingLow = mConditions.swingLowBuffer[zIDX]; + double cSwingLow = mConditions.swingLowBuffer[cIDX]; + double pSwingLow = mConditions.swingLowBuffer[pIDX]; + double p2SwingLow = mConditions.swingLowBuffer[p2IDX]; + + // + // SWING High ... + double zSwingHigh = mConditions.swingHighBuffer[zIDX]; + double cSwingHigh = mConditions.swingHighBuffer[cIDX]; + double pSwingHigh = mConditions.swingHighBuffer[pIDX]; + double p2SwingHigh = mConditions.swingHighBuffer[p2IDX]; + + // + // FIBO Level 1 ... + double zFiboLevel1 = mConditions.fiboLevel1Buffer[zIDX]; + double cFiboLevel1 = mConditions.fiboLevel1Buffer[cIDX]; + double pFiboLevel1 = mConditions.fiboLevel1Buffer[pIDX]; + double p2FiboLevel1 = mConditions.fiboLevel1Buffer[p2IDX]; + + // + // FIBO Level 2 ... + double zFiboLevel2 = mConditions.fiboLevel2Buffer[zIDX]; + double cFiboLevel2 = mConditions.fiboLevel2Buffer[cIDX]; + double pFiboLevel2 = mConditions.fiboLevel2Buffer[pIDX]; + double p2FiboLevel2 = mConditions.fiboLevel2Buffer[p2IDX]; + + // + // FIBO Level 3 ... + double zFiboLevel3 = mConditions.fiboLevel3Buffer[zIDX]; + double cFiboLevel3 = mConditions.fiboLevel3Buffer[cIDX]; + double pFiboLevel3 = mConditions.fiboLevel3Buffer[pIDX]; + double p2FiboLevel3 = mConditions.fiboLevel3Buffer[p2IDX]; + + // + // X3MA ... + + // + // FAST ... + + // + double z3MAFast = mConditions.fastBuffer[zIDX]; + double c3MAFast = mConditions.fastBuffer[cIDX]; + double p3MAFast = mConditions.fastBuffer[pIDX]; + double p23MAFast = mConditions.fastBuffer[p2IDX]; + + // + double z3MAFastState = mConditions.fastStateBuffer[zIDX]; + double c3MAFastState = mConditions.fastStateBuffer[cIDX]; + double p3MAFastState = mConditions.fastStateBuffer[pIDX]; + double p23MAFastState = mConditions.fastStateBuffer[p2IDX]; + + // + // MEDIUM ... + + // + double z3MAMedium = mConditions.mediumBuffer[zIDX]; + double c3MAMedium = mConditions.mediumBuffer[cIDX]; + double p3MAMedium = mConditions.mediumBuffer[pIDX]; + double p23MAMedium = mConditions.mediumBuffer[p2IDX]; + + // + double z3MAMediumState = mConditions.mediumStateBuffer[zIDX]; + double c3MAMediumState = mConditions.mediumStateBuffer[cIDX]; + double p3MAMediumState = mConditions.mediumStateBuffer[pIDX]; + double p23MAMediumState = mConditions.mediumStateBuffer[p2IDX]; + + // + // SLOW ... + + // + double z3MASlow = mConditions.slowBuffer[zIDX]; + double c3MASlow = mConditions.slowBuffer[cIDX]; + double p3MASlow = mConditions.slowBuffer[pIDX]; + double p23MASlow = mConditions.slowBuffer[p2IDX]; + + // + double z3MASlowState = mConditions.slowStateBuffer[zIDX]; + double c3MASlowState = mConditions.slowStateBuffer[cIDX]; + double p3MASlowState = mConditions.slowStateBuffer[pIDX]; + double p23MASlowState = mConditions.slowStateBuffer[p2IDX]; + + // + // RSI ... + double zRSI = mConditions.rsiBuffer[zIDX]; + double cRSI = mConditions.rsiBuffer[cIDX]; + double pRSI = mConditions.rsiBuffer[pIDX]; + double p2RSI = mConditions.rsiBuffer[p2IDX]; + + // + // Reading Bars ... + + // + XOHCL zBar; + XOHCL cBar; + XOHCL pBar; + XOHCL p2Bar; + XOHCL p3Bar; + XOHCL p4Bar; + has = zBar.Init( + _Symbol, + _Period, + zIDX // + ); + 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; + } + + // + // Reading Bars Related Data ... + + // + // Score ... + + // + double bullishScore = 0; + double bearishScore = 0; + mConditions.GenerateScore( + bullishScore, + bearishScore // + ); + + // + bool isScoreBullish = + bullishScore > bearishScore; + + // + bool isScoreBearish = + bearishScore > bullishScore; + + // + // Generating Conditions Summary ... + string summary = + mConditions + .GenerateSummary(); + + // + // Calculating Range Volumes ... + + // + double bullishVolume = 0; + double bearishVolume = 0; + int volumeRangeLoopback = 5; + helper.barAnalyser.CalculateRangeVolume( + cBar, + bullishVolume, + bearishVolume, + volumeRangeLoopback // + ); + + // + double rangeVolume = bullishVolume = bearishVolume; + double rangeVolumeAvg = rangeVolume / volumeRangeLoopback; + + // + // Preparing Complex Conditions ... + + // + bool isRSIBullish = + cRSI > pRSI && + !mConditions.isRSIOB; + + // + bool isRSIBearish = + cRSI < pRSI && + !mConditions.isRSIOS; + + // + bool isVolumeBullish = bullishVolume > bearishVolume; + bool isVolumeBearish = bullishVolume < bearishVolume; + bool isVolumeOverLast = cBar.volume > pBar.volume; + bool isVolumeOverAvg = cBar.volume > rangeVolumeAvg; + + // + // Cond2 ... + + // + bool isCond2Bullish = + // + mConditions.isUnderMal && + mConditions.isValeIsPivot && + // mConditions.swingLowBuffer[cIDX] > mConditions.valeBuffer[cIDX] && + mConditions.swingLowBuffer[cIDX] < mConditions.fiboLevel3Buffer[cIDX] + // + ; + + // + bool isCond2Bearish = + // + false // && + // + ; + + // + bool isCond2 = isCond2Bullish || + isCond2Bearish; + if (isCond2) + { + // + // Print("Cond2"); + // isCond2Bullish = false; + // isCond2Bearish = false; + } + + // + // Check Results ... + + // + bool isBullish = isCond2Bullish; + bool isBearish = isCond2Bearish; + + // + bool result = isBullish || + isBearish; + if (result) + { + // + datetime time = zBar.time; + + // + ENUM_X_DIRECTION iDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Handle Works ... + if (isCond2) + { + // + string name = "Cond2_" + ToString(iDir); + + // + color clr = isBullish + ? clrAqua + : clrMagenta; + + // + CChartObjectHLine *iObj; + iObj = new CChartObjectHLine(); + has = iObj.Create( + 0, + name, + 0, + time // + ); + if (has) + { + // + // Style Object ... + iObj.Width(1); + iObj.Color(clr); + iObj.Style(STYLE_DOT); + + // + // Store Object ... + mObjects.Add(iObj); + } + } + } +} + +// \ No newline at end of file