From 903c4062e1e18ce5d81ac285ea05338f25122c2f Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Mon, 23 Dec 2024 19:31:05 +0330 Subject: [PATCH] bkp ... --- .../Classes/x-saherelm.base.class.mq5 | 97 + .../Classes/x-saherelm.x-account.class.mq5 | 398 + .../Classes/x-saherelm.x-alert.class.mq5 | 1577 ++ .../Classes/x-saherelm.x-app-dialog.class.mq5 | 275 + .../x-saherelm.x-bar.analyser.class.mq5 | 2195 +++ .../Classes/x-saherelm.x-cobject.class.mq5 | 2502 +++ .../Classes/x-saherelm.x-expert.class.mq5 | 927 ++ .../Classes/x-saherelm.x-helper.class.mq5 | 148 + .../Classes/x-saherelm.x-http.class.mq5 | 373 + .../Classes/x-saherelm.x-md5.class.mq5 | 445 + .../Classes/x-saherelm.x-poi.class.mq5 | 4370 +++++ .../Classes/x-saherelm.x-poi.drawer.class.mq5 | 2629 +++ .../Classes/x-saherelm.x-trade.class.mq5 | 3924 +++++ .../Experts/x-saherelm.x-121.smc.ea.ex5 | Bin 0 -> 1083774 bytes .../Experts/x-saherelm.x-121.smc.ea.mq5 | 363 + .../Helpers/x-saherelm.x121.helper.mq5 | 4289 +++++ .../Helpers/x-saherelm.x3ma.helper.mq5 | 758 + .../Helpers/x-saherelm.x3vwap.helper.mq5 | 1150 ++ .../Helpers/x-saherelm.xcc.helper.mq5 | 245 + .../Helpers/x-saherelm.xchsar.helper.mq5 | 1267 ++ .../Helpers/x-saherelm.xct.helper.mq5 | 230 + .../Helpers/x-saherelm.xpv.helper.mq5 | 3237 ++++ BKPS/14031003/Indicators/x-saherelm.x121.ex5 | Bin 0 -> 66444 bytes BKPS/14031003/Indicators/x-saherelm.x121.mq5 | 2241 +++ BKPS/14031003/Indicators/x-saherelm.xcc.ex5 | Bin 0 -> 13184 bytes BKPS/14031003/Indicators/x-saherelm.xcc.mq5 | 437 + BKPS/14031003/Indicators/x-saherelm.xct.ex5 | Bin 0 -> 18038 bytes BKPS/14031003/Indicators/x-saherelm.xct.mq5 | 262 + .../Libraries/x-saherelm.common.lib.mq5 | 13367 ++++++++++++++++ .../Libraries/x-saherelm.draw.lib.mq5 | 2620 +++ .../Libraries/x-saherelm.x-poi.lib.ex5 | Bin 0 -> 7886 bytes .../Libraries/x-saherelm.x-poi.lib.mq5 | 4788 ++++++ .../Libraries/x-saherelm.x-trade.lib.mq5 | 5769 +++++++ .../Classes/x-121.smc.base.strategy.class.mq5 | 1644 ++ .../Classes/x-121.smc.cobjects.class.mq5 | 195 + .../Classes/x-121.smc.ea.panel.class.mq5 | 63 + .../x-121.smc.market.cycle.helper.class.ex5 | Bin 0 -> 16228 bytes .../x-121.smc.market.cycle.helper.class.mq5 | 2433 +++ .../x-121.smc.x-tradehandler.class.mq5 | 4236 +++++ .../Experts/x-121.smc.expert.class.ex5 | Bin 0 -> 17726 bytes .../Experts/x-121.smc.expert.class.mq5 | 1111 ++ .../X121SMCEA/Libraries/x-121.smc.lib.ex5 | Bin 0 -> 13226 bytes .../X121SMCEA/Libraries/x-121.smc.lib.mq5 | 2117 +++ .../Signals/x-121.smc.test.signal.class.mq5 | 1669 ++ .../x-121.smc.test.strategy.class.ex5 | Bin 0 -> 16784 bytes .../x-121.smc.test.strategy.class.mq5 | 2108 +++ 46 files changed, 76459 insertions(+) create mode 100644 BKPS/14031003/Classes/x-saherelm.base.class.mq5 create mode 100644 BKPS/14031003/Classes/x-saherelm.x-account.class.mq5 create mode 100644 BKPS/14031003/Classes/x-saherelm.x-alert.class.mq5 create mode 100644 BKPS/14031003/Classes/x-saherelm.x-app-dialog.class.mq5 create mode 100644 BKPS/14031003/Classes/x-saherelm.x-bar.analyser.class.mq5 create mode 100644 BKPS/14031003/Classes/x-saherelm.x-cobject.class.mq5 create mode 100644 BKPS/14031003/Classes/x-saherelm.x-expert.class.mq5 create mode 100644 BKPS/14031003/Classes/x-saherelm.x-helper.class.mq5 create mode 100644 BKPS/14031003/Classes/x-saherelm.x-http.class.mq5 create mode 100644 BKPS/14031003/Classes/x-saherelm.x-md5.class.mq5 create mode 100644 BKPS/14031003/Classes/x-saherelm.x-poi.class.mq5 create mode 100644 BKPS/14031003/Classes/x-saherelm.x-poi.drawer.class.mq5 create mode 100644 BKPS/14031003/Classes/x-saherelm.x-trade.class.mq5 create mode 100644 BKPS/14031003/Experts/x-saherelm.x-121.smc.ea.ex5 create mode 100644 BKPS/14031003/Experts/x-saherelm.x-121.smc.ea.mq5 create mode 100644 BKPS/14031003/Helpers/x-saherelm.x121.helper.mq5 create mode 100644 BKPS/14031003/Helpers/x-saherelm.x3ma.helper.mq5 create mode 100644 BKPS/14031003/Helpers/x-saherelm.x3vwap.helper.mq5 create mode 100644 BKPS/14031003/Helpers/x-saherelm.xcc.helper.mq5 create mode 100644 BKPS/14031003/Helpers/x-saherelm.xchsar.helper.mq5 create mode 100644 BKPS/14031003/Helpers/x-saherelm.xct.helper.mq5 create mode 100644 BKPS/14031003/Helpers/x-saherelm.xpv.helper.mq5 create mode 100644 BKPS/14031003/Indicators/x-saherelm.x121.ex5 create mode 100644 BKPS/14031003/Indicators/x-saherelm.x121.mq5 create mode 100644 BKPS/14031003/Indicators/x-saherelm.xcc.ex5 create mode 100644 BKPS/14031003/Indicators/x-saherelm.xcc.mq5 create mode 100644 BKPS/14031003/Indicators/x-saherelm.xct.ex5 create mode 100644 BKPS/14031003/Indicators/x-saherelm.xct.mq5 create mode 100644 BKPS/14031003/Libraries/x-saherelm.common.lib.mq5 create mode 100644 BKPS/14031003/Libraries/x-saherelm.draw.lib.mq5 create mode 100644 BKPS/14031003/Libraries/x-saherelm.x-poi.lib.ex5 create mode 100644 BKPS/14031003/Libraries/x-saherelm.x-poi.lib.mq5 create mode 100644 BKPS/14031003/Libraries/x-saherelm.x-trade.lib.mq5 create mode 100644 BKPS/14031003/X121SMCEA/Classes/x-121.smc.base.strategy.class.mq5 create mode 100644 BKPS/14031003/X121SMCEA/Classes/x-121.smc.cobjects.class.mq5 create mode 100644 BKPS/14031003/X121SMCEA/Classes/x-121.smc.ea.panel.class.mq5 create mode 100644 BKPS/14031003/X121SMCEA/Classes/x-121.smc.market.cycle.helper.class.ex5 create mode 100644 BKPS/14031003/X121SMCEA/Classes/x-121.smc.market.cycle.helper.class.mq5 create mode 100644 BKPS/14031003/X121SMCEA/Classes/x-121.smc.x-tradehandler.class.mq5 create mode 100644 BKPS/14031003/X121SMCEA/Experts/x-121.smc.expert.class.ex5 create mode 100644 BKPS/14031003/X121SMCEA/Experts/x-121.smc.expert.class.mq5 create mode 100644 BKPS/14031003/X121SMCEA/Libraries/x-121.smc.lib.ex5 create mode 100644 BKPS/14031003/X121SMCEA/Libraries/x-121.smc.lib.mq5 create mode 100644 BKPS/14031003/X121SMCEA/Signals/x-121.smc.test.signal.class.mq5 create mode 100644 BKPS/14031003/X121SMCEA/Strategy/x-121.smc.test.strategy.class.ex5 create mode 100644 BKPS/14031003/X121SMCEA/Strategy/x-121.smc.test.strategy.class.mq5 diff --git a/BKPS/14031003/Classes/x-saherelm.base.class.mq5 b/BKPS/14031003/Classes/x-saherelm.base.class.mq5 new file mode 100644 index 0000000..b367dbe --- /dev/null +++ b/BKPS/14031003/Classes/x-saherelm.base.class.mq5 @@ -0,0 +1,97 @@ +/////////////////////////////////////////////////////// +// +// 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(); + + // + // Retrieve Class Token ... + virtual string GetToken(); + + // + // 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/14031003/Classes/x-saherelm.x-account.class.mq5 b/BKPS/14031003/Classes/x-saherelm.x-account.class.mq5 new file mode 100644 index 0000000..c451091 --- /dev/null +++ b/BKPS/14031003/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/14031003/Classes/x-saherelm.x-alert.class.mq5 b/BKPS/14031003/Classes/x-saherelm.x-alert.class.mq5 new file mode 100644 index 0000000..2c7ef5e --- /dev/null +++ b/BKPS/14031003/Classes/x-saherelm.x-alert.class.mq5 @@ -0,0 +1,1577 @@ +/////////////////////////////////////////////////////// +// +// 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; + } + + // + // 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/14031003/Classes/x-saherelm.x-app-dialog.class.mq5 b/BKPS/14031003/Classes/x-saherelm.x-app-dialog.class.mq5 new file mode 100644 index 0000000..6bfa4d9 --- /dev/null +++ b/BKPS/14031003/Classes/x-saherelm.x-app-dialog.class.mq5 @@ -0,0 +1,275 @@ +/////////////////////////////////////////////////////// +// +// 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); + } + + // + 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/14031003/Classes/x-saherelm.x-bar.analyser.class.mq5 b/BKPS/14031003/Classes/x-saherelm.x-bar.analyser.class.mq5 new file mode 100644 index 0000000..ea635ad --- /dev/null +++ b/BKPS/14031003/Classes/x-saherelm.x-bar.analyser.class.mq5 @@ -0,0 +1,2195 @@ +/////////////////////////////////////////////////////// +// +// 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 ... + + // + // Actions ... + + /** + * 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; + } + + /** + * Calculate Bar Range ... + * + * @param bar: XOHCL instance ... + * + * @return ( double ) + */ + double GetBarRangePercent(XOHCL &bar) + { + // + double result = 0; + + // + result = bar.GetRange() / 100; + + // + 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(); + 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 + { + // + sameBearishBarsFounded++; + canContinueForBullish = 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; + } + + // + dir = + hasBullishSameBars + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; + } + + /** + * Detect Price Consolidation ... + * + * @param bar: XOHCL instance Reference, Start Bar ... + * @param loopback: Integer, Consolidation Range Finder ... + * @param upper: Double Reference ... + * @param lower: Double Reference ... + * @param upperAppliedTo: ENUM_APPLIED_PRICE member, Upper Price ... + * @param lowerAppliedTo: ENUM_APPLIED_PRICE member, Lower Price ... + * + * @return ( bool ) + */ + bool IsConsolidate( + XOHCL &bar, + double &upper, + double &lower, + int loopback = 30, + ENUM_APPLIED_PRICE upperAppliedTo = PRICE_HIGH, + ENUM_APPLIED_PRICE lowerAppliedTo = PRICE_LOW // + ) + { + // + bool result = false; + + // + upper = 0; + lower = 0; + + // + if (loopback < 7) + { + loopback = 7; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int consolidationRange = 30; + double points = GetPoints(bar.symbol); + int index = bar.Index(); + + // + double upperPrice[]; + int upperPriceCount = FillPrice( + upperPrice, + upperAppliedTo, + bar.symbol, + bar.period, + index, + loopback // + ); + + // + double lowerPrice[]; + int lowerPriceCount = FillPrice( + lowerPrice, + lowerAppliedTo, + bar.symbol, + bar.period, + index, + loopback // + ); + + // + result = upperPriceCount == lowerPriceCount && + lowerPriceCount == loopback; + if (!result) + { + return result; + } + + // + upper = upperPrice[ArrayMaximum(upperPrice)]; + lower = lowerPrice[ArrayMinimum(lowerPrice)]; + + // + double range = upper - lower; + result = range <= consolidationRange * points; + + // + return result; + } + + /** + * Check Bar Has Bullish Trend or not ... + * + * @param bar: XOHCL instance ... + * @param forceAll: Boolean ... + * + * @return ( bool ) + */ + bool HasBullishTrend( + XOHCL &bar, + bool forceAll = false // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL tmpHSW[]; + XOHCL tmpLSW[]; + + // + bool trend1 = bar.HasBullishTrend( + tmpHSW, + tmpLSW, + true // + ); + + // + bool trend2 = bar.HasBullishTrend( + tmpHSW, + tmpLSW, + false // + ); + + // + if (!forceAll) + { + // + result = trend1; + if (!result) + { + return result; + } + } + + // + result = + trend1 || + trend2; + + // + return result; + } + + /** + * Check Bar Has Bearish Trend or not ... + * + * @param bar: XOHCL instance ... + * @param forceAll: Boolean ... + * + * @return ( bool ) + */ + bool HasBearishTrend( + XOHCL &bar, + bool forceAll = false // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL tmpHSW[]; + XOHCL tmpLSW[]; + + // + bool trend1 = bar.HasBearishTrend( + tmpHSW, + tmpLSW, + true // + ); + + // + bool trend2 = bar.HasBearishTrend( + tmpHSW, + tmpLSW, + false // + ); + + // + if (!forceAll) + { + // + result = trend1; + if (!result) + { + return result; + } + } + + // + result = + trend1 || + trend2; + + // + return result; + } + + /** + * Check Specified Bar Has Bullish Pattern or not ... + * + * @param bar: XOHCL instance, Specified Bar ... + * @param loopback: Integer, Loopback Length for Patterns ... + * @param verifications: Integer, Number of Given Verifications ... + * @param checkHammer: Boolean, Specified Check Hammer Pattern ... + * @param checkMorningStar: Boolean, Specified Check Morning Star Pattern ... + * @param checkBullishMarubozu: Boolean, Specified Check Marubozu Pattern ... + * @param checkBullishEngulfing: Boolean, Specified Check Engulfing Pattern ... + * + * @return ( bool ) + */ + bool HasBullishPattern( + XOHCL &bar, + int loopback = 0, + int verifications = 1, + bool checkHammer = true, + bool checkMorningStar = true, + bool checkBullishMarubozu = true, + bool checkBullishEngulfing = true // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + if (verifications <= 0) + { + verifications = 1; + } + + // + int founded = 0; + + // + int idx = bar.Index(); + for (int i = idx; i <= idx + loopback; i++) + { + // + XOHCL iBar; + result = iBar.Init( + bar.symbol, + bar.period, + i // + ); + if (!result) + { + break; + } + + // + bool isHammer = + !checkHammer + ? false + : iBar.IsHammer(); + if (isHammer) + { + founded++; + } + + // + bool isMorningStar = + !checkMorningStar + ? false + : iBar.IsMorningStar(); + if (isMorningStar) + { + founded++; + } + + // + bool isBullishMarubozu = + !checkBullishMarubozu + ? false + : iBar.IsBullishMarubozu(); + if (isBullishMarubozu) + { + founded++; + } + + // + bool isBullishEngulfing = + !checkBullishEngulfing + ? false + : iBar.IsBullishEngulfing(); + if (isBullishEngulfing) + { + founded++; + } + + // + } + + // + result = + result && + founded >= verifications; + + // + return result; + } + + /** + * Check Specified Bar Has Bearish Pattern or not ... + * + * @param bar: XOHCL instance, Specified Bar ... + * @param loopback: Integer, Loopback Length for Patterns ... + * @param verifications: Integer, Number of Given Verifications ... + * @param checkShootingStar: Boolean, Specified Check Shooting Star Pattern ... + * @param checkEveningStar: Boolean, Specified Check Evening Star Pattern ... + * @param checkBearishMarubozu: Boolean, Specified Check Marubozu Pattern ... + * @param checkBearishEngulfing: Boolean, Specified Check Engulfing Pattern ... + * + * @return ( bool ) + */ + bool HasBearishPattern( + XOHCL &bar, + int loopback = 0, + int verifications = 1, + bool checkShootingStar = true, + bool checkEveningStar = true, + bool checkBearishMarubozu = true, + bool checkBearishEngulfing = true // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + if (verifications <= 0) + { + verifications = 1; + } + + // + int founded = 0; + + // + int idx = bar.Index(); + for (int i = idx - 1; i <= idx + loopback; i++) + { + // + XOHCL iBar; + result = iBar.Init( + bar.symbol, + bar.period, + i // + ); + if (!result) + { + break; + } + + // + bool isShootingStar = + !checkShootingStar + ? false + : iBar.IsShootingStar(); + if (isShootingStar) + { + founded++; + } + + // + bool isEveningStar = + !checkEveningStar + ? false + : iBar.IsEveningStar(); + if (isEveningStar) + { + founded++; + } + + // + bool isBearishMarubozu = + !checkBearishMarubozu + ? false + : iBar.IsBearishMarubozu(); + if (isBearishMarubozu) + { + founded++; + } + + // + bool isBearishEngulfing = + !checkBearishEngulfing + ? false + : iBar.IsBearishEngulfing(); + if (isBearishEngulfing) + { + founded++; + } + + // + } + + // + result = + result && + founded >= verifications; + + // + return result; + } + + // + // Commons ... + + /** + * Check Specified Bar's Range is Extended or not ... + * + * @param bar: XOHCL instance, Specified Bar ... + * @param loopback: Integer, Loopback Length ... + * + * @return ( bool ) + */ + bool HasExtendedRange( + XOHCL &bar, + int loopback = 3 // + ) + { + // + bool result = false; + + // + if (loopback < 3) + { + loopback = 3; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int index = bar.Index(); + int start = index + 1; + int end = start + loopback; + int count = end - start; + result = count >= 1; + if (!result) + { + return result; + } + + // + double sum = 0; + XOHCL iBar = bar; + for (int i = start; i < end; i++) + { + // + bool isRetrieved = iBar.GetPreviousBar(iBar); + if (!isRetrieved) + { + continue; + } + + // + sum += iBar.GetRange(); + } + + // + result = sum > 0; + if (!result) + { + return result; + } + + // + double avg = sum / count; + + // + result = bar.GetRange() >= avg; + + // + return result; + } + + /** + * Check Specified Bar's Body is Extended or not ... + * + * @param bar: XOHCL instance, Specified Bar ... + * @param loopback: Integer, Loopback Length ... + * + * @return ( bool ) + */ + bool HasExtendedBody( + XOHCL &bar, + int loopback = 3 // + ) + { + // + bool result = false; + + // + if (loopback < 3) + { + loopback = 3; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int index = bar.Index(); + int start = index + 1; + int end = start + loopback; + int count = end - start; + result = count >= 1; + if (!result) + { + return result; + } + + // + double sum = 0; + XOHCL iBar = bar; + for (int i = start; i < end; i++) + { + // + bool isRetrieved = iBar.GetPreviousBar(iBar); + if (!isRetrieved) + { + continue; + } + + // + sum += iBar.GetBody(); + } + + // + result = sum > 0; + if (!result) + { + return result; + } + + // + double avg = sum / count; + + // + result = bar.GetBody() >= avg; + + // + return result; + } + + /** + * Check Specified Bar's Body and Range is Extended or not ... + * + * @param bar: XOHCL instance, Specified Bar ... + * @param loopback: Integer, Loopback Length ... + * + * @return ( bool ) + */ + bool IsExtended( + XOHCL &bar, + int loopback = 3 // + ) + { + // + bool result = false; + + // + bool hasExtendedBody = HasExtendedBody(bar, loopback); + bool hasExtendedRange = HasExtendedRange(bar, loopback); + result = hasExtendedBody && + hasExtendedRange; + + // + return result; + } + + /** + * Check Specified Bar is Swing High or not ... + * + * @param bar: XOHCL instnce ... + * @param range: Integer, Specified Range ... + * + * @return ( bool ) + */ + bool IsSwingHigh( + XOHCL &bar, + int range = 2 // + ) + { + // + bool result = false; + + // + if (range < 1) + { + range = 1; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int index = bar.Index(); + result = range > 0 && + index >= range; + if (!result) + { + return result; + } + + // + string symbol = bar.symbol; + ENUM_TIMEFRAMES period = bar.period; + + // + for (int i = 1; i <= range; i++) + { + // + // Prev Bar ... + XOHCL iPrevBar; + result = iPrevBar.Init( + symbol, + period, + index + i // + ); + if (!result) + { + break; + } + + // + // Next Bar ... + XOHCL iNextBar; + result = iNextBar.Init( + symbol, + period, + index - i // + ); + if (!result) + { + break; + } + + // + result = bar.high >= iPrevBar.high && + bar.high >= iNextBar.high; + if (!result) + { + break; + } + } + + // + return result; + } + + /** + * Check Specified Bar is Swing Low or not ... + * + * @param bar: XOHCL instnce ... + * @param range: Integer, Specified Range ... + * + * @return ( bool ) + */ + bool IsSwingLow( + XOHCL &bar, + int range = 2 // + ) + { + // + bool result = false; + + // + if (range < 1) + { + range = 1; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int index = bar.Index(); + result = range > 0 && + index >= range; + if (!result) + { + return result; + } + + // + string symbol = bar.symbol; + ENUM_TIMEFRAMES period = bar.period; + + // + for (int i = 1; i <= range; i++) + { + // + // Prev Bar ... + XOHCL iPrevBar; + result = iPrevBar.Init( + symbol, + period, + index + i // + ); + if (!result) + { + break; + } + + // + // Next Bar ... + XOHCL iNextBar; + result = iNextBar.Init( + symbol, + period, + index - i // + ); + if (!result) + { + break; + } + + // + result = bar.low <= iPrevBar.low && + bar.low <= iNextBar.low; + if (!result) + { + break; + } + } + + // + return result; + } + + /** + * Check a Bar is Momentum Bar or not ... + * + * @param bar: XOHCL instance ... + * @param dir: ENUM_X_DIRECTION member ... + * @param extend: Integer ... + * @param bodyPercent: Double ... + * + * @return ( bool ) + */ + bool IsMomentumBar( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + int extend = 1, + double bodyPercent = 70 // + ) + { + // + bool result = false; + + // + if (extend < 0) + { + extend = 0; + } + + // + if (bodyPercent < 50) + { + bodyPercent = 50; + } + + // + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid() && + bar.Index() > 0; + if (!result) + { + return result; + } + + // + if (extend > 0) + { + // + result = IsExtended( + bar, + extend // + ); + + // + if (!result) + { + return result; + } + } + + // + double body = bar.GetBody(); + double rp = GetBarRangePercent(bar); + + // + result = body >= rp * bodyPercent; + + // + if (result) + { + // + dir = + bar.IsBullish() + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + return result; + } + + /** + * Check a Bar is Rejection Bar or not ... + * + * @param bar: XOHCL instance ... + * @param dir: ENUM_X_DIRECTION member ... + * @param extend: Integer ... + * @param shadowPercent: Double ... + * + * @return ( bool ) + */ + bool IsRejectionBar( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + int extend = 1, + double shadowPercent = 60 // + ) + { + // + bool result = false; + + // + if (extend < 0) + { + extend = 0; + } + + // + if (shadowPercent < 50) + { + shadowPercent = 50; + } + + // + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid() && + bar.Index() > 0; + if (!result) + { + return result; + } + + // + if (extend > 0) + { + // + result = IsExtended( + bar, + extend // + ); + + // + if (!result) + { + return result; + } + } + + // + double body = bar.GetBody(); + double range = bar.GetRange(); + double shadows = bar.GetShadows(); + double lowShadow = bar.GetLowShadow(); + double highShadow = bar.GetHighShadow(); + double rp = GetBarRangePercent(bar); + + // + result = shadows >= rp * shadowPercent; + + // + if (result) + { + // + dir = + lowShadow > highShadow + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + return result; + } + + /** + * Check Specified Bar is Engulfing Bar or not ... + * + * @param bar: XOHCL instance ... + * @param dir: ENUM_X_DIRECTION member ... + * @param extend: Integer ... + * @param bodyPercent: Double ... + * + * @return ( bool ) + */ + bool IsEngulfBar( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + int extend = 1, + double bodyPercent = 60 // + ) + { + // + bool result = false; + + // + if (extend < 0) + { + extend = 0; + } + + // + if (bodyPercent < 50) + { + bodyPercent = 50; + } + + // + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid() && + bar.Index() > 0; + if (!result) + { + return result; + } + + // + // Previous Bar ... + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + if (extend > 0) + { + // + result = IsExtended( + pBar, + extend // + ); + + // + if (!result) + { + return result; + } + } + + // + // Check Engulfig ... + result = + bar.GetUp() > pBar.GetUp() && + bar.GetDown() < pBar.GetDown(); + if (!result) + { + return result; + } + + // + // Check Engulfing Direction ... + bool isBullishEngulfed = + pBar.IsBearish() && + bar.IsBullish(); + bool isBearishEngulfed = + pBar.IsBullish() && + bar.IsBearish(); + + // + result = isBullishEngulfed || + isBearishEngulfed; + if (!result) + { + return result; + } + + // + dir = isBullishEngulfed + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; + } + + /** + * Check Specified Bar is Pin Bar or not ... + * + * @param bar: XOHCL instance ... + * @param dir: ENUM_X_DIRECTION member ... + * @param extend: Integer ... + * @param shadowPercent: Double ... + * @param bodyPercent: Double ... + * + * @return ( bool ) + */ + bool IsPinBar( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + int extend = 1, + double shadowPercent = 65, + double bodyPercent = 25 // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid() && + bar.Index() > 0 && + bodyPercent > 0 && + shadowPercent > 0 && + bodyPercent < shadowPercent; + if (!result) + { + return result; + } + + // + // Chack Range Extends ... + if (extend > 0) + { + // + result = HasExtendedRange( + bar, + extend // + ); + if (!result) + { + return result; + } + } + + // + // Check Body ... + double rangePercent = GetBarRangePercent(bar); + + // + double body = bar.GetBody(); + double highShadow = bar.GetHighShadow(); + double lowShadow = bar.GetLowShadow(); + + // + // Check Body ... + result = body / rangePercent >= bodyPercent; + if (!result) + { + return result; + } + + // + bool isPassedHighShadow = + highShadow / rangePercent >= shadowPercent; + bool isPassedLowShadow = + lowShadow / rangePercent >= shadowPercent; + result = + isPassedLowShadow || + isPassedHighShadow; + if (!result) + { + return result; + } + + // + dir = isPassedLowShadow + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; + } + + /** + * Decision Bar (Pin, Momentum or Rejection) ... + * + * @param bar: XOHCL instance ... + * @param dir: ENUM_X_DIRECTION member ... + * @param extend: Integer ... + * @param shadowForPinAndRejectionBarPercent: Double ... + * @param bodyForPinBarPercent: Double ... + * @param bodyForEngulfBarPercent: Double ... + * @param bodyForMomentumBarPercent: Double ... + * + * @return ( bool ) + */ + bool IsDecisionBar( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + int extend = 1, + double shadowForPinAndRejectionBarPercent = 65, + double bodyForPinBarPercent = 25, + double bodyForEngulfBarPercent = 65, + double bodyForMomentumBarPercent = 70 // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid() && + bar.Index() > 0; + if (!result) + { + return result; + } + + // + // Pin Bar ... + ENUM_X_DIRECTION pinDir; + bool isPiBar = IsPinBar( + bar, + pinDir, + extend, + shadowForPinAndRejectionBarPercent, + bodyForPinBarPercent // + ); + + // + // Engulfing Bar ... + ENUM_X_DIRECTION engulfDir; + bool isEngulfBar = IsEngulfBar( + bar, + engulfDir, + extend, + bodyForEngulfBarPercent // + ); + + // + // Momentum Bar ... + ENUM_X_DIRECTION momentumDir; + bool isMomentumBar = IsMomentumBar( + bar, + momentumDir, + extend, + bodyForMomentumBarPercent // + ); + + // + // Rejection Bar ... + ENUM_X_DIRECTION rejectionDir; + bool isRejectionBar = IsRejectionBar( + bar, + rejectionDir, + extend, + shadowForPinAndRejectionBarPercent // + ); + + // + result = isPiBar || + isEngulfBar || + isMomentumBar || + isRejectionBar; + if (result) + { + // + if (isPiBar) + { + dir = pinDir; + } + else if (isEngulfBar) + { + dir = engulfDir; + } + else if (isMomentumBar) + { + dir = momentumDir; + } + else + { + dir = rejectionDir; + } + } + + // + result = IsBullish(dir) || + IsBearish(dir); + + // + 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 &dir // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double bearishFib382 = GetFibonacciLevel( + bar.high, + bar.low, + 0.382, + 1 // + ); + double bullishFib382 = GetFibonacciLevel( + bar.high, + bar.low, + 0.382, + -1 // + ); + + // + bool isBullish = bar.GetDown() > bearishFib382; + bool isBearish = bar.GetUp() < bullishFib382; + + // + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + dir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; + } + + // + // Support and Resistance Zones ... + + /** + * Check a Bar is Support Bar or not ... + * + * @param bar: XOHCL instance ... + * @param range: Integer, Specified Verifiation Range ... + * + * @return ( bool ) + */ + bool IsSupport( + XOHCL &bar, + int range = 21 // + ) + { + // + bool result = false; + + // + if (range < 2) + { + range = 2; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int index = bar.Index(); + result = range > 0 && + index >= range; + if (!result) + { + return result; + } + + // + string symbol = bar.symbol; + ENUM_TIMEFRAMES period = bar.period; + + // + for (int i = 1; i <= range; i++) + { + // + int prevIDX = index + i; + int nextIDX = index - 1; + + // + // Prev Bar ... + XOHCL iPrevBar; + result = iPrevBar.Init( + symbol, + period, + prevIDX // + ); + if (!result) + { + break; + } + + // + // Next Bar ... + XOHCL iNextBar; + result = iNextBar.Init( + symbol, + period, + nextIDX // + ); + if (!result) + { + break; + } + + // + result = bar.low <= iPrevBar.low && + bar.low <= iNextBar.low; + if (!result) + { + break; + } + } + + // + return result; + } + + /** + * Check a Bar is Resistance Bar or not ... + * + * @param bar: XOHCL instance ... + * @param range: Integer, Specified Verifiation Range ... + * + * @return ( bool ) + */ + bool IsResistance( + XOHCL &bar, + int range = 21 // + ) + { + // + bool result = false; + + // + if (range < 2) + { + range = 2; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int index = bar.Index(); + result = range > 0 && + index >= range; + if (!result) + { + return result; + } + + // + string symbol = bar.symbol; + ENUM_TIMEFRAMES period = bar.period; + + // + for (int i = 1; i <= range; i++) + { + // + int prevIDX = index + i; + int nextIDX = index - 1; + + // + // Prev Bar ... + XOHCL iPrevBar; + result = iPrevBar.Init( + symbol, + period, + prevIDX // + ); + if (!result) + { + break; + } + + // + // Next Bar ... + XOHCL iNextBar; + result = iNextBar.Init( + symbol, + period, + nextIDX // + ); + if (!result) + { + break; + } + + // + result = bar.high >= iPrevBar.high && + bar.high >= iNextBar.high; + if (!result) + { + break; + } + } + + // + return result; + } + + // + // Order Blocks ... + + /** + * 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 result = false; + + // + ob.Clean(); + dir = X_DIRECTION_NONE; + + // + if (sameBars < 1) + { + sameBars = 1; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int index = 0; + result = HasSameBars( + bar, + dir, + index, + sameBars // + ); + if (!result) + { + return result; + } + + // + int obIndex = index; + result = ob.Init( + bar.symbol, + bar.period, + obIndex // + ); + if (!result) + { + return result; + } + + // + return result; + } + + // + // Fair Value Gaps ... + + /** + * Detect a Fair Value Gap Based on Given Bar ... + * + * @param bar: XOHCL instance, Specified Start Bar ... + * @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 &prevBar, + XOHCL &nextBar, + ENUM_X_DIRECTION &dir, + int sameBars = 3 // + ) + { + // + bool result = false; + + // + prevBar.Clean(); + nextBar.Clean(); + dir = X_DIRECTION_NONE; + + // + if (sameBars < 1) + { + sameBars = 1; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int index = 0; + result = HasSameBars( + bar, + dir, + index, + sameBars // + ); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(dir); + + // + int to = bar.Index() + 1; + int from = index + 1; + for (int i = from; i > to; i--) + { + // + result = prevBar.Init( + bar.symbol, + bar.period, + i // + ); + if (!result) + { + break; + } + + // + result = nextBar.Init( + bar.symbol, + bar.period, + i - 2 // + ); + if (!result) + { + break; + } + + // + result = isBullish + ? prevBar.high < nextBar.low + : prevBar.low > nextBar.high; + if (result) + { + break; + } + } + + // + if (!result) + { + // + prevBar.Clean(); + nextBar.Clean(); + dir = X_DIRECTION_NONE; + } + + // + return result; + } + + // + // Bar CHOCH ... + + /** + * Check Specified Bar Has PullBack or not ... + * + * @param dir: ENUM_X_DIRECTION member, Specified Direction ... + * @param bar: XOHCL instance, Speciied Bar ... + * @param loopback: Integer, loopback Length ... + * @param forceBody: Boolean, Specified Choch Happens only by Bar's Body ... + * + * @return ( bool ) + */ + bool HasPullBack( + ENUM_X_DIRECTION &dir, + XOHCL &bar, + int loopback = 3, + bool forceBody = false // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + if (loopback < 1) + { + loopback = 1; + } + + // + result = bar.IsValid(); + if (!result) + { + 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; + result = CalculateLoopBackData( + index, + start, + end, + count, + bar, + loopback // + ); + if (!result) + { + return result; + } + + // + // Calculate Loopback HH and LL Data ... + int hhIDX = -1; + double hh = -1; + int llIDX = -1; + double ll = -1; + result = CalculateLoopbackHLData( + hhIDX, + hh, + llIDX, + ll, + bar, + loopback // + ); + if (!result) + { + return result; + } + + // + bool isBullishDirection = + bar.high > hh && + bar.low > ll; + bool isBearishDirection = + bar.high < hh && + bar.low < ll; + result = isBullishDirection || + isBearishDirection; + if (!result) + { + return result; + } + + // + if (forceBody) + { + // + isBullishDirection = + bar.GetUp() > hh && + bar.GetDown() > ll; + isBearishDirection = + bar.GetUp() < hh && + bar.GetDown() < ll; + result = isBullishDirection || + isBearishDirection; + if (!result) + { + return result; + } + } + + // + // Check Bar's Direction in related to CHOCH Direction ... + result = + isBullishDirection + ? bar.IsBullish() + : bar.IsBearish(); + if (!result) + { + return result; + } + + // + // Set Direction ... + dir = + isBullishDirection + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Check Loopback End Bar ... + XOHCL endBar; + result = endBar.Init( + symbol, + period, + end - 1 // + ); + if (!result) + { + return result; + } + + // + // End Bar Must be InDirect by Specified Bar ... + result = + isBullishDirection + ? endBar.IsBearish() + : endBar.IsBullish(); + + // + // Check Loopback for Directional Bars ... + + // + return result; + } + + // + protected: + // + + // + private: + // + + // + // Props ... + + // + // Actions ... + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14031003/Classes/x-saherelm.x-cobject.class.mq5 b/BKPS/14031003/Classes/x-saherelm.x-cobject.class.mq5 new file mode 100644 index 0000000..26fc987 --- /dev/null +++ b/BKPS/14031003/Classes/x-saherelm.x-cobject.class.mq5 @@ -0,0 +1,2502 @@ +/////////////////////////////////////////////////////// +// +// 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 + +// +// Definitions ... + +enum ENUM_XCHARTOBJECTS +{ + // + // Global ... + X_ZONE_OBJ = 7860, + X_FROM_TO_OBJ = 7861, + X_BAR_ARROW_OBJ = 7862, + // + X_SIGNAL_OBJ = 8860, + X_TREND_OBJ = 8861, + // + // 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_SL, + X_TP +}; + +// +// 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() + // + ; + 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, + TimeCurrent(), + 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 string name, + const int window, + XSignal &signal // + ) + { + // + bool result = false; + + // + result = IsValid(name) && + signal + .IsValid(); + if (!result) + { + return result; + } + + // + 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; + } + + // + // 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(); + 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); + } + + // + // 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; +}; + +// +// 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; + } + + // + 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; + } + + // + string lblName = "LBL_" + name; + result = mLabel.Create( + chart_id, + lblName, + window, + from, + zone.high // + ); + if (!result) + { + return result; + } + + // + mLabel.Description(ToString(zone.percent) + "%"); + + // + 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) + { + mLabel.Color(value); + } + + /** + * Set Label Size ... + * + * @param value: Integer ... + */ + void LabelSize(int value) + { + mLabel.FontSize(value); + } + + /** + * Set Label Font ... + * + * @param value: String ... + */ + void LabelFont(string value) + { + mLabel.Font(value); + } + + /** + * Set Label Angle ... + * + * @param value: double ... + */ + void LabelAngle(double value) + { + mLabel.Angle(value); + } + + // + private: + // + // Props ... + CChartObjectRectangle mRect; + CChartObjectLabel mLabel; + + // +}; +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/14031003/Classes/x-saherelm.x-expert.class.mq5 b/BKPS/14031003/Classes/x-saherelm.x-expert.class.mq5 new file mode 100644 index 0000000..db538a7 --- /dev/null +++ b/BKPS/14031003/Classes/x-saherelm.x-expert.class.mq5 @@ -0,0 +1,927 @@ +/////////////////////////////////////////////////////// +// +// 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" +#include "../Helpers/x-saherelm.xcc.helper.mq5" +#include "../Helpers/x-saherelm.xct.helper.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() + { + } + + // + // 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; + } + + /** + * Get Slippage ... + * + * @return ( int ) + */ + int Slippage() + { + return mSlippage; + } + + /** + * Set Slippage ... + * + * @param value: Integer ... + */ + void Slippage(int value) + { + mSlippage = value; + } + + /** + * Get Tag Prefix ... + * + * @return ( string ) + */ + string TagPrefix() + { + return mTagPrefix; + } + + /** + * Set Tag Prefix ... + * + * @param value: String ... + */ + void TagPrefix(string value) + { + mTagPrefix = value; + } + + // + // 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; + } + + /** + * Get Symbol ... + * + * @return ( string ) + */ + string GetSymbol() + { + return mSymbol; + } + + /** + * Set Symbol ... + * + * @param value: String ... + */ + void SetSymbol(string value) + { + mSymbol = value; + } + + /** + * 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; + } + + /** + * Get Multi Provided Symbols ... + * + * @return ( string ) + */ + string Symbols() + { + return mSymbols; + } + + /** + * Set Multi Provided Symbols ... + * + * @param value: String ... + */ + void Symbols(string value) + { + mSymbols = value; + } + + // + // Signalling ... + + /** + * Get Force Disable Signalling ... + * + * @return ( bool ) + */ + bool Disabled() + { + return mDisabled; + } + + /** + * Set Force Disable Signalling ... + * + * @param value: Boolean ... + */ + void Disabled(bool value) + { + mDisabled = value; + } + + /** + * Get Allow Long Signals ... + * + * @return ( bool ) + */ + bool AllowLong() + { + return mAllowLong; + } + + /** + * Set Allow Long Signals ... + * + * @param value: Boolean ... + */ + void AllowLong(bool value) + { + mAllowLong = value; + } + + /** + * Get Allow Short Signalling ... + * + * @return ( bool ) + */ + bool AllowShort() + { + return mAllowShort; + } + + /** + * Set Allow Short Signalling ... + * + * @param value: Boolean ... + */ + void AllowShort(bool value) + { + mAllowShort = value; + } + + // + // 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; + } + + /** + * 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; + } + + /** + * 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; + } + + /** + * 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; + } + + // + // 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(); + } + + /** + * 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 ... + + // + // Bar Timer ... + XCTInputs ctInputs; + ctInputs.Default(); // Default Configurations ... + mCTHelper = new XCXCTHelper(); + result = mCTHelper.Init( + _Symbol, + _Period, + ctInputs // + ); + if (!result) + { + return result; + } + + // + // Bar Styles ... + XCCInputs ccInputs; + ccInputs.Default(); // Default Configurations ... + mCCHelper = new XCXCCHelper(); + result = mCCHelper.Init( + _Symbol, + _Period, + ccInputs // + ); + if (!result) + { + return result; + } + + // + // Create Trader Instance and Configure it ... + mTrader = new XCTrade( + mSlippage, + mMagicNumber // + ); + + // + return result; + } + + /** + * Destroy Initialized Requirements ... + */ + virtual void DestroyEA() + { + // + delete mCTHelper; + delete mCCHelper; + } + + /** + * 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 // + ) + { + } + + /** + * Do All Signalling Processing Here ... + */ + virtual void HandleStrategiesOnTick() + { + } + + // + // Time Handlers ... + + virtual void HandleOnNewMonth() + { + } + + virtual void HandleOnNewWeek() + { + } + + virtual void HandleOnNewDay() + { + } + + virtual void HandleOnNewHour() + { + } + + /** + * 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 ... + XCXCTHelper *mCTHelper; // Bar Timer Indicator Helper class ... + XCXCCHelper *mCCHelper; // Chart Styler Indicator Helper Class ... + + // + // 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/14031003/Classes/x-saherelm.x-helper.class.mq5 b/BKPS/14031003/Classes/x-saherelm.x-helper.class.mq5 new file mode 100644 index 0000000..8aa63e8 --- /dev/null +++ b/BKPS/14031003/Classes/x-saherelm.x-helper.class.mq5 @@ -0,0 +1,148 @@ +/////////////////////////////////////////////////////// +// +// 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); + } + + // + // 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/14031003/Classes/x-saherelm.x-http.class.mq5 b/BKPS/14031003/Classes/x-saherelm.x-http.class.mq5 new file mode 100644 index 0000000..631532f --- /dev/null +++ b/BKPS/14031003/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/14031003/Classes/x-saherelm.x-md5.class.mq5 b/BKPS/14031003/Classes/x-saherelm.x-md5.class.mq5 new file mode 100644 index 0000000..e5cc201 --- /dev/null +++ b/BKPS/14031003/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/14031003/Classes/x-saherelm.x-poi.class.mq5 b/BKPS/14031003/Classes/x-saherelm.x-poi.class.mq5 new file mode 100644 index 0000000..c7d77ac --- /dev/null +++ b/BKPS/14031003/Classes/x-saherelm.x-poi.class.mq5 @@ -0,0 +1,4370 @@ +/////////////////////////////////////////////////////// +// +// 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 "../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../Libraries/x-saherelm.x-poi.lib.mq5" + +// +#include + +// +// Implementation ... + +// +// POI Detector Class ... +class XCPOIDetector : public XCBaseAlert +{ + // + public: + // + XCPOIDrawer mDrawer; + + // + // 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 // + ); + + // + // 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 Number of POIs which holds ... + * + * @return ( int ) + */ + int MaxNumberOfPOIs() + { + return mMaxNumberOfPOIs; + } + + /** + * Set Max Number of POIs which holds ... + * 0 => Infinity ... + * + * @param value: Integer ... + */ + void MaxNumberOfPOIs(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mMaxNumberOfPOIs = value; + } + + /** + * Get Number of POI(s) which must Find at Initializations ... + * + * @return ( int ) + */ + int MaxNumberOfRequiredPOIs() + { + return mMaxNumberOfRequiredPOIs; + } + + /** + * Set Number of POI(s) which must Find at Initializations ... + * 2 is Default ... + * + * @param value: Integer ... + */ + void MaxNumberOfRequiredPOIs(int value) + { + // + if (value < 2) + { + value = 2; + } + + // + mMaxNumberOfRequiredPOIs = value; + } + + /** + * Check Is Locked or not ... + * + * @return ( bool ) + */ + bool IsLocked() + { + return mLock; + } + + // + // POI(s) Configs ... + + // + // Swings ... + + /** + * Get Swing Verification Range Length ... + * + * @return ( int ) + */ + int SwingRange() + { + return mSwingRange; + } + + /** + * Set Swing Verification Range Length ... + * + * @param value: Integer ... + */ + void SwingRange(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mSwingRange = value; + } + + // + // Momentum Bars ... + + /** + * Get Momentum Bars must Extends Range ... + * + * @return ( int ) + */ + int MomentumBarExtendRange() + { + return mMomentumBarExtendRange; + } + + /** + * Set Momentum Bars must Extends Range ... + * + * @param value: Integer ... + */ + void MomentumBarExtendRange(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mMomentumBarExtendRange = value; + } + + /** + * Get Momentum Bars Body Percent ... + * + * @return ( double ) + */ + double MomentumBarBodyPercent() + { + return mMomentumBarBodyPercent; + } + + /** + * Set Momentum Bars Body Percent ... + * + * @param value: Double ... + */ + void MomentumBarBodyPercent(double value) + { + // + if (value < 50) + { + value = 50; + } + + // + mMomentumBarBodyPercent = value; + } + + // + // Rejection Bars ... + + /** + * Get Rejection Bars must Extends Range ... + * + * @return ( int ) + */ + int RejectionBarExtendRange() + { + return mRejectionBarExtendRange; + } + + /** + * Set Rejection Bars must Extends Range ... + * + * @param value: Integer ... + */ + void RejectionBarExtendRange(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mRejectionBarExtendRange = value; + } + + /** + * Get Rejection Bars Shadow Percent ... + * + * @return ( double ) + */ + double RejectionBarShadowPercent() + { + return mRejectionBarShadowPercent; + } + + /** + * Set Rejection Bars Shadow Percent ... + * + * @param value: Double ... + */ + void RejectionBarShadowPercent(double value) + { + // + if (value < 50) + { + value = 50; + } + + // + mRejectionBarShadowPercent = value; + } + + // + // Support and Resistance Zone(s) ... + + /** + * Get Support and Resistance Range for Verification ... + * + * @return ( int ) + */ + int SupportAndResistanceRange() + { + return mSupportAndResistanceRange; + } + + /** + * Set Support and Resistance Range for Verification ... + * + * @param value: Integer ... + */ + void SupportAndResistanceRange(int value) + { + // + if (value < 2) + { + value = 2; + } + + // + mSupportAndResistanceRange = value; + } + + // + // Supply and Demand Zone(s) ... + + /** + * Get Supply and Demand Range Verifications ... + * + * @return ( int ) + */ + int SupplyAndDemandRange() + { + return mSupplyAndDemandRange; + } + + /** + * Set Supply and Demand Range Verifications ... + * + * @param value: Integer ... + */ + void SupplyAndDemandRange(int value) + { + // + if (value < 2) + { + value = 2; + } + + // + mSupplyAndDemandRange = value; + } + + // + // Order Blocks ... + + /** + * Get Order Blocks Detection Bars ... + * + * @return ( int ) + */ + int OrderBlocksSameBars() + { + return mOrderBlocksSameBars; + } + + /** + * Set Order Blocks Detection Bars ... + * + * @param value: Argument 1 + */ + void OrderBlocksSameBars(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mOrderBlocksSameBars = value; + } + + // + // Fair Value Gaps ... + + /** + * Get Fair Value Gaps Detection Same Bars ... + * + * @return ( int ) + */ + int FairValueGapsSameBars() + { + return mFairValueGapsSameBars; + } + + /** + * Set Fair Value Gaps Detection Same Bars ... + * + * @param value: Integer ... + */ + void FairValueGapsSameBars(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mFairValueGapsSameBars = value; + } + + // + // Ticks Zone ... + + /** + * Get Ticks Range Levels ... + * + * @return ( int ) + */ + int TicksRangeZoneLevel() + { + return mTicksRangeZoneLevel; + } + + /** + * Set Ticks Range Levels ... + * + * @param value: Integer ... + */ + void TicksRangeZoneLevel(int value) + { + // + if (value < 2) + { + value = 2; + } + + // + mTicksRangeZoneLevel = value; + } + + /** + * Get Ticks Range Zone Loopback Period ... + * + * @return ( int ) + */ + int TicksRangeZoneRange() + { + return mTicksRangeZoneRange; + } + + /** + * Set Ticks Range Zone Loopback Period ... + * + * @param value: Integer ... + */ + void TicksRangeZoneRange(int value) + { + // + if (value < 7) + { + value = 7; + } + + // + mTicksRangeZoneRange = value; + } + + // + // Actions ... + + /** + * Initialize POI Detector ... + */ + void Init() + { + DetectRequiredPOIs(); + } + + /** + * Update POI(s) ... + * + * @param state: an Array Refrence of ENUM_XPOI_EVENTS members ... + */ + int Update( + ENUM_XPOI_EVENTS &state[] // + ) + { + // + int result = 0; + + // + Clean(state); + + // + // Check Bar Tracker if Waits ... + if (!mBarTracker.IsNewBar()) + { + return result; + } + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + datetime cTime = TimeCurrent(); + + // + XOHCL zBar; + bool isInited = zBar.Init( + symbol, + period, + zIndex // + ); + if (!isInited) + { + return result; + } + + // + XOHCL cBar; + isInited = cBar.Init( + symbol, + period, + cIndex // + ); + if (!isInited) + { + return result; + } + + // + // POI Detecting ... + bool isDetected = false; + + // + // Swings ... + int swingRange = SwingRange(); + if (swingRange > 0) + { + // + XOHCL swingBar; + isInited = swingBar.Init( + symbol, + period, + zIndex + swingRange // + ); + if (isInited) + { + // + // Swing High ... + isDetected = DetectSwingHigh(swingBar); + if (isDetected) + { + // + ENUM_XPOI_EVENTS event = X_SWING_HIGH_DETECTED; + XCSwing *param; + bool hasItem = GetLastItem( + param, + mSwingHighs // + ); + if (hasItem) + { + // + NotifyEventListeners( + event, + param // + ); + } + + // + Add( + event, + state // + ); + } + + // + // Swing Low ... + isDetected = DetectSwingLow(swingBar); + if (isDetected) + { + // + ENUM_XPOI_EVENTS event = X_SWING_LOW_DETECTED; + XCSwing *param; + bool hasItem = GetLastItem( + param, + mSwingLows // + ); + if (hasItem) + { + // + NotifyEventListeners( + event, + param // + ); + } + + // + Add( + event, + state // + ); + } + } + } + + // + // Bullish Momentum Bars ... + isDetected = DetectBullishMomentumBar(cBar); + if (isDetected) + { + // + ENUM_XPOI_EVENTS event = X_BULLISH_MOMENTUM_BAR_DETECTED; + XCMomentumBar *param; + bool hasItem = GetLastItem( + param, + mBullishMomentumBars // + ); + if (hasItem) + { + // + NotifyEventListeners( + event, + param // + ); + } + + // + Add( + event, + state // + ); + } + + // + // Bearish Momentum Bars ... + isDetected = DetectBearishMomentumBar(cBar); + if (isDetected) + { + // + ENUM_XPOI_EVENTS event = X_BEARISH_MOMENTUM_BAR_DETECTED; + XCMomentumBar *param; + bool hasItem = GetLastItem( + param, + mBearishMomentumBars // + ); + if (hasItem) + { + // + NotifyEventListeners( + event, + param // + ); + } + + // + Add( + event, + state // + ); + } + + // + // Bullish Rejection Bars ... + isDetected = DetectBullishRejectionBar(cBar); + if (isDetected) + { + // + ENUM_XPOI_EVENTS event = X_BULLISH_REJECTION_BAR_DETECTED; + XCRejectionBar *param; + bool hasItem = GetLastItem( + param, + mBullishRejectionBars // + ); + if (hasItem) + { + // + NotifyEventListeners( + event, + param // + ); + } + + // + Add( + event, + state // + ); + } + + // + // Bearish Rejection Bars ... + isDetected = DetectBearishRejectionBar(cBar); + if (isDetected) + { + // + ENUM_XPOI_EVENTS event = X_BEARISH_REJECTION_BAR_DETECTED; + XCRejectionBar *param; + bool hasItem = GetLastItem( + param, + mBearishRejectionBars // + ); + if (hasItem) + { + // + NotifyEventListeners( + event, + param // + ); + } + + // + Add( + event, + state // + ); + } + + // + // Support and Resistance Zones ... + int supResRange = SupportAndResistanceRange(); + if (supResRange > 0) + { + // + XOHCL supResBar; + isInited = supResBar.Init( + symbol, + period, + zIndex + supResRange // + ); + if (isInited) + { + // + // Support Zones ... + isDetected = DetectSupportZone(supResBar); + if (isDetected) + { + // + ENUM_XPOI_EVENTS event = X_SUPPORT_ZONE_DETECTED; + XCSupportZone *param; + bool hasItem = GetLastItem( + param, + mSupportZones // + ); + if (hasItem) + { + // + NotifyEventListeners( + event, + param // + ); + } + + // + Add( + event, + state // + ); + } + + // + // Resistance Zones ... + isDetected = DetectResistanceZone(supResBar); + if (isDetected) + { + // + ENUM_XPOI_EVENTS event = X_RESISTANCE_ZONE_DETECTED; + XCResistanceZone *param; + bool hasItem = GetLastItem( + param, + mResistanceZones // + ); + if (hasItem) + { + // + NotifyEventListeners( + event, + param // + ); + } + + // + Add( + event, + state // + ); + } + } + } + + // + // Supply And Demand Zones ... + int supDemRange = SupplyAndDemandRange(); + if (supDemRange > 0) + { + // + // Supply Zone ... + isDetected = DetectSupplyZone(cBar); + if (isDetected) + { + // + ENUM_XPOI_EVENTS event = X_SUPPLY_ZONE_DETECTED; + XCSupplyZone *param; + bool hasItem = GetLastItem( + param, + mSupplyZones // + ); + if (hasItem) + { + // + NotifyEventListeners( + event, + param // + ); + } + + // + Add( + event, + state // + ); + } + + // + // Demand Zone ... + isDetected = DetectDemandZone(cBar); + if (isDetected) + { + // + ENUM_XPOI_EVENTS event = X_DEMAND_ZONE_DETECTED; + XCDemandZone *param; + bool hasItem = GetLastItem( + param, + mDemandZones // + ); + if (hasItem) + { + // + NotifyEventListeners( + event, + param // + ); + } + + // + Add( + event, + state // + ); + } + } + + // + // Order Blocks ... + int obSameBars = OrderBlocksSameBars(); + if (obSameBars > 0) + { + // + // Bullish Order Block ... + isDetected = DetectBullishOrderBlock(cBar); + if (isDetected) + { + // + ENUM_XPOI_EVENTS event = X_BULLISH_ORDERBLOCK_DETECTED; + XCOrderBlock *param; + bool hasItem = GetLastItem( + param, + mBullishOrderBlocks // + ); + if (hasItem) + { + // + NotifyEventListeners( + event, + param // + ); + } + + // + Add( + event, + state // + ); + } + + // + // Bearish Order Block ... + isDetected = DetectBearishOrderBlock(cBar); + if (isDetected) + { + // + ENUM_XPOI_EVENTS event = X_BEARISH_ORDERBLOCK_DETECTED; + XCOrderBlock *param; + bool hasItem = GetLastItem( + param, + mBearishOrderBlocks // + ); + if (hasItem) + { + // + NotifyEventListeners( + event, + param // + ); + } + + // + Add( + event, + state // + ); + } + } + + // + // Fair Value Gaps ... + int fvgSameBars = FairValueGapsSameBars(); + if (fvgSameBars > 0) + { + // + // Bullish Fair Value Gap ... + isDetected = DetectBullishFairValueGap(cBar); + if (isDetected) + { + // + ENUM_XPOI_EVENTS event = X_BULLISH_FVG_DETECTED; + XCFVG *param; + bool hasItem = GetLastItem( + param, + mBullishFairValueGaps // + ); + if (hasItem) + { + // + NotifyEventListeners( + event, + param // + ); + } + + // + Add( + event, + state // + ); + } + + // + // Bearish Fair Value Gap ... + isDetected = DetectBearishFairValueGap(cBar); + if (isDetected) + { + // + ENUM_XPOI_EVENTS event = X_BEARISH_FVG_DETECTED; + XCFVG *param; + bool hasItem = GetLastItem( + param, + mBearishFairValueGaps // + ); + if (hasItem) + { + // + NotifyEventListeners( + event, + param // + ); + } + + // + Add( + event, + state // + ); + } + } + + // + // Ticks Range Zone ... + int ticksLevels = TicksRangeZoneLevel(); + int ticksRange = TicksRangeZoneRange(); + if (ticksLevels > 0 && + ticksRange > 0) + { + // + isDetected = DetectTicksZoneRange(cBar); + if (isDetected) + { + } + } + + // + ValidatePOIs(cBar); + + // + CleanupUnusedPOIs(); + + // + mBarTracker.Waits(); + + // + result = ArraySize(state); + + // + return result; + } + + /** + * Destroy Class ... + */ + void Destroy() + { + // + DestroyPOIs(); + DestroySessions(); + DestroyEventListeners(); + } + + // + // Retrievers ... + + /** + * Get Current State of POIs ... + * + * @param state: XPOIState instance ... + */ + void GetState( + XPOIState &state // + ) + { + // + state.Clean(); + + // + state.symbol = mSymbol; + state.period = mPeriod; + state.time = TimeCurrent(); + + // + Copy( + mSwingHighs, + state.swingHighs // + ); + + // + Copy( + mSwingLows, + state.swingLows // + ); + + // + Copy( + mBullishMomentumBars, + state.bullishMomentumBars // + ); + + // + Copy( + mBearishMomentumBars, + state.bearishMomentumBars // + ); + + // + Copy( + mBullishRejectionBars, + state.bullishRejectionBars // + ); + + // + Copy( + mBearishRejectionBars, + state.bearishRejectionBars // + ); + + // + Copy( + mSupportZones, + state.supportZones // + ); + + // + Copy( + mResistanceZones, + state.resistanceZones // + ); + + // + Copy( + mSupplyZones, + state.supplyZones // + ); + + // + Copy( + mDemandZones, + state.demandZones // + ); + + // + Copy( + mBullishOrderBlocks, + state.bullishOrderBlocks // + ); + + // + Copy( + mBearishOrderBlocks, + state.bearishOrderBlocks // + ); + + // + Copy( + mBullishFairValueGaps, + state.bullishFairValueGaps // + ); + + // + Copy( + mBearishFairValueGaps, + state.bearishFairValueGaps // + ); + + // + state.ticksZone = mTicksZone; + + // + } + + // + // Event Listeners ... + + /** + * Add Event Listener ... + * + * @param listener: TOnPOIEvent instance ... + */ + void AddEventListener(TOnPOIEvent listener) + { + // + Add( + listener, + mEventListeners // + ); + } + + // + // Destroy ... + + /** + * Destroy Detected POI(s) ... + */ + void DestroyPOIs() + { + // + Clean(mSwingHighs); + Clean(mSwingLows); + + // + Clean(mBullishMomentumBars); + Clean(mBearishMomentumBars); + + // + Clean(mBullishRejectionBars); + Clean(mBearishRejectionBars); + + // + Clean(mSupportZones); + Clean(mResistanceZones); + + // + Clean(mSupplyZones); + Clean(mDemandZones); + + // + Clean(mBullishOrderBlocks); + Clean(mBearishOrderBlocks); + + // + Clean(mBullishFairValueGaps); + Clean(mBearishFairValueGaps); + } + + /** + * Destroy Added Sessions ... + */ + void DestroySessions() + { + } + + /** + * Destroy Rejistered Event Handlers ... + */ + void DestroyEventListeners() + { + Clean(mEventListeners); + } + + // + // Virtual Actions ... + + /** + * Apply Default Configurations ... + */ + virtual void Default() + { + // + // Common ... + + // + MaxNumberOfPOIs(10); + MaxNumberOfRequiredPOIs(2); + + // + SwingRange(2); + + // + MomentumBarExtendRange(2); + MomentumBarBodyPercent(70); + + // + RejectionBarExtendRange(0); + RejectionBarShadowPercent(55); + + // + SupportAndResistanceRange(7); + + // + SupplyAndDemandRange(144); + + // + OrderBlocksSameBars(3); + + // + FairValueGapsSameBars(3); + + // + TicksRangeZoneLevel(10); + TicksRangeZoneRange(144); + } + + // + // Detector Functions ... + + /** + * Detect Swing High ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool DetectSwingHigh(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int range = SwingRange(); + int barIndex = bar.Index(); + result = range > 0 && + barIndex >= range; + if (!result) + { + return result; + } + + // + result = mBarAnalyser.IsSwingHigh( + bar, + range // + ); + if (result) + { + // + XCSwing *swing; + swing = new XCSwing(); + result = swing.Init( + bar, + X_POI_SWING_HIGH // + ); + + // + if (result) + { + // + Add( + swing, + mSwingHighs // + ); + + // + // XCSwingHighObject *iObj; + // bool isCreated = mDrawer.CreateSwingHigh( + // swing, + // iObj // + // ); + // if (isCreated) + // { + // AddObjectIfNotExists(iObj); + // } + } + } + + // + return result; + } + + /** + * Detect Swing Low ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool DetectSwingLow(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int range = SwingRange(); + int barIndex = bar.Index(); + result = range > 0 && + barIndex >= range; + if (!result) + { + return result; + } + + // + result = mBarAnalyser.IsSwingLow( + bar, + range // + ); + if (result) + { + // + XCSwing *swing; + swing = new XCSwing(); + result = swing.Init( + bar, + X_POI_SWING_LOW // + ); + + // + if (result) + { + // + Add( + swing, + mSwingLows // + ); + + // // + // XCSwingLowObject *iObj; + // bool isCreated = mDrawer.CreateSwingLow( + // swing, + // iObj // + // ); + // if (isCreated) + // { + // AddObjectIfNotExists(iObj); + // } + } + } + + // + return result; + } + + /** + * Detect Bullish Momentum Bar ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool DetectBullishMomentumBar(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid() && + bar.Index() > 0; + if (!result) + { + return result; + } + + // + int extendRange = MomentumBarExtendRange(); + double bodyPercent = MomentumBarBodyPercent(); + ENUM_X_DIRECTION dir; + result = mBarAnalyser.IsMomentumBar( + bar, + dir, + extendRange, + bodyPercent // + ); + result = + result && + dir == X_DIRECTION_BULLISH; + if (result) + { + // + XCMomentumBar *momentumBar; + momentumBar = new XCMomentumBar(); + result = momentumBar.Init(bar); + + // + if (result) + { + // + Add( + momentumBar, + mBullishMomentumBars // + ); + + // + // XCBullishMomentumObject *iObj; + // bool isCreated = mDrawer.CreateBullishMomentumBar( + // momentumBar, + // iObj // + // ); + // if (isCreated) + // { + // AddObjectIfNotExists(iObj); + // } + } + } + + // + return result; + } + + /** + * Detect Bearish Momentum Bar ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool DetectBearishMomentumBar(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid() && + bar.Index() > 0; + if (!result) + { + return result; + } + + // + int extendRange = MomentumBarExtendRange(); + double bodyPercent = MomentumBarBodyPercent(); + ENUM_X_DIRECTION dir; + result = mBarAnalyser.IsMomentumBar( + bar, + dir, + extendRange, + bodyPercent // + ); + result = + result && + dir == X_DIRECTION_BEARISH; + if (result) + { + // + XCMomentumBar *momentumBar; + momentumBar = new XCMomentumBar(); + result = momentumBar.Init(bar); + + // + if (result) + { + // + Add( + momentumBar, + mBearishMomentumBars // + ); + + // + // XCBearishMomentumObject *iObj; + // bool isCreated = mDrawer.CreateBearishMomentumBar( + // momentumBar, + // iObj // + // ); + // if (isCreated) + // { + // AddObjectIfNotExists(iObj); + // } + } + } + + // + return result; + } + + /** + * Detect Bullish Rejection Bar ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool DetectBullishRejectionBar(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid() && + bar.Index() > 0; + if (!result) + { + return result; + } + + // + int extendRange = RejectionBarExtendRange(); + double shadowPercent = RejectionBarShadowPercent(); + ENUM_X_DIRECTION dir; + result = mBarAnalyser.IsRejectionBar( + bar, + dir, + extendRange, + shadowPercent // + ); + result = + result && + dir == X_DIRECTION_BULLISH; + if (result) + { + // + XCRejectionBar *rejectionBar; + rejectionBar = new XCRejectionBar(); + result = rejectionBar.Init(bar); + + // + if (result) + { + // + Add( + rejectionBar, + mBullishRejectionBars // + ); + + // // + // XCBullishRejectionObject *iObj; + // bool isCreated = mDrawer.CreateBullishRejectionBar( + // rejectionBar, + // iObj // + // ); + // if (isCreated) + // { + // AddObjectIfNotExists(iObj); + // } + } + } + + // + return result; + } + + /** + * Detect Bearish Rejection Bar ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool DetectBearishRejectionBar(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid() && + bar.Index() > 0; + if (!result) + { + return result; + } + + // + int extendRange = RejectionBarExtendRange(); + double shadowPercent = RejectionBarShadowPercent(); + ENUM_X_DIRECTION dir; + result = mBarAnalyser.IsRejectionBar( + bar, + dir, + extendRange, + shadowPercent // + ); + result = + result && + dir == X_DIRECTION_BEARISH; + if (result) + { + // + XCRejectionBar *rejectionBar; + rejectionBar = new XCRejectionBar(); + result = rejectionBar.Init(bar); + + // + if (result) + { + // + Add( + rejectionBar, + mBearishRejectionBars // + ); + + // + // XCBearishRejectionObject *iObj; + // bool isCreated = mDrawer.CreateBearishRejectionBar( + // rejectionBar, + // iObj // + // ); + // if (isCreated) + // { + // AddObjectIfNotExists(iObj); + // } + } + } + + // + return result; + } + + /** + * Detect Support Zone ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool DetectSupportZone(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int range = SupportAndResistanceRange(); + int barIndex = bar.Index(); + result = range > 0 && + barIndex >= range; + if (!result) + { + return result; + } + + // + result = mBarAnalyser.IsSupport( + bar, + range // + ); + if (result) + { + // + XCSupportZone *support; + support = new XCSupportZone(); + result = support.Init( + bar, + range // + ); + + // + if (result) + { + // + datetime cTime = TimeCurrent(); + support.To(cTime); + + // + Add( + support, + mSupportZones // + ); + + // // + // XCSupportZoneObject *iObj; + // bool isCreated = mDrawer.CreateSupportZone( + // support, + // iObj // + // ); + // if (isCreated) + // { + // AddObjectIfNotExists(iObj); + // } + } + } + + // + return result; + } + + /** + * Detect Resistance Zone ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool DetectResistanceZone(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int range = SupportAndResistanceRange(); + int barIndex = bar.Index(); + result = range > 0 && + barIndex >= range; + if (!result) + { + return result; + } + + // + result = mBarAnalyser.IsResistance( + bar, + range // + ); + if (result) + { + // + XCResistanceZone *resistance; + resistance = new XCResistanceZone(); + result = resistance.Init( + bar, + range // + ); + + // + if (result) + { + // + Add( + resistance, + mResistanceZones // + ); + + // // + // XCResistanceZoneObject *iObj; + // bool isCreated = mDrawer.CreateResistanceZone( + // resistance, + // iObj // + // ); + // if (isCreated) + // { + // AddObjectIfNotExists(iObj); + // } + } + } + + // + return result; + } + + /** + * Detect Supply Zone ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool DetectSupplyZone(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int range = SupplyAndDemandRange(); + result = range > 0; + if (!result) + { + return result; + } + + // + int hhIDX = -1; + double hh = -1; + + // + int llIDX = -1; + double ll = -1; + + // + result = mBarAnalyser + .CalculateLoopbackHLData( + hhIDX, + hh, + llIDX, + ll, + bar, + range // + ); + if (!result) + { + return result; + } + + // + XOHCL supplyBar; + result = supplyBar.Init( + bar.symbol, + bar.period, + hhIDX // + ); + if (result) + { + // + XCSupplyZone *supply; + supply = new XCSupplyZone(); + result = supply.Init( + supplyBar, + range // + ); + + // + if (result) + { + // + datetime cTime = TimeCurrent(); + supply.To(cTime); + + // + Add( + supply, + mSupplyZones // + ); + + // // + // XCSupplyZoneObject *iObj; + // bool isCreated = mDrawer.CreateSupplyZone( + // supply, + // iObj // + // ); + // if (isCreated) + // { + // AddObjectIfNotExists(iObj); + // } + } + } + + // + return result; + } + + /** + * Detect Demand Zone ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool DetectDemandZone(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int range = SupplyAndDemandRange(); + result = range > 0; + if (!result) + { + return result; + } + + // + int hhIDX = -1; + double hh = -1; + + // + int llIDX = -1; + double ll = -1; + + // + result = mBarAnalyser + .CalculateLoopbackHLData( + hhIDX, + hh, + llIDX, + ll, + bar, + range // + ); + if (!result) + { + return result; + } + + // + XOHCL demandBar; + result = demandBar.Init( + bar.symbol, + bar.period, + llIDX // + ); + if (result) + { + // + XCDemandZone *demand; + demand = new XCDemandZone(); + result = demand.Init( + demandBar, + range // + ); + + // + if (result) + { + // + datetime cTime = TimeCurrent(); + demand.To(cTime); + + // + Add( + demand, + mDemandZones // + ); + + // // + // XCDemandZoneObject *iObj; + // bool isCreated = mDrawer.CreateDemandZone( + // demand, + // iObj // + // ); + // if (isCreated) + // { + // AddObjectIfNotExists(iObj); + // } + } + } + + // + return result; + } + + /** + * Detect Bullish Order Block ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool DetectBullishOrderBlock(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int sameBars = OrderBlocksSameBars(); + result = sameBars > 0; + if (!result) + { + return result; + } + + // + XOHCL obBar; + ENUM_X_DIRECTION dir; + result = mBarAnalyser + .HasOrderBlock( + bar, + obBar, + dir, + sameBars // + ); + result = + result && + dir == X_DIRECTION_BULLISH; + if (!result) + { + return result; + } + + // + if (result) + { + // + XCOrderBlock *ob; + ob = new XCOrderBlock(); + result = ob.Init( + obBar, + dir // + ); + + // + if (result) + { + // + datetime cTime = TimeCurrent(); + ob.To(cTime); + + // + Add( + ob, + mBullishOrderBlocks // + ); + + // // + // XCBullishOrderBlockObject *iObj; + // bool isCreated = mDrawer.CreateBullishOrderBlock( + // ob, + // iObj // + // ); + // if (isCreated) + // { + // AddObjectIfNotExists(iObj); + // } + } + } + + // + return result; + } + + /** + * Detect Bullish Order Block ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool DetectBullishOrderBlock( + XOHCL &bar, + XCOrderBlock *&ob // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int sameBars = OrderBlocksSameBars(); + result = sameBars > 0; + if (!result) + { + return result; + } + + // + XOHCL obBar; + ENUM_X_DIRECTION dir; + result = mBarAnalyser + .HasOrderBlock( + bar, + obBar, + dir, + sameBars // + ); + result = + result && + dir == X_DIRECTION_BULLISH; + if (!result) + { + return result; + } + + // + if (result) + { + // + ob = new XCOrderBlock(); + result = ob.Init( + obBar, + dir // + ); + + // + if (result) + { + // + datetime cTime = TimeCurrent(); + ob.To(cTime); + } + } + + // + return result; + } + + /** + * Detect Bearish Order Block ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool DetectBearishOrderBlock(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int sameBars = OrderBlocksSameBars(); + result = sameBars > 0; + if (!result) + { + return result; + } + + // + XOHCL obBar; + ENUM_X_DIRECTION dir; + result = mBarAnalyser + .HasOrderBlock( + bar, + obBar, + dir, + sameBars // + ); + result = + result && + dir == X_DIRECTION_BEARISH; + if (!result) + { + return result; + } + + // + if (result) + { + // + XCOrderBlock *ob; + ob = new XCOrderBlock(); + result = ob.Init( + obBar, + dir // + ); + + // + if (result) + { + // + datetime cTime = TimeCurrent(); + ob.To(cTime); + + // + Add( + ob, + mBearishOrderBlocks // + ); + + // // + // XCBearishOrderBlockObject *iObj; + // bool isCreated = mDrawer.CreateBearishOrderBlock( + // ob, + // iObj // + // ); + // if (isCreated) + // { + // AddObjectIfNotExists(iObj); + // } + } + } + + // + return result; + } + + /** + * Detect Bearish Order Block ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool DetectBearishOrderBlock( + XOHCL &bar, + XCOrderBlock *&ob // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int sameBars = OrderBlocksSameBars(); + result = sameBars > 0; + if (!result) + { + return result; + } + + // + XOHCL obBar; + ENUM_X_DIRECTION dir; + result = mBarAnalyser + .HasOrderBlock( + bar, + obBar, + dir, + sameBars // + ); + result = + result && + dir == X_DIRECTION_BEARISH; + if (!result) + { + return result; + } + + // + if (result) + { + // + ob = new XCOrderBlock(); + result = ob.Init( + obBar, + dir // + ); + + // + if (result) + { + // + datetime cTime = TimeCurrent(); + ob.To(cTime); + } + } + + // + return result; + } + + /** + * Detect Bullish Fair Value Gap ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool DetectBullishFairValueGap(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int sameBars = FairValueGapsSameBars(); + result = sameBars > 0; + if (!result) + { + return result; + } + + // + XOHCL prevBar; + XOHCL nextBar; + ENUM_X_DIRECTION dir; + result = mBarAnalyser + .HasFairValueGap( + bar, + prevBar, + nextBar, + dir, + sameBars // + ); + result = + result && + dir == X_DIRECTION_BULLISH; + if (!result) + { + return result; + } + + // + if (result) + { + // + XCFVG *fvg; + fvg = new XCFVG(); + result = fvg.Init( + prevBar, + nextBar, + dir // + ); + + // + if (result) + { + // + datetime cTime = TimeCurrent(); + fvg.To(cTime); + + // + Add( + fvg, + mBullishFairValueGaps // + ); + + // // + // XCBullishFairValueGapObject *iObj; + // bool isCreated = mDrawer.CreateBullishFairValueGap( + // fvg, + // iObj // + // ); + // if (isCreated) + // { + // AddObjectIfNotExists(iObj); + // } + } + } + + // + return result; + } + + /** + * Detect Bearish Fair Value Gap ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool DetectBearishFairValueGap(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int sameBars = FairValueGapsSameBars(); + result = sameBars > 0; + if (!result) + { + return result; + } + + // + XOHCL prevBar; + XOHCL nextBar; + ENUM_X_DIRECTION dir; + result = mBarAnalyser + .HasFairValueGap( + bar, + prevBar, + nextBar, + dir, + sameBars // + ); + result = + result && + dir == X_DIRECTION_BEARISH; + if (!result) + { + return result; + } + + // + if (result) + { + // + XCFVG *fvg; + fvg = new XCFVG(); + result = fvg.Init( + prevBar, + nextBar, + dir // + ); + + // + if (result) + { + // + datetime cTime = TimeCurrent(); + fvg.To(cTime); + + // + Add( + fvg, + mBearishFairValueGaps // + ); + + // // + // XCBearishFairValueGapObject *iObj; + // bool isCreated = mDrawer.CreateBearishFairValueGap( + // fvg, + // iObj // + // ); + // if (isCreated) + // { + // AddObjectIfNotExists(iObj); + // } + } + } + + // + return result; + } + + // + protected: + // + + // + // Actions ... + + /** + * Lock ... + */ + void Lock() + { + mLock = true; + } + + /** + * Unlock ... + */ + void Unlock() + { + mLock = false; + } + + /** + * Detect Required POI(s) ... + * + * @param barIndex: Integer Start bar index ... + * 0 is Default ... + */ + void DetectRequiredPOIs(int barIndex = 0) + { + // + // Validate Reuired POI(s) ... + int requiredPOIs = MaxNumberOfRequiredPOIs(); + if (requiredPOIs <= 0) + { + return; + } + + // + // Locking Detector ... + Lock(); + + // + // Normalize Bar Index ... + if (barIndex < 0) + { + barIndex = 0; + } + + // + int swingLowsCount = 0; + int swingHighsCount = 0; + + // + int bullishMomentumBarsCount = 0; + int bearishMomentumBarsCount = 0; + + // + int bullishRejectionBarsCount = 0; + int bearishRejectionBarsCount = 0; + + // + int supportZonesCount = 0; + int resistanceZonesCount = 0; + + // + int supplyZonesCount = 0; + int demandZonesCount = 0; + + // + int bullishOrderBlocksCount = 0; + int bearishOrderBlocksCount = 0; + + // + int bullishFairValueGapsCount = 0; + int bearishFairValueGapsCount = 0; + + // + bool canContinue = true; + + // + while (canContinue) + { + // + // Swings ... + int swingRange = SwingRange(); + if (swingRange > 0) + { + // + // Swing Highs ... + swingHighsCount = DetectRequiredSwingHighs(barIndex); + if (swingHighsCount == requiredPOIs) + { + ArrayReverse(mSwingHighs); + } + + // + // Swing Lows ... + swingLowsCount = DetectRequiredSwingLows(barIndex); + if (swingLowsCount == requiredPOIs) + { + ArrayReverse(mSwingLows); + } + } + + // + bool canLookupMomentumBars = + MomentumBarExtendRange() >= 0 && + MomentumBarBodyPercent() > 0; + if (canLookupMomentumBars) + { + // + // + // Bullish Momentum Bars ... + bullishMomentumBarsCount = DetectRequiredBullishMomentumBars(barIndex); + if (bullishMomentumBarsCount == requiredPOIs) + { + ArrayReverse(mBullishMomentumBars); + } + + // + // Bearish Momentum Bars ... + bearishMomentumBarsCount = DetectRequiredBearishMomentumBars(barIndex); + if (bearishMomentumBarsCount == requiredPOIs) + { + ArrayReverse(mBearishMomentumBars); + } + } + + // + bool canLookupRejectionBars = + RejectionBarExtendRange() >= 0 && + RejectionBarShadowPercent() > 0; + if (canLookupRejectionBars) + { + // + // + // Bullish Rejection Bars ... + bullishRejectionBarsCount = DetectRequiredBullishRejectionBars(barIndex); + if (bullishRejectionBarsCount == requiredPOIs) + { + ArrayReverse(mBullishRejectionBars); + } + + // + // Bearish Rejection Bars ... + bearishRejectionBarsCount = DetectRequiredBearishRejectionBars(barIndex); + if (bearishRejectionBarsCount == requiredPOIs) + { + ArrayReverse(mBearishRejectionBars); + } + } + + // + // Support and Resistance Zones ... + int supResRange = SupportAndResistanceRange(); + if (supResRange > 0) + { + // + // Support Zone(s) ... + supportZonesCount = DetectRequiredSupportZones(barIndex); + if (supportZonesCount == requiredPOIs) + { + ArrayReverse(mSupportZones); + } + + // + // Resistance Zone(s) ... + resistanceZonesCount = DetectRequiredResistanceZones(barIndex); + if (resistanceZonesCount == requiredPOIs) + { + ArrayReverse(mResistanceZones); + } + } + + // + // Supply and Demand Zones ... + int supDemRange = SupplyAndDemandRange(); + if (supDemRange > 0) + { + // + supplyZonesCount = DetectRequiredSupplyZones(barIndex); + if (supplyZonesCount == requiredPOIs) + { + ArrayReverse(mSupplyZones); + } + + // + demandZonesCount = DetectRequiredDemandZones(barIndex); + if (demandZonesCount == requiredPOIs) + { + ArrayReverse(mDemandZones); + } + } + + // + // Oder Blocks ... + int obSameBars = OrderBlocksSameBars(); + if (obSameBars > 0) + { + // + // Bullish Order Blocks ... + bullishOrderBlocksCount = DetectRequiredBullishOrderBlocks(barIndex); + if (bullishOrderBlocksCount == requiredPOIs) + { + ArrayReverse(mBullishOrderBlocks); + } + + // + // Bearish Order Blocks ... + bearishOrderBlocksCount = DetectRequiredBearishOrderBlocks(barIndex); + if (bearishOrderBlocksCount == requiredPOIs) + { + ArrayReverse(mBearishOrderBlocks); + } + } + + // + // Fair Value Gaps ... + int fvgSameBars = FairValueGapsSameBars(); + if (fvgSameBars > 0) + { + // + // Bullish Fair Value Gaps ... + bullishFairValueGapsCount = DetectRequiredBullishFairValueGaps(barIndex); + if (bullishFairValueGapsCount == requiredPOIs) + { + ArrayReverse(mBullishFairValueGaps); + } + + // + // Bearish Fair Value Gaps ... + bearishFairValueGapsCount = DetectRequiredBearishFairValueGaps(barIndex); + if (bearishFairValueGapsCount == requiredPOIs) + { + ArrayReverse(mBearishFairValueGaps); + } + } + + // + // Swings ... + bool canContinueSwingHighs = + swingRange > 0 + ? swingHighsCount < requiredPOIs + : false; + bool canContinueSwingLows = + swingRange > 0 + ? swingLowsCount < requiredPOIs + : false; + + // + // Support and Resistance Zones ... + bool canContinueSupportZones = + supResRange > 0 + ? supportZonesCount < requiredPOIs + : false; + bool canContinueResistanceZones = + supResRange > 0 + ? resistanceZonesCount < requiredPOIs + : false; + + // + // Supply and Demand Zones ... + bool canContinueSupplyZones = + supDemRange > 0 + ? supplyZonesCount < requiredPOIs + : false; + bool canContinueDemandZones = + supDemRange > 0 + ? demandZonesCount < requiredPOIs + : false; + + // + // Order Blocks ... + bool canContinueBullishOrderBlocks = + obSameBars > 0 + ? bullishOrderBlocksCount < requiredPOIs + : false; + bool canContinueBearishOrderBlocks = + obSameBars > 0 + ? bearishOrderBlocksCount < requiredPOIs + : false; + + // + // Fair Value Gaps ... + bool canContinueBullishFairValueGaps = + fvgSameBars > 0 + ? bullishFairValueGapsCount < requiredPOIs + : false; + bool canContinueBearishFairValueGaps = + fvgSameBars > 0 + ? bearishFairValueGapsCount < requiredPOIs + : false; + + // + // Rejection Bars ... + bool canContinueBullishRejectionBars = + canLookupRejectionBars + ? bullishRejectionBarsCount < requiredPOIs + : false; + bool canContinueBearishRejectionBars = + canLookupRejectionBars + ? bearishRejectionBarsCount < requiredPOIs + : false; + + // + // Momentum Bars ... + bool canContinueBullishMomentumBars = + canLookupMomentumBars + ? bullishMomentumBarsCount < requiredPOIs + : false; + bool canContinueBearishMomentumBars = + canLookupMomentumBars + ? bearishMomentumBarsCount < requiredPOIs + : false; + + // + canContinue = + // + // Swings ... + canContinueSwingHighs || + canContinueSwingLows || + // + // Support and Resistance Zones ... + canContinueSupportZones || + canContinueResistanceZones || + // + // Supply and Demand Zones ... + canContinueSupplyZones || + canContinueDemandZones || + // + // Order Blocks ... + canContinueBullishOrderBlocks || + canContinueBearishOrderBlocks || + // + // Fair Value Gaps ... + canContinueBullishFairValueGaps || + canContinueBearishFairValueGaps || + // + // Rejection Bars ... + canContinueBullishRejectionBars || + canContinueBearishRejectionBars || + // + // Momentum Bars ... + canContinueBullishMomentumBars || + canContinueBearishMomentumBars + // + ; + if (canContinue) + { + barIndex++; + } + } + + // + // Unlocking Detector ... + Unlock(); + } + + /** + * Validate Founded POI(s) ... + * + * @param bar: XOHCL instance ... + */ + void ValidatePOIs(XOHCL &bar) + { + } + + /** + * Cleanup Unused Objects ... + */ + void CleanupUnusedPOIs() + { + // + int maxAllowed = MaxNumberOfPOIs(); + if (!IsValidSize(maxAllowed)) + { + return; + } + + // + int swingHighsCount = ArraySize(mSwingHighs); + int swingLowsCount = ArraySize(mSwingLows); + // int tradingDaysCount = ArraySize(mTradingDays); + // int marketSessionsCount = ArraySize(mMarketSessions); + // int momentumBarsCount = ArraySize(mMomentumBars); + // int rejectionBarsCount = ArraySize(mRejectionBars); + // int supportZonesCount = ArraySize(mSupportZones); + // int resistanceZonesCount = ArraySize(mResistanceZones); + // int supplyZonesCount = ArraySize(mSupplyZones); + // int demandZonesCount = ArraySize(mDemandZones); + // int bullishOBsCount = ArraySize(mBullishOrderBlocks); + // int bearishOBsCount = ArraySize(mBearishOrderBlocks); + // int bullishFVGsCount = ArraySize(mBullishFVGs); + // int bearishFVGsCount = ArraySize(mBearishFVGs); + + // + int from = 0; + int requiredPOIs = MaxNumberOfRequiredPOIs(); + int count = maxAllowed - requiredPOIs; + int to = count - 1; + + // + // Swings ... + + // // + // // Swing Highs ... + // if (swingHighsCount >= maxAllowed) + // { + // // + // ArrayRemove( + // mSwingHighs, + // from, + // count // + // ); + // } + + // // + // // Swing Lows ... + // if (swingLowsCount >= maxAllowed) + // { + // // + // ArrayRemove( + // mSwingLows, + // from, + // count // + // ); + // } + + // // + // // Trading Days ... + // if (tradingDaysCount >= maxAllowed) + // { + // // + // ArrayRemove( + // mTradingDays, + // from, + // count // + // ); + + // // + // mTradingDayObjects.DeleteRange( + // from, + // to // + // ); + // } + + // // + // // Market Sessions ... + // if (marketSessionsCount >= maxAllowed) + // { + // // + // ArrayRemove( + // mMarketSessions, + // from, + // count // + // ); + + // // + // mMarketSessionObjects.DeleteRange( + // from, + // to // + // ); + // } + + // // + // // Momentum Bars ... + // if (momentumBarsCount >= maxAllowed) + // { + // // + // ArrayRemove( + // mMomentumBars, + // from, + // count // + // ); + + // // + // mMomentumBarObjects.DeleteRange( + // from, + // to // + // ); + // } + + // // + // // Rejection Bars ... + // if (rejectionBarsCount >= maxAllowed) + // { + // // + // ArrayRemove( + // mRejectionBars, + // from, + // count // + // ); + + // // + // mRejectionBarObjects.DeleteRange( + // from, + // to // + // ); + // } + + // // + // // Support and Resistance Zones ... + + // // + // // Support Zones ... + // if (supportZonesCount >= maxAllowed) + // { + // // + // ArrayRemove( + // mSupportZones, + // from, + // count // + // ); + + // // + // mSupportZoneObjects.DeleteRange( + // from, + // to // + // ); + // } + + // // + // // Resistance Zones ... + // if (resistanceZonesCount >= maxAllowed) + // { + // // + // ArrayRemove( + // mResistanceZones, + // from, + // count // + // ); + + // // + // mResistanceZoneObjects.DeleteRange( + // from, + // to // + // ); + // } + + // // + // // Supply and Demand Zones ... + + // // + // // Supply Zones ... + // if (supplyZonesCount >= maxAllowed) + // { + // // + // ArrayRemove( + // mSupplyZones, + // from, + // count // + // ); + + // // + // mSupplyZoneObjects.DeleteRange( + // from, + // to // + // ); + // } + + // // + // // Demand Zones ... + // if (demandZonesCount >= maxAllowed) + // { + // // + // ArrayRemove( + // mDemandZones, + // from, + // count // + // ); + + // // + // mDemandZoneObjects.DeleteRange( + // from, + // to // + // ); + // } + + // // + // // Order Blocks ... + + // // + // // Bullish Order Blocks ... + // if (bullishOBsCount >= maxAllowed) + // { + // // + // ArrayRemove( + // mBullishOrderBlocks, + // from, + // count // + // ); + + // // + // mBullishOrderBlockObjects.DeleteRange( + // from, + // to // + // ); + // } + + // // + // // Bearish Order Blocks ... + // if (bearishOBsCount >= maxAllowed) + // { + // // + // ArrayRemove( + // mBearishOrderBlocks, + // from, + // count // + // ); + + // // + // mBearishOrderBlockObjects.DeleteRange( + // from, + // to // + // ); + // } + + // // + // // Fair Vakue Gaps ... + + // // + // // Bullish FVGs ... + // if (bullishFVGsCount >= maxAllowed) + // { + // // + // ArrayRemove( + // mBullishFVGs, + // from, + // count // + // ); + + // // + // mBullishFVGObjects.DeleteRange( + // from, + // to // + // ); + // } + + // // + // // Bearish FVGs ... + // if (bearishFVGsCount >= maxAllowed) + // { + // // + // ArrayRemove( + // mBearishFVGs, + // from, + // count // + // ); + + // // + // mBearishFVGObjects.DeleteRange( + // from, + // to // + // ); + // } + + // + } + + /** + * 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 // + ); + } + } + + void AddObjectIfNotExists(XCBaseObject *object) + { + // + string name = object.ObjName(); + + // + bool canAdd = true; + int count = mDrawnObjects.Total(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + string iName = ((XCBaseObject *)mDrawnObjects.At(i)).ObjName(); + + // + if (name == iName) + { + // + canAdd = false; + break; + } + } + } + + // + if (canAdd) + { + mDrawnObjects.Add(object); + } + } + + // + private: + // + + // + // Props ... + + // + bool mLock; // Lock State ... + string mSymbol; // Market Symbol ... + ENUM_TIMEFRAMES mPeriod; // Market Period ... + int mMaxNumberOfPOIs; // Max Allowed Number of POI(s) which Can Holds ... + int mMaxNumberOfRequiredPOIs; // Max Allowed Number of POI(s) which Must Find at Initializion Time ... + + // + CArrayObj mDrawnObjects; // Drawn Objects ... + XBarTracker mBarTracker; // Market Bar Tracker ... + XCBarAnalyser mBarAnalyser; // Bar Analyser ... + + // + TOnPOIEvent mEventListeners[]; // Event Listeners ... + + // + // POI Props ... + + // + // XDay ... + + // + // XSession ... + + // + // XSwing ... + int mSwingRange; // Swing Verification Range Length ... + + // + // Swing High ... + + // + XCSwing *mSwingHighs[]; // Holds Founded Swing Highs ... + + /** + * Detect Required Swing Highs ... + * + * @param barIndex: Integer Start bar index ... + * 0 is Default ... + * + * @return ( int ) + */ + int DetectRequiredSwingHighs(int barIndex = 0) + { + // + int result = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int required = MaxNumberOfRequiredPOIs(); + if (required <= 0) + { + return result; + } + + // + int count = ArraySize(mSwingHighs); + if (count >= required) + { + // + result = count; + return result; + } + + // + int range = SwingRange(); + if (range < 0 || barIndex < range) + { + return result; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + XOHCL bar; + bool isInited = bar.Init( + symbol, + period, + barIndex // + ); + if (!isInited) + { + return result; + } + + // + DetectSwingHigh(bar); + + // + result = ArraySize(mSwingHighs); + + // + return result; + } + + // + // Swing Low ... + + // + XCSwing *mSwingLows[]; // Holds Founded Swing Lows ... + + /** + * Detect Required Swing Lows ... + * + * @param barIndex: Integer Start bar index ... + * 0 is Default ... + * + * @return ( int ) + */ + int DetectRequiredSwingLows(int barIndex = 0) + { + // + int result = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int required = MaxNumberOfRequiredPOIs(); + if (required <= 0) + { + return result; + } + + // + int count = ArraySize(mSwingLows); + if (count >= required) + { + // + result = count; + return result; + } + + // + int range = SwingRange(); + if (range < 0 || barIndex < range) + { + return result; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + XOHCL bar; + bool isInited = bar.Init( + symbol, + period, + barIndex // + ); + if (!isInited) + { + return result; + } + + // + DetectSwingLow(bar); + + // + result = ArraySize(mSwingLows); + + // + return result; + } + + // + // Momentum Bars ... + int mMomentumBarExtendRange; // Momentum Bars must Extends Range ... + double mMomentumBarBodyPercent; // Momentum Bars Body Percent ... + + // + // Bullish ... + XCMomentumBar *mBullishMomentumBars[]; // Holds Founded Bullish Momentum Bars ... + + /** + * Detect Required Bullish Momentum Bars ... + * + * @param barIndex: Integer Start bar index ... + * 0 is Default ... + * + * @return ( int ) + */ + int DetectRequiredBullishMomentumBars(int barIndex = 0) + { + // + int result = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int required = MaxNumberOfRequiredPOIs(); + if (required <= 0) + { + return result; + } + + // + int count = ArraySize(mBullishMomentumBars); + if (count >= required) + { + // + result = count; + return result; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + XOHCL bar; + bool isInited = bar.Init( + symbol, + period, + barIndex // + ); + if (!isInited) + { + return result; + } + + // + DetectBullishMomentumBar(bar); + + // + result = ArraySize(mBullishMomentumBars); + + // + return result; + } + + // + // Bearish ... + XCMomentumBar *mBearishMomentumBars[]; // Holds Founded Bearish Momentum Bars ... + + /** + * Detect Required Bearish Momentum Bars ... + * + * @param barIndex: Integer Start bar index ... + * 0 is Default ... + * + * @return ( int ) + */ + int DetectRequiredBearishMomentumBars(int barIndex = 0) + { + // + int result = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int required = MaxNumberOfRequiredPOIs(); + if (required <= 0) + { + return result; + } + + // + int count = ArraySize(mBearishMomentumBars); + if (count >= required) + { + // + result = count; + return result; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + XOHCL bar; + bool isInited = bar.Init( + symbol, + period, + barIndex // + ); + if (!isInited) + { + return result; + } + + // + DetectBearishMomentumBar(bar); + + // + result = ArraySize(mBearishMomentumBars); + + // + return result; + } + + // + // Rejection Bars ... + int mRejectionBarExtendRange; // Rejection Bars must Extends Range ... + double mRejectionBarShadowPercent; // Rejection Bars Shadow Percent ... + + // + // Bullish ... + XCRejectionBar *mBullishRejectionBars[]; // Holds Founded Bullish Rejection Bars ... + + /** + * Detect Required Bullish Rejection Bars ... + * + * @param barIndex: Integer Start bar index ... + * 0 is Default ... + * + * @return ( int ) + */ + int DetectRequiredBullishRejectionBars(int barIndex = 0) + { + // + int result = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int required = MaxNumberOfRequiredPOIs(); + if (required <= 0) + { + return result; + } + + // + int count = ArraySize(mBullishRejectionBars); + if (count >= required) + { + // + result = count; + return result; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + XOHCL bar; + bool isInited = bar.Init( + symbol, + period, + barIndex // + ); + if (!isInited) + { + return result; + } + + // + DetectBullishRejectionBar(bar); + + // + result = ArraySize(mBullishRejectionBars); + + // + return result; + } + + // + // Bearish ... + XCRejectionBar *mBearishRejectionBars[]; // Holds Founded Bearish Rejection Bars ... + + /** + * Detect Required Bearish Rejection Bars ... + * + * @param barIndex: Integer Start bar index ... + * 0 is Default ... + * + * @return ( int ) + */ + int DetectRequiredBearishRejectionBars(int barIndex = 0) + { + // + int result = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int required = MaxNumberOfRequiredPOIs(); + if (required <= 0) + { + return result; + } + + // + int count = ArraySize(mBearishRejectionBars); + if (count >= required) + { + // + result = count; + return result; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + XOHCL bar; + bool isInited = bar.Init( + symbol, + period, + barIndex // + ); + if (!isInited) + { + return result; + } + + // + DetectBearishRejectionBar(bar); + + // + result = ArraySize(mBearishRejectionBars); + + // + return result; + } + + // + // Support and Resistance Zone ... + int mSupportAndResistanceRange; // Support and Resistance Range for Verification ... + + // + // Support Zone(s) ... + XCSupportZone *mSupportZones[]; // Holds Founded Support Zones ... + + /** + * Detect Required Support Zones ... + * + * @param barIndex: Integer Start bar index ... + * 0 is Default ... + * + * @return ( int ) + */ + int DetectRequiredSupportZones(int barIndex = 0) + { + // + int result = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int required = MaxNumberOfRequiredPOIs(); + if (required <= 0) + { + return result; + } + + // + int count = ArraySize(mSupportZones); + if (count >= required) + { + // + result = count; + return result; + } + + // + int range = SupportAndResistanceRange(); + if (range < 0 || barIndex < range) + { + return result; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + XOHCL bar; + bool isInited = bar.Init( + symbol, + period, + barIndex // + ); + if (!isInited) + { + return result; + } + + // + DetectSupportZone(bar); + + // + result = ArraySize(mSupportZones); + + // + return result; + } + + // + // Resistance Zone(s) ... + XCResistanceZone *mResistanceZones[]; // Holds Founded Resistance Zones ... + + /** + * Detect Required Resistance Zones ... + * + * @param barIndex: Integer Start bar index ... + * 0 is Default ... + * + * @return ( int ) + */ + int DetectRequiredResistanceZones(int barIndex = 0) + { + // + int result = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int required = MaxNumberOfRequiredPOIs(); + if (required <= 0) + { + return result; + } + + // + int count = ArraySize(mResistanceZones); + if (count >= required) + { + // + result = count; + return result; + } + + // + int range = SupportAndResistanceRange(); + if (range < 0 || barIndex < range) + { + return result; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + XOHCL bar; + bool isInited = bar.Init( + symbol, + period, + barIndex // + ); + if (!isInited) + { + return result; + } + + // + DetectResistanceZone(bar); + + // + result = ArraySize(mResistanceZones); + + // + return result; + } + + // + // Supply and Demand Zones ... + int mSupplyAndDemandRange; // Supply and Demand Range Verifications ... + + // + // Supply Zone(s) ... + XCSupplyZone *mSupplyZones[]; // Holds Founded Supply Zones ... + + /** + * Detect Required Supply Zones ... + * + * @param barIndex: Integer Start bar index ... + * 0 is Default ... + * + * @return ( int ) + */ + int DetectRequiredSupplyZones(int barIndex) + { + // + int result = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int required = MaxNumberOfRequiredPOIs(); + if (required <= 0) + { + return result; + } + + // + int count = ArraySize(mSupplyZones); + if (count >= required) + { + // + result = count; + return result; + } + + // + int range = SupplyAndDemandRange(); + if (range < 0) + { + return result; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + XOHCL bar; + bool isInited = bar.Init( + symbol, + period, + barIndex // + ); + if (!isInited) + { + return result; + } + + // + DetectSupplyZone(bar); + + // + result = ArraySize(mSupplyZones); + + // + return result; + } + + // + // Demand Zone(s) ... + XCDemandZone *mDemandZones[]; // Holds Founded Demand Zones ... + + /** + * Detect Required Demand Zones ... + * + * @param barIndex: Integer Start bar index ... + * 0 is Default ... + * + * @return ( int ) + */ + int DetectRequiredDemandZones(int barIndex) + { + // + int result = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int required = MaxNumberOfRequiredPOIs(); + if (required <= 0) + { + return result; + } + + // + int count = ArraySize(mDemandZones); + if (count >= required) + { + // + result = count; + return result; + } + + // + int range = SupplyAndDemandRange(); + if (range < 0) + { + return result; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + XOHCL bar; + bool isInited = bar.Init( + symbol, + period, + barIndex // + ); + if (!isInited) + { + return result; + } + + // + DetectDemandZone(bar); + + // + result = ArraySize(mDemandZones); + + // + return result; + } + + // + // Order Blocks ... + int mOrderBlocksSameBars; // Order Blocks Detection Bars ... + + // + // Bullish OB ... + XCOrderBlock *mBullishOrderBlocks[]; // Holds Founded Bullish Order Blocks ... + + /** + * Detect Required Bullish Order Blocks ... + * + * @param barIndex: Integer Start bar index ... + * 0 is Default ... + * + * @return ( int ) + */ + int DetectRequiredBullishOrderBlocks(int barIndex) + { + // + int result = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int required = MaxNumberOfRequiredPOIs(); + if (required <= 0) + { + return result; + } + + // + int count = ArraySize(mBullishOrderBlocks); + if (count >= required) + { + // + result = count; + return result; + } + + // + int sameBars = OrderBlocksSameBars(); + if (sameBars < 0) + { + return result; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + XOHCL bar; + bool isInited = bar.Init( + symbol, + period, + barIndex // + ); + if (!isInited) + { + return result; + } + + // + DetectBullishOrderBlock(bar); + + // + result = ArraySize(mBullishOrderBlocks); + + // + return result; + } + + // + // Bearish OB ... + XCOrderBlock *mBearishOrderBlocks[]; // Holds Founded Bearish Order Blocks ... + + /** + * Detect Required Bearish Order Blocks ... + * + * @param barIndex: Integer Start bar index ... + * 0 is Default ... + * + * @return ( int ) + */ + int DetectRequiredBearishOrderBlocks(int barIndex) + { + // + int result = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int required = MaxNumberOfRequiredPOIs(); + if (required <= 0) + { + return result; + } + + // + int count = ArraySize(mBearishOrderBlocks); + if (count >= required) + { + // + result = count; + return result; + } + + // + int sameBars = OrderBlocksSameBars(); + if (sameBars < 0) + { + return result; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + XOHCL bar; + bool isInited = bar.Init( + symbol, + period, + barIndex // + ); + if (!isInited) + { + return result; + } + + // + DetectBearishOrderBlock(bar); + + // + result = ArraySize(mBearishOrderBlocks); + + // + return result; + } + + // + // Fair Value Gaps ... + int mFairValueGapsSameBars; // Fair Value Gaps Detection Same Bars ... + + // + // Bullish FVG ... + XCFVG *mBullishFairValueGaps[]; // Holds Founded Bullish Fair Value Gaps ... + + /** + * Detect Required Bullish Fair Value Gaps ... + * + * @param barIndex: Integer Start bar index ... + * 0 is Default ... + * + * @return ( int ) + */ + int DetectRequiredBullishFairValueGaps(int barIndex) + { + // + int result = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int required = MaxNumberOfRequiredPOIs(); + if (required <= 0) + { + return result; + } + + // + int count = ArraySize(mBullishFairValueGaps); + if (count >= required) + { + // + result = count; + return result; + } + + // + int sameBars = FairValueGapsSameBars(); + if (sameBars < 0) + { + return result; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + XOHCL bar; + bool isInited = bar.Init( + symbol, + period, + barIndex // + ); + if (!isInited) + { + return result; + } + + // + DetectBullishFairValueGap(bar); + + // + result = ArraySize(mBullishFairValueGaps); + + // + return result; + } + + // + // Bearish FVG ... + XCFVG *mBearishFairValueGaps[]; // Holds Founded Bearish Fair Value Gaps ... + + /** + * Detect Required Bearish Fair Value Gaps ... + * + * @param barIndex: Integer Start bar index ... + * 0 is Default ... + * + * @return ( int ) + */ + int DetectRequiredBearishFairValueGaps(int barIndex) + { + // + int result = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int required = MaxNumberOfRequiredPOIs(); + if (required <= 0) + { + return result; + } + + // + int count = ArraySize(mBearishFairValueGaps); + if (count >= required) + { + // + result = count; + return result; + } + + // + int sameBars = FairValueGapsSameBars(); + if (sameBars < 0) + { + return result; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + XOHCL bar; + bool isInited = bar.Init( + symbol, + period, + barIndex // + ); + if (!isInited) + { + return result; + } + + // + DetectBearishFairValueGap(bar); + + // + result = ArraySize(mBearishFairValueGaps); + + // + return result; + } + + // + // Ticks Range Zones ... + int mTicksRangeZoneLevel; // Ticks Range Levels ... + int mTicksRangeZoneRange; // Ticks Range Zone Loopback Period ... + + // + XCTicksZone *mTicksZone; // Ticks Zone ... + // XCTicksZoneObject *mTicksZoneObject; // Ticks Zone Object ... + + /** + * Detect Ticks Zone Range ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool DetectTicksZoneRange(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int ticksLevels = TicksRangeZoneLevel(); + int ticksRange = TicksRangeZoneRange(); + result = ticksLevels > 0 && + ticksRange > 0; + if (!result) + { + return result; + } + + // + int startBarIndex = bar.Index() + ticksRange; + XOHCL startBar; + result = startBar.Init( + bar.symbol, + bar.period, + startBarIndex // + ); + if (!result) + { + return result; + } + + // + mTicksZone = new XCTicksZone(); + result = mTicksZone.Init( + startBar, + bar // + ); + if (!result) + { + // + mTicksZone = NULL; + return result; + } + + // // + // if (mTicksZoneObject != NULL) + // { + // mTicksZoneObject.Destroy(); + // } + // mDrawer.CreateTicksZone( + // mTicksZone, + // mTicksZoneObject // + // ); + + // + return result; + } + + // + // Liquidity Zones ... + + // + // Sell Side ... + + // + // Buy Side ... + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14031003/Classes/x-saherelm.x-poi.drawer.class.mq5 b/BKPS/14031003/Classes/x-saherelm.x-poi.drawer.class.mq5 new file mode 100644 index 0000000..abff976 --- /dev/null +++ b/BKPS/14031003/Classes/x-saherelm.x-poi.drawer.class.mq5 @@ -0,0 +1,2629 @@ +/////////////////////////////////////////////////////// +// +// 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" + +// +// Definitions ... +class XCPOIDrawer : public XCBase +{ + // + public: + // + + // + // Constructor ... + void XCPOIDrawer() + { + // + Default(); + } + + // + // Deconstructor ... + void ~XCPOIDrawer() + { + } + + // + // 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; + } + + // + // 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); + + // + 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; + } + + // + // 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; + } + + // + // 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; + + // + result = zone.IsValid(); + 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 XCTicksZoneObject(); + result = object.Create( + chartID, + window, + zone, + mTicksZoneSpecs, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + return result; + } + + // + protected: + // + + // + private: + // + + // + // Props ... + + // + string mPrefix; // Prefix of Created Objects ... + long mChartIdentification; // Chart Id ... + int mSubWindowIdentification; // Sub Window ... + + // + // 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/14031003/Classes/x-saherelm.x-trade.class.mq5 b/BKPS/14031003/Classes/x-saherelm.x-trade.class.mq5 new file mode 100644 index 0000000..badfc21 --- /dev/null +++ b/BKPS/14031003/Classes/x-saherelm.x-trade.class.mq5 @@ -0,0 +1,3924 @@ +/////////////////////////////////////////////////////// +// +// 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; + + // + 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 = mSignal.GetSpread(); + result = spread <= mMaxAllowedSpread; + } + + // + return result; + } + + // + // Check Account Policy ... + bool CheckAccountPolicy( + XSignal &mSignal, // For Executing Signal + ENUM_X_SIGNAL_EXECUTION_RESULT &state // State Holder + ) + { + // + bool result = false; + + // + // Check Positions For Trade ... + result = CheckPositionsForTrade(); + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_MAX_REACHED; + return result; + } + + // + // Check Equity For Trade ... + result = CheckEquityForTrade(); + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_NO_EQUITY; + return result; + } + + // + // Check Spread for Trade ... + result = CheckSpreadForSignalExecution(mSignal); + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_SPREAD; + return result; + } + + // + return result; + } + + // + // 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 + ) + { + // + return result + .ByIndex(index); + } + + // + // Retrieve Specific Position by Ticket ... + bool GetPosition( + ulong ticket, // Specified Ticket + XPosition &result // Hold's Result + ) + { + // + return result + .ByTicket(ticket); + } + + // + 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/14031003/Experts/x-saherelm.x-121.smc.ea.ex5 b/BKPS/14031003/Experts/x-saherelm.x-121.smc.ea.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..77c5a6409c74bc716e5e5721c9f06ebda6fe82f9 GIT binary patch literal 1083774 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 z%0A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

44YET_xID((><4&t*K&Xo4 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 CUkmn=is&?}80`&waycc7m!Rn0D8g@#uz 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

XxPbcl2BfG?3A3K0w;diO^L` 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

  • 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

    *J{*& z3!p7Jmq1zqk!)wR?Cwinrs!S4@nM86`Zg2g)=|`0b;vq+Uwyk7^1NdB5|DMTorg6BZ10|f3;P^YR znVGp!h4UZcn{ScUPTToli|$sr_OL7?(Lk6{z(a$v0BkSiNcd4Ds^n&u$Ixz;j)0#> z3x@L?%oCpAiU5PxNHd88j-U(sgwC1$67XmmdoN#v8I_BA&ic=b?I~z{#R$#X!5Be@ z19Ag`oE?%5xRR~Dd)r~PYLQRaJ++dmtF7y9O&OnCD%Xt6fl6HJ)RWp8YXBB4!S8x5n`wWjtHVaNvKUnb+Cq50_1IuoLJs^v8 z6ss&tqL6 z!i?og3;2tji;Kolt~}h((uFyqIKJbN^!0M=Da-^d@U$xxT}b^fUyxUtM#eubaN%$k*ppt*44&AT8Vh#xS_vOP)9&ti@1Z0~v|%AdU><_zZ)g*QHJkb_b$ zhRYu`wkZt@aV}<5Qj~Kn10^{0ygCH#m4X)Q99vdT29Wtn_mJuRj168 ziSZdB(FY68vvmkjLuYoFf55jc(>qtzvSroPSp9iOoLv%Z*PR6u<`9kuXp$u|Qc0;z z($I`c_p|=wXbWiaJ9pqyVpAErc{hX`S?NjV93RCLmSnbv)q&~ z!>Ce}9Xv@RBPEe`GcfFyKBciMY|QR0wrp%%y7`f1?{97@z#*4|XmMjpWm;{Wc#w|G zzVIEcZ?)40%S5Q1cyc4oBd0y_yiEth+O%_0_D$cHs=lXyPBK$RK*;PF zbm0JKpk_`2g`Vu~5Mpg*Z#@rkKKJeCl4(aSa^1eS^s?Hxc-YA0y;S~^LVovc^1oj@ zOg0^g9I)6;)heSez3_QuXdK*Y>alSP)ymn zBW8@Ca}p?b$U>ks%^>nANFUdH$GPS_07sI_r(MLRP#b+=TvQud<* zcMMVTT_?`kwf#N3=01SOY}yK$8fHSXCh9M>!f|cy`cAln=ys^Vb%n5Twu0*c8jztf z_WYVCm2jLpoW`@m%$>BofCnkd?}x|uTZHF zQH!JS8!BcRNTy>w?cf9PJ5Ic%(#7 zg~41F-SI0{ltua@_a>l_*X%0AB&d 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 NM>D};Z{ 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(); +} + +// diff --git a/BKPS/14031003/Helpers/x-saherelm.x121.helper.mq5 b/BKPS/14031003/Helpers/x-saherelm.x121.helper.mq5 new file mode 100644 index 0000000..9f4c5ca --- /dev/null +++ b/BKPS/14031003/Helpers/x-saherelm.x121.helper.mq5 @@ -0,0 +1,4289 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XCX121Helper +// 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 ... +enum ENUM_X121_BUFFERS +{ + // + // Main Buffers ... + X121_PEAKS_LINE = 0, + X121_VALES_LINE = 1, + X121_SAR_LINE = 2, + X121_VWAP_FAST_LINE = 3, + X121_VWAP_MID_LINE = 5, + X121_VWAP_SLOW_LINE = 7, + X121_DON_OPEN_UPPER_LINE = 9, + X121_DON_OPEN_LOWER_LINE = 10, + X121_DON_HIGH_UPPER_LINE = 11, + X121_DON_HIGH_LOWER_LINE = 12, + X121_DON_LOW_UPPER_LINE = 13, + X121_DON_LOW_LOWER_LINE = 14, + X121_DON_CLOSE_UPPER_LINE = 15, + X121_DON_CLOSE_LOWER_LINE = 16, + X121_FIB_LEVEL_1_LINE = 17, + X121_FIB_LEVEL_2_LINE = 18, + X121_FIB_LEVEL_3_LINE = 19, + X121_FIB_LEVEL_4_LINE = 20, + X121_FIB_LEVEL_5_LINE = 21, + // + // Data Buffers ... + // + // XPV Data ... + X121_CURRENT_HH_LINE = 22, + X121_CURRENT_LL_LINE = 23, + X121_SHORT_HH_LINE = 24, + X121_SHORT_LL_LINE = 25, + X121_MEDIUM_HH_LINE = 26, + X121_MEDIUM_LL_LINE = 27, + X121_LONG_HH_LINE = 28, + X121_LONG_LL_LINE = 29, + X121_HIND_HH_LINE = 30, + X121_HIND_LL_LINE = 31, + // + // VWAP Data ... + X121_VWAP_VOLUME_LINE = 32, + X121_VWAP_PRICE_LINE = 33, + X121_VWAP_FAST_STATE_LINE = 34, + X121_VWAP_MID_STATE_LINE = 35, + X121_VWAP_SLOW_STATE_LINE = 36, + // + // VALID PEAKS and VALES ... + X121_VALID_PEAKS_LINE = 37, + X121_VALID_VALES_LINE = 38, +}; + +// +enum ENUM_XVWAP_STATES +{ + // + XVWAP_STATE_BULLISH = 1, + XVWAP_STATE_BEARISH = 2, + XVWAP_STATE_NEUTURAL = 3, +}; + +// +// Inputs ... +struct X121Inputs +{ + // + // Props ... + + // + // Cycles ... + + // + // Short ... + ENUM_X_PERIOD_METHOD scMethod; // How to Find Period + ENUM_TIMEFRAMES scPeriod; // Time Period + + // + // Medium ... + ENUM_X_PERIOD_METHOD mcMethod; // How to Find Period + ENUM_TIMEFRAMES mcPeriod; // Time Period + + // + // Long ... + ENUM_X_PERIOD_METHOD lcMethod; // How to Find Period + ENUM_TIMEFRAMES lcPeriod; // Time Period + + // + // Hind ... + ENUM_X_PERIOD_METHOD hcMethod; // How to Find Period + ENUM_TIMEFRAMES hcPeriod; // Time Period + + // + // Boundary Detection ... + ENUM_SERIESMODE hhMode; // Highest High Calculation Method + ENUM_SERIESMODE llMode; // Lowest Low Calculation Method + + // + // Paraboli Sar Detection ... + double sarStep; // Step + double sarMax; // Maximum + + // + // VWap Detection ... + int vwapFastLength; // Fast Length + int vwapMidLength; // Mid Length + int vwapSlowLength; // Slow Length + ENUM_APPLIED_PRICE vwapAppliedTo; // Applied To + + // + // Donchain Detection ... + int donchainLength; // Donchain Length + + // + // Fibonacci ... + double fiboLevel1; // Fibio 1st Level + double fiboLevel2; // Fibio 2st Level + double fiboLevel3; // Fibio 3rd Level + double fiboLevel4; // Fibio 4th Level + double fiboLevel5; // Fibio 5th Level + + // + // Presentation ... + + // + int startCalculationForLastBars; // Calculate Last n Bars + + // + int sarArrowCode; // Parabolic Sar Arrow Code + int peaksArrowCode; // Peaks Arrow Code + int valesArrowCode; // Vales Arrow Code + + // + // Global ... + bool showSar; // Show Parabolic Sar + bool showPeaks; // Show Peaks + bool showVales; // Show Vales + bool showVWap; // Show VWap + bool showDonchain; // Show Donchain + + // + // Fibonachi Presentation ... + bool showFibo1Levels; // Show Fibo 1st Level + bool showFibo2Levels; // Show Fibo 2nd Level + bool showFibo3Levels; // Show Fibo 3rd Level + bool showFibo4Levels; // Show Fibo 4th Level + bool showFibo5Levels; // Show Fibo 5th Level + + // + // VWap Presentation ... + bool showVWapFast; // Show VWap Fast + bool showVWapMedium; // Show VWap Medium + bool showVWapSlow; // Show VWap Slow + + // + // Donchain Presentation ... + + // + bool showUpper; // Show Upper Band + bool showLower; // Show Lower Band + + // + bool showOpen; // Show Open + bool showHigh; // Show High + bool showClose; // Show Close + bool showLow; // Show Low + + // + // Constructor ... + X121Inputs() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + // Cycles ... + + // + // Short ... + scMethod = X_PERIOD_NOTHING; + scPeriod = NULL; + + // + // Medium ... + mcMethod = X_PERIOD_NOTHING; + mcPeriod = NULL; + + // + // Long ... + lcMethod = X_PERIOD_NOTHING; + lcPeriod = NULL; + + // + // Hind ... + hcMethod = X_PERIOD_NOTHING; + hcPeriod = NULL; + + // + // Boundary Detection ... + hhMode = MODE_HIGH; + llMode = MODE_LOW; + + // + // Paraboli Sar Detection ... + sarStep = 0; + sarMax = 0; + + // + // VWap Detection ... + vwapFastLength = 0; + vwapMidLength = 0; + vwapSlowLength = 0; + vwapAppliedTo = PRICE_CLOSE; + + // + // Donchain Detection ... + donchainLength = 0; + + // + // Fibonacci ... + fiboLevel1 = 0; + fiboLevel2 = 0; + fiboLevel3 = 0; + fiboLevel4 = 0; + fiboLevel5 = 0; + + // + // Presentation ... + + // + startCalculationForLastBars = 0; + + // + sarArrowCode = 0; + peaksArrowCode = 0; + valesArrowCode = 0; + + // + // Globals ... + showSar = false; + showPeaks = false; + showVales = false; + showVWap = false; + showDonchain = false; + + // + // Fibonachi Presentation ... + showFibo1Levels = false; + showFibo2Levels = false; + showFibo3Levels = false; + showFibo4Levels = false; + showFibo5Levels = false; + + // + // VWap Presentation ... + showVWapFast = false; + showVWapMedium = false; + showVWapSlow = false; + + // + // Donchain Presentation ... + + // + showUpper = false; + showLower = false; + + // + showOpen = false; + showHigh = false; + showClose = false; + showLow = false; + } + + /** + * Set Default Values ... + */ + void Default() + { + // + // Cycles ... + + // + // Short ... + scMethod = X_PERIOD_AUTO; + scPeriod = NULL; + + // + // Medium ... + mcMethod = X_PERIOD_AUTO; + mcPeriod = NULL; + + // + // Long ... + lcMethod = X_PERIOD_AUTO; + lcPeriod = NULL; + + // + // Hind ... + hcMethod = X_PERIOD_AUTO; + hcPeriod = NULL; + + // + // Boundary Detection ... + hhMode = MODE_HIGH; + llMode = MODE_LOW; + + // + // Paraboli Sar Detection ... + sarStep = 0.02; + sarMax = 0.2; + + // + // VWap Detection ... + vwapFastLength = 20; + vwapMidLength = 40; + vwapSlowLength = 60; + vwapAppliedTo = PRICE_CLOSE; + + // + // Donchain Detection ... + donchainLength = 40; + + // + // Fibonacci ... + fiboLevel1 = 0.236; + fiboLevel2 = 0.382; + fiboLevel3 = 0.5; + fiboLevel4 = 0.618; + fiboLevel5 = 0.764; + + // + // Presentation ... + + // + startCalculationForLastBars = 1500; + + // + sarArrowCode = 159; + peaksArrowCode = 159; + valesArrowCode = 159; + + // + // Globals ... + showSar = true; + showPeaks = true; + showVales = true; + showVWap = true; + showDonchain = true; + + // + // Fibonachi Presentation ... + showFibo1Levels = false; + showFibo2Levels = false; + showFibo3Levels = true; + showFibo4Levels = false; + showFibo5Levels = false; + + // + // VWap Presentation ... + showVWapFast = true; + showVWapMedium = true; + showVWapSlow = true; + + // + // Donchain Presentation ... + + // + showUpper = true; + showLower = true; + + // + showOpen = true; + showHigh = false; + showClose = true; + showLow = false; + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + // + // PSAR ... + sarMax > 0 && + sarStep > 0 && + sarMax > sarStep && + // + // XDON ... + donchainLength > 0 && + // + // VWAP ... + vwapFastLength > 2 && + vwapMidLength > vwapFastLength && + vwapSlowLength > vwapMidLength && + // + // XPV ... + (IsValid(scMethod, scPeriod) && + IsValid(mcMethod, mcPeriod) && + IsValid(lcMethod, lcPeriod) && + IsValid(hcMethod, hcPeriod)) + // + ; + + // + return result; + } + + /** + * Extract Max Input Length ... + * + * @return ( int ) + */ + int Max() + { + // + int result = 0; + + // + // XVWAP ... + result = MathMax(result, vwapFastLength); + result = MathMax(result, vwapMidLength); + result = MathMax(result, vwapSlowLength); + + // + return result; + } +}; + +// +// Conditions ... +struct X121Conditions +{ + // + // Common ... + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + // Buffers ... + double peaksBuffer[]; + double valesBuffer[]; + double sarBuffer[]; + double vwapFastBuffer[]; + double vwapMidBuffer[]; + double vwapSlowBuffer[]; + double donOpenUpperBuffer[]; + double donOpenLowerBuffer[]; + double donCloseUpperBuffer[]; + double donCloseLowerBuffer[]; + double donHighUpperBuffer[]; + double donHighLowerBuffer[]; + double donLowUpperBuffer[]; + double donLowLowerBuffer[]; + double fl1Buffer[]; + double fl2Buffer[]; + double fl3Buffer[]; + double fl4Buffer[]; + double fl5Buffer[]; + double cHHBuffer[]; + double cLLBuffer[]; + double sHHBuffer[]; + double sLLBuffer[]; + double mHHBuffer[]; + double mLLBuffer[]; + double lHHBuffer[]; + double lLLBuffer[]; + double hHHBuffer[]; + double hLLBuffer[]; + double vwapVolumeBuffer[]; + double vwapPriceBuffer[]; + double vwapFastStateBuffer[]; + double vwapMidStateBuffer[]; + double vwapSlowStateBuffer[]; + double validPeaksBuffer[]; + double validValesBuffer[]; + + // + // Conditions ... + + // + // XSAR ... + + // + bool isSarBullish; + bool isSarBearish; + + // + bool isSarSwitchedToBullish; + bool isSarSwitchedToBearish; + + // + // XPV ... + + // + bool isNewPeak; + bool isNewPeakOverLast; + bool isNewPeakUnderLast; + + // + bool isNewVale; + bool isNewValeOverLast; + bool isNewValeUnderLast; + + // + // XVWAP ... + + // + bool isVWapFastBullish; + bool isVWapFastBearish; + bool isVWapFastNeutural; + + // + bool isVWapMidBullish; + bool isVWapMidBearish; + bool isVWapMidNeutural; + + // + bool isVWapSlowBullish; + bool isVWapSlowBearish; + bool isVWapSlowNeutural; + + // + bool isVWapFastOverMid; + bool isVWapMidOverSlow; + + // + bool isVWapFastUnderMid; + bool isVWapMidUnderSlow; + + // + bool isVWapBullishState; + bool isVWapBearishState; + bool isVWapNeuturalState; + + // + bool isVWapBullishOrdered; + bool isVWapBearishOrdered; + + // + bool isVWapSwitchedToBullishOrdered; + bool isVWapSwitchedToBearishOrdered; + + // + bool isVWapSwitchedToBullishState; + bool isVWapSwitchedToBearishState; + bool isVWapSwitchedToNeuturalState; + + // + // XDON ... + + // + // bool isCloseLower + + // + // XFIBONACCI ... + + // + bool isOerFib1; + bool isOerFib2; + bool isOerFib3; + bool isOerFib4; + bool isOerFib5; + + // + bool isUnderFib1; + bool isUnderFib2; + bool isUnderFib3; + bool isUnderFib4; + bool isUnderFib5; + + // + bool isCloseOerFib1; + bool isCloseOerFib2; + bool isCloseOerFib3; + bool isCloseOerFib4; + bool isCloseOerFib5; + + // + bool isCloseUnderFib1; + bool isCloseUnderFib2; + bool isCloseUnderFib3; + bool isCloseUnderFib4; + bool isCloseUnderFib5; + + // + // Constructor ... + X121Conditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + // Commons ... + symbol = NULL; + period = NULL; + time = NULL; + + // + // Buffers ... + + // + Clean(peaksBuffer); + Clean(valesBuffer); + Clean(sarBuffer); + Clean(vwapFastBuffer); + Clean(vwapMidBuffer); + Clean(vwapSlowBuffer); + Clean(donOpenUpperBuffer); + Clean(donOpenLowerBuffer); + Clean(donCloseUpperBuffer); + Clean(donCloseLowerBuffer); + Clean(donHighUpperBuffer); + Clean(donHighLowerBuffer); + Clean(donLowUpperBuffer); + Clean(donLowLowerBuffer); + Clean(fl1Buffer); + Clean(fl2Buffer); + Clean(fl3Buffer); + Clean(fl4Buffer); + Clean(fl5Buffer); + Clean(cHHBuffer); + Clean(cLLBuffer); + Clean(sHHBuffer); + Clean(sLLBuffer); + Clean(mHHBuffer); + Clean(mLLBuffer); + Clean(lHHBuffer); + Clean(lLLBuffer); + Clean(hHHBuffer); + Clean(hLLBuffer); + Clean(vwapVolumeBuffer); + Clean(vwapPriceBuffer); + Clean(vwapFastStateBuffer); + Clean(vwapMidStateBuffer); + Clean(vwapSlowStateBuffer); + Clean(validPeaksBuffer); + Clean(validValesBuffer); + + // + ArraySetAsSeries(peaksBuffer, true); + ArraySetAsSeries(valesBuffer, true); + ArraySetAsSeries(sarBuffer, true); + ArraySetAsSeries(vwapFastBuffer, true); + ArraySetAsSeries(vwapMidBuffer, true); + ArraySetAsSeries(vwapSlowBuffer, true); + ArraySetAsSeries(donOpenUpperBuffer, true); + ArraySetAsSeries(donOpenLowerBuffer, true); + ArraySetAsSeries(donCloseUpperBuffer, true); + ArraySetAsSeries(donCloseLowerBuffer, true); + ArraySetAsSeries(donHighUpperBuffer, true); + ArraySetAsSeries(donHighLowerBuffer, true); + ArraySetAsSeries(donLowUpperBuffer, true); + ArraySetAsSeries(donLowLowerBuffer, true); + ArraySetAsSeries(fl1Buffer, true); + ArraySetAsSeries(fl2Buffer, true); + ArraySetAsSeries(fl3Buffer, true); + ArraySetAsSeries(fl4Buffer, true); + ArraySetAsSeries(fl5Buffer, true); + ArraySetAsSeries(cHHBuffer, true); + ArraySetAsSeries(cLLBuffer, 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(vwapVolumeBuffer, true); + ArraySetAsSeries(vwapPriceBuffer, true); + ArraySetAsSeries(vwapFastStateBuffer, true); + ArraySetAsSeries(vwapMidStateBuffer, true); + ArraySetAsSeries(vwapSlowStateBuffer, true); + ArraySetAsSeries(validPeaksBuffer, true); + ArraySetAsSeries(validValesBuffer, true); + + // + // Conditions ... + + // + // XSAR ... + + // + isSarBullish = false; + isSarBearish = false; + + // + isSarSwitchedToBullish = false; + isSarSwitchedToBearish = false; + + // + // XPV ... + + // + isNewPeak = false; + isNewPeakOverLast = false; + isNewPeakUnderLast = false; + + // + isNewVale = false; + isNewValeOverLast = false; + isNewValeUnderLast = false; + + // + // XVWAP ... + + // + isVWapFastBullish = false; + isVWapFastBearish = false; + isVWapFastNeutural = false; + + // + isVWapMidBullish = false; + isVWapMidBearish = false; + isVWapMidNeutural = false; + + // + isVWapSlowBullish = false; + isVWapSlowBearish = false; + isVWapSlowNeutural = false; + + // + isVWapFastOverMid = false; + isVWapMidOverSlow = false; + + // + isVWapFastUnderMid = false; + isVWapMidUnderSlow = false; + + // + isVWapBullishState = false; + isVWapBearishState = false; + isVWapNeuturalState = false; + + // + isVWapBullishOrdered = false; + isVWapBearishOrdered = false; + + // + isVWapSwitchedToBullishOrdered = false; + isVWapSwitchedToBearishOrdered = false; + + // + isVWapSwitchedToBullishState = false; + isVWapSwitchedToBearishState = false; + isVWapSwitchedToNeuturalState = false; + + // + // XDON ... + + // + // XFIBONACCI ... + + // + isOerFib1 = false; + isOerFib2 = false; + isOerFib3 = false; + isOerFib4 = false; + isOerFib5 = false; + + // + isUnderFib1 = false; + isUnderFib2 = false; + isUnderFib3 = false; + isUnderFib4 = false; + isUnderFib5 = false; + + // + isCloseOerFib1 = false; + isCloseOerFib2 = false; + isCloseOerFib3 = false; + isCloseOerFib4 = false; + isCloseOerFib5 = false; + + // + isCloseUnderFib1 = false; + isCloseUnderFib2 = false; + isCloseUnderFib3 = false; + isCloseUnderFib4 = false; + isCloseUnderFib5 = false; + } + + /** + * 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; + + // + // TODO: Implement if Required ... + } + + /** + * 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 // + ); + + // + // TODO: Implement this if required ... + string conditionsStr = + // + // XSAR ... + ToString("isSarBullish", isSarBullish, ignoreFalseConditions, separator) + + ToString("isSarBearish", isSarBearish, ignoreFalseConditions, separator) + + ToString("isSarSwitchedToBullish", isSarSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isSarSwitchedToBearish", isSarSwitchedToBearish, ignoreFalseConditions, separator) + + // + // XPV ... + ToString("isNewPeak", isNewPeak, ignoreFalseConditions, separator) + + ToString("isNewPeakOverLast", isNewPeakOverLast, ignoreFalseConditions, separator) + + ToString("isNewPeakUnderLast", isNewPeakUnderLast, ignoreFalseConditions, separator) + + ToString("isNewVale", isNewVale, ignoreFalseConditions, separator) + + ToString("isNewValeOverLast", isNewValeOverLast, ignoreFalseConditions, separator) + + ToString("isNewValeUnderLast", isNewValeUnderLast, ignoreFalseConditions, separator) + + // + // XVWAP ... + ToString("isVWapFastBullish", isVWapFastBullish, ignoreFalseConditions, separator) + + ToString("isVWapFastBearish", isVWapFastBearish, ignoreFalseConditions, separator) + + ToString("isVWapFastNeutural", isVWapFastNeutural, ignoreFalseConditions, separator) + + ToString("isVWapMidBullish", isVWapMidBullish, ignoreFalseConditions, separator) + + ToString("isVWapMidBearish", isVWapMidBearish, ignoreFalseConditions, separator) + + ToString("isVWapMidNeutural", isVWapMidNeutural, ignoreFalseConditions, separator) + + ToString("isVWapSlowBullish", isVWapSlowBullish, ignoreFalseConditions, separator) + + ToString("isVWapSlowBearish", isVWapSlowBearish, ignoreFalseConditions, separator) + + ToString("isVWapSlowNeutural", isVWapSlowNeutural, ignoreFalseConditions, separator) + + ToString("isVWapFastOverMid", isVWapFastOverMid, ignoreFalseConditions, separator) + + ToString("isVWapMidOverSlow", isVWapMidOverSlow, ignoreFalseConditions, separator) + + ToString("isVWapFastUnderMid", isVWapFastUnderMid, ignoreFalseConditions, separator) + + ToString("isVWapMidUnderSlow", isVWapMidUnderSlow, ignoreFalseConditions, separator) + + ToString("isVWapBullishState", isVWapBullishState, ignoreFalseConditions, separator) + + ToString("isVWapBearishState", isVWapBearishState, ignoreFalseConditions, separator) + + ToString("isVWapNeuturalState", isVWapNeuturalState, ignoreFalseConditions, separator) + + ToString("isVWapBullishOrdered", isVWapBullishOrdered, ignoreFalseConditions, separator) + + ToString("isVWapBearishOrdered", isVWapBearishOrdered, ignoreFalseConditions, separator) + + ToString("isVWapSwitchedToBullishOrdered", isVWapSwitchedToBullishOrdered, ignoreFalseConditions, separator) + + ToString("isVWapSwitchedToBearishOrdered", isVWapSwitchedToBearishOrdered, ignoreFalseConditions, separator) + + ToString("isVWapSwitchedToBullishState", isVWapSwitchedToBullishState, ignoreFalseConditions, separator) + + ToString("isVWapSwitchedToBearishState", isVWapSwitchedToBearishState, ignoreFalseConditions, separator) + + ToString("isVWapSwitchedToNeuturalState", isVWapSwitchedToNeuturalState, ignoreFalseConditions, separator) + + // + // XFIBONACCI ... + ToString("isOerFib1", isOerFib1, ignoreFalseConditions, separator) + + ToString("isOerFib2", isOerFib2, ignoreFalseConditions, separator) + + ToString("isOerFib3", isOerFib3, ignoreFalseConditions, separator) + + ToString("isOerFib4", isOerFib4, ignoreFalseConditions, separator) + + ToString("isOerFib5", isOerFib5, ignoreFalseConditions, separator) + + ToString("isUnderFib1", isUnderFib1, ignoreFalseConditions, separator) + + ToString("isUnderFib2", isUnderFib2, ignoreFalseConditions, separator) + + ToString("isUnderFib3", isUnderFib3, ignoreFalseConditions, separator) + + ToString("isUnderFib4", isUnderFib4, ignoreFalseConditions, separator) + + ToString("isUnderFib5", isUnderFib5, ignoreFalseConditions, separator) + + ToString("isCloseOerFib1", isCloseOerFib1, ignoreFalseConditions, separator) + + ToString("isCloseOerFib2", isCloseOerFib2, ignoreFalseConditions, separator) + + ToString("isCloseOerFib3", isCloseOerFib3, ignoreFalseConditions, separator) + + ToString("isCloseOerFib4", isCloseOerFib4, ignoreFalseConditions, separator) + + ToString("isCloseOerFib5", isCloseOerFib5, ignoreFalseConditions, separator) + + ToString("isCloseUnderFib1", isCloseUnderFib1, ignoreFalseConditions, separator) + + ToString("isCloseUnderFib2", isCloseUnderFib2, ignoreFalseConditions, separator) + + ToString("isCloseUnderFib3", isCloseUnderFib3, ignoreFalseConditions, separator) + + ToString("isCloseUnderFib4", isCloseUnderFib4, ignoreFalseConditions, separator) + + ToString("isCloseUnderFib5", isCloseUnderFib5, 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); + } + + // +}; + +// +// Implementation ... + +class XCX121Helper : public XCBaseHelper +{ + // + public: + // + + // + // Constructors ... + XCX121Helper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCX121Helper() + { + } + + // + // Tools ... + + /** + * Initialize Indicator Helper ... + * + * @param symbol: String, Symbol ... + * @param period: ENUM_TIMEFRAMES member, Period ... + * @param inputs: X121Inputs instance, Indicator Inputs ... + * + * @return ( bool ) + */ + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + X121Inputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + // Validate Inputs ... + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + // Setting Arrays As Series ... + ArraySetAsSeries(peaksBuffer, true); + ArraySetAsSeries(valesBuffer, true); + ArraySetAsSeries(sarBuffer, true); + ArraySetAsSeries(vwapFastBuffer, true); + ArraySetAsSeries(vwapMidBuffer, true); + ArraySetAsSeries(vwapSlowBuffer, true); + ArraySetAsSeries(donOpenUpperBuffer, true); + ArraySetAsSeries(donOpenLowerBuffer, true); + ArraySetAsSeries(donCloseUpperBuffer, true); + ArraySetAsSeries(donCloseLowerBuffer, true); + ArraySetAsSeries(donHighUpperBuffer, true); + ArraySetAsSeries(donHighLowerBuffer, true); + ArraySetAsSeries(donLowUpperBuffer, true); + ArraySetAsSeries(donLowLowerBuffer, true); + ArraySetAsSeries(fl1Buffer, true); + ArraySetAsSeries(fl2Buffer, true); + ArraySetAsSeries(fl3Buffer, true); + ArraySetAsSeries(fl4Buffer, true); + ArraySetAsSeries(fl5Buffer, true); + ArraySetAsSeries(cHHBuffer, true); + ArraySetAsSeries(cLLBuffer, 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(vwapVolumeBuffer, true); + ArraySetAsSeries(vwapPriceBuffer, true); + ArraySetAsSeries(vwapFastStateBuffer, true); + ArraySetAsSeries(vwapMidStateBuffer, true); + ArraySetAsSeries(vwapSlowStateBuffer, true); + ArraySetAsSeries(validPeaksBuffer, true); + ArraySetAsSeries(validValesBuffer, true); + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121", + // + // Inputs ... + // + // Cycles ... + "", + // + // 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, + // + // Paraboli Sar Detection ... + "", + mInputs.sarStep, + mInputs.sarMax, + // + // VWap Detection ... + "", + mInputs.vwapFastLength, + mInputs.vwapMidLength, + mInputs.vwapSlowLength, + mInputs.vwapAppliedTo, + // + // Donchain Detection ... + "", + mInputs.donchainLength, + // + // Fibonacci ... + "", + mInputs.fiboLevel1, + mInputs.fiboLevel2, + mInputs.fiboLevel3, + mInputs.fiboLevel4, + mInputs.fiboLevel5, + // + // Presentation ... + "", + mInputs.startCalculationForLastBars, + mInputs.sarArrowCode, + mInputs.peaksArrowCode, + mInputs.valesArrowCode, + // + // Commons ... + mInputs.showSar, + mInputs.showPeaks, + mInputs.showVales, + mInputs.showVWap, + mInputs.showDonchain, + // + // Fibonachi Presentation ... + "", + mInputs.showFibo1Levels, + mInputs.showFibo2Levels, + mInputs.showFibo3Levels, + mInputs.showFibo4Levels, + mInputs.showFibo5Levels, + // + // VWap Presentation ... + "", + mInputs.showVWapFast, + mInputs.showVWapMedium, + mInputs.showVWapSlow, + // + // Donchain Presentation ... + "", + mInputs.showUpper, + mInputs.showLower, + mInputs.showOpen, + mInputs.showHigh, + mInputs.showClose, + mInputs.showLow + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Retrieve Current Indicator Configs ... + * + * @return ( Inputs ) + */ + X121Inputs GetInputs() + { + return mInputs; + } + + /** + * Set New Indicator Inputs ... + * + * @param inputs: X121Inputs instance, Indicator Inputs ... + * + * @return ( bool ) + */ + bool SetInputs( + X121Inputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + /** + * Retrieve DON Chain Length ... + * + * @return ( int ) + */ + int GetDonChainLength() { + return mInputs.donchainLength; + } + + // + // Implement Value Getters ... + + // + // XSAR ... + + // + double GetSar( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + 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(); + + // + // Copy Items ... + return Copy( + start, + count, + sarBuffer, + buffer, + forceClean + // + ); + } + + // + // XPV ... + + // + // PEAKS ... + + // + double GetPeak( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(peaksBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return peaksBuffer[barIndex]; + } + + // + int CopyPeak( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + peaksBuffer, + buffer, + forceClean + // + ); + } + + // + // VALES ... + + // + double GetVale( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(valesBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return valesBuffer[barIndex]; + } + + // + int CopyVale( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + valesBuffer, + buffer, + forceClean + // + ); + } + + // + // CURRENT ... + + // + // HH ... + + // + double GetCHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(cHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return cHHBuffer[barIndex]; + } + + // + int CopyCHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + cHHBuffer, + buffer, + forceClean + // + ); + } + + // + // LL ... + + // + double GetCLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(cLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return cLLBuffer[barIndex]; + } + + // + int CopyCLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + cLLBuffer, + buffer, + forceClean + // + ); + } + + // + // SHORT ... + + // + // HH ... + + // + double GetSHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + 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(); + + // + // Copy Items ... + return Copy( + start, + count, + sHHBuffer, + buffer, + forceClean + // + ); + } + + // + // LL ... + + // + double GetSLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + 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(); + + // + // Copy Items ... + return Copy( + start, + count, + sLLBuffer, + buffer, + forceClean + // + ); + } + + // + // MEDIUM ... + + // + // HH ... + + // + double GetMHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + 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(); + + // + // Copy Items ... + return Copy( + start, + count, + mHHBuffer, + buffer, + forceClean + // + ); + } + + // + // LL ... + + // + double GetMLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + 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(); + + // + // Copy Items ... + return Copy( + start, + count, + mLLBuffer, + buffer, + forceClean + // + ); + } + + // + // LONG ... + + // + // HH ... + + // + double GetLHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + 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(); + + // + // Copy Items ... + return Copy( + start, + count, + lHHBuffer, + buffer, + forceClean + // + ); + } + + // + // LL ... + + // + double GetLLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + 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(); + + // + // Copy Items ... + return Copy( + start, + count, + lLLBuffer, + buffer, + forceClean + // + ); + } + + // + // HIND ... + + // + // HH ... + + // + double GetHHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + 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(); + + // + // Copy Items ... + return Copy( + start, + count, + hHHBuffer, + buffer, + forceClean + // + ); + } + + // + // LL ... + + // + double GetHLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + 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(); + + // + // Copy Items ... + return Copy( + start, + count, + hLLBuffer, + buffer, + forceClean + // + ); + } + + // + // VALID PEAKS ... + + // + double GetValidPeak( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(validPeaksBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return validPeaksBuffer[barIndex]; + } + + // + int CopyValidPeak( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + validPeaksBuffer, + buffer, + forceClean + // + ); + } + + // + // VALID VALES ... + + // + double GetValidVale( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(validValesBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return validValesBuffer[barIndex]; + } + + // + int CopyValidVale( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + validValesBuffer, + buffer, + forceClean + // + ); + } + + // + // XVWAP ... + + // + // FAST ... + + // + double GetVWapFast( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(vwapFastBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return vwapFastBuffer[barIndex]; + } + + // + int CopyVWapFast( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + vwapFastBuffer, + buffer, + forceClean + // + ); + } + + // + // STATE FAST ... + + // + double GetVWapFastState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(vwapFastStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return vwapFastStateBuffer[barIndex]; + } + + // + int CopyVWapFastState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + vwapFastStateBuffer, + buffer, + forceClean + // + ); + } + + // + // MID ... + + // + double GetVWapMid( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(vwapMidBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return vwapMidBuffer[barIndex]; + } + + // + int CopyVWapMid( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + vwapMidBuffer, + buffer, + forceClean + // + ); + } + + // + // STATE MID ... + + // + double GetVWapMidState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(vwapMidStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return vwapMidStateBuffer[barIndex]; + } + + // + int CopyVWapMidState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + vwapMidStateBuffer, + buffer, + forceClean + // + ); + } + + // + // SLOW ... + + // + double GetVWapSlowBuffer( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(vwapSlowBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return vwapSlowBuffer[barIndex]; + } + + // + int CopyVWapSlow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + vwapSlowBuffer, + buffer, + forceClean + // + ); + } + + // + // STATE SLOW ... + + // + double GetVWapSlowState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(vwapSlowStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return vwapSlowStateBuffer[barIndex]; + } + + // + int CopyVWapSlowState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + vwapSlowStateBuffer, + buffer, + forceClean + // + ); + } + + // + // VOLUME ... + + // + double GetVWapVolume( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(vwapVolumeBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return vwapVolumeBuffer[barIndex]; + } + + // + int CopyVWapVolume( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + vwapVolumeBuffer, + buffer, + forceClean + // + ); + } + + // + // PRICE ... + + // + double GetVWapPrice( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(vwapPriceBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return vwapPriceBuffer[barIndex]; + } + + // + int CopyVWapPrice( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + vwapPriceBuffer, + buffer, + forceClean + // + ); + } + + // + // Converts to State ... + ENUM_XVWAP_STATES ToVWAPState(double value) + { + // + ENUM_XVWAP_STATES result = + value == 1 + ? XVWAP_STATE_BULLISH + : value == 2 + ? XVWAP_STATE_BEARISH + : XVWAP_STATE_NEUTURAL; + + // + return result; + } + + // + bool IsVWAPBullish(double value) + { + // + bool result = false; + + // + result = ToVWAPState(value) == XVWAP_STATE_BULLISH; + + // + return result; + } + + // + bool IsVWAPBearish(double value) + { + // + bool result = false; + + // + result = ToVWAPState(value) == XVWAP_STATE_BEARISH; + + // + return result; + } + + // + bool IsVWAPNeutural(double value) + { + // + bool result = false; + + // + result = ToVWAPState(value) == XVWAP_STATE_NEUTURAL; + + // + return result; + } + + // + // XDON ... + + // + // OPEN ... + + // + // UPPER ... + + // + double GetDonOpenUpper( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(donOpenUpperBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return donOpenUpperBuffer[barIndex]; + } + + // + int CopyDonOpenUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + donOpenUpperBuffer, + buffer, + forceClean + // + ); + } + + // + // LOWER ... + + // + double GetDonOpenLower( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(donOpenLowerBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return donOpenLowerBuffer[barIndex]; + } + + // + int CopyDonOpenLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + donOpenLowerBuffer, + buffer, + forceClean + // + ); + } + + // + // CLOSE ... + + // + // UPPER ... + + // + double GetDonCloseUpper( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(donCloseUpperBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return donCloseUpperBuffer[barIndex]; + } + + // + int CopyDonCloseUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + donCloseUpperBuffer, + buffer, + forceClean + // + ); + } + + // + // LOWER ... + + // + double GetDonCloseLower( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(donCloseLowerBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return donCloseLowerBuffer[barIndex]; + } + + // + int CopyDonCloseLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + donCloseLowerBuffer, + buffer, + forceClean + // + ); + } + + // + // HIGH ... + + // + // UPPER ... + + // + double GetDonHighUpper( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(donHighUpperBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return donHighUpperBuffer[barIndex]; + } + + // + int CopyDonHighUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + donHighUpperBuffer, + buffer, + forceClean + // + ); + } + + // + // LOWER ... + + // + double GetDonHighLower( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(donHighLowerBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return donHighLowerBuffer[barIndex]; + } + + // + int CopyDonHighLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + donHighLowerBuffer, + buffer, + forceClean + // + ); + } + + // + // LOW ... + + // + // UPPER ... + + // + double GetDonLowUpper( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(donLowUpperBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return donLowUpperBuffer[barIndex]; + } + + // + int CopyDonLowUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + donLowUpperBuffer, + buffer, + forceClean + // + ); + } + + // + // LOWER ... + + // + double GetDonLoweLower( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(donLowLowerBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return donLowLowerBuffer[barIndex]; + } + + // + int CopyDonLoweLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + donLowLowerBuffer, + buffer, + forceClean + // + ); + } + + // + // FIBONACCHI ... + + // + // LEVEL 1 ... + + // + double GetFiboLevel1( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(fl1Buffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fl1Buffer[barIndex]; + } + + // + int CopyFiboLevel1( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // FiboLevel To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + fl1Buffer, + buffer, + forceClean + // + ); + } + + // + // LEVEL 2 ... + + // + double GetFiboLevel2( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(fl2Buffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fl2Buffer[barIndex]; + } + + // + int CopyFiboLevel2( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // FiboLevel To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + fl2Buffer, + buffer, + forceClean + // + ); + } + + // + // LEVEL 3 ... + + // + double GetFiboLevel3( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(fl3Buffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fl3Buffer[barIndex]; + } + + // + int CopyFiboLevel3( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // FiboLevel To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + fl3Buffer, + buffer, + forceClean + // + ); + } + + // + // LEVEL 4 ... + + // + double GetFiboLevel4( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(fl4Buffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fl4Buffer[barIndex]; + } + + // + int CopyFiboLevel4( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // FiboLevel To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + fl4Buffer, + buffer, + forceClean + // + ); + } + + // + // LEVEL 5 ... + + // + double GetFiboLevel5( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(fl5Buffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fl5Buffer[barIndex]; + } + + // + int CopyFiboLevel5( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // FiboLevel To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + fl5Buffer, + buffer, + forceClean + // + ); + } + + // + // Conditions Generation ... + + bool GetConditions( + X121Conditions &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 ... + + // + CopySar( + zIndex, + loopback, + conditions.sarBuffer // + ); + + // + CopyPeak( + zIndex, + loopback, + conditions.peaksBuffer // + ); + + // + CopyVale( + zIndex, + loopback, + conditions.valesBuffer // + ); + + // + CopyCHH( + zIndex, + loopback, + conditions.cHHBuffer // + ); + + // + CopyCLL( + zIndex, + loopback, + conditions.cLLBuffer // + ); + + // + 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 // + ); + + // + CopyValidPeak( + zIndex, + loopback, + conditions.validPeaksBuffer // + ); + + // + CopyValidVale( + zIndex, + loopback, + conditions.validValesBuffer // + ); + + // + CopyVWapFast( + zIndex, + loopback, + conditions.vwapFastBuffer // + ); + + // + CopyVWapFastState( + zIndex, + loopback, + conditions.vwapFastStateBuffer // + ); + + // + CopyVWapMid( + zIndex, + loopback, + conditions.vwapMidBuffer // + ); + + // + CopyVWapMidState( + zIndex, + loopback, + conditions.vwapMidStateBuffer // + ); + + // + CopyVWapSlow( + zIndex, + loopback, + conditions.vwapSlowBuffer // + ); + + // + CopyVWapSlowState( + zIndex, + loopback, + conditions.vwapSlowStateBuffer // + ); + + // + CopyVWapVolume( + zIndex, + loopback, + conditions.vwapVolumeBuffer // + ); + + // + CopyVWapPrice( + zIndex, + loopback, + conditions.vwapPriceBuffer // + ); + + // + CopyDonOpenUpper( + zIndex, + loopback, + conditions.donOpenUpperBuffer // + ); + + // + CopyDonOpenLower( + zIndex, + loopback, + conditions.donOpenLowerBuffer // + ); + + // + CopyDonCloseUpper( + zIndex, + loopback, + conditions.donCloseUpperBuffer // + ); + + // + CopyDonCloseLower( + zIndex, + loopback, + conditions.donCloseLowerBuffer // + ); + + // + CopyDonHighUpper( + zIndex, + loopback, + conditions.donHighUpperBuffer // + ); + + // + CopyDonHighLower( + zIndex, + loopback, + conditions.donHighLowerBuffer // + ); + + // + CopyDonLowUpper( + zIndex, + loopback, + conditions.donLowUpperBuffer // + ); + + // + CopyDonLoweLower( + zIndex, + loopback, + conditions.donLowLowerBuffer // + ); + + // + CopyFiboLevel1( + zIndex, + loopback, + conditions.fl1Buffer // + ); + + // + CopyFiboLevel2( + zIndex, + loopback, + conditions.fl2Buffer // + ); + + // + CopyFiboLevel3( + zIndex, + loopback, + conditions.fl3Buffer // + ); + + // + CopyFiboLevel4( + zIndex, + loopback, + conditions.fl4Buffer // + ); + + // + CopyFiboLevel5( + zIndex, + loopback, + conditions.fl5Buffer // + ); + + // + // Conditions ... + + // + int cIDX = 1; + int pIDX = cIDX + 1; + + // + // XSAR ... + + // + bool isSarBullish = conditions.sarBuffer[cIDX] < cBar.low; + bool isSarBullishPrev = conditions.sarBuffer[pIDX] < pBar.low; + + // + bool isSarBearish = conditions.sarBuffer[cIDX] > cBar.high; + bool isSarBearishPrev = conditions.sarBuffer[pIDX] > pBar.high; + + // + bool isSarSwitchedToBullish = isSarBullish && + !isSarBullishPrev; + bool isSarSwitchedToBearish = isSarBearish && + !isSarBearishPrev; + + // + // XPV ... + + // + bool isNewPeak = conditions.peaksBuffer[cIDX] != conditions.peaksBuffer[pIDX]; + bool isNewPeakOverLast = isNewPeak && + conditions.peaksBuffer[cIDX] > conditions.peaksBuffer[pIDX]; + bool isNewPeakUnderLast = isNewPeak && + conditions.peaksBuffer[cIDX] < conditions.peaksBuffer[pIDX]; + + // + bool isNewVale = conditions.valesBuffer[cIDX] != conditions.valesBuffer[pIDX]; + bool isNewValeOverLast = isNewVale && + conditions.valesBuffer[cIDX] > conditions.valesBuffer[pIDX]; + bool isNewValeUnderLast = isNewVale && + conditions.valesBuffer[cIDX] < conditions.valesBuffer[pIDX]; + + // + // XVWAP ... + + // + bool isVWapFastBullish = IsVWAPBullish(conditions.vwapFastStateBuffer[cIDX]); + bool isVWapFastBullishPrev = IsVWAPBullish(conditions.vwapFastStateBuffer[pIDX]); + + // + bool isVWapFastBearish = IsVWAPBearish(conditions.vwapFastStateBuffer[cIDX]); + bool isVWapFastBearishPrev = IsVWAPBearish(conditions.vwapFastStateBuffer[pIDX]); + + // + bool isVWapFastNeutural = IsVWAPNeutural(conditions.vwapFastStateBuffer[cIDX]); + bool isVWapFastNeuturalPrev = IsVWAPNeutural(conditions.vwapFastStateBuffer[pIDX]); + + // + bool isVWapMidBullish = IsVWAPBullish(conditions.vwapMidStateBuffer[cIDX]); + bool isVWapMidBullishPrev = IsVWAPBullish(conditions.vwapMidStateBuffer[pIDX]); + + // + bool isVWapMidBearish = IsVWAPBearish(conditions.vwapMidStateBuffer[cIDX]); + bool isVWapMidBearishPrev = IsVWAPBearish(conditions.vwapMidStateBuffer[pIDX]); + + // + bool isVWapMidNeutural = IsVWAPNeutural(conditions.vwapMidStateBuffer[cIDX]); + bool isVWapMidNeuturalPrev = IsVWAPNeutural(conditions.vwapMidStateBuffer[pIDX]); + + // + bool isVWapSlowBullish = IsVWAPBullish(conditions.vwapSlowStateBuffer[cIDX]); + bool isVWapSlowBullishPrev = IsVWAPBullish(conditions.vwapSlowStateBuffer[pIDX]); + + // + bool isVWapSlowBearish = IsVWAPBearish(conditions.vwapSlowStateBuffer[cIDX]); + bool isVWapSlowBearishPrev = IsVWAPBearish(conditions.vwapSlowStateBuffer[pIDX]); + + // + bool isVWapSlowNeutural = IsVWAPNeutural(conditions.vwapSlowStateBuffer[cIDX]); + bool isVWapSlowNeuturalPrev = IsVWAPNeutural(conditions.vwapSlowStateBuffer[pIDX]); + + // + bool isVWapFastOverMid = conditions.vwapFastBuffer[cIDX] > conditions.vwapMidBuffer[cIDX]; + bool isVWapFastOverMidPrev = conditions.vwapFastBuffer[pIDX] > conditions.vwapMidBuffer[pIDX]; + + // + bool isVWapMidOverSlow = conditions.vwapMidBuffer[cIDX] > conditions.vwapSlowBuffer[cIDX]; + bool isVWapMidOverSlowPrev = conditions.vwapMidBuffer[pIDX] > conditions.vwapSlowBuffer[pIDX]; + + // + bool isVWapFastUnderMid = conditions.vwapFastBuffer[cIDX] < conditions.vwapMidBuffer[cIDX]; + bool isVWapFastUnderMidPrev = conditions.vwapFastBuffer[pIDX] < conditions.vwapMidBuffer[pIDX]; + + // + bool isVWapMidUnderSlow = conditions.vwapMidBuffer[cIDX] < conditions.vwapSlowBuffer[cIDX]; + bool isVWapMidUnderSlowPrev = conditions.vwapMidBuffer[pIDX] < conditions.vwapSlowBuffer[pIDX]; + + // + bool isVWapBullishState = isVWapFastBullish && + isVWapMidBullish && + isVWapSlowBullish; + bool isVWapBullishStatePrev = isVWapFastBullishPrev && + isVWapMidBullishPrev && + isVWapSlowBullishPrev; + + // + bool isVWapBearishState = isVWapFastBearish && + isVWapMidBearish && + isVWapSlowBearish; + bool isVWapBearishStatePrev = isVWapFastBearishPrev && + isVWapMidBearishPrev && + isVWapSlowBearishPrev; + + // + bool isVWapNeuturalState = isVWapFastNeutural && + isVWapMidNeutural && + isVWapSlowNeutural; + bool isVWapNeuturalStatePrev = isVWapFastNeuturalPrev && + isVWapMidNeuturalPrev && + isVWapSlowNeuturalPrev; + + // + bool isVWapBullishOrdered = isVWapFastOverMid && + isVWapMidOverSlow; + bool isVWapBullishOrderedPrev = isVWapFastOverMidPrev && + isVWapMidOverSlowPrev; + + // + bool isVWapBearishOrdered = isVWapFastUnderMid && + isVWapMidUnderSlow; + bool isVWapBearishOrderedPrev = isVWapFastUnderMidPrev && + isVWapMidUnderSlowPrev; + + // + bool isVWapSwitchedToBullishOrdered = isVWapBullishOrdered && + !isVWapBullishOrderedPrev; + bool isVWapSwitchedToBearishOrdered = isVWapBearishOrdered && + !isVWapBearishOrderedPrev; + + // + bool isVWapSwitchedToBullishState = isVWapBullishState && + !isVWapBullishStatePrev; + bool isVWapSwitchedToBearishState = isVWapBearishState && + !isVWapBearishStatePrev; + bool isVWapSwitchedToNeuturalState = isVWapNeuturalState && + !isVWapNeuturalStatePrev; + + // + // XDON ... + + // + // XFIBONACCI ... + + // + bool isOerFib1 = cBar.low > conditions.fl1Buffer[cIDX]; + bool isOerFib2 = cBar.low > conditions.fl2Buffer[cIDX]; + bool isOerFib3 = cBar.low > conditions.fl3Buffer[cIDX]; + bool isOerFib4 = cBar.low > conditions.fl4Buffer[cIDX]; + bool isOerFib5 = cBar.low > conditions.fl5Buffer[cIDX]; + + // + bool isUnderFib1 = cBar.high < conditions.fl1Buffer[cIDX]; + bool isUnderFib2 = cBar.high < conditions.fl2Buffer[cIDX]; + bool isUnderFib3 = cBar.high < conditions.fl3Buffer[cIDX]; + bool isUnderFib4 = cBar.high < conditions.fl4Buffer[cIDX]; + bool isUnderFib5 = cBar.high < conditions.fl5Buffer[cIDX]; + + // + bool isCloseOerFib1 = cBar.close > conditions.fl1Buffer[cIDX]; + bool isCloseOerFib2 = cBar.close > conditions.fl2Buffer[cIDX]; + bool isCloseOerFib3 = cBar.close > conditions.fl3Buffer[cIDX]; + bool isCloseOerFib4 = cBar.close > conditions.fl4Buffer[cIDX]; + bool isCloseOerFib5 = cBar.close > conditions.fl5Buffer[cIDX]; + + // + bool isCloseUnderFib1 = cBar.close < conditions.fl1Buffer[cIDX]; + bool isCloseUnderFib2 = cBar.close < conditions.fl2Buffer[cIDX]; + bool isCloseUnderFib3 = cBar.close < conditions.fl3Buffer[cIDX]; + bool isCloseUnderFib4 = cBar.close < conditions.fl4Buffer[cIDX]; + bool isCloseUnderFib5 = cBar.close < conditions.fl5Buffer[cIDX]; + + // + + // + // Set ... + conditions.isSarBullish = isSarBullish; + conditions.isSarBearish = isSarBearish; + conditions.isSarSwitchedToBullish = isSarSwitchedToBullish; + conditions.isSarSwitchedToBearish = isSarSwitchedToBearish; + conditions.isNewPeak = isNewPeak; + conditions.isNewPeakOverLast = isNewPeakOverLast; + conditions.isNewPeakUnderLast = isNewPeakUnderLast; + conditions.isNewVale = isNewVale; + conditions.isNewValeOverLast = isNewValeOverLast; + conditions.isNewValeUnderLast = isNewValeUnderLast; + conditions.isVWapFastBullish = isVWapFastBullish; + conditions.isVWapFastBearish = isVWapFastBearish; + conditions.isVWapFastNeutural = isVWapFastNeutural; + conditions.isVWapMidBullish = isVWapMidBullish; + conditions.isVWapMidBearish = isVWapMidBearish; + conditions.isVWapMidNeutural = isVWapMidNeutural; + conditions.isVWapSlowBullish = isVWapSlowBullish; + conditions.isVWapSlowBearish = isVWapSlowBearish; + conditions.isVWapSlowNeutural = isVWapSlowNeutural; + conditions.isVWapFastOverMid = isVWapFastOverMid; + conditions.isVWapMidOverSlow = isVWapMidOverSlow; + conditions.isVWapFastUnderMid = isVWapFastUnderMid; + conditions.isVWapMidUnderSlow = isVWapMidUnderSlow; + conditions.isVWapBullishState = isVWapBullishState; + conditions.isVWapBearishState = isVWapBearishState; + conditions.isVWapNeuturalState = isVWapNeuturalState; + conditions.isVWapBullishOrdered = isVWapBullishOrdered; + conditions.isVWapBearishOrdered = isVWapBearishOrdered; + conditions.isVWapSwitchedToBullishOrdered = isVWapSwitchedToBullishOrdered; + conditions.isVWapSwitchedToBearishOrdered = isVWapSwitchedToBearishOrdered; + conditions.isVWapSwitchedToBullishState = isVWapSwitchedToBullishState; + conditions.isVWapSwitchedToBearishState = isVWapSwitchedToBearishState; + conditions.isVWapSwitchedToNeuturalState = isVWapSwitchedToNeuturalState; + conditions.isOerFib1 = isOerFib1; + conditions.isOerFib2 = isOerFib2; + conditions.isOerFib3 = isOerFib3; + conditions.isOerFib4 = isOerFib4; + conditions.isOerFib5 = isOerFib5; + conditions.isUnderFib1 = isUnderFib1; + conditions.isUnderFib2 = isUnderFib2; + conditions.isUnderFib3 = isUnderFib3; + conditions.isUnderFib4 = isUnderFib4; + conditions.isUnderFib5 = isUnderFib5; + conditions.isCloseOerFib1 = isCloseOerFib1; + conditions.isCloseOerFib2 = isCloseOerFib2; + conditions.isCloseOerFib3 = isCloseOerFib3; + conditions.isCloseOerFib4 = isCloseOerFib4; + conditions.isCloseOerFib5 = isCloseOerFib5; + conditions.isCloseUnderFib1 = isCloseUnderFib1; + conditions.isCloseUnderFib2 = isCloseUnderFib2; + conditions.isCloseUnderFib3 = isCloseUnderFib3; + conditions.isCloseUnderFib4 = isCloseUnderFib4; + conditions.isCloseUnderFib5 = isCloseUnderFib5; + + // + return result; + } + + // + protected: + // + + // + private: + // + // Props ... + X121Inputs mInputs; // Inputs ... + + // + // Buffers ... + + // + // Buffers ... + double peaksBuffer[]; + double valesBuffer[]; + double sarBuffer[]; + double vwapFastBuffer[]; + double vwapMidBuffer[]; + double vwapSlowBuffer[]; + double donOpenUpperBuffer[]; + double donOpenLowerBuffer[]; + double donCloseUpperBuffer[]; + double donCloseLowerBuffer[]; + double donHighUpperBuffer[]; + double donHighLowerBuffer[]; + double donLowUpperBuffer[]; + double donLowLowerBuffer[]; + double fl1Buffer[]; + double fl2Buffer[]; + double fl3Buffer[]; + double fl4Buffer[]; + double fl5Buffer[]; + double cHHBuffer[]; + double cLLBuffer[]; + double sHHBuffer[]; + double sLLBuffer[]; + double mHHBuffer[]; + double mLLBuffer[]; + double lHHBuffer[]; + double lLLBuffer[]; + double hHHBuffer[]; + double hLLBuffer[]; + double vwapVolumeBuffer[]; + double vwapPriceBuffer[]; + double vwapFastStateBuffer[]; + double vwapMidStateBuffer[]; + double vwapSlowStateBuffer[]; + double validPeaksBuffer[]; + double validValesBuffer[]; + + // + // Tools ... + + /** + * Calculate Buffers ... + */ + void Calculate() + { + // + int totalBars = CountBars(); + if (totalBars > 1000) + { + totalBars = 1000; + } + + // + // Buffers ... + + // + // XSAR ... + CopyBuffer( + mHandler, + X121_SAR_LINE, + 0, + totalBars, + sarBuffer + // + ); + + // + // XPV ... + + // + // PEAKS ... + CopyBuffer( + mHandler, + X121_PEAKS_LINE, + 0, + totalBars, + peaksBuffer + // + ); + + // + // VALES ... + CopyBuffer( + mHandler, + X121_VALES_LINE, + 0, + totalBars, + valesBuffer + // + ); + + // + // VALID PEAKS ... + CopyBuffer( + mHandler, + X121_VALID_PEAKS_LINE, + 0, + totalBars, + validPeaksBuffer + // + ); + + // + // VALID VALES ... + CopyBuffer( + mHandler, + X121_VALID_VALES_LINE, + 0, + totalBars, + validValesBuffer + // + ); + + // + // CURRENT ... + + // + // HH ... + CopyBuffer( + mHandler, + X121_CURRENT_HH_LINE, + 0, + totalBars, + cHHBuffer + // + ); + + // + // LL ... + CopyBuffer( + mHandler, + X121_CURRENT_LL_LINE, + 0, + totalBars, + cLLBuffer + // + ); + + // + // SHORT ... + + // + // HH ... + CopyBuffer( + mHandler, + X121_SHORT_HH_LINE, + 0, + totalBars, + sHHBuffer + // + ); + + // + // LL ... + CopyBuffer( + mHandler, + X121_SHORT_LL_LINE, + 0, + totalBars, + sLLBuffer + // + ); + + // + // MEDIUM ... + + // + // HH ... + CopyBuffer( + mHandler, + X121_MEDIUM_HH_LINE, + 0, + totalBars, + mHHBuffer + // + ); + + // + // LL ... + CopyBuffer( + mHandler, + X121_MEDIUM_LL_LINE, + 0, + totalBars, + mLLBuffer + // + ); + + // + // LONG ... + + // + // HH ... + CopyBuffer( + mHandler, + X121_LONG_HH_LINE, + 0, + totalBars, + lHHBuffer + // + ); + + // + // LL ... + CopyBuffer( + mHandler, + X121_LONG_LL_LINE, + 0, + totalBars, + lLLBuffer + // + ); + + // + // HIND ... + + // + // HH ... + CopyBuffer( + mHandler, + X121_HIND_HH_LINE, + 0, + totalBars, + hHHBuffer + // + ); + + // + // LL ... + CopyBuffer( + mHandler, + X121_HIND_LL_LINE, + 0, + totalBars, + hLLBuffer + // + ); + + // + // XVWAP ... + + // + // FAST ... + CopyBuffer( + mHandler, + X121_VWAP_FAST_LINE, + 0, + totalBars, + vwapFastBuffer + // + ); + + // + // FAST STATE ... + CopyBuffer( + mHandler, + X121_VWAP_FAST_STATE_LINE, + 0, + totalBars, + vwapFastStateBuffer + // + ); + + // + // MID ... + CopyBuffer( + mHandler, + X121_VWAP_MID_LINE, + 0, + totalBars, + vwapMidBuffer + // + ); + + // + // MID STATE ... + CopyBuffer( + mHandler, + X121_VWAP_MID_STATE_LINE, + 0, + totalBars, + vwapMidStateBuffer + // + ); + + // + // SLOW ... + CopyBuffer( + mHandler, + X121_VWAP_SLOW_LINE, + 0, + totalBars, + vwapSlowBuffer + // + ); + + // + // SLOW STATE ... + CopyBuffer( + mHandler, + X121_VWAP_SLOW_STATE_LINE, + 0, + totalBars, + vwapSlowStateBuffer + // + ); + + // + // VOLUME ... + CopyBuffer( + mHandler, + X121_VWAP_VOLUME_LINE, + 0, + totalBars, + vwapVolumeBuffer + // + ); + + // + // PRICE ... + CopyBuffer( + mHandler, + X121_VWAP_PRICE_LINE, + 0, + totalBars, + vwapPriceBuffer + // + ); + + // + // FIBONACCI ... + + // + // LEVEL 1 ... + CopyBuffer( + mHandler, + X121_FIB_LEVEL_1_LINE, + 0, + totalBars, + fl1Buffer + // + ); + + // + // LEVEL 2 ... + CopyBuffer( + mHandler, + X121_FIB_LEVEL_2_LINE, + 0, + totalBars, + fl2Buffer + // + ); + + // + // LEVEL 3 ... + CopyBuffer( + mHandler, + X121_FIB_LEVEL_3_LINE, + 0, + totalBars, + fl3Buffer + // + ); + + // + // LEVEL 4 ... + CopyBuffer( + mHandler, + X121_FIB_LEVEL_4_LINE, + 0, + totalBars, + fl4Buffer + // + ); + + // + // LEVEL 5 ... + CopyBuffer( + mHandler, + X121_FIB_LEVEL_5_LINE, + 0, + totalBars, + fl5Buffer + // + ); + + // + // XDON ... + + // + // OPEN ... + + // + // Upper ... + CopyBuffer( + mHandler, + X121_DON_OPEN_UPPER_LINE, + 0, + totalBars, + donOpenUpperBuffer + // + ); + + // + // Lower ... + CopyBuffer( + mHandler, + X121_DON_OPEN_LOWER_LINE, + 0, + totalBars, + donOpenLowerBuffer + // + ); + + // + // CLOSE ... + + // + // Upper ... + CopyBuffer( + mHandler, + X121_DON_CLOSE_UPPER_LINE, + 0, + totalBars, + donCloseUpperBuffer + // + ); + + // + // Lower ... + CopyBuffer( + mHandler, + X121_DON_CLOSE_LOWER_LINE, + 0, + totalBars, + donCloseLowerBuffer + // + ); + + // + // HIGH ... + + // + // Upper ... + CopyBuffer( + mHandler, + X121_DON_HIGH_UPPER_LINE, + 0, + totalBars, + donHighUpperBuffer + // + ); + + // + // Lower ... + CopyBuffer( + mHandler, + X121_DON_HIGH_LOWER_LINE, + 0, + totalBars, + donHighLowerBuffer + // + ); + + // + // LOW ... + + // + // Upper ... + CopyBuffer( + mHandler, + X121_DON_LOW_UPPER_LINE, + 0, + totalBars, + donLowUpperBuffer + // + ); + + // + // Lower ... + CopyBuffer( + mHandler, + X121_DON_LOW_LOWER_LINE, + 0, + totalBars, + donLowLowerBuffer + // + ); + } +}; + +// \ No newline at end of file diff --git a/BKPS/14031003/Helpers/x-saherelm.x3ma.helper.mq5 b/BKPS/14031003/Helpers/x-saherelm.x3ma.helper.mq5 new file mode 100644 index 0000000..96458f2 --- /dev/null +++ b/BKPS/14031003/Helpers/x-saherelm.x3ma.helper.mq5 @@ -0,0 +1,758 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCX3MAHelper +// 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 ... + +// +enum ENUM_X3MA_BUFFERS +{ + // + X3MA_FAST_LINE = 0, + X3MA_MID_LINE = 1, + X3MA_SLOW_LINE = 2, +}; + +// +// Input Models ... +struct X3MAInputs +{ + // + // Props ... + + // + // Market ... + int fastLength; // Fast Length + int midLength; // Mid Length + int slowLength; // Slow Length + int shiftLength; // Shift + ENUM_MA_METHOD method; // Mode + ENUM_APPLIED_PRICE appliedTo; // Applied To + + // + // Presentation ... + + // + bool showFast; // Show Fast + bool showMid; // Show Mid + bool showSlow; // Show Slow + + // + // Constructor(s) ... + X3MAInputs() + { + // + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + fastLength = 0; + midLength = 0; + slowLength = 0; + shiftLength = 0; + method = MODE_SMA; + appliedTo = PRICE_CLOSE; + + // + showFast = false; + showMid = false; + showSlow = false; + } + + // + // Default ... + void Default() + { + // + fastLength = 50; + midLength = 100; + slowLength = 200; + shiftLength = 0; + method = MODE_SMA; + appliedTo = PRICE_CLOSE; + + // + showFast = true; + showMid = true; + showSlow = true; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + fastLength > 2 && + midLength > fastLength && + slowLength > midLength && + // + shiftLength >= 0 + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(fastLength, midLength); + result = MathMax(result, slowLength); + + // + return result; + } +}; + +// +// Define Conditions ... +struct X3MAConditions +{ + // + // Common ... + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + // Buffers ... + + // + double fasts[]; + double mids[]; + double slows[]; + + // + // Conditions ... + + // + bool isFastOverMid; + bool isMidOverSlow; + + // + bool isFastUnderMid; + bool isMidUnderSlow; + + // + bool isBullishOrdered; + bool isBearishOrdered; + + // + bool isSwitchedToBullishOrdered; + bool isSwitchedToBearishOrdered; + + // + void X3MAConditions() + { + Clean(); + } + + // + void Clean() + { + // + Clean(fasts); + Clean(mids); + Clean(slows); + + // + ArraySetAsSeries(fasts, true); + ArraySetAsSeries(mids, true); + ArraySetAsSeries(slows, true); + + // + isFastOverMid = false; + isMidOverSlow = false; + isFastUnderMid = false; + isMidUnderSlow = false; + isBullishOrdered = false; + isBearishOrdered = false; + isSwitchedToBullishOrdered = false; + isSwitchedToBearishOrdered = false; + } + + // + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + // + bullishScore = 0; + bearishScore = 0; + + // + // Since We have to Use this + // Only for Filtering Signals ... + // We Can Ignore Scoring ... + // or Complete this later ... + } + + // + 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 = + // + "" + // + ; + + // + result = + // + "[" + GetTag() + "]" + separator + + (onlyConditions + ? "" + : commonStr) + + (!includeScores + ? "" + : scoresStr) + + " " + separator + + (onlyCommons + ? "" + : conditionsStr) + + "" + // + ; + + // + return result; + } + + // + string GetTag() + { + return "X3MA"; + } +}; + +// +// Class ... +class XCX3MAHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructors ... + XCX3MAHelper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCX3MAHelper() + { + // + Clean(fastBuffer); + Clean(midBuffer); + Clean(slowBuffer); + } + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + X3MAInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + ArraySetAsSeries(fastBuffer, true); + ArraySetAsSeries(midBuffer, true); + ArraySetAsSeries(slowBuffer, true); + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x3ma", + // + // Inputs ... + // + // Market ... + "", + mInputs.fastLength, + mInputs.midLength, + mInputs.slowLength, + mInputs.shiftLength, + mInputs.method, + mInputs.appliedTo, + // + // Presentation ... + "", + // + mInputs.showFast, + mInputs.showMid, + mInputs.showSlow + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + X3MAInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + X3MAInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Buffers ... + + // + double GetFast( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(fastBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fastBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyFast( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + fastBuffer, + buffer, + forceClean + // + ); + } + + // + double GetMid( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(midBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return midBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyMid( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + midBuffer, + buffer, + forceClean + // + ); + } + + // + double GetSlow( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(slowBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return slowBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopySlow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + slowBuffer, + buffer, + forceClean + // + ); + } + + // + // Conditions ... + + // + bool GetConditions( + X3MAConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = true; + + // + if (loopback < 3) + { + loopback = 3; + } + + // + 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; + + // + // Buffers ... + + // + // Fast ... + CopyFast( + zIndex, + loopback, + conditions.fasts // + ); + + // + // Mid ... + CopyMid( + zIndex, + loopback, + conditions.mids // + ); + + // + // Slow ... + CopySlow( + zIndex, + loopback, + conditions.slows // + ); + + // + // Conditions ... + + // + bool isFastOverMid = + conditions.fasts[cIndex] > conditions.mids[cIndex]; + bool isFastOverMidPrev = + conditions.fasts[pIndex] > conditions.mids[pIndex]; + + // + bool isMidOverSlow = + conditions.mids[cIndex] > conditions.slows[cIndex]; + bool isMidOverSlowPrev = + conditions.mids[pIndex] > conditions.slows[pIndex]; + + // + bool isFastUnderMid = + conditions.fasts[cIndex] < conditions.mids[cIndex]; + bool isFastUnderMidPrev = + conditions.fasts[pIndex] < conditions.mids[pIndex]; + + // + bool isMidUnderSlow = + conditions.mids[cIndex] < conditions.slows[cIndex]; + bool isMidUnderSlowPrev = + conditions.mids[pIndex] < conditions.slows[pIndex]; + + // + bool isBullishOrdered = isFastOverMid && + isMidOverSlow; + bool isBullishOrderedPrev = isFastOverMidPrev && + isMidOverSlowPrev; + + // + bool isBearishOrdered = isFastUnderMid && + isMidUnderSlow; + bool isBearishOrderedPrev = isFastUnderMidPrev && + isMidUnderSlowPrev; + + // + bool isSwitchedToBullishOrdered = isBullishOrdered && + !isBullishOrderedPrev; + bool isSwitchedToBearishOrdered = isBearishOrdered && + !isBearishOrderedPrev; + + // + conditions.isFastOverMid = isFastOverMid; + conditions.isMidOverSlow = isMidOverSlow; + conditions.isFastUnderMid = isFastUnderMid; + conditions.isMidUnderSlow = isMidUnderSlow; + conditions.isBullishOrdered = isBullishOrdered; + conditions.isBearishOrdered = isBearishOrdered; + conditions.isSwitchedToBullishOrdered = isSwitchedToBullishOrdered; + conditions.isSwitchedToBearishOrdered = isSwitchedToBearishOrdered; + + // + return result; + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + X3MAInputs mInputs; // Inputs ... + + // + // Buffers ... + double fastBuffer[]; + double midBuffer[]; + double slowBuffer[]; + + // + // Tools ... + + // + // Calculate Values Until Now ... + void Calculate() + { + // + int totalBars = CountBars(); + if (totalBars > 1000) + { + totalBars = 1000; + } + + // + // Fast ... + CopyBuffer( + mHandler, + X3MA_FAST_LINE, + 0, + totalBars, + fastBuffer + // + ); + + // + // Mid ... + CopyBuffer( + mHandler, + X3MA_MID_LINE, + 0, + totalBars, + midBuffer + // + ); + + // + // Slow ... + CopyBuffer( + mHandler, + X3MA_SLOW_LINE, + 0, + totalBars, + slowBuffer + // + ); + } +}; + +// \ No newline at end of file diff --git a/BKPS/14031003/Helpers/x-saherelm.x3vwap.helper.mq5 b/BKPS/14031003/Helpers/x-saherelm.x3vwap.helper.mq5 new file mode 100644 index 0000000..e3cc34a --- /dev/null +++ b/BKPS/14031003/Helpers/x-saherelm.x3vwap.helper.mq5 @@ -0,0 +1,1150 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCX3VWAPHelper +// 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 ... + +// +enum ENUM_X3VWAP_BUFFERS +{ + // + X3VWAP_FAST_LINE = 0, + X3VWAP_FAST_STATE_LINE = 8, + X3VWAP_MID_LINE = 2, + X3VWAP_MID_STATE_LINE = 9, + X3VWAP_SLOW_LINE = 4, + X3VWAP_SLOW_STATE_LINE = 10, +}; + +// +enum ENUM_X3VWAP_STATES +{ + // + X3VWAP_STATE_BULLISH = 1, + X3VWAP_STATE_BEARISH = 2, + X3VWAP_STATE_NEUTURAL = 3, +}; + +// +// Input Models ... +struct X3VWAPInputs +{ + // + // Props ... + + // + // Market ... + int fastLength; // Fast Length + int midLength; // Mid Length + int slowLength; // Slow Length + ENUM_APPLIED_PRICE appliedTo; // Applied To + + // + // Presentation ... + + // + bool showFast; // Show Fast + bool showMid; // Show Mid + bool showSlow; // Show Slow + + // + // Constructor(s) ... + X3VWAPInputs() + { + // + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + fastLength = 0; + midLength = 0; + slowLength = 0; + appliedTo = PRICE_CLOSE; + + // + showFast = false; + showMid = false; + showSlow = false; + } + + // + // Default ... + void Default() + { + // + fastLength = 50; + midLength = 100; + slowLength = 200; + appliedTo = PRICE_CLOSE; + + // + showFast = true; + showMid = true; + showSlow = true; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + fastLength > 2 && + midLength > fastLength && + slowLength > midLength + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(fastLength, midLength); + result = MathMax(result, slowLength); + + // + return result; + } +}; + +// +// Define Conditions ... +struct X3VWAPConditions +{ + // + // Common ... + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + // Buffers ... + + // + double fasts[]; + double fastStates[]; + double mids[]; + double midStates[]; + double slows[]; + double slowStates[]; + + // + // Conditions ... + + // + bool isFastBullish; + bool isFastBearish; + bool isFastNeutural; + + // + bool isMidBullish; + bool isMidBearish; + bool isMidNeutural; + + // + bool isSlowBullish; + bool isSlowBearish; + bool isSlowNeutural; + + // + bool isFastOverMid; + bool isMidOverSlow; + + // + bool isFastUnderMid; + bool isMidUnderSlow; + + // + bool isBullishState; + bool isBearishState; + bool isNeuturalState; + + // + bool isBullishOrdered; + bool isBearishOrdered; + + // + bool isSwitchedToBullishOrdered; + bool isSwitchedToBearishOrdered; + + // + bool isSwitchedToBullishState; + bool isSwitchedToBearishState; + bool isSwitchedToNeuturalState; + + // + void X3VWAPConditions() + { + Clean(); + } + + // + void Clean() + { + // + Clean(fasts); + Clean(mids); + Clean(slows); + + // + Clean(fastStates); + Clean(midStates); + Clean(slowStates); + + // + ArraySetAsSeries(fasts, true); + ArraySetAsSeries(mids, true); + ArraySetAsSeries(slows, true); + + // + ArraySetAsSeries(fastStates, true); + ArraySetAsSeries(midStates, true); + ArraySetAsSeries(slowStates, true); + + // + isFastBullish = false; + isFastBearish = false; + isFastNeutural = false; + isMidBullish = false; + isMidBearish = false; + isMidNeutural = false; + isSlowBullish = false; + isSlowBearish = false; + isSlowNeutural = false; + isFastOverMid = false; + isMidOverSlow = false; + isFastUnderMid = false; + isMidUnderSlow = false; + isBullishState = false; + isBearishState = false; + isNeuturalState = false; + isBullishOrdered = false; + isBearishOrdered = false; + isSwitchedToBullishOrdered = false; + isSwitchedToBearishOrdered = false; + isSwitchedToBullishState = false; + isSwitchedToBearishState = false; + isSwitchedToNeuturalState = false; + } + + // + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + // + bullishScore = 0; + bearishScore = 0; + + // + // Since We have to Use this + // Only for Filtering Signals ... + // We Can Ignore Scoring ... + // or Complete this later ... + } + + // + 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 = + // + "" + // + ; + + // + result = + // + "[" + GetTag() + "]" + separator + + (onlyConditions + ? "" + : commonStr) + + (!includeScores + ? "" + : scoresStr) + + " " + separator + + (onlyCommons + ? "" + : conditionsStr) + + "" + // + ; + + // + return result; + } + + // + string GetTag() + { + return "X3VWAP"; + } +}; + +// +// Class ... +class XCX3VWAPHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructors ... + XCX3VWAPHelper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCX3VWAPHelper() + { + // + Clean(fastBuffer); + Clean(midBuffer); + Clean(slowBuffer); + } + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + X3VWAPInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + ArraySetAsSeries(fastBuffer, true); + ArraySetAsSeries(fastStateBuffer, true); + + // + ArraySetAsSeries(midBuffer, true); + ArraySetAsSeries(midStateBuffer, true); + + // + ArraySetAsSeries(slowBuffer, true); + ArraySetAsSeries(slowStateBuffer, true); + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x3vwap", + // + // Inputs ... + // + // Market ... + "", + mInputs.fastLength, + mInputs.midLength, + mInputs.slowLength, + mInputs.appliedTo, + // + // Presentation ... + "", + // + mInputs.showFast, + mInputs.showMid, + mInputs.showSlow + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + X3VWAPInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + X3VWAPInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Buffers ... + + // + double GetFast( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(fastBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fastBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyFast( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + fastBuffer, + buffer, + forceClean + // + ); + } + + // + double GetFastState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(fastStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fastStateBuffer[barIndex]; + } + + // + // Copy Required Items ... + 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(); + + // + // Copy Items ... + return Copy( + start, + count, + fastStateBuffer, + buffer, + forceClean + // + ); + } + + // + double GetMid( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(midBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return midBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyMid( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + midBuffer, + buffer, + forceClean + // + ); + } + + // + double GetMidState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(midStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return midStateBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyMidState( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + midStateBuffer, + buffer, + forceClean + // + ); + } + + // + double GetSlow( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(slowBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return slowBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopySlow( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + slowBuffer, + buffer, + forceClean + // + ); + } + + // + double GetSlowState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(slowStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return slowStateBuffer[barIndex]; + } + + // + // Copy Required Items ... + 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(); + + // + // Copy Items ... + return Copy( + start, + count, + slowStateBuffer, + buffer, + forceClean + // + ); + } + + // + // Converts to State ... + ENUM_X3VWAP_STATES ToState(double value) + { + // + ENUM_X3VWAP_STATES result = + value == 1 + ? X3VWAP_STATE_BULLISH + : value == 2 + ? X3VWAP_STATE_BEARISH + : X3VWAP_STATE_NEUTURAL; + + // + return result; + } + + // + bool IsBullish(double value) + { + // + bool result = false; + + // + result = ToState(value) == X3VWAP_STATE_BULLISH; + + // + return result; + } + + // + bool IsBearish(double value) + { + // + bool result = false; + + // + result = ToState(value) == X3VWAP_STATE_BEARISH; + + // + return result; + } + + // + bool IsNeutural(double value) + { + // + bool result = false; + + // + result = ToState(value) == X3VWAP_STATE_NEUTURAL; + + // + return result; + } + + // + // Conditions ... + + // + bool GetConditions( + X3VWAPConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = true; + + // + if (loopback < 3) + { + loopback = 3; + } + + // + 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; + + // + // Buffers ... + + // + // Fast ... + CopyFast( + zIndex, + loopback, + conditions.fasts // + ); + CopyFastState( + zIndex, + loopback, + conditions.fastStates // + ); + + // + // Mid ... + CopyMid( + zIndex, + loopback, + conditions.mids // + ); + CopyMidState( + zIndex, + loopback, + conditions.midStates // + ); + + // + // Slow ... + CopySlow( + zIndex, + loopback, + conditions.slows // + ); + CopySlowState( + zIndex, + loopback, + conditions.slowStates // + ); + + // + // Conditions ... + + // + bool isFastBullish = IsBullish(conditions.fastStates[cIndex]); + bool isFastBullishPrev = IsBullish(conditions.fastStates[pIndex]); + + // + bool isFastBearish = IsBearish(conditions.fastStates[cIndex]); + bool isFastBearishPrev = IsBearish(conditions.fastStates[pIndex]); + + // + bool isFastNeutural = IsNeutural(conditions.fastStates[cIndex]); + bool isFastNeuturalPrev = IsNeutural(conditions.fastStates[pIndex]); + + // + bool isMidBullish = IsBullish(conditions.midStates[cIndex]); + bool isMidBullishPrev = IsBullish(conditions.midStates[pIndex]); + + // + bool isMidBearish = IsBearish(conditions.midStates[cIndex]); + bool isMidBearishPrev = IsBearish(conditions.midStates[pIndex]); + + // + bool isMidNeutural = IsNeutural(conditions.midStates[cIndex]); + bool isMidNeuturalPrev = IsNeutural(conditions.midStates[pIndex]); + + // + bool isSlowBullish = IsBullish(conditions.slowStates[cIndex]); + bool isSlowBullishPrev = IsBullish(conditions.slowStates[pIndex]); + + // + bool isSlowBearish = IsBearish(conditions.slowStates[cIndex]); + bool isSlowBearishPrev = IsBearish(conditions.slowStates[pIndex]); + + // + bool isSlowNeutural = IsNeutural(conditions.slowStates[cIndex]); + bool isSlowNeuturalPrev = IsNeutural(conditions.slowStates[pIndex]); + + // + bool isFastOverMid = + conditions.fasts[cIndex] > conditions.mids[cIndex]; + bool isFastOverMidPrev = + conditions.fasts[pIndex] > conditions.mids[pIndex]; + + // + bool isMidOverSlow = + conditions.mids[cIndex] > conditions.slows[cIndex]; + bool isMidOverSlowPrev = + conditions.mids[pIndex] > conditions.slows[pIndex]; + + // + bool isFastUnderMid = + conditions.fasts[cIndex] < conditions.mids[cIndex]; + bool isFastUnderMidPrev = + conditions.fasts[pIndex] < conditions.mids[pIndex]; + + // + bool isMidUnderSlow = + conditions.mids[cIndex] < conditions.slows[cIndex]; + bool isMidUnderSlowPrev = + conditions.mids[pIndex] < conditions.slows[pIndex]; + + // + bool isBullishState = isFastBullish && + isMidBullish && + isSlowBullish; + bool isBullishStatePrev = isFastBullishPrev && + isMidBullishPrev && + isSlowBullishPrev; + + // + bool isBearishState = isFastBearish && + isMidBearish && + isSlowBearish; + bool isBearishStatePrev = isFastBearishPrev && + isMidBearishPrev && + isSlowBearishPrev; + + // + bool isNeuturalState = isFastNeutural && + isMidNeutural && + isSlowNeutural; + bool isNeuturalStatePrev = isFastNeuturalPrev && + isMidNeuturalPrev && + isSlowNeuturalPrev; + + // + bool isBullishOrdered = isFastOverMid && + isMidOverSlow; + bool isBullishOrderedPrev = isFastOverMidPrev && + isMidOverSlowPrev; + + // + bool isBearishOrdered = isFastUnderMid && + isMidUnderSlow; + bool isBearishOrderedPrev = isFastUnderMidPrev && + isMidUnderSlowPrev; + + // + bool isSwitchedToBullishOrdered = isBullishOrdered && + !isBullishOrderedPrev; + bool isSwitchedToBearishOrdered = isBearishOrdered && + !isBearishOrderedPrev; + + // + bool isSwitchedToBullishState = isBullishState && + !isBullishStatePrev; + bool isSwitchedToBearishState = isBearishState && + !isBearishStatePrev; + bool isSwitchedToNeuturalState = isNeuturalState && + !isNeuturalStatePrev; + + // + conditions.isFastBullish = isFastBullish; + conditions.isFastBearish = isFastBearish; + conditions.isFastNeutural = isFastNeutural; + conditions.isMidBullish = isMidBullish; + conditions.isMidBearish = isMidBearish; + conditions.isMidNeutural = isMidNeutural; + conditions.isSlowBullish = isSlowBullish; + conditions.isSlowBearish = isSlowBearish; + conditions.isSlowNeutural = isSlowNeutural; + conditions.isFastOverMid = isFastOverMid; + conditions.isMidOverSlow = isMidOverSlow; + conditions.isFastUnderMid = isFastUnderMid; + conditions.isMidUnderSlow = isMidUnderSlow; + conditions.isBullishState = isBullishState; + conditions.isBearishState = isBearishState; + conditions.isNeuturalState = isNeuturalState; + conditions.isBullishOrdered = isBullishOrdered; + conditions.isBearishOrdered = isBearishOrdered; + conditions.isSwitchedToBullishOrdered = isSwitchedToBullishOrdered; + conditions.isSwitchedToBearishOrdered = isSwitchedToBearishOrdered; + conditions.isSwitchedToBullishState = isSwitchedToBullishState; + conditions.isSwitchedToBearishState = isSwitchedToBearishState; + conditions.isSwitchedToNeuturalState = isSwitchedToNeuturalState; + + // + return result; + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + X3VWAPInputs mInputs; // Inputs ... + + // + // Buffers ... + double fastBuffer[]; + double fastStateBuffer[]; + double midBuffer[]; + double midStateBuffer[]; + double slowBuffer[]; + double slowStateBuffer[]; + + // + // Tools ... + + // + // Calculate Values Until Now ... + void Calculate() + { + // + int totalBars = CountBars(); + if (totalBars > 1000) + { + totalBars = 1000; + } + + // + // Fast ... + CopyBuffer( + mHandler, + X3VWAP_FAST_LINE, + 0, + totalBars, + fastBuffer + // + ); + CopyBuffer( + mHandler, + X3VWAP_FAST_STATE_LINE, + 0, + totalBars, + fastStateBuffer + // + ); + + // + // Mid ... + CopyBuffer( + mHandler, + X3VWAP_MID_LINE, + 0, + totalBars, + midBuffer + // + ); + CopyBuffer( + mHandler, + X3VWAP_MID_STATE_LINE, + 0, + totalBars, + midStateBuffer + // + ); + + // + // Slow ... + CopyBuffer( + mHandler, + X3VWAP_SLOW_LINE, + 0, + totalBars, + slowBuffer + // + ); + CopyBuffer( + mHandler, + X3VWAP_SLOW_STATE_LINE, + 0, + totalBars, + slowStateBuffer + // + ); + } +}; + +// \ No newline at end of file diff --git a/BKPS/14031003/Helpers/x-saherelm.xcc.helper.mq5 b/BKPS/14031003/Helpers/x-saherelm.xcc.helper.mq5 new file mode 100644 index 0000000..485ce71 --- /dev/null +++ b/BKPS/14031003/Helpers/x-saherelm.xcc.helper.mq5 @@ -0,0 +1,245 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCXCCHelper +// 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 XCCInputs +{ + // + // 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) ... + XCCInputs() + { + // + 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; + } + + // + // 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 XCXCCHelper : public XCBaseHelper +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructors ... + XCXCCHelper() : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCXCCHelper() {} + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + XCCInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.xcc", + // + // Inputs ... + // + // Chart Style ... + "", + mInputs.mode, // Mode + mInputs.upColor, // Up Color + mInputs.downColor, // Down Color + mInputs.lineColor, // Line mode and Doji candlestick Color + mInputs.bearishColor, // Bullish Color + mInputs.bullishColor, // Bearish Color + mInputs.volumesColor, // Volumes Color + // + // Presentation ... + "", + mInputs.showCandles // Show Candles + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + XCCInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + XCCInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Props ... + XCCInputs mInputs; // Inputs ... +}; + +// +// Tools ... \ No newline at end of file diff --git a/BKPS/14031003/Helpers/x-saherelm.xchsar.helper.mq5 b/BKPS/14031003/Helpers/x-saherelm.xchsar.helper.mq5 new file mode 100644 index 0000000..de0a620 --- /dev/null +++ b/BKPS/14031003/Helpers/x-saherelm.xchsar.helper.mq5 @@ -0,0 +1,1267 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XCXCHSARHelper +// 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 ... + +// +enum ENUM_XCHSAR_BUFFERS +{ + // + // Current ... + XCHSAR_C_LINE = 0, + // + // Short ... + XCHSAR_S_LINE = 1, + // + // Medium ... + XCHSAR_M_LINE = 2, + // + // Long ... + XCHSAR_L_LINE = 3, + // + // Hind ... + XCHSAR_H_LINE = 4, +}; + +// +// Input Models ... +struct XCHSARInputs +{ + // + // Props ... + + // + // Market ... + double sarStep; // Step + double sarMax; // Maximum + + // + // Cycles ... + + // + // Short ... + ENUM_X_PERIOD_METHOD scMethod; // How to Find Period + ENUM_TIMEFRAMES scPeriod; // Time Period + + // + // Medium ... + ENUM_X_PERIOD_METHOD mcMethod; // How to Find Period + ENUM_TIMEFRAMES mcPeriod; // Time Period + + // + // Long ... + ENUM_X_PERIOD_METHOD lcMethod; // How to Find Period + ENUM_TIMEFRAMES lcPeriod; // Time Period + + // + // Hind ... + ENUM_X_PERIOD_METHOD hcMethod; // How to Find Period + ENUM_TIMEFRAMES hcPeriod; // Time Period + + // + // Presentation ... + + // + int cArrowCode; // Current Cycle Arrow Code + int sArrowCode; // Short Cycle Arrow Code + int mArrowCode; // Medium Cycle Arrow Code + int lArrowCode; // Long Cycle Arrow Code + int hArrowCode; // Hind Cycle Arrow Code + + // + bool showCurrent; // Show Current Cycle + bool showShort; // Show Short Cycle + bool showMedium; // Show Medium Cycle + bool showLong; // Show Long Cycle + bool showHind; // Show Hind Cycle + + // + // Constructor(s) ... + XCHSARInputs() + { + // + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + sarStep = 0.02; + sarMax = 0.2; + + // + scMethod = X_PERIOD_AUTO; + scPeriod = NULL; + mcMethod = X_PERIOD_AUTO; + mcPeriod = NULL; + lcMethod = X_PERIOD_AUTO; + lcPeriod = NULL; + hcMethod = X_PERIOD_AUTO; + hcPeriod = NULL; + + // + cArrowCode = 255; + sArrowCode = 255; + mArrowCode = 255; + lArrowCode = 255; + hArrowCode = 255; + + // + showCurrent = true; + showShort = true; + showMedium = true; + showLong = true; + showHind = true; + } + + // + // Default ... + void Default() + { + // + sarStep = 0.02; + sarMax = 0.2; + + // + scMethod = X_PERIOD_AUTO; + scPeriod = NULL; + mcMethod = X_PERIOD_AUTO; + mcPeriod = NULL; + lcMethod = X_PERIOD_AUTO; + lcPeriod = NULL; + hcMethod = X_PERIOD_AUTO; + hcPeriod = NULL; + + // + cArrowCode = 255; + sArrowCode = 255; + mArrowCode = 255; + lArrowCode = 255; + hArrowCode = 255; + + // + showCurrent = true; + showShort = true; + showMedium = true; + showLong = true; + showHind = true; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + sarStep > 0 && + sarMax > sarStep && + // + (IsValid(scMethod, scPeriod) && + IsValid(mcMethod, mcPeriod) && + IsValid(lcMethod, lcPeriod) && + IsValid(hcMethod, hcPeriod)) + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + return result; + } +}; + +// +// Define Conditions ... +struct XCHSARConditions +{ + // + // Common ... + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + // Buffers ... + + // + double cSars[]; + double sSars[]; + double mSars[]; + double lSars[]; + double hSars[]; + + // + // Conditions ... + + // + // Current ... + + // + bool isCBullish; + bool isCBearish; + + // + bool isCSwitchedBullish; + bool isCSwitchedBearish; + + // + // Short ... + + // + bool isSBullish; + bool isSBearish; + + // + bool isSSwitchedBullish; + bool isSSwitchedBearish; + + // + // Medium ... + + // + bool isMBullish; + bool isMBearish; + + // + bool isMSwitchedBullish; + bool isMSwitchedBearish; + + // + // Long ... + + // + bool isLBullish; + bool isLBearish; + + // + bool isLSwitchedBullish; + bool isLSwitchedBearish; + + // + // Hind ... + + // + bool isHBullish; + bool isHBearish; + + // + bool isHSwitchedBullish; + bool isHSwitchedBearish; + + // + void Clean() + { + // + Clean(cSars); + Clean(sSars); + Clean(mSars); + Clean(lSars); + Clean(hSars); + + // + ArraySetAsSeries(cSars, true); + ArraySetAsSeries(sSars, true); + ArraySetAsSeries(mSars, true); + ArraySetAsSeries(lSars, true); + ArraySetAsSeries(hSars, true); + + // + isCBullish = false; + isCBearish = false; + isCSwitchedBullish = false; + isCSwitchedBearish = false; + isSBullish = false; + isSBearish = false; + isSSwitchedBullish = false; + isSSwitchedBearish = false; + isMBullish = false; + isMBearish = false; + isMSwitchedBullish = false; + isMSwitchedBearish = false; + isLBullish = false; + isLBearish = false; + isLSwitchedBullish = false; + isLSwitchedBearish = false; + isHBullish = false; + isHBearish = false; + isHSwitchedBullish = false; + isHSwitchedBearish = false; + } + + // + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + // + bullishScore = 0; + bearishScore = 0; + + // + // Current ... + if (isCBullish) + { + bullishScore++; + } + if (isCSwitchedBullish) + { + bullishScore++; + } + if (isCBearish) + { + bearishScore++; + } + if (isCSwitchedBearish) + { + bearishScore++; + } + + // + // Short ... + if (isSBullish) + { + bullishScore++; + } + if (isSSwitchedBullish) + { + bullishScore++; + } + if (isSBearish) + { + bearishScore++; + } + if (isSSwitchedBearish) + { + bearishScore++; + } + + // + // Medium ... + if (isMBullish) + { + bullishScore++; + } + if (isMSwitchedBullish) + { + bullishScore++; + } + if (isMBearish) + { + bearishScore++; + } + if (isMSwitchedBearish) + { + bearishScore++; + } + + // + // Long ... + if (isLBullish) + { + bullishScore++; + } + if (isLSwitchedBullish) + { + bullishScore++; + } + if (isLBearish) + { + bearishScore++; + } + if (isLSwitchedBearish) + { + bearishScore++; + } + + // + // Hind ... + if (isHBullish) + { + bullishScore++; + } + if (isHSwitchedBullish) + { + bullishScore++; + } + if (isHBearish) + { + bearishScore++; + } + if (isHSwitchedBearish) + { + bearishScore++; + } + } + + // + 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 = + // + // Current ... + ToString("isCBullish", isCBullish, ignoreFalseConditions, separator) + + ToString("isCBearish", isCBearish, ignoreFalseConditions, separator) + + ToString("isCSwitchedBullish", isCSwitchedBullish, ignoreFalseConditions, separator) + + ToString("isCSwitchedBearish", isCSwitchedBearish, ignoreFalseConditions, separator) + + // + // Short ... + ToString("isSBullish", isSBullish, ignoreFalseConditions, separator) + + ToString("isSBearish", isSBearish, ignoreFalseConditions, separator) + + ToString("isSSwitchedBullish", isSSwitchedBullish, ignoreFalseConditions, separator) + + ToString("isSSwitchedBearish", isSSwitchedBearish, ignoreFalseConditions, separator) + + // + // Medium ... + ToString("isMBullish", isMBullish, ignoreFalseConditions, separator) + + ToString("isMBearish", isMBearish, ignoreFalseConditions, separator) + + ToString("isMSwitchedBullish", isMSwitchedBullish, ignoreFalseConditions, separator) + + ToString("isMSwitchedBearish", isMSwitchedBearish, ignoreFalseConditions, separator) + + // + // Long ... + ToString("isLBullish", isLBullish, ignoreFalseConditions, separator) + + ToString("isLBearish", isLBearish, ignoreFalseConditions, separator) + + ToString("isLSwitchedBullish", isLSwitchedBullish, ignoreFalseConditions, separator) + + ToString("isLSwitchedBearish", isLSwitchedBearish, ignoreFalseConditions, separator) + + // + // Hind ... + ToString("isHBullish", isHBullish, ignoreFalseConditions, separator) + + ToString("isHBearish", isHBearish, ignoreFalseConditions, separator) + + ToString("isHSwitchedBullish", isHSwitchedBullish, ignoreFalseConditions, separator) + + ToString("isHSwitchedBearish", isHSwitchedBearish, ignoreFalseConditions, separator) + + // + "" + // + ; + + // + result = + // + "[" + GetTag() + "]" + separator + + (onlyConditions + ? "" + : commonStr) + + (!includeScores + ? "" + : scoresStr) + + " " + separator + + (onlyCommons + ? "" + : conditionsStr) + + "" + // + ; + + // + return result; + } + + // + string GetTag() + { + return "XCHSAR"; + } +}; + +// +// Class ... +class XCXCHSARHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructors ... + XCXCHSARHelper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCXCHSARHelper() + { + } + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + XCHSARInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + ArraySetAsSeries(cBuffer, true); + ArraySetAsSeries(sBuffer, true); + ArraySetAsSeries(mBuffer, true); + ArraySetAsSeries(lBuffer, true); + ArraySetAsSeries(hBuffer, true); + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.xchsar", + // + // Inputs ... + // + // Market ... + "", + mInputs.sarStep, + mInputs.sarMax, + // + // Cycles ... + "", + // + // Short ... + "", + mInputs.scMethod, + mInputs.scPeriod, + // + // Medium ... + "", + mInputs.mcMethod, + mInputs.mcPeriod, + // + // Long ... + "", + mInputs.lcMethod, + mInputs.lcPeriod, + // + // Hind ... + "", + mInputs.hcMethod, + mInputs.hcPeriod, + // + // Presentation ... + "", + mInputs.cArrowCode, + mInputs.sArrowCode, + mInputs.mArrowCode, + mInputs.lArrowCode, + mInputs.hArrowCode, + mInputs.showCurrent, + mInputs.showShort, + mInputs.showMedium, + mInputs.showLong, + mInputs.showHind + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + XCHSARInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + XCHSARInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Buffers ... + + // + // Current ... + + // + double GetC( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(cBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return cBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyC( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + cBuffer, + buffer, + forceClean + // + ); + } + + // + // Short ... + + // + double GetS( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(sBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return sBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyS( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + sBuffer, + buffer, + forceClean + // + ); + } + + // + // Medium ... + + // + double GetM( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(mBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return mBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyM( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + mBuffer, + buffer, + forceClean + // + ); + } + + // + // Long ... + + // + double GetL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(lBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return lBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + lBuffer, + buffer, + forceClean + // + ); + } + + // + // Hind ... + + // + double GetH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(hBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + hBuffer, + buffer, + forceClean + // + ); + } + + // + bool GetConditions( + XCHSARConditions &conditions, // + int barIndex = 0, // + int loopback = 3 // + ) + { + // + bool result = true; + + // + if (loopback < 3) + { + loopback = 3; + } + + // + 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; + + // + // Buffers ... + + // + // Current ... + CopyC( + zIndex, + loopback, + conditions.cSars // + ); + + // + // Short ... + CopyS( + zIndex, + loopback, + conditions.sSars // + ); + + // + // Medium ... + CopyM( + zIndex, + loopback, + conditions.mSars // + ); + + // + // Long ... + CopyL( + zIndex, + loopback, + conditions.lSars // + ); + + // + // Hind ... + CopyH( + zIndex, + loopback, + conditions.hSars // + ); + + // + // Conditions ... + + // + XOHCL cBar; + result = cBar.Init( + mSymbol, + mPeriod, + cIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL pBar; + result = pBar.Init( + mSymbol, + mPeriod, + pIndex // + ); + if (!result) + { + return result; + } + double hhValue = pBar.FindHighest( + loopback, + MODE_HIGH // + ); + double llValue = pBar.FindLowest( + loopback, + MODE_LOW // + ); + + // + // Current ... + + // + bool isCBullish = conditions.cSars[cIndex] < cBar.low; + bool isCBullishPrev = conditions.cSars[pIndex] < pBar.low; + + // + bool isCBearish = conditions.cSars[cIndex] > cBar.high; + bool isCBearishPrev = conditions.cSars[pIndex] > pBar.high; + + // + bool isCSwitchedBullish = isCBullish && + !isCBullishPrev; + bool isCSwitchedBearish = isCBearish && + !isCBearishPrev; + + // + conditions.isCBullish = isCBullish; + conditions.isCBearish = isCBearish; + conditions.isCSwitchedBullish = isCSwitchedBullish; + conditions.isCSwitchedBearish = isCSwitchedBearish; + + // + // Short ... + + // + bool isSBullish = conditions.sSars[cIndex] < cBar.low; + bool isSBullishPrev = conditions.sSars[pIndex] < pBar.low; + + // + bool isSBearish = conditions.sSars[cIndex] > cBar.high; + bool isSBearishPrev = conditions.sSars[pIndex] > pBar.high; + + // + bool isSSwitchedBullish = isSBullish && + !isSBullishPrev; + bool isSSwitchedBearish = isSBearish && + !isSBearishPrev; + + // + conditions.isSBullish = isSBullish; + conditions.isSBearish = isSBearish; + conditions.isSSwitchedBullish = isSSwitchedBullish; + conditions.isSSwitchedBearish = isSSwitchedBearish; + + // + // Medium ... + + // + bool isMBullish = conditions.mSars[cIndex] < cBar.low; + bool isMBullishPrev = conditions.mSars[pIndex] < pBar.low; + + // + bool isMBearish = conditions.mSars[cIndex] > cBar.high; + bool isMBearishPrev = conditions.mSars[pIndex] > pBar.high; + + // + bool isMSwitchedBullish = isMBullish && + !isMBullishPrev; + bool isMSwitchedBearish = isMBearish && + !isMBearishPrev; + + // + conditions.isMBullish = isMBullish; + conditions.isMBearish = isMBearish; + conditions.isMSwitchedBullish = isMSwitchedBullish; + conditions.isMSwitchedBearish = isMSwitchedBearish; + + // + // Long ... + + // + bool isLBullish = conditions.lSars[cIndex] < cBar.low; + bool isLBullishPrev = conditions.lSars[pIndex] < pBar.low; + + // + bool isLBearish = conditions.lSars[cIndex] > cBar.high; + bool isLBearishPrev = conditions.lSars[pIndex] > pBar.high; + + // + bool isLSwitchedBullish = isLBullish && + !isLBullishPrev; + bool isLSwitchedBearish = isLBearish && + !isLBearishPrev; + + // + conditions.isLBullish = isLBullish; + conditions.isLBearish = isLBearish; + conditions.isLSwitchedBullish = isLSwitchedBullish; + conditions.isLSwitchedBearish = isLSwitchedBearish; + + // + // Hind ... + + // + bool isHBullish = conditions.hSars[cIndex] < cBar.low; + bool isHBullishPrev = conditions.hSars[pIndex] < pBar.low; + + // + bool isHBearish = conditions.hSars[cIndex] > cBar.high; + bool isHBearishPrev = conditions.hSars[pIndex] > pBar.high; + + // + bool isHSwitchedBullish = isHBullish && + !isHBullishPrev; + bool isHSwitchedBearish = isHBearish && + !isHBearishPrev; + + // + conditions.isHBullish = isHBullish; + conditions.isHBearish = isHBearish; + conditions.isHSwitchedBullish = isHSwitchedBullish; + conditions.isHSwitchedBearish = isHSwitchedBearish; + + // + return result; + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + XCHSARInputs mInputs; // Inputs ... + + // + // Buffers ... + + // + double cBuffer[]; + double sBuffer[]; + double mBuffer[]; + double lBuffer[]; + double hBuffer[]; + + // + // Tools ... + + // + // Calculate Values Until Now ... + void Calculate() + { + // + int totalBars = CountBars(); + if (totalBars > 1000) + { + totalBars = 1000; + } + + // + // Current ... + CopyBuffer( + mHandler, + XCHSAR_C_LINE, + 0, + totalBars, + cBuffer + // + ); + + // + // Short ... + CopyBuffer( + mHandler, + XCHSAR_S_LINE, + 0, + totalBars, + sBuffer + // + ); + + // + // Medium ... + CopyBuffer( + mHandler, + XCHSAR_S_LINE, + 0, + totalBars, + mBuffer + // + ); + + // + // Long ... + CopyBuffer( + mHandler, + XCHSAR_S_LINE, + 0, + totalBars, + lBuffer + // + ); + + // + // Hind ... + CopyBuffer( + mHandler, + XCHSAR_S_LINE, + 0, + totalBars, + hBuffer + // + ); + } +}; + +// \ No newline at end of file diff --git a/BKPS/14031003/Helpers/x-saherelm.xct.helper.mq5 b/BKPS/14031003/Helpers/x-saherelm.xct.helper.mq5 new file mode 100644 index 0000000..2bd7ced --- /dev/null +++ b/BKPS/14031003/Helpers/x-saherelm.xct.helper.mq5 @@ -0,0 +1,230 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCXCTHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.x-helper.class.mq5" + +// +// Definitions ... + +// +// Input Models ... +struct XCTInputs +{ + // + // 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) ... + XCTInputs() + { + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + font = NULL; + fontSize = 15; + clr = CLR_NONE; + corner = CORNER_RIGHT_LOWER; + + // + // Presentation ... + showCandleTime = false; + } + + // + // 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 XCXCTHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructors ... + XCXCTHelper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCXCTHelper() + { + } + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + XCTInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.xct", + // + // Inputs ... + mInputs.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 ... + + // + XCTInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + XCTInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + XCTInputs mInputs; // Inputs ... +}; + +// +// Tools ... \ No newline at end of file diff --git a/BKPS/14031003/Helpers/x-saherelm.xpv.helper.mq5 b/BKPS/14031003/Helpers/x-saherelm.xpv.helper.mq5 new file mode 100644 index 0000000..5cad913 --- /dev/null +++ b/BKPS/14031003/Helpers/x-saherelm.xpv.helper.mq5 @@ -0,0 +1,3237 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCXPVHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.x-helper.class.mq5" + +// +// Definitions ... + +// +enum ENUM_XPV_BUFFERS +{ + // + // Peaks and Vales ... + XPV_PEAKS_LINE = 0, + XPV_VALES_LINE = 1, + // + // Support and Resistances ... + XPV_RESISTANCE_LINE = 2, + XPV_SUPPORT_LINE = 4, + // + // Fibonacci ... + XPV_FIB_1_LINE = 6, + XPV_FIB_2_LINE = 8, + XPV_FIB_3_LINE = 10, + XPV_FIB_4_LINE = 12, + XPV_FIB_5_LINE = 14, + // + // Short ... + XPV_SC_HH_LINE = 16, + XPV_SC_LL_LINE = 18, + // + // Medium ... + XPV_MC_HH_LINE = 20, + XPV_MC_LL_LINE = 22, + // + // Long ... + XPV_LC_HH_LINE = 24, + XPV_LC_LL_LINE = 26, + // + // Hind ... + XPV_HC_HH_LINE = 28, + XPV_HC_LL_LINE = 30, +}; + +// +// Input Models ... +struct XPVInputs +{ + // + // Props ... + + // + // Makret Cycles ... + + // + // Short ... + ENUM_X_PERIOD_METHOD scMethod; // How to Find Period + ENUM_TIMEFRAMES scPeriod; // Time Period + + // + // Medium ... + ENUM_X_PERIOD_METHOD mcMethod; // How to Find Period + ENUM_TIMEFRAMES mcPeriod; // Time Period + + // + // Long ... + ENUM_X_PERIOD_METHOD lcMethod; // How to Find Period + ENUM_TIMEFRAMES lcPeriod; // Time Period + + // + // Hind ... + ENUM_X_PERIOD_METHOD hcMethod; // How to Find Period + ENUM_TIMEFRAMES hcPeriod; // Time Period + + // + // Fibonacci ... + double fiboLevel1; // Fibio 1st Level + double fiboLevel2; // Fibio 2st Level + double fiboLevel3; // Fibio 3rd Level + double fiboLevel4; // Fibio 4th Level + double fiboLevel5; // Fibio 5th Level + + // + // Boundary Detection Modes ... + ENUM_SERIESMODE hhMode; // Highest High Calculation Method + ENUM_SERIESMODE llMode; // Lowest Low Calculation Method + + // + // Presentation ... + bool showPeaksAndVales; // Show Peaks and Vales + bool showLevels; // Show Levels + bool showConsolidations; // Show Consolidations + bool showFibo1Levels; // Show Fibo 1st Level + bool showFibo2Levels; // Show Fibo 2nd Level + bool showFibo3Levels; // Show Fibo 3rd Level + bool showFibo4Levels; // Show Fibo 4th Level + bool showFibo5Levels; // Show Fibo 5th Level + + // + // Constructor(s) ... + XPVInputs() + { + // + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + // Makret Cycles ... + + // + // Short ... + scMethod = X_PERIOD_NOTHING; + scPeriod = NULL; + + // + // Medium ... + mcMethod = X_PERIOD_NOTHING; + mcPeriod = NULL; + + // + // Long ... + lcMethod = X_PERIOD_NOTHING; + lcPeriod = NULL; + + // + // Hind ... + hcMethod = X_PERIOD_NOTHING; + hcPeriod = NULL; + + // + // Fibonacci ... + fiboLevel1 = 0; + fiboLevel2 = 0; + fiboLevel3 = 0; + fiboLevel4 = 0; + fiboLevel5 = 0; + + // + // Boundary Detection Modes ... + hhMode = MODE_HIGH; + llMode = MODE_LOW; + + // + // Presentation ... + showPeaksAndVales = false; + showLevels = false; + showConsolidations = false; + showFibo1Levels = false; + showFibo2Levels = false; + showFibo3Levels = false; + showFibo4Levels = false; + showFibo5Levels = false; + } + + // + // Default ... + void Default() + { + // + // Makret Cycles ... + + // + // Short ... + scMethod = X_PERIOD_AUTO; + scPeriod = NULL; + + // + // Medium ... + mcMethod = X_PERIOD_AUTO; + mcPeriod = NULL; + + // + // Long ... + lcMethod = X_PERIOD_AUTO; + lcPeriod = NULL; + + // + // Hind ... + hcMethod = X_PERIOD_AUTO; + hcPeriod = NULL; + + // + // Fibonacci ... + fiboLevel1 = 0.236; + fiboLevel2 = 0.382; + fiboLevel3 = 0.5; + fiboLevel4 = 0.618; + fiboLevel5 = 0.764; + + // + // Boundary Detection Modes ... + hhMode = MODE_HIGH; + llMode = MODE_LOW; + + // + // Presentation ... + showPeaksAndVales = true; + showLevels = false; + showConsolidations = false; + showFibo1Levels = true; + showFibo2Levels = true; + showFibo3Levels = true; + showFibo4Levels = true; + showFibo5Levels = true; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsValid(scMethod, scPeriod) && + IsValid(mcMethod, mcPeriod) && + IsValid(lcMethod, lcPeriod) && + IsValid(hcMethod, hcPeriod) + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(result, 0); + + // + return result; + } +}; + +// +// Conditions ... +struct XPVConditions +{ + // + // Common ... + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + // Buffers ... + double peaks[]; + double vales[]; + double resistances[]; + double supports[]; + double fib1s[]; + double fib2s[]; + double fib3s[]; + double fib4s[]; + double fib5s[]; + double sCHHs[]; + double sCLLs[]; + double mCHHs[]; + double mCLLs[]; + double lCHHs[]; + double lCLLs[]; + double hCHHs[]; + double hCLLs[]; + + // + // Conditions ... + + // + bool isNewPeak; + bool isNewPeakOverLast; + bool isNewPeakUnderLast; + + // + bool isNewVale; + bool isNewValeOverLast; + bool isNewValeUnderLast; + + // + bool isFiboIncreased; + bool isFiboDecreased; + bool isFiboSectionChanged; + + // + // SC ... + + // + bool isSCBullish; + bool isSCHHBullish; + bool isSCLLBullish; + bool isSCSwitchedToBullish; + bool isSCHHSwitchedToBullish; + bool isSCLLSwitchedToBullish; + + // + bool isSCBearish; + bool isSCHHBearish; + bool isSCLLBearish; + bool isSCSwitchedToBearish; + bool isSCHHSwitchedToBearish; + bool isSCLLSwitchedToBeraish; + + // + // MC ... + + // + bool isMCBullish; + bool isMCHHBullish; + bool isMCLLBullish; + bool isMCSwitchedToBullish; + bool isMCHHSwitchedToBullish; + bool isMCLLSwitchedToBullish; + + // + bool isMCBearish; + bool isMCHHBearish; + bool isMCLLBearish; + bool isMCSwitchedToBearish; + bool isMCHHSwitchedToBearish; + bool isMCLLSwitchedToBeraish; + + // + // LC ... + + // + bool isLCBullish; + bool isLCHHBullish; + bool isLCLLBullish; + bool isLCSwitchedToBullish; + bool isLCHHSwitchedToBullish; + bool isLCLLSwitchedToBullish; + // + bool isLCBearish; + bool isLCHHBearish; + bool isLCLLBearish; + bool isLCSwitchedToBearish; + bool isLCHHSwitchedToBearish; + bool isLCLLSwitchedToBeraish; + + // + // HC ... + + // + bool isHCBullish; + bool isHCHHBullish; + bool isHCLLBullish; + bool isHCSwitchedToBullish; + bool isHCHHSwitchedToBullish; + bool isHCLLSwitchedToBullish; + + // + bool isHCBearish; + bool isHCHHBearish; + bool isHCLLBearish; + bool isHCSwitchedToBearish; + bool isHCHHSwitchedToBearish; + bool isHCLLSwitchedToBeraish; + + // + // Fibonachi Conditions ... + + // + bool isCloseOverFib1; + bool isCloseOverFib2; + bool isCloseOverFib3; + bool isCloseOverFib4; + bool isCloseOverFib5; + + // + bool isCloseUnderFib1; + bool isCloseUnderFib2; + bool isCloseUnderFib3; + bool isCloseUnderFib4; + bool isCloseUnderFib5; + + // + bool isCloseCrossedOverFib1; + bool isCloseCrossedOverFib2; + bool isCloseCrossedOverFib3; + bool isCloseCrossedOverFib4; + bool isCloseCrossedOverFib5; + + // + bool isCloseCrossedUnderFib1; + bool isCloseCrossedUnderFib2; + bool isCloseCrossedUnderFib3; + bool isCloseCrossedUnderFib4; + bool isCloseCrossedUnderFib5; + + // + void Clean() + { + // + Clean(peaks); + Clean(vales); + Clean(resistances); + Clean(supports); + Clean(fib1s); + Clean(fib2s); + Clean(fib3s); + Clean(fib4s); + Clean(fib5s); + Clean(sCHHs); + Clean(sCLLs); + Clean(mCHHs); + Clean(mCLLs); + Clean(lCHHs); + Clean(lCLLs); + Clean(hCHHs); + Clean(hCLLs); + + // + ArraySetAsSeries(peaks, true); + ArraySetAsSeries(vales, true); + ArraySetAsSeries(resistances, true); + ArraySetAsSeries(supports, true); + ArraySetAsSeries(fib1s, true); + ArraySetAsSeries(fib2s, true); + ArraySetAsSeries(fib3s, true); + ArraySetAsSeries(fib4s, true); + ArraySetAsSeries(fib5s, true); + ArraySetAsSeries(sCHHs, true); + ArraySetAsSeries(sCLLs, true); + ArraySetAsSeries(mCHHs, true); + ArraySetAsSeries(mCLLs, true); + ArraySetAsSeries(lCHHs, true); + ArraySetAsSeries(lCLLs, true); + ArraySetAsSeries(hCHHs, true); + ArraySetAsSeries(hCLLs, true); + + // + isNewPeak = false; + isNewPeakOverLast = false; + isNewPeakUnderLast = false; + isNewVale = false; + isNewValeOverLast = false; + isNewValeUnderLast = false; + isFiboIncreased = false; + isFiboDecreased = false; + isFiboSectionChanged = false; + isCloseOverFib1 = false; + isCloseOverFib2 = false; + isCloseOverFib3 = false; + isCloseOverFib4 = false; + isCloseOverFib5 = false; + isCloseUnderFib1 = false; + isCloseUnderFib2 = false; + isCloseUnderFib3 = false; + isCloseUnderFib4 = false; + isCloseUnderFib5 = false; + isCloseCrossedOverFib1 = false; + isCloseCrossedOverFib2 = false; + isCloseCrossedOverFib3 = false; + isCloseCrossedOverFib4 = false; + isCloseCrossedOverFib5 = false; + isCloseCrossedUnderFib1 = false; + isCloseCrossedUnderFib2 = false; + isCloseCrossedUnderFib3 = false; + isCloseCrossedUnderFib4 = false; + isCloseCrossedUnderFib5 = false; + isSCBullish = false; + isSCHHBullish = false; + isSCLLBullish = false; + isSCSwitchedToBullish = false; + isSCHHSwitchedToBullish = false; + isSCLLSwitchedToBullish = false; + isSCBearish = false; + isSCHHBearish = false; + isSCLLBearish = false; + isSCSwitchedToBearish = false; + isSCHHSwitchedToBearish = false; + isSCLLSwitchedToBeraish = false; + isMCBullish = false; + isMCHHBullish = false; + isMCLLBullish = false; + isMCSwitchedToBullish = false; + isMCHHSwitchedToBullish = false; + isMCLLSwitchedToBullish = false; + isMCBearish = false; + isMCHHBearish = false; + isMCLLBearish = false; + isMCSwitchedToBearish = false; + isMCHHSwitchedToBearish = false; + isMCLLSwitchedToBeraish = false; + isLCBullish = false; + isLCHHBullish = false; + isLCLLBullish = false; + isLCSwitchedToBullish = false; + isLCHHSwitchedToBullish = false; + isLCLLSwitchedToBullish = false; + isLCBearish = false; + isLCHHBearish = false; + isLCLLBearish = false; + isLCSwitchedToBearish = false; + isLCHHSwitchedToBearish = false; + isLCLLSwitchedToBeraish = false; + isHCBullish = false; + isHCHHBullish = false; + isHCLLBullish = false; + isHCSwitchedToBullish = false; + isHCHHSwitchedToBullish = false; + isHCLLSwitchedToBullish = false; + isHCBearish = false; + isHCHHBearish = false; + isHCLLBearish = false; + isHCSwitchedToBearish = false; + isHCHHSwitchedToBearish = false; + isHCLLSwitchedToBeraish = false; + } + + // + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + // + bullishScore = 0; + bearishScore = 0; + + // + if (isNewPeak) + { + } + if (isNewPeakOverLast) + { + } + if (isNewPeakUnderLast) + { + } + + // + if (isNewVale) + { + } + if (isNewValeOverLast) + { + } + if (isNewValeUnderLast) + { + } + + // + if (isFiboIncreased) + { + } + if (isFiboDecreased) + { + } + if (isFiboSectionChanged) + { + } + + // + if (isSCBullish) + { + bullishScore++; + } + if (isSCHHBullish) + { + bullishScore++; + } + if (isSCLLBullish) + { + bullishScore++; + } + if (isSCSwitchedToBullish) + { + bullishScore++; + } + if (isSCHHSwitchedToBullish) + { + bullishScore++; + } + if (isSCLLSwitchedToBullish) + { + bullishScore++; + } + + // + if (isSCBearish) + { + bearishScore++; + } + if (isSCHHBearish) + { + bearishScore++; + } + if (isSCLLBearish) + { + bearishScore++; + } + if (isSCSwitchedToBearish) + { + bearishScore++; + } + if (isSCHHSwitchedToBearish) + { + bearishScore++; + } + if (isSCLLSwitchedToBeraish) + { + bearishScore++; + } + + // + if (isMCBullish) + { + bullishScore++; + } + if (isMCHHBullish) + { + bullishScore++; + } + if (isMCLLBullish) + { + bullishScore++; + } + if (isMCSwitchedToBullish) + { + bullishScore++; + } + if (isMCHHSwitchedToBullish) + { + bullishScore++; + } + if (isMCLLSwitchedToBullish) + { + bullishScore++; + } + + // + if (isMCBearish) + { + bearishScore++; + } + if (isMCHHBearish) + { + bearishScore++; + } + if (isMCLLBearish) + { + bearishScore++; + } + if (isMCSwitchedToBearish) + { + bearishScore++; + } + if (isMCHHSwitchedToBearish) + { + bearishScore++; + } + if (isMCLLSwitchedToBeraish) + { + bearishScore++; + } + + // + if (isLCBullish) + { + bullishScore++; + } + if (isLCHHBullish) + { + bullishScore++; + } + if (isLCLLBullish) + { + bullishScore++; + } + if (isLCSwitchedToBullish) + { + bullishScore++; + } + if (isLCHHSwitchedToBullish) + { + bullishScore++; + } + if (isLCLLSwitchedToBullish) + { + bullishScore++; + } + + // + if (isLCBearish) + { + bearishScore++; + } + if (isLCHHBearish) + { + bearishScore++; + } + if (isLCLLBearish) + { + bearishScore++; + } + if (isLCSwitchedToBearish) + { + bearishScore++; + } + if (isLCHHSwitchedToBearish) + { + bearishScore++; + } + if (isLCLLSwitchedToBeraish) + { + bearishScore++; + } + + if (isHCBullish) + { + bullishScore++; + } + if (isHCHHBullish) + { + bullishScore++; + } + if (isHCLLBullish) + { + bullishScore++; + } + if (isHCSwitchedToBullish) + { + bullishScore++; + } + if (isHCHHSwitchedToBullish) + { + bullishScore++; + } + if (isHCLLSwitchedToBullish) + { + bullishScore++; + } + + // + if (isHCBearish) + { + bearishScore++; + } + if (isHCHHBearish) + { + bearishScore++; + } + if (isHCLLBearish) + { + bearishScore++; + } + if (isHCSwitchedToBearish) + { + bearishScore++; + } + if (isHCHHSwitchedToBearish) + { + bearishScore++; + } + if (isHCLLSwitchedToBeraish) + { + bearishScore++; + } + } + + // + 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 = + // + ToString("isNewPeak", isNewPeak, ignoreFalseConditions, separator) + + ToString("isNewPeakOverLast", isNewPeakOverLast, ignoreFalseConditions, separator) + + ToString("isNewPeakUnderLast", isNewPeakUnderLast, ignoreFalseConditions, separator) + + ToString("isNewVale", isNewVale, ignoreFalseConditions, separator) + + ToString("isNewValeOverLast", isNewValeOverLast, ignoreFalseConditions, separator) + + ToString("isNewValeUnderLast", isNewValeUnderLast, ignoreFalseConditions, separator) + + ToString("isFiboIncreased", isFiboIncreased, ignoreFalseConditions, separator) + + ToString("isFiboDecreased", isFiboDecreased, ignoreFalseConditions, separator) + + ToString("isFiboSectionChanged", isFiboSectionChanged, ignoreFalseConditions, separator) + + ToString("isCloseOverFib1", isCloseOverFib1, ignoreFalseConditions, separator) + + ToString("isCloseOverFib2", isCloseOverFib2, ignoreFalseConditions, separator) + + ToString("isCloseOverFib3", isCloseOverFib3, ignoreFalseConditions, separator) + + ToString("isCloseOverFib4", isCloseOverFib4, ignoreFalseConditions, separator) + + ToString("isCloseOverFib5", isCloseOverFib5, ignoreFalseConditions, separator) + + ToString("isCloseUnderFib1", isCloseUnderFib1, ignoreFalseConditions, separator) + + ToString("isCloseUnderFib2", isCloseUnderFib2, ignoreFalseConditions, separator) + + ToString("isCloseUnderFib3", isCloseUnderFib3, ignoreFalseConditions, separator) + + ToString("isCloseUnderFib4", isCloseUnderFib4, ignoreFalseConditions, separator) + + ToString("isCloseUnderFib5", isCloseUnderFib5, ignoreFalseConditions, separator) + + ToString("isCloseCrossedOverFib1", isCloseCrossedOverFib1, ignoreFalseConditions, separator) + + ToString("isCloseCrossedOverFib2", isCloseCrossedOverFib2, ignoreFalseConditions, separator) + + ToString("isCloseCrossedOverFib3", isCloseCrossedOverFib3, ignoreFalseConditions, separator) + + ToString("isCloseCrossedOverFib4", isCloseCrossedOverFib4, ignoreFalseConditions, separator) + + ToString("isCloseCrossedOverFib5", isCloseCrossedOverFib5, ignoreFalseConditions, separator) + + ToString("isCloseCrossedUnderFib1", isCloseCrossedUnderFib1, ignoreFalseConditions, separator) + + ToString("isCloseCrossedUnderFib2", isCloseCrossedUnderFib2, ignoreFalseConditions, separator) + + ToString("isCloseCrossedUnderFib3", isCloseCrossedUnderFib3, ignoreFalseConditions, separator) + + ToString("isCloseCrossedUnderFib4", isCloseCrossedUnderFib4, ignoreFalseConditions, separator) + + ToString("isCloseCrossedUnderFib5", isCloseCrossedUnderFib5, ignoreFalseConditions, separator) + + ToString("isSCBullish", isSCBullish, ignoreFalseConditions, separator) + + ToString("isSCHHBullish", isSCHHBullish, ignoreFalseConditions, separator) + + ToString("isSCLLBullish", isSCLLBullish, ignoreFalseConditions, separator) + + ToString("isSCSwitchedToBullish", isSCSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isSCHHSwitchedToBullish", isSCHHSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isSCLLSwitchedToBullish", isSCLLSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isSCBearish", isSCBearish, ignoreFalseConditions, separator) + + ToString("isSCHHBearish", isSCHHBearish, ignoreFalseConditions, separator) + + ToString("isSCLLBearish", isSCLLBearish, ignoreFalseConditions, separator) + + ToString("isSCSwitchedToBearish", isSCSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isSCHHSwitchedToBearish", isSCHHSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isSCLLSwitchedToBeraish", isSCLLSwitchedToBeraish, ignoreFalseConditions, separator) + + ToString("isMCBullish", isMCBullish, ignoreFalseConditions, separator) + + ToString("isMCHHBullish", isMCHHBullish, ignoreFalseConditions, separator) + + ToString("isMCLLBullish", isMCLLBullish, ignoreFalseConditions, separator) + + ToString("isMCSwitchedToBullish", isMCSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isMCHHSwitchedToBullish", isMCHHSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isMCLLSwitchedToBullish", isMCLLSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isMCBearish", isMCBearish, ignoreFalseConditions, separator) + + ToString("isMCHHBearish", isMCHHBearish, ignoreFalseConditions, separator) + + ToString("isMCLLBearish", isMCLLBearish, ignoreFalseConditions, separator) + + ToString("isMCSwitchedToBearish", isMCSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isMCHHSwitchedToBearish", isMCHHSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isMCLLSwitchedToBeraish", isMCLLSwitchedToBeraish, ignoreFalseConditions, separator) + + ToString("isLCBullish", isLCBullish, ignoreFalseConditions, separator) + + ToString("isLCHHBullish", isLCHHBullish, ignoreFalseConditions, separator) + + ToString("isLCLLBullish", isLCLLBullish, ignoreFalseConditions, separator) + + ToString("isLCSwitchedToBullish", isLCSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isLCHHSwitchedToBullish", isLCHHSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isLCLLSwitchedToBullish", isLCLLSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isLCBearish", isLCBearish, ignoreFalseConditions, separator) + + ToString("isLCHHBearish", isLCHHBearish, ignoreFalseConditions, separator) + + ToString("isLCLLBearish", isLCLLBearish, ignoreFalseConditions, separator) + + ToString("isLCSwitchedToBearish", isLCSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isLCHHSwitchedToBearish", isLCHHSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isLCLLSwitchedToBeraish", isLCLLSwitchedToBeraish, ignoreFalseConditions, separator) + + ToString("isHCBullish", isHCBullish, ignoreFalseConditions, separator) + + ToString("isHCHHBullish", isHCHHBullish, ignoreFalseConditions, separator) + + ToString("isHCLLBullish", isHCLLBullish, ignoreFalseConditions, separator) + + ToString("isHCSwitchedToBullish", isHCSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isHCHHSwitchedToBullish", isHCHHSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isHCLLSwitchedToBullish", isHCLLSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isHCBearish", isHCBearish, ignoreFalseConditions, separator) + + ToString("isHCHHBearish", isHCHHBearish, ignoreFalseConditions, separator) + + ToString("isHCLLBearish", isHCLLBearish, ignoreFalseConditions, separator) + + ToString("isHCSwitchedToBearish", isHCSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isHCHHSwitchedToBearish", isHCHHSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isHCLLSwitchedToBeraish", isHCLLSwitchedToBeraish, ignoreFalseConditions, separator) + + // + "" + // + ; + + // + result = + // + "[" + GetTag() + "]" + separator + + (onlyConditions + ? "" + : commonStr) + + (!includeScores + ? "" + : scoresStr) + + " " + separator + + (onlyCommons + ? "" + : conditionsStr) + + "" + // + ; + + // + return result; + } + + // + string GetTag() + { + return "XPV"; + } +}; + +// +// Class ... +class XCXPVHelper : public XCBaseHelper +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructors ... + XCXPVHelper() : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCXPVHelper() + { + // + Clean(fib1Buffer); + Clean(fib2Buffer); + Clean(fib3Buffer); + Clean(fib4Buffer); + Clean(fib5Buffer); + Clean(scHHBuffer); + Clean(scLLBuffer); + Clean(mcHHBuffer); + Clean(mcLLBuffer); + Clean(lcHHBuffer); + Clean(lcLLBuffer); + Clean(hcHHBuffer); + Clean(hcLLBuffer); + Clean(peaksBuffer); + Clean(valesBuffer); + Clean(supportBuffer); + Clean(resistanceBuffer); + } + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + XPVInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + ArraySetAsSeries(peaksBuffer, true); + ArraySetAsSeries(valesBuffer, true); + ArraySetAsSeries(resistanceBuffer, true); + ArraySetAsSeries(supportBuffer, true); + ArraySetAsSeries(fib1Buffer, true); + ArraySetAsSeries(fib2Buffer, true); + ArraySetAsSeries(fib3Buffer, true); + ArraySetAsSeries(fib4Buffer, true); + ArraySetAsSeries(fib5Buffer, true); + ArraySetAsSeries(scHHBuffer, true); + ArraySetAsSeries(scLLBuffer, true); + ArraySetAsSeries(mcHHBuffer, true); + ArraySetAsSeries(mcLLBuffer, true); + ArraySetAsSeries(lcHHBuffer, true); + ArraySetAsSeries(lcLLBuffer, true); + ArraySetAsSeries(hcHHBuffer, true); + ArraySetAsSeries(hcLLBuffer, true); + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.xpv", + // + // Inputs ... + // + // Makret Cycles ... + "", + // + // Short ... + "", + mInputs.scMethod, // How to Find Period + mInputs.scPeriod, // Time Period + // + // Medium ... + "", + mInputs.mcMethod, // How to Find Period + mInputs.mcPeriod, // Time Period + // + // Long ... + "", + mInputs.lcMethod, // How to Find Period + mInputs.lcPeriod, // Time Period + // + // Hind ... + "", + mInputs.hcMethod, // How to Find Period + mInputs.hcPeriod, // Time Period + // + // Fibonacci ... + "", + mInputs.fiboLevel1, // Fibio 1st Level + mInputs.fiboLevel2, // Fibio 2st Level + mInputs.fiboLevel3, // Fibio 3rd Level + mInputs.fiboLevel4, // Fibio 4th Level + mInputs.fiboLevel5, // Fibio 5th Level + // + // Boundary Detection Modes ... + "", + mInputs.hhMode, // Highest High Calculation Method + mInputs.llMode, // Lowest Low Calculation Method + // + // Presentation ... + "", + mInputs.showPeaksAndVales, // Show Peaks and Vales + mInputs.showLevels, // Show Levels + mInputs.showConsolidations, // Show Consolidations + mInputs.showFibo1Levels, // Show Fibo 1st Level + mInputs.showFibo2Levels, // Show Fibo 2nd Level + mInputs.showFibo3Levels, // Show Fibo 3rd Level + mInputs.showFibo4Levels, // Show Fibo 4th Level + mInputs.showFibo5Levels // Show Fibo 5th Level + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + XPVInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + XPVInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Buffers ... + + // + // Peaks ... + + // + double GetPeak( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(peaksBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return peaksBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyPeak( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + peaksBuffer, + buffer, + forceClean + // + ); + } + + // + bool IsSamePeak( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + peaksBuffer, + verifier, + barIndex // + ); + } + + // + // Vales ... + + // + double GetVale( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(valesBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return valesBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyVale( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + valesBuffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameVale( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + valesBuffer, + verifier, + barIndex // + ); + } + + // + // Resistance ... + + // + double GetResistance( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(resistanceBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return resistanceBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyResistance( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + resistanceBuffer, + buffer, + forceClean + // + ); + } + + // + // Support ... + + // + double GetSupport( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(supportBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return supportBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopySupport( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + supportBuffer, + buffer, + forceClean + // + ); + } + + // + // Fibonacci ... + + // + // Level 1 ... + + // + double GetFib1( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(fib1Buffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fib1Buffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyFib1( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + fib1Buffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameFib1( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + fib1Buffer, + verifier, + barIndex // + ); + } + + // + // Level 2 ... + + // + double GetFib2( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(fib2Buffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fib2Buffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyFib2( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + fib2Buffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameFib2( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + fib2Buffer, + verifier, + barIndex // + ); + } + + // + // Level 3 ... + + // + double GetFib3( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(fib3Buffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fib3Buffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyFib3( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + fib3Buffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameFib3( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + fib3Buffer, + verifier, + barIndex // + ); + } + + // + // Level 4 ... + + // + double GetFib4( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(fib4Buffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fib4Buffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyFib4( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + fib4Buffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameFib4( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + fib4Buffer, + verifier, + barIndex // + ); + } + + // + // Level 5 ... + + // + double GetFib5( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(fib5Buffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return fib5Buffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyFib5( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + fib5Buffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameFib5( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + fib5Buffer, + verifier, + barIndex // + ); + } + + // + // Cycles ... + + // + // Short ... + + // + // HH ... + + // + double GetSCHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(scHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return scHHBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopySCHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + scHHBuffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameSCHH( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + scHHBuffer, + verifier, + barIndex // + ); + } + + // + // LL ... + + // + double GetSCLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(scLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return scLLBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopySCLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + scLLBuffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameSCLL( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + scLLBuffer, + verifier, + barIndex // + ); + } + + // + // Medium ... + + // + // HH ... + + // + double GetMCHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(mcHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return mcHHBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyMCHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + mcHHBuffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameMCHH( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + mcHHBuffer, + verifier, + barIndex // + ); + } + + // + // LL ... + + // + double GetMCLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(mcLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return mcLLBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyMCLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + mcLLBuffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameMCLL( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + mcLLBuffer, + verifier, + barIndex // + ); + } + + // + // Long ... + + // + // HH ... + + // + double GetLCHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(lcHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return lcHHBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyLCHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + lcHHBuffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameLCHH( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + lcHHBuffer, + verifier, + barIndex // + ); + } + + // + // LL ... + + // + double GetLCLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(lcLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return lcLLBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyLCLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + lcLLBuffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameLCLL( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + lcLLBuffer, + verifier, + barIndex // + ); + } + + // + // Hind ... + + // + // HH ... + + // + double GetHCHH( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(hcHHBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hcHHBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyHCHH( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + hcHHBuffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameHCHH( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + hcHHBuffer, + verifier, + barIndex // + ); + } + + // + // LL ... + + // + double GetHCLL( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(hcLLBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return hcLLBuffer[barIndex]; + } + + // + // Copy Required Items ... + int CopyHCLL( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + hcLLBuffer, + buffer, + forceClean + // + ); + } + + // + bool IsSameHCLL( + int barIndex, // Start Bar Index + int verifier = 71 // Number of Verifiers + ) + { + // + // Update Calculations ... + Calculate(); + + // + return IsSame( + hcLLBuffer, + verifier, + barIndex // + ); + } + + // + bool GetConditions( + XPVConditions &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; + + // + // Buffers ... + + // + CopyPeak( + zIndex, + loopback, + conditions.peaks // + ); + + // + CopyVale( + zIndex, + loopback, + conditions.vales // + ); + + // + CopySupport( + zIndex, + loopback, + conditions.supports // + ); + + // + CopyResistance( + zIndex, + loopback, + conditions.resistances // + ); + + // + CopyFib1( + zIndex, + loopback, + conditions.fib1s // + ); + + // + CopyFib2( + zIndex, + loopback, + conditions.fib2s // + ); + + // + CopyFib3( + zIndex, + loopback, + conditions.fib3s // + ); + + // + CopyFib4( + zIndex, + loopback, + conditions.fib4s // + ); + + // + CopyFib5( + zIndex, + loopback, + conditions.fib5s // + ); + + // + CopySCHH( + zIndex, + loopback, + conditions.sCHHs // + ); + + // + CopySCLL( + zIndex, + loopback, + conditions.sCLLs // + ); + + // + CopyMCHH( + zIndex, + loopback, + conditions.mCHHs // + ); + + // + CopyMCLL( + zIndex, + loopback, + conditions.mCLLs // + ); + + // + CopyLCHH( + zIndex, + loopback, + conditions.lCHHs // + ); + + // + CopyLCLL( + zIndex, + loopback, + conditions.lCLLs // + ); + + // + CopyHCHH( + zIndex, + loopback, + conditions.hCHHs // + ); + + // + CopyHCLL( + zIndex, + loopback, + conditions.hCLLs // + ); + + // + // Conditions ... + + // + bool isNewPeak = conditions.peaks[cIndex] != conditions.peaks[pIndex]; + bool isNewPeakOverLast = isNewPeak && + conditions.peaks[cIndex] > conditions.peaks[pIndex]; + bool isNewPeakUnderLast = isNewPeak && + conditions.peaks[cIndex] < conditions.peaks[pIndex]; + + // + bool isNewVale = conditions.vales[cIndex] != conditions.vales[pIndex]; + bool isNewValeOverLast = isNewVale && + conditions.vales[cIndex] > conditions.vales[pIndex]; + bool isNewValeUnderLast = isNewVale && + conditions.vales[cIndex] < conditions.vales[pIndex]; + + // + bool isFiboIncreased = + // + conditions.fib1s[cIndex] > conditions.fib1s[pIndex] && + conditions.fib2s[cIndex] > conditions.fib2s[pIndex] && + conditions.fib3s[cIndex] > conditions.fib3s[pIndex] && + conditions.fib4s[cIndex] > conditions.fib4s[pIndex] && + conditions.fib5s[cIndex] > conditions.fib5s[pIndex] + // + ; + bool isFiboDecreased = + // + conditions.fib1s[cIndex] < conditions.fib1s[pIndex] && + conditions.fib2s[cIndex] < conditions.fib2s[pIndex] && + conditions.fib3s[cIndex] < conditions.fib3s[pIndex] && + conditions.fib4s[cIndex] < conditions.fib4s[pIndex] && + conditions.fib5s[cIndex] < conditions.fib5s[pIndex] + // + ; + bool isFiboSectionChanged = + // + (isFiboDecreased && + isNewPeakUnderLast) + // + || + // + (isFiboIncreased && + isNewValeOverLast) + // + ; + + // + // SC ... + + // + bool isSCHHBullish = conditions.sCHHs[cIndex] > conditions.sCHHs[pIndex]; + bool isSCLLBullish = conditions.sCLLs[cIndex] > conditions.sCLLs[pIndex]; + + // + bool isSCHHBullishPrev = conditions.sCHHs[pIndex] > conditions.sCHHs[ppIndex]; + bool isSCLLBullishPrev = conditions.sCLLs[pIndex] > conditions.sCLLs[ppIndex]; + + // + bool isSCBullish = isSCHHBullish && + isSCLLBullish; + + // + bool isSCBullishPrev = isSCHHBullishPrev && + isSCLLBullishPrev; + + // + bool isSCHHSwitchedToBullish = isSCHHBullish && + !isSCHHBullishPrev; + bool isSCLLSwitchedToBullish = isSCLLBullish && + !isSCLLBullishPrev; + + // + bool isSCHHBearish = conditions.sCHHs[cIndex] < conditions.sCHHs[pIndex]; + bool isSCLLBearish = conditions.sCLLs[cIndex] < conditions.sCLLs[pIndex]; + + // + bool isSCHHBearishPrev = conditions.sCHHs[pIndex] < conditions.sCHHs[ppIndex]; + bool isSCLLBearishPrev = conditions.sCLLs[pIndex] < conditions.sCLLs[ppIndex]; + + // + bool isSCBearish = isSCHHBearish && + isSCLLBearish; + + // + bool isSCBearishPrev = isSCHHBearishPrev && + isSCLLBearishPrev; + + // + bool isSCHHSwitchedToBearish = isSCHHBearish && + !isSCHHBearishPrev; + bool isSCLLSwitchedToBeraish = isSCLLBearish && + !isSCLLBearishPrev; + + // + bool isSCSwitchedToBullish = + // + (isSCHHSwitchedToBullish && + !isSCLLBearish) + // + || + // + (isSCLLSwitchedToBullish && + !isSCHHBearish) + // + ; + + // + bool isSCSwitchedToBearish = + // + (isSCHHSwitchedToBearish && + !isSCLLBullish) + // + || + // + (isSCLLSwitchedToBeraish && + !isSCHHBullish) + // + ; + + // + // MC ... + + // + bool isMCHHBullish = conditions.mCHHs[cIndex] > conditions.mCHHs[pIndex]; + bool isMCLLBullish = conditions.mCLLs[cIndex] > conditions.mCLLs[pIndex]; + + // + bool isMCHHBullishPrev = conditions.mCHHs[pIndex] > conditions.mCHHs[ppIndex]; + bool isMCLLBullishPrev = conditions.mCLLs[pIndex] > conditions.mCLLs[ppIndex]; + + // + bool isMCBullish = isMCHHBullish && + isMCLLBullish; + + // + bool isMCBullishPrev = isMCHHBullishPrev && + isMCLLBullishPrev; + + // + bool isMCHHSwitchedToBullish = isMCHHBullish && + !isMCHHBullishPrev; + bool isMCLLSwitchedToBullish = isMCLLBullish && + !isMCLLBullishPrev; + + // + bool isMCHHBearish = conditions.mCHHs[cIndex] < conditions.mCHHs[pIndex]; + bool isMCLLBearish = conditions.mCLLs[cIndex] < conditions.mCLLs[pIndex]; + + // + bool isMCHHBearishPrev = conditions.mCHHs[pIndex] < conditions.mCHHs[ppIndex]; + bool isMCLLBearishPrev = conditions.mCLLs[pIndex] < conditions.mCLLs[ppIndex]; + + // + bool isMCBearish = isMCHHBearish && + isMCLLBearish; + + // + bool isMCBearishPrev = isMCHHBearishPrev && + isMCLLBearishPrev; + + // + bool isMCHHSwitchedToBearish = isMCHHBearish && + !isMCHHBearishPrev; + bool isMCLLSwitchedToBeraish = isMCLLBearish && + !isMCLLBearishPrev; + + // + bool isMCSwitchedToBullish = + // + (isMCHHSwitchedToBullish && + !isMCLLBearish) + // + || + // + (isMCLLSwitchedToBullish && + !isMCHHBearish) + // + ; + + // + bool isMCSwitchedToBearish = + // + (isMCHHSwitchedToBearish && + !isMCLLBullish) + // + || + // + (isMCLLSwitchedToBeraish && + !isMCHHBullish) + // + ; + + // + // LC ... + + // + bool isLCHHBullish = conditions.lCHHs[cIndex] > conditions.lCHHs[pIndex]; + bool isLCLLBullish = conditions.lCLLs[cIndex] > conditions.lCLLs[pIndex]; + + // + bool isLCHHBullishPrev = conditions.lCHHs[pIndex] > conditions.lCHHs[ppIndex]; + bool isLCLLBullishPrev = conditions.lCLLs[pIndex] > conditions.lCLLs[ppIndex]; + + // + bool isLCBullish = isLCHHBullish && + isLCLLBullish; + + // + bool isLCBullishPrev = isLCHHBullishPrev && + isLCLLBullishPrev; + + // + bool isLCHHSwitchedToBullish = isLCHHBullish && + !isLCHHBullishPrev; + bool isLCLLSwitchedToBullish = isLCLLBullish && + !isLCLLBullishPrev; + + // + bool isLCHHBearish = conditions.lCHHs[cIndex] < conditions.lCHHs[pIndex]; + bool isLCLLBearish = conditions.lCLLs[cIndex] < conditions.lCLLs[pIndex]; + + // + bool isLCHHBearishPrev = conditions.lCHHs[pIndex] < conditions.lCHHs[ppIndex]; + bool isLCLLBearishPrev = conditions.lCLLs[pIndex] < conditions.lCLLs[ppIndex]; + + // + bool isLCBearish = isLCHHBearish && + isLCLLBearish; + + // + bool isLCBearishPrev = isLCHHBearishPrev && + isLCLLBearishPrev; + + // + bool isLCHHSwitchedToBearish = isLCHHBearish && + !isLCHHBearishPrev; + bool isLCLLSwitchedToBeraish = isLCLLBearish && + !isLCLLBearishPrev; + + // + bool isLCSwitchedToBullish = + // + (isLCHHSwitchedToBullish && + !isLCLLBearish) + // + || + // + (isLCLLSwitchedToBullish && + !isLCHHBearish) + // + ; + + // + bool isLCSwitchedToBearish = + // + (isLCHHSwitchedToBearish && + !isLCLLBullish) + // + || + // + (isLCLLSwitchedToBeraish && + !isLCHHBullish) + // + ; + + // + // HC ... + + // + bool isHCHHBullish = conditions.hCHHs[cIndex] > conditions.hCHHs[pIndex]; + bool isHCLLBullish = conditions.hCLLs[cIndex] > conditions.hCLLs[pIndex]; + + // + bool isHCHHBullishPrev = conditions.hCHHs[pIndex] > conditions.hCHHs[ppIndex]; + bool isHCLLBullishPrev = conditions.hCLLs[pIndex] > conditions.hCLLs[ppIndex]; + + // + bool isHCBullish = isHCHHBullish && + isHCLLBullish; + + // + bool isHCBullishPrev = isHCHHBullishPrev && + isHCLLBullishPrev; + + // + bool isHCHHSwitchedToBullish = isHCHHBullish && + !isHCHHBullishPrev; + bool isHCLLSwitchedToBullish = isHCLLBullish && + !isHCLLBullishPrev; + + // + bool isHCHHBearish = conditions.hCHHs[cIndex] < conditions.hCHHs[pIndex]; + bool isHCLLBearish = conditions.hCLLs[cIndex] < conditions.hCLLs[pIndex]; + + // + bool isHCHHBearishPrev = conditions.hCHHs[pIndex] < conditions.hCHHs[ppIndex]; + bool isHCLLBearishPrev = conditions.hCLLs[pIndex] < conditions.hCLLs[ppIndex]; + + // + bool isHCBearish = isHCHHBearish && + isHCLLBearish; + + // + bool isHCBearishPrev = isHCHHBearishPrev && + isHCLLBearishPrev; + + // + bool isHCHHSwitchedToBearish = isHCHHBearish && + !isHCHHBearishPrev; + bool isHCLLSwitchedToBeraish = isHCLLBearish && + !isHCLLBearishPrev; + + // + bool isHCSwitchedToBullish = + // + (isHCHHSwitchedToBullish && + !isHCLLBearish) + // + || + // + (isHCLLSwitchedToBullish && + !isHCHHBearish) + // + ; + + // + bool isHCSwitchedToBearish = + // + (isHCHHSwitchedToBearish && + !isHCLLBullish) + // + || + // + (isHCLLSwitchedToBeraish && + !isHCHHBullish) + // + ; + + // + // Define Bars For Calculations ... + + // + XOHCL cBar; + result = cBar.Init( + mSymbol, + mPeriod, + cIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL pBar; + result = pBar.Init( + mSymbol, + mPeriod, + pIndex // + ); + if (!result) + { + return result; + } + + // + bool isCloseOverFib1 = cBar.close > conditions.fib1s[cIndex]; + bool isCloseOverFib1Prev = pBar.close > conditions.fib1s[pIndex]; + + // + bool isCloseOverFib2 = cBar.close > conditions.fib2s[cIndex]; + bool isCloseOverFib2Prev = pBar.close > conditions.fib2s[pIndex]; + + // + bool isCloseOverFib3 = cBar.close > conditions.fib3s[cIndex]; + bool isCloseOverFib3Prev = pBar.close > conditions.fib3s[pIndex]; + + // + bool isCloseOverFib4 = cBar.close > conditions.fib4s[cIndex]; + bool isCloseOverFib4Prev = pBar.close > conditions.fib4s[pIndex]; + + // + bool isCloseOverFib5 = cBar.close > conditions.fib5s[cIndex]; + bool isCloseOverFib5Prev = pBar.close > conditions.fib5s[pIndex]; + + // + bool isCloseUnderFib1 = cBar.close < conditions.fib1s[cIndex]; + bool isCloseUnderFib1Prev = pBar.close < conditions.fib1s[pIndex]; + + // + bool isCloseUnderFib2 = cBar.close < conditions.fib2s[cIndex]; + bool isCloseUnderFib2Prev = pBar.close < conditions.fib2s[pIndex]; + + // + bool isCloseUnderFib3 = cBar.close < conditions.fib3s[cIndex]; + bool isCloseUnderFib3Prev = pBar.close < conditions.fib3s[pIndex]; + + // + bool isCloseUnderFib4 = cBar.close < conditions.fib4s[cIndex]; + bool isCloseUnderFib4Prev = pBar.close < conditions.fib4s[pIndex]; + + // + bool isCloseUnderFib5 = cBar.close < conditions.fib5s[cIndex]; + bool isCloseUnderFib5Prev = pBar.close < conditions.fib5s[pIndex]; + + // + bool isCloseCrossedOverFib1 = isCloseOverFib1 && + !isCloseOverFib1Prev; + bool isCloseCrossedOverFib2 = isCloseOverFib2 && + !isCloseOverFib2Prev; + bool isCloseCrossedOverFib3 = isCloseOverFib3 && + !isCloseOverFib3Prev; + bool isCloseCrossedOverFib4 = isCloseOverFib4 && + !isCloseOverFib4Prev; + bool isCloseCrossedOverFib5 = isCloseOverFib5 && + !isCloseOverFib5Prev; + + // + bool isCloseCrossedUnderFib1 = isCloseUnderFib1 && + !isCloseUnderFib1Prev; + bool isCloseCrossedUnderFib2 = isCloseUnderFib2 && + !isCloseUnderFib2Prev; + bool isCloseCrossedUnderFib3 = isCloseUnderFib3 && + !isCloseUnderFib3Prev; + bool isCloseCrossedUnderFib4 = isCloseUnderFib4 && + !isCloseUnderFib4Prev; + bool isCloseCrossedUnderFib5 = isCloseUnderFib5 && + !isCloseUnderFib5Prev; + + // + conditions.isNewPeak = isNewPeak; + conditions.isNewPeakOverLast = isNewPeakOverLast; + conditions.isNewPeakUnderLast = isNewPeakUnderLast; + conditions.isNewVale = isNewVale; + conditions.isNewValeOverLast = isNewValeOverLast; + conditions.isNewValeUnderLast = isNewValeUnderLast; + conditions.isFiboIncreased = isFiboIncreased; + conditions.isFiboDecreased = isFiboDecreased; + conditions.isFiboSectionChanged = isFiboSectionChanged; + conditions.isCloseOverFib1 = isCloseOverFib1; + conditions.isCloseOverFib2 = isCloseOverFib2; + conditions.isCloseOverFib3 = isCloseOverFib3; + conditions.isCloseOverFib4 = isCloseOverFib4; + conditions.isCloseOverFib5 = isCloseOverFib5; + conditions.isCloseUnderFib1 = isCloseUnderFib1; + conditions.isCloseUnderFib2 = isCloseUnderFib2; + conditions.isCloseUnderFib3 = isCloseUnderFib3; + conditions.isCloseUnderFib4 = isCloseUnderFib4; + conditions.isCloseUnderFib5 = isCloseUnderFib5; + conditions.isCloseCrossedOverFib1 = isCloseCrossedOverFib1; + conditions.isCloseCrossedOverFib2 = isCloseCrossedOverFib2; + conditions.isCloseCrossedOverFib3 = isCloseCrossedOverFib3; + conditions.isCloseCrossedOverFib4 = isCloseCrossedOverFib4; + conditions.isCloseCrossedOverFib5 = isCloseCrossedOverFib5; + conditions.isCloseCrossedUnderFib1 = isCloseCrossedUnderFib1; + conditions.isCloseCrossedUnderFib2 = isCloseCrossedUnderFib2; + conditions.isCloseCrossedUnderFib3 = isCloseCrossedUnderFib3; + conditions.isCloseCrossedUnderFib4 = isCloseCrossedUnderFib4; + conditions.isCloseCrossedUnderFib5 = isCloseCrossedUnderFib5; + conditions.isSCBullish = isSCBullish; + conditions.isSCHHBullish = isSCHHBullish; + conditions.isSCLLBullish = isSCLLBullish; + conditions.isSCSwitchedToBullish = isSCSwitchedToBullish; + conditions.isSCHHSwitchedToBullish = isSCHHSwitchedToBullish; + conditions.isSCLLSwitchedToBullish = isSCLLSwitchedToBullish; + conditions.isSCBearish = isSCBearish; + conditions.isSCHHBearish = isSCHHBearish; + conditions.isSCLLBearish = isSCLLBearish; + conditions.isSCSwitchedToBearish = isSCSwitchedToBearish; + conditions.isSCHHSwitchedToBearish = isSCHHSwitchedToBearish; + conditions.isSCLLSwitchedToBeraish = isSCLLSwitchedToBeraish; + conditions.isMCBullish = isMCBullish; + conditions.isMCHHBullish = isMCHHBullish; + conditions.isMCLLBullish = isMCLLBullish; + conditions.isMCSwitchedToBullish = isMCSwitchedToBullish; + conditions.isMCHHSwitchedToBullish = isMCHHSwitchedToBullish; + conditions.isMCLLSwitchedToBullish = isMCLLSwitchedToBullish; + conditions.isMCBearish = isMCBearish; + conditions.isMCHHBearish = isMCHHBearish; + conditions.isMCLLBearish = isMCLLBearish; + conditions.isMCSwitchedToBearish = isMCSwitchedToBearish; + conditions.isMCHHSwitchedToBearish = isMCHHSwitchedToBearish; + conditions.isMCLLSwitchedToBeraish = isMCLLSwitchedToBeraish; + conditions.isLCBullish = isLCBullish; + conditions.isLCHHBullish = isLCHHBullish; + conditions.isLCLLBullish = isLCLLBullish; + conditions.isLCSwitchedToBullish = isLCSwitchedToBullish; + conditions.isLCHHSwitchedToBullish = isLCHHSwitchedToBullish; + conditions.isLCLLSwitchedToBullish = isLCLLSwitchedToBullish; + conditions.isLCBearish = isLCBearish; + conditions.isLCHHBearish = isLCHHBearish; + conditions.isLCLLBearish = isLCLLBearish; + conditions.isLCSwitchedToBearish = isLCSwitchedToBearish; + conditions.isLCHHSwitchedToBearish = isLCHHSwitchedToBearish; + conditions.isLCLLSwitchedToBeraish = isLCLLSwitchedToBeraish; + conditions.isHCBullish = isHCBullish; + conditions.isHCHHBullish = isHCHHBullish; + conditions.isHCLLBullish = isHCLLBullish; + conditions.isHCSwitchedToBullish = isHCSwitchedToBullish; + conditions.isHCHHSwitchedToBullish = isHCHHSwitchedToBullish; + conditions.isHCLLSwitchedToBullish = isHCLLSwitchedToBullish; + conditions.isHCBearish = isHCBearish; + conditions.isHCHHBearish = isHCHHBearish; + conditions.isHCLLBearish = isHCLLBearish; + conditions.isHCSwitchedToBearish = isHCSwitchedToBearish; + conditions.isHCHHSwitchedToBearish = isHCHHSwitchedToBearish; + conditions.isHCLLSwitchedToBeraish = isHCLLSwitchedToBeraish; + // + return result; + } + + // + // Protected ... +protected: + // + // Private ... +private: + // + // Props ... + XPVInputs mInputs; // Inputs ... + + // + // Buffers ... + double peaksBuffer[]; + double valesBuffer[]; + double resistanceBuffer[]; + double supportBuffer[]; + double fib1Buffer[]; + double fib2Buffer[]; + double fib3Buffer[]; + double fib4Buffer[]; + double fib5Buffer[]; + double scHHBuffer[]; + double scLLBuffer[]; + double mcHHBuffer[]; + double mcLLBuffer[]; + double lcHHBuffer[]; + double lcLLBuffer[]; + double hcHHBuffer[]; + double hcLLBuffer[]; + + // + // Tools ... + + // + // Calculate Values Until Now ... + void Calculate() + { + // + int totalBars = CountBars(); + if (totalBars > 1000) + { + totalBars = 1000; + } + + // + // Peaks and Vales ... + + // + // Peaks Buffer ... + CopyBuffer( + mHandler, + XPV_PEAKS_LINE, + 0, + totalBars, + peaksBuffer + // + ); + + // + // Vales Buffer ... + CopyBuffer( + mHandler, + XPV_VALES_LINE, + 0, + totalBars, + valesBuffer + // + ); + + // + // Support and Resistances ... + + // + // Resistances Buffer ... + CopyBuffer( + mHandler, + XPV_RESISTANCE_LINE, + 0, + totalBars, + resistanceBuffer + // + ); + + // + // Supports Buffer ... + CopyBuffer( + mHandler, + XPV_SUPPORT_LINE, + 0, + totalBars, + supportBuffer + // + ); + + // + // Fibonacci ... + + // + // Level 1 Buffer ... + CopyBuffer( + mHandler, + XPV_FIB_1_LINE, + 0, + totalBars, + fib1Buffer + // + ); + + // + // Level 2 Buffer ... + CopyBuffer( + mHandler, + XPV_FIB_2_LINE, + 0, + totalBars, + fib2Buffer + // + ); + + // + // Level 3 Buffer ... + CopyBuffer( + mHandler, + XPV_FIB_3_LINE, + 0, + totalBars, + fib3Buffer + // + ); + + // + // Level 4 Buffer ... + CopyBuffer( + mHandler, + XPV_FIB_4_LINE, + 0, + totalBars, + fib4Buffer + // + ); + + // + // Level 5 Buffer ... + CopyBuffer( + mHandler, + XPV_FIB_5_LINE, + 0, + totalBars, + fib5Buffer + // + ); + + // + // Cycles ... + + // + // Short ... + + // + // HH ... + CopyBuffer( + mHandler, + XPV_SC_HH_LINE, + 0, + totalBars, + scHHBuffer + // + ); + + // + // LL ... + CopyBuffer( + mHandler, + XPV_SC_LL_LINE, + 0, + totalBars, + scLLBuffer + // + ); + + // + // Medium ... + + // + // HH ... + CopyBuffer( + mHandler, + XPV_MC_HH_LINE, + 0, + totalBars, + mcHHBuffer + // + ); + + // + // LL ... + CopyBuffer( + mHandler, + XPV_MC_LL_LINE, + 0, + totalBars, + mcLLBuffer + // + ); + + // + // Long ... + + // + // HH ... + CopyBuffer( + mHandler, + XPV_LC_HH_LINE, + 0, + totalBars, + lcHHBuffer + // + ); + + // + // LL ... + CopyBuffer( + mHandler, + XPV_LC_LL_LINE, + 0, + totalBars, + lcLLBuffer + // + ); + + // + // Hind ... + + // + // HH ... + CopyBuffer( + mHandler, + XPV_HC_HH_LINE, + 0, + totalBars, + hcHHBuffer + // + ); + + // + // LL ... + CopyBuffer( + mHandler, + XPV_HC_LL_LINE, + 0, + totalBars, + hcLLBuffer + // + ); + } +}; + +// +// Tools ... \ No newline at end of file diff --git a/BKPS/14031003/Indicators/x-saherelm.x121.ex5 b/BKPS/14031003/Indicators/x-saherelm.x121.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..972023b672392aba336562d72f86d91be2d1b671 GIT binary patch literal 66444 zcmdS8Q?M>f%r5vY+qP}nwr$(CZQHhuz4x+h+qTzy|J0nRI&*RECtYdeNu@eTSGB}6 z*+88DDaeAL073u&2yg@n_}_?u8p3oIoE0TrVA$9P#R27i1OFS4|9=JlYyAJ%@rDEd z{)YhoSi=7W{jXNlPE0q5;GINBrO{&za0;%E8mVi_wXSw!`$LDTm_f}VC4g;xYHaa8 z`XT@afFr;Q;0&+=SO6>muK!J!8Nm1-vjAxS>#G2a{*#*hhl>Gh0e1gMqyVb_)gu4N z?ElmLALRef^gkZE{ucok05^c)zvA-$`fK)o`%C{{T>k&<;r}^1OaS`-vd#E^R{B4n zVD$Gu77#xOR?^y72h^;plHxm5GZy)N8>-j8=>EZ)KIJixVGAi$947p(OlY+*6D-1l zi=1Yw-a!gUPK&K)>}Euv-VWd7*H#lPH4270G@~vHm9cecAMG0+cK!jNg{G9MRroa1 ze7_5Cq@Lngu8`Jql0Av!AX5jasxSf2Mo9whExFS1>$<{X!!=XFi%j!Sn(atyZ9RYS z4?o@cgTLWZlk=v0zUTR5XB(p(65547d~vMfGE(O2tfB%N(X+Iz$R(YMuIX-Yn52^M zOAPdcTbc5e;24nHQtc5abu~~`IHC0{rZxZBYVjX&M>6;jK>~9Vj5_6mJ#zMAaAUQb z9$B~=*ZADBL?a{O@32op`jRW6zpiboS`{0t14sNdhvjk4UO-VVIz|)A82c7<5EF9G^D?RZED?ffGn>R#Zw(J2gjcVT zjCwCK6Ps7re2}9#k^l;V(5`%7XH_t7D?9#!w=s6zYa=y*b!WH|oMxA(<^L*Iq9xY~ zeCdF`#=x2s3-rq}HPF*8oQ**>7azNKddgh(rs=WxX_At7V_P1OA=A1b)e@&-g8+)qbRI4WJ46S;g2bW z)^EFh;qr~G1*MjN9)G{0^wUHG&ZY*bv0MeP_Ep`7^t`cPDfnuTA|Y!y@Qo%fI=?LY zRka!ClufVT)M52=`op^$VdN0)AguhmZXR#;l|gXBDkvRrWrk3H92guPX9*5~>ZD^P zBc$6dyhzXDTpI|9B=JW?Nejmy%aHQ?2o0p3 zB}=DEd=mC+A$3aF6TZB%mi2r{Ldl_-c44|zrj>qlfA`?uLG;iE0@4`zSC&%6P=qYEX+G!MBJ@XnQ=j+*Ws~{;lq~v9w?j;S8@LBP%+DE*WWGeu{NRJtIyF8 zW1ejRT1foURuBK)K#Z_>g1mtD>9~`1#(d;-4|mAu5$t}9VvV7IzVOho*2z15 z=>}h9ga*izJ(RbPHfLK3sWuH-c08p+E+1DD0=s5T@0J?*>W+r~3yUpT|4TWI*=FW9 zyS+mNnS5Orj9nY&vU+lSBqBrWx|6@yCIqBkv4N#xB^(-W&k)Jnr$KI(_tY>zMB5VS zfv)8gp!`vBqyg}f$-KcpYgmIDINQmZwlL#zSdF#3SR<7xSJ8S0pRiVEed?!VnS4`c z(hY@m@&8%H<{b;&<#VMDh(BN9JN@ai_Ve=?0+1v%g+@B{Q0i@a#L%0ARR^6$Ynigh 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 T(1bH^vbC0 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πz-C6TN>HT$eIPjW40s;0R69svs=1U!2U}c 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 literal 0 HcmV?d00001 diff --git a/BKPS/14031003/Indicators/x-saherelm.x121.mq5 b/BKPS/14031003/Indicators/x-saherelm.x121.mq5 new file mode 100644 index 0000000..0cae13d --- /dev/null +++ b/BKPS/14031003/Indicators/x-saherelm.x121.mq5 @@ -0,0 +1,2241 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 +// Description: Peaks and Vales ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121 Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121" + +// +// Includes Common Library ... +#include "../Classes/x-saherelm.x-poi.class.mq5" +#include "../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +input group "Makret Cycles"; + +// +input group "Short"; +input ENUM_X_PERIOD_METHOD scMethod = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES scPeriod = NULL; // Time Period + +// +input group "Medium"; +input ENUM_X_PERIOD_METHOD mcMethod = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES mcPeriod = NULL; // Time Period + +// +input group "Long"; +input ENUM_X_PERIOD_METHOD lcMethod = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES lcPeriod = NULL; // Time Period + +// +input group "Hind"; +input ENUM_X_PERIOD_METHOD hcMethod = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES hcPeriod = NULL; // Time Period + +// +input group "Boundary Detection"; +input ENUM_SERIESMODE hhMode = MODE_HIGH; // Highest High Calculation Method +input ENUM_SERIESMODE llMode = MODE_LOW; // Lowest Low Calculation Method + +// +input group "Paraboli Sar Detection"; +input double sarStep = 0.02; // Step +input double sarMax = 0.2; // Maximum + +// +input group "VWap Detection"; +input int vwapFastLength = 20; // Fast Length +input int vwapMidLength = 40; // Mid Length +input int vwapSlowLength = 60; // Slow Length +input ENUM_APPLIED_PRICE vwapAppliedTo = PRICE_CLOSE; // Applied To + +// +input group "Donchain Detection"; +input int donchainLength = 40; // Donchain Length + +// +input group "Fibonacci"; +input double fiboLevel1 = 0.236; // Fibio 1st Level +input double fiboLevel2 = 0.382; // Fibio 2st Level +input double fiboLevel3 = 0.5; // Fibio 3rd Level +input double fiboLevel4 = 0.618; // Fibio 4th Level +input double fiboLevel5 = 0.764; // Fibio 5th Level + +// +input group "Presentation"; + +// +input int startCalculationForLastBars = 1000; // Calculate Last n Bars + +// +input int sarArrowCode = 159; // Parabolic Sar Arrow Code +input int peaksArrowCode = 159; // Peaks Arrow Code +input int valesArrowCode = 159; // Vales Arrow Code + +// +input bool showSar = true; // Show Parabolic Sar +input bool showPeaks = true; // Show Peaks +input bool showVales = true; // Show Vales +input bool showVWap = true; // Show VWap +input bool showDonchain = true; // Show Donchain + +// +input group "Fibonachi Presentation"; +input bool showFibo1Levels = false; // Show Fibo 1st Level +input bool showFibo2Levels = false; // Show Fibo 2nd Level +input bool showFibo3Levels = false; // Show Fibo 3rd Level +input bool showFibo4Levels = false; // Show Fibo 4th Level +input bool showFibo5Levels = false; // Show Fibo 5th Level + +// +input group "VWap Presentation"; +input bool showVWapFast = true; // Show VWap Fast +input bool showVWapMedium = true; // Show VWap Medium +input bool showVWapSlow = true; // Show VWap Slow + +// +input group "Donchain Presentation"; +input bool showUpper = true; // Show Upper Band +input bool showLower = true; // Show Lower Band +input bool showOpen = true; // Show Open +input bool showHigh = false; // Show High +input bool showClose = true; // Show Close +input bool showLow = false; // Show Low + +// +// Buffers ... + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#property indicator_chart_window + +// +#property indicator_buffers 39 +#property indicator_plots 19 + +// +// PEAKS ... + +// +#define peaksBufferIndex 0 +double peaksBuffer[]; + +// +#property indicator_label1 "X121 PEAKS" +#property indicator_type1 DRAW_ARROW +#property indicator_color1 clrAqua +#property indicator_width1 1 + +// +// VALES ... + +// +#define valesBufferIndex 1 +double valesBuffer[]; + +// +#property indicator_label2 "X121 VALES" +#property indicator_type2 DRAW_ARROW +#property indicator_color2 clrMagenta +#property indicator_width2 1 + +// +#define sarBufferIndex 2 +double sarBuffer[]; + +// +#property indicator_label3 "X121 SAR" +#property indicator_type3 DRAW_ARROW +#property indicator_color3 clrYellow +#property indicator_width3 1 + +// +// FAST ... +#define vwapFastBufferIndex 3 +double vwapFastBuffer[]; + +#define vwapFastColorBufferIndex 4 +double vwapFastColorBuffer[]; + +// +#define vwapFastPlotBufferIndex 3 +#property indicator_label4 "X121 VWF" +#property indicator_type4 DRAW_COLOR_LINE +#property indicator_color4 CLR_NONE, clrAqua, clrMagenta, clrGray +#property indicator_style4 STYLE_SOLID +#property indicator_width4 2 + +// +// MID ... +#define vwapMidBufferIndex 5 +double vwapMidBuffer[]; + +#define vwapMidColorBufferIndex 6 +double vwapMidColorBuffer[]; + +// +#define vwapMidPlotBufferIndex 4 +#property indicator_label5 "X121 VWM" +#property indicator_type5 DRAW_COLOR_LINE +#property indicator_color5 CLR_NONE, clrGreen, clrRed, clrGray +#property indicator_style5 STYLE_SOLID +#property indicator_width5 2 + +// +// SLOW ... +#define vwapSlowBufferIndex 7 +double vwapSlowBuffer[]; + +#define vwapSlowColorBufferIndex 8 +double vwapSlowColorBuffer[]; + +// +#define vwapSlowPlotBufferIndex 5 +#property indicator_label6 "X121 VWS" +#property indicator_type6 DRAW_COLOR_LINE +#property indicator_color6 CLR_NONE, clrSteelBlue, clrDarkRed, clrGray +#property indicator_style6 STYLE_SOLID +#property indicator_width6 2 + +// +// XDON ... + +// +// Open ... + +// +#define donOpenUpperBufferIndex 9 +double donOpenUpperBuffer[]; + +// +#define donOpenUpperPlotBufferIndex 6 +#property indicator_label7 "X121 O U" +#property indicator_type7 DRAW_LINE +#property indicator_color7 clrCornflowerBlue +#property indicator_width7 1 + +// +#define donOpenLowerBufferIndex 10 +double donOpenLowerBuffer[]; + +// +#define donOpenLowerPlotBufferIndex 7 +#property indicator_label8 "X121 O L" +#property indicator_type8 DRAW_LINE +#property indicator_color8 clrCornflowerBlue +#property indicator_width8 1 + +// +// High ... + +// +#define donHighUpperBufferIndex 11 +double donHighUpperBuffer[]; + +// +#define donHighUpperPlotBufferIndex 8 +#property indicator_label9 "X121 H U" +#property indicator_type9 DRAW_LINE +#property indicator_color9 clrAquamarine +#property indicator_width9 1 + +// +#define donHighLowerBufferIndex 12 +double donHighLowerBuffer[]; + +// +#define donHighLowerPlotBufferIndex 9 +#property indicator_label10 "X121 H L" +#property indicator_type10 DRAW_LINE +#property indicator_color10 clrAquamarine +#property indicator_width10 1 + +// +// Low ... + +// +#define donLowUpperBufferIndex 13 +double donLowUpperBuffer[]; + +// +#define donLowUpperPlotBufferIndex 10 +#property indicator_label11 "X121 L U" +#property indicator_type11 DRAW_LINE +#property indicator_color11 clrDarkOrchid +#property indicator_width11 1 + +// +#define donLowLowerBufferIndex 14 +double donLowLowerBuffer[]; + +// +#define donLowLowerPlotBufferIndex 11 +#property indicator_label12 "X121 L L" +#property indicator_type12 DRAW_LINE +#property indicator_color12 clrDarkOrchid +#property indicator_width12 1 + +// +// Close ... + +// +#define donCloseUpperBufferIndex 15 +double donCloseUpperBuffer[]; + +// +#define donCloseUpperPlotBufferIndex 12 +#property indicator_label13 "X121 C U" +#property indicator_type13 DRAW_LINE +#property indicator_color13 clrCoral +#property indicator_width13 1 + +// +#define donCloseLowerBufferIndex 16 +double donCloseLowerBuffer[]; + +// +#define donCloseLowerPlotBufferIndex 13 +#property indicator_label14 "X121 C L" +#property indicator_type14 DRAW_LINE +#property indicator_color14 clrCoral +#property indicator_width14 1 + +// +// FIBONACCI ... + +// +// FIBBO Level 1 ... + +// +#define fl1BufferIndex 17 +double fl1Buffer[]; + +// +#define fl1PlotBufferIndex 14 +#property indicator_label15 "X121 FL1" +#property indicator_type15 DRAW_LINE +#property indicator_color15 clrGold +#property indicator_style15 STYLE_DASHDOTDOT +#property indicator_width15 1 + +// +// FIBBO Level 2 ... + +// +#define fl2BufferIndex 18 +double fl2Buffer[]; + +// +#define fl2PlotBufferIndex 15 +#property indicator_label16 "X121 FL2" +#property indicator_type16 DRAW_LINE +#property indicator_color16 clrGold +#property indicator_style16 STYLE_DASHDOTDOT +#property indicator_width16 1 + +// +// FIBBO Level 3 ... + +// +#define fl3BufferIndex 19 +double fl3Buffer[]; + +// +#define fl3PlotBufferIndex 16 +#property indicator_label17 "X121 FL3" +#property indicator_type17 DRAW_LINE +#property indicator_color17 clrGold +#property indicator_style17 STYLE_DASHDOTDOT +#property indicator_width17 1 + +// +// FIBBO Level 4 ... + +// +#define fl4BufferIndex 20 +double fl4Buffer[]; + +// +#define fl4PlotBufferIndex 17 +#property indicator_label18 "X121 FL4" +#property indicator_type18 DRAW_LINE +#property indicator_color18 clrGold +#property indicator_style18 STYLE_DASHDOTDOT +#property indicator_width18 1 + +// +// FIBBO Level 5 ... + +// +#define fl5BufferIndex 21 +double fl5Buffer[]; + +// +#define fl5PlotBufferIndex 18 +#property indicator_label19 "X121 FL5" +#property indicator_type19 DRAW_LINE +#property indicator_color19 clrGold +#property indicator_style19 STYLE_DASHDOTDOT +#property indicator_width19 1 + +// +// Data Buffers ... + +// +int mLastBufferIndex = 21; + +// +// CURRENT ... + +// +#define cHHBufferIndex mLastBufferIndex + 1 +double cHHBuffer[]; + +// +#define cLLBufferIndex mLastBufferIndex + 2 +double cLLBuffer[]; + +// +// SHORT ... + +// +#define sHHBufferIndex mLastBufferIndex + 3 +double sHHBuffer[]; + +// +#define sLLBufferIndex mLastBufferIndex + 4 +double sLLBuffer[]; + +// +// MEDIUM ... + +// +#define mHHBufferIndex mLastBufferIndex + 5 +double mHHBuffer[]; + +// +#define mLLBufferIndex mLastBufferIndex + 6 +double mLLBuffer[]; + +// +// LONG ... + +// +#define lHHBufferIndex mLastBufferIndex + 7 +double lHHBuffer[]; + +// +#define lLLBufferIndex mLastBufferIndex + 8 +double lLLBuffer[]; + +// +// HIND ... + +// +#define hHHBufferIndex mLastBufferIndex + 9 +double hHHBuffer[]; + +// +#define hLLBufferIndex mLastBufferIndex + 10 +double hLLBuffer[]; + +// +// VOLUME ... +#define vwapVolumeBufferIndex mLastBufferIndex + 11 +double vwapVolumeBuffer[]; + +// +// Price ... +#define vwapPriceBufferIndex mLastBufferIndex + 12 +double vwapPriceBuffer[]; + +// +// Fast State ... +#define vwapFastStateBufferIndex mLastBufferIndex + 13 +double vwapFastStateBuffer[]; + +// +// Mid State ... +#define vwapMidStateBufferIndex mLastBufferIndex + 14 +double vwapMidStateBuffer[]; + +// +// Slow State ... +#define vwapSlowStateBufferIndex mLastBufferIndex + 15 +double vwapSlowStateBuffer[]; + +// +// Valid Peaks and Vales ... + +#define validPeaksBufferIndex mLastBufferIndex + 16 +double validPeaksBuffer[]; + +#define validValesBufferIndex mLastBufferIndex + 17 +double validValesBuffer[]; + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +// SAR Handler ... +int sarHandler = INVALID_HANDLE; + +// +double mHideColorIDX = 0; + +// +// 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; + } + + // + // Initialize Indicator Handlers ... + + // + // SAR ... + sarHandler = iSAR( + _Symbol, + _Period, + sarStep, + sarMax // + ); + bool isInited = sarHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + if (!InitMarketCycles()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +/** + * 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); +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // Fill All Buffers by Zero ... + if (prev_calculated == 0) + { + // + ArrayInitialize(peaksBuffer, 0); + ArrayInitialize(valesBuffer, 0); + ArrayInitialize(sarBuffer, 0); + } + + // + // Validate Calculated Bars ... + + // + // SAR ... + int sarCalculatedBars = BarsCalculated(sarHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // SAR ... + sarCalculatedBars >= 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); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // + // SAR ... + copiedSars > 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 = + // + // PSAR ... + sarMax > 0 && + sarStep > 0 && + sarMax > sarStep && + // + // XDON ... + donchainLength > 0 && + // + // VWAP ... + vwapFastLength > 2 && + vwapMidLength > vwapFastLength && + vwapSlowLength > vwapMidLength && + // + // XPV ... + (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; + + // + // XPV ... + result = MathMax(mSCLength, mMCLength); + result = MathMax(result, mLCLength); + result = MathMax(result, mHCLength); + + // + // XVWAP ... + result = MathMax(result, vwapFastLength); + result = MathMax(result, vwapMidLength); + result = MathMax(result, vwapSlowLength); + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // PEAKS ... + + // + ENUM_DRAW_TYPE peaksDrawType = showPeaks ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(peaksBuffer, true); + SetIndexBuffer(peaksBufferIndex, peaksBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(peaksBufferIndex, PLOT_SHOW_DATA, showPeaks); + PlotIndexSetInteger(peaksBufferIndex, PLOT_DRAW_TYPE, peaksDrawType); + + // + PlotIndexSetDouble(peaksBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(peaksBufferIndex, PLOT_ARROW, peaksArrowCode); + + // + // VALES ... + // + ENUM_DRAW_TYPE valesDrawType = showVales ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(valesBuffer, true); + SetIndexBuffer(valesBufferIndex, valesBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(valesBufferIndex, PLOT_SHOW_DATA, showVales); + PlotIndexSetInteger(valesBufferIndex, PLOT_DRAW_TYPE, valesDrawType); + + // + PlotIndexSetDouble(valesBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(valesBufferIndex, PLOT_ARROW, valesArrowCode); + + // + // 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, 0); + PlotIndexSetInteger(sarBufferIndex, PLOT_ARROW, sarArrowCode); + + // + // XVWAP ... + + // + // Fast ... + ArraySetAsSeries(vwapFastBuffer, true); + ArraySetAsSeries(vwapFastColorBuffer, true); + SetIndexBuffer(vwapFastBufferIndex, vwapFastBuffer, INDICATOR_DATA); + SetIndexBuffer(vwapFastColorBufferIndex, vwapFastColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Mid ... + ArraySetAsSeries(vwapMidBuffer, true); + ArraySetAsSeries(vwapMidColorBuffer, true); + SetIndexBuffer(vwapMidBufferIndex, vwapMidBuffer, INDICATOR_DATA); + SetIndexBuffer(vwapMidColorBufferIndex, vwapMidColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Slow ... + ArraySetAsSeries(vwapSlowBuffer, true); + ArraySetAsSeries(vwapSlowColorBuffer, true); + SetIndexBuffer(vwapSlowBufferIndex, vwapSlowBuffer, INDICATOR_DATA); + SetIndexBuffer(vwapSlowColorBufferIndex, vwapSlowColorBuffer, INDICATOR_COLOR_INDEX); + + // + // XDON ... + + // + // Open ... + + // + // UPPER ... + bool canShowCOpenUpper = showDonchain && showUpper && showOpen; + ENUM_DRAW_TYPE donOpenUpperDrawType = canShowCOpenUpper ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donOpenUpperBuffer, true); + SetIndexBuffer(donOpenUpperBufferIndex, donOpenUpperBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donOpenUpperPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donOpenUpperPlotBufferIndex, PLOT_SHOW_DATA, canShowCOpenUpper); + PlotIndexSetInteger(donOpenUpperPlotBufferIndex, PLOT_DRAW_TYPE, donOpenUpperDrawType); + + // + // LOWER ... + bool canShowCOpenLower = showDonchain && showLower && showOpen; + ENUM_DRAW_TYPE donOpenLowerDrawType = canShowCOpenLower ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donOpenLowerBuffer, true); + SetIndexBuffer(donOpenLowerBufferIndex, donOpenLowerBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donOpenLowerPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donOpenLowerPlotBufferIndex, PLOT_SHOW_DATA, canShowCOpenLower); + PlotIndexSetInteger(donOpenLowerPlotBufferIndex, PLOT_DRAW_TYPE, donOpenLowerDrawType); + + // + // Close ... + + // + // UPPER ... + bool canShowCCloseUpper = showDonchain && showUpper && showClose; + ENUM_DRAW_TYPE donCloseUpperDrawType = canShowCCloseUpper ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donCloseUpperBuffer, true); + SetIndexBuffer(donCloseUpperBufferIndex, donCloseUpperBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donCloseUpperPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donCloseUpperPlotBufferIndex, PLOT_SHOW_DATA, canShowCCloseUpper); + PlotIndexSetInteger(donCloseUpperPlotBufferIndex, PLOT_DRAW_TYPE, donCloseUpperDrawType); + + // + // LOWER ... + bool canShowCCloseLower = showDonchain && showLower && showClose; + ENUM_DRAW_TYPE donCloseLowerDrawType = canShowCCloseLower ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donCloseLowerBuffer, true); + SetIndexBuffer(donCloseLowerBufferIndex, donCloseLowerBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donCloseLowerPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donCloseLowerPlotBufferIndex, PLOT_SHOW_DATA, canShowCCloseLower); + PlotIndexSetInteger(donCloseLowerPlotBufferIndex, PLOT_DRAW_TYPE, donCloseLowerDrawType); + + // + // High ... + + // + // UPPER ... + bool canShowCHighUpper = showDonchain && showUpper && showHigh; + ENUM_DRAW_TYPE donHighUpperDrawType = canShowCHighUpper ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donHighUpperBuffer, true); + SetIndexBuffer(donHighUpperBufferIndex, donHighUpperBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donHighUpperPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donHighUpperPlotBufferIndex, PLOT_SHOW_DATA, canShowCHighUpper); + PlotIndexSetInteger(donHighUpperPlotBufferIndex, PLOT_DRAW_TYPE, donHighUpperDrawType); + + // + // LOWER ... + bool canShowCHighLower = showDonchain && showLower && showHigh; + ENUM_DRAW_TYPE donHighLowerDrawType = canShowCHighLower ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donHighLowerBuffer, true); + SetIndexBuffer(donHighLowerBufferIndex, donHighLowerBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donHighLowerPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donHighLowerPlotBufferIndex, PLOT_SHOW_DATA, canShowCHighLower); + PlotIndexSetInteger(donHighLowerPlotBufferIndex, PLOT_DRAW_TYPE, donHighLowerDrawType); + + // + // Low ... + + // + // UPPER ... + bool canShowCLowUpper = showDonchain && showUpper && showLow; + ENUM_DRAW_TYPE donLowUpperDrawType = canShowCLowUpper ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donLowUpperBuffer, true); + SetIndexBuffer(donLowUpperBufferIndex, donLowUpperBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donLowUpperPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donLowUpperPlotBufferIndex, PLOT_SHOW_DATA, canShowCLowUpper); + PlotIndexSetInteger(donLowUpperPlotBufferIndex, PLOT_DRAW_TYPE, donLowUpperDrawType); + + // + // LOWER ... + bool canShowCLowLower = showDonchain && showLower && showLow; + ENUM_DRAW_TYPE donLowLowerDrawType = canShowCLowLower ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donLowLowerBuffer, true); + SetIndexBuffer(donLowLowerBufferIndex, donLowLowerBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donLowLowerPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donLowLowerPlotBufferIndex, PLOT_SHOW_DATA, canShowCLowLower); + PlotIndexSetInteger(donLowLowerPlotBufferIndex, PLOT_DRAW_TYPE, donLowLowerDrawType); + + // + // FIBONNACI ... + + // + // LEVEL 1 ... + bool canShowFl1 = showFibo1Levels; + ENUM_DRAW_TYPE fl1DrawType = canShowFl1 ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(fl1Buffer, true); + SetIndexBuffer(fl1BufferIndex, fl1Buffer, INDICATOR_DATA); + PlotIndexSetDouble(fl1PlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(fl1PlotBufferIndex, PLOT_SHOW_DATA, canShowFl1); + PlotIndexSetInteger(fl1PlotBufferIndex, PLOT_DRAW_TYPE, fl1DrawType); + + // + // LEVEL 2 ... + bool canShowFl2 = showFibo2Levels; + ENUM_DRAW_TYPE fl2DrawType = canShowFl2 ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(fl2Buffer, true); + SetIndexBuffer(fl2BufferIndex, fl2Buffer, INDICATOR_DATA); + PlotIndexSetDouble(fl2PlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(fl2PlotBufferIndex, PLOT_SHOW_DATA, canShowFl2); + PlotIndexSetInteger(fl2PlotBufferIndex, PLOT_DRAW_TYPE, fl2DrawType); + + // + // LEVEL 3 ... + bool canShowFl3 = showFibo3Levels; + ENUM_DRAW_TYPE fl3DrawType = canShowFl3 ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(fl3Buffer, true); + SetIndexBuffer(fl3BufferIndex, fl3Buffer, INDICATOR_DATA); + PlotIndexSetDouble(fl3PlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(fl3PlotBufferIndex, PLOT_SHOW_DATA, canShowFl3); + PlotIndexSetInteger(fl3PlotBufferIndex, PLOT_DRAW_TYPE, fl3DrawType); + + // + // LEVEL 4 ... + bool canShowFl4 = showFibo4Levels; + ENUM_DRAW_TYPE fl4DrawType = canShowFl4 ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(fl4Buffer, true); + SetIndexBuffer(fl4BufferIndex, fl4Buffer, INDICATOR_DATA); + PlotIndexSetDouble(fl4PlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(fl4PlotBufferIndex, PLOT_SHOW_DATA, canShowFl4); + PlotIndexSetInteger(fl4PlotBufferIndex, PLOT_DRAW_TYPE, fl4DrawType); + + // + // LEVEL 5 ... + bool canShowFl5 = showFibo5Levels; + ENUM_DRAW_TYPE fl5DrawType = canShowFl5 ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(fl5Buffer, true); + SetIndexBuffer(fl5BufferIndex, fl5Buffer, INDICATOR_DATA); + PlotIndexSetDouble(fl5PlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(fl5PlotBufferIndex, PLOT_SHOW_DATA, canShowFl5); + PlotIndexSetInteger(fl5PlotBufferIndex, PLOT_DRAW_TYPE, fl5DrawType); + + // + // Data Buffers ... + + // + // CURRENT ... + + // + ArraySetAsSeries(cHHBuffer, true); + SetIndexBuffer(cHHBufferIndex, cHHBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(cLLBuffer, true); + SetIndexBuffer(cLLBufferIndex, cLLBuffer, INDICATOR_CALCULATIONS); + + // + // SHORT ... + + // + ArraySetAsSeries(sHHBuffer, true); + SetIndexBuffer(sHHBufferIndex, sHHBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(sLLBuffer, true); + SetIndexBuffer(sLLBufferIndex, sLLBuffer, INDICATOR_CALCULATIONS); + + // + // MEDIUM ... + + // + ArraySetAsSeries(mHHBuffer, true); + SetIndexBuffer(mHHBufferIndex, mHHBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(mLLBuffer, true); + SetIndexBuffer(mLLBufferIndex, mLLBuffer, INDICATOR_CALCULATIONS); + + // + // LONG ... + + // + ArraySetAsSeries(lHHBuffer, true); + SetIndexBuffer(lHHBufferIndex, lHHBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(lLLBuffer, true); + SetIndexBuffer(lLLBufferIndex, lLLBuffer, INDICATOR_CALCULATIONS); + + // + // HIND ... + + // + ArraySetAsSeries(hHHBuffer, true); + SetIndexBuffer(hHHBufferIndex, hHHBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(hLLBuffer, true); + SetIndexBuffer(hLLBufferIndex, hLLBuffer, INDICATOR_CALCULATIONS); + + // + // XVWAP ... + + // + // Volumes ... + ArraySetAsSeries(vwapVolumeBuffer, true); + SetIndexBuffer(vwapVolumeBufferIndex, vwapVolumeBuffer, INDICATOR_CALCULATIONS); + + // + // Price ... + ArraySetAsSeries(vwapPriceBuffer, true); + SetIndexBuffer(vwapPriceBufferIndex, vwapPriceBuffer, INDICATOR_CALCULATIONS); + + // + // Fast State ... + ArraySetAsSeries(vwapFastStateBuffer, true); + SetIndexBuffer(vwapFastStateBufferIndex, vwapFastStateBuffer, INDICATOR_CALCULATIONS); + + // + // Mid State ... + ArraySetAsSeries(vwapMidStateBuffer, true); + SetIndexBuffer(vwapMidStateBufferIndex, vwapMidStateBuffer, INDICATOR_CALCULATIONS); + + // + // Slow State ... + ArraySetAsSeries(vwapSlowStateBuffer, true); + SetIndexBuffer(vwapSlowStateBufferIndex, vwapSlowStateBuffer, INDICATOR_CALCULATIONS); + + // + // VALID Peaks and Vales ... + + // + ArraySetAsSeries(validPeaksBuffer, true); + SetIndexBuffer(validPeaksBufferIndex, validPeaksBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(validValesBuffer, true); + SetIndexBuffer(validValesBufferIndex, validValesBuffer, INDICATOR_CALCULATIONS); +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateBuffers( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + // + // bool canCalculate = true; + bool canCalculate = + barsLimit == 0 || + bar_index <= barsLimit; + if (canCalculate) + { + // + // Calculate Cycles ... + CalculateCycles(bar_index); + + // + // Calculate Peaks and Vales ... + CalculatePeaksAndVales(bar_index); + + // + CalculateDonchains( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // if (bar_index <= barsLimit + 576) + // { + // // + // CalculateValidPeaksAndVales( + // bar_index, + // prevCalculated // + // ); + // } + + // + CalculateFibonacci( + bar_index // + ); + + // + // Calculate Required VWAP Data Buffers ... + if (ratesTotal - bar_index <= maxLength) + { + // + CalculateVWAPDataBuffers( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // Prevent Moving Forward ... + } + else + { + // + CalculateVWAPDataBuffers( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + CalculateVWAPS( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + } + else + { + FillBuffersZero(bar_index); + } +} + +// +// Custom ... + +/** + * 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) +{ + // + // CURRENT ... + cHHBuffer[barIndex] = 0; + cLLBuffer[barIndex] = 0; + + // + // SHORT ... + sHHBuffer[barIndex] = 0; + sLLBuffer[barIndex] = 0; + + // + // MEDIUM ... + mHHBuffer[barIndex] = 0; + mLLBuffer[barIndex] = 0; + + // + // LONG ... + lHHBuffer[barIndex] = 0; + lLLBuffer[barIndex] = 0; + + // + // HIND ... + hHHBuffer[barIndex] = 0; + hLLBuffer[barIndex] = 0; + + // + // PEAKS ... + peaksBuffer[barIndex] = 0; + + // + // VALES ... + valesBuffer[barIndex] = 0; + + // + // SARS ... + sarBuffer[barIndex] = 0; + + // + // VWAP ... + + // + vwapFastBuffer[barIndex] = 0; + vwapMidBuffer[barIndex] = 0; + vwapSlowBuffer[barIndex] = 0; + vwapVolumeBuffer[barIndex] = 0; + vwapPriceBuffer[barIndex] = 0; + + // + vwapFastColorBuffer[barIndex] = hideColorIDX; + vwapMidColorBuffer[barIndex] = hideColorIDX; + vwapSlowColorBuffer[barIndex] = hideColorIDX; + vwapFastStateBuffer[barIndex] = hideColorIDX; + vwapMidStateBuffer[barIndex] = hideColorIDX; + vwapSlowStateBuffer[barIndex] = hideColorIDX; + + // + validPeaksBuffer[barIndex] = 0; + validValesBuffer[barIndex] = 0; + + // + donOpenUpperBuffer[barIndex] = 0; + donOpenLowerBuffer[barIndex] = 0; + donCloseUpperBuffer[barIndex] = 0; + donCloseLowerBuffer[barIndex] = 0; + donHighUpperBuffer[barIndex] = 0; + donHighLowerBuffer[barIndex] = 0; + donLowUpperBuffer[barIndex] = 0; + donLowLowerBuffer[barIndex] = 0; + + // + fl1Buffer[barIndex] = 0; + fl2Buffer[barIndex] = 0; + fl3Buffer[barIndex] = 0; + fl4Buffer[barIndex] = 0; + fl5Buffer[barIndex] = 0; +} + +/** + * 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 Peaks and Vales ... + * + * @param barIndex: Integer, Bar Index ... + */ +void CalculatePeaksAndVales(int barIndex) +{ + // + int lastIndex = barIndex + 1; + int barsCount = iBars(_Symbol, _Period); + + // + // PEAKS ... + double lastPeak = + lastIndex < barsCount + ? peaksBuffer[lastIndex] + : 0; + + // + double isHH = sHHBuffer[barIndex]; + double imHH = mHHBuffer[barIndex]; + double ilHH = lHHBuffer[barIndex]; + double ihHH = hHHBuffer[barIndex]; + + // + double iHHs[4] = { + isHH, + imHH, + ilHH, + ihHH // + }; + double rValue = GetAverage(iHHs); + bool isPeak = rValue == isHH && + isHH == imHH && + imHH == ilHH && + ilHH == ihHH; + double iPeak = + isPeak + ? rValue + : lastPeak; + peaksBuffer[barIndex] = iPeak; + + // + // VALES ... + double lastVale = + lastIndex < barsCount + ? valesBuffer[lastIndex] + : 0; + + // + double isLL = sLLBuffer[barIndex]; + double imLL = mLLBuffer[barIndex]; + double ilLL = lLLBuffer[barIndex]; + double ihLL = hLLBuffer[barIndex]; + + // + double iLLs[4] = { + isLL, + imLL, + ilLL, + ihLL // + }; + double sValue = GetAverage(iLLs); + bool isVale = sValue == isLL && + isLL == imLL && + imLL == ilLL && + ilLL == ihLL; + double iVale = + isVale + ? sValue + : lastVale; + valesBuffer[barIndex] = iVale; +} + +/** + * Calculate VWAP Value for Specified Bar ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + * @param _length: Integer, Specified VWAP Length ... + * @param _show: Boolean, Specified Show Buffer or not ... + * @param _buffer: Double Array Reference, Points to Buffer ... + * @param _colorBuffer: Double Array Reference, Points to Color Buffer ... + * @param _stateBuffer: Double Array Reference, Points to State Buffer ... + */ +void CalculateVWAP( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[], + // + int _length, // Calculation Length + bool _show, + double &_buffer[], + double &_colorBuffer[], + double &_stateBuffer[] // +) +{ + // + double vSum = 0; + double pSum = 0; + double mSum = 0; + for (int x = 0; x < _length; x++) + { + // + pSum += vwapPriceBuffer[x + bar_index]; + vSum += vwapVolumeBuffer[x + bar_index]; + mSum += vwapPriceBuffer[x + bar_index] * vwapVolumeBuffer[x + bar_index]; + } + + // + double iValue = mSum / vSum; + iValue = NormalizeDouble(iValue, _Digits); + + // + _buffer[bar_index] = iValue; + + // + bool isBullish = low[bar_index] > iValue; + bool isBearish = high[bar_index] < iValue; + + // + double iColor = + isBullish + ? bullishColorIDX + : isBearish + ? bearishColorIDX + : neuturalColorIDX; + + // + _colorBuffer[bar_index] = hideColorIDX; + _stateBuffer[bar_index] = iColor; + if (showVWap && _show) + { + _colorBuffer[bar_index] = iColor; + } +} + +/** + * Calculate Donchain ... + * + * @param bar_index: Integer, Bar Index ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + * @param _length: Integer, Donchain Length ... + * @param _ouBuffer: Double Array Reference ... + * @param _olBuffer: Double Array Reference ... + * @param _huBuffer: Double Array Reference ... + * @param _hlBuffer: Double Array Reference ... + * @param _luBuffer: Double Array Reference ... + * @param _llBuffer: Double Array Reference ... + * @param _cuBuffer: Double Array Reference ... + * @param _clBuffer: Double Array Reference ... + */ +void CalculateDonchain( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + // + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[], + // + int _length, + // + double &_ouBuffer[], + double &_olBuffer[], + double &_huBuffer[], + double &_hlBuffer[], + double &_luBuffer[], + double &_llBuffer[], + double &_cuBuffer[], + double &_clBuffer[] // +) +{ + // + double iUpper = 0; + double iLower = 0; + + // + // OPEN ... + + // + int from = bar_index; + + // + iUpper = open[ArrayMaximum(open, from, _length)]; + iLower = open[ArrayMinimum(open, from, _length)]; + + // + _ouBuffer[bar_index] = iUpper; + _olBuffer[bar_index] = iLower; + + // + // HIGH ... + + // + iUpper = high[ArrayMaximum(high, from, _length)]; + iLower = high[ArrayMinimum(high, from, _length)]; + + // + _huBuffer[bar_index] = iUpper; + _hlBuffer[bar_index] = iLower; + + // + // LOW ... + + // + iUpper = low[ArrayMaximum(low, from, _length)]; + iLower = low[ArrayMinimum(low, from, _length)]; + + // + _luBuffer[bar_index] = iUpper; + _llBuffer[bar_index] = iLower; + + // + // CLOSE ... + + // + iUpper = close[ArrayMaximum(close, from, _length)]; + iLower = close[ArrayMinimum(close, from, _length)]; + + // + _cuBuffer[bar_index] = iUpper; + _clBuffer[bar_index] = iLower; +} + +/** + * Calculate VWAP Required Data Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateVWAPDataBuffers( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + double price = GetAppliedPrice( + vwapAppliedTo, + open, + high, + low, + close, + bar_index // + ); + vwapPriceBuffer[bar_index] = price; + vwapVolumeBuffer[bar_index] = (double)tickVolume[bar_index]; +} + +/** + * Calculate Different VWaps ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateVWAPS( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // Fast ... + CalculateVWAP( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume, + // + vwapFastLength, + showVWapFast, + vwapFastBuffer, + vwapFastColorBuffer, + vwapFastStateBuffer // + ); + + // + // Mid ... + CalculateVWAP( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume, + // + vwapMidLength, + showVWapMedium, + vwapMidBuffer, + vwapMidColorBuffer, + vwapMidStateBuffer // + ); + + // + // Fast ... + CalculateVWAP( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume, + // + vwapSlowLength, + showVWapSlow, + vwapSlowBuffer, + vwapSlowColorBuffer, + vwapSlowStateBuffer // + ); +} + +/** + * Calculate Different VWaps ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateDonchains( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + CalculateDonchain( + // + bar_index, + prevCalculated, + ratesTotal, + // + open, + high, + close, + low, + tickVolume, + // + donchainLength, + // + donOpenUpperBuffer, + donOpenLowerBuffer, + donHighUpperBuffer, + donHighLowerBuffer, + donLowUpperBuffer, + donLowLowerBuffer, + donCloseUpperBuffer, + donCloseLowerBuffer // + ); +} + +/** + * Calculate Valid Vales and Peaks ... + * + * @param bar_index: Integer, current Bar Index ... + */ +void CalculateValidPeaksAndVales( + int bar_index, + int prevCalculated // +) +{ + // + int minRepetition = donchainLength; + int maxAllowedLoopbackBars = 576; + + // + int barIndex = bar_index; + int start = barIndex; + int end = start + maxAllowedLoopbackBars; + + // + double peak = 0; + int peakRepeate = 0; + int peakToBarIndex = 0; + int peakFromBarIndex = 0; + + // + double vale = 0; + int valeRepeate = 0; + int valeToBarIndex = 0; + int valeFromBarIndex = 0; + + // + bool canLookupPeak = true; + bool canLookupVale = true; + bool canLookup = true; + + // + while (canLookup) + { + // + // Check Peak ... + if (canLookupPeak) + { + // + double iPeak = peaksBuffer[barIndex]; + if (iPeak != peak) + { + // + if (peak != 0 && + peakRepeate >= minRepetition) + { + // + canLookupPeak = false; + } + else + { + // + peak = iPeak; + peakRepeate = 0; + peakFromBarIndex = 0; + peakToBarIndex = barIndex; + } + } + else if (iPeak == peak) + { + // + peakRepeate++; + peakFromBarIndex = barIndex; + } + } + + // + // Check Vale ... + if (canLookupVale) + { + // + double iVale = valesBuffer[barIndex]; + if (iVale != vale) + { + // + if (vale != 0 && + valeRepeate >= minRepetition) + { + canLookupVale = false; + } + else + { + // + vale = iVale; + valeRepeate = 0; + valeFromBarIndex = 0; + valeToBarIndex = barIndex; + } + } + else if (iVale == vale) + { + // + valeRepeate++; + valeFromBarIndex = barIndex; + } + } + + // + canLookup = barIndex < end && + (canLookupPeak || + canLookupVale); + if (canLookup) + { + barIndex++; + } + } + + // + if (!canLookupPeak) + { + validPeaksBuffer[bar_index] = peak; + } + else + { + // + double lastValidPeak = prevCalculated == 0 + ? 0 + : validPeaksBuffer[bar_index + 1]; + + // + validPeaksBuffer[bar_index] = lastValidPeak; + } + + // + if (!canLookupVale) + { + validValesBuffer[bar_index] = vale; + } + else + { + // + double lastValidVale = prevCalculated == 0 + ? 0 + : validValesBuffer[bar_index + 1]; + + // + validValesBuffer[bar_index] = lastValidVale; + } +} + +/** + * Calculate Fibonacci Levels ... + * + * @param bar_index: Integer, current Bar Index ... + */ +void CalculateFibonacci( + int bar_index // +) +{ + // + double fiboUpper = 0; + double fiboLower = 0; + + // + fiboUpper = peaksBuffer[bar_index]; + fiboLower = valesBuffer[bar_index]; + + // + // Level 1 ... + bool canCalculateFiboLevel1 = fiboLevel1 > 0; + if (canCalculateFiboLevel1) + { + // + double iFib = GetFibonacciLevel( + fiboUpper, + fiboLower, + fiboLevel1, + 1 // + ); + + // + fl1Buffer[bar_index] = iFib; + } + + // + // Level 2 ... + bool canCalculateFiboLevel2 = fiboLevel2 > 0; + if (canCalculateFiboLevel2) + { + // + double iFib = GetFibonacciLevel( + fiboUpper, + fiboLower, + fiboLevel2, + 1 // + ); + + // + fl2Buffer[bar_index] = iFib; + } + + // + // Level 3 ... + bool canCalculateFiboLevel3 = fiboLevel3 > 0; + if (canCalculateFiboLevel3) + { + // + double iFib = GetFibonacciLevel( + fiboUpper, + fiboLower, + fiboLevel3, + 1 // + ); + + // + fl3Buffer[bar_index] = iFib; + } + + // + // Level 4 ... + bool canCalculateFiboLevel4 = fiboLevel4 > 0; + if (canCalculateFiboLevel4) + { + // + double iFib = GetFibonacciLevel( + fiboUpper, + fiboLower, + fiboLevel4, + 1 // + ); + + // + fl4Buffer[bar_index] = iFib; + } + + // + // Level 5 ... + bool canCalculateFiboLevel5 = fiboLevel5 > 0; + if (canCalculateFiboLevel5) + { + // + double iFib = GetFibonacciLevel( + fiboUpper, + fiboLower, + fiboLevel5, + 1 // + ); + + // + fl5Buffer[bar_index] = iFib; + } + + // +} + +// \ No newline at end of file diff --git a/BKPS/14031003/Indicators/x-saherelm.xcc.ex5 b/BKPS/14031003/Indicators/x-saherelm.xcc.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..348ff56f67ad2e12b2384fd7dbbe911cf8b47208 GIT binary patch literal 13184 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 literal 0 HcmV?d00001 diff --git a/BKPS/14031003/Indicators/x-saherelm.xcc.mq5 b/BKPS/14031003/Indicators/x-saherelm.xcc.mq5 new file mode 100644 index 0000000..71bdd19 --- /dev/null +++ b/BKPS/14031003/Indicators/x-saherelm.xcc.mq5 @@ -0,0 +1,437 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Candle Styles +// --------------------------------------------------- +// Name: XCC +// Description: Candle Styles ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XCC Indicator" +#property strict + +// +// START Constants ... +// + +// +// Indicator Short Name ... +#define ShortName "XCC" + +// +// Holds an SnapShot of Charts Configuration ... +struct XChartStyle +{ + // + // chart's ID ... + long chartId; + // + // chart's mode ... + ENUM_CHART_MODE mode; + // + // show bid line ... + bool showBidLine; + // + // show ask line ... + bool showAskLine; + // + // show grids on chart ... + bool showGrid; + // + // show volumes ... + bool showVolumes; + // + // Displaying trade levels in the chart (levels of open positions, Stop Loss, Take Profit and pending orders) ... + bool showTradeLevels; + // + // chart autoscroll ... + bool autoScroll; + // + // chart quick navigation state ... + bool quickNavigation; + // + // chart's foreground color ... + color foreGroundColor; + // + // chart's background color ... + color backGroundColor; + // + // Up Color ... + color upColor; + // + // Down Color ... + color downColor; + // + // Bullish color ... + color bullishColor; + // + // Bearish color ... + color bearishColor; + // + // grid color ... + color gridColor; + // + // bid line color ... + color bidLineColor; + // + // ask line color ... + color askLineColor; + // + // line mode and doji candlestick color ... + color lineColor; + // + // Color of stop order levels (Stop Loss and Take Profit) ... + color stopColor; + // + // volumes color ... + color volumesColor; +}; + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input group "Chart Style"; +input ENUM_CHART_MODE mode = CHART_CANDLES; // Mode +input color upColor = 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/14031003/Indicators/x-saherelm.xct.ex5 b/BKPS/14031003/Indicators/x-saherelm.xct.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..4e8e9f0804724c533fdb6a67da17731fa9110a56 GIT binary patch literal 18038 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 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/14031003/Libraries/x-saherelm.common.lib.mq5 b/BKPS/14031003/Libraries/x-saherelm.common.lib.mq5 new file mode 100644 index 0000000..10d9006 --- /dev/null +++ b/BKPS/14031003/Libraries/x-saherelm.common.lib.mq5 @@ -0,0 +1,13367 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Common Library +// -------------------------------------- +// Name: XCommonLib +// Description: provide all commonly used functions ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.x-md5.class.mq5" + +// +#include + +// +// Models ... + +// +// Specified Price Type ... +enum ENUM_X_PRICE +{ + X_PRICE_HIGH, + X_PRICE_OPEN, + X_PRICE_CLOSE, + X_PRICE_LOW, + X_PRICE_UP, + X_PRICE_DOWN +}; + +// +enum ENUM_X_DIRECTION +{ + X_DIRECTION_ALL, // All + X_DIRECTION_NONE, // None + X_DIRECTION_BULLISH, // Bullish + X_DIRECTION_BEARISH, // Bearish +}; + +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; +} + +// +// Swing Types Enum ... +enum ENUM_X_SWING_TYPE +{ + X_NO_SWING = 0, + X_SWING_HIGH = 1, + X_SWING_LOW = -1, +}; + +// +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: + result = MODE_LOW; + break; + } + + // + return result; +} + +// +// Find Swing Points ... +int FindSwing( + string mSymbol, // Trading Symbol ... + ENUM_TIMEFRAMES mPeriod, // Trading Period ... + ENUM_X_SWING_TYPE mMode, // Swing Based On Price mode ... + int mLength, // Loopback ... + int bar_index // BarIndex ... +) +{ + // + int result = -1; + + // + if (StringLen(mSymbol) == 0 || (mMode != X_SWING_HIGH && mMode != X_SWING_LOW)) + { + return result; + } + + // + int current = bar_index; + int founded = FindNextSwing( + mSymbol, + mPeriod, + mMode, + (mLength * 2) + 1, + current - mLength); + + // + while (founded != current) + { + // + current = FindNextSwing( + mSymbol, + mPeriod, + mMode, + mLength, + current + 1); + + // + founded = FindNextSwing( + mSymbol, + mPeriod, + mMode, + (mLength * 2) + 1, + current - mLength); + } + + // + result = current; + + // + return result; +} + +// +// Find Next Swing ... +int FindNextSwing( + string mSymbol, // Trading Symbol ... + ENUM_TIMEFRAMES mPeriod, // Trading Period ... + ENUM_X_SWING_TYPE mMode, // Swing Based On Price mode ... + int mLength, // Loopback ... + int bar_index // BarIndex ... +) +{ + // + int result = -1; + + // + if (bar_index < 0) + { + mLength += bar_index; + bar_index = 0; + } + + // + ENUM_SERIESMODE mSeriesMode = ToSeriesMode(mMode); + + // + result = mMode == X_SWING_HIGH + ? iHighest( + mSymbol, + mPeriod, + mSeriesMode, + mLength, + bar_index) + : iLowest( + mSymbol, + mPeriod, + mSeriesMode, + mLength, + bar_index); + + // + return result; +} + +// +// XPERIOD Calculation Method ... +enum ENUM_X_PERIOD_METHOD +{ + // + X_PERIOD_NOTHING, // Nothing + X_PERIOD_AUTO, // Auto Select + X_PERIOD_MANUALLY // Manually +}; + +// +// Available Market Cycles ... +enum ENUM_X_MARKET_CYCLES +{ + // + X_MARKET_CYCLE_UNKNOWN, // Unknown Cycle + X_MARKET_CYCLE_SHORT, // Short Cycle + X_MARKET_CYCLE_MEDIUM, // Medium Cycle + X_MARKET_CYCLE_LONG, // Long Cycle + X_MARKET_CYCLE_HIND, // Hind Cycle +}; + +// +// Structs ... + +// +// Model Specified Ticks Info ... +struct XTick +{ + // + string symbol; // Symbol ... + datetime time; // Time ... + double bid; // Bid ... + double ask; // Ask ... + double spread; // Spread ... + long volume; // Volume ... + + // + // Constructor ... + void XTick() + { + Clean(); + } + + // + // Tools Functions ... + + /** + * Initial ... + * + * @param _symbol: Symbol ... + * @param _time: Time ... + * @param _bid: Bid Price ... + * @param _ask: Ask Price ... + * @param _volume: Tick Volume ... + */ + bool Init( + string _symbol, + datetime _time, + double _bid, + double _ask, + double _spread, + long _volume // + ) + { + // + bool result = false; + + // + result = IsValid(_symbol) && + IsValid(_time) && + _bid > 0 && + _ask > 0; + if (!result) + { + return result; + } + + // + bid = _bid; + ask = _ask; + time = _time; + symbol = _symbol; + spread = _spread; + + // + result = IsValid(); + + // + return result; + } + + /** + * Init Tick by Symbol ... + * + * @param _symbol: String ... + * + * @return ( bool ) + */ + bool Init(string _symbol) + { + // + bool result = false; + + // + result = IsValid(_symbol); + if (!result) + { + return result; + } + + // + datetime _time = TimeCurrent(); + double _bid = GetBid(_symbol); + double _ask = GetAsk(_symbol); + double _spread = GetSpread(_symbol); + long _volume = iTickVolume(_symbol, PERIOD_M1, 0); + + // + result = Init( + _symbol, + _time, + _bid, + _ask, + _spread, + _volume // + ); + + // + return result; + } + + /** + * Cleanup ... + */ + void Clean() + { + // + bid = 0; + ask = 0; + volume = 0; + time = NULL; + symbol = NULL; + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = IsValid(symbol) && + IsValid(time) && + bid > 0 && + ask > 0 && + volume >= 0; + + // + return result; + } + + // +}; + +// +// Model a Bar Remains Time ... +struct XBarRemainsTime +{ + // + int days; + int hours; + int minutes; + int seconds; + + // + // Constructor ... + XBarRemainsTime() + { + Clean(); + } + + // + // Always Calculate Current 0 Bar Timing ... + bool Init( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL // Trading Period + ) + { + // + bool result = false; + + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + int minuteSecoonds = 60; + int hourSeconds = minuteSecoonds * 60; + int daySeconds = 24 * hourSeconds; + + // + int periodSeconds = PeriodSeconds( + mPeriod); + datetime startTime = GetBarTime( + mSymbol, + mPeriod, + 0 + // + ); + + // + int secondsDiff = (int)startTime + periodSeconds - (int)TimeCurrent(); + + // + int mWorkingSecondsDiff = secondsDiff; + if (mWorkingSecondsDiff > daySeconds) + { + // + days = mWorkingSecondsDiff / daySeconds; + mWorkingSecondsDiff -= days * daySeconds; + } + if (mWorkingSecondsDiff > hourSeconds) + { + // + hours = mWorkingSecondsDiff / hourSeconds; + mWorkingSecondsDiff -= hours * hourSeconds; + } + if (mWorkingSecondsDiff > minuteSecoonds) + { + // + minutes = mWorkingSecondsDiff / minuteSecoonds; + mWorkingSecondsDiff -= minutes * minuteSecoonds; + } + seconds = mWorkingSecondsDiff; + + // + result = true; + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + days = 0; + hours = 0; + minutes = 0; + seconds = 0; + } + + // + // To String Representation ... + string ToString( + string dayId = "d", + string hourId = "h", + string minuteId = "m", + string secondId = "s", + string idSeparator = ": ", + string separator = ", ", + bool ignoreZeroValues = true + // + ) + { + // + string result = ""; + + // + // Days ... + if (!ignoreZeroValues || days > 0) + { + result += dayId + idSeparator + (string)days + separator; + } + + // + // Hours ... + if (!ignoreZeroValues || hours > 0) + { + // + string strHour = ToString(hours); + if (StringLen(strHour) == 1) + { + strHour = "0" + strHour; + } + + // + result += hourId + idSeparator + strHour + separator; + } + + // + // Minutes ... + if (!ignoreZeroValues || minutes > 0) + { + // + string strMinute = ToString(minutes); + if (StringLen(strMinute) == 1) + { + strMinute = "0" + strMinute; + } + + // + result += minuteId + idSeparator + strMinute + separator; + } + + // + // Seconds ... + if (!ignoreZeroValues || seconds > 0) + { + // + string strSec = ToString(seconds); + if (StringLen(strSec) == 1) + { + strSec = "0" + strSec; + } + + // + result += secondId + idSeparator + strSec; + } + + // + return result; + } +}; + +// +// Describe an Specific Candle ... +struct XOHCL +{ + // + // Props ... + + // + double high; + double open; + double close; + double low; + + // + string symbol; + datetime time; + ENUM_TIMEFRAMES period; + + // + // Constructor ... + XOHCL() + { + Clean(); + } + + // + // Init a Bar ... + // Using Bar Index ... + bool Init( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Period + int barIndex = 0 // Bar Index + ) + { + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + symbol = mSymbol; + period = mPeriod; + + // + time = iTime( + mSymbol, + mPeriod, + barIndex // + ); + + // + open = iOpen( + mSymbol, + mPeriod, + barIndex // + ); + 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); + + // + bool result = IsValid(); + + // + return result; + } + + // + // Init a Bar ... + // Using Bar Time ... + bool Init( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Period + datetime mTime = NULL // Bar Time + ) + { + // + mTime = NormalizeTime(mTime); + + // + int barIndex = iBarShift( + mSymbol, + mPeriod, + mTime, + false // + ); + + // + bool result = Init( + mSymbol, + mPeriod, + barIndex + // + ); + + // + return result; + } + + // + bool Init( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Period + double mOpen = 0, // Open + double mHigh = 0, // High + double mClose = 0, // Close + double mLow = 0, // Low + int barIndex = 0 // Bar Index + ) + { + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + symbol = mSymbol; + period = mPeriod; + + // + time = iTime( + mSymbol, + mPeriod, + barIndex + // + ); + + // + open = mOpen; + high = mHigh; + close = mClose; + low = mLow; + + // + return IsValid(); + } + + // + bool Init( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Period + double mOpen = 0, // Open + double mHigh = 0, // High + double mClose = 0, // Close + double mLow = 0, // Low + datetime mTime = NULL // Bar Time + ) + { + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + symbol = mSymbol; + period = mPeriod; + + // + int barIndex = iBarShift( + symbol, + period, + mTime); + + // + time = iTime( + mSymbol, + mPeriod, + barIndex + // + ); + + // + open = mOpen; + high = mHigh; + close = mClose; + low = mLow; + + // + return IsValid(); + } + + // + // Tools ... + + // + void Clean() + { + // + high = 0; + open = 0; + close = 0; + low = 0; + + // + time = NULL; + symbol = NULL; + period = NULL; + } + + // + // Validate Bar ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + high > 0 && + open > 0 && + close > 0 && + low > 0 + // + ; + + // + return result; + } + + // + 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; + } + + // + switch (mPType) + { + // + case X_PRICE_OPEN: + result = open; + break; + // + case X_PRICE_HIGH: + result = high; + break; + // + case X_PRICE_CLOSE: + result = close; + break; + // + case X_PRICE_LOW: + result = low; + break; + // + case X_PRICE_UP: + result = GetUp(); + break; + // + case X_PRICE_DOWN: + result = GetDown(); + break; + } + + // + return result; + } + + // + // Retrieve Price base On Series Mode ... + double GetPrice(ENUM_SERIESMODE mMode) + { + // + ENUM_X_PRICE mXMode = ToPrice(mMode); + + // + return GetPrice(mXMode); + } + + // + // Calculate Applied Price ... + double GetPrice( + ENUM_APPLIED_PRICE mAppliedTo // Select Application Method + ) + { + // + double result = 0; + + // + // Calculate Applied Price ... + switch (mAppliedTo) + { + // + case PRICE_CLOSE: + result = close; + break; + + // + case PRICE_OPEN: + result = open; + break; + + // + case PRICE_HIGH: + result = high; + break; + + // + case PRICE_LOW: + result = low; + break; + + // + case PRICE_MEDIAN: + result = (high + low) / 2; + break; + + // + case PRICE_TYPICAL: + result = (high + low + close) / 3; + break; + + // + case PRICE_WEIGHTED: + result = (high + low + close + close) / 4; + break; + } + + // + return result; + } + + // + // 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 Bar Mid Line ... + double GetMid() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = (high + low) / 2; + + // + return result; + } + + // + // Calculate up Price ... + double GetUp() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = MathMax(open, close); + + // + return result; + } + + // + // Calculate Down Price ... + double GetDown() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = MathMin(open, close); + + // + return result; + } + + // + // Calculate Bar Body ... + double GetBody() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetUp() - GetDown(); + + // + return result; + } + + // + // Calculate Bar Range ... + double GetRange() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = high - low; + + // + return result; + } + + // + // Calculate Bar Shadows ... + double GetShadows() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetRange() - GetBody(); + + // + return result; + } + + // + // Calculate Bar High Shadow ... + double GetHighShadow() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = + // + high - GetUp() + // + ; + + // + return result; + } + + // + // Calculate Bar Low Shadow ... + double GetLowShadow() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = + // + GetDown() - low; + // + ; + + // + return result; + } + + // + // Check Bar is Bullish ... + bool IsBullish() + { + // + bool result = false; + + // + if (!IsValid()) + { + return result; + } + + // + result = open < close; + + // + return result; + } + + // + // Check Bar is Bearish ... + bool IsBearish() + { + // + bool result = false; + + // + if (!IsValid()) + { + return result; + } + + // + result = open > close; + + // + return result; + } + + // + // 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 IsStrong( + double percent = 50 // Percent of Body + ) + { + // + bool result = false; + + // + result = IsValid() && Index() > 0; + if (!result) + { + return result; + } + + // + result = + (GetRange() * percent) / 100 <= GetBody(); + + // + return result; + } + + // + bool HasStrongLowShadow( + double percent = 50, // Percent of Body + int __loopback = 2, + double _sharpRatio = 2.5 // + ) + { + // + bool result = false; + + // + result = IsValid() && Index() > 0; + if (!result) + { + return result; + } + + // + result = + (GetRange() * percent) / 100 <= GetLowShadow(); + if (!result) + { + return result; + } + + // + if (__loopback < 0) + { + __loopback = 2; + } + + // + if (_sharpRatio < 0) + { + _sharpRatio = 2.5; + } + + // + result = Index() > __loopback; + if (!result) + { + return result; + } + + // + // Get Highest High and Lowest Low in loopback Range ... + int startIndex = Index() - __loopback; + int endIndex = Index() + __loopback; + int requiredBars = MathAbs(endIndex - startIndex); + + // + // Highs ... + double highs[]; + int copiedHighs = CopyHigh( + symbol, + period, + startIndex, + requiredBars, + highs // + ); + + // + result = copiedHighs == requiredBars; + if (!result) + { + return result; + } + + // + int highestHighIDX = ArrayMaximum(highs); + result = IsValidIndex(highestHighIDX); + if (!result) + { + return result; + } + + // + double highestHigh = highs[highestHighIDX]; + + // + // Lows ... + double lows[]; + int copiedLows = CopyLow( + symbol, + period, + startIndex, + requiredBars, + lows // + ); + + // + result = copiedLows == requiredBars; + if (!result) + { + return result; + } + + // + int lowestLowIDX = ArrayMinimum(lows); + result = IsValidIndex(lowestLowIDX); + if (!result) + { + return result; + } + + // + double lowestLow = lows[lowestLowIDX]; + + // + result = low == lowestLow && + highestHigh > high; + if (!result) + { + return result; + } + + // + // Try to Validate Sharp Ratio ... + + // + Clean(highs); + Clean(lows); + + // + // Left Side ... + startIndex = Index() + 1; + endIndex = startIndex + (__loopback / 2) - 1; + requiredBars = MathAbs(endIndex - startIndex); + + // + copiedHighs = CopyHigh( + symbol, + period, + startIndex, + requiredBars, + highs // + ); + result = copiedHighs == requiredBars; + if (!result) + { + return result; + } + + // + highestHighIDX = ArrayMaximum(highs); + result = IsValidIndex(highestHighIDX); + if (!result) + { + return result; + } + + // + highestHigh = highs[highestHighIDX]; + + // + copiedLows = CopyLow( + symbol, + period, + startIndex, + requiredBars, + lows // + ); + result = copiedLows == requiredBars; + if (!result) + { + return result; + } + + // + lowestLowIDX = ArrayMinimum(lows); + result = IsValidIndex(lowestLowIDX); + if (!result) + { + return result; + } + + // + lowestLow = lows[lowestLowIDX]; + + // + double leftDiff = highestHigh - lowestLow; + + // + Clean(highs); + Clean(lows); + + // + // Right Side ... + startIndex = Index() - 1; + endIndex = startIndex - (__loopback / 2) + 1; + requiredBars = MathAbs(endIndex - startIndex); + + // + copiedHighs = CopyHigh( + symbol, + period, + startIndex, + requiredBars, + highs // + ); + result = copiedHighs == requiredBars; + if (!result) + { + return result; + } + + // + highestHighIDX = ArrayMaximum(highs); + result = IsValidIndex(highestHighIDX); + if (!result) + { + return result; + } + + // + highestHigh = highs[highestHighIDX]; + + // + copiedLows = CopyLow( + symbol, + period, + startIndex, + requiredBars, + lows // + ); + result = copiedLows == requiredBars; + if (!result) + { + return result; + } + + // + lowestLowIDX = ArrayMinimum(lows); + result = IsValidIndex(lowestLowIDX); + if (!result) + { + return result; + } + + // + lowestLow = lows[lowestLowIDX]; + + // + double rightDiff = highestHigh - lowestLow; + double diff = MathMax(leftDiff, rightDiff); + result = GetLowShadow() >= (diff / 100) * _sharpRatio; + + // + return result; + } + + // + bool HasStrongHighShadow( + double percent = 50, // Percent of Body + int __loopback = 2, + double _sharpRatio = 2.5 // + ) + { + // + bool result = false; + + // + result = IsValid() && Index() > 0; + if (!result) + { + return result; + } + + // + result = + (GetRange() * percent) / 100 <= GetHighShadow(); + if (!result) + { + return result; + } + + // + if (__loopback < 0) + { + __loopback = 2; + } + + // + if (_sharpRatio < 0) + { + _sharpRatio = 2.5; + } + + // + result = Index() > __loopback; + if (!result) + { + return result; + } + + // + // Get Highest High and Lowest Low in loopback Range ... + int startIndex = Index() - __loopback; + int endIndex = Index() + __loopback; + int requiredBars = MathAbs(endIndex - startIndex); + + // + // Highs ... + double highs[]; + int copiedHighs = CopyHigh( + symbol, + period, + startIndex, + requiredBars, + highs // + ); + + // + result = copiedHighs == requiredBars; + if (!result) + { + return result; + } + + // + int highestHighIDX = ArrayMaximum(highs); + result = IsValidIndex(highestHighIDX); + if (!result) + { + return result; + } + + // + double highestHigh = highs[highestHighIDX]; + + // + // Lows ... + double lows[]; + int copiedLows = CopyLow( + symbol, + period, + startIndex, + requiredBars, + lows // + ); + + // + result = copiedLows == requiredBars; + if (!result) + { + return result; + } + + // + int lowestLowIDX = ArrayMinimum(lows); + result = IsValidIndex(lowestLowIDX); + if (!result) + { + return result; + } + + // + double lowestLow = lows[lowestLowIDX]; + + // + result = high == highestHigh && + lowestLow < low; + if (!result) + { + return result; + } + + // + // Try to Validate Sharp Ratio ... + + // + Clean(highs); + Clean(lows); + + // + // Left Side ... + startIndex = Index() + 1; + endIndex = startIndex + (__loopback / 2) - 1; + requiredBars = MathAbs(endIndex - startIndex); + + // + copiedHighs = CopyHigh( + symbol, + period, + startIndex, + requiredBars, + highs // + ); + result = copiedHighs == requiredBars; + if (!result) + { + return result; + } + + // + highestHighIDX = ArrayMaximum(highs); + result = IsValidIndex(highestHighIDX); + if (!result) + { + return result; + } + + // + highestHigh = highs[highestHighIDX]; + + // + copiedLows = CopyLow( + symbol, + period, + startIndex, + requiredBars, + lows // + ); + result = copiedLows == requiredBars; + if (!result) + { + return result; + } + + // + lowestLowIDX = ArrayMinimum(lows); + result = IsValidIndex(lowestLowIDX); + if (!result) + { + return result; + } + + // + lowestLow = lows[lowestLowIDX]; + + // + double leftDiff = highestHigh - lowestLow; + + // + Clean(highs); + Clean(lows); + + // + // Right Side ... + startIndex = Index() - 1; + endIndex = startIndex - (__loopback / 2) + 1; + requiredBars = MathAbs(endIndex - startIndex); + + // + copiedHighs = CopyHigh( + symbol, + period, + startIndex, + requiredBars, + highs // + ); + result = copiedHighs == requiredBars; + if (!result) + { + return result; + } + + // + highestHighIDX = ArrayMaximum(highs); + result = IsValidIndex(highestHighIDX); + if (!result) + { + return result; + } + + // + highestHigh = highs[highestHighIDX]; + + // + copiedLows = CopyLow( + symbol, + period, + startIndex, + requiredBars, + lows // + ); + result = copiedLows == requiredBars; + if (!result) + { + return result; + } + + // + lowestLowIDX = ArrayMinimum(lows); + result = IsValidIndex(lowestLowIDX); + if (!result) + { + return result; + } + + // + lowestLow = lows[lowestLowIDX]; + + // + double rightDiff = highestHigh - lowestLow; + double diff = MathMax(leftDiff, rightDiff); + result = GetHighShadow() >= (diff / 100) * _sharpRatio; + + // + return result; + } + + // + bool IsStrongBullish( + double percent = 50 // Percent of Body + ) + { + // + bool result = false; + + // + result = + IsStrong(percent) && IsBullish(); + + // + return result; + } + + // + bool IsStrongBearish( + double percent = 50 // Percent of Body + ) + { + // + bool result = false; + + // + result = + IsStrong(percent) && IsBearish(); + + // + return result; + } + + // + bool IsSharpBullish( + int __loopback = 2, + double _sharpRatio = 2.5 // + ) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + if (__loopback < 0) + { + __loopback = 2; + } + + // + if (_sharpRatio < 0) + { + _sharpRatio = 2.5; + } + + // + int hIDX = FindHighestIndex( + __loopback, + MODE_HIGH // + ); + int lIDX = FindLowestIndex( + __loopback, + MODE_LOW // + ); + + // + result = + // + hIDX >= 0 && + lIDX >= 0 && + MathAbs(hIDX - Index()) < 2 + // + ; + + // + if (!result) + { + return result; + } + + // + XOHCL hBar; + result = hBar.Init( + symbol, + period, + hIDX // + ); + if (!result) + { + return result; + } + + // + XOHCL lBar; + result = lBar.Init( + symbol, + period, + lIDX // + ); + if (!result) + { + return result; + } + + // + double lhDif = hBar.high - lBar.low; + + // + int hhIDX = hBar.FindHighestIndex( + __loopback, + MODE_HIGH // + ); + + // + int llIDX = lBar.FindLowestIndex( + __loopback, + MODE_LOW // + ); + + // + XOHCL hhBar; + result = hhBar.Init( + symbol, + period, + hhIDX + hIDX // + ); + if (!result) + { + return result; + } + + // + XOHCL llBar; + result = llBar.Init( + symbol, + period, + llIDX + lIDX // + ); + if (!result) + { + return result; + } + + // + double llhhDif = hhBar.high - llBar.low; + + // + result = + // + lBar.low > llBar.low && + hBar.high > hhBar.high && + lhDif >= llhhDif * _sharpRatio + // + ; + + // + return result; + } + + // + bool IsSharpBearish( + int __loopback = 2, + double _sharpRatio = 2.5 // + ) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + if (__loopback < 0) + { + __loopback = 2; + } + + // + if (_sharpRatio < 0) + { + _sharpRatio = 2.5; + } + + // + int hIDX = FindHighestIndex( + __loopback, + MODE_HIGH // + ); + int lIDX = FindLowestIndex( + __loopback, + MODE_LOW // + ); + + // + result = + // + hIDX >= 0 && + lIDX >= 0 && + MathAbs(hIDX - Index()) < 2 + // + ; + + // + if (!result) + { + return result; + } + + // + XOHCL hBar; + result = hBar.Init( + symbol, + period, + hIDX // + ); + if (!result) + { + return result; + } + + // + XOHCL lBar; + result = lBar.Init( + symbol, + period, + lIDX // + ); + if (!result) + { + return result; + } + + // + double lhDif = hBar.high - lBar.low; + + // + int hhIDX = hBar.FindHighestIndex( + __loopback, + MODE_HIGH // + ); + + // + int llIDX = lBar.FindLowestIndex( + __loopback, + MODE_LOW // + ); + + // + XOHCL hhBar; + result = hhBar.Init( + symbol, + period, + hhIDX + hIDX // + ); + if (!result) + { + return result; + } + + // + XOHCL llBar; + result = llBar.Init( + symbol, + period, + llIDX + lIDX // + ); + if (!result) + { + return result; + } + + // + double llhhDif = hhBar.high - llBar.low; + + // + result = + // + lBar.low < llBar.low && + hBar.high < hhBar.high && + lhDif >= llhhDif * _sharpRatio + // + ; + + // + return result; + } + + // + // Find Lowest Bar Index ... + int FindHighestIndex( + int mLength, // Loopback ... + ENUM_SERIESMODE mMode // Calculation mode + ) + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + if (mLength < 2) + { + mLength = 2; + } + + // + result = iHighest( + symbol, + period, + mMode, + mLength, + Index()); + + // + return result; + } + + // + // Find Lowest ... + double FindHighest( + int mLength, // Loopback ... + ENUM_SERIESMODE mMode // Calculation mode + ) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + int idx = FindHighestIndex( + mLength, + mMode); + if (idx <= -1) + { + return result; + } + + // + XOHCL iH; + result = iH.Init( + symbol, + period, + idx + // + ); + if (!result) + { + return result; + } + + // + result = iH.GetPrice(mMode); + + // + return result; + } + + // + // Find Lowest Bar Index ... + int FindLowestIndex( + int mLength, // Loopback ... + ENUM_SERIESMODE mMode // Calculation mode + ) + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + if (mLength < 2) + { + mLength = 2; + } + + // + result = iLowest( + symbol, + period, + mMode, + mLength, + Index()); + + // + return result; + } + + // + // Find Lowest ... + double FindLowest( + int mLength, // Loopback ... + ENUM_SERIESMODE mMode // Calculation mode + ) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + int idx = FindLowestIndex( + mLength, + mMode); + if (idx <= -1) + { + return result; + } + + // + XOHCL iL; + result = iL.Init( + symbol, + period, + idx + // + ); + if (!result) + { + return result; + } + + // + result = iL.GetPrice(mMode); + + // + return result; + } + + // + // Retrieve Bullish Pressure ... + double GetBullishPressure( + int __loopback = 7 // + ) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + XOHCL bars[]; + int barsCount = GetBars( + bars, + symbol, + period, + Index(), + __loopback // + ); + if (!IsValidSize(barsCount)) + { + return result; + } + + // + for (int i = 0; i < barsCount; i++) + { + result += bars[i].GetLowShadow(); + } + + // + return result; + } + + // + // Retrieve Bearish Pressure ... + double GetBearishPressure( + int __loopback = 7 // + ) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + XOHCL bars[]; + int barsCount = GetBars( + bars, + symbol, + period, + Index(), + __loopback // + ); + if (!IsValidSize(barsCount)) + { + return result; + } + + // + for (int i = 0; i < barsCount; i++) + { + result += bars[i].GetHighShadow(); + } + + // + return result; + } + + // + bool HasBullishPressure( + int __loopback = 7 // + ) + { + // + bool result = false; + + // + if (__loopback < 0) + { + __loopback = 7; + } + + // + double bullishPressure = GetBullishPressure(__loopback); + double bearishPressure = GetBearishPressure(__loopback); + + // + result = + // + bullishPressure > 0 && + bearishPressure >= 0 && + bullishPressure > bearishPressure + // + ; + + // + return result; + } + + // + bool HasBearishPressure( + int __loopback = 7 // + ) + { + // + bool result = false; + + // + if (__loopback < 0) + { + __loopback = 7; + } + + // + double bullishPressure = GetBullishPressure(__loopback); + double bearishPressure = GetBearishPressure(__loopback); + + // + result = + // + bearishPressure > 0 && + bullishPressure >= 0 && + bearishPressure > bullishPressure + // + ; + + // + return result; + } + + // + // Retrieve Bullish Power ... + double GetBullishPower( + int __loopback = 7 // + ) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + XOHCL bars[]; + int barsCount = GetBars( + bars, + symbol, + period, + Index(), + __loopback // + ); + if (!IsValidSize(barsCount)) + { + return result; + } + + // + for (int i = 0; i < barsCount; i++) + { + // + if (bars[i].IsBullish()) + { + result += bars[i].GetBody(); + } + } + + // + return result; + } + + // + // Retrieve Bearish Pressure ... + double GetBearishPower( + int __loopback = 7 // + ) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + XOHCL bars[]; + int barsCount = GetBars( + bars, + symbol, + period, + Index(), + __loopback // + ); + if (!IsValidSize(barsCount)) + { + return result; + } + + // + for (int i = 0; i < barsCount; i++) + { + // + if (bars[i].IsBearish()) + { + result += bars[i].GetBody(); + } + } + + // + return result; + } + + // + bool HasBullishPower( + int __loopback = 7 // + ) + { + // + bool result = false; + + // + if (__loopback < 0) + { + __loopback = 7; + } + + // + double bullishPressure = GetBullishPower(__loopback); + double bearishPressure = GetBearishPower(__loopback); + + // + result = + // + bullishPressure > 0 && + bearishPressure >= 0 && + bullishPressure > bearishPressure + // + ; + + // + return result; + } + + // + bool HasBearishPower( + int __loopback = 7 // + ) + { + // + bool result = false; + + // + if (__loopback < 0) + { + __loopback = 7; + } + + // + double bullishPressure = GetBullishPower(__loopback); + double bearishPressure = GetBearishPower(__loopback); + + // + result = + // + bearishPressure > 0 && + bullishPressure >= 0 && + bearishPressure > bullishPressure + // + ; + + // + return result; + } + + // + // Decisions ... + + // + bool IsBullishDecision( + double percent = 70 // Percent of Body + ) + { + // + bool result = false; + + // + result = + // + IsValid() && + Index() > 0 && + IsBullish() && + (GetRange() * percent) / 100 <= GetBody() + // + ; + + // + return result; + } + + // + bool IsBearishDecision( + double percent = 70 // Percent of Body + ) + { + // + bool result = false; + + // + result = + // + IsValid() && + Index() > 0 && + IsBearish() && + (GetRange() * percent) / 100 <= GetBody() + // + ; + + // + return result; + } + + // + // Touches ... + + // + bool IsBullishTouched(double price) + { + // + bool result = false; + + // + result = + // + IsValid() + // + && + // + price > 0 + // + ; + if (!result) + { + return result; + } + + // + XOHCL pBar; + result = GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + result = + // + (pBar.low <= price || + pBar.GetDown() <= price) + // + && + // + (pBar.high > price || + pBar.GetUp() > price) + // + && + // + open > price && + low > price + // + ; + + // + return result; + } + + // + bool IsBearishTouched(double price) + { + // + bool result = false; + + // + result = + // + IsValid() + // + && + // + price > 0 + // + ; + if (!result) + { + return result; + } + + // + XOHCL pBar; + result = GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + result = + // + (pBar.high >= price || + pBar.GetUp() >= price) + // + && + // + (pBar.low < price || + pBar.GetDown() < price) + // + && + // + open < price && + high < price + // + ; + + // + return result; + } + + // + // Candlestic Patterns ... + + // + // Check Doji ... + bool IsDoji() + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = IsValid() && Index() > 0; + if (!result) + { + return result; + } + + // + result = open == close; + + // + return result; + } + + // + // Check Hammer ... + bool IsHammer( + double _upShadowFactor = 0.1, + double _downShadowFactor = 0.6, + bool applyFib382Check = true, + bool applyPrevShadowCheck = true // + ) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = IsValid() && Index() > 0; + if (!result) + { + return result; + } + + // + if (_upShadowFactor < 0) + { + _upShadowFactor = 0.1; + } + + // + if (_downShadowFactor < 0) + { + _upShadowFactor = 0.6; + } + + // + double range = GetRange(); + + // + // Check Upper Shadow Must be 0 or Under 10% ... + double upShadow = GetHighShadow(); + result = upShadow < range * _upShadowFactor; + if (!result) + { + return result; + } + + // + // Check Down Shadow Must at least 60% ... + double downShadow = GetLowShadow(); + result = downShadow > range * _downShadowFactor; + if (!result) + { + return result; + } + + // + // Check Fib 382 ... + if (result && applyFib382Check) + { + // + double fib382 = GetFibonacciLevel( + high, + low, + 0.382, + -1 // + ); + result = GetDown() > fib382; + } + + // + // Check Shadow Based on Prev Bar ... + if (result && applyPrevShadowCheck) + { + // + XOHCL pBar; + result = GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + result = low < pBar.low; + } + + // + return result; + } + + // + // Check Sgooting Star ... + // Reversal Hammer ... + bool IsShootingStar( + double _upShadowFactor = 0.6, + double _downShadowFactor = 0.1, + bool applyFib382Check = true, + bool applyPrevShadowCheck = true // + ) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = IsValid() && Index() > 0; + if (!result) + { + return result; + } + + // + if (_upShadowFactor < 0) + { + _upShadowFactor = 0.6; + } + + // + if (_downShadowFactor < 0) + { + _upShadowFactor = 0.1; + } + + // + double range = GetRange(); + + // + // Check Upper Shadow Must be 0 or Under 10% ... + double upShadow = GetHighShadow(); + result = upShadow > range * _upShadowFactor; + if (!result) + { + return result; + } + + // + // Check Down Shadow Must at least 60% ... + double downShadow = GetLowShadow(); + result = downShadow < range * _downShadowFactor; + if (!result) + { + return result; + } + + // + // Check Fib 382 ... + if (result && applyFib382Check) + { + // + double fib382 = GetFibonacciLevel( + high, + low, + 0.382, + 1 // + ); + result = GetUp() < fib382; + } + + // + // Check Shadow Based on Prev Bar ... + if (result && applyPrevShadowCheck) + { + // + XOHCL pBar; + result = GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + result = high > pBar.high; + } + + // + return result; + } + + // + // Check Bullish Engulfing ... + bool IsBullishEngulfing( + double _engulfBarBodyFactor = 0.7 // + ) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = IsValid() && Index() > 0; + if (!result) + { + return result; + } + + // + if (_engulfBarBodyFactor < 0) + { + _engulfBarBodyFactor = 0.7; + } + + // + // Check Bar Is Bullish ... + result = IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Previous Bar ... + XOHCL pBar; + result = GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + double range = GetRange(); + double body = GetBody(); + + // + // Check Prev Bar Must Bearish ... + result = pBar.IsBearish(); + if (!result) + { + return result; + } + + // + // Check Shadows Engulf Prev Bar ... + result = + // + high > pBar.high && + low <= pBar.low + // + ; + if (!result) + { + return result; + } + + // + // Check Engulfed Bar Must Inside Engulfer Body ... + result = + // + GetUp() > pBar.GetUp() && + GetDown() < pBar.GetDown() + // + ; + if (!result) + { + return result; + } + + // + // Check Body of Engulfing Bar ... + if (result && _engulfBarBodyFactor > 0) + { + result = body >= range * _engulfBarBodyFactor; + } + + // + return result; + } + + // + // Check Bearish Engulfing ... + bool IsBearishEngulfing( + double _engulfBarBodyFactor = 0.7 // + ) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = IsValid() && Index() > 0; + if (!result) + { + return result; + } + + // + if (_engulfBarBodyFactor < 0) + { + _engulfBarBodyFactor = 0.7; + } + + // + // Check Bar Is Bearish ... + result = IsBearish(); + if (!result) + { + return result; + } + + // + // Retrieve Previous Bar ... + XOHCL pBar; + result = GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + double range = GetRange(); + double body = GetBody(); + + // + // Check Prev Bar Must Bullish ... + result = pBar.IsBullish(); + if (!result) + { + return result; + } + + // + // Check Shadows Engulf Prev Bar ... + result = high >= pBar.high && low < pBar.low; + if (!result) + { + return result; + } + + // + // Check Engulfed Bar Must Inside Engulfer Body ... + result = + // + GetUp() > pBar.GetUp() && + GetDown() < pBar.GetDown() + // + ; + if (!result) + { + return result; + } + + // + // Check Body of Engulfing Bar ... + if (result && _engulfBarBodyFactor > 0) + { + result = body >= range * _engulfBarBodyFactor; + } + + // + return result; + } + + // + // Check Morning Star Pattern ... + bool IsMorningStar( + double _middleRangeFactor = 0.3, + double _startBodyFactor = 0.6, + bool forceCheckMiddleBarDirection = true, + bool forceCheckStartBody = true // + ) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = IsValid() && Index() > 0; + if (!result) + { + return result; + } + + // + if (_middleRangeFactor < 0) + { + _middleRangeFactor = 0.3; + } + + // + if (_startBodyFactor < 0) + { + _startBodyFactor = 0.6; + } + + // + // Current Bar Must be Bullish ... + result = IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Previous Bar ... + XOHCL pBar; + result = GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // Prev Bar must be Bearish ... + if (result && forceCheckMiddleBarDirection) + { + // + result = pBar.IsBearish(); + if (!result) + { + return result; + } + } + + // + // Retrieve Previous Bar of Prev Bar ... + XOHCL ppBar; + result = pBar.GetPreviousBar(ppBar); + if (!result) + { + return result; + } + + // + // Prev Of Prev Bar Must be Bearish ... + result = ppBar.IsBearish(); + if (!result) + { + return result; + } + + // + double range = GetRange(); + double pRange = pBar.GetRange(); + double ppRange = ppBar.GetRange(); + + // + // Middle Bar must be Smaller than Ratio of other ... + result = + // + pRange < range * _middleRangeFactor && + pRange < ppRange * _middleRangeFactor + // + ; + if (!result) + { + return result; + } + + // + if (result && forceCheckStartBody) + { + // + result = ppBar.GetBody() > ppRange * _startBodyFactor; + if (!result) + { + return result; + } + } + + // + return result; + } + + // + // Check Evening Star Pattern ... + bool IsEveningStar( + double _middleRangeFactor = 0.3, + double _startBodyFactor = 0.6, + bool forceCheckMiddleBarDirection = true, + bool forceCheckStartBody = true // + ) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = IsValid() && Index() > 0; + if (!result) + { + return result; + } + + // + if (_middleRangeFactor < 0) + { + _middleRangeFactor = 0.3; + } + + // + if (_startBodyFactor < 0) + { + _startBodyFactor = 0.6; + } + + // + // Current Bar Must be Bearish ... + result = IsBearish(); + if (!result) + { + return result; + } + + // + // Retrieve Previous Bar ... + XOHCL pBar; + result = GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // Prev Bar must be Bullish ... + if (result && forceCheckMiddleBarDirection) + { + // + result = pBar.IsBullish(); + if (!result) + { + return result; + } + } + + // + // Retrieve Previous Bar of Prev Bar ... + XOHCL ppBar; + result = pBar.GetPreviousBar(ppBar); + if (!result) + { + return result; + } + + // + // Prev Of Prev Bar Must be Bullish ... + result = ppBar.IsBullish(); + if (!result) + { + return result; + } + + // + double range = GetRange(); + double pRange = pBar.GetRange(); + double ppRange = ppBar.GetRange(); + + // + // Middle Bar must be Smaller than Ratio of other ... + result = + // + pRange < range * _middleRangeFactor && + pRange < ppRange * _middleRangeFactor + // + ; + if (!result) + { + return result; + } + + // + if (result && forceCheckStartBody) + { + // + result = ppBar.GetBody() > ppRange * _startBodyFactor; + if (!result) + { + return result; + } + } + + // + return result; + } + + // + // Bullish Marubozu ... + bool IsBullishMarubozu() + { + // + bool result = false; + + // + result = IsValid() && Index() > 0; + if (!result) + { + return result; + } + + // + result = IsBullish(); + if (!result) + { + return result; + } + + // + result = + // + GetUp() == high && + GetDown() == low + // + ; + + // + return result; + } + + // + // Bearish Marubozu ... + bool IsBearishMarubozu() + { + // + bool result = false; + + // + result = IsValid() && Index() > 0; + if (!result) + { + return result; + } + + // + result = IsBearish(); + if (!result) + { + return result; + } + + // + result = + // + GetUp() == high && + GetDown() == low + // + ; + + // + return result; + } + + // + // Contextual Patterns ... + + // + // Check Swing High ... + bool IsSwingHigh() + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = IsValid() && Index() > 0; + if (!result) + { + return result; + } + + // + // Current Bar Must be Bearish ... + result = IsBearish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev Bar ... + XOHCL pBar; + result = GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // Prev Bar Must be Bullish ... + result = pBar.IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev of Prev Bar ... + XOHCL ppBar; + result = pBar.GetPreviousBar(ppBar); + if (!result) + { + return result; + } + + // + // Prev of Prev Bar Must be Bullish ... + result = ppBar.IsBullish(); + if (!result) + { + return result; + } + + // + // Check All Highs ... + result = + // + high < pBar.high && + pBar.high > ppBar.high + // + ; + + // + return result; + } + + // + // Find Simple 3 Candle Based Swing High ... + bool IsSimpleSwingHigh(double thresholdInPoint = 1) + { + // + bool result = false; + + // + int index = Index(); + result = index > 0; + if (!result) + { + return result; + } + + // + XOHCL nextBar; + result = GetNextBar(nextBar); + if (!result) + { + return result; + } + + // + XOHCL prevBar; + result = GetPreviousBar(prevBar); + if (!result) + { + return result; + } + + // + double point = GetPoints(symbol); + double requiredOffset = point * thresholdInPoint; + + // + result = + high > nextBar.high && + high > prevBar.high && + (thresholdInPoint <= 0 + ? true + : MathAbs( + MathMax( + nextBar.high, + prevBar.high) - + high) >= requiredOffset); + + // + return result; + } + + // + // Find Last Swing High ... + bool FindLastSwingHigh(XOHCL &swing) + { + // + bool result = false; + + // + swing.Clean(); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int totalBars = iBars( + symbol, + period // + ); + int maxAllowed = MathMin(100, (totalBars / 100)); + + // + int idx = Index(); + for (int i = idx; i <= idx + maxAllowed; i++) + { + // + swing.Clean(); + result = swing.Init( + symbol, + period, + i // + ); + if (!result) + { + // + swing.Clean(); + break; + } + + // + result = swing.IsSwingHigh(); + if (result) + { + break; + } + } + + // + return result; + } + + // + // Check Swing Low ... + bool IsSwingLow() + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = IsValid() && Index() > 0; + if (!result) + { + return result; + } + + // + // Current Bar Must be Bullish ... + result = IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev Bar ... + XOHCL pBar; + result = GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // Prev Bar Must be Bearish ... + result = pBar.IsBearish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev of Prev Bar ... + XOHCL ppBar; + result = pBar.GetPreviousBar(ppBar); + if (!result) + { + return result; + } + + // + // Prev of Prev Bar Must be Bearish ... + result = ppBar.IsBearish(); + if (!result) + { + return result; + } + + // + // Check All Lows ... + result = + // + low > pBar.low && + pBar.low < ppBar.low + // + ; + + // + return result; + } + + // + // Find Simple 3 Candle Based Swing Low ... + bool IsSimpleSwingLow(double thresholdInPoint = 1) + { + // + bool result = false; + + // + int index = Index(); + result = index > 0; + if (!result) + { + return result; + } + + // + XOHCL nextBar; + result = GetNextBar(nextBar); + if (!result) + { + return result; + } + + // + XOHCL prevBar; + result = GetPreviousBar(prevBar); + if (!result) + { + return result; + } + + // + double point = GetPoints(symbol); + double requiredOffset = point * thresholdInPoint; + + // + result = + low < nextBar.low && + low < prevBar.low && + (thresholdInPoint <= 0 + ? true + : MathAbs( + MathMax( + nextBar.low, + prevBar.low) - + low) >= requiredOffset); + + // + return result; + } + + // + // Find Last Swing Low ... + bool FindLastSwingLow(XOHCL &swing) + { + // + bool result = false; + + // + swing.Clean(); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int totalBars = iBars( + symbol, + period // + ); + int maxAllowed = MathMin(100, (totalBars / 100)); + + // + int idx = Index(); + for (int i = idx; i <= idx + maxAllowed; i++) + { + // + swing.Clean(); + result = swing.Init( + symbol, + period, + i // + ); + if (!result) + { + // + swing.Clean(); + break; + } + + // + result = swing.IsSwingLow(); + if (result) + { + break; + } + } + + // + return result; + } + + // + // Check Bullish FVG ... + bool HasBullishFVG( + double &upper, + double &lower, + datetime &start, + datetime &end, + bool forceMiddleBarCheck = true, + bool forceCheckLastBarDirection = false // + ) + { + // + bool result = false; + + // + upper = 0; + lower = 0; + + // + end = NULL; + start = NULL; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = IsValid() && Index() > 0; + if (!result) + { + return result; + } + + // + // Current Bar Must be Bullish ... + result = + !forceCheckLastBarDirection + ? true + : IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev Bar ... + XOHCL pBar; + result = GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // Prev Bar Must be Bullish ... + result = pBar.IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev of Prev Bar ... + XOHCL ppBar; + result = pBar.GetPreviousBar(ppBar); + if (!result) + { + return result; + } + + // + // Prev of Prev Bar Must be Bullish ... + result = ppBar.IsBullish(); + if (!result) + { + return result; + } + + // + // Other Conditions ... + result = + // + low > ppBar.high + // + ; + + // + // Check Middle Bar Range ... + if (result && forceMiddleBarCheck) + { + // + result = + // + pBar.high > low && + pBar.low < ppBar.high + // + ; + + // + if (!result) + { + return result; + } + } + + // + if (result) + { + // + end = time; + upper = low; + lower = ppBar.high; + start = ppBar.time; + } + + // + return result; + } + + // + // Check Bearish FVG ... + bool HasBearishFVG( + double &upper, + double &lower, + datetime &start, + datetime &end, + bool forceMiddleBarCheck = true, + bool forceCheckLastBarDirection = false // + ) + { + // + bool result = false; + + // + upper = 0; + lower = 0; + + // + end = NULL; + start = NULL; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = IsValid() && Index() > 0; + if (!result) + { + return result; + } + + // + // Current Bar Must be Bearish ... + result = + !forceCheckLastBarDirection + ? true + : IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev Bar ... + XOHCL pBar; + result = GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // Prev Bar Must be Bearish ... + result = pBar.IsBearish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev of Prev Bar ... + XOHCL ppBar; + result = pBar.GetPreviousBar(ppBar); + if (!result) + { + return result; + } + + // + // Prev of Prev Bar Must be Bearish ... + result = ppBar.IsBearish(); + if (!result) + { + return result; + } + + // + // Other Conditions ... + result = + // + high < ppBar.low + // + ; + + // + // Check Middle Bar Range ... + if (result && forceMiddleBarCheck) + { + // + result = + // + pBar.high > low && + pBar.low < ppBar.high + // + ; + + // + if (!result) + { + return result; + } + } + + // + if (result) + { + // + end = time; + lower = high; + upper = ppBar.low; + start = ppBar.time; + } + + // + return result; + } + + // + // Find Support ... + bool HasSupport( + XOHCL &bar, + ENUM_X_PRICE type = X_PRICE_CLOSE, + int _loopback = 21, + int tries = 100 // + ) + { + // + bool result = false; + + // + bar.Clean(); + + // + if (_loopback < 0) + { + _loopback = 21; + } + + // + if (tries < 0) + { + tries = 100; + } + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + double price = GetPrice(type); + + // + for (int i = 1; i < tries; i++) + { + // + int _length = _loopback * i; + + // + int lowestIDX = FindLowestIndex( + _length, + MODE_LOW // + ); + result = IsValidSize(lowestIDX); + if (!result) + { + break; + } + + // + XOHCL iLBar; + result = iLBar.Init( + symbol, + period, + lowestIDX // + ); + if (!result) + { + break; + } + + // + result = + // + price > iLBar.high + // + ; + if (result) + { + // + bar = iLBar; + break; + } + } + + // + return result; + } + + // + // Find Resistance ... + bool HasResistance( + XOHCL &bar, + ENUM_X_PRICE type = X_PRICE_CLOSE, + int _loopback = 21, + int tries = 100 // + ) + { + // + bool result = false; + + // + bar.Clean(); + + // + if (_loopback < 0) + { + _loopback = 21; + } + + // + if (tries < 0) + { + tries = 100; + } + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + double price = GetPrice(type); + + // + for (int i = 1; i < tries; i++) + { + // + int _length = _loopback * i; + + // + int highestIDX = FindHighestIndex( + _length, + MODE_LOW // + ); + result = IsValidSize(highestIDX); + if (!result) + { + break; + } + + // + XOHCL iHBar; + result = iHBar.Init( + symbol, + period, + highestIDX // + ); + if (!result) + { + break; + } + + // + result = + // + price < iHBar.high + // + ; + if (result) + { + // + bar = iHBar; + break; + } + } + + // + return result; + } + + // + // Trend Detection ... + + // + // Find Bullish Trend ... + bool HasBullishTrend( + XOHCL &highSwingBars[], + XOHCL &lowSwingBars[], + bool forceMethod2 = false, + int _loopback = 3, + int tries = 3, + ENUM_X_PRICE type = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + Clean(lowSwingBars); + Clean(highSwingBars); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + double price = GetPrice(type); + + // + int lastIDX = Index(); + double lastH = 0; + double lastL = 0; + for (int i = 1; i < tries + 1; i++) + { + // + // Use Regular Method ... + if (!forceMethod2) + { + // + int iHIDX = FindSwing( + symbol, + period, + X_SWING_HIGH, + _loopback, + lastIDX // + ); + result = IsValidIndex(iHIDX); + if (!result) + { + break; + } + + // + XOHCL iHBar; + result = iHBar.Init( + symbol, + period, + iHIDX // + ); + if (!result) + { + break; + } + + // + double iH = iHBar.high; + bool isIHAccepted = + // + iH > 0 && + ( + // + lastH == 0 + ? true + : iH < lastH + // + ) + // + ; + if (isIHAccepted) + { + // + AddRef( + iHBar, + highSwingBars // + ); + + // + lastH = iH; + lastIDX = iHIDX; + } + + // + int iLIDX = FindSwing( + symbol, + period, + X_SWING_LOW, + _loopback, + lastIDX // + ); + result = IsValidIndex(iLIDX); + if (!result) + { + break; + } + + // + XOHCL iLBar; + result = iLBar.Init( + symbol, + period, + iLIDX // + ); + if (!result) + { + break; + } + + // + double iL = iLBar.low; + bool isILAccepted = + // + iL > 0 && + ( + // + lastL == 0 + ? true + : iL < lastL + // + ) + // + ; + if (isILAccepted) + { + // + AddRef( + iLBar, + lowSwingBars // + ); + + // + lastL = iL; + lastIDX = iLIDX; + } + } + // + // Use Other MEthod ... + else + { + // + int _length = i * _loopback; + int start = + // + i == 1 + ? 1 + : _length - _loopback + // + ; + + // + int iHIDX = iHighest( + symbol, + period, + MODE_HIGH, + _loopback, + start // + ); + result = IsValidIndex(iHIDX); + if (!result) + { + break; + } + + // + XOHCL iHBar; + result = iHBar.Init( + symbol, + period, + iHIDX // + ); + if (!result) + { + break; + } + + // + double iH = iHBar.high; + bool isIHAccepted = + // + iH > 0 && + ( + // + lastH == 0 + ? true + : iH < lastH + // + ) + // + ; + if (isIHAccepted) + { + // + AddRef( + iHBar, + highSwingBars // + ); + + // + lastH = iH; + lastIDX = iHIDX; + } + + // + int iLIDX = iLowest( + symbol, + period, + MODE_LOW, + _loopback, + start // + ); + result = IsValidIndex(iLIDX); + if (!result) + { + break; + } + + // + XOHCL iLBar; + result = iLBar.Init( + symbol, + period, + iLIDX // + ); + if (!result) + { + break; + } + + // + double iL = iLBar.low; + bool isILAccepted = + // + iL > 0 && + ( + // + lastL == 0 + ? true + : iL < lastL + // + ) + // + ; + if (isILAccepted) + { + // + AddRef( + iLBar, + lowSwingBars // + ); + + // + lastL = iL; + lastIDX = iLIDX; + } + } + } + + // + if (result) + { + // + result = + // + ArraySize(lowSwingBars) == tries && + ArraySize(highSwingBars) == tries + // + ; + } + + // + if (!result) + { + // + Clean(lowSwingBars); + Clean(highSwingBars); + } + + // + return result; + } + + // + // Find Bearish Trend ... + bool HasBearishTrend( + XOHCL &highSwingBars[], + XOHCL &lowSwingBars[], + bool forceMethod2 = false, + int _loopback = 3, + int tries = 3, + ENUM_X_PRICE type = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + Clean(lowSwingBars); + Clean(highSwingBars); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + double price = GetPrice(type); + + // + int lastIDX = Index(); + double lastH = 0; + double lastL = 0; + for (int i = 1; i < tries + 1; i++) + { + // + // Use Regular Method ... + if (!forceMethod2) + { + // + int iHIDX = FindSwing( + symbol, + period, + X_SWING_HIGH, + _loopback, + lastIDX // + ); + result = IsValidIndex(iHIDX); + if (!result) + { + break; + } + + // + XOHCL iHBar; + result = iHBar.Init( + symbol, + period, + iHIDX // + ); + if (!result) + { + break; + } + + // + double iH = iHBar.high; + bool isIHAccepted = + // + iH > 0 && + ( + // + lastH == 0 + ? true + : iH > lastH + // + ) + // + ; + if (isIHAccepted) + { + // + AddRef( + iHBar, + highSwingBars // + ); + + // + lastH = iH; + lastIDX = iHIDX; + } + + // + int iLIDX = FindSwing( + symbol, + period, + X_SWING_LOW, + _loopback, + lastIDX // + ); + result = IsValidIndex(iLIDX); + if (!result) + { + break; + } + + // + XOHCL iLBar; + result = iLBar.Init( + symbol, + period, + iLIDX // + ); + if (!result) + { + break; + } + + // + double iL = iLBar.low; + bool isILAccepted = + // + iL > 0 && + ( + // + lastL == 0 + ? true + : iL > lastL + // + ) + // + ; + if (isILAccepted) + { + // + AddRef( + iLBar, + lowSwingBars // + ); + + // + lastL = iL; + lastIDX = iLIDX; + } + } + // + // Use Other MEthod ... + else + { + // + int _length = i * _loopback; + int start = + // + i == 1 + ? 1 + : _length - _loopback + // + ; + + // + int iHIDX = iHighest( + symbol, + period, + MODE_HIGH, + _loopback, + start // + ); + result = IsValidIndex(iHIDX); + if (!result) + { + break; + } + + // + XOHCL iHBar; + result = iHBar.Init( + symbol, + period, + iHIDX // + ); + if (!result) + { + break; + } + + // + double iH = iHBar.high; + bool isIHAccepted = + // + iH > 0 && + ( + // + lastH == 0 + ? true + : iH > lastH + // + ) + // + ; + if (isIHAccepted) + { + // + AddRef( + iHBar, + highSwingBars // + ); + + // + lastH = iH; + lastIDX = iHIDX; + } + + // + int iLIDX = iLowest( + symbol, + period, + MODE_LOW, + _loopback, + start // + ); + result = IsValidIndex(iLIDX); + if (!result) + { + break; + } + + // + XOHCL iLBar; + result = iLBar.Init( + symbol, + period, + iLIDX // + ); + if (!result) + { + break; + } + + // + double iL = iLBar.low; + bool isILAccepted = + // + iL > 0 && + ( + // + lastL == 0 + ? true + : iL > lastL + // + ) + // + ; + if (isILAccepted) + { + // + AddRef( + iLBar, + lowSwingBars // + ); + + // + lastL = iL; + lastIDX = iLIDX; + } + } + } + + // + if (result) + { + // + result = + // + ArraySize(lowSwingBars) == tries && + ArraySize(highSwingBars) == tries + // + ; + } + + // + if (!result) + { + // + Clean(lowSwingBars); + Clean(highSwingBars); + } + + // + return result; + } + + // + // Order Blocks ... + + // + // Find Bullish Order Block ... + bool HasBullishOrderBlock( + XOHCL &orderBlock, + int _minimumSameBars = 4 // + ) + { + // + bool result = false; + + // + orderBlock.Clean(); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + if (_minimumSameBars < 0) + { + _minimumSameBars = 4; + } + + // + XOHCL cBar; + int founded = 0; + int cIDX = Index(); + bool isEnough = false; + while (!isEnough) + { + // + result = cBar.Init( + symbol, + period, + cIDX // + ); + if (!result) + { + break; + } + + // + result = cBar.IsBullish(); + if (!result && cBar.IsBearish()) + { + break; + } + + // + cIDX++; + founded++; + } + + // + // Here we have to check founded and if it's fill + // our requirements ... + // cIDX is Order Block Index ... + result = + // + cBar.IsValid() && + high > cBar.high && + founded >= _minimumSameBars + // + ; + if (!result) + { + return result; + } + + // + result = orderBlock.Init( + symbol, + period, + cIDX // + ); + if (!result) + { + // + orderBlock.Clean(); + return result; + } + + // + return result; + } + + // + // Find Bearish Order Block ... + bool HasBearishOrderBlock( + XOHCL &orderBlock, + int _minimumSameBars = 4 // + ) + { + // + bool result = false; + + // + orderBlock.Clean(); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + if (_minimumSameBars < 0) + { + _minimumSameBars = 4; + } + + // + XOHCL cBar; + int founded = 0; + int cIDX = Index(); + bool isEnough = false; + while (!isEnough) + { + // + bool isInited = cBar.Init( + symbol, + period, + cIDX // + ); + + // + result = cBar.IsBearish(); + if (!result && cBar.IsBullish()) + { + break; + } + + // + cIDX++; + founded++; + } + + // + // Here we have to check founded and if it's fill + // our requirements ... + // cIDX is Order Block Index ... + result = + // + cBar.IsValid() && + high < cBar.low && + founded >= _minimumSameBars + // + ; + if (!result) + { + return result; + } + + // + result = orderBlock.Init( + symbol, + period, + cIDX // + ); + if (!result) + { + // + orderBlock.Clean(); + return result; + } + + // + return result; + } + + // + // Order Blocks ... + + // + // Supply and Demand ... + + // + // 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; + } +}; + +// +struct XTrend +{ + // + string symbol; + ENUM_TIMEFRAMES period; + + // + datetime at; + + // + XOHCL swingHighs[]; + XOHCL swingLows[]; + + // + bool isBullish; + bool isBearish; + + // + void XTrend() + { + Clean(); + } + + // + // Tools ... + + /** + * Initialize ... + * + * @param _symbol: String ... + * @param _period: ENUM_TIMEFRAMES member ... + * + * @return ( bool ) + */ + bool Init( + string _symbol, + ENUM_TIMEFRAMES _period = NULL // + ) + { + // + bool result = false; + + // + NormalizePeriod(_period); + + // + result = IsValid(_symbol) && + IsValid(_period); + if (!result) + { + return result; + } + + // + symbol = _symbol; + period = _period; + + // + XOHCL bar; + result = bar.Init( + symbol, + period, + 0 // + ); + if (!result) + { + return result; + } + + // + XOHCL tmpBULLSWH[]; + XOHCL tmpBULLSWL[]; + bool hasBullishTrend = bar.HasBullishTrend( + tmpBULLSWH, + tmpBULLSWL, + true // + ); + + // + XOHCL tmpBEARSWH[]; + XOHCL tmpBEARSWL[]; + bool hasBearishTrend = bar.HasBearishTrend( + tmpBEARSWH, + tmpBEARSWL, + true // + ); + + // + if (hasBullishTrend) + { + // + Copy( + tmpBULLSWH, + swingHighs // + ); + + // + Copy( + tmpBULLSWL, + swingLows // + ); + } + // + else if (hasBearishTrend) + { + // + Copy( + tmpBEARSWH, + swingHighs // + ); + + // + Copy( + tmpBEARSWL, + swingLows // + ); + } + + // + if (hasBullishTrend || + hasBullishTrend) + { + at = TimeCurrent(); + } + + // + result = IsValid(); + + // + return result; + } + + /** + * Clean ... + */ + void Clean() + { + // + symbol = NULL; + period = NULL; + at = NULL; + + // + isBullish = false; + isBearish = false; + + // + Clean(swingLows); + Clean(swingHighs); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + IsValid(symbol) && + IsValid(period) && + IsValid(at) && + (isBullish || + isBearish) && + (ArraySize(swingHighs) > 0 || + ArraySize(swingLows) > 0); + + // + return result; + } + + /** + * Generate Unique Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + string hash = symbol + "," + ToString(period) + "," + ToFormatString(at); + hash = ToMD5(hash); + + // + result = + // + "XTrend_" + + (isBullish ? "Bullish_" : "Bearish_") + + symbol + "_" + + ToString(period) + "_" + + hash + // + ; + + // + 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; + } + + // + // 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); + } + + // + 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; + } +}; + +// +// Model a Market Cycle ... +struct XMarketCycle +{ + // + // Props ... + + // + string prefix; // Prefix Trag ... + + // + string symbol; // Market Symbol ... + + // + ENUM_TIMEFRAMES period; // Period of Cycle ... + ENUM_X_PERIOD_METHOD method; // Period Selection Method ... + ENUM_X_MARKET_CYCLES cycle; // Cycles of MArket ... + + // + int length; // Number Of Candles per Current Time Frame ... + ENUM_TIMEFRAMES hostPeriod; // Current Time Frame ... + + // + datetime lastStart; // Last Candle Bar Time ... + + // + XBarTracker barTracker; // Bar Tracker ... + XBarRemainsTime remains; // Current Bar Remains Model ... + + // + // Constructor ... + XMarketCycle() + { + Clean(); + } + + // + // Init Cycle ... + bool Init( + string mSymbol, // Trading Symbol + ENUM_TIMEFRAMES mHostPeriod, // Host Period + ENUM_X_MARKET_CYCLES mCycle, // Init Cycle + string mPrefix = "" // Prefix + ) + { + // + bool result = false; + + // + mSymbol = NormalizeSymbol(mSymbol); + mHostPeriod = NormalizePeriod(mHostPeriod); + + // + result = IsValid(mCycle); + if (!result) + { + return result; + } + + // + this.cycle = mCycle; + + // + // Set Automatically Prefix ... + if (StringLen(mPrefix) == 0) + { + this.prefix = ToString(cycle); + } + + // + result = IsValid( + method, + period // + ); + if (!result) + { + return result; + } + + // + this.symbol = mSymbol; + this.hostPeriod = mHostPeriod; + + // + // Find Cycle Period ... + if (method == X_PERIOD_AUTO) + { + // + // Select Period ... + this.period = GetCyclePeriod( + this.cycle, + this.hostPeriod); + } + + // + // Set Prefix if Provided ... + if (StringLen(mPrefix) > 0) + { + this.prefix = mPrefix; + } + + // + // Calculate Required Info ... + + // + // Length ... + this.length = PeriodSeconds(this.period) / PeriodSeconds(this.hostPeriod); + + // + // Update Additional Data ... + result = this.Update(0); + + // + return result; + } + + // + bool Init( + string mSymbol, // Trading Symbol + ENUM_TIMEFRAMES mHostPeriod, // Host Period + ENUM_X_MARKET_CYCLES mCycle, // Init Cycle + ENUM_X_PERIOD_METHOD mMethod, // Period Selection Method + ENUM_TIMEFRAMES mPeriod, // Provided Period + string mPrefix = "" // Prefix + ) + { + // + this.period = mPeriod; + this.method = mMethod; + + // + return Init( + mSymbol, + mHostPeriod, + mCycle, + mPrefix + // + ); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + length = 0; + lastStart = 0; + + // + cycle = NULL; + prefix = NULL; + symbol = NULL; + period = NULL; + method = NULL; + hostPeriod = NULL; + + // + remains.Clean(); + barTracker.Clean(); + } + + // + // Check Structure Valid ... + bool IsValid() + { + // + bool result = false; + + // + result = IsValid( + method, + period); + if (!result) + { + return result; + } + + // + result = + // + length > 0 && + symbol != NULL && + period != NULL && + method != NULL && + hostPeriod != NULL && + method != X_PERIOD_NOTHING + // + ; + + // + return result; + } + + // + // Update Market Cycle Additional Info ... + bool Update(int hostBarIndex) + { + // + bool result = false; + + // + result = this.IsValid(); + if (!result) + { + return result; + } + + // + // Init Remains ... + result = remains.Init( + this.symbol, + this.period); + if (!result) + { + return result; + } + + // + // Init Bar Tracker ... + result = barTracker.Init( + this.symbol, + this.period); + if (!result) + { + return result; + } + + // + return result; + } + + // + // Count Bars ... + int CountBars() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = barTracker.CountBars(); + + // + return result; + } + + // + // Check New Bar ... + bool IsNewBar() + { + // + bool result = false; + + // + if (!IsValid()) + { + return result; + } + + // + result = barTracker.IsNewBar(); + + // + return result; + } + + // + // Retrieve Current Bar Index based on Host Period bar Index ... + int GetBarIndex(int barIndex) + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + if (barIndex < 0) + { + return result; + } + + // + int totalBars = CountBars(); + if (barIndex >= totalBars) + { + // + result = totalBars - 1; + return result; + } + + // + datetime hostBarTime = iTime( + this.symbol, + this.hostPeriod, + barIndex + // + ); + + // + result = iBarShift( + this.symbol, + this.period, + hostBarTime + // + ); + + // + return result; + } + + // + // Retrieve Current Cycles Specific Bar ... + XOHCL GetBar(int barIndex) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int totalBars = CountBars(); + if (barIndex >= totalBars) + { + barIndex = totalBars - 1; + } + + // + XOHCL result; + result.Init( + this.symbol, + this.period, + barIndex + // + ); + + // + return result; + } + + // + // Extract Specific Range of Bars ... + // using Start Bar Index ... + int GetBars( + XOHCL &result[], // Hold Result + int from = 0, // Start Bar Index + int count = 1, // Number of Bars + bool forceClean = true // Clean Result Array + ) + { + // + int mResult = 0; + + // + if (from < 0) + { + from = 0; + } + + // + int total = Bars( + symbol, + period); + if (from > total - 2) + { + from = total - 2; + } + + // + if (count < 0) + { + count = 1; + } + + // + int start = from; + int end = start + count; + if (end > total - 1) + { + end = total - 1; + } + + // + if (forceClean) + { + Clean(result); + } + + // + int beforeSize = ArraySize(result); + + // + for (int i = start; i < end; i++) + { + // + XOHCL iBar; + bool isValid = iBar.Init( + symbol, + period, + i + // + ); + + // + if (isValid) + { + // + AddRef( + iBar, + result + // + ); + } + } + + // + int afterSize = ArraySize(result); + + // + mResult = afterSize - beforeSize; + + // + return mResult; + } + + // + // Extract Specific Range of Bars ... + // using Start Bar Time ... + int GetBars( + XOHCL &result[], // Hold Result + datetime from = NULL, // Start Bar Time + int count = 1, // Number of Bars + bool forceClean = true // Clean Result Array + ) + { + // + from = NormalizeTime(from); + + // + int barIndex = iBarShift( + symbol, + period, + from, + false + // + ); + + // + return GetBars( + result, + symbol, + period, + barIndex, + count, + forceClean + // + ); + } + + // + // Retrieve Bar Time ... + datetime GetBarTime(int barIndex) + { + // + datetime result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int totalBars = CountBars(); + if (barIndex >= totalBars) + { + barIndex = totalBars - 1; + } + + // + result = iTime( + this.symbol, + this.period, + barIndex + // + ); + + // + return result; + } + + // + // Find Chart ID ... + ulong GetChartID() + { + // + ulong result = 0; + + // + long firstChart = ChartFirst(); + result = firstChart; + + // + while (result >= 0) + { + // + string chSymbol = ChartSymbol(result); + ENUM_TIMEFRAMES chPeriod = ChartPeriod(result); + + // + bool isOwnChart = + // + symbol == chSymbol && + period == chPeriod + // + ; + if (isOwnChart) + { + break; + } + + // + result = ChartNext(result); + if (result < 0) + { + break; + } + } + + // + return result; + } + + // + // Create and String Representation for Unique Taging ... + string ToString() + { + // + string result = ""; + + // + if (!IsValid()) + { + return result; + } + + // + result = + GetTypeName(this) + "(" + + "PRFX(" + this.prefix + ")" + + "SMBL(" + this.symbol + ")" + + "CYC(" + ToString(this.cycle) + ")" + + "PRD(" + ToString(this.period) + ")" + + "PRDHST(" + ToString(this.hostPeriod) + ")" + + "MTH(" + EnumToString(this.method) + ")" + + ")"; + + // + return result; + } + + // + // Here we Produce a Summary brief of + // state of Cycle ... + string GenerateSummary() + { + // + string result = ""; + + // + bool hasPrefix = + StringLen(this.prefix) > 0 && + this.prefix != ToString(this.cycle); + result += (hasPrefix ? this.prefix + "[" : "") + + ToString(this.cycle) + + (hasPrefix ? "]" : "") + "\n"; + + // + result += " - PR: " + ToString(this.period) + "\n"; + + // + XOHCL cBar = GetBar(0); + + // + result += " - State: " + (cBar.IsBullish() ? "Bullish" : cBar.IsBearish() ? "Bearish" + : "Neutural"); + + // + return result; + } +}; + +// +// Linear Regression ... + +// +struct XLinearRegressionWorkStruct +{ + // + struct sDataStruct + { + // + double value; + double sumY; + double sumXY; + }; + + // + sDataStruct data[]; + + // + int dataSize; + int period; + double sumX; + double sumXX; + double divisor; + + // + // Constructor ... + XLinearRegressionWorkStruct() + : dataSize(-1), period(-1) + { + } +}; + +// +struct XLinearRegression +{ + // + XLinearRegressionWorkStruct m_work; + + // + // Calculate Linear Regression ... + double Calculate( + double value, + int period, + double &_slope, + double &_intercept, + int r, + int bars // + ) + { + // + if (m_work.dataSize <= bars) + { + m_work.dataSize = ArrayResize(m_work.data, bars + 500, 2000); + } + + // + if (period < 1) + { + period = 1; + } + + // + if (m_work.period != (int)period) + { + // + m_work.period = (int)period; + m_work.sumX = m_work.period * (m_work.period - 1.0) / 2.0; + m_work.sumXX = m_work.period * (m_work.period - 1.0) * (2.0 * m_work.period - 1.0) / 6.0; + m_work.divisor = m_work.sumX * m_work.sumX - m_work.period * m_work.sumXX; + + // + if (m_work.divisor) + { + m_work.divisor = 1.0 / m_work.divisor; + } + } + + // + m_work.data[r].value = value; + + // + if (r >= m_work.period) + { + // + m_work.data[r].sumY = m_work.data[r - 1].sumY + value - m_work.data[r - m_work.period].value; + m_work.data[r].sumXY = m_work.data[r - 1].sumXY + m_work.data[r].sumY - m_work.data[r - m_work.period].value * (m_work.period - 1.0) - value; + } + else + { + // + m_work.data[r].sumY = value; + m_work.data[r].sumXY = 0; + + // + for (int _k = 1; _k < m_work.period && r >= _k; _k++) + { + // + m_work.data[r].sumY += m_work.data[r - _k].value; + m_work.data[r].sumXY += _k * m_work.data[r - _k].value; + } + } + + // + _slope = (m_work.period * m_work.data[r].sumXY - m_work.sumX * m_work.data[r].sumY) * m_work.divisor; + _intercept = (m_work.data[r].sumY - _slope * m_work.sumX) / (double)m_work.period; + + // + double result = (_intercept + _slope * (m_work.period - 1.0)); + + // + return result; + } + + // +}; + +// +// 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; + } +}; + +// +struct XSymbolSessionParser +{ + // + string version; // Temp ... + + // + // Check Market Is Open for Specific Symbol + // in Current Time ... + bool CanTrade( + string symbol // Trading Symbol + ) + { + // + bool result = false; + + // + result = IsValid(symbol); + if (!result) + { + return result; + } + + // + MqlDateTime timeStruct; + result = TimeCurrent(timeStruct); + if (!result) + { + return result; + } + + // + ENUM_DAY_OF_WEEK dayOfWeek = (ENUM_DAY_OF_WEEK)timeStruct.day_of_week; + + // + datetime cTime = TimeCurrent(); + + // + datetime from; + datetime to; + result = SymbolInfoSessionTrade( + symbol, + dayOfWeek, + 0, // Session Index ... + from, + to // + ); + if (!result) + { + return result; + } + + // + result = cTime > from && cTime < to; + + // + return result; + } +}; + +// +// Parsing Market Names ... +struct XMarketParser +{ + // + string _version; // Temp ... + + // + bool IsIngot(string market) + { + // + bool result = false; + + // + // result = IsValid(market) && + // market == ""; + + // + return result; + } + + // + bool IsErrante(string market) + { + // + bool result = false; + + // + // result = IsValid(market) && + // market == ""; + + // + return result; + } + + // + bool IsAMarkets(string market) + { + // + bool result = false; + + // + result = IsValid(market) && + market == "AMarkets LLC"; + + // + return result; + } + + // + bool IsIFCMarkets(string market) + { + // + bool result = false; + + // + // result = IsValid(market) && + // market == ""; + + // + return result; + } + + // + bool IsOtetMarkets(string market) + { + // + bool result = false; + + // + // result = IsValid(market) && + // market == ""; + + // + return result; + } + + // +}; + +// +// Functions ... + +// +// Validators ... + +// +// Validate an String has length and not NULL ... +bool IsValid(string value) +{ + // + bool result = false; + + // + result = + // + value != NULL && + StringLen(value) > 0 + // + ; + + // + return result; +} +bool IsSpecifiedValid(string value) +{ + return IsValid(value); +} + +// +// Validate a Date ... +bool IsValid(datetime value) +{ + // + bool result = false; + + // + result = NotEmpty(value) && value != NULL; + + // + return result; +} +bool IsSpecifiedValid(datetime value) +{ + return IsValid(value); +} + +// +// Validate a Period Param ... +bool IsValid(ENUM_TIMEFRAMES value) +{ + // + bool result = false; + + // + result = + // + value != NULL + // + ; + + // + return result; +} +bool IsSpecifiedValid(ENUM_TIMEFRAMES value) +{ + // + return IsValid(value); +} + +// +// Validate Specified Cycle ... +bool IsValid(ENUM_X_MARKET_CYCLES value) +{ + // + bool result = false; + + // + result = + // + value != NULL && + value != X_MARKET_CYCLE_UNKNOWN + // + ; + + // + return result; +} + +// +// Validate Specific Period Mode ... +bool IsValid( + ENUM_X_PERIOD_METHOD mMethod, // Period Select Method + ENUM_TIMEFRAMES mPeriod // Selected Period +) +{ + // + bool result = false; + + // + result = + // + mMethod == X_PERIOD_NOTHING + ? false + : mMethod == X_PERIOD_MANUALLY + ? mPeriod != NULL + : mMethod == X_PERIOD_AUTO + ? true + : false + // + ; + + // + return result; +} + +// +bool IsSpecifiedValid( + ENUM_X_PERIOD_METHOD mMethod, // Period Select Method + ENUM_TIMEFRAMES mPeriod // Selected Period +) +{ + return IsValid(mMethod, + mPeriod // + ); +} + +// +// Validate Swing Mode ... +bool IsValid(ENUM_X_SWING_TYPE value) +{ + // + bool result = false; + + // + result = + // + value == X_SWING_HIGH || + value == X_SWING_LOW + // + ; + + // + return result; +} + +// +// As IS ... + +// +// Determine a Position type is Long or not ... +bool IsLong(ENUM_POSITION_TYPE type) +{ + // + bool result = type == POSITION_TYPE_BUY; + + // + return result; +} +bool IsLong(ENUM_ORDER_TYPE type) +{ + // + bool result = type == ORDER_TYPE_BUY; + + // + return result; +} + +// +// Determine a Position type is Short or not ... +bool IsShort(ENUM_POSITION_TYPE type) +{ + // + bool result = type == POSITION_TYPE_SELL; + + // + return result; +} +bool IsShort(ENUM_ORDER_TYPE type) +{ + // + bool result = type == ORDER_TYPE_SELL; + + // + return result; +} + +// +// Retrieve Opposit Direction Type ... +ENUM_POSITION_TYPE GetOpposit(ENUM_POSITION_TYPE type) +{ + // + ENUM_POSITION_TYPE result = NULL; + + // + bool isLong = IsLong(type); + result = isLong + ? POSITION_TYPE_SELL + : POSITION_TYPE_BUY; + + // + return result; +} +ENUM_ORDER_TYPE GetOpposit(ENUM_ORDER_TYPE type) +{ + // + ENUM_ORDER_TYPE result = NULL; + + // + bool isLong = IsLong(type); + result = isLong + ? ORDER_TYPE_SELL + : ORDER_TYPE_BUY; + + // + return result; +} + +// +string ToString(ENUM_POSITION_TYPE value) +{ + // + string result = NULL; + + // + result = + // + IsLong(value) + ? "Long" + : "Short" + // + ; + + // + return result; +} +string ToString(ENUM_ORDER_TYPE value) +{ + // + string result = NULL; + + // + result = + // + IsLong(value) + ? "Long" + : "Short" + // + ; + + // + return result; +} + +// +// Check Expert Running in Testing Mode or not ... +bool IsRunningOnTestMode() +{ + // + bool result = false; + + // + // check programm mode ... + result = MQL5InfoInteger(MQL5_TESTING); + + // + return result; +} + +// +// Find Chart ID ... +long FindChartID( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL // Trading Period +) +{ + // + long result = ChartFirst(); + long first = result; + + // + while (result > 0) + { + // + string chSymbol = ChartSymbol(result); + ENUM_TIMEFRAMES chPeriod = ChartPeriod(result); + + // + bool isOwn = + // + chSymbol == mSymbol && + chPeriod == mPeriod + // + ; + if (isOwn) + { + break; + } + + // + result = ChartNext(result); + } + + // + return result; +} + +// +// Normalizers ... + +// +// Check a Symbol provided or not ... +// if not use Default ... +string NormalizeSymbol(string value) +{ + // + string result = value; + + // + if (!IsValid(result)) + { + result = _Symbol; + } + + // + return result; +} + +// +// Check a Datetime provided or not ... +// if not use Current ... +datetime NormalizeTime(datetime value) +{ + // + datetime result = value; + + // + if (!IsValid(result)) + { + result = TimeCurrent(); + } + + // + return result; +} + +// +// Check a Period provided or not ... +// if not use Default ... +ENUM_TIMEFRAMES NormalizePeriod(ENUM_TIMEFRAMES value) +{ + // + ENUM_TIMEFRAMES result = value; + + // + if (!IsValid(value)) + { + result = _Period; + } + + // + return result; +} + +// +// Normalize Cycle ... +ENUM_X_MARKET_CYCLES NormalizeCycle(ENUM_X_MARKET_CYCLES value) +{ + // + ENUM_X_MARKET_CYCLES result = value; + + // + if (!IsValid(result)) + { + result = X_MARKET_CYCLE_SHORT; + } + + // + return value; +} + +// +// Validate a Buffer Size for Looping or etc ... +bool IsValidSize(int size) +{ + // + bool result = size > 0; + + // + return result; +} + +template +bool IsValidSize(T &buffer[]) +{ + // + bool result = false; + + // + result = + // + IsValidSize(ArraySize(buffer)) + // + ; + + // + return result; +} + +// +// Check a Given Index is Valid or not ... +bool IsValidIndex(int index) +{ + return index >= 0; +} + +// +// Normalize Index Based On Specified Buffer ... +template +void NormalizeIndex( + int &index, + T &buffer[] // +) +{ + // + int bufferSize = ArraySize(buffer); + + // + if (bufferSize <= 0) + { + index = 0; + } + + // + if (index <= 0) + { + index = 0; + } + + // + if (index > bufferSize - 1) + { + index = bufferSize - 1; + } +} + +// +// Normalize Start and Count based on Specified Buffer ... +template +void NormalizeCount( + int &start, + int &count, + T &buffer[] // +) +{ + // + // Validate Buffer Size ... + int bufferSize = ArraySize(buffer); + if (!IsValidSize(bufferSize)) + { + return; + } + + // + // Normalization Start ... + NormalizeIndex( + start, + buffer // + ); + + // + if (count < start) + { + count = (start - count); + } + + // + // Normalization Count ... + + // + if (count < 0) + { + count = start; + } + + // + if (count > bufferSize) + { + count = bufferSize; + } +} + +// +// Normalize a give Volume ... +double NormalizeVolume( + double mVolume, // desired volume to normalize + string mSymbol = NULL, // Trading Symbol + int mLength = 2 // Length of Digits +) +{ + // + double result = mVolume; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + // Normalize Digits ... + int digits = GetDigits(mSymbol); + + // + mLength = + mLength == 0 || mLength > digits + ? digits + : MathMin(mLength, digits); + + // + // Normalize Volume ... + result = NormalizeDouble(result, mLength); + + // + double maxAvailableVolume = SymbolInfoDouble(mSymbol, SYMBOL_VOLUME_MAX); + double minAvailableVolume = SymbolInfoDouble(mSymbol, SYMBOL_VOLUME_MIN); + + // + // Validate Result ... + if (result > maxAvailableVolume) + { + result = maxAvailableVolume; + } + else if (result < minAvailableVolume) + { + result = minAvailableVolume; + } + + // + return result; +} + +// +// Normallize Price ... +double NormalizePrice( + double mPrice, // desired Price for normalization + string mSymbol = NULL // Trading Symbol +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double tickSize = 0; + result = SymbolInfoDouble(mSymbol, SYMBOL_TRADE_TICK_SIZE, tickSize); + + // + int digits = GetDigits(mSymbol); + result = NormalizeDouble(MathRound(mPrice / tickSize) * tickSize, digits); + + // + return result; +} + +// +// Prices ... + +// +// Retrieve Ask Price ... +double GetAsk( + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double result = SymbolInfoDouble(mSymbol, SYMBOL_ASK); + + // + return result; +} + +// +// Retrieve Bid Price ... +double GetBid( + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double result = SymbolInfoDouble(mSymbol, SYMBOL_BID); + + // + return result; +} + +// +// Retrieve Spread Price ... +double GetSpread( + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double ask = GetAsk(mSymbol); + double bid = GetBid(mSymbol); + + // + double result = MathAbs(ask - bid); + + // + return result; +} + +// +// Retrieve Point Value ... +double GetPoints( + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double result = SymbolInfoDouble(mSymbol, SYMBOL_POINT); + + // + return result; +} + +// +// Retrieve Point Digits ... +int GetDigits( + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + int result = (int)SymbolInfoInteger(mSymbol, SYMBOL_DIGITS); + + // + return result; +} + +// +// Retrieve Entry Price ... +double GetEntry( + string mSymbol = NULL, // Trading Symbol + ENUM_POSITION_TYPE type = POSITION_TYPE_BUY // Get entry price for Which direction trade ... +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + result = + IsLong(type) + ? GetAsk(mSymbol) + : GetBid(mSymbol); + result = NormalizePrice(result, mSymbol); + + // + return result; +} +double GetEntry( + string mSymbol = NULL, // Trading Symbol + ENUM_X_DIRECTION type = X_DIRECTION_BULLISH // Get entry price for Which direction trade ... +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + result = + IsBullish(type) + ? GetAsk(mSymbol) + : GetBid(mSymbol); + result = NormalizePrice(result, mSymbol); + + // + return result; +} + +// +// Retrieve Exit Price ... +double GetExit( + string mSymbol = NULL, // Trading Symbol + ENUM_POSITION_TYPE type = POSITION_TYPE_BUY // Get entry price for Which direction trade ... +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + result = + IsLong(type) + ? GetBid(mSymbol) + : GetAsk(mSymbol); + result = NormalizePrice(result, mSymbol); + + // + return result; +} +double GetExit( + string mSymbol = NULL, // Trading Symbol + ENUM_X_DIRECTION type = X_DIRECTION_BULLISH // Get entry price for Which direction trade ... +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + result = + IsBullish(type) + ? GetBid(mSymbol) + : GetAsk(mSymbol); + result = NormalizePrice(result, mSymbol); + + // + return result; +} + +// +// Get 1 Pip in Price Value ... +double GetPipPrice( + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double symbolPoint = GetPoints(mSymbol); + int symbolDigits = GetDigits(mSymbol); + + // + double result = symbolPoint; + if (symbolDigits == 3 || symbolDigits == 5) + { + result *= 10; + } + + // + return result; +} + +// +// Converts Pips To Price ... +double PipsToPrice( + double mPips, // pips amount + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + int digits = GetDigits(mSymbol); + double pipValue = GetPipPrice(mSymbol); + double result = mPips * pipValue; + + // + result = NormalizePrice(result, mSymbol); + + // + return result; +} + +// +// Converts Price to Pips ... +double PriceToPips( + double mPrice, // the price amount which required to calculate + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + mPrice = NormalizePrice(mPrice, mSymbol); + + // + int digits = GetDigits(mSymbol); + double pipPrice = GetPipPrice(mSymbol); + + // + double result = mPrice / pipPrice; + + // + result = NormalizeDouble(result, digits); + + // + return result; +} + +// +// Convert Price to Point ... +double PriceToPoint( + double price, // the price amount which required to calculate + string mSymbol = NULL // Trading Symbol +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + price = NormalizePrice(price, mSymbol); + + // + double point = GetPoints(mSymbol); + result = price / point; + + // + return result; +} + +// +// Converts Point to Price ... +double PointToPrice( + double points, // Points Amount + string mSymbol = NULL // Trading Symbol +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double point = GetPoints(mSymbol); + result = points * point; + + // + result = NormalizePrice(result, mSymbol); + + // + return result; +} + +// +// Converts Series Mode to XPRICE ... +ENUM_X_PRICE ToPrice( + ENUM_SERIESMODE mMode // Specified Series Mode ... +) +{ + // + ENUM_X_PRICE result = X_PRICE_CLOSE; + + // + switch (mMode) + { + // + // High ... + case MODE_HIGH: + result = X_PRICE_HIGH; + break; + + // + // Open ... + case MODE_OPEN: + result = X_PRICE_OPEN; + break; + + // + // Low ... + case MODE_LOW: + result = X_PRICE_LOW; + break; + + // + // Close ... + // Default ... + case MODE_CLOSE: + default: + result = X_PRICE_CLOSE; + break; + } + + // + return result; +} + +// +// Retrieve Applied Price ... +template +double GetAppliedPrice( + ENUM_APPLIED_PRICE tprice, // Type of Price Selection + T &open[], // Open Prices + T &high[], // High Preices + T &low[], // Low Prices + T &close[], // Close Prices + int i // Bar Index +) +{ + switch (tprice) + { + case PRICE_CLOSE: + return (close[i]); + case PRICE_OPEN: + return (open[i]); + case PRICE_HIGH: + return (high[i]); + case PRICE_LOW: + return (low[i]); + case PRICE_MEDIAN: + return ((high[i] + low[i]) / 2.0); + case PRICE_TYPICAL: + return ((high[i] + low[i] + close[i]) / 3.0); + case PRICE_WEIGHTED: + return ((high[i] + low[i] + close[i] + close[i]) / 4.0); + } + return (0); +} + +// +double iGetPrice( + int tprice, + double open, + double high, + const double low, + const double close // +) +{ + // + switch (tprice) + { + case PRICE_CLOSE: + return (close); + case PRICE_OPEN: + return (open); + case PRICE_HIGH: + return (high); + case PRICE_LOW: + return (low); + case PRICE_MEDIAN: + return ((high + low) / 2.0); + case PRICE_TYPICAL: + return ((high + low + close) / 3.0); + case PRICE_WEIGHTED: + return ((high + low + close + close) / 4.0); + } + + // + return (0); +} + +/** + * Calculates Price Change Percentage based on + * Several Params ... + * + * @param _symbol: Symbol ... + * @param _period: Time Frame ... + * @param _from: start Bar Index ... + * @param _length: Length of Bars ... + * + * @return ( double ) + */ +double GetPriceChanged( + string _symbol = NULL, + ENUM_TIMEFRAMES _period = NULL, + int _from = 0, + int _length = 3 // +) +{ + // + double result = 0; + + // + NormalizeSymbol(_symbol); + NormalizePeriod(_period); + + // + if (_from < 0) + { + _from = 0; + } + + // + if (_length < 2) + { + _length = 2; + } + + // + double closes[]; + int copiedCloses = CopyClose( + _symbol, + _period, + _from, + _length, + closes // + ); + if (copiedCloses < _length) + { + return result; + } + ArrayReverse(closes); + + // + double change = (closes[0] - closes[_length - 1]) / closes[_length - 1] * 100; + result = change; + + // + return result; +} + +// +// Calculate TP/SL for Specified Type of Positions ... +void CalculateTPSL( + double &mSL, // Hold SL + double &mTP, // Hold TP + ENUM_POSITION_TYPE mType, // Position Type Long (Buy) / Short (Sell) + double mEntry, // Entry Price + double mR2R = 1, // Provided Risk To Reward Ratio + double slPrice = 0, // Provided SL Price + double tpPrice = 0, // Provided TP Price + double priceToRisk = 0, // If Entry equal to Provided SL Price Risk Point + double priceToReward = 0 // If Entry equal to Provided TP Price Reward Point +) +{ + // + // if Both TP and SL Provided, ignore R2R and Calculate direct ... + // if SL provided, Calculate TP based on Provided R2R ... + // if TP provided, Calculate SL based on Provided R2R ... + // default R2R is set to 1 ... + + // + mSL = 0; + mTP = 0; + + // + bool isLong = IsLong(mType); + + // + // Set Default R2R ... + if (mR2R < 1) + { + mR2R = 1; + } + + // + if (mEntry <= 0 || + (tpPrice <= 0 && slPrice <= 0)) + { + return; + } + + // + double risk = 0; + double reward = 0; + + // + bool canCalculateBasedOnSL = slPrice > 0 && + (isLong + ? slPrice <= mEntry + : slPrice >= mEntry); + + // + bool canCalculateBasedOnTP = tpPrice > 0 && + (isLong + ? tpPrice >= mEntry + : tpPrice <= mEntry); + + // + if (canCalculateBasedOnSL && !canCalculateBasedOnTP) + { + // + risk = MathAbs(mEntry - slPrice); + if (risk == 0) + { + risk = priceToRisk; + } + reward = risk * mR2R; + } + else if (!canCalculateBasedOnSL && canCalculateBasedOnTP) + { + // + reward = MathAbs(mEntry - tpPrice); + if (reward == 0) + { + reward = priceToReward; + } + risk = reward / mR2R; + } + else if (!canCalculateBasedOnSL && !canCalculateBasedOnTP) + { + // + bool canSetTPPrice = isLong + ? tpPrice > mEntry + : tpPrice < mEntry; + if (canSetTPPrice) + { + mTP = tpPrice; + } + + // + bool canSetSLPrice = isLong + ? slPrice < mEntry + : slPrice > mEntry; + if (canSetSLPrice) + { + mSL = slPrice; + } + + // + return; + } + else if (canCalculateBasedOnSL && canCalculateBasedOnTP) + { + // + bool canSetTPPrice = isLong + ? tpPrice > mEntry + : tpPrice < mEntry; + if (canSetTPPrice) + { + mTP = tpPrice; + } + + // + bool canSetSLPrice = isLong + ? slPrice < mEntry + : slPrice > mEntry; + if (canSetSLPrice) + { + mSL = slPrice; + } + + // + return; + } + + // + mTP = isLong + ? mEntry + reward + : mEntry - reward; + + // + mSL = isLong + ? mEntry - risk + : mEntry + risk; +} + +// +bool CalculateTPSLByPoint( + double &mSL, // Hold SL + double &mTP, // Hold TP + ENUM_POSITION_TYPE mType, // Position Type Long (Buy) / Short (Sell) + double mEntry, // Entry Price + double mPointValue, // Point Value + double mR2R = 1, // Provided Risk To Reward Ratio + double slPoint = 0, // Provided SL Point + double tpPoint = 0 // Provided TP Point +) +{ + // + bool result = false; + + // + mSL = 0; + mTP = 0; + + // + bool isLong = IsLong(mType); + + // + // Set Default R2R ... + if (mR2R < 1) + { + mR2R = 1; + } + + // + if (mEntry <= 0 || + mPointValue <= 0 || + (slPoint <= 0 && tpPoint <= 0)) + { + return result; + } + + // + double risk = 0; + double reward = 0; + + // + bool canCalculateBasedOnSL = slPoint > 0; + + // + bool canCalculateBasedOnTP = tpPoint > 0; + + // + if (!canCalculateBasedOnSL && !canCalculateBasedOnTP) + { + return result; + } + + // + if (canCalculateBasedOnSL && canCalculateBasedOnTP) + { + // + reward = tpPoint * mPointValue; + risk = slPoint * mPointValue; + } + else if (!canCalculateBasedOnSL && canCalculateBasedOnTP) + { + // + reward = tpPoint * mPointValue; + risk = reward / mR2R; + } + else if (canCalculateBasedOnSL && !canCalculateBasedOnTP) + { + // + risk = slPoint * mPointValue; + reward = risk * mR2R; + } + + // + result = risk > 0 && reward > 0; + if (!result) + { + return result; + } + + // + mTP = isLong + ? mEntry + reward + : mEntry - reward; + + // + mSL = isLong + ? mEntry - risk + : mEntry + risk; + + // + return result; +} + +// +bool CalculateTPSLByPrice( + double &mSL, // Hold SL + double &mTP, // Hold TP + ENUM_POSITION_TYPE mType, // Position Type Long (Buy) / Short (Sell) + double mEntry, // Entry Price + double mR2R = 1 // Provided Risk To Reward Ratio +) +{ + // + bool result = false; + + // + bool isLong = IsLong(mType); + + // + // Set Default R2R ... + if (mR2R < 1) + { + mR2R = 1; + } + + // + if (mEntry <= 0 || + (mSL <= 0 && mTP <= 0)) + { + return result; + } + + // + double risk = 0; + double reward = 0; + + // + bool canCalculateBasedOnSL = mSL > 0; + bool canCalculateBasedOnTP = mTP > 0; + + // + if ( + !canCalculateBasedOnSL && + !canCalculateBasedOnTP) + { + return result; + } + + // + if (!canCalculateBasedOnSL && canCalculateBasedOnTP) + { + // + reward = MathAbs(mTP - mEntry); + risk = reward / mR2R; + } + else if (canCalculateBasedOnSL && !canCalculateBasedOnTP) + { + // + risk = MathAbs(mEntry - mSL); + reward = risk * mR2R; + } + + // + result = risk > 0 && reward > 0; + if (!result) + { + return result; + } + + // + mTP = isLong + ? mEntry + reward + : mEntry - reward; + + // + mSL = isLong + ? mEntry - risk + : mEntry + risk; + + // + return result; +} + +/** + * Retrieve Current Tick ... + */ +bool GetTick( + string mSymbol, + MqlTick &tick // +) +{ + return SymbolInfoTick(mSymbol, tick); +} + +/** + * Retrieve Tick Entry ... + */ +double GetTickEntry( + MqlTick &mTick, + ENUM_POSITION_TYPE type, + string mSymbol = NULL // +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + result = + IsLong(type) + ? mTick.ask + : mTick.bid; + result = NormalizePrice(result, mSymbol); + + // + return result; +} + +/** + * Retrieve Tick Exit ... + */ +double GetTickExit( + MqlTick &mTick, + ENUM_POSITION_TYPE type, + string mSymbol = NULL // +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + result = + IsLong(type) + ? mTick.bid + : mTick.ask; + result = NormalizePrice(result, mSymbol); + + // + return result; +} + +/** + * Calculate Momentum Changes based on Given Price + */ +double CalculateMomentum( + double currentPrice, + double previousPrice // +) +{ + // + double result = 0; + + // + return result; +} + +/** + * Detect Possible Momentum Changes + * Using MqlTick ... + */ +bool DetectMomentumChange( + ENUM_POSITION_TYPE type, + string mSymbol = NULL, + int mLength = 14 // +) +{ + // + bool result = false; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + MqlTick ticks[]; + int copied = CopyTicks( + mSymbol, + ticks, + COPY_TICKS_ALL, + 0, + mLength + 1 // + ); + + // + result = copied > mLength; + if (!result) + { + return result; + } + + // + double previousPrice = GetTickExit( + ticks[mLength], + type, + mSymbol // + ); + for (int i = mLength - 1; i >= 0; i--) + { + // + double currentPrice = GetTickExit( + ticks[i], + type, + mSymbol // + ); + + // + double momentum = CalculateMomentum( + currentPrice, + previousPrice // + ); + + // + if (fabs(momentum) > 1.0) + { + // + result = true; + break; + } + } + + // + return result; +} + +// +// Fill Specified Applied Prices ... +int FillPrice( + double &buffer[], + ENUM_APPLIED_PRICE _mAppliedTo = PRICE_CLOSE, + string _mSymbol = NULL, + ENUM_TIMEFRAMES _mPeriod = NULL, + int _mStart = 0, + int _mLoopback = 10 // +) +{ + // + int result = 0; + + // + if (_mStart < 0) + { + _mStart = 0; + } + + // + if (_mLoopback < 7) + { + _mLoopback = 7; + } + + // + _mSymbol = NormalizeSymbol(_mSymbol); + _mPeriod = NormalizePeriod(_mPeriod); + + // + Clean(buffer); + ArraySetAsSeries(buffer, true); + + // + double open[]; + result = CopyOpen( + _mSymbol, + _mPeriod, + _mStart, + _mLoopback, + open // + ); + if (!IsValidSize(result)) + { + return result; + } + + // + double high[]; + result = CopyHigh( + _mSymbol, + _mPeriod, + _mStart, + _mLoopback, + high // + ); + if (!IsValidSize(result)) + { + return result; + } + + // + double low[]; + result = CopyLow( + _mSymbol, + _mPeriod, + _mStart, + _mLoopback, + low // + ); + if (!IsValidSize(result)) + { + return result; + } + + // + double close[]; + result = CopyClose( + _mSymbol, + _mPeriod, + _mStart, + _mLoopback, + close // + ); + if (!IsValidSize(result)) + { + return result; + } + + // + for (int i = 0; i < result; i++) + { + // + double iPrice = GetAppliedPrice( + _mAppliedTo, + open, + high, + low, + close, + i // + ); + + // + Add( + iPrice, + buffer // + ); + } + + // + result = ArraySize(buffer); + + // + return result; +} + +// +// Symbols ... + +// +// Retrieve Available Symbols ... +int GetAllSymbols( + string &symbols[], // Hold Result + bool onlyInWatchList = false, // Specified Retrieve only Symbols which in Watch List + bool forceClean = true // Force To Clean Result Array +) +{ + // + int result = 0; + + // + if (forceClean) + { + Clean(symbols); + } + + // + int beforeSize = ArraySize(symbols); + + // + int symbolsCount = SymbolsTotal(onlyInWatchList); + if (symbolsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < symbolsCount; i++) + { + // + string iSymbol = SymbolName( + i, + onlyInWatchList + // + ); + if (!IsValid(iSymbol)) + { + continue; + } + + // + Add( + iSymbol, + symbols + // + ); + } + + // + int afterSize = ArraySize(symbols); + + // + result = afterSize - beforeSize; + + // + return result; +} + +// +// This is a Global Way to Filter Symbols +// you can pass Specific string as Query or a List String for Filtering ... +int FilterSymbols( + string query, // Which Query to Search Symbol + string &symbols[], // Hold Result + bool onlyInWatchList = false, // Specified Retrieve only Symbols which in Watch List + bool forceClean = true, // Force To Clean Result Array + bool ignoreCase = true, // Ignore Case + string querySeparator = "," // If Provided means query is a COllection of Queries and need to be Splitted +) +{ + // + int result = 0; + + // + if (forceClean) + { + Clean(symbols); + } + + // + if (!IsValid(query)) + { + return result; + } + + // + // Check Query is an String array or not ... + string mQueries[]; + int queriesCount = 0; + if (IsValid(querySeparator) && Contains(querySeparator, query, true)) + { + // + queriesCount = SplitContent( + mQueries, + query, + querySeparator + // + ); + } + + // + int beforeSize = ArraySize(symbols); + + // + string allSymbols[]; + int allSymbolsCount = GetAllSymbols( + allSymbols, + onlyInWatchList, + forceClean); + if (allSymbolsCount <= 0) + { + return result; + } + + // + // Loop Through all Symbols ... + for (int i = 0; i < allSymbolsCount; i++) + { + // + string iSymbol = allSymbols[i]; + + // + bool isFilterPassed = false; + if (queriesCount == 0) + { + // + isFilterPassed = Contains( + query, + iSymbol, + ignoreCase + // + ); + } + else if (queriesCount > 0) + { + // + isFilterPassed = Contains( + mQueries, + iSymbol, + ignoreCase + // + ); + } + + // + if (isFilterPassed) + { + // + Add( + iSymbol, + symbols + // + ); + } + } + + // + int afterSize = ArraySize(symbols); + + // + result = afterSize - beforeSize; + + // + return result; +} + +// +int FilterUSDSymbols( + string &symbols[], // Hold Result + bool onlyInWatchList = false, // Specified Retrieve only Symbols which in Watch List + bool forceClean = true, // Force To Clean Result Array + bool ignoreCase = true, // Ignore Case + string querySeparator = "," // If Provided means query is a COllection of Queries and need to be Splitted +) +{ + // + return FilterSymbols( + "USD", + symbols, + onlyInWatchList, + forceClean, + ignoreCase, + querySeparator + // + ); +} + +// +// Time / Date ... + +// +// Representation of Time Struct ... +// struct MqlDateTime +// { +// int year; // Year +// int mon; // Month +// int day; // Day +// int hour; // Hour +// int min; // Minutes +// int sec; // Seconds +// int day_of_week; // Day of week (0-Sunday, 1-Monday, ... ,6-Saturday) +// int day_of_year; // Day number of the year (January 1st is assigned the number value of zero) +// }; + +// +// Converts Time to Seconds ... +ulong TimeToSeconds( + datetime time // Specify time to Convert ... +) +{ + // + ulong result = (ulong)time; + + // + return result; +} +ulong TimeToSeconds( + MqlDateTime &time // Specify time to Convert ... +) +{ + // + datetime dTime = StructToTime(time); + + // + ulong result = TimeToSeconds(dTime); + + // + return result; +} + +// +// Converts Seconds To Time ... +datetime SecondsToTime( + ulong seconds // Specify Seconds to Convert ... +) +{ + // + datetime result = (datetime)seconds; + + // + return result; +} +MqlDateTime SecondsToStruct( + ulong seconds // Specify Seconds to Convert ... +) +{ + // + datetime dTime = SecondsToTime(seconds); + + // + MqlDateTime result = {}; + TimeToStruct( + dTime, + result); + + // + return result; +} + +// +// Converts Time to MilliSeconds ... +ulong TimeToMilliSeconds( + datetime time // Specify time to Convert ... +) +{ + // + ulong result = TimeToSeconds(time) * 1000; + + // + return result; +} +ulong TimeToMilliSeconds( + MqlDateTime &time // Specify time to Convert ... +) +{ + // + datetime dTime = StructToTime(time); + + // + ulong result = TimeToMilliSeconds(dTime); + + // + return result; +} + +// +// Converts MillisSeconds to Time ... +datetime MilliSecondsToTiem( + ulong milliSeconds // Specify MilliSeconds to Convert ... +) +{ + // + ulong seconds = milliSeconds / 1000; + + // + datetime result = SecondsToTime(seconds); + + // + return result; +} +MqlDateTime MilliSecondsToStruct( + ulong milliSeconds // Specify MilliSeconds to Convert ... +) +{ + // + datetime dTime = MilliSecondsToTiem(milliSeconds); + + // + MqlDateTime result = {}; + TimeToStruct( + dTime, + result); + + // + return result; +} + +// +// 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; +} + +// +// 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 ... + 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; +} + +// +// Bar Times ... + +// +// Retrieve Specified Bar Time ... +datetime GetBarTime( + string mSymbol = "", // Specify Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Specify TimeFrame + int barIndex = 0 // Specify Bar Index +) +{ + // + // Validate and Normalize Args ... + + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + // Retrieve Bar Time ... + datetime result = iTime( + mSymbol, + mPeriod, + barIndex); + + // + return result; +} + +// +// Retrieve Specified Bar Time ... +ulong GetBarTimeAsSeconds( + string mSymbol = "", // Specify Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Specify TimeFrame + int barIndex = 0 // Specify Bar Index +) +{ + // + // Retrieve Bar Time ... + datetime time = GetBarTime( + mSymbol, + mPeriod, + barIndex); + + // + ulong result = TimeToSeconds(time); + + // + return result; +} + +// +// Retrieve Specified Bar Time ... +ulong GetBarTimeAsMilliSeconds( + string mSymbol = "", // Specify Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Specify TimeFrame + int barIndex = 0 // Specify Bar Index +) +{ + // + // Retrieve Bar Time ... + datetime time = GetBarTime( + mSymbol, + mPeriod, + barIndex); + + // + ulong result = TimeToMilliSeconds(time); + + // + return result; +} + +// +// Retrieve a Bar Time Structure ... +MqlDateTime GetBarTimeStruct( + string mSymbol = "", // Specify Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Specify TimeFrame + int barIndex = 0 // Specify Bar Index +) +{ + // + MqlDateTime result = {}; + + // + // Retrieve Bar Time ... + datetime barTime = GetBarTime( + mSymbol, + mPeriod, + barIndex); + + // + // Convert to Structure ... + TimeToStruct(barTime, result); + + // + return result; +} + +// +// Retrieve Last Available Bar Time of +// Dest Period inside Source Period ... +datetime GetLastBarTime( + ENUM_TIMEFRAMES sourcePeriod, + ENUM_TIMEFRAMES destPeriod // +) +{ + // + datetime result = NULL; + + // + if (!IsValid(sourcePeriod) || + !IsValid(destPeriod)) + { + return result; + } + + // + int sourceSeconds = PeriodSeconds(sourcePeriod); + int destSeconds = PeriodSeconds(destPeriod); + if (sourceSeconds < destSeconds) + { + return result; + } + + // + XOHCL sourceBar; + bool isInited = sourceBar.Init( + _Symbol, + sourcePeriod, + 0 // + ); + if (!isInited) + { + return result; + } + + // + result = (datetime)((((int)sourceBar.time) + sourceSeconds) - destSeconds); + + // + return result; +} + +// +// Other Tools ... + +// +template +bool IsSame( + T &buffer[], // Search Buffer + int count = 5, // Number of Searchs + int start = 0 // Start ... +) +{ + // + bool result = false; + + // + int bufferSize = ArraySize(buffer); + result = bufferSize > 0; + if (!result) + { + return result; + } + + // + // Validate Count ... + result = start + count < bufferSize; + if (!result) + { + return result; + } + + // + T iTem = buffer[start]; + for (int i = start; i < start + count; i++) + { + // + if (iTem != buffer[i]) + { + result = false; + break; + } + + // + if (!result) + { + result = true; + } + } + + // + return result; +} + +// +// Check first Cross Over second at index ... +bool IsCrossedOver( + const double &first[], // the buffer which check crossing over second buffer + const double &second[], // first buffer checks based on this buffer + const int index = 0 // check crosses in specific index +) +{ + // + bool result = false; + + // + // Validate Args ... + if (ArraySize(first) < index + 1 || ArraySize(second) < index + 1) + { + return result; + } + + // + result = first[index] > second[index] && + !(first[index + 1] > second[index + 1]); + + // + return result; +} + +// +// Check first is Over second at index ... +bool IsOver( + const double &first[], // the buffer which check over second buffer + const double &second[], // first buffer checks based on this buffer + const int index = 0 // check crosses in specific index +) +{ + // + bool result = false; + + // + // Validate Args ... + if (ArraySize(first) < index + 1 || ArraySize(second) < index + 1) + { + return result; + } + + // + result = first[index] > second[index] && + first[index + 1] > second[index + 1]; + + // + return result; +} + +// +// Check first Cross Under second at index ... +bool IsCrossedUnder( + const double &first[], // the buffer which check crossing under second buffer + const double &second[], // first buffer checks based on this buffer + const int index = 0 // check crosses in specific index +) +{ + // + bool result = false; + + // + // Validate Args ... + if (ArraySize(first) < index + 1 || ArraySize(second) < index + 1) + { + return result; + } + + // + result = first[index] < second[index] && + !(first[index + 1] < second[index + 1]); + + // + return result; +} + +// +// Check first is Under second at index ... +bool IsUnder( + const double &first[], // the buffer which check under second buffer + const double &second[], // first buffer checks based on this buffer + const int index = 0 // check crosses in specific index +) +{ + // + bool result = false; + + // + // Validate Args ... + if (ArraySize(first) < index + 1 || ArraySize(second) < index + 1) + { + return result; + } + + // + result = first[index] < second[index] && + first[index + 1] < second[index + 1]; + + // + return result; +} + +// +// Check if a Value Increasing in Loopback ... +bool IsIncreasing( + const int from, // Last Time Index + const int to, // Fisrs Tima Index + const double &buffer[] // the Buffer which required to search +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + from <= to || + ArraySize(buffer) < from + 1) + { + return result; + } + + // + // Loop through Items ... + double toValue = buffer[to]; + double fromValue = buffer[from]; + result = toValue > fromValue; + for (int i = to + 1; i <= from - 1; i++) + { + // + double iValue = buffer[i]; + bool isPassed = toValue >= iValue; + + // + bool isIIncreasing = IsIncreasing( + from, + i, + buffer); + + // + // Check Result ... + result = result && isPassed && isIIncreasing; + if (!result) + { + break; + } + } + + // + return result; +} + +// +// Check if a Value Decreasing in Loopback ... +bool IsDecreasing( + const int from, // Last Time Index + const int to, // Fisr Tima Index + const double &buffer[] // the Buffer which required to search +) +{ + // + bool result = false; + + // + // Validate Args ... + if ( + from <= to || + ArraySize(buffer) < from + 1) + { + return result; + } + + // + // Loop through Items ... + double toValue = buffer[to]; + double fromValue = buffer[from]; + result = toValue < fromValue; + for (int i = to + 1; i <= from - 1; i++) + { + // + double iValue = buffer[i]; + bool isPassed = toValue <= iValue; + + // + bool isIDecreasing = IsDecreasing( + from, + i, + buffer); + + // + // Check Result ... + result = result && isPassed && isIDecreasing; + if (!result) + { + break; + } + } + + // + return result; +} + +// +bool IsTrendingUp( + const double &buffer1[], // First Buffer + const double &buffer2[] // Seccend Buffer +) +{ + // + bool result = false; + + // + int buffer1Count = ArraySize(buffer1); + int buffer2Count = ArraySize(buffer2); + if (buffer1Count <= 0 || buffer2Count <= 0) + { + return result; + } + + // + int count = MathMin(buffer1Count, buffer2Count); + if (count <= 1) + { + return result; + } + + // + int upCounts = 0; + int downCounts = 0; + double value = MathAbs(buffer1[0] - buffer2[0]); + for (int i = 1; i < count; i++) + { + // + double iValue = MathAbs(buffer1[i] - buffer2[i]); + + // + if (value > iValue) + { + upCounts++; + } + + // + if (value < iValue) + { + downCounts++; + } + } + + // + result = upCounts > 1 && upCounts > downCounts; + + // + return result; +} + +// +bool IsTrendingDown( + const double &buffer1[], // First Buffer + const double &buffer2[] // Seccend Buffer +) +{ + // + bool result = false; + + // + int buffer1Count = ArraySize(buffer1); + int buffer2Count = ArraySize(buffer2); + if (buffer1Count <= 0 || buffer2Count <= 0) + { + return result; + } + + // + int count = MathMin(buffer1Count, buffer2Count); + if (count <= 1) + { + return result; + } + + // + int upCounts = 0; + int downCounts = 0; + double value = MathAbs(buffer1[0] - buffer2[0]); + for (int i = 1; i < count; i++) + { + // + double iValue = MathAbs(buffer1[i] - buffer2[i]); + + // + if (value > iValue) + { + upCounts++; + } + + // + if (value < iValue) + { + downCounts++; + } + } + + // + result = downCounts > 1 && downCounts > upCounts; + + // + return result; +} + +// +// Calculate Slope of Specified Buffer at Specified Index ... +double GetSlope( + const double &buffer[], // Buffer + int from, // In Past Index ... + int to // In Past Index ... +) +{ + // + double result = 0; + + // + if (from > ArraySize(buffer) || to > ArraySize(buffer)) + { + return result; + } + + // + double toValue = buffer[to]; + double fromValue = buffer[from]; + double deltaValue = toValue - fromValue; + double deltaTime = from - to; + + // + result = deltaValue / deltaTime; + + // + return result; +} + +// +// Calculate Fib Level ... +double GetFibonacciLevel( + double upPrice, // Upper Bound + double downPrice, // Downer Bound + double level, // Level Multiplier Factor + int direction // From Down to Up < 0, other wise Vice Versa + // +) +{ + // + double ling = upPrice - downPrice; + double pLevel = (ling / 100) * (level * 100); + + // + double result = direction > 0 ? upPrice - pLevel : downPrice + pLevel; + + // + return result; +} + +// +// Method 1 +// Normalize between 1 and 0 ... +template +double GetNormalizedValueMethod1( + T &buffer[], // Array which required to Normalize + int mLength, // Length of Normalization + int mStart = 0, // start index + int digits = 5 // Normalization Digits +) +{ + // + double result = 0; + + // + if (digits <= 5) + { + digits = 5; + } + + // + int bufferSize = ArraySize(buffer); + if (!IsValidSize(bufferSize)) + { + return result; + } + + // + // Normalize Count ... + NormalizeCount( + mStart, + mLength, + buffer // + ); + + // + T max = 0; + T min = 0; + + // + if (bufferSize != mLength) + { + // + T tmp[]; + Copy( + mStart, + mLength, + buffer, + tmp // + ); + + // + max = GetMax(tmp); + min = GetMin(tmp); + } + + // + if (bufferSize == mLength) + { + // + max = GetMax(buffer); + min = GetMin(buffer); + } + + // + T iValue = buffer[mStart]; + + // + double minMaxDiff = (max - min); + if (minMaxDiff <= 0) + { + return result; + } + + // + result = (iValue - min) / minMaxDiff; + + // + result = NormalizeDouble(result, digits); + + // + return result; +} + +// +// Method 2 +// Normalize Between Specified Upper and Lower ... +template +double GetNormalizedValueMethod2( + T &buffer[], // Array which required to Normalize + int mLength, // Length of Normalization + int mUpper, // Specified Upper Value + int mLower, // Specified Lower Value + int mStart = 0, // start index + int digits = 5 // Normalization Digits +) +{ + // + double result = 0; + + // + if (digits <= 5) + { + digits = 5; + } + + // + int bufferSize = ArraySize(buffer); + if (!IsValidSize(bufferSize)) + { + return result; + } + + // + // Normalize Count ... + NormalizeCount( + mStart, + mLength, + buffer // + ); + + // + T max = 0; + T min = 0; + + // + if (bufferSize != mLength) + { + // + T tmp[]; + Copy( + mStart, + mLength, + buffer, + tmp // + ); + + // + max = GetMax(tmp); + min = GetMin(tmp); + } + + // + if (bufferSize == mLength) + { + // + max = GetMax(buffer); + min = GetMin(buffer); + } + + // + T iValue = buffer[mStart]; + + // + double minMaxDiff = (max - min); + double boundaryDiff = (mUpper - mLower); + if (minMaxDiff <= 0 || boundaryDiff <= 0) + { + return result; + } + + // + result = boundaryDiff / (minMaxDiff * (iValue - max) + max); + + // + result = NormalizeDouble(result, digits); + + // + return result; +} + +// +void NormalizeBuffer( + double &source[], // Source Buffer + double &dest[], // Result Buffer + double upper = 100, // Upper Value to Normalize + double lower = -100, // Lower Value to Normalize + int size = -1, // Size Of Normalization + int digits = 5 // Digits for Result +) +{ + // + if (size <= 0) + { + size = ArraySize(source); + } + + // + bool asSeriesFlag = ArrayGetAsSeries(source); + + // + ArraySetAsSeries(source, false); + ArraySetAsSeries(dest, false); + + // + double min = ArrayMinimum(source, 0, size); + double max = ArrayMaximum(source, 0, size); + + // + for (int i = 0; i < size; i++) + { + // + double iNormal = lower + ((source[i] - min) / (max - min)) * (upper - lower); + + // + if (digits > 0) + { + iNormal = NormalizeDouble(iNormal, digits); + } + + // + dest[i] = iNormal; + } + + // + ArraySetAsSeries(source, asSeriesFlag); + ArraySetAsSeries(dest, asSeriesFlag); +} + +// +// Templates ... + +// +// Retrieve Specific Object Types Name ... +template +string GetTypeName(const T &t) +{ + return typename(T); +} + +// +template +string GetToken(T &item) +{ + // + string mType = GetTypeName(item); + + // + string result = mType; + + // + string parts[]; + int partsCount = SplitContent( + parts, + result, + " " + // + ); + if (partsCount <= 0) + { + // + result = mType; + return result; + } + + // + bool hasLastPart = GetLastItem( + result, + parts + // + ); + if (!hasLastPart) + { + // + result = mType; + return result; + } + + // + return result; +} + +// +// Same as Get Token for Use in Classes ... +template +string GetSpecificToken(T &item) +{ + // + string mType = GetTypeName(item); + + // + string result = mType; + + // + string parts[]; + int partsCount = SplitContent( + parts, + result, + " " + // + ); + if (partsCount <= 0) + { + // + result = mType; + return result; + } + + // + bool hasLastPart = GetLastItem( + result, + parts + // + ); + if (!hasLastPart) + { + // + result = mType; + return result; + } + + // + return result; +} + +// +// Generate Unique Tags ... +template +string GenerateTag(T &model) +{ + // + string result = ""; + + // + string tag = model.ToString(); + if (StringLen(tag) == 0) + { + return result; + } + + // + static XSCMD5 md5; + + // + result = md5.Hash(tag); + + // + return result; +} + +// +// Hash Specified Content ... +template +string ToMD5(T content) +{ + // + string result = ""; + + // + string strContent = ToString(content); + if (StringLen(strContent) == 0) + { + return result; + } + + // + static XCMD5 md5; + + // + result = md5.Hash(strContent); + + // + return result; +} + +// +// 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 != EMPTY_VALUE && value != 0; +} + +// +// Add Specified Item to Array ... +template +int Add( + T item, // item want to add + T &buffer[] // Destination buffer +) +{ + // + int result = 0; + + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; + + // + result = ArraySize(buffer); + + // + return result; +} +template +int AddSpecific( + T item, // item want to add + T &buffer[] // Destination buffer +) +{ + // + return Add( + item, + buffer // + ); +} +template +int AddRef( + T &item, // item want to add + T &buffer[] // Destination buffer +) +{ + // + int result = 0; + + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; + + // + result = ArraySize(buffer); + + // + return result; +} + +// +// Remove Specified Item from an Array ... +template +bool Remove( + T item, + T &buffer[]) +{ + // + bool result = false; + + // + int itemIndex = FindIndex( + item, + buffer); + if (itemIndex < 0) + { + return result; + } + + // + result = ArrayRemove( + buffer, + itemIndex, + 1); + + // + return result; +} + +// +// Clean Specified Array ... +template +void Clean(T &buffer[]) +{ + // + ArrayFree(buffer); + ArrayResize(buffer, 0); +} +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 // + ); +} + +// +// Search Array For Specific Item ... +template +int FindIndex( + T item, // What is Search ... + T &buffer[] // Search in ... +) +{ + // + int result = -1; + + // + int count = ArraySize(buffer); + if (count <= 0) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + T iT = buffer[i]; + + // + if (iT == item) + { + // + result = i; + break; + } + } + + // + return result; +} + +// +// Check an Array Contains Specified Value ... +template +bool Contains( + T item, // What is Search ... + T &buffer[] // Search in ... +) +{ + // + bool result = false; + + // + int idx = FindIndex( + item, + buffer); + result = idx > -1; + + // + return result; +} + +// +// Calculate a Buffer's 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 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 // + ); +} + +// +// 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 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 // + ); +} + +// +// Find a Value less than Specified ... +template +T FindLesserThan( + T value, // Specified Value ... + const T &source[], // Source ... + bool isDescend = false // Find Biggest Lesser Value ... +) +{ + // + T result = -1; + + // + int itemsCount = ArraySize(source); + if (itemsCount <= 0) + { + return result; + } + + // + // Make a Copy of source ... + T tmp[]; + + // + ArrayResize( + tmp, + ArraySize(source)); + + // + ArrayCopy( + tmp, + source); + + // + // Sort Temp Buffer ... + ArraySort(tmp); + if (isDescend) + { + ArrayReverse(tmp); + } + + // + int tmpCount = ArraySize(tmp); + for (int i = 0; i < tmpCount; i++) + { + // + T iValue = tmp[i]; + + // + if (iValue < value) + { + // + result = iValue; + break; + } + } + + // + return result; +} + +// +// Find a Value less than Specified ... +template +T FindBiggerThan( + T value, // Specified Value ... + const T &source[], // Source ... + bool isDescend = false // Find Smallest Bigger Value ... +) +{ + // + T result = -1; + + // + int itemsCount = ArraySize(source); + if (itemsCount <= 0) + { + return result; + } + + // + // Make a Copy of source ... + T tmp[]; + + // + ArrayResize( + tmp, + ArraySize(source)); + + // + ArrayCopy( + tmp, + source); + + // + // Sort Temp Buffer ... + ArraySort(tmp); + if (!isDescend) + { + ArrayReverse(tmp); + } + + // + int tmpCount = ArraySize(tmp); + for (int i = 0; i < tmpCount; i++) + { + // + T iValue = tmp[i]; + + // + if (iValue > value) + { + // + result = iValue; + break; + } + } + + // + return result; +} + +// +// Find Same Values in Array ... +template +void FindSames( + T &result[], // Holds Result ... + T &source[], // Source ... + int verifications = 3 // Number of Consequence Repeat ... +) +{ + // + Clean(result); + + // + // TenkanSen Flats ... + int sourceCount = ArraySize(source); + if (sourceCount > verifications) + { + // + T mLast = 0; + int mVerified = 0; + for (int i = 0; i < sourceCount; i++) + { + // + T iVal = source[i]; + if (mLast == 0) + { + mLast = iVal; + } + else if (mLast == iVal) + { + mVerified++; + } + else + { + mLast = iVal; + mVerified = 0; + } + + // + if (iVal == mLast && mVerified >= verifications) + { + // + Add( + iVal, + result); + + // + mLast = 0; + mVerified = 0; + } + } + } +} + +// +// Add an Item to a Buffer if not Exists ... +void AddIfNotExists( + double value, + double &values[], + double smoothingPoint = 3 // +) +{ + // + double smoothingValue = smoothingPoint * GetPoints(_Symbol); + + // + int valuesCount = ArraySize(values); + if (valuesCount <= 0) + { + // + Add(value, + values); + } + else + { + // + bool isExists = false; + for (int i = 0; i < valuesCount; i++) + { + // + double iVal = values[i]; + + // + double diff = MathAbs(iVal - value); + + // + if (iVal == value || diff < smoothingValue) + { + // + isExists = true; + break; + } + } + + // + if (!isExists) + { + // + Add(value, + values); + } + } +} + +// +// Add a Buffers Child to another Buffer +// if it's not Contains them ... +void AddsIfNotExists( + double &source[], + double &dest[], + double smoothingPoint = 3) +{ + // + double smoothingValue = smoothingPoint * GetPoints(_Symbol); + + // + int sourceCount = ArraySize(source); + if (sourceCount <= 0) + { + return; + } + + // + for (int i = 0; i < sourceCount; i++) + { + // + double iSource = source[i]; + + // + AddIfNotExists( + iSource, + dest, + smoothingPoint); + } +} + +// +// Bar XOHCL ... + +// +// Extract Specific Range of Bars ... +// using Start Bar Index ... +int GetBars( + XOHCL &result[], // Hold Result + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Time Frame + int from = 0, // Start Bar Index + int count = 1, // Number of Bars + bool forceClean = true // Clean Result Array +) +{ + // + int mResult = 0; + + // + if (from < 0) + { + from = 0; + } + + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + int total = Bars( + mSymbol, + mPeriod); + if (from > total - 2) + { + from = total - 2; + } + + // + if (count < 0) + { + count = 1; + } + + // + int start = from; + int end = start + count; + if (end > total - 1) + { + end = total - 1; + } + + // + if (forceClean) + { + Clean(result); + } + + // + int beforeSize = ArraySize(result); + + // + for (int i = start; i < end; i++) + { + // + XOHCL iBar; + bool isValid = iBar.Init( + mSymbol, + mPeriod, + i + // + ); + + // + if (isValid) + { + // + AddRef( + iBar, + result + // + ); + } + } + + // + int afterSize = ArraySize(result); + + // + mResult = afterSize - beforeSize; + + // + return mResult; +} + +// +// Extract Specific Range of Bars ... +// using Start Bar Time ... +int GetBars( + XOHCL &result[], // Hold Result + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Time Frame + datetime from = NULL, // Start Bar Time + int count = 1, // Number of Bars + bool forceClean = true // Clean Result Array +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + from = NormalizeTime(from); + + // + int barIndex = iBarShift( + mSymbol, + mPeriod, + from, + false + // + ); + + // + return GetBars( + result, + mSymbol, + mPeriod, + barIndex, + count, + forceClean + // + ); +} + +// +// String ... + +// +// Search a Content Contains Specific String or not ... +bool Contains( + string mQuery, // Search String + string mContent, // Search Content + bool ignoreCase = true // Ignore Case +) +{ + // + bool result = false; + + // + // Validate Query ... + result = IsValid(mQuery); + if (!result) + { + return result; + } + + // + // Validate Content ... + result = IsValid(mContent); + if (!result) + { + return result; + } + + // + // Normalize Inputs ... + string query = mQuery; + string content = mContent; + if (ignoreCase) + { + // + StringToLower(query); + StringToLower(content); + } + + // + int queryIdx = StringFind( + content, + query); + + // + result = queryIdx >= 0; + + // + return result; +} + +// +bool Contains( + string &mQueries[], // Search Strings + string mContent, // Search Content + bool ignoreCase = true // Ignore Case +) +{ + // + bool result = false; + + // + // Validate Queries ... + int queriesCount = ArraySize(mQueries); + result = queriesCount > 0; + if (!result) + { + return result; + } + + // + // Validate Content ... + result = IsValid(mContent); + if (!result) + { + return result; + } + + // + int containsCount = 0; + for (int i = 0; i < queriesCount; i++) + { + // + bool isContains = Contains( + mQueries[i], + mContent, + ignoreCase); + + // + if (!isContains) + { + // + result = false; + break; + } + + // + containsCount++; + } + + // + result = containsCount == queriesCount; + + // + return result; +} + +// +int FindIndexes( + string mQuery, // Search String + string mContent, // Search Content + int &result[], // Holding Results + bool ignoreCase = false // Ignore Case +) +{ + // + 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 ... +template +T FromString(string value) +{ + // + T result = NULL; + + // + if (!IsValid(value)) + { + return result; + } + + // + result = (T)value; + + // + return result; +} + +// +// Converts an item to String ... +template +string ToString(T value) +{ + return (string)value; +} + +// +// Used In Report or Summary Generators ... +string ToString( + string prefix, // Title + bool value, // Value + bool ignoreFalseConditions = true, // Ignore False Conditions + string lineSeparator = "\n", // Line Separator + string prefixSeparator = ":" // Title Separator +) +{ + // + string result = NULL; + + // + result = (value || !ignoreFalseConditions) + ? prefix + + prefixSeparator + " " + + ToString(value) + + lineSeparator + : ""; + + // + return result; +} + +// +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 ... +bool ToBoolean(string value) +{ + // + bool result = false; + + // + if (StringLen(value) <= 0) + { + return result; + } + + // + StringToLower(value); + result = value == "true"; + + // + return result; +} + +// +// Split an String Representation of an Array ... +int SplitContent( + string &result[], // Hold Result ... + string content, // Source ... + string separator = ",", // Separator ... + bool forceCleanResult = true // Clean Result ... +) +{ + // + int mResult = 0; + + // + if (forceCleanResult) + { + Clean(result); + } + + // + int before = ArraySize(result); + + // + if (separator == NULL || StringLen(separator) == 0) + { + separator = ","; + } + + // + if (StringLen(content) == 0) + { + return mResult; + } + + // + StringSplit( + content, + StringGetCharacter( + separator, + 0), + result); + + // + int after = ArraySize(result); + + // + mResult = after - before; + + // + return mResult; +} + +// +// Extract Data from String ... +string ExtractString( + const string source, // Source String used for Extracting + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + string result = ""; + + // + // Validate String ... + if ( + StringLen(source) == 0 || + StringLen(endString) == 0 || + StringLen(startString) == 0) + { + return result; + } + + // + // Find Start String Position ... + int sPos = StringFind( + source, + startString); + if (sPos < 0) + { + return result; + } + + // + // Find End String Position after Start String ... + int searchEndFromPos = sPos + StringLen(startString); + int ePos = StringFind( + source, + endString, + searchEndFromPos); + if (ePos < 0) + { + return result; + } + + // + // Extract Data from Source ... + int dLength = ePos - searchEndFromPos; + result = StringSubstr( + source, + searchEndFromPos, + dLength); + + // + return result; +} + +// +// Extract an Array of Contents ... +int ExtractStrings( + string &result[], // Hold Result + const string source, // Source String used for Extracting + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + int mResult = 0; + + // + Clean(result); + + // + // Validate Args ... + int sourceLength = StringLen(source); + int startLength = StringLen(startString); + int endLength = StringLen(endString); + + // + int minRequiredLength = startLength + endLength; + + // + if ( + endLength <= 0 || + startLength <= 0 || + sourceLength <= 0 || + sourceLength < minRequiredLength) + { + return mResult; + } + + // + // Make a Copy of Source for Manipulating ... + string workStr = source; + + // + // Define a Loop ... + while (StringLen(workStr) > minRequiredLength) + { + // + // Find Item ... + string item = ExtractString( + workStr, + startString, + endString); + + // + // Breakout when couldn't find anymore item ... + int itemLength = StringLen(item); + if (itemLength <= 0) + { + break; + } + + // + // Prepare Item Source String for Replacing in Work String ... + string itemSource = startString + item + endString; + + // + // Add Item to Result Array ... + Add( + item, + result); + + // + // Replace Item Soure in Work String ... + StringReplace( + workStr, + itemSource, + ""); + } + + // + // Calculate Size of Array ... + mResult = ArraySize(result); + + // + return mResult; +} + +// +string ExtractSurrounded( + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + return ExtractString( + surrounded, + mToken + startString, + endString + // + ); +} + +// +int ParseIntSurrounded( + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + int result = NULL; + + // + string strContent = ExtractSurrounded( + surrounded, + mToken, + startString, + endString + // + ); + if (!IsValid(strContent)) + { + return result; + } + + // + result = (int)strContent; + + // + return result; +} +long ParseLongSurrounded( + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + long result = NULL; + + // + string strContent = ExtractSurrounded( + surrounded, + mToken, + startString, + endString + // + ); + if (!IsValid(strContent)) + { + return result; + } + + // + result = (long)strContent; + + // + return result; +} +string ParseStringSurrounded( + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + string result = NULL; + + // + string strContent = ExtractSurrounded( + surrounded, + mToken, + startString, + endString + // + ); + if (!IsValid(strContent)) + { + return result; + } + + // + result = (string)strContent; + + // + return result; +} +double ParseDoubleSurrounded( + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + double result = NULL; + + // + string strContent = ExtractSurrounded( + surrounded, + mToken, + startString, + endString + // + ); + if (!IsValid(strContent)) + { + return result; + } + + // + result = (double)strContent; + + // + return result; +} +datetime ParseTimeSurrounded( + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + datetime result = NULL; + + // + string strContent = ExtractSurrounded( + surrounded, + mToken, + startString, + endString + // + ); + if (!IsValid(strContent)) + { + return result; + } + + // + result = (datetime)strContent; + + // + return result; +} + +// +int ParseIntArraySurrounded( + int &result[], // Holds Result + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + string separator = ",", // Separator ... + const string startString = "(", // Expression Start String must be Unique + const string endString = ")", // Where to End Extraction, usually a Sign + bool forceClean = true // Clean Result ... +) +{ + // + int count = 0; + + // + if (forceClean) + { + Clean(result); + } + + // + int before = ArraySize(result); + + // + string contentStr = ParseStringSurrounded(surrounded, mToken); + if (!IsValid(contentStr)) + { + return count; + } + + // + string tmps[]; + int tmpsCount = SplitContent( + tmps, + contentStr + // + ); + if (tmpsCount <= 0) + { + return count; + } + + // + for (int i = 0; i < tmpsCount; i++) + { + // + string iTMP = tmps[i]; + if (!IsValid(iTMP)) + { + continue; + } + + // + int iValue = (int)iTMP; + + // + Add( + iValue, + result + // + ); + } + + // + int after = ArraySize(result); + + // + count = after - before; + + // + return count; +} +int ParseLongArraySurrounded( + long &result[], // Holds Result + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + string separator = ",", // Separator ... + const string startString = "(", // Expression Start String must be Unique + const string endString = ")", // Where to End Extraction, usually a Sign + bool forceClean = true // Clean Result ... +) +{ + // + int count = 0; + + // + if (forceClean) + { + Clean(result); + } + + // + int before = ArraySize(result); + + // + string contentStr = ParseStringSurrounded(surrounded, mToken); + if (!IsValid(contentStr)) + { + return count; + } + + // + string tmps[]; + int tmpsCount = SplitContent( + tmps, + contentStr + // + ); + if (tmpsCount <= 0) + { + return count; + } + + // + for (int i = 0; i < tmpsCount; i++) + { + // + string iTMP = tmps[i]; + if (!IsValid(iTMP)) + { + continue; + } + + // + long iValue = (long)iTMP; + + // + Add( + iValue, + result + // + ); + } + + // + int after = ArraySize(result); + + // + count = after - before; + + // + return count; +} +int ParseDoubleArraySurrounded( + double &result[], // Holds Result + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + string separator = ",", // Separator ... + const string startString = "(", // Expression Start String must be Unique + const string endString = ")", // Where to End Extraction, usually a Sign + bool forceClean = true // Clean Result ... +) +{ + // + int count = 0; + + // + if (forceClean) + { + Clean(result); + } + + // + int before = ArraySize(result); + + // + string contentStr = ParseStringSurrounded(surrounded, mToken); + if (!IsValid(contentStr)) + { + return count; + } + + // + string tmps[]; + int tmpsCount = SplitContent( + tmps, + contentStr + // + ); + if (tmpsCount <= 0) + { + return count; + } + + // + for (int i = 0; i < tmpsCount; i++) + { + // + string iTMP = tmps[i]; + if (!IsValid(iTMP)) + { + continue; + } + + // + double iValue = (double)iTMP; + + // + Add( + iValue, + result + // + ); + } + + // + int after = ArraySize(result); + + // + count = after - before; + + // + return count; +} +int ParseTimeArraySurrounded( + datetime &result[], // Holds Result + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + string separator = ",", // Separator ... + const string startString = "(", // Expression Start String must be Unique + const string endString = ")", // Where to End Extraction, usually a Sign + bool forceClean = true // Clean Result ... +) +{ + // + int count = 0; + + // + if (forceClean) + { + Clean(result); + } + + // + int before = ArraySize(result); + + // + string contentStr = ParseStringSurrounded(surrounded, mToken); + if (!IsValid(contentStr)) + { + return count; + } + + // + string tmps[]; + int tmpsCount = SplitContent( + tmps, + contentStr + // + ); + if (tmpsCount <= 0) + { + return count; + } + + // + for (int i = 0; i < tmpsCount; i++) + { + // + string iTMP = tmps[i]; + if (!IsValid(iTMP)) + { + continue; + } + + // + datetime iValue = (datetime)iTMP; + + // + Add( + iValue, + result + // + ); + } + + // + int after = ArraySize(result); + + // + count = after - before; + + // + return count; +} + +// +// Surround an String by Specific Token ... +template +string Surround( + string mToken, // an String which used to Tokenize + T &value, // a Value for Tokenize it + string startString = "(", // Token Start Content + string endString = ")" // Token End Content +) +{ + // + string result = NULL; + + // + string strValue = ToString(value); + if (!IsValid(strValue)) + { + return result; + } + + // + result = + // + (IsValid(mToken) + ? mToken + : "") + + // + startString + + strValue + + endString + // + ; + + // + return result; +} + +// +template +string SurroundArray( + string mToken, + T &value[], + string startString = "(", // Token Start Content + string endString = ")" // Token End Content +) +{ + // + string result = NULL; + + // + string valueStr = ToString(value); + if (!IsValid(valueStr)) + { + return result; + } + + // + result = Surround( + mToken, + valueStr, + startString, + endString + // + ); + + // + return result; +} + +// +// Periods / Cycles ... + +// +// Converts an String to TimeFrame ... +ENUM_TIMEFRAMES ToPeriod(string value) +{ + // + if (StringLen(value) == 0) + { + return _Period; + } + + // + StringTrimLeft(value); + StringTrimRight(value); + + // + ENUM_TIMEFRAMES result = _Period; + + // + if (value == "M1") + { + result = PERIOD_M1; + } + else if (value == "M2") + { + result = PERIOD_M2; + } + else if (value == "M3") + { + result = PERIOD_M3; + } + else if (value == "M4") + { + result = PERIOD_M4; + } + else if (value == "M5") + { + result = PERIOD_M5; + } + else if (value == "M6") + { + result = PERIOD_M6; + } + else if (value == "M10") + { + result = PERIOD_M10; + } + else if (value == "M12") + { + result = PERIOD_M12; + } + else if (value == "M15") + { + result = PERIOD_M15; + } + else if (value == "M20") + { + result = PERIOD_M20; + } + else if (value == "M30") + { + result = PERIOD_M30; + } + else if (value == "H1") + { + result = PERIOD_H1; + } + else if (value == "H2") + { + result = PERIOD_H2; + } + else if (value == "H3") + { + result = PERIOD_H3; + } + else if (value == "H4") + { + result = PERIOD_H4; + } + else if (value == "H6") + { + result = PERIOD_H6; + } + else if (value == "H8") + { + result = PERIOD_H8; + } + else if (value == "H12") + { + result = PERIOD_H12; + } + else if (value == "D1") + { + result = PERIOD_D1; + } + else if (value == "W1") + { + result = PERIOD_W1; + } + else if (value == "MN1") + { + result = PERIOD_MN1; + } + + // + return result; +} + +// +// Converts Period to String ... +string ToString(ENUM_TIMEFRAMES mPeriod) +{ + // + string result = ""; + + // + string mPStr = EnumToString(mPeriod); + + string mPStrParts[]; + int partsCount = StringSplit( + mPStr, + StringGetCharacter("_", 0), + mPStrParts); + if (partsCount <= 0) + { + return result; + } + + // + result = mPStrParts[1]; + + // + return result; +} + +// +// Retrieve All Available Period as an Array ...s +int GetAllAvailablePeriods( + ENUM_TIMEFRAMES &result[] // Holds Result ... +) +{ + // + Clean(result); + + // + Add( + PERIOD_M1, + result + // + ); + + // + Add( + PERIOD_M2, + result + // + ); + + // + Add( + PERIOD_M3, + result + // + ); + + // + Add( + PERIOD_M4, + result + // + ); + + // + Add( + PERIOD_M5, + result + // + ); + + // + Add( + PERIOD_M6, + result + // + ); + + // + Add( + PERIOD_M10, + result + // + ); + + // + Add( + PERIOD_M12, + result + // + ); + + // + Add( + PERIOD_M15, + result + // + ); + + // + Add( + PERIOD_M20, + result + // + ); + + // + Add( + PERIOD_M30, + result + // + ); + + // + Add( + PERIOD_H1, + result + // + ); + + // + Add( + PERIOD_H2, + result + // + ); + + // + Add( + PERIOD_H3, + result + // + ); + + // + Add( + PERIOD_H4, + result + // + ); + + // + Add( + PERIOD_H6, + result + // + ); + + // + Add( + PERIOD_H8, + result + // + ); + + // + Add( + PERIOD_H12, + result + // + ); + + // + Add( + PERIOD_D1, + result + // + ); + + // + Add( + PERIOD_W1, + result + // + ); + + // + Add( + PERIOD_MN1, + result + // + ); + + // + int mResult = ArraySize(result); + + // + return mResult; +} + +// +// Get Specific Time Frame Start Candle Time ... +datetime GetPeriodStartTime( + string mSymbol = NULL, // Specified Symbol ... + ENUM_TIMEFRAMES mPeriod = NULL, // Specified Period ... + datetime mTime = NULL // Specified Bar Time of Host Period ... +) +{ + // + // Normalize Arg ... + mTime = NormalizeTime(mTime); + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + int barIndex = iBarShift( + mSymbol, + mPeriod, + mTime, + false + // + ); + + // + datetime result = GetBarTime( + mSymbol, + mPeriod, + barIndex + // + ); + + // + return result; +} + +// +// Converts an String to it's related Market Cycle ... +ENUM_X_MARKET_CYCLES ToCycle(string value) +{ + // + ENUM_X_MARKET_CYCLES result = X_MARKET_CYCLE_UNKNOWN; + + // + ENUM_X_MARKET_CYCLES cycles[]; + int count = GetAllMarketCycles(cycles); + for (int i = 0; i < count; i++) + { + // + ENUM_X_MARKET_CYCLES iCycle = cycles[i]; + string iStr = ToString(iCycle); + + // + if (value == iStr) + { + // + result = iCycle; + break; + } + } + + // + return result; +} + +// +// Converts a Cycle to it's String Representation ... +string ToString(ENUM_X_MARKET_CYCLES cycle) +{ + // + string result = ""; + + // + string mPStr = EnumToString(cycle); + + string mPStrParts[]; + int partsCount = StringSplit( + mPStr, + StringGetCharacter("_", 0), + mPStrParts); + if (partsCount <= 0) + { + return result; + } + + // + result = mPStrParts[3]; + + // + return result; +} + +// +// Retrieve all Available Cycles ... +int GetAllMarketCycles(ENUM_X_MARKET_CYCLES &result[]) +{ + // + int mResult = 0; + + // + Clean(result); + + // + ENUM_X_MARKET_CYCLES tmp[] = { + X_MARKET_CYCLE_UNKNOWN, + X_MARKET_CYCLE_SHORT, + X_MARKET_CYCLE_MEDIUM, + X_MARKET_CYCLE_LONG, + X_MARKET_CYCLE_HIND}; + + // + Copy( + tmp, + result // + ); + + // + Clean(tmp); + + // + mResult = ArraySize(result); + + // + return mResult; +} + +// +// Retrieve Nearest Period base on Given Period ... +ENUM_TIMEFRAMES GetNearestPeriod(ENUM_TIMEFRAMES mPeriod) +{ + // + ENUM_TIMEFRAMES result = _Period; + + // + mPeriod = NormalizePeriod(mPeriod); + + // + switch (mPeriod) + { + // + case PERIOD_M1: + case PERIOD_M2: + 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_NOTHING && + _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; +} + +// +// Direction ... + +// +bool HasDirection(ENUM_X_DIRECTION value) +{ + // + bool result = false; + + // + result = value != X_DIRECTION_NONE && + value != X_DIRECTION_ALL; + + // + return result; +} + +// +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; +} + +// +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; +} + +// +// Moving Average ... + +/** + * 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 price: 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 &_price[], + double &_buffer[], + ENUM_MA_METHOD _method = MODE_SMA // +) +{ + // + int result = 0; + + // + if ( + _period < 0 || + _rates_total <= 0 || + _prev_calculated < 0 || + _prev_calculated > _rates_total) + { + return result; + } + + // + switch (_method) + { + // + case MODE_SMA: + result = SimpleMAOnBuffer( + _rates_total, + _prev_calculated, + _begin, + _period, + _price, + _buffer // + ); + break; + + // + case MODE_EMA: + result = ExponentialMAOnBuffer( + _rates_total, + _prev_calculated, + _begin, + _period, + _price, + _buffer // + ); + break; + + // + case MODE_LWMA: + result = LinearWeightedMAOnBuffer( + _rates_total, + _prev_calculated, + _begin, + _period, + _price, + _buffer // + ); + break; + + // + case MODE_SMMA: + result = SmoothedMAOnBuffer( + _rates_total, + _prev_calculated, + _begin, + _period, + _price, + _buffer // + ); + break; + } + + // + return result; +} + +// \ No newline at end of file diff --git a/BKPS/14031003/Libraries/x-saherelm.draw.lib.mq5 b/BKPS/14031003/Libraries/x-saherelm.draw.lib.mq5 new file mode 100644 index 0000000..aeb124e --- /dev/null +++ b/BKPS/14031003/Libraries/x-saherelm.draw.lib.mq5 @@ -0,0 +1,2620 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Draw Library +// -------------------------------------- +// Name: XDraw +// Description: provides Draw abilities ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Global Definitions: Variables, Properties and etc ... + +// +// Retrieve Chart Size in Pixel ... +struct XSize +{ + long width; + long height; + + // + int x; + int y; + int w; + int h; + + // + int wStep; + int hStep; +}; + +// +// Define a Draw Specifications ... +struct XDrawSpecifications +{ + // + // Props ... + + // + bool draw; // Draw or Not ... + + // + int width; // Draw Witdth ... + color clr; // Draw Color ... + ENUM_LINE_STYLE style; // Draw Style ... + + // + bool back; // in the background + bool fill; // fill object if supported + bool selection; // highlight to move + bool rayRight; // line's continuation to the right + bool hidden; // hidden in the object list + long zOrder; // priority for mouse click + + // + string label; // Label ... + color labelColor; // Label Color ... + double labelAngel; // Label Angle ... + string labelFont; // Label Font ... + int labelFontSize; // Label Font Size ... + ENUM_ANCHOR_POINT labelAnchor; // Label Anchor Point ... + + // + // Constructor ... + XDrawSpecifications() + { + Clean(); + } + + // + // Operator ... + void operator=(const XDrawSpecifications &value) + { + // + clr = value.clr; + draw = value.draw; + width = value.width; + style = value.style; + + // + back = value.back; + hidden = value.hidden; + zOrder = value.zOrder; + rayRight = value.rayRight; + selection = value.selection; + + // + fill = value.fill; + + // + label = value.label; + labelColor = value.labelColor; + labelAngel = value.labelAngel; + labelFont = value.labelFont; + labelFontSize = value.labelFontSize; + labelAnchor = value.labelAnchor; + } + + // + // Functions ... + + // + void Clean() + { + // + draw = false; + width = 1; + clr = CLR_NONE; + style = STYLE_SOLID; + + // + back = false; + hidden = false; + rayRight = false; + selection = false; + fill = false; + + // + zOrder = 0; + + // + label = ""; + labelColor = CLR_NONE; + labelAngel = 0; + labelFont = "Arial"; + labelFontSize = 20; + labelAnchor = ANCHOR_LEFT_UPPER; + } + + // + void Label( + string mLabel = "", // Label ... + color mLabelColor = CLR_NONE, // Label Color ... + string mLabelFont = "Arial", // Label Font ... + int mLabelFontSize = 20, // Label Font Size ... + ENUM_ANCHOR_POINT mLabelAnchor = ANCHOR_LEFT_UPPER, // Label Anchor Point ... + double mLabelAngel = 0 // Label Angle ... + ) + { + // + label = mLabel; + labelFont = mLabelFont; + labelColor = mLabelColor; + labelAngel = mLabelAngel; + labelAnchor = mLabelAnchor; + labelFontSize = mLabelFontSize; + } +}; + +// +// Candle Draw Specifications ... +struct XOHCLDrawSpecification +{ + // + // Props ... + XDrawSpecifications openStyle; + XDrawSpecifications highStyle; + XDrawSpecifications closeStyle; + XDrawSpecifications lowStyle; + + // + // Constructors ... + XOHCLDrawSpecification() + { + Clean(); + } + + // + // Operators ... + void operator=(const XOHCLDrawSpecification &value) + { + // + lowStyle = value.lowStyle; + openStyle = value.openStyle; + highStyle = value.highStyle; + closeStyle = value.closeStyle; + } + + // + // Functions ... + + // + void Clean() + { + // + lowStyle.Clean(); + openStyle.Clean(); + highStyle.Clean(); + closeStyle.Clean(); + } + + // + void Default() + { + // + // Open ... + openStyle.width = 1; + openStyle.draw = true; + openStyle.clr = clrLime; + openStyle.style = STYLE_SOLID; + openStyle.Label( + "O", + openStyle.clr); + + // + // High ... + highStyle.width = 1; + highStyle.draw = true; + highStyle.clr = clrAqua; + highStyle.style = STYLE_SOLID; + highStyle.Label( + "H", + highStyle.clr); + + // + // Close ... + closeStyle.width = 1; + closeStyle.draw = true; + closeStyle.clr = clrRed; + closeStyle.style = STYLE_SOLID; + closeStyle.Label( + "C", + closeStyle.clr); + + // + // Low ... + lowStyle.width = 1; + lowStyle.draw = true; + lowStyle.clr = clrMagenta; + lowStyle.style = STYLE_SOLID; + lowStyle.Label( + "L", + lowStyle.clr); + } + + // + void Width(int value) + { + // + lowStyle.width = value; + openStyle.width = value; + highStyle.width = value; + closeStyle.width = value; + } + + // + void Style(ENUM_LINE_STYLE value) + { + // + lowStyle.style = value; + openStyle.style = value; + highStyle.style = value; + closeStyle.style = value; + } + + // + void Color(color value) + { + // + lowStyle.clr = value; + openStyle.clr = value; + highStyle.clr = value; + closeStyle.clr = value; + } + + // + void RayRight(bool value) + { + // + lowStyle.rayRight = value; + openStyle.rayRight = value; + highStyle.rayRight = value; + closeStyle.rayRight = value; + } + + // + void Draw(bool value) + { + // + lowStyle.draw = value; + openStyle.draw = value; + highStyle.draw = value; + closeStyle.draw = value; + } + + // + void Back(bool value) + { + // + lowStyle.back = value; + openStyle.back = value; + highStyle.back = value; + closeStyle.back = value; + } + + // + void Fill(bool value) + { + // + lowStyle.fill = value; + openStyle.fill = value; + highStyle.fill = value; + closeStyle.fill = value; + } + + // + void Label(string value) + { + // + lowStyle.Label(value); + openStyle.Label(value); + highStyle.Label(value); + closeStyle.Label(value); + } + + // + void SetLabelPrefix(string value) + { + // + lowStyle.label = value + " " + lowStyle.label; + openStyle.label = value + " " + openStyle.label; + highStyle.label = value + " " + highStyle.label; + closeStyle.label = value + " " + closeStyle.label; + } +}; + +// +string drawPrefix = "X-OBJ"; + +// +// Common Draw Functions ... + +// +// remove drawn objects ... +void RemoveDraws( + string tag = NULL, + long chartId = -1, + int subWindow = -1 // +) +{ + // + // Normalize Args ... + // + if (tag == NULL) + { + tag = drawPrefix; + } + + // + if (chartId == -1) + { + chartId = 0; + } + + // + if (subWindow == -1) + { + subWindow = 0; + } + + // + for (int iObj = ObjectsTotal(chartId, subWindow) - 1; iObj >= 0; iObj--) + { + // + string on = ObjectName(chartId, iObj, subWindow); + if (StringFind(on, tag) >= 0) + { + ObjectDelete(chartId, on); + } + } + + // + // Redraw Chart ... + ChartRedraw(); +} + +// +bool RemoveDraw( + string name, + long chartId = -1, + int subWindow = -1 // +) +{ + // + bool result = false; + + // + if (chartId == -1) + { + chartId = 0; + } + + // + if (subWindow == -1) + { + subWindow = 0; + } + + // + string objName = ""; + for (int iObj = ObjectsTotal(chartId, subWindow) - 1; iObj >= 0; iObj--) + { + // + string on = ObjectName(chartId, iObj, subWindow); + if (StringFind(on, name) >= 0) + { + // + objName = on; + break; + } + } + + // + if (StringLen(objName) > 0) + { + result = ObjectDelete(chartId, objName); + } + + // + return result; +} + +// +// Deselect All Draws ... +void DeselectAllDraws() +{ + // + int objs = ObjectsTotal(ChartID(), 0); + for (int o = 0; o < objs; o++) + { + ObjectSetInteger(ChartID(), ObjectName(ChartID(), o, 0), OBJPROP_SELECTED, false); + } + + // + ChartRedraw(); +} + +// +// Check Object Exists ... +bool IsDrawExists( + string name, + long chartId = -1, + int subWindow = -1 // +) +{ + // + bool result = false; + + // + if (chartId == -1) + { + chartId = 0; + } + + // + if (subWindow == -1) + { + subWindow = 0; + } + + // + for (int iObj = ObjectsTotal(chartId, subWindow) - 1; iObj >= 0; iObj--) + { + // + string on = ObjectName(chartId, iObj, subWindow); + result = StringFind(on, name) >= 0; + if (result) + { + break; + } + } + + // + return result; +} + +// +// 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/14031003/Libraries/x-saherelm.x-poi.lib.ex5 b/BKPS/14031003/Libraries/x-saherelm.x-poi.lib.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..eb0f92f7703174a3546e6884d127b73d11297fb0 GIT binary patch literal 7886 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 SDDM3maSrn; + +// +// Definitions ... + +// +// 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 ... +}; + +// +// Event Types ... +enum ENUM_XPOI_EVENTS +{ + // + // 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Ù‘ ... +}; + +// +// Forext Sessions ... +enum ENUM_XSESSION +{ + X_TOKYO, + X_SYDNEY, + X_LONDON, + X_NEW_YORK, + X_FRANKFORT, +}; + +// +// 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: + // +}; + +// +// 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; + } + + /** + * Get Zone Lower Boundary ... + * + * @return ( double ) + */ + double Lower() + { + return mLower; + } + + /** + * 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() + { + return IsSpecifiedValid(From()); + } + + // + 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; + } + + ENUM_TIMEFRAMES GetPeriod() + { + // + ENUM_TIMEFRAMES result = NULL; + + // + XOHCL bar; + bool isFilled = FillBar(bar); + if (!isFilled) + { + return result; + } + + // + result = bar.period; + + // + 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; + } + + // + // 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, + bool useStartBarForUpper, + ENUM_X_PRICE upperPrice, + ENUM_X_PRICE lowerPrice // + ) + { + // + 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; + mUpperPrice = upperPrice; + mLowerPrice = lowerPrice; + mUseStartBarForUpper = useStartBarForUpper; + + mUpper = + useStartBarForUpper + ? startBar.GetPrice(upperPrice) + : endBar.GetPrice(upperPrice); + mLower = + useStartBarForUpper + ? endBar.GetPrice(lowerPrice) + : startBar.GetPrice(lowerPrice); + + // + 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; + } + + ENUM_TIMEFRAMES GetPeriod() + { + // + ENUM_TIMEFRAMES result = NULL; + + // + XOHCL bar; + bool isFilled = FillStartBar(bar); + if (!isFilled) + { + return result; + } + + // + result = bar.period; + + // + 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; + } + + 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 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 = (datetime)((int)time - (range * periodSeconds)); + 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 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 = (datetime)((int)time - (range * periodSeconds)); + 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 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 = (datetime)((int)time - (range * periodSeconds)); + 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 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 = (datetime)((int)time - (range * periodSeconds)); + 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; + } + + // + // 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; + + // + bool useFistForUpper = isDirBullish + ? false + : true; + ENUM_X_PRICE upPrice = isDirBullish + ? X_PRICE_LOW + : X_PRICE_HIGH; + ENUM_X_PRICE loPrice = isDirBullish + ? X_PRICE_HIGH + : X_PRICE_LOW; + + // + result = InitTwoBarZone( + startBar, + endBar, + mTT, + useFistForUpper, + 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_BULLISH_FVG; + + // + return result; + } + + /** + * Check is Bearish ... + * + * @return ( bool ) + */ + bool IsBearish() + { + // + bool result = false; + + // + result = IsValid() && + Type() == X_POI_BEARISH_FVG; + + // + 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 ... + 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 // + ) + { + // + bool result = false; + + // + result = endBar.IsValid() && + startBar.IsValid(); + if (!result) + { + return result; + } + + // + // Calculate Start and End Time ... + datetime from = startBar.time; + datetime to = endBar.time; + ulong fromM = ((ulong)startBar.time * 1000); + ulong toM = ((ulong)endBar.time * 1000); + + // + // Symbol and Period ... + string symbol = startBar.symbol; + ENUM_TIMEFRAMES period = startBar.period; + + // + // Prepare Zones Array ... + mZones.Clear(); + + // + // Retrieve Ticks between Times ... + SpecificClean(mTicks); + CopyTicksRange( + symbol, + mTicks, + COPY_TICKS_ALL, + fromM, + toM // + ); + + // + // Ticks Volumes ... + int ticksVolumeCount = CopyTickVolume( + symbol, + PERIOD_M1, + 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(); + + // + // 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(startBar.time); + To(endBar.time); + + // + result = IsValid(); + + // + // Try to Find Out PERIOD_1M times in each zone ... + datetime to1M = (datetime)((int)endBar.time + PeriodSeconds(period) - 60); + int to1MIndex = iBarShift( + symbol, + PERIOD_M1, + to1M // + ); + int from1MIndex = iBarShift( + symbol, + PERIOD_M1, + from // + ); + for (int i = from1MIndex; i > to1MIndex; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + symbol, + PERIOD_M1, + i // + ); + if (!isInited) + { + continue; + } + ulong iVolume = iTickVolume( + symbol, + PERIOD_M1, + 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); + + // + 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; + } + + // + 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: + // + + // +}; + +// +// +// Model Exists Founded POIs ... +struct XPOIState +{ + // + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + XCTicksZone *ticksZone; // Ticks Zone ... + + // + XCSwing *swingHighs[]; // Holds Founded Swing Highs ... + XCSwing *swingLows[]; // Holds Founded Swing Lows ... + XCMomentumBar *bullishMomentumBars[]; // Holds Founded Bullish Momentum Bars ... + XCMomentumBar *bearishMomentumBars[]; // Holds Founded Bearish Momentum Bars ... + XCRejectionBar *bullishRejectionBars[]; // Holds Founded Bullish Rejection Bars ... + XCRejectionBar *bearishRejectionBars[]; // 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 *bullishOrderBlocks[]; // Holds Founded Bullish Order Blocks ... + XCOrderBlock *bearishOrderBlocks[]; // Holds Founded Bearish Order Blocks ... + XCFVG *bullishFairValueGaps[]; // Holds Founded Bullish Fair Value Gaps ... + XCFVG *bearishFairValueGaps[]; // Holds Founded Bearish Fair Value Gaps ... + + // + // Constructor ... + void XPOIState() + { + Clean(); + } + + // + // Actions ... + + /** + * Cleanup all props ... + */ + void Clean() + { + // + symbol = NULL; + period = NULL; + time = NULL; + + // + ticksZone = NULL; + + // + Clean(swingHighs); + Clean(swingLows); + Clean(bullishMomentumBars); + Clean(bearishMomentumBars); + Clean(bullishRejectionBars); + Clean(bearishRejectionBars); + Clean(supportZones); + Clean(resistanceZones); + Clean(supplyZones); + Clean(demandZones); + Clean(bullishOrderBlocks); + Clean(bearishOrderBlocks); + Clean(bullishFairValueGaps); + Clean(bearishFairValueGaps); + } + + /** + * 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 = + // + IsValidSize(CountSwingHighs()) || + IsValidSize(CountSwingLows()) || + IsValidSize(CountBullishMomentumBars()) || + IsValidSize(CountBearishMomentumBars()) || + IsValidSize(CountBullishRejectionBars()) || + IsValidSize(CountBearishRejectionBars()) || + IsValidSize(CountSupportZones()) || + IsValidSize(CountResistanceZones()) || + IsValidSize(CountSupplyZones()) || + IsValidSize(CountDemandZones()) || + IsValidSize(CountBullishOrderBlocks()) || + IsValidSize(CountBearishOrderBlocks()) || + IsValidSize(CountBullishFairValueGaps()) || + IsValidSize(CountBearishFairValueGaps()) + // + ; + + // + return result; + } + + /** + * Fill Dest State by Current State's Data ... + * + * @param dest: XPOIState instance, reference to specified dest ... + * + */ + void Fill(XPOIState &dest) + { + // + if (!IsValid() || + !HasChild()) + { + return; + } + + // + dest.symbol = symbol; + dest.period = period; + dest.time = time; + + // + Copy( + swingHighs, + dest.swingHighs, + false // + ); + Copy( + swingLows, + dest.swingLows, + false // + ); + Copy( + bullishMomentumBars, + dest.bullishMomentumBars, + false // + ); + Copy( + bearishMomentumBars, + dest.bearishMomentumBars, + false // + ); + Copy( + bullishRejectionBars, + dest.bullishRejectionBars, + false // + ); + Copy( + bearishRejectionBars, + dest.bearishRejectionBars, + false // + ); + Copy( + supportZones, + dest.supportZones, + false // + ); + Copy( + resistanceZones, + dest.resistanceZones, + false // + ); + Copy( + supplyZones, + dest.supplyZones, + false // + ); + Copy( + demandZones, + dest.demandZones, + false // + ); + Copy( + bullishOrderBlocks, + dest.bullishOrderBlocks, + false // + ); + Copy( + bearishOrderBlocks, + dest.bearishOrderBlocks, + false // + ); + Copy( + bullishFairValueGaps, + dest.bullishFairValueGaps, + false // + ); + Copy( + bearishFairValueGaps, + dest.bearishFairValueGaps, + false // + ); + + // + } + + /** + * 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 = 0 // + ) + { + // + double result = 0; + + // + if (!IsValid() || + ticksZone == NULL) + { + return result; + } + + // + // Normalize Price for Actions ... + if (price <= 0) + { + // + MqlTick mTick; + bool isTickRetrieved = GetTick( + symbol, + mTick // + ); + if (isTickRetrieved) + { + price = mTick.bid; + } + } + + // + result = ticksZone + .CalculateLiquidityPercent( + forDirection, + price // + ); + + // + return result; + } + + // + // Counters ... + + // + int CountSwingHighs() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(swingHighs); + + // + return result; + } + + // + int CountSwingLows() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(swingLows); + + // + return result; + } + + // + int CountBullishMomentumBars() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(bullishMomentumBars); + + // + return result; + } + + // + int CountBearishMomentumBars() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(bearishMomentumBars); + + // + return result; + } + + // + int CountBullishRejectionBars() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(bullishRejectionBars); + + // + return result; + } + + // + int CountBearishRejectionBars() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(bearishRejectionBars); + + // + return result; + } + + // + int CountSupportZones() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(supportZones); + + // + return result; + } + + // + int CountResistanceZones() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(resistanceZones); + + // + return result; + } + + // + int CountSupplyZones() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(supplyZones); + + // + return result; + } + + // + int CountDemandZones() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(demandZones); + + // + return result; + } + + // + int CountBullishOrderBlocks() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(bullishOrderBlocks); + + // + return result; + } + + // + int CountBearishOrderBlocks() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(bearishOrderBlocks); + + // + return result; + } + + // + int CountBullishFairValueGaps() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(bullishFairValueGaps); + + // + return result; + } + + // + int CountBearishFairValueGaps() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(bearishFairValueGaps); + + // + return result; + } + + // +}; + +// +// Consolidation Zone ... +struct XConsolidationZone +{ + // + // Props ... + + // + string symbol; // Symbol ... + ENUM_TIMEFRAMES period; // Period ... + + // + double upper; // Upper ... + double lower; // Lower ... + + // + datetime initTime; + int loopback; // Loopback ... + + // + ENUM_X_DIRECTION breakDirection; // Break Direction ... + XOHCL breakerBar; // Breaker Bar ... + + // + // Constructor ... + XConsolidationZone() + { + Clean(); + } + + // + // Tools ... + + /** + * Initialize Zone ... + * + * @param _symbol: String ... + * @param _period: ENUM_TIMEFRAMES member ... + * @param _upper: Double ... + * @param _lower: Double ... + * @param _loopback: Integer ... + * + * @return ( bool ) + */ + bool Init( + string _symbol, + ENUM_TIMEFRAMES _period, + double _upper, + double _lower, + int _loopback // + ) + { + // + bool result = false; + + // + _symbol = NormalizeSymbol(_symbol); + _period = NormalizePeriod(_period); + + // + result = + // + _upper > 0 && + _lower > 0 && + _loopback > 0 + // + ; + if (!result) + { + return result; + } + + // + upper = _upper; + lower = _lower; + symbol = _symbol; + period = _period; + loopback = _loopback; + + // + result = IsValid(); + if (result) + { + initTime = TimeCurrent(); + } + + // + return result; + } + + /** + * Update Breaked State ... + */ + void Update() + { + // + if (!IsValid()) + { + return; + } + + // + if (IsBreaked()) + { + return; + } + + // + XOHCL cBar; + bool isInited = cBar.Init( + symbol, + period, + 0 // + ); + if (!isInited) + { + return; + } + + // + XOHCL pBar; + isInited = cBar.GetPreviousBar(pBar); + if (!isInited) + { + return; + } + + // + // Check Consolidation Hounts ... + bool isHountTop = cBar.high > upper && + cBar.low < upper && + cBar.GetUp() < upper; + bool isHountBottom = cBar.low < lower && + cBar.high > lower && + cBar.GetDown() > lower; + bool isHounted = isHountTop || + isHountBottom; + if (isHounted) + { + // + if (isHountTop) + { + upper = cBar.high; + } + + // + if (isHountBottom) + { + lower = cBar.low; + } + + // + return; + } + + // + // Check Consolidation Breaks ... + bool isBreakTop = (cBar.GetUp() > upper && + cBar.GetDown() < upper) || + (cBar.low > upper && + cBar.high > upper); + bool isBreakBottom = (cBar.GetDown() < lower && + cBar.GetUp() > lower) || + (cBar.high < lower && + cBar.low < lower); + bool isBreaked = isBreakTop || + isBreakBottom; + if (!isBreaked) + { + return; + } + + // + // Calculate Break Direction ... + breakerBar = cBar; + breakDirection = isBreakTop + ? X_DIRECTION_BULLISH + : isBreakBottom + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + } + + /** + * Cleanup ... + */ + void Clean() + { + // + upper = 0; + lower = 0; + loopback = 0; + symbol = NULL; + period = NULL; + initTime = NULL; + breakerBar.Clean(); + breakDirection = X_DIRECTION_NONE; + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsValid(symbol) && + IsValid(period) && + upper > 0 && + lower > 0 && + loopback > 0 + // + ; + + // + return result; + } + + /** + * Check Zone is Breaked or not ... + * + * @return ( bool ) + */ + bool IsBreaked() + { + // + bool result = false; + + // + result = breakerBar.IsValid() && + HasDirection(breakDirection); + + // + return result; + } + + /** + * Detect Supply Zone if Exists ... + * + * @return ( bool ) + */ + bool HasSupplyZone( + XCSupplyZone *&zone // + ) + { + // + bool result = false; + + // + result = IsBreaked() && + breakDirection == X_DIRECTION_BEARISH; + if (!result) + { + return result; + } + + // + // Implment Zone Finding ... + int index = breakerBar.Index(); + int hhIDX = iHighest( + symbol, + period, + MODE_HIGH, + loopback, + index // + ); + result = IsValidIndex(hhIDX); + if (!result) + { + return result; + } + + // + XOHCL hhBar; + result = hhBar.Init( + symbol, + period, + hhIDX // + ); + if (!result) + { + return result; + } + + // + zone = new XCSupplyZone(); + result = zone.Init( + hhBar, + loopback // + ); + + // + return result; + } + + /** + * Detect Demand Zone if Exists ... + * + * @return ( bool ) + */ + bool HasDemandZone( + XCDemandZone *&zone // + ) + { + // + bool result = false; + + // + result = IsBreaked() && + breakDirection == X_DIRECTION_BULLISH; + if (!result) + { + return result; + } + + // + // Implment Zone Finding ... + int index = breakerBar.Index(); + int llIDX = iLowest( + symbol, + period, + MODE_LOW, + loopback, + index // + ); + result = IsValidIndex(llIDX); + if (!result) + { + return result; + } + + // + XOHCL llBar; + result = llBar.Init( + symbol, + period, + llIDX // + ); + if (!result) + { + return result; + } + + // + zone = new XCDemandZone(); + result = zone.Init( + llBar, + loopback // + ); + + // + return result; + } + + /** + * Retrieve Start Time ... + * + * @return ( datetime ) + */ + datetime From() + { + // + datetime result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + int startIndex = iBarShift( + symbol, + period, + initTime // + ); + + // + result = iTime( + symbol, + period, + loopback + startIndex // + ); + + // + return result; + } + + /** + * Retrieve Unique Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + // + string result = + // + GetTypeName(this) + "_" + + symbol + "_" + + ToString(period) + "_" + + ToString(upper) + "_" + + ToString(lower) + // + ; + + // + return result; + } + + // +}; + +// +// Model Value Changed ... +struct XValueChange +{ + // + // Props ... + double before; // Before Change Value ... + double after; // After Change Value ... + datetime time; // Change Time ... + ENUM_X_DIRECTION dir; // Change Direction ... + + // + // Constructor ... + XValueChange() + { + Clean(); + } + + // + // Tools ... + + /** + * Initialize ... + * + * @param _before: Double, Value Before Change ... + * @param _after: Double, Value After Change ... + * @param _time: Datetime, Change Time ... + * @param _dir: ENUM_X_DIRECTION member, Specified Changed Direction ... + * + * @return ( bool ) + */ + bool Init( + double _before, // Before Change Value ... + double _after, // After Change Value ... + ENUM_X_DIRECTION _dir, // Change Direction ... + datetime _time = NULL // Change Time ... + ) + { + // + bool result = false; + + // + _time = NormalizeTime(_time); + + // + // Validate Inputs ... + result = + // + _after > 0 && + _before > 0 && + IsValid(_time) && + _after != _before && + HasDirection(_dir) + // + ; + if (!result) + { + return result; + } + + // + // Set Validated Values ... + dir = _dir; + time = _time; + after = _after; + before = _before; + + // + result = IsValid(); + + // + return result; + } + + /** + * Cleaning Up ... + */ + void Clean() + { + // + after = 0; + before = 0; + time = NULL; + dir = X_DIRECTION_NONE; + } + + /** + * Validate Model ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + // + after > 0 && + before > 0 && + IsValid(time) && + after != before && + HasDirection(dir) + // + ; + + // + return result; + } + + /** + * Fill Change Bar ... + * + * @param bar: XOHCL instance Reference, holds Change Bar ... + * @param _symbol: String, Specified Symbol ... + * @param _period: ENUM_TIMEFRAMES _period member, Specified Period ... + * + * @return ( bool ) + */ + bool FillBar( + XOHCL &bar, + string _symbol = NULL, + ENUM_TIMEFRAMES _period = NULL // + ) + { + // + bool result = false; + + // + bar.Clean(); + _symbol = NormalizeSymbol(_symbol); + _period = NormalizePeriod(_period); + + // + result = IsValid() && + IsValid(_symbol) && + IsValid(_period); + if (!result) + { + return result; + } + + // + result = bar.Init( + _symbol, + _period, + time // + ); + + // + return result; + } + + // +}; + +// +// Extensions ... + +/** + * 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; + } + + // + 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; +} + +/** + * Add Value Change instance to Exists Collection if it's not Exists ... + * + * @param item: XValueChange instance Reference ... + * @param items: XValueChange instance Array Reference ... + * + * @return ( int ) + */ +int AddIfNotExists( + XValueChange &item, + XValueChange &items[] // +) +{ + // + int result = 0; + + // + result = item.IsValid(); + if (!result) + { + return result; + } + + // + bool canAdd = false; + int count = ArraySize(items); + if (!IsValidSize(count)) + { + canAdd = true; + } + else + { + // + XValueChange last; + bool hasItem = GetLastItem( + last, + items // + ); + if (!hasItem) + { + canAdd = true; + } + else + { + // + // Compare Last Item with Current ... + canAdd = item.time > last.time; + } + } + + // + // Add Item if Allowed ... + if (canAdd) + { + // + AddRef( + item, + items // + ); + } + + // + result = ArraySize(items); + + // + return result; +} + +/** + * Combine a Collection of States into dest ... + * + * @param dest: XPOIState instance ... + * @param source: XPOIState Collection ... + */ +void CombineStates( + XPOIState &dest, + XPOIState &source[] // +) +{ + // + dest.Clean(); + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + XPOIState iState = source[i]; + + // + if (dest.ticksZone == NULL) + { + dest.ticksZone = iState.ticksZone; + } + + // + Copy( + iState.swingHighs, + dest.swingHighs, + false // + ); + + // + Copy( + iState.swingLows, + dest.swingLows, + false // + ); + + // + Copy( + iState.bullishMomentumBars, + dest.bullishMomentumBars, + false // + ); + + // + Copy( + iState.bearishMomentumBars, + dest.bearishMomentumBars, + false // + ); + + // + Copy( + iState.bullishRejectionBars, + dest.bullishRejectionBars, + false // + ); + + // + Copy( + iState.bearishRejectionBars, + dest.bearishRejectionBars, + false // + ); + + // + Copy( + iState.supportZones, + dest.supportZones, + false // + ); + + // + Copy( + iState.resistanceZones, + dest.resistanceZones, + false // + ); + + // + Copy( + iState.supplyZones, + dest.supplyZones, + false // + ); + + // + Copy( + iState.demandZones, + dest.demandZones, + false // + ); + + // + Copy( + iState.bullishOrderBlocks, + dest.bullishOrderBlocks, + false // + ); + + // + Copy( + iState.bearishOrderBlocks, + dest.bearishOrderBlocks, + false // + ); + + // + Copy( + iState.bullishFairValueGaps, + dest.bullishFairValueGaps, + false // + ); + + // + Copy( + iState.bearishFairValueGaps, + dest.bearishFairValueGaps, + false // + ); + + // + } +} + +// +typedef void (*TOnPOIEvent)(ENUM_XPOI_EVENTS event, + XCBasePOI *param // +); + +// \ No newline at end of file diff --git a/BKPS/14031003/Libraries/x-saherelm.x-trade.lib.mq5 b/BKPS/14031003/Libraries/x-saherelm.x-trade.lib.mq5 new file mode 100644 index 0000000..eedbdec --- /dev/null +++ b/BKPS/14031003/Libraries/x-saherelm.x-trade.lib.mq5 @@ -0,0 +1,5769 @@ +/////////////////////////////////////////////////////// +// +// 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_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 GetOppositPositionType(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 ... + +// +// Model an Open Position ... +struct XPosition +{ + // + // Props ... + + // + // Magic Number ... + ulong magic; + + // + // Ticket ID ... + ulong ticket; + + // + // Tradinng Symbol ... + string symbol; + + // + // Trading Period ... + ENUM_TIMEFRAMES period; + + // + // Position Type ... + ENUM_POSITION_TYPE type; + + // + // Take Profit ... + double tp; + + // + // Stop Loss ... + double sl; + + // + // Position Current Profit ... + double profit; + + // + // Position Open Price ... + double entry; + + // + // Current Symbol Price ... + double price; + + // + // Position Swap ... + double swap; + + // + // Position Commission ... + double commission; + + // + // Volume ... + double volume; + + // + // Position Open Time ... + datetime openAt; + + // + // Sifnal Provider ... + string provider; + + // + // Position Comment ... + string comment; + + // + // Constructor ... + XPosition() + { + Clean(); + } + + // + // Initializers ... + + bool ByIndex(int index) + { + // + bool result = false; + + // + static CPositionInfo mPositionInfo; + + // + result = mPositionInfo.SelectByIndex(index); + if (!result) + { + return result; + } + + // + ulong mTicket = mPositionInfo.Ticket(); + + // + result = ByTicket(mTicket); + + // + return result; + } + + bool ByTicket(ulong mTicket) + { + // + bool result = false; + + // + static CPositionInfo mPositionInfo; + + // + result = mPositionInfo.SelectByTicket(mTicket); + if (!result) + { + return result; + } + + // + swap = mPositionInfo.Swap(); + magic = mPositionInfo.Magic(); + openAt = mPositionInfo.Time(); + sl = mPositionInfo.StopLoss(); + ticket = mPositionInfo.Ticket(); + symbol = mPositionInfo.Symbol(); + tp = mPositionInfo.TakeProfit(); + profit = mPositionInfo.Profit(); + volume = mPositionInfo.Volume(); + comment = mPositionInfo.Comment(); + entry = mPositionInfo.PriceOpen(); + type = mPositionInfo.PositionType(); + price = mPositionInfo.PriceCurrent(); + commission = mPositionInfo.Commission(); + + // + period = ExtractPeriod(comment); + provider = ExtractProvider(comment); + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + magic = 0; + ticket = 0; + tp = 0; + sl = 0; + swap = 0; + entry = 0; + price = 0; + profit = 0; + volume = 0; + openAt = 0; + commission = 0; + + // + type = NULL; + period = NULL; + + // + symbol = NULL; + comment = NULL; + provider = NULL; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsValid(symbol) && + NotEmpty(ticket) + // + ; + + // + return result; + } + + // + // Retrieve Entry Price ... + double GetEntry() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetEntry( + symbol, + type + // + ); + + // + return result; + } + + // + // Retrieve Exit ... + double GetExit() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetExit( + symbol, + type + // + ); + + // + return result; + } + + // + // Get Spread by Point ... + double GetSpread() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = PriceToPoint(GetSpread(symbol)); + + // + return result; + } + + // + 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 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 ... + + // + // Constructor ... + XSignal() + { + Clean(); + } + + // + bool Prepare( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + ENUM_POSITION_TYPE mType, // Long (Buy) or Short (Sell) + ENUM_X_ORDER_MODES mMode, // Execution Mode + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + bool result = false; + + // + result = + // + IsValid(mMode) && + IsValid(mSymbol) && + IsValid(mPeriod) && + NotEmpty(mEntry) && + NotEmpty(mVolume) && + IsValid(mProvider) + // + ; + if (!result) + { + return result; + } + + // + if (mTP < 0) + { + mTP = 0; + } + + // + if (mSL < 0) + { + mSL = 0; + } + + // + type = mType; + mode = mMode; + symbol = mSymbol; + period = mPeriod; + provider = mProvider; + + // + // Normalization Values ... + sl = NormalizePrice(mSL, mSymbol); + tp = NormalizePrice(mTP, mSymbol); + mEntry = NormalizePrice(mEntry, mSymbol); + mVolume = NormalizeVolume(mVolume, mSymbol); + + // + entry = mEntry; + volume = mVolume; + + // + result = Normalize(); + + // + return result; + } + + // + bool PrepareLong( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + ENUM_X_ORDER_MODES mMode, // Execution Mode + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + return Prepare( + mSymbol, + mProvider, + mPeriod, + POSITION_TYPE_BUY, + mMode, + mEntry, + mVolume, + mSL, + mTP + // + ); + } + + // + bool PrepareShort( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + ENUM_X_ORDER_MODES mMode, // Execution Mode + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + return Prepare( + mSymbol, + mProvider, + mPeriod, + POSITION_TYPE_SELL, + mMode, + mEntry, + mVolume, + mSL, + mTP + // + ); + } + + // + // Market Mode ... + + // + bool PrepareMarketLong( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + return PrepareLong( + mSymbol, + mProvider, + mPeriod, + X_ORDER_MODE_MARKET, + mEntry, + mVolume, + mSL, + mTP + // + ); + } + + // + bool PrepareMarketShort( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + return PrepareShort( + mSymbol, + mProvider, + mPeriod, + X_ORDER_MODE_MARKET, + mEntry, + mVolume, + mSL, + mTP + // + ); + } + + // + // Stop Mode ... + + // + bool PrepareStopLong( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + return PrepareLong( + mSymbol, + mProvider, + mPeriod, + X_ORDER_MODE_STOP, + mEntry, + mVolume, + mSL, + mTP + // + ); + } + + // + bool PrepareStopShort( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + return PrepareShort( + mSymbol, + mProvider, + mPeriod, + X_ORDER_MODE_STOP, + mEntry, + mVolume, + mSL, + mTP + // + ); + } + + // + // Limit Mode ... + + // + bool PrepareLimitLong( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + return PrepareLong( + mSymbol, + mProvider, + mPeriod, + X_ORDER_MODE_LIMIT, + mEntry, + mVolume, + mSL, + mTP + // + ); + } + + // + bool PrepareLimitShort( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + return PrepareShort( + mSymbol, + mProvider, + mPeriod, + X_ORDER_MODE_LIMIT, + mEntry, + mVolume, + mSL, + mTP + // + ); + } + + // + // Generate Opposit Direction ... + bool GenerateOpposit( + XSignal &mSignal // Oppsoit Signal + ) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + ENUM_POSITION_TYPE mType = GetOpposit(this.type); + double mEntry = GetExit(this.symbol, mType); + + // + bool isLong = IsLong(mType); + + // + // Calculate Risk Reward Ratio ... + double risk = GetRisk(); + double reward = GetReward(); + + // + double mSL = isLong + ? mEntry - risk + : mEntry + risk; + + // + double mTP = isLong + ? mEntry + reward + : mEntry - reward; + + // + result = mSignal.Prepare( + this.symbol, + this.provider, + this.period, + mType, + this.mode, + mEntry, + this.volume, + mSL, + mTP // + ); + + // + return result; + } + + // + // Prepare Opposit Signal based On a Position ... + bool PrepareOpposit( + XPosition &source // Source Data + ) + { + // + bool result = false; + + // + ENUM_POSITION_TYPE mType = GetOpposit(source.type); + double mEntry = GetEntry(source.symbol, mType); + + // + bool isLong = IsLong(mType); + + // + double risk = source.GetRisk(); + double reward = source.GetReward(); + + // + double mSL = isLong + ? mEntry - risk + : mEntry + risk; + + // + double mTP = isLong + ? mEntry + reward + : mEntry - reward; + + // + return Prepare( + source.symbol, + source.provider, + source.period, + mType, + X_ORDER_MODE_MARKET, + mEntry, + source.volume, + mSL, + mTP // + ); + + // + result = IsValid(); + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + entry = 0; + volume = 0; + pushers = 0; + positionId = 0; + + // + time = NULL; + type = NULL; + mode = NULL; + symbol = NULL; + period = NULL; + comment = NULL; + provider = NULL; + conditions = NULL; + + // + Clean(supports); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsValid(period) && + IsValid(symbol) && + NotEmpty(volume) && + NotEmpty(entry) + // + ; + + // + if (!result) + { + return result; + } + + // + return result; + } + + // + // DO All Calculations and Normalizations ... + bool Normalize() + { + // + bool result = false; + + // + // Normalizations ... + symbol = NormalizeSymbol(symbol); + period = NormalizePeriod(period); + + // + time = NormalizeTime(time); + + // + sl = NormalizePrice(sl, symbol); + tp = NormalizePrice(tp, symbol); + entry = NormalizePrice(entry, symbol); + volume = NormalizeVolume(volume, symbol); + + // + result = IsValid(); + + // + return result; + } + + // + // Check Signal Executed or not ... + bool IsExecuted() + { + // + bool result = false; + + // + result = + // + IsValid() && + NotEmpty(positionId) + // + ; + + // + return result; + } + + // + // Generate Comment for Signal ... + string GenerateComment() + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + if (IsValid(provider)) + { + // + // Generate Provider Tag ... + result += GenerateProviderTag(provider); + } + + // + if (IsValid(period)) + { + // + // Generate Period Tag ... + result += GeneratePeriodTag(period); + } + + // + return result; + } + + // + int GetAge() + { + // + return GetAge( + this, + this.period // + ); + } + + // + // Retrieve Entry Price ... + double GetEntry() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetEntry( + symbol, + type + // + ); + + // + return result; + } + + // + // Retrieve Exit ... + double GetExit() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetExit( + symbol, + type + // + ); + + // + return result; + } + + // + // Get Spread by Point ... + double GetSpread() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = PriceToPoint(GetSpread(symbol)); + + // + return result; + } + + // + // Find Risk ... + double GetRisk() + { + // + double result = 0; + + // + if (!IsValid()) + { + return 0; + } + + // + result = MathAbs(entry - sl); + + // + return result; + } + + // + // Find Reward ... + double GetReward() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = MathAbs(tp - entry); + + // + return result; + } + + // + // Find Risk Reward Ratio ... + double GetRiskRewardRatio() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetReward() / GetRisk(); + + // + return result; + } + + // + 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; + } +}; + +// +// Model an Order ... +struct XOrder +{ + // + // Time of order placement ... + datetime setupAt; + + // + // Time of order expiration ... + datetime expiredAt; + + // + // Time of order execution or cancellation ... + datetime executedAt; + + // + // Order type ... + ENUM_ORDER_TYPE type; + + // + // Order state ... + ENUM_ORDER_STATE state; + + // + // Type of execution by remainder ... + ENUM_ORDER_TYPE_FILLING filling; + + // + // Order lifetime ... + ENUM_ORDER_TYPE_TIME lifetime; + + // + // Order ticket ... + ulong ticket; + + // + // Magic Number ... + long magic; + + // + // Position id, that is placed on order, + // when it is executed. Each executed order invokes a + // deal, that opens new or changes existing + // position. Id of that position is placed on + // executed order in this moment. + long positionId; + + // + // Initial volume on order placement ... + double initialVolume; + + // + // Unfilled volume ... + double currentVolume; + + // + // Price, specified in the order ... + double openPrice; + + // + // Current price by order symbol ... + double currentPrice; + + // + // Price of placing Limit order when StopLimit order is triggered ... + double stopLimitPrice; + + // + // Take Profit level ... + double tp; + + // + // Stop Loss level ... + double sl; + + // + // Trading Symbol ... + string symbol; + + // + // Signal Provider ... + string provider; + + // + // Order Comment ... + string comment; + + // + ENUM_TIMEFRAMES period; + + // + // Constructor ... + XOrder() + { + Clean(); + } + + // + // Initializers ... + bool ByIndex( + int index // Fill By Index ... + ) + { + // + bool result = false; + + // + int ordersCount = OrdersTotal(); + if (ordersCount <= 0) + { + return result; + } + + // + static COrderInfo mOrderInfo; + + // + result = mOrderInfo.SelectByIndex(index); + if (!result) + { + return result; + } + + // + // Reading Order Info ... + magic = mOrderInfo.Magic(); + sl = mOrderInfo.StopLoss(); + tp = mOrderInfo.TakeProfit(); + ticket = mOrderInfo.Ticket(); + openPrice = mOrderInfo.PriceOpen(); + positionId = mOrderInfo.PositionId(); + currentPrice = mOrderInfo.PriceCurrent(); + initialVolume = mOrderInfo.VolumeInitial(); + currentVolume = mOrderInfo.VolumeCurrent(); + stopLimitPrice = mOrderInfo.PriceStopLimit(); + + // + symbol = mOrderInfo.Symbol(); + comment = mOrderInfo.Comment(); + + // + state = mOrderInfo.State(); + type = mOrderInfo.OrderType(); + lifetime = mOrderInfo.TypeTime(); + filling = mOrderInfo.TypeFilling(); + + // + setupAt = mOrderInfo.TimeSetup(); + executedAt = mOrderInfo.TimeDone(); + expiredAt = mOrderInfo.TimeExpiration(); + + // + period = ExtractPeriod(comment); + provider = ExtractProvider(comment); + + // + result = IsValid(); + + // + return result; + } + + // + // Retrieve Specific History Order ... + bool HistoryByIndex( + int index // Fill By Index ... + ) + { + // + bool result = false; + + // + int ordersCount = HistoryOrdersTotal(); + if (ordersCount <= 0) + { + return result; + } + + // + static CHistoryOrderInfo mOrderInfo; + + // + result = mOrderInfo.SelectByIndex(index); + if (!result) + { + return result; + } + + // + // Reading Order Info ... + magic = mOrderInfo.Magic(); + sl = mOrderInfo.StopLoss(); + tp = mOrderInfo.TakeProfit(); + ticket = mOrderInfo.Ticket(); + openPrice = mOrderInfo.PriceOpen(); + positionId = mOrderInfo.PositionId(); + currentPrice = mOrderInfo.PriceCurrent(); + initialVolume = mOrderInfo.VolumeInitial(); + currentVolume = mOrderInfo.VolumeCurrent(); + stopLimitPrice = mOrderInfo.PriceStopLimit(); + + // + symbol = mOrderInfo.Symbol(); + comment = mOrderInfo.Comment(); + + // + state = mOrderInfo.State(); + type = mOrderInfo.OrderType(); + lifetime = mOrderInfo.TypeTime(); + filling = mOrderInfo.TypeFilling(); + + // + setupAt = mOrderInfo.TimeSetup(); + executedAt = mOrderInfo.TimeDone(); + expiredAt = mOrderInfo.TimeExpiration(); + + // + period = ExtractPeriod(comment); + provider = ExtractProvider(comment); + + // + result = IsValid(); + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + tp = 0; + sl = 0; + magic = 0; + ticket = 0; + positionId = 0; + openPrice = 0; + currentPrice = 0; + initialVolume = 0; + currentVolume = 0; + stopLimitPrice = 0; + + // + setupAt = NULL; + expiredAt = NULL; + executedAt = NULL; + + // + symbol = NULL; + comment = NULL; + provider = NULL; + + // + type = NULL; + state = NULL; + period = NULL; + filling = NULL; + lifetime = NULL; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsValid(symbol) && + NotEmpty(ticket) && + NotEmpty(positionId) + // + ; + + // + return result; + } + + // + // Calculate Age ... + int GetAge( + ENUM_TIMEFRAMES mPeriod // Calculate Age based on this period + ) + { + return GetAge(this, mPeriod); + } + + // + // Check this instance is Same os Given instance or not ... + bool IsSameAs( + const XOrder &value // instance for Compare + ) + { + // + bool result = false; + + // + result = + // + type == value.type && + state == value.state && + magic == value.magic && + ticket == value.ticket && + symbol == value.symbol && + provider == value.provider && + positionId == value.positionId + // + ; + + // + return result; + } + + // + // Find index in a Collection ... + int FindIndex( + const XOrder &values[] // Collection to Find + ) + { + // + return FindIndex( + this, + values + // + ); + } + + // + // Check Items Passed Specific Filters or not ... + bool IsFiltersPassed( + string mSymbol = NULL, // Trading Symbol + string mProvider = NULL, // Signal Provider + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Timeframe + ENUM_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; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsValid(symbol) && + NotEmpty(ticket) && + NotEmpty(positionId) + // + ; + + // + return result; + } + + // + // Calculate Age ... + int GetAge( + ENUM_TIMEFRAMES mPeriod // Calculate Age based on this period + ) + { + return GetAge(this, mPeriod); + } + + // + // Check this instance is Same os Given instance or not ... + bool IsSameAs( + const XDeal &value // instance for Compare + ) + { + // + bool result = false; + + // + result = + // + type == value.type && + magic == value.magic && + entry == value.entry && + reason == value.reason && + ticket == value.ticket && + volume == value.volume && + symbol == value.symbol && + provider == value.provider && + positionId == value.positionId + // + ; + + // + return result; + } + + // + // Find index in a Collection ... + int FindIndex( + const XDeal &values[] // Collection to Find + ) + { + // + return FindIndex( + this, + values + // + ); + } + + // + // Check Items Passed Specific Filters or not ... + bool IsFiltersPassed( + string mSymbol = NULL, // Trading Symbol + string mProvider = NULL, // Signal Provider + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Timeframe + ENUM_DEAL_TYPE mType = NULL, // Deal Type + ENUM_DEAL_ENTRY mEntry = NULL, // Deal Entry + ENUM_DEAL_REASON mReason = NULL, // Deal Reason + ulong mMagic = NULL, // Magic Number + bool mFilterByMagic = true // Get Only Self Open Positions + ) + { + // + bool result = false; + + // + result = + // + // Magic Filter ... + IsMagicFilterPassed( + mMagic, + mFilterByMagic, + this + // + ) + // + && + // + // Symbol Filter ... + IsSymbolFilterPassed( + mSymbol, + this + // + ) + // + && + // + // Provider Filter ... + IsProviderFilterPassed( + mProvider, + this + // + ) + // + && + // + // Period Filter ... + IsPeriodFilterPassed( + mPeriod, + this + // + ) + // + && + // + // Type Filter ... + IsTypeFilterPassed( + mType, + this + // + ) + // + && + // + // Entry Filter ... + IsEntryFilterPassed( + mEntry, + this + // + ) + // + && + // + // Reason Filter ... + IsReasonFilterPassed( + mReason, + this + // + ) + // + ; + + // + return result; + } +}; + +// +// Model OnTrade Event Handler Result on XCTrade Class ... +struct XOnTradeHandlerState +{ + // + bool hasNewDeal; + int newDeals; + + // + bool hasNewOrder; + int newOrders; + + // + bool hasNewPosition; + int newPositions; + + // + bool hasNewHistoryOrder; + int newHistoryOrders; + + // + // Constructor ... + XOnTradeHandlerState() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + hasNewDeal = false; + hasNewOrder = false; + hasNewPosition = false; + hasNewHistoryOrder = false; + + // + newDeals = 0; + newOrders = 0; + newPositions = 0; + newHistoryOrders = 0; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + ( + // + hasNewDeal + ? newDeals > 0 + : true + // + ) + // + && + // + ( + // + hasNewOrder + ? newOrders > 0 + : true + // + ) + // + && + // + ( + // + hasNewPosition + ? newPositions > 0 + : true + // + ) + // + && + // + ( + // + hasNewHistoryOrder + ? newHistoryOrders > 0 + : true + // + ) + // + ; + + // + return result; + } +}; + +// +// Model Guard Info ... +struct XGuard +{ + // + string symbol; // Trading Symbol ... + string provider; // Signal Provider ... + ENUM_TIMEFRAMES period; // Trading Timeframe ... + ENUM_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; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + action != X_GUARD_ACTION_NOTHING + // + ; + + // + return result; + } +}; + +// +// Model a Position with all of it's Supports ... +struct XPositionPack +{ + // + ulong ticket; // Main Position's Ticket + + // + XPosition position; // Main Position (if Exists) + + // + int supportOrdersCount; // Supported Orders (Untriggered) + int supportPositionsCount; // Supported Positions + + // + XOrder supportOrders[]; // Supported Orders (Untriggered) + XPosition supportPositions[]; // Supported Positions + + // + // Constructor ... + XPositionPack() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + ticket = 0; + + // + position.Clean(); + + // + supportOrdersCount = 0; + supportPositionsCount = 0; + + // + Clean(supportOrders); + Clean(supportPositions); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + NotEmpty(ticket) && + ( + // + supportOrdersCount > 0 + ? ArraySize(supportOrders) == supportOrdersCount + : true + // + ) + // + && + // + ( + // + supportPositionsCount > 0 + ? ArraySize(supportPositions) == supportPositionsCount + : true + // + ) + // + ; + + // + return result; + } +}; + +// +// Check Position SL Trails Structure ... +struct XTrail +{ + // + ulong ticket; // Position Ticket ... + ENUM_POSITION_TYPE type; // Type ... + datetime time; // Trail Time ... + double before; // SL Value Before Trailing ... + double after; // SL Value After Trailing ... + int level; // Number of Trails SL ... + double profit; // Profit in SL Time ... + + // + // Constructor ... + XTrail() + { + Clean(); + } + + // + // Tools ... + + // + bool Init( + ulong mTicket, // Ticket + ENUM_POSITION_TYPE mType, // Type + double mProfit, // Profit + double mBefore, // Before + double mAfter // After + ) + { + // + Clean(); + + // + type = mType; + after = mAfter; + ticket = mTicket; + before = mBefore; + profit = mProfit; + + // + level++; + + // + time = TimeCurrent(); + + // + return IsValid(); + } + + // + bool Update( + double mSl, // new SL ... + double mProfit // Profit + ) + { + // + bool result = false; + + // + time = TimeCurrent(); + + // + double cAfter = after; + after = mSl; + before = cAfter; + profit = mProfit; + + // + level++; + + // + result = IsValid(); + + // + return result; + } + + // + string GenerateTag() + { + // + string result = NULL; + + // + string ticketLevelStr = ToString(ticket) + "," + ToString(level); + + // + result = Surround( + XSLTrailToken, + ticketLevelStr // + ); + + // + return result; + } + + // + // Cleanup ... + void Clean() + { + // + ticket = 0; + time = 0; + before = 0; + after = 0; + level = 0; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + ticket > 0 && + time > 0 && + level > 0 + // + ; + + // + return result; + } +}; + +// +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); + } + + // + // 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; + } +}; + +// +// 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(); + } + + // + // 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; +} + +// + +// +// Find Specific Item Index inside a Collection ... +template +int FindIndex( + T &item, // Item to Find + const T &items[] // Items for Search +) +{ + // + int result = -1; + + // + // Check Item Validation ... + if (!item.IsValid()) + { + return result; + } + + // + int itemsCount = ArraySize(items); + if (itemsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < itemsCount; i++) + { + // + T iItem = items[i]; + + // + // Validate Item ... + if (!iItem.IsValid()) + { + continue; + } + + // + bool isSame = item.IsSameAs(iItem); + if (isSame && result <= -1) + { + // + result = i; + break; + } + } + + // + return result; +} + +// +// +// Calculate Positions Profit Summary ... +double SpecifiedCalculatePositionsProfit( + XPosition &positions[] // Source +) +{ + // + double result = 0; + + // + int positionsCount = ArraySize(positions); + if (positionsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + result += iPosition.profit; + } + + // + return result; +} + +// +// Calculate Required Profit for Hedging ... +double SpecifiedCalculateRequiredProfitForHedge( + XPosition &positions[], // Source + double mMinProfitPerTrade, + double mMinProfitPerVolumeFactor // +) +{ + // + double result = 0; + + // + int positionsCount = ArraySize(positions); + if (positionsCount <= 0) + { + return result; + } + + // + bool isHedgingEnable = mMinProfitPerTrade > 0 && mMinProfitPerVolumeFactor > 0; + if (!isHedgingEnable) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + if (mMinProfitPerTrade > 0 && mMinProfitPerVolumeFactor > 0) + { + // + result += + ((iPosition.volume / mMinProfitPerVolumeFactor) * + mMinProfitPerTrade) + + (-1 * iPosition.swap); + } + } + + // + return result; +} + +// +bool SpecifiedIsPositionsReadyForHedge( + XPosition &positions[], // Source + double mMinProfitPerTrade, + double mMinProfitPerVolumeFactor // +) +{ + // + double profit = SpecifiedCalculatePositionsProfit(positions); + double requiredProfit = SpecifiedCalculateRequiredProfitForHedge( + positions, + mMinProfitPerTrade, + mMinProfitPerVolumeFactor // + ); + + // + bool result = requiredProfit > 0 + ? profit >= requiredProfit + : profit > requiredProfit; + + // + return result; +} + +// +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_NO_EQUITY: + result = "No Equity for Trade"; + break; + + // + case X_SIGNAL_EXECUTION_FAILED_PRICE_ERROR: + result = "Price Error"; + break; + + // + case X_SIGNAL_EXECUTION_FAILED_MAX_REACHED: + result = "Max Allowed Positions Reached"; + break; + + // + case X_SIGNAL_EXECUTION_FAILED_INVALID_PARAMS: + result = "Invalid Params"; + break; + } + + // + return result; +} + +// +// Converts Position Type to Order Type ... +ENUM_ORDER_TYPE ToOrderType(ENUM_POSITION_TYPE value) +{ + // + bool isLong = IsLong(value); + + // + ENUM_ORDER_TYPE result = + isLong + ? ORDER_TYPE_BUY + : ORDER_TYPE_SELL; + + // + return result; +} +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/14031003/X121SMCEA/Classes/x-121.smc.base.strategy.class.mq5 b/BKPS/14031003/X121SMCEA/Classes/x-121.smc.base.strategy.class.mq5 new file mode 100644 index 0000000..1557a52 --- /dev/null +++ b/BKPS/14031003/X121SMCEA/Classes/x-121.smc.base.strategy.class.mq5 @@ -0,0 +1,1644 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XSCX121SMCBaseStrategy +// 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-bar.analyser.class.mq5" +#include "../../Classes/x-saherelm.x-poi.class.mq5" +#include "../../Classes/x-saherelm.x-trade.class.mq5" +#include "../Classes/x-121.smc.cobjects.class.mq5" +#include "../Libraries/x-121.smc.lib.mq5" + +// +// Helper(s) ... + +// +// XStrategy Class Implementation(s) ... +class XCX121SMCBaseStrategy : public XCBaseAlert +{ + // + // Public ... + public: + // + + // + // Constructor(s) ... + void XCX121SMCBaseStrategy( + // + // Base ... + string _symbol, // Trading Symbol + ENUM_TIMEFRAMES _period // Trading TimeFrame + ) + { + // + mSymbol = _symbol; + mPeriod = _period; + + // + Init(); + } + + // + // Deconstructor ... + void ~XCX121SMCBaseStrategy() + { + DeInit(); + } + + // + // Getter / Setter (s) ... + + /** + * Retrieve Symbol ... + * + * @return ( string ) + */ + string GetSymbol() + { + return mSymbol; + } + + /** + * Retrieve TimeFrame ... + * + * @return ( ENUM_TIMEFRAMES ) + */ + ENUM_TIMEFRAMES GetPeriod() + { + return mPeriod; + } + + /** + * Check Strategy is Disabled or not ... + * + * @return ( bool ) + */ + bool IsDisabled() + { + return mForceDisabled; + } + + /** + * Get Chart Id ... + * + * @return ( long ) + */ + long ChartIdentification() + { + return mChartID; + } + + /** + * Set Chart Id ... + * + * @param value: Long ... + */ + void ChartIdentification(long value) + { + // + if (value < 0) + { + value = 0; + } + + // + mChartID = value; + if (mPOIDrawer != NULL) + { + mPOIDrawer.ChartIdentification(value); + } + } + + /** + * Get Sub Window Id ... + * + * @return ( int ) + */ + int SubWindowIdentification() + { + return mSubWindow; + } + + /** + * Set Sub Window Id ... + * + * @param value: Integer ... + */ + void SubWindowIdentification(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mSubWindow = value; + if (mPOIDrawer != NULL) + { + mPOIDrawer.SubWindowIdentification(value); + } + } + + /** + * Get Signal Volume ... + * + * @return ( double ) + */ + double Volume() + { + return mVolume; + } + + /** + * Set Signal Volume ... + * + * @param value: Double ... + */ + void Volume(double value) + { + // + if (value < 0.01) + { + value = 0.01; + } + + // + mVolume = value; + } + + /** + * Get Risk/Reward Ratio ... + * + * @return ( double ) + */ + double R2R() + { + return mR2R; + } + + /** + * Set Risk/Reward Ratio ... + * + * @param value: Double ... + */ + void R2R(double value) + { + // + if (value < 0) + { + value = 1.5; + } + + // + mR2R = value; + } + + /** + * Get Max Allowed Spread ... + * + * @return ( double ) + */ + double MaxAllowedSpread() + { + return mMaxAllowedSpread; + } + + /** + * Set Max Allowed Spread ... + * + * @param value: Double ... + */ + void MaxAllowedSpread(double value) + { + mMaxAllowedSpread = value; + } + + /** + * Get Min Required Ticks Verification for Spread Pass ... + * + * @return ( int ) + */ + int MinRequiredTicksForSpreadPass() + { + return mMinRequiredTicksForSpreadPass; + } + + /** + * Set Min Required Ticks Verification for Spread Pass ... + * + * @param value: Integer ... + */ + void MinRequiredTicksForSpreadPass(int value) + { + // + if (value < 100) + { + value = 100; + } + + // + mMinRequiredTicksForSpreadPass = value; + } + + /** + * Get Max Allowed Save Ticks ... + * + * @return ( int ) + */ + int MaxAllowedSaveTicks() + { + return mMaxAllowedSaveTicks; + } + + /** + * Set Max Allowed Save Ticks ... + * + * @param value: Integer ... + */ + void MaxAllowedSaveTicks(int value) + { + // + if (value < 150) + { + value = 150; + } + + // + mMaxAllowedSaveTicks = value; + } + + /** + * Get Long Signalling State ... + * + * @return ( bool ) + */ + bool AllowLong() + { + return mAllowLong; + } + + /** + * Set Long Signalling State ... + * + * @param value: Boolean ... + */ + void AllowLong(bool value) + { + mAllowLong = value; + } + + /** + * Get Short Signalling State ... + * + * @return ( bool ) + */ + bool AllowShort() + { + return mAllowShort; + } + + /** + * Set Short Signalling State ... + * + * @param value: Argument 1 + */ + void AllowShort(bool value) + { + mAllowShort = value; + } + + // + // Actions ... + + /** + * Disable Strategy ... + */ + void Disable() + { + mForceDisabled = true; + } + + /** + * Enable Strategy ... + */ + void Enable() + { + mForceDisabled = false; + } + + /** + * Register Signal Event Handler ... + * + * @param handler: an Instance of TOnXSignal ... + */ + void AddXSignalEventHandler(TOnX121SMCSignal handler) + { + // + Add( + handler, + mSignalEventHandlers // + ); + } + + // + // Virtual Actions ... + + /** + * Destroy All Class Implementations ... + */ + virtual void Destroy() + { + } + + /** + * Handle Tick Processing ... + */ + virtual void HandleTick() + { + // + // Check State ... + if (IsDisabled()) + { + return; + } + + // + // Check Signalling State ... + if (!AllowLong() && !AllowShort()) + { + return; + } + + // + // Check Bar Tracker State ... + if (!mBarTracker.CanProcessBar()) + { + return; + } + + // + // Retrieve Current Tick and Check it's Time + // by Last Issued Tick ... + MqlTick cTick; + bool hasTick = GetTick( + mSymbol, + cTick // + ); + bool isSameAsLast = cTick.time == mLastTick.time; + if (isSameAsLast) + { + return; + } + + // + // Update Last Issued Tick ... + mLastTick = cTick; + SaveTickData(); + CleanupTicks(); + + // + // Update POIs ... + + // + // Trigger ... + ENUM_XPOI_EVENTS mTriggerEvents[]; + mTriggerDetector.Update(mTriggerEvents); + mTriggerDetector.GetState(mTriggerState); + + // + // Decision ... + ENUM_XPOI_EVENTS mDecisionEvents[]; + mDecisionDetector.Update(mDecisionEvents); + mDecisionDetector.GetState(mDecisionState); + + // + // Analyse ... + ENUM_XPOI_EVENTS mAnalyseEvents[]; + mAnalyseDetector.Update(mAnalyseEvents); + mAnalyseDetector.GetState(mAnalyseState); + + // + // Verification ... + ENUM_XPOI_EVENTS mVerificationEvents[]; + mVerificationDetector.Update(mVerificationEvents); + mVerificationDetector.GetState(mVerificationState); + + // + // Consolidation ... + ENUM_XPOI_EVENTS mConsolidationEvents[]; + mConsolidationDetector.Update(mConsolidationEvents); + mConsolidationDetector.GetState(mConsolidationState); + + // + // Vision ... + ENUM_XPOI_EVENTS mVisionEvents[]; + mVisionDetector.Update(mVisionEvents); + mVisionDetector.GetState(mVisionState); + + // + // Check Current Processing Tick has Signal or not ... + XSignal signal; + X121SMCStrategyConditions conditions; + bool hasSignal = HasSignal( + signal, + conditions // + ); + if (!hasSignal) + { + return; + } + + // + // Waits Until Next Candle if Current Tick has Signal ... + mBarTracker.Waits(); + + // + // Notify Signal Event Handlers ... + NotifyOnSignalEventHandlers( + signal, + conditions // + ); + } + + /** + * Check For Signal ... + * + * @param signal: XSignal instance ... + * @param conditions: X121SMCStrategyConditions instance ... + * + * @return ( virtual bool ) + */ + virtual bool HasSignal( + XSignal &signal, + X121SMCStrategyConditions &conditions // + ) + { + // + bool result = false; + + // + signal.Clean(); + conditions.Clean(); + + // + return result; + } + + /** + * Detect SL Candidates based on Strategy and Conditions ... + * + * @param result: Double array reference ... + * @param entry: Double, Position Entry Price ... + * @param conditions: X121SMCStrategyConditions instance, Provides Configurations ... + * @param type: ENUM_X_POSITION_TYPES member, Specified Position Type ... + */ + virtual void DetectSLCandidates( + double &result[], + double entry, + X121SMCStrategyConditions &conditions, + ENUM_X_POSITION_TYPES type // + ) + { + } + + /** + * Customize Strategy Identifier ... + * + * @return ( virtual string ) + */ + virtual string GetTag() + { + return X121SMCStrategyToken; + } + + // + // Protected ... + protected: + // + + // + // Props ... + + // + // Point Of Interests ... + XCPOIDetector *mVisionDetector; + XCPOIDetector *mConsolidationDetector; + XCPOIDetector *mVerificationDetector; + XCPOIDetector *mAnalyseDetector; + XCPOIDetector *mDecisionDetector; + XCPOIDetector *mTriggerDetector; + + // + XPOIState mVisionState; + XPOIState mConsolidationState; + XPOIState mVerificationState; + XPOIState mAnalyseState; + XPOIState mDecisionState; + XPOIState mTriggerState; + + // + XCPOIDrawer *mPOIDrawer; // POI Drawer Class ... + CArrayObj mDrawnObjects; + + // + XTick mTicks[]; // Hold Ticks Data ... + MqlTick mLastTick; // Last Issued Tick ... + + // + XBarTracker mBarTracker; // Strategy Time Tracker ... + XCBarAnalyser mBarAnalyser; // Bar Analyser Instance + // X121SMCStrategyConditions mConditions; // Market Conditions ... + + // + // Actions ... + + /** + * Check Spread Passed for Positions... + * + * @return ( bool ) + */ + bool IsSpreadPass() + { + // + bool result = false; + + // + double pointValue = GetPoints(mSymbol); + double maxAllowedSpread = MaxAllowedSpread(); + int minRequiredTicksVerification = MinRequiredTicksForSpreadPass(); + if (maxAllowedSpread > 0) + { + maxAllowedSpread *= pointValue; + } + else + { + maxAllowedSpread = 0; + } + + // + result = maxAllowedSpread <= 0 + ? true + : minRequiredTicksVerification > 0; + if (!result) + { + return result; + } + + // + int ticksCount = ArraySize(mTicks); + result = ticksCount >= minRequiredTicksVerification; + if (!result) + { + return result; + } + + // + if (maxAllowedSpread > 0) + { + // + int end = -1; + int start = -1; + result = CalculateTicksParams( + start, + end, + minRequiredTicksVerification // + ); + if (!result) { + return result; + } + + // + for (int i = start; i < end; i++) + { + // + XTick iTick = mTicks[i]; + + // + result = iTick.spread <= maxAllowedSpread; + if (!result) + { + break; + } + } + } + + // + return result; + } + + /** + * Prepare and Normalize Signal for Execution in Strategy ... + * + * @param signal: XSignal instance ... + * + * @return ( bool ) + */ + bool PrepareSignal(XSignal &signal) + { + // + bool result = false; + + // + // Check Strategy Is Enables ... + result = !IsDisabled(); + if (!result) + { + return result; + } + + // + // Validate Signal ... + result = signal.IsValid(); + if (!result) + { + return result; + } + + // + bool isLong = IsLong(signal.type); + + // + // TODO: Implement Signal Preparation Mechanism here ... + + // + return result; + } + + // + + /** + * Notified Signal Event Handler(s) ... + * + * @param signal: XSignal instance ... + * @param conditions: XStrategyConditions instance ... + */ + void NotifyOnSignalEventHandlers( + XSignal &signal, + X121SMCStrategyConditions &conditions // + ) + { + // + if (!signal.IsValid() || !conditions.IsValid()) + { + return; + } + + // + int count = ArraySize(mSignalEventHandlers); + if (!IsValidSize(count)) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + mSignalEventHandlers[i]( + signal, + conditions // + ); + } + } + + // + // Draw Functions ... + + /** + * Clear all Drawn Objects ... + */ + void ClearDraws() + { + mDrawnObjects.Clear(); + } + + /** + * Remove Specified Drawn Object ... + * + * @param name: Object name ... + */ + void RemoveObject(string name) + { + // + if (!IsValid(name)) + { + return; + } + + // + int count = mDrawnObjects.Total(); + if (!IsValidSize(count)) + { + return; + } + + // + int idx = -1; + for (int i = 0; i < count; i++) + { + // + string iName = ((CChartObject *)mDrawnObjects.At(i)).Name(); + string iObjName = NULL; + if (!IsValid(iName)) + { + iObjName = ((XCBaseObject *)mDrawnObjects.At(i)).ObjName(); + } + + // + if ((IsValid(iName) && + iName == name) || + (IsValid(iObjName) && + iObjName == name)) + { + // + idx = i; + break; + } + } + + // + if (IsValidIndex(idx)) + { + mDrawnObjects.Delete(idx); + } + } + + /** + * Draw Specified Signal ... + * + * @param signal: XSignal instance ... + */ + void DrawSignal(XSignal &signal) + { + // + if (!signal.IsValid()) + { + return; + } + + // + // DrawConditions(conditions); + + // + string name = signal.GetTag(); + RemoveObject(name); + + // + XCSignalObject *iObj; + iObj = new XCSignalObject(); + + // + bool isCreated = iObj.Create( + ChartIdentification(), + name, + SubWindowIdentification(), + signal // + ); + if (!isCreated) + { + return; + } + + // + iObj.TPWidth(1); + iObj.TPColor(clrGreen); + iObj.TPWidth(STYLE_DOT); + + // + iObj.SLWidth(1); + iObj.SLColor(clrRed); + iObj.SLWidth(STYLE_DOT); + + // + iObj.EntryWidth(1); + iObj.EntryColor(clrYellow); + iObj.EntryWidth(STYLE_DOT); + + // + mDrawnObjects.Add(iObj); + } + + /** + * Draw Specified State on Chart ... + * + * @param state: XPOIState instance ... + */ + void DrawState( + XPOIState &state, + bool forceUpdateTo = false, + bool drawSwingHighs = true, + bool drawSwingLows = true, + bool drawSupportZones = true, + bool drawResistanceZones = true, + bool drawSupplyZones = true, + bool drawDemandZones = true, + bool drawBullishOrderBlocks = true, + bool drawBearishOrderBlocks = true, + bool drawBullishFairValueGaps = true, + bool drawBearishFairValueGaps = true, + bool drawBullishRejectionBars = true, + bool drawBearishRejectionBars = true, + bool drawBullishMomentumBars = true, + bool drawBearishMomentumBars = true, + bool drawTicksZone = true // + ) + { + // + int count = 0; + datetime cTime = TimeCurrent(); + + // + // Swings ... + + // + // Swing Highs ... + if (drawSwingHighs) + { + // + count = ArraySize(state.swingHighs); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSwing item = state.swingHighs[i]; + + // + XCSwingHighObject *iObj; + bool isCreated = mPOIDrawer.CreateSwingHigh( + item, + iObj // + ); + if (isCreated) + { + AddObjectIfNotExists(iObj); + } + } + } + } + + // + // Swing Lows ... + if (drawSwingLows) + { + // + count = ArraySize(state.swingLows); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSwing item = state.swingLows[i]; + + // + XCSwingLowObject *iObj; + bool isCreated = mPOIDrawer.CreateSwingLow( + item, + iObj // + ); + if (isCreated) + { + AddObjectIfNotExists(iObj); + } + } + } + } + + // + // Support and Resistance Zones ... + + // + // Support Zones ... + if (drawSupportZones) + { + // + count = ArraySize(state.supportZones); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSupportZone item = state.supportZones[i]; + if (forceUpdateTo) + { + item.To(cTime); + } + + // + XCSupportZoneObject *iObj; + bool isCreated = mPOIDrawer.CreateSupportZone( + item, + iObj // + ); + if (isCreated) + { + AddObjectIfNotExists(iObj); + } + } + } + } + + // + // Resistance Zones ... + if (drawResistanceZones) + { + // + count = ArraySize(state.resistanceZones); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCResistanceZone item = state.resistanceZones[i]; + if (forceUpdateTo) + { + item.To(cTime); + } + + // + XCResistanceZoneObject *iObj; + bool isCreated = mPOIDrawer.CreateResistanceZone( + item, + iObj // + ); + if (isCreated) + { + AddObjectIfNotExists(iObj); + } + } + } + } + + // + // Supply and Demand Zones ... + + // + // Supply Zones ... + if (drawSupplyZones) + { + // + count = ArraySize(state.supplyZones); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSupplyZone item = state.supplyZones[i]; + if (forceUpdateTo) + { + item.To(cTime); + } + + // + XCSupplyZoneObject *iObj; + bool isCreated = mPOIDrawer.CreateSupplyZone( + item, + iObj // + ); + if (isCreated) + { + AddObjectIfNotExists(iObj); + } + } + } + } + + // + // Demand Zones ... + if (drawDemandZones) + { + // + count = ArraySize(state.demandZones); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCDemandZone item = state.demandZones[i]; + if (forceUpdateTo) + { + item.To(cTime); + } + + // + XCDemandZoneObject *iObj; + bool isCreated = mPOIDrawer.CreateDemandZone( + item, + iObj // + ); + if (isCreated) + { + AddObjectIfNotExists(iObj); + } + } + } + } + + // + // Order Blocks ... + + // + // Bullish Order Blocks ... + if (drawBullishOrderBlocks) + { + // + count = ArraySize(state.bullishOrderBlocks); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock item = state.bullishOrderBlocks[i]; + if (forceUpdateTo) + { + item.To(cTime); + } + + // + XCBullishOrderBlockObject *iObj; + bool isCreated = mPOIDrawer.CreateBullishOrderBlock( + item, + iObj // + ); + if (isCreated) + { + AddObjectIfNotExists(iObj); + } + } + } + } + + // + // Bearish Order Blocks ... + if (drawBearishOrderBlocks) + { + // + count = ArraySize(state.bearishOrderBlocks); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock item = state.bearishOrderBlocks[i]; + if (forceUpdateTo) + { + item.To(cTime); + } + + // + XCBearishOrderBlockObject *iObj; + bool isCreated = mPOIDrawer.CreateBearishOrderBlock( + item, + iObj // + ); + if (isCreated) + { + AddObjectIfNotExists(iObj); + } + } + } + } + + // + // Fair Value Gaps ... + + // + // Bullish Fair Value Gaps ... + if (drawBullishFairValueGaps) + { + // + count = ArraySize(state.bullishFairValueGaps); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCFVG item = state.bullishFairValueGaps[i]; + if (forceUpdateTo) + { + item.To(cTime); + } + + // + XCBullishFairValueGapObject *iObj; + bool isCreated = mPOIDrawer.CreateBullishFairValueGap( + item, + iObj // + ); + if (isCreated) + { + AddObjectIfNotExists(iObj); + } + } + } + } + + // + // Bearish Fair Value Gaps ... + if (drawBearishFairValueGaps) + { + // + count = ArraySize(state.bearishFairValueGaps); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCFVG item = state.bearishFairValueGaps[i]; + if (forceUpdateTo) + { + item.To(cTime); + } + + // + XCBearishFairValueGapObject *iObj; + bool isCreated = mPOIDrawer.CreateBearishFairValueGap( + item, + iObj // + ); + if (isCreated) + { + AddObjectIfNotExists(iObj); + } + } + } + } + + // + // Rejection Bars ... + + // + // Bullish Rejection Bars ... + if (drawBullishRejectionBars) + { + // + count = ArraySize(state.bullishRejectionBars); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCRejectionBar item = state.bullishRejectionBars[i]; + + // + XCBullishRejectionBarObject *iObj; + bool isCreated = mPOIDrawer.CreateBullishRejectionBar( + item, + iObj // + ); + if (isCreated) + { + AddObjectIfNotExists(iObj); + } + } + } + } + + // + // Bearish Rejection Bars ... + if (drawBearishRejectionBars) + { + // + count = ArraySize(state.bearishRejectionBars); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCRejectionBar item = state.bearishRejectionBars[i]; + + // + XCBearishRejectionBarObject *iObj; + bool isCreated = mPOIDrawer.CreateBearishRejectionBar( + item, + iObj // + ); + if (isCreated) + { + AddObjectIfNotExists(iObj); + } + } + } + } + + // + // Momentum Bars ... + + // + // Bullish Momentum Bars ... + if (drawBullishMomentumBars) + { + // + count = ArraySize(state.bullishMomentumBars); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCMomentumBar item = state.bullishMomentumBars[i]; + + // + XCBullishMomentumBarObject *iObj; + bool isCreated = mPOIDrawer.CreateBullishMomentumBar( + item, + iObj // + ); + if (isCreated) + { + AddObjectIfNotExists(iObj); + } + } + } + } + + // + // Bearish Momentum Bars ... + if (drawBearishMomentumBars) + { + // + count = ArraySize(state.bearishMomentumBars); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCMomentumBar item = state.bearishMomentumBars[i]; + + // + XCBearishMomentumBarObject *iObj; + bool isCreated = mPOIDrawer.CreateBearishMomentumBar( + item, + iObj // + ); + if (isCreated) + { + AddObjectIfNotExists(iObj); + } + } + } + } + + // + // Ticks Zone ... + if (drawTicksZone && + state.ticksZone != NULL) + { + // + XCTicksZone *iZone = state.ticksZone; + + // + if (forceUpdateTo) + { + iZone.To(cTime); + } + + // + XCTicksZoneObject *iObj; + bool isCreated = mPOIDrawer.CreateTicksZone( + iZone, + iObj // + ); + if (isCreated) + { + AddObjectIfNotExists(iObj); + } + } + } + + /** + * Add Specified Object to Drawn Objects if not Exists ... + */ + void AddObjectIfNotExists(XCBaseObject *object) + { + // + string name = object.ObjName(); + + // + bool canAdd = true; + int count = mDrawnObjects.Total(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + string iName = ((XCBaseObject *)mDrawnObjects.At(i)).ObjName(); + + // + if (name == iName) + { + // + canAdd = false; + break; + } + } + } + + // + if (canAdd) + { + mDrawnObjects.Add(object); + } + } + + // + // Private ... + private: + // + // Props ... + + // + string mSymbol; // Trading Symbol ... + ENUM_TIMEFRAMES mPeriod; // Trading TimeFrame ... + bool mForceDisabled; // Force Disabled ... + bool mAllowLong; // Allow Long Signals + bool mAllowShort; // Allow Short Signals + double mR2R; // Risk/Rewar Ratio ... + double mVolume; // Static Volume Per Trades ... + + // + double mMaxAllowedSpread; // Max Allowed Spread ... + int mMinRequiredTicksForSpreadPass; // Min Required Ticks Verification for Spread Pass ... + int mMaxAllowedSaveTicks; // Max Allowed Save Ticks ... + + // + long mChartID; // Chart ID ... + int mSubWindow; // Sub Window ID ... + + // + // On X121 Signal Recieved Event Handler(s) ... + TOnX121SMCSignal mSignalEventHandlers[]; + + // + // Actions ... + + /** + * Install all Helpers and Prepare all Configurations for required Indicators ... + */ + void Init() + { + // + mForceDisabled = false; + + // + R2R(1); + Volume(0.01); + MaxAllowedSaveTicks(150); + MinRequiredTicksForSpreadPass(100); + + // + ChartIdentification(0); + SubWindowIdentification(0); + + // + // Configure POI Drawer if Required ... + mPOIDrawer = new XCPOIDrawer(); + mPOIDrawer.ChartIdentification(0); + mPOIDrawer.SubWindowIdentification(0); + + // + mPOIDrawer.DemandZoneFill(false); + mPOIDrawer.SupplyZoneFill(false); + mPOIDrawer.BullishFVGFill(false); + mPOIDrawer.BearishFVGFill(false); + mPOIDrawer.SupportZoneFill(false); + mPOIDrawer.ResistanceZoneFill(false); + mPOIDrawer.BullishOrderBlockFill(false); + mPOIDrawer.BearishOrderBlockFill(false); + + // + string symbol = Symbol(); + ENUM_TIMEFRAMES period = Period(); + + // + // Initialize Bar Tracker ... + mBarTracker.Init( + symbol, + period // + ); + + // + // Initialize POIs ... + + // + int poiRequired = 40; + + // + // Trigger ... + mTriggerDetector = new XCPOIDetector( + symbol, + PERIOD_M1 // + ); + mTriggerDetector.MaxNumberOfRequiredPOIs(poiRequired); + mTriggerDetector.Init(); + + // + // Decision ... + mDecisionDetector = new XCPOIDetector( + symbol, + PERIOD_M5 // + ); + mDecisionDetector.MaxNumberOfRequiredPOIs(poiRequired); + mDecisionDetector.Init(); + + // + // Analyse ... + mAnalyseDetector = new XCPOIDetector( + symbol, + PERIOD_M15 // + ); + mAnalyseDetector.MaxNumberOfRequiredPOIs(poiRequired); + mAnalyseDetector.Init(); + + // + // Verification ... + mVerificationDetector = new XCPOIDetector( + symbol, + PERIOD_M30 // + ); + mVerificationDetector.MaxNumberOfRequiredPOIs(poiRequired); + mVerificationDetector.Init(); + + // + // Consolidation ... + mConsolidationDetector = new XCPOIDetector( + symbol, + PERIOD_H1 // + ); + mConsolidationDetector.MaxNumberOfRequiredPOIs(poiRequired); + mConsolidationDetector.Init(); + + // + // Vision ... + mVisionDetector = new XCPOIDetector( + symbol, + PERIOD_H4 // + ); + mVisionDetector.MaxNumberOfRequiredPOIs(poiRequired); + mVisionDetector.Init(); + + // + } + + /** + * De Initialize all Tools ... + */ + void DeInit() + { + // + delete mVisionDetector; + delete mConsolidationDetector; + delete mVerificationDetector; + delete mAnalyseDetector; + delete mDecisionDetector; + delete mTriggerDetector; + + // + delete mPOIDrawer; + + // + Destroy(); + } + + /** + * Reste Bar Tracker ... + */ + void ResetBarTracker() + { + mBarTracker.Clean(); + } + + /** + * Cleanup Ticks Size ... + */ + void CleanupTicks() + { + // + int maxRequiredTicks = MaxAllowedSaveTicks(); + int ticksCount = ArraySize(mTicks); + if (!IsValidSize(ticksCount) || + ticksCount <= maxRequiredTicks) + { + return; + } + + // + int removeCount = ticksCount - maxRequiredTicks; + if (!IsValidSize(removeCount)) + { + return; + } + + // + ArrayRemove( + mTicks, + 0, + removeCount // + ); + } + + /** + * Add new Tick Data to Collection ... + */ + void SaveTickData() + { + // + XTick tick; + bool isInited = tick.Init(mSymbol); + if (!isInited) + { + return; + } + + // + AddRef( + tick, + mTicks // + ); + } + + /** + * Calculate Ticks Param for Looping through Last n items ... + * + * @param start: Integer Reference to Start ... + * @param end: Integer Reference to End ... + * @param numOfLastTicks: Integer Max Number of Required N Last Ticks ... + */ + bool CalculateTicksParams( + int &start, + int &end, + int numOfLastTicks = 5 // + ) + { + // + bool result = 0; + + // + start = -1; + end = -1; + + // + int count = ArraySize(mTicks); + + // + start = count - numOfLastTicks; + if (start < 0) + { + start = 0; + } + + // + end = start + numOfLastTicks; + if (end > count) + { + end = count; + } + + // + result = IsValidIndex(start) && + IsValidIndex(end); + + // + return result; + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14031003/X121SMCEA/Classes/x-121.smc.cobjects.class.mq5 b/BKPS/14031003/X121SMCEA/Classes/x-121.smc.cobjects.class.mq5 new file mode 100644 index 0000000..bc455b9 --- /dev/null +++ b/BKPS/14031003/X121SMCEA/Classes/x-121.smc.cobjects.class.mq5 @@ -0,0 +1,195 @@ +/////////////////////////////////////////////////////// +// +// 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 "../../Classes/x-saherelm.x-cobject.class.mq5" +#include "../Libraries/x-121.smc.lib.mq5" + +// +// Definitions ... + +enum ENUM_X121SMC_CHARTOBJECTS +{ + X_XPVPIVOT_OBJ, // XPVPivot Object ... +}; + +// +// Implementations ... + +// +// XPVPivot Object ... +class XCXPVPivotObject : 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, + XPVPivot &pivot, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = pivot.IsValid(); + if (!result) + { + return result; + } + + // + string name = pivot.GetTag(); + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + + // + result = mRect.Create( + chart_id, + name, + window, + pivot.from, + pivot.upper, + pivot.to, + pivot.lower // + ); + + // + if (result) + { + ObjName(name); + } + + // + string mTrendName = "MID_" + name; + double mid = pivot.CalculateMid(); + result = mTrend.Create( + chart_id, + mTrendName, + window, + pivot.from, + mid, + pivot.to, + mid // + ); + if (!result) + { + // + mRect.Delete(); + mRect.Detach(); + } + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Set Pivot Width ... + * + * @param value: Integer ... + */ + void PivotWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mRect.Width(value); + mTrend.Width(value); + } + + /** + * Set Pivot Color ... + * + * @param value: Color ... + */ + void PivotColor(color value) + { + // + mRect.Color(value); + mTrend.Color(value); + } + + /** + * Set Pivot Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void PivotStyle(ENUM_LINE_STYLE value) + { + // + mRect.Style(value); + mTrend.Style(value); + } + + /** + * Set Pivot Fill ... + * + * @param value: Boolean ... + */ + void PivotFill(bool value) + { + mRect.Fill(value); + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_X121SMC_CHARTOBJECTS ) + */ + virtual ENUM_X121SMC_CHARTOBJECTS Type() + { + return X_XPVPIVOT_OBJ; + } + + // + private: + // + + // + // Props ... + CChartObjectRectangle mRect; + CChartObjectTrend mTrend; +}; \ No newline at end of file diff --git a/BKPS/14031003/X121SMCEA/Classes/x-121.smc.ea.panel.class.mq5 b/BKPS/14031003/X121SMCEA/Classes/x-121.smc.ea.panel.class.mq5 new file mode 100644 index 0000000..47d16e0 --- /dev/null +++ b/BKPS/14031003/X121SMCEA/Classes/x-121.smc.ea.panel.class.mq5 @@ -0,0 +1,63 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XC121Panel +// 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" + +// +// Implementation ... + +// +class X121CAppDialog : public XCAppDialog +{ + // + public: + // + // Constructor(s) ... + void X121CAppDialog() + { + } + + // + // Deconstructor ... + void ~X121CAppDialog() + { + } + + // + void Configure() + { + // + // Configure Dialog ... + BackgroundColor(clrBlack); + } + + // + protected: + // + + // + private: + // +}; + +// \ No newline at end of file diff --git a/BKPS/14031003/X121SMCEA/Classes/x-121.smc.market.cycle.helper.class.ex5 b/BKPS/14031003/X121SMCEA/Classes/x-121.smc.market.cycle.helper.class.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..8b7ea37e82cc791565f48ed49d9b22292eb38266 GIT binary patch literal 16228 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 literal 0 HcmV?d00001 diff --git a/BKPS/14031003/X121SMCEA/Classes/x-121.smc.market.cycle.helper.class.mq5 b/BKPS/14031003/X121SMCEA/Classes/x-121.smc.market.cycle.helper.class.mq5 new file mode 100644 index 0000000..a4b9bdc --- /dev/null +++ b/BKPS/14031003/X121SMCEA/Classes/x-121.smc.market.cycle.helper.class.mq5 @@ -0,0 +1,2433 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XC121SMCCycleHelper +// 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-bar.analyser.class.mq5" +#include "../../Classes/x-saherelm.x-poi.class.mq5" +#include "../Libraries/x-121.smc.lib.mq5" + +// +// Definitions ... + +// +// Implementations ... + +enum ENUM_X_CYCLES +{ + X_CYCLE_TRIGGER, + X_CYCLE_DECISION, + X_CYCLE_ANALYSE, + X_CYCLE_VERIFICATION, + X_CYCLE_CONSOLIDATION, + X_CYCLE_VISION, +}; + +enum ENUM_X_CYCLE_EVENTS +{ + SAR_CHANGE_DETECTED, + NEW_PEAK_DETECTED, + NEW_VALE_DETECTED, + PIVOT_POINT_DETECTED, + VWAP_ORDER_CHANGE_ETECTED, + VWAP_STATE_CHANGE_DETCTED, + CONSOLIDATION_BREAKED_DETECTED, + PIVOT_STARTED, + PIVOT_ENDED, +}; + +class XC121SMCCycleHelper : public XCBase +{ + // + public: + // + // Props ... + + // + // X121 ... + XCX121Helper *mX121Helper; + + // + // POI Detector ... + XCPOIDetector *mPOIDetector; + + // + // Bar Analyser + XCBarAnalyser *mBarAnalyser; + + // + // Constructor(s) ... + XC121SMCCycleHelper() + { + Default(); + } + + // + // Deconstructor ... + ~XC121SMCCycleHelper() + { + DeInit(); + } + + // + // Getter/Setter(s) ... + + /** + * Get Max llowed Changes to Save ... + * + * @return ( int ) + */ + int MaxAllowedSavedChanges() + { + return mMaxAllowedSavedChanges; + } + + /** + * Set Max llowed Changes to Save ... + * + * @param value: Integer ... + */ + void MaxAllowedSavedChanges(int value) + { + // + if (value < 10) + { + value = 10; + } + + // + mMaxAllowedSavedChanges = value; + } + + /** + * Get Consolidation Loopback Length ... + * + * @return ( int ) + */ + int ConsolidationLoopback() + { + return mConsolidationLoopback; + } + + /** + * Set Consolidation Loopback Length ... + * + * @param value: Integer ... + */ + void ConsolidationLoopback(int value) + { + // + if (value < 7) + { + value = 7; + } + + // + mConsolidationLoopback = value; + } + + // + // Actions ... + + /** + * Initialize ... + * + * @param symbol: String ... + * @param period: ENUM_TIMEFRAMES member ... + * @param x121Inputs: X121Inputs instance ... + * + * @return ( bool ) + */ + bool Init( + string symbol, + ENUM_TIMEFRAMES period, + X121Inputs &x121Inputs // + ) + { + // + bool result = false; + + // + result = IsValid(symbol) && + IsValid(period); + if (!result) + { + return result; + } + + // + // X121 ... + mX121Helper = new XCX121Helper(); + result = mX121Helper.Init( + symbol, + period, + x121Inputs // + ); + if (!result) + { + return result; + } + + // + mPOIDetector = new XCPOIDetector( + symbol, + period // + ); + mPOIDetector.MaxNumberOfRequiredPOIs(0); + mPOIDetector.Init(); + + // + // Initialize Bar Analyser Class Instance ... + mBarAnalyser = new XCBarAnalyser(); + + // + // Set Chart Style ... + ApplyChartStyle(); + + // + return result; + } + + /** + * Retrieve Symbol ... + * + * @return ( string ) + */ + string GetSymbol() + { + // + string result = NULL; + + // + result = mX121Helper.GetSymbol(); + + // + return result; + } + + /** + * Retrieve TimeFrame (Period) ... + * + * @return ( ENUM_TIMEFRAMES ) + */ + ENUM_TIMEFRAMES GetPeriod() + { + // + ENUM_TIMEFRAMES result = NULL; + + // + result = mX121Helper.GetPeriod(); + + // + return result; + } + + /** + * Get Specified Bar ... + * + * @param source: XOHCL instance, Source Bar ... + * @param bar: XOHCL instance, Dest Bar ... + * + * @return ( bool ) + */ + bool GetBar( + XOHCL &source, + XOHCL &bar // + ) + { + // + bool result = false; + + // + bar.Clean(); + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + result = + IsValid(symbol) && + IsValid(period) && + source.IsValid(); + if (!result) + { + return result; + } + + // + int index = iBarShift( + symbol, + period, + source.time // + ); + result = bar.Init( + symbol, + period, + index // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + return result; + } + + /** + * Retrieve Specified Bar ... + * + * @param bar: XOHCL instance ... + * @param index: Integer ... + * + * @return ( bool ) + */ + bool GetBar( + XOHCL &bar, + int index = 0 // + ) + { + // + bool result = false; + + // + bar.Clean(); + + // + if (index < 0) + { + index = 0; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + result = bar.Init( + symbol, + period, + index // + ); + + // + return result; + } + + /** + * Retrieve Specified Bar ... + * + * @param bar: XOHCL instance ... + * @param time: Datetime ... + * + * @return ( bool ) + */ + bool GetBar( + XOHCL &bar, + datetime time = NULL // + ) + { + // + bool result = false; + + // + int index = GetBarIndex(time); + result = GetBar(bar, + index // + ); + + // + return result; + } + + /** + * Retrieve Specified Time Bar Index ... + * + * @param time: DateTime ... + * + * @return ( int ) + */ + int GetBarIndex(datetime time = NULL) + { + // + int result = -1; + + // + time = NormalizeTime(time); + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + result = iBarShift( + symbol, + period, + time // + ); + + // + return result; + } + + /** + * Retrieve Cycle Conditions ... + * + * @param events: ENUM_X_CYCLE_EVENTS member, Array ... + * @param conditions: X121SMCCycleConditions instance ... + * @param barIndex: Integer ... + * @param loopback: Integer ... + * + * @return ( bool ) + */ + bool GetConditions( + ENUM_X_CYCLE_EVENTS &events[], + ENUM_XPOI_EVENTS &poiEvents[], + X121SMCCycleConditions &conditions, + int barIndex = 0, + int loopback = 7 // + ) + { + // + bool result = false; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (loopback < 5) + { + loopback = 5; + } + + // + Clean(events); + Clean(poiEvents); + conditions.Clean(); + + // + result = mX121Helper.GetConditions( + conditions.x121Conditions, + barIndex, + loopback // + ); + if (!result) + { + // + conditions.Clean(); + return result; + } + + // + mPOIDetector.Update(poiEvents); + mPOIDetector.GetState(conditions.state); + + // + conditions.symbol = conditions.x121Conditions.symbol; + conditions.period = conditions.x121Conditions.period; + conditions.time = TimeCurrent(); + + // + result = conditions.IsValid(); + + // + if (result) + { + // + Calculate( + barIndex, + events, + conditions // + ); + } + + // + return result; + } + + // + // Tools ... + + /** + * Get POI State of Specified Pivot ... + * + * @param pivot: XPVPivot instance Reference ... + * @param lookupSwingHighs: Boolean ... + * @param lookupSwingLows: Boolean ... + * @param lookupSupportZones: Boolean ... + * @param lookupResistanceZones: Boolean ... + * @param lookupSupplyZones: Boolean ... + * @param lookupDemandZones: Boolean ... + * @param lookupBullishOrderBlocks: Boolean ... + * @param lookupBearishOrderBlocks: Boolean ... + * @param lookupBullishFairValueGaps: Boolean ... + * @param lookupBearishFairValueGaps: Boolean ... + * @param lookupBullishRejectionBars: Boolean ... + * @param lookupBearishRejectionBars: Boolean ... + * @param lookupBullishMomentumBars: Boolean ... + * @param lookupBearishMomentumBars: Boolean ... + * + * @return ( bool ) + */ + bool FillPivotState( + XPVPivot &pivot, + bool lookupSwingHighs = true, + bool lookupSwingLows = true, + bool lookupSupportZones = true, + bool lookupResistanceZones = true, + bool lookupSupplyZones = true, + bool lookupDemandZones = true, + bool lookupBullishOrderBlocks = true, + bool lookupBearishOrderBlocks = true, + bool lookupBullishFairValueGaps = true, + bool lookupBearishFairValueGaps = true, + bool lookupBullishRejectionBars = true, + bool lookupBearishRejectionBars = true, + bool lookupBullishMomentumBars = true, + bool lookupBearishMomentumBars = true // + ) + { + // + bool result = false; + + // + XPOIState state; + state.Clean(); + + // + result = pivot.IsValid(); + if (!result) + { + return result; + } + + // + XPOIState _state; + mPOIDetector.GetState(_state); + result = _state.IsValid() && + _state.HasChild(); + if (!result) + { + return result; + } + + // + DetectPivotPOIs( + pivot, + _state, + state, + lookupSwingHighs, + lookupSwingLows, + lookupSupportZones, + lookupResistanceZones, + lookupSupplyZones, + lookupDemandZones, + lookupBullishOrderBlocks, + lookupBearishOrderBlocks, + lookupBullishFairValueGaps, + lookupBearishFairValueGaps, + lookupBullishRejectionBars, + lookupBearishRejectionBars, + lookupBullishMomentumBars, + lookupBearishMomentumBars // + ); + + // + result = state.IsValid() && + state.HasChild(); + if (result) + { + // + pivot.state = state; + + // + CalculatePivotTickZone(pivot); + } + + // + return result; + } + + /** + * Detect XPV Based POI(s) ... + * + * @param barIndex: Start Bar Index ... + * @param minRepetition: minimum Repeate of POI for Validation ... + * @param requiredPivots: Number of Min Requirement POI(s) ... + * @param pivotHelper: XC121SMCCycleHelper instance Pointer ... + * @param orderFlow: XPVPivot instance Array Reference ... + * @param orderFlowDirection: ENUM_X_DIRECTION member Reference which represents OrderFlow Direction ... + * @param maxAllowedLoopbackBars: Integer, Max Allowed Loopback Bars ... + * + * @return ( bool ) + */ + bool DetectOrderFlow( + int barIndex, + XPVPivot &orderFlow[], // OrderFlows ... + ENUM_X_DIRECTION &orderFlowDirection, // Order Flow Direction ... + int minRepetition = 0, + int requiredPivots = 0, + int maxAllowedLoopbackBars = 576 // + ) + { + // + bool result = false; + + // + orderFlowDirection = X_DIRECTION_NONE; + + // + if (maxAllowedLoopbackBars <= 0) + { + maxAllowedLoopbackBars = 1000; + } + + // + if (minRepetition <= 0) + { + minRepetition = mX121Helper.GetDonChainLength(); + } + + // + if (requiredPivots <= 0) + { + requiredPivots = 3; + } + + // + int start = barIndex; + int end = start + maxAllowedLoopbackBars; + + // + Clean(orderFlow); + + // + result = minRepetition > 0 && + requiredPivots > 0; + if (!result) + { + return result; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + double peak = 0; + XPVPivot peaks[]; + int peakRepeate = 0; + int peakToBarIndex = 0; + int peakFromBarIndex = 0; + + // + double vale = 0; + XPVPivot vales[]; + int valeRepeate = 0; + int valeToBarIndex = 0; + int valeFromBarIndex = 0; + + // + bool canLookupPeak = true; + bool canLookupVale = true; + bool canLookup = true; + while (canLookup) + { + // + // Check Peak ... + double iPeak = mX121Helper.GetPeak(barIndex); + if (iPeak != peak) + { + // + if (peak != 0 && + peakRepeate >= minRepetition) + { + // + bool isExists = false; + int count = ArraySize(peaks); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XPVPivot iPivot = peaks[i]; + + // + if (iPivot.upper == iPeak) + { + // + isExists = true; + break; + } + } + } + if (!isExists) + { + // + XPVPivot iPivot; + + // + iPivot.lower = 0; + iPivot.upper = peak; + iPivot.symbol = symbol; + iPivot.period = period; + iPivot.type = XPV_PEAK; + iPivot.repetition = peakRepeate; + iPivot.to = iTime( + symbol, + period, + peakToBarIndex // + ); + iPivot.from = iTime( + symbol, + period, + peakFromBarIndex // + ); + + // + iPivot.lower = iPivot.CalculateLower(); + + // + bool isValid = iPivot.IsValid(); + if (isValid) + { + // + AddRef( + iPivot, + peaks // + ); + } + } + } + + // + peak = iPeak; + peakRepeate = 0; + peakFromBarIndex = 0; + peakToBarIndex = barIndex; + } + else if (iPeak == peak) + { + // + peakRepeate++; + peakFromBarIndex = barIndex; + } + + // + // Check Vale ... + double iVale = mX121Helper.GetVale(barIndex); + if (iVale != vale) + { + // + if (vale != 0 && + valeRepeate >= minRepetition) + { + // + bool isExists = false; + int count = ArraySize(vales); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XPVPivot iPivot = vales[i]; + + // + if (iPivot.lower == iVale) + { + // + isExists = true; + break; + } + } + } + if (!isExists) + { + // + XPVPivot iPivot; + + // + iPivot.upper = 0; + iPivot.lower = vale; + iPivot.symbol = symbol; + iPivot.period = period; + iPivot.type = XPV_VALE; + iPivot.repetition = valeRepeate; + iPivot.to = iTime( + symbol, + period, + valeToBarIndex // + ); + iPivot.from = iTime( + symbol, + period, + valeFromBarIndex // + ); + + // + iPivot.upper = iPivot.CalculateUpper(); + + // + bool isValid = iPivot.IsValid(); + if (isValid) + { + // + AddRef( + iPivot, + vales // + ); + } + } + } + + // + vale = iVale; + valeRepeate = 0; + valeFromBarIndex = 0; + valeToBarIndex = barIndex; + } + else if (iVale == vale) + { + // + valeRepeate++; + valeFromBarIndex = barIndex; + } + + // + canLookupPeak = ArraySize(peaks) < requiredPivots; + canLookupVale = ArraySize(vales) < requiredPivots; + canLookup = barIndex < end && + (canLookupPeak || + canLookupVale); + if (canLookup) + { + barIndex++; + } + } + + // + result = IsValidSize(ArraySize(peaks)) || + IsValidSize(ArraySize(vales)); + if (!result) + { + return result; + } + + // + // Detect Order Flow ... + Copy( + peaks, + orderFlow, + false // + ); + Copy( + vales, + orderFlow, + false // + ); + int count = ArraySize(orderFlow); + result = IsValidSize(orderFlow); + if (!result) + { + return result; + } + + // + // Sort Pivots ... + SortPivots(orderFlow); + + // + // Filter Broken Order Flows ... + FilterBrokenPivots(orderFlow); + + // + // Detect Order Flow Direction ... + result = DetectPivotDirection( + orderFlow, + orderFlowDirection // + ); + if (!result) + { + return result; + } + + // + return result; + } + + // + // Change Values Actions ... + + /** + * Count Saved Parabolic Sar Changes ... + * + * @return ( int ) + */ + int CountSarChanges() + { + return ArraySize(mSarChanges); + } + + /** + * Fill Saved Sar Changes ... + * + * @param changes: XValueChange instance Array Reference ... + * + * @return ( int ) + */ + int FillSarChanges( + XValueChange &changes[] // + ) + { + // + Clean(changes); + + // + Copy( + mSarChanges, + changes // + ); + + // + int result = ArraySize(changes); + + // + return result; + } + + /** + * Retrieve Last Sar Changes ... + * + * @param change: XValueChange instance ... + * + * @return ( bool ) + */ + bool GetLastSarChange(XValueChange &change) + { + // + bool result = false; + + // + result = GetLastItem( + change, + mSarChanges // + ); + + // + return result; + } + + /** + * Count Saved Peaks Changes ... + * + * @return ( int ) + */ + int CountPeaksChanges() + { + return ArraySize(mPeaksChanges); + } + + /** + * Fill Saved Peaks Changes ... + * + * @param changes: XValueChange instance Array Reference ... + * + * @return ( int ) + */ + int FillPeaksChanges( + XValueChange &changes[] // + ) + { + // + Clean(changes); + + // + Copy( + mPeaksChanges, + changes // + ); + + // + int result = ArraySize(changes); + + // + return result; + } + + /** + * Retrieve Last Peak Changes ... + * + * @param change: XValueChange instance ... + * + * @return ( bool ) + */ + bool GetLastPeakChange(XValueChange &change) + { + // + bool result = false; + + // + result = GetLastItem( + change, + mPeaksChanges // + ); + + // + return result; + } + + /** + * Count Saved Vales Changes ... + * + * @return ( int ) + */ + int CountValesChanges() + { + return ArraySize(mValesChanges); + } + + /** + * Fill Saved Vales Changes ... + * + * @param changes: XValueChange instance Array Reference ... + * + * @return ( int ) + */ + int FillValesChanges( + XValueChange &changes[] // + ) + { + // + Clean(changes); + + // + Copy( + mValesChanges, + changes // + ); + + // + int result = ArraySize(changes); + + // + return result; + } + + /** + * Retrieve Last Vale Changes ... + * + * @param change: XValueChange instance ... + * + * @return ( bool ) + */ + bool GetLastValeChange(XValueChange &change) + { + // + bool result = false; + + // + result = GetLastItem( + change, + mValesChanges // + ); + + // + return result; + } + + /** + * Count Saved VWap Order Changes ... + * + * @return ( int ) + */ + int CountVWapOrderChanges() + { + return ArraySize(mVWapOrderChanges); + } + + /** + * Fill Saved VWap Order Changes ... + * + * @param changes: XValueChange instance Array Reference ... + * + * @return ( int ) + */ + int FillVWapOrderChanges( + XValueChange &changes[] // + ) + { + // + Clean(changes); + + // + Copy( + mVWapOrderChanges, + changes // + ); + + // + int result = ArraySize(changes); + + // + return result; + } + + /** + * Retrieve Last VWap Order Changes ... + * + * @param change: XValueChange instance ... + * + * @return ( bool ) + */ + bool GetLastVWapOrderChange(XValueChange &change) + { + // + bool result = false; + + // + result = GetLastItem( + change, + mVWapOrderChanges // + ); + + // + return result; + } + + /** + * Count Saved VWap State Changes ... + * + * @return ( int ) + */ + int CountVWapStateChanges() + { + return ArraySize(mVWapStateChanges); + } + + /** + * Fill Saved VWap State Changes ... + * + * @param changes: XValueChange instance Array Reference ... + * + * @return ( int ) + */ + int FillVWapStateChanges( + XValueChange &changes[] // + ) + { + // + Clean(changes); + + // + Copy( + mVWapStateChanges, + changes // + ); + + // + int result = ArraySize(changes); + + // + return result; + } + + /** + * Retrieve Last VWap State Changes ... + * + * @param change: XValueChange instance ... + * + * @return ( bool ) + */ + bool GetLastVWapStateChange(XValueChange &change) + { + // + bool result = false; + + // + result = GetLastItem( + change, + mVWapStateChanges // + ); + + // + return result; + } + + /** + * Count Founded Consolidation Zones ... + * + * @return ( int ) + */ + int CountConsolidationZones() + { + return ArraySize(mConsolidationZones); + } + + /** + * Fill Broken Consolidations ... + * + * @param consolidations: XConsolidationZone instance Array Reference ... + * + * @return ( int ) + */ + int FillConsolidationZones( + XConsolidationZone &consolidations[] // + ) + { + // + Clean(consolidations); + + // + Copy( + mConsolidationZones, + consolidations // + ); + + // + int result = ArraySize(consolidations); + + // + return result; + } + + /** + * Retrieve Last Consolidation Breaks ... + * + * @param change: XValueChange instance ... + * + * @return ( bool ) + */ + bool GetLastConsolidationZone(XConsolidationZone &zone) + { + // + bool result = false; + + // + result = GetLastItem( + zone, + mConsolidationZones // + ); + + // + return result; + } + + /** + * Count Pivot Points Change ... + * + * @return ( int ) + */ + int CountPivotPoints() + { + return ArraySize(mPivotPoints); + } + + /** + * Retrieve All Pivot Point Changes as a Collection ... + * + * @param pivots: XPVPivotPoint instance Reference ... + * + * @return ( int ) + */ + int FillPivotPointss(XPVPivotPoint &pivots[]) + { + // + int result = 0; + + // + Clean(pivots); + + // + int count = CountPivotPoints(); + if (!IsValidSize(pivots)) + { + return result; + } + + // + Copy( + mPivotPoints, + pivots // + ); + + // + result = ArraySize(pivots); + + // + return result; + } + + /** + * Retrieve All Peak Pivot Point Changes as a Collection ... + * + * @param pivots: XPVPivotPoint instance Reference ... + * + * @return ( int ) + */ + int FillPeakPivotPoints(XPVPivotPoint &pivots[]) + { + // + int result = 0; + + // + Clean(pivots); + + // + int count = CountPivotPoints(); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XPVPivotPoint iPivot = mPivotPoints[i]; + + // + bool isValid = iPivot.IsPeak(); + if (isValid) + { + // + AddRef( + iPivot, + pivots // + ); + } + } + + // + result = ArraySize(pivots); + + // + return result; + } + + /** + * Retrieve All Vale Pivot Point Changes as a Collection ... + * + * @param pivots: XPVPivotPoint instance Reference ... + * + * @return ( int ) + */ + int FillValePivotPoints(XPVPivotPoint &pivots[]) + { + // + int result = 0; + + // + Clean(pivots); + + // + int count = CountPivotPoints(); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XPVPivotPoint iPivot = mPivotPoints[i]; + + // + bool isValid = iPivot.IsVale(); + if (isValid) + { + // + AddRef( + iPivot, + pivots // + ); + } + } + + // + result = ArraySize(pivots); + + // + return result; + } + + /** + * Get Current Active Pivot ... + * + * @param pivot: XPVPivot instance reference ... + */ + void GetActivePivot(XPVPivot &pivot) + { + // + mActivePivot.to = TimeCurrent(); + pivot = mActivePivot; + } + + /** + * Count Calculated Pivots ... + * + * @return ( int ) + */ + int CountPivots() + { + return ArraySize(mPivots); + } + + /** + * Fill Pivots ... + * + * @param pivots: XPVPivot instance Reference Array ... + * + * @return ( int ) + */ + int FillPivots(XPVPivot &pivots[]) + { + // + int result = 0; + + // + Clean(pivots); + + // + Copy( + mPivots, + pivots // + ); + + // + result = ArraySize(pivots); + + // + return result; + } + + // + // Virtuals ... + + /** + * Set Default Properties Values ... + */ + virtual void Default() + { + // + ConsolidationLoopback(10); + MaxAllowedSavedChanges(50); + } + + // + protected: + // + + /** + * Calculate Requirements ... + * + * @param barIndex: Integer, Bar Index ... + * @param events: ENUM_X_CYCLE_EVENTS member, Array ... + * @param conditions: X121SMCCycleConditions instance ... + */ + void Calculate( + int barIndex, + ENUM_X_CYCLE_EVENTS &events[], + X121SMCCycleConditions &conditions // + ) + { + // + Clean(events); + + // + string symbol = GetSymbol(); + datetime cTime = TimeCurrent(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + XOHCL changeBar; + int index = + barIndex <= 0 + ? 1 + : barIndex; + bool isInited = GetBar( + changeBar, + index // + ); + if (!isInited) + { + return; + } + + // + // Detect Sar Change ... + bool isSarSwitchedToBullish = conditions.x121Conditions.isSarSwitchedToBullish; + bool isSarSwitchedToBearish = conditions.x121Conditions.isSarSwitchedToBearish; + bool isSarChanged = isSarSwitchedToBullish || + isSarSwitchedToBearish; + + // + if (isSarChanged) + { + // + XValueChange sarChanged; + + // + datetime time = changeBar.time; + double after = conditions.x121Conditions.sarBuffer[1]; + double before = conditions.x121Conditions.sarBuffer[2]; + ENUM_X_DIRECTION dir = + isSarSwitchedToBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Initialize Model ... + isInited = sarChanged.Init( + before, + after, + dir, + time // + ); + if (isInited) + { + // + isInited = AddSarChange(sarChanged); + + // + Add( + SAR_CHANGE_DETECTED, + events // + ); + } + } + + // + // Detect Peaks Changes ... + + // + bool isNewPeak = conditions.x121Conditions.isNewPeak; + double peak = conditions.x121Conditions.peaksBuffer[0]; + bool isNewPeakOverLast = conditions.x121Conditions.isNewPeakOverLast; + bool isNewPeakUnderLast = conditions.x121Conditions.isNewPeakUnderLast; + + // + if (isNewPeak) + { + // + XValueChange peaksChanged; + + // + datetime time = changeBar.time; + double after = conditions.x121Conditions.peaksBuffer[1]; + double before = conditions.x121Conditions.peaksBuffer[2]; + ENUM_X_DIRECTION dir = + isNewPeakOverLast + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Initialize Model ... + isInited = peaksChanged.Init( + before, + after, + dir, + time // + ); + if (isInited) + { + // + isInited = AddPeaksChange(peaksChanged); + + // + Add( + NEW_PEAK_DETECTED, + events // + ); + } + } + + // + // Detect Vales Changes ... + + // + bool isNewVale = conditions.x121Conditions.isNewVale; + double vale = conditions.x121Conditions.valesBuffer[0]; + bool isNewValeOverLast = conditions.x121Conditions.isNewValeOverLast; + bool isNewValeUnderLast = conditions.x121Conditions.isNewValeUnderLast; + + // + if (isNewVale) + { + // + XValueChange valesChanged; + + // + datetime time = changeBar.time; + double after = conditions.x121Conditions.valesBuffer[1]; + double before = conditions.x121Conditions.valesBuffer[2]; + ENUM_X_DIRECTION dir = + isNewValeUnderLast + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + // Initialize Model ... + isInited = valesChanged.Init( + before, + after, + dir, + time // + ); + if (isInited) + { + // + isInited = AddValesChange(valesChanged); + + // + Add( + NEW_VALE_DETECTED, + events // + ); + } + } + + // + // VWap Direction Change ... + + // + // Ordered Change ... + bool isVWapSwitchedToBullishOrdered = + conditions.x121Conditions.isVWapSwitchedToBullishOrdered; + bool isVWapSwitchedToBearishOrdered = + conditions.x121Conditions.isVWapSwitchedToBearishOrdered; + bool isVWAPOrderedChanged = isVWapSwitchedToBullishOrdered || + isVWapSwitchedToBearishOrdered; + // + if (isVWAPOrderedChanged) + { + // + XValueChange vwapOrderChanged; + + // + datetime time = changeBar.time; + ENUM_X_DIRECTION dir = + isVWapSwitchedToBullishOrdered + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + double after = 0; + double before = 0; + if (isVWapSwitchedToBullishOrdered) + { + // + // After Max ... + after = MathMax( + conditions.x121Conditions.vwapFastBuffer[1], + conditions.x121Conditions.vwapMidBuffer[1] // + ); + after = MathMax( + after, + conditions.x121Conditions.vwapSlowBuffer[1] // + ); + + // + // Before Min ... + before = MathMin( + conditions.x121Conditions.vwapFastBuffer[1], + conditions.x121Conditions.vwapMidBuffer[1] // + ); + before = MathMin( + before, + conditions.x121Conditions.vwapSlowBuffer[1] // + ); + } + else + { + // + // After Min ... + after = MathMin( + conditions.x121Conditions.vwapFastBuffer[1], + conditions.x121Conditions.vwapMidBuffer[1] // + ); + after = MathMin( + after, + conditions.x121Conditions.vwapSlowBuffer[1] // + ); + + // + // Before Max ... + before = MathMax( + conditions.x121Conditions.vwapFastBuffer[1], + conditions.x121Conditions.vwapMidBuffer[1] // + ); + before = MathMax( + before, + conditions.x121Conditions.vwapSlowBuffer[1] // + ); + } + + // + // Initialize Model ... + isInited = vwapOrderChanged.Init( + before, + after, + dir, + time // + ); + if (isInited) + { + // + isInited = AddVWapOrderChange(vwapOrderChanged); + + // + Add( + VWAP_ORDER_CHANGE_ETECTED, + events // + ); + } + } + + // + // States Changed ... + bool isVWapSwitchedToBullishState = + conditions.x121Conditions.isVWapSwitchedToBullishState; + bool isVWapSwitchedToBearishState = + conditions.x121Conditions.isVWapSwitchedToBearishState; + bool isVWapStatesChanged = isVWapSwitchedToBullishState || + isVWapSwitchedToBearishState; + + // + if (isVWapStatesChanged) + { + // + XValueChange vwapStateChanged; + + // + datetime time = changeBar.time; + ENUM_X_DIRECTION dir = + isVWapSwitchedToBullishState + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + double after = 0; + double before = 0; + if (isVWapSwitchedToBullishState) + { + // + // After Max ... + after = MathMax( + conditions.x121Conditions.vwapFastBuffer[1], + conditions.x121Conditions.vwapMidBuffer[1] // + ); + after = MathMax( + after, + conditions.x121Conditions.vwapSlowBuffer[1] // + ); + + // + // Before Min ... + before = MathMin( + conditions.x121Conditions.vwapFastBuffer[1], + conditions.x121Conditions.vwapMidBuffer[1] // + ); + before = MathMin( + before, + conditions.x121Conditions.vwapSlowBuffer[1] // + ); + } + else + { + // + // After Min ... + after = MathMin( + conditions.x121Conditions.vwapFastBuffer[1], + conditions.x121Conditions.vwapMidBuffer[1] // + ); + after = MathMin( + after, + conditions.x121Conditions.vwapSlowBuffer[1] // + ); + + // + // Before Max ... + before = MathMax( + conditions.x121Conditions.vwapFastBuffer[1], + conditions.x121Conditions.vwapMidBuffer[1] // + ); + before = MathMax( + before, + conditions.x121Conditions.vwapSlowBuffer[1] // + ); + } + + // + // Initialize Model ... + isInited = vwapStateChanged.Init( + before, + after, + dir, + time // + ); + if (isInited) + { + // + isInited = AddVWapStateChange(vwapStateChanged); + + // + Add( + VWAP_STATE_CHANGE_DETCTED, + events // + ); + } + } + + // + // Detect Consolidations ... + + // + int consolidationLoopback = ConsolidationLoopback(); + if (IsValidSize(consolidationLoopback)) + { + // + double upper = 0; + double lower = 0; + bool hasConsolidation = + mBarAnalyser.IsConsolidate( + changeBar, + upper, + lower, + consolidationLoopback // + ); + + // + if (hasConsolidation && + !mActioveConsolidationZone.IsValid()) + { + // + // Initialize Consolidation Zone ... + bool isInited = mActioveConsolidationZone.Init( + changeBar.symbol, + changeBar.period, + upper, + lower, + consolidationLoopback // + ); + } + + // + if (!hasConsolidation && + mActioveConsolidationZone.IsValid()) + { + // + mActioveConsolidationZone.Update(); + bool isBreaked = mActioveConsolidationZone.IsBreaked(); + + // + if (isBreaked) + { + // + // Add Active to List ... + AddRef( + mActioveConsolidationZone, + mConsolidationZones // + ); + + // + // Clean Active Zone ... + mActioveConsolidationZone.Clean(); + + // + Add( + CONSOLIDATION_BREAKED_DETECTED, + events // + ); + } + } + } + + // + // Check Valid Peaks and Vales ... + if (isNewPeak || isNewVale) + { + // + int count = 0; + double value = 0; + int repetition = 0; + ENUM_TIMEFRAMES period = GetPeriod(); + int periodSeconds = PeriodSeconds(period); + int minRepetition = mX121Helper.GetDonChainLength(); + ENUM_XPV_PIVOTS type = isNewPeak + ? XPV_PEAK + : XPV_VALE; + + // + XValueChange lastChange; + XValueChange prevChange; + + // + count = CountPeaksChanges(); + if (isNewPeak && count >= 2) + { + // + lastChange = mPeaksChanges[count - 1]; + prevChange = mPeaksChanges[count - 2]; + } + + // + count = CountValesChanges(); + if (isNewVale && count >= 2) + { + // + lastChange = mValesChanges[count - 1]; + prevChange = mValesChanges[count - 2]; + } + + // + if (lastChange.IsValid() && + prevChange.IsValid()) + { + // + value = prevChange.after; + int delayTime = ((int)lastChange.time - (int)prevChange.time); + repetition = delayTime / periodSeconds; + + // + bool isValidPivot = repetition >= minRepetition; + if (isValidPivot) + { + // + XPVPivotPoint pivotPoint; + pivotPoint.type = type; + pivotPoint.value = value; + pivotPoint.time = prevChange.time; + pivotPoint.repetition = repetition; + + // + AddRef( + pivotPoint, + mPivotPoints // + ); + + // + Add( + PIVOT_POINT_DETECTED, + events // + ); + } + } + } + + // // + // // Calculate Pivots ... + // if (isNewPeak || isNewVale) + // { + // // + // if (!mActivePivot.IsValid()) + // { + // // + // mActivePivot.symbol = symbol; + // mActivePivot.period = period; + + // // + // mActivePivot.upper = peak; + // mActivePivot.lower = vale; + + // // + // mActivePivot.from = cTime; + // mActivePivot.to = cTime; + + // // + // mActivePivot.type = + // isNewPeak + // ? XPV_VALE + // : XPV_PEAK; + // mActivePivot.repetition++; + + // // + // Add( + // PIVOT_STARTED, + // events // + // ); + // } + // else + // { + // // + // mActivePivot.to = cTime; + + // // + // mActivePivot.repetition++; + + // // + // if (mActivePivot.to > mActivePivot.from) + // { + // FillPivotState(mActivePivot); + // } + + // // + // // Check Ticks Zone is Valid ... + // bool isTicksZoneValid = + // // + // mActivePivot.state.IsValid() && + // mActivePivot.state.ticksZone != NULL && + // mActivePivot.state.ticksZone.IsValid() + // // + // ; + // if (isTicksZoneValid) { + // // + // Print("Has Valid Ticks Zone ..."); + // } + // } + // } + } + + // + private: + // + // Props ... + + // + // Change Holders ... + int mMaxAllowedSavedChanges; // Max llowed Changes to Save ... + XValueChange mSarChanges[]; // Holds Parabolic Sar Direction Changes ... + XValueChange mPeaksChanges[]; // Holds Peaks Changes ... + XValueChange mValesChanges[]; // Holds Vales Changes ... + XValueChange mVWapOrderChanges[]; // Holds Vales Changes ... + XValueChange mVWapStateChanges[]; // Holds Vales Changes ... + + // + int mConsolidationLoopback; // Consolidation Loopback Length ... + XConsolidationZone mConsolidationZones[]; // Holds Consolidation Zones ... + XConsolidationZone mActioveConsolidationZone; // Holds Actiove Consolidation Zone ... + + // + XPVPivotPoint mPivotPoints[]; // Holds Pivots ... + + // + XCXPVPivotObject mActivePivotObject; + XPVPivot mActivePivot; + XPVPivot mPivots[]; + + // + // Actions ... + + /** + * Release All Resources ... + */ + void DeInit() + { + // + delete mX121Helper; + + // + delete mBarAnalyser; + } + + /** + * Apply Chart Style ... + */ + void ApplyChartStyle() + { + // + // Retrieve Current Chart ID ... + long chartId = ChartID(); + + // + 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 + + // + ChartSetInteger(chartId, CHART_MODE, mMode); + ChartSetInteger(chartId, CHART_SHOW_BID_LINE, mShowBidLine); + ChartSetInteger(chartId, CHART_SHOW_ASK_LINE, mShowAskLine); + ChartSetInteger(chartId, CHART_SHOW_GRID, mShowGrid); + ChartSetInteger(chartId, CHART_SHOW_VOLUMES, mShowVolumes); + ChartSetInteger(chartId, CHART_SHOW_TRADE_LEVELS, mShowTradeLevels); + ChartSetInteger(chartId, CHART_AUTOSCROLL, mAutoScroll); + ChartSetInteger(chartId, CHART_QUICK_NAVIGATION, mQuickNavigation); + ChartSetInteger(chartId, CHART_COLOR_FOREGROUND, mForeGroundColor); + ChartSetInteger(chartId, CHART_COLOR_BACKGROUND, mBackGroundColor); + ChartSetInteger(chartId, CHART_COLOR_CHART_UP, mUpColor); + ChartSetInteger(chartId, CHART_COLOR_CHART_DOWN, mDownColor); + ChartSetInteger(chartId, CHART_COLOR_CANDLE_BULL, mBullishColor); + ChartSetInteger(chartId, CHART_COLOR_CANDLE_BEAR, mBearishColor); + ChartSetInteger(chartId, CHART_COLOR_GRID, mGridColor); + ChartSetInteger(chartId, CHART_COLOR_BID, mBidLineColor); + ChartSetInteger(chartId, CHART_COLOR_ASK, mAskLineColor); + ChartSetInteger(chartId, CHART_COLOR_STOP_LEVEL, mStopColor); + ChartSetInteger(chartId, CHART_COLOR_CHART_LINE, mLineColor); + ChartSetInteger(chartId, CHART_COLOR_VOLUME, mVolumesColor); + } + + /** + * Fill Pivot Tick Zone ... + * + * @param pivot: XPVPivot instance Reference ... + */ + void CalculatePivotTickZone( + XPVPivot &pivot // + ) + { + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + bool isInited = false; + + // + datetime from = pivot.from; + XOHCL iFromBar; + int iFromBarIndex = iBarShift( + symbol, + period, + from // + ); + isInited = iFromBar.Init( + symbol, + period, + iFromBarIndex // + ); + if (!isInited) + { + return; + } + + // + datetime to = pivot.to; + XOHCL iToBar; + int iToBarIndex = iBarShift( + symbol, + period, + to // + ); + isInited = iToBar.Init( + symbol, + period, + iToBarIndex // + ); + if (!isInited) + { + return; + } + + // + if (iFromBarIndex <= iToBarIndex) + { + return; + } + + // + XCTicksZone *iZone; + iZone = new XCTicksZone(); + + // + int ticksLevels = mPOIDetector.TicksRangeZoneLevel(); + int ticksRange = mPOIDetector.TicksRangeZoneRange(); + isInited = ticksLevels > 0 && + ticksRange > 0; + if (!isInited) + { + return; + } + + // + isInited = iZone.Init( + iFromBar, + iToBar // + ); + if (!isInited) + { + return; + } + + // + pivot.state.ticksZone = iZone; + } + + // + // Change Values Actions ... + + /** + * Add Specified Parabolic Sar Changed Item ... + * + * @param value: XValueChange instance Reference ... + * + * @return ( bool ) + */ + bool AddSarChange(XValueChange &value) + { + // + bool result = false; + + // + result = value.IsValid(); + if (!result) + { + return result; + } + + // + int beforeCount = CountSarChanges(); + + // + AddIfNotExists( + value, + mSarChanges // + ); + + // + int afterCount = CountSarChanges(); + + // + result = afterCount == beforeCount + 1; + if (result) + { + // + // Cleaning Up Unused Items ... + int maxAllowed = MaxAllowedSavedChanges(); + CleanupArray( + mSarChanges, + maxAllowed // + ); + } + + // + return result; + } + + /** + * Add Specified Peaks Changed Item ... + * + * @param value: XValueChange instance Reference ... + * + * @return ( bool ) + */ + bool AddPeaksChange(XValueChange &value) + { + // + bool result = false; + + // + result = value.IsValid(); + if (!result) + { + return result; + } + + // + int beforeCount = CountSarChanges(); + + // + AddIfNotExists( + value, + mPeaksChanges // + ); + + // + int afterCount = CountSarChanges(); + + // + result = afterCount == beforeCount + 1; + if (result) + { + // + // Cleaning Up Unused Items ... + int maxAllowed = MaxAllowedSavedChanges(); + CleanupArray( + mPeaksChanges, + maxAllowed // + ); + } + + // + return result; + } + + /** + * Add Specified Vales Changed Item ... + * + * @param value: XValueChange instance Reference ... + * + * @return ( bool ) + */ + bool AddValesChange(XValueChange &value) + { + // + bool result = false; + + // + result = value.IsValid(); + if (!result) + { + return result; + } + + // + int beforeCount = CountSarChanges(); + + // + AddIfNotExists( + value, + mValesChanges // + ); + + // + int afterCount = CountSarChanges(); + + // + result = afterCount == beforeCount + 1; + if (result) + { + // + // Cleaning Up Unused Items ... + int maxAllowed = MaxAllowedSavedChanges(); + CleanupArray( + mValesChanges, + maxAllowed // + ); + } + + // + return result; + } + + /** + * Add Specified VWap Order Changed Item ... + * + * @param value: XValueChange instance Reference ... + * + * @return ( bool ) + */ + bool AddVWapOrderChange(XValueChange &value) + { + // + bool result = false; + + // + result = value.IsValid(); + if (!result) + { + return result; + } + + // + int beforeCount = CountSarChanges(); + + // + AddIfNotExists( + value, + mVWapOrderChanges // + ); + + // + int afterCount = CountSarChanges(); + + // + result = afterCount == beforeCount + 1; + if (result) + { + // + // Cleaning Up Unused Items ... + int maxAllowed = MaxAllowedSavedChanges(); + CleanupArray( + mVWapOrderChanges, + maxAllowed // + ); + } + + // + return result; + } + + /** + * Add Specified VWap State Changed Item ... + * + * @param value: XValueChange instance Reference ... + * + * @return ( bool ) + */ + bool AddVWapStateChange(XValueChange &value) + { + // + bool result = false; + + // + result = value.IsValid(); + if (!result) + { + return result; + } + + // + int beforeCount = CountSarChanges(); + + // + AddIfNotExists( + value, + mVWapStateChanges // + ); + + // + int afterCount = CountSarChanges(); + + // + result = afterCount == beforeCount + 1; + if (result) + { + // + // Cleaning Up Unused Items ... + int maxAllowed = MaxAllowedSavedChanges(); + CleanupArray( + mVWapStateChanges, + maxAllowed // + ); + } + + // + return result; + } + + // +}; diff --git a/BKPS/14031003/X121SMCEA/Classes/x-121.smc.x-tradehandler.class.mq5 b/BKPS/14031003/X121SMCEA/Classes/x-121.smc.x-tradehandler.class.mq5 new file mode 100644 index 0000000..03f323e --- /dev/null +++ b/BKPS/14031003/X121SMCEA/Classes/x-121.smc.x-tradehandler.class.mq5 @@ -0,0 +1,4236 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XCX121SMCTradeHandler +// 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-bar.analyser.class.mq5" +#include "../../Classes/x-saherelm.x-trade.class.mq5" + +// +// Definitions ... + +// +// Model a Trade Data ... +struct X121SMCTradeData +{ + // + 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 + + // + bool forceTrail; // Force Trail + int trailStep; // Trail Step + bool partiallyClosed; // Partially Closed or not + datetime lastProtectedOn; // Last Protected On + + // + // Constructor ... + void X121SMCTradeData() + { + 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; + + // + trailStep = 0; + forceTrail = false; + lastProtectedOn = NULL; + partiallyClosed = false; + + // + signal.Clean(); + } + + // + // 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; + } + + // +}; + +// +// Model a Position and it's Protected Positions ... +struct X121SMCProtectedPosition +{ + // + XPosition main; // Main Position ... + X121SMCTradeData data; // Trade Handler Data ... + + // + XPosition supports[]; // Support Positions ... + + /** + * Count Supported Positions + */ + int CountSupports() + { + return ArraySize(supports); + } + + /** + * Extract All Positions into Specified Array + * of Positions ... + */ + int ExtractPositions( + XPosition &positions[] // + ) + { + // + int result = 0; + + // + Clean(positions); + + // + if (main.IsValid()) + { + // + AddRef( + main, + positions // + ); + } + + // + int supportsCount = CountSupports(); + if (IsValidSize(supportsCount)) + { + // + Copy( + supports, + positions, + false // + ); + } + + // + result = ArraySize(positions); + + // + return result; + } +}; + +// +struct X121SMCSymbolPositionInfo +{ + // + string symbol; + + // + datetime enableAt; + + // + int longSLs; + int longTPs; + + // + int shortSLs; + int shortTPs; + + // + int countedSLs; + + // + void X121SMCSymbolPositionInfo() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + longSLs = 0; + longTPs = 0; + + // + shortSLs = 0; + shortTPs = 0; + + // + countedSLs = 0; + + // + enableAt = NULL; + } + + /** + * Check is own Symbol Info ... + * + * @param _symbol: String ... + * + * @return ( bool ) + */ + bool IsOwn(string _symbol) + { + // + bool result = false; + + // + result = + // + IsValid(symbol) && + _symbol == symbol + // + ; + + // + return result; + } + + /** + * Check Symbol Trading is Enable or not ... + * + * @param time: DateTime ... + * + * @return ( bool ) + */ + bool IsEnable(datetime time = NULL) + { + // + bool result = false; + + // + time = NormalizeTime(time); + + // + bool isEnableAtValid = IsValid(enableAt); + + // + result = + !isEnableAtValid + ? true + : time > enableAt; + if (result && + isEnableAtValid) + { + Reset(); + } + + // + return result; + } + + /** + * Pause Symbol Trading ... + * + * @param seconds: Integer ... + */ + void Pause(int seconds) + { + // + if (seconds <= 0) + { + return; + } + + // + datetime _enableAt = ((datetime)((int)TimeCurrent() + seconds)); + enableAt = _enableAt; + } + + /** + * Handle Stop Loss ... + * + * @param _type: ENUM_POSITION_TYPE member ... + */ + void HandleSL(ENUM_POSITION_TYPE _type) + { + // + bool isLong = IsLong(_type); + if (isLong) + { + longSLs++; + } + else + { + shortSLs++; + } + + // + countedSLs++; + } + + /** + * Handle Take Profit ... + * + * @param _type: ENUM_POSITION_TYPE member ... + */ + void HandleTP(ENUM_POSITION_TYPE _type) + { + // + bool isLong = IsLong(_type); + if (isLong) + { + longTPs++; + } + else + { + shortTPs++; + } + + // + countedSLs--; + if (countedSLs < 0) + { + countedSLs = 0; + } + } + + /** + * Reset Counter ... + */ + void Reset() + { + // + countedSLs = 0; + enableAt = NULL; + } + + // +}; + +// +// Implementations ... + +// +// a Class For Read and Write Trade Info Data in Files ... +class X121SMCTradeCollector +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructor(s) ... + void X121SMCTradeCollector( + string _path = NULL // Base Path + ) + { + // + mAccount = new XCAccount(); + + // + if (IsValid(_path)) + { + mPath = _path; + } + else + { + mPath = "X121SMCTradeData" + "\\" + mAccount.GetCompany(); + } + } + + // + // Deconstructor ... + void ~X121SMCTradeCollector() + { + } + + // + bool IsExists(X121SMCTradeData &item) + { + // + bool result = false; + + // + int mHandler = GetFileHandlerForRead(item); + result = mHandler != INVALID_HANDLE; + FileClose(mHandler); + + // + return result; + } + + // + bool Save(X121SMCTradeData &item) + { + // + bool result = false; + + // + // Check info is Valid ... + result = item.IsValid(); + if (!result) + { + return result; + } + + // + string content = item.ToString(); + content += "\n" + "-----------" + "\n" + "Signal: " + "\n" + "-----------" + "\n" + item.ToString(true); + + // + result = IsValid(content); + if (!result) + { + return result; + } + + // + int mHandler = GetFileHandlerForWrite(item); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + FileWrite(mHandler, content); + FileFlush(mHandler); + FileClose(mHandler); + + // + return result; + } + + // + bool SaveSignal(X121SMCTradeData &item) + { + // + bool result = false; + + // + string content = item.ToString(true); + result = IsValid(content); + if (!result) + { + return result; + } + + // + int mHandler = GetSignalFileHandlerForWrite(item); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + FileWrite(mHandler, content); + FileFlush(mHandler); + FileClose(mHandler); + + // + return result; + } + + // + // Conditions only save for Loss Signals ... + // this means the profit must be Lower than Zero ... + // ans also message Contains SL ... + bool SaveConditions(X121SMCTradeData &item) + { + // + bool result = false; + + // + // Validate Item ... + result = + // + item.profit < 0 && + Contains("SL", item.message) + // + ; + if (!result) + { + return result; + } + + // + string content = item.signal.conditions; + result = IsValid(content); + if (!result) + { + return result; + } + + // + int mHandler = GetConditionsFileHandlerForWrite(item); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + FileSeek(mHandler, 0, SEEK_END); + FileWrite(mHandler, content); + FileFlush(mHandler); + FileClose(mHandler); + + // + return result; + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + + // + string mPath; // Base Path ... + + // + XCAccount *mAccount; + + // + string GetFilePath(X121SMCTradeData &item) + { + // + string fileName = item.GetFileName(); + + // + return GetFilePath(fileName); + } + string GetFilePath(string fileName) + { + // + string result = ""; + + // + result = + // + mPath + "\\" + "Trades" + "\\" + fileName + ".x121.log" + // + ; + + // + return result; + } + + // + string GetSignalFilePath(X121SMCTradeData &item) + { + // + string fileName = item.GetSignalFileName(); + + // + return GetSignalFilePath(fileName); + } + string GetSignalFilePath(string fileName) + { + // + string result = ""; + + // + result = + // + mPath + "\\" + "Signals" + "\\" + fileName + ".x121.log" + // + ; + + // + return result; + } + + // + string GetConditionsFilePath(X121SMCTradeData &item) + { + // + bool isLong = IsLong(item.type); + + // + string fileName = + item.symbol + "\\" + + (isLong ? "Longs" : "Shorts"); + + // + return GetConditionsFilePath(fileName); + } + string GetConditionsFilePath(string fileName) + { + // + string result = ""; + + // + result = + // + mPath + "\\" + "Conditions" + "\\" + fileName + ".x121.log" + // + ; + + // + return result; + } + + // + int GetFileHandlerForRead(X121SMCTradeData &item) + { + // + int result = INVALID_HANDLE; + + // + string filePath = GetFilePath(item); + if (!IsValid(filePath)) + { + return result; + } + + // + result = FileOpen( + filePath, + FILE_READ | FILE_TXT // + ); + + // + return result; + } + int GetFileHandlerForWrite(X121SMCTradeData &item) + { + // + int result = INVALID_HANDLE; + + // + string filePath = GetFilePath(item); + if (!IsValid(filePath)) + { + return result; + } + + // + result = FileOpen( + filePath, + FILE_READ | FILE_WRITE | FILE_TXT // + ); + + // + return result; + } + + // + int GetSignalFileHandlerForRead(X121SMCTradeData &item) + { + // + int result = INVALID_HANDLE; + + // + string filePath = GetSignalFilePath(item); + if (!IsValid(filePath)) + { + return result; + } + + // + result = FileOpen( + filePath, + FILE_READ | FILE_TXT // + ); + + // + return result; + } + int GetSignalFileHandlerForWrite(X121SMCTradeData &item) + { + // + int result = INVALID_HANDLE; + + // + string filePath = GetSignalFilePath(item); + if (!IsValid(filePath)) + { + return result; + } + + // + result = FileOpen( + filePath, + FILE_READ | FILE_WRITE | FILE_TXT // + ); + + // + return result; + } + + // + int GetConditionsFileHandlerForRead(X121SMCTradeData &item) + { + // + int result = INVALID_HANDLE; + + // + string filePath = GetConditionsFilePath(item); + if (!IsValid(filePath)) + { + return result; + } + + // + result = FileOpen( + filePath, + FILE_READ | FILE_TXT // + ); + + // + return result; + } + int GetConditionsFileHandlerForWrite(X121SMCTradeData &item) + { + // + int result = INVALID_HANDLE; + + // + string filePath = GetConditionsFilePath(item); + if (!IsValid(filePath)) + { + return result; + } + + // + result = FileOpen( + filePath, + FILE_READ | FILE_WRITE | FILE_TXT // + ); + + // + return result; + } +}; + +// +// Trade Handler Class ... +class XC121SMCTradeHandler : public XCBaseAlert +{ + // + // Public ... + public: + // + + // + // Constructor(s) ... + void XC121SMCTradeHandler(XCTrade *trader) + { + // + mTrader = trader; + mAdditionalVolume = 0; + mCollector = new X121SMCTradeCollector(); + } + + // + // Deconstructor ... + void ~XC121SMCTradeHandler() + { + // + delete mTrader; + delete mCollector; + } + + // + // Getter(s) / Setter(s) ... + + // + bool SaveSignals() + { + return mSaveSignals; + } + + // + void SaveSignals(bool value) + { + mSaveSignals = value; + } + + // + bool SaveTrades() + { + return mSaveTrades; + } + + // + void SaveTrades(bool value) + { + mSaveTrades = value; + } + + // + bool SaveConditions() + { + return mSaveConditions; + } + + // + void SaveConditions(bool value) + { + mSaveConditions = value; + } + + // + bool AllowLong() + { + return mAllowLong; + } + + // + void AllowLong(bool value) + { + mAllowLong = value; + } + + // + bool AllowShort() + { + return mAllowShort; + } + + // + void AllowShort(bool value) + { + mAllowShort = value; + } + + // + int MaxAllowedLongs() + { + return mMaxAllowedLongs; + } + + // + void MaxAllowedLongs(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mMaxAllowedLongs = value; + } + + // + int MaxAllowedShorts() + { + return mMaxAllowedShorts; + } + + // + void MaxAllowedShorts(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mMaxAllowedShorts = value; + } + + // + bool UseMaxAllowedTradesPerSymbol() + { + return mUseMaxAllowedTradesPerSymbol; + } + + // + void UseMaxAllowedTradesPerSymbol(bool value) + { + mUseMaxAllowedTradesPerSymbol = value; + } + + // + double MaxDrawdownPercentForOpenTrades() + { + return mMaxDrawdownPercentForOpenTrades; + } + + // + void MaxDrawdownPercentForOpenTrades(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mMaxDrawdownPercentForOpenTrades = value; + } + + // + // Protector Start ... + + // + bool UseForceMomentumsInProtection() + { + return mUseForceMomentumsInProtection; + } + + // + void UseForceMomentumsInProtection(bool value) + { + mUseForceMomentumsInProtection = value; + } + + // + int DelayBarBetweenTwoSignal() + { + return mDelayBarBetweenTwoSignal; + } + + // + void DelayBarBetweenTwoSignal(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mDelayBarBetweenTwoSignal = value; + } + + // + int MaxAllowedSLToPause() + { + return mMaxAllowedSLToPause; + } + + // + void MaxAllowedSLToPause(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mMaxAllowedSLToPause = value; + } + + // + int MaxAllowedSLReachedPauseDelay() + { + return mMaxAllowedSLReachedPauseDelay; + } + + // + void MaxAllowedSLReachedPauseDelay(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mMaxAllowedSLReachedPauseDelay = value; + } + + // + double AcceptNextSameTypeSignalWhenLastInProfit() + { + return mAcceptNextSameTypeSignalWhenLastInProfit; + } + + // + void AcceptNextSameTypeSignalWhenLastInProfit(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mAcceptNextSameTypeSignalWhenLastInProfit = value; + } + + // + // In Profit Position Protecting ... + + // + // Trail ... + + // + bool AllowTrail() + { + return mAllowTrail; + } + + // + void AllowTrail(bool value) + { + mAllowTrail = value; + } + + // + double TrailStartDistance() + { + return mTrailStartDistance; + } + + // + void TrailStartDistance(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mTrailStartDistance = value; + } + + // + double TrailStep() + { + return mTrailStep; + } + + // + void TrailStep(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mTrailStep = value; + } + + // + int RemoveTPAfterTrailedLevel() + { + return mRemoveTPAfterTrailedLevel; + } + + // + void RemoveTPAfterTrailedLevel(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mRemoveTPAfterTrailedLevel = value; + } + + // + bool OnlyTrailUnprotected() + { + return mOnlyTrailUnprotected; + } + + // + void OnlyTrailUnprotected(bool value) + { + mOnlyTrailUnprotected = value; + } + + // + // Partial Close (In Profit) ... + + // + double PartialCloseInProfitDistance() + { + return mPartialCloseInProfitDistance; + } + + // + void PartialCloseInProfitDistance(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mPartialCloseInProfitDistance = value; + } + + // + double PartialCloseInProfitVolume() + { + return mPartialCloseInProfitVolume; + } + + // + void PartialCloseInProfitVolume(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mPartialCloseInProfitVolume = value; + } + + // + // In Drawdown Positions Protecting ... + + // + // Protect ... + + // + bool AllowProtect() + { + return mAllowProtect; + } + + // + void AllowProtect(bool value) + { + mAllowProtect = value; + } + + // + double ProtectionStartDistance() + { + return mProtectionStartDistance; + } + + // + void ProtectionStartDistance(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mProtectionStartDistance = value; + } + + // + int ProtectionDelay() + { + return mProtectionDelay; + } + + // + void ProtectionDelay(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mProtectionDelay = value; + } + + // + double ProtectionVolumeMultiplier() + { + return mProtectionVolumeMultiplier; + } + + // + void ProtectionVolumeMultiplier(double value) + { + // + if (value < 1) + { + value = 1; + } + + // + mProtectionVolumeMultiplier = value; + } + + // + int MaxAllowedProtection() + { + return mMaxAllowedProtection; + } + + // + void MaxAllowedProtection(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mMaxAllowedProtection = value; + } + + // + bool UseEntryAsProtectionSL() + { + return mUseEntryAsProtectionSL; + } + + // + void UseEntryAsProtectionSL(bool value) + { + mUseEntryAsProtectionSL = value; + } + + // + bool ProtectOnConditions() + { + return mProtectOnConditions; + } + + // + void ProtectOnConditions(bool value) + { + mProtectOnConditions = value; + } + + // + bool AllowDirectionProtct() + { + return mAllowDirectionProtct; + } + + // + void AllowDirectionProtct(bool value) + { + mAllowDirectionProtct = value; + } + + // + // Partial Close (In Drawdown) ... + + // + double PartialCloseInDrawdownDistance() + { + return mPartialCloseInDrawdownDistance; + } + + // + void PartialCloseInDrawdownDistance(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mPartialCloseInDrawdownDistance = value; + } + + // + double PartialCloseInDrawdownVolume() + { + return mPartialCloseInDrawdownVolume; + } + + // + void PartialCloseInDrawdownVolume(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mPartialCloseInDrawdownVolume = value; + } + + // + // Hedge Props ... + + // + bool AllowHedge() + { + return mAllowHedge; + } + + // + void AllowHedge(bool value) + { + mAllowHedge = value; + } + + // + double HedgeMinVolumeStep() + { + return mHedgeMinVolumeStep; + } + + // + // Min: 0.01 + // Max 0.1 + void HedgeMinVolumeStep(double value) + { + // + if (value < 0.01) + { + value = 0.01; + } + + // + if (value > 0.1) + { + value = 0.1; + } + + // + mHedgeMinVolumeStep = value; + } + + // + int MinimumOpenPositionsForHEHedge() + { + return mMinimumOpenPositionsForHEHedge; + } + + // + void MinimumOpenPositionsForHEHedge(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mMinimumOpenPositionsForHEHedge = value; + } + + // + double HedgeHEMinProfitPerVolumeStep() + { + return mHedgeHEMinProfitPerVolumeStep; + } + + // + // Min: 0.01 + void HedgeHEMinProfitPerVolumeStep(double value) + { + // + if (value < 0.01) + { + value = 0.01; + } + + // + mHedgeHEMinProfitPerVolumeStep = value; + } + + // + double HedgeBEMinProfitPerVolumeStep() + { + return mHedgeBEMinProfitPerVolumeStep; + } + + // + // Min: 0.01 + void HedgeBEMinProfitPerVolumeStep(double value) + { + // + if (value < 0.01) + { + value = 0.01; + } + + // + mHedgeBEMinProfitPerVolumeStep = value; + } + + // + // Read Only Props ... + + // + int MaxSameTimeTrades() + { + return maxSameTimeTrades; + } + + // + // Calculate Max Drawdown and it's Percent ... + double GetMaxDrawdown() + { + // + XPosition positions[]; + int positionsCount = mTrader.GetPositions(positions); + if (IsValidSize(positionsCount)) + { + double mEquity = mTrader.mAccount.GetEquity(); + if (mEquity > maxDrawdown) + { + maxDrawdown = mEquity; + } + + // + drawdownPercent = (maxDrawdown - mEquity) / (staticBalanceForCalculateDrawdown > 0 ? staticBalanceForCalculateDrawdown : maxDrawdown) * 100; + drawdownPercent = NormalizeDouble(drawdownPercent, 3); + } + else + { + // + maxDrawdown = 0.0; + drawdownPercent = 0.0; + } + + // + return drawdownPercent; + } + + // + double AdditionalVolume() + { + return mAdditionalVolume; + } + + // + // Position Retrievers ... + + /** + * Retrieve Positions as XProtetedPosition structure + * @param positions: Argument 1 + * @return ( int ) + */ + int GetPositions( + X121SMCProtectedPosition &positions[] // + ) + { + // + int result = 0; + + // + Clean(positions); + + // + // Retrieve Positions from Trader Class ... + XPosition allPositions[]; + int allPositionsCount = mTrader.GetPositions( + allPositions, + NULL, // All Symbols ... + NULL, // All Providers ... + NULL, // All Periods ... + X_POSITION_TYPE_ALL, // Long and Short ... + false, // Filter By Magic ... + true // Force Clean ... + ); + if (!IsValidSize(allPositionsCount)) + { + return result; + } + + // + // Filter Support Positions ... + XPosition mainPositions[]; + XPosition supportPositions[]; + for (int i = 0; i < allPositionsCount; i++) + { + // + XPosition iPosition = allPositions[i]; + + // + // Check Validation ... + if (!iPosition.IsValid()) + { + continue; + } + + // + // Check Position Support or not ... + bool isSupport = IsSupport(iPosition.comment); + if (isSupport) + { + // + AddRef( + iPosition, + supportPositions // + ); + continue; + } + + // + AddRef( + iPosition, + mainPositions // + ); + } + + // + // Check Main Positions Count ... + int mainPositionsCount = ArraySize(mainPositions); + if (!IsValidSize(mainPositionsCount)) + { + return result; + } + + // + int supportPositionsCount = ArraySize(supportPositions); + + // + for (int i = 0; i < mainPositionsCount; i++) + { + // + XPosition iPosition = mainPositions[i]; + + // + X121SMCProtectedPosition iProtected; + iProtected.main = iPosition; + Clean(iProtected.supports); + + // + // Loop Through Support Positions To Find iPositions Support ... + if (IsValidSize(supportPositionsCount)) + { + // + for (int j = 0; j < supportPositionsCount; j++) + { + // + XPosition jSupport = supportPositions[j]; + + // + ulong supportParentTicket = ExtractSupportedTicket(jSupport.comment); + bool isSupport = supportParentTicket > 0; + if (isSupport && + supportParentTicket == iPosition.ticket) + { + // + AddRef( + jSupport, + iProtected.supports // + ); + } + + // + ulong eqmSupportParentTicket = ExtractEQMSupportedTicket(jSupport.comment); + bool isEQMSupport = eqmSupportParentTicket > 0; + if (isEQMSupport && + eqmSupportParentTicket == iPosition.ticket) + { + // + AddRef( + jSupport, + iProtected.supports // + ); + } + } + } + + // + // Findout X121SMCTradeData ... + int iIDX = -1; + bool hasItem = HasItem( + iPosition.ticket, + iIDX // + ); + if (hasItem && IsValidIndex(iIDX)) + { + iProtected.data = mData[iIDX]; + } + + // + AddRef( + iProtected, + positions // + ); + } + + // + Clean(allPositions); + Clean(mainPositions); + Clean(supportPositions); + + // + result = ArraySize(positions); + + // + return result; + } + + // + // Trade Handling Functions ... + + // + // First Step of Trade Handling ... + // Since Must Call when a Signal Executed ... + void AddData( + XSignal &signal, // Executed Signal + double commission = 0, // Commission + // + // Force Protections ... + bool forceTrail = false // Force Trail Stops ... + ) + { + // + // Check Signal Valid ... + if (!signal.IsValid()) + { + return; + } + + // + // Check Signal Support or Recovery ... + bool isSupport = IsSupport(signal.comment); + bool isRecovery = ExtractRecoveredTicket(signal.comment) > 0; + + // + X121SMCTradeData item; + bool isFilled = item.Fill(signal); + if (!isFilled) + { + return; + } + + // + item.commission = commission; + + // + // Checking Trailling Configs ... + double trailStep = TrailStep(); + double trailStartDistance = TrailStartDistance(); + bool enableTrail = + trailStep > 0 && + trailStartDistance > 0; + + // + bool onlyTrailUnprotecteds = OnlyTrailUnprotected(); + bool canCheck = + (onlyTrailUnprotecteds + ? !isSupport && + !isRecovery + : true) && + enableTrail; + if (canCheck) + { + item.forceTrail = forceTrail; + } + + // + Add(item); + + // + SaveSignal(item); + } + + // + void Finish(const XDeal &deal) + { + // + int idx = -1; + bool hasItem = HasItem( + deal.positionId, + idx // + ); + if (!hasItem) + { + return; + } + + // + // Update Item Info ... + mData[idx].swap = deal.swap; + mData[idx].endTime = deal.time; + mData[idx].profit = deal.profit; + + // + bool isTP = deal.reason == DEAL_REASON_TP; + bool isSL = deal.reason == DEAL_REASON_SL; + + // + mData[idx].message = + isTP + ? "TP" + : isSL + ? "SL" + : ""; + + // + if (isTP || isSL) + { + // + int symbolIDX = -1; + bool hasInfo = HasSymbol( + mData[idx].symbol, + symbolIDX // + ); + + // + X121SMCSymbolPositionInfo info; + if (!hasInfo) + { + // + // Add New One ... + info.symbol = mData[idx].symbol; + } + else + { + // + // Update Exists ... + info = mSymbolInfos[symbolIDX]; + + // + // Remove Exists ... + ArrayRemove( + mSymbolInfos, + symbolIDX, + 1 // + ); + } + + // + ENUM_POSITION_TYPE xType = IsLong(mData[idx].type) + ? POSITION_TYPE_BUY + : POSITION_TYPE_SELL; + if (isTP) + { + info.HandleTP(xType); + } + else if (isSL) + { + info.HandleSL(xType); + } + + // + AddRef( + info, + mSymbolInfos // + ); + + // + HandlePauseSymbol(mData[idx].symbol); + } + + // + Save(idx); + } + + // + void Finish( + const ulong ticket, + const XPosition &position, + const string comment // + ) + { + // + int idx = -1; + bool hasItem = HasItem( + ticket, + idx // + ); + if (!hasItem) + { + return; + } + + // + // Update Item Info ... + mData[idx].swap = position.swap; + mData[idx].endTime = TimeCurrent(); + mData[idx].profit = position.profit; + + // + mData[idx].message = comment; + + // + bool handleForceClose = true; + if (handleForceClose) + { + // + bool isTP = position.profit > 0; + bool isSL = position.profit < 0; + + // + if (isTP || isSL) + { + // + int symbolIDX = -1; + bool hasInfo = HasSymbol( + mData[idx].symbol, + symbolIDX // + ); + + // + X121SMCSymbolPositionInfo info; + if (!hasInfo) + { + // + // Add New One ... + info.symbol = mData[idx].symbol; + } + else + { + // + // Update Exists ... + info = mSymbolInfos[symbolIDX]; + + // + // Remove Exists ... + ArrayRemove( + mSymbolInfos, + symbolIDX, + 1 // + ); + } + + // + ENUM_POSITION_TYPE xType = IsLong(mData[idx].type) + ? POSITION_TYPE_BUY + : POSITION_TYPE_SELL; + if (isTP) + { + info.HandleTP(xType); + } + else if (isSL) + { + info.HandleSL(xType); + } + + // + AddRef( + info, + mSymbolInfos // + ); + + // + HandlePauseSymbol(mData[idx].symbol); + } + + // + Save(idx); + } + } + + // + // this Method call's by a Timer, + // or in OnTick for Update Positions, + // Data ... + void UpdateData() + { + // + XPosition positions[]; + int count = mTrader.GetPositions(positions); + if (!IsValidSize(count)) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + XPosition iPosition = positions[i]; + + // + int idx = -1; + bool isExists = HasItem( + iPosition.ticket, + idx // + ); + if (!isExists) + { + // + // Add New Data ... + + // + // Find Executed Signal Deal History ... + XDeal deals[]; + double commission = 0; + int dealsCount = mTrader.GetDeals( + deals, + iPosition.symbol, + iPosition.provider, + iPosition.period, + NULL, + DEAL_ENTRY_IN // + ); + if (IsValidSize(dealsCount)) + { + // + for (int i = 0; i < dealsCount; i++) + { + // + XDeal iDeal = deals[i]; + if (iDeal.positionId == iPosition.ticket) + { + // + commission = iDeal.commission; + break; + } + } + } + + // + X121SMCTradeData iData; + iData.Fill( + iPosition // + ); + + // + iData.ticket = iPosition.ticket; + + // + Add(iData); + } + else + { + // + // Update Exists ... + mData[idx].Update(iPosition); + } + } + + // + count = Count(); + if (count > maxSameTimeTrades) + { + maxSameTimeTrades = count; + } + + // + GetMaxDrawdown(); + } + + // + void UpdateSignal(XSignal &signal) + { + // + if (!signal.IsValid()) + { + return; + } + + // + int count = Count(); + if (!IsValidSize(count)) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + bool isOwn = mData[i].IsOwn( + signal.symbol, + signal.provider, + signal.period, + ToPositionType(signal.type) // + ); + if (isOwn) + { + mData[i].Fill(signal); + } + } + } + + // + void RemoveSignal(XSignal &signal) + { + // + if (!signal.IsValid()) + { + return; + } + + // + int signalIDX = -1; + ENUM_X_POSITION_TYPES xType = ToPositionType(signal.type); + bool hasSignal = HasItem( + signal.symbol, + signal.provider, + signal.period, + xType, + signalIDX // + ); + if (!hasSignal || !IsValidIndex(signalIDX)) + { + return; + } + + // + // Remove Item From List ... + ArrayRemove( + mData, + signalIDX, + 1 // + ); + } + + /** + * Retrieve Specified Symbols Info ... + * + * @param symbol: String ... + * @param info: X121SMCSymbolPositionInfo instance ... + * + * @return ( bool ) + */ + bool GetSymbolInfo( + string symbol, + X121SMCSymbolPositionInfo &info // + ) + { + // + bool result = false; + + // + info.Clean(); + + // + int symbolIDX = -1; + result = HasSymbol( + symbol, + symbolIDX // + ); + if (!result) + { + return result; + } + + // + info = mSymbolInfos[symbolIDX]; + + // + return result; + } + + /** + * Reset Specified Symbol Info ... + * + * @param symbol: String ... + */ + void ResetSymbolInfo(string symbol) + { + // + if (!IsValid(symbol)) + { + return; + } + + // + int symbolIDX = -1; + bool hasSymbol = HasSymbol( + symbol, + symbolIDX // + ); + if (!hasSymbol) + { + return; + } + + // + mSymbolInfos[symbolIDX].Reset(); + } + + // + // Position Execute and Sync Functions ... + + /** + * Validate Signal For Execution ... + */ + bool CanExecute(XSignal &signal) + { + // + bool result = false; + + // + // Validate Signal ... + result = signal.IsValid(); + if (!result) + { + return result; + } + + // + int symbolIDX = -1; + bool hasSymbolInfo = HasSymbol( + signal.symbol, + symbolIDX // + ); + + // + // Check rading Not Paused ... + result = + !hasSymbolInfo || + mSymbolInfos[symbolIDX].IsEnable(); + if (!result) + { + return result; + } + + // + bool isLong = IsLong(signal.type); + + // + // Chekc Signalling Enable or not ... + result = + isLong + ? mAllowLong + : mAllowShort; + if (!result) + { + return result; + } + + // + // Check Signal is Support or not ... + bool isSupport = IsSupport(signal.comment); + result = !isSupport; + if (!result) + { + return result; + } + + // + ENUM_X_POSITION_TYPES pType = ToPositionType(signal.type); + double requiredProfitForAcceptNext = AcceptNextSameTypeSignalWhenLastInProfit(); + + // + // Implement Same Signal Conditions ... + XPosition smaeSymbolPositions[]; + int sameSymbolPositionsCount = mTrader.GetPositions( + smaeSymbolPositions, + signal.symbol, + signal.provider, + signal.period, + pType, + true, // Filter By Magic ... + true // Force Clean ... + ); + XPosition youngestSame; + int youngestSameAge = GetYoungest( + youngestSame, + smaeSymbolPositions // + ); + + // + double youngestSameProfitInPoint = youngestSame.GetProfitInPoint(); + + // + result = + sameSymbolPositionsCount == 0 || + (sameSymbolPositionsCount <= 0 + ? true + : requiredProfitForAcceptNext <= 0 + ? true + : youngestSameAge >= 0 && + youngestSameProfitInPoint >= requiredProfitForAcceptNext); + + // + return result; + } + + /** + * Execute Specific Signal using Trade Handler ... + */ + bool ExecuteSignal( + XSignal &signal, // Signal for Execution + ENUM_X_SIGNAL_EXECUTION_RESULT &state, // Execution State + bool ignorePolicies = false, // Ignore Execution Policies + // + // Force Protections ... + bool forceTrail = false // Force Trail Position + ) + { + // + bool result = false; + + // + // Check Signal Validation ... + result = signal.IsValid(); + if (!result) + { + return result; + } + + // + // Check Policies ... + if (!ignorePolicies) + { + // + // Filter Signals if Necessary ... + result = CanExecute(signal); + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_INVALID_PARAMS; + return result; + } + + // + bool isLong = IsLong(signal.type); + + // + // Check Allow Trade Type ... + result = + isLong + ? mAllowLong + : mAllowShort; + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_NOT_ALLOWED; + return result; + } + + // + XPosition longs[]; + XPosition shorts[]; + + // + // Counting Positions ... + if (mUseMaxAllowedTradesPerSymbol) + { + // + mTrader.GetPositions( + longs, + shorts, + signal.symbol // + ); + } + else + { + // + mTrader.GetPositions( + longs, + shorts, + NULL // All Symbols ... + ); + } + + // + int longsCount = ArraySize(longs); + int shortsCount = ArraySize(shorts); + + // + // Check Trades Count ... + if (mMaxAllowedLongs > 0 || mMaxAllowedShorts > 0) + { + // + result = + // + // Long ... + isLong + ? mMaxAllowedLongs <= 0 + ? true + : longsCount < mMaxAllowedLongs + // + // Short ... + : mMaxAllowedShorts <= 0 + ? true + : shortsCount < mMaxAllowedShorts + // + ; + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_MAX_REACHED; + return result; + } + } + + // + // Check Position Delays ... + if (result && mDelayBarBetweenTwoSignal > 0) + { + // + int youngestAge = 0; + XPosition youngestPosition; + + // + // Long Positions when there are Longs ... + if (isLong && longsCount > 0) + { + // + youngestAge = GetYoungest( + youngestPosition, + longs // + ); + } + // + // Short Positions when there are Shorts ... + else if (!isLong && shortsCount > 0) + { + // + youngestAge = GetYoungest( + youngestPosition, + shorts // + ); + } + + // + // Only Check when there is must to check and conditions happens ... + if (youngestAge > 0 && youngestPosition.IsValid()) + { + // + result = youngestAge >= mDelayBarBetweenTwoSignal; + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_MAX_REACHED; + return result; + } + } + + // + if (!youngestPosition.IsValid()) + { + // + int symbolIDX = FindLastExecutedSignalItem(signal); + if (IsValidIndex(symbolIDX)) + { + // + datetime cTime = TimeCurrent(); + int signalPeriodSeconds = PeriodSeconds(signal.period); + datetime lastExecutedTime = mLastExecutedSignals[symbolIDX].time; + datetime passedTime = ((datetime)lastExecutedTime + + ((mDelayBarBetweenTwoSignal * signalPeriodSeconds))); + + // + result = cTime >= passedTime; + if (!result) + { + return result; + } + } + } + } + + // + // Check Drawdown ... + if (mMaxDrawdownPercentForOpenTrades > 0) + { + // + drawdownPercent = GetMaxDrawdown(); + + // + result = + drawdownPercent <= 0 + ? true + : drawdownPercent < mMaxDrawdownPercentForOpenTrades; + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_NO_EQUITY; + return result; + } + } + } + + // + // Add Additional Volume to Signal ... + signal.volume += mAdditionalVolume; + + // + // Execute Signal ... + result = mTrader.ExecuteSignal( + signal, + state // + ); + if (result) + { + // + double commission = mTrader.GetPositionCommission(signal.positionId); + + // + // Add Signal to Trade Handler ... + AddData( + signal, + commission, + forceTrail // + ); + + // + HandleSignalExecuted(signal); + + // + string msg = (signal.type == POSITION_TYPE_BUY ? "Long" : "Short") + + " Signal Provided by: " + signal.provider + + (signal.pushers > 1 ? " Pushers: " + ToString(signal.pushers) : "") + + " on: " + signal.symbol + + " in: " + ToString(signal.period) + + " Executed Successfully ..."; + Alert(msg); + } + + // + return result; + } + + // + // Protection Functions ... + + /** + * Handle Positiona Protections + */ + void HandleProtection() + { + // + // Retrieve Positions ... + X121SMCProtectedPosition pPositions[]; + int pPositionsCount = GetPositions( + pPositions // + ); + + // + // Validate Count ... + if (!IsValidSize(pPositionsCount)) + { + return; + } + + // + bool isHedged = HandleHedge(pPositions); + if (isHedged) + { + // + // Renew Data ... + Clean(pPositions); + int pPositionsCount = GetPositions( + pPositions // + ); + + // + // Validate Count ... + if (!IsValidSize(pPositionsCount)) + { + return; + } + + // + return; + } + + // + int protectedPositions = 0; + for (int i = 0; i < pPositionsCount; i++) + { + // + // Check Position is Protectable or not ... + X121SMCProtectedPosition iProtected = pPositions[i]; + XPosition iPosition = iProtected.main; + + // + bool isProtected = HandlePositionProtecting( + iPosition, + iProtected.supports, + pPositions // + ); + if (isProtected) + { + protectedPositions++; + } + } + + // + if (protectedPositions > 0) + { + // + // Renew Data ... + Clean(pPositions); + int pPositionsCount = GetPositions( + pPositions // + ); + + // + // Validate Count ... + if (!IsValidSize(pPositionsCount)) + { + return; + } + } + } + + /** + * Reset All Paused Symbols ... + */ + void ResumePausedSymbols() + { + // + int count = ArraySize(mSymbolInfos); + if (!IsValidSize(count)) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + mSymbolInfos[i].Reset(); + } + + // + string message = "Force Resume Paused Symbols ..."; + Alert(message); + } + + // + // Protected ... + protected: + // + XCTrade *mTrader; // Instance of Trader Class + X121SMCTradeCollector *mCollector; // Instance of Trade Collector Class + + // + X121SMCTradeData mData[]; // Hold Trade Data + + // + // Hedge Related Functions ... + + /** + * Handle Hedging On Positions ... + */ + bool HandleHedge(X121SMCProtectedPosition &positions[]) + { + // + bool result = false; + + // + // Check Hedging is Enabled Or Not ... + result = AllowHedge(); + if (!result) + { + return result; + } + + // + // Check Minimum Volume Step is Provided or not ... + double minVolumeStep = HedgeMinVolumeStep(); + result = minVolumeStep > 0; + if (!result) + { + return result; + } + + // + // Check Positions ... + int positionsCount = ArraySize(positions); + result = IsValidSize(positionsCount); + if (!result) + { + return result; + } + + // + // Calculate Required Info ... + double swaps = 0; // Summary of Positions Swaps ... + double profits = 0; // Summary of Positions and Supports Profits ... + double volumes = 0; // Summary of Positions and Supports Volumes ... + int supportsCount = 0; // Number of Protecting Positions ... + double commissions = 0; // Summary of Positions and Supports Commissions ... + XPosition flatPositions[]; // Flat Positions ... + for (int i = 0; i < positionsCount; i++) + { + // + X121SMCProtectedPosition iProtected = positions[i]; + + // + XPosition iPositions[]; + int iPositionsCount = iProtected.ExtractPositions(iPositions); + if (IsValidSize(iPositionsCount)) + { + // + Copy( + iPositions, + flatPositions, + false // + ); + } + + // + // Collect Main Positions Data ... + swaps += iProtected.main.swap; + profits += iProtected.main.profit; + volumes += iProtected.main.volume; + commissions += mTrader.GetPositionCommission(iProtected.main.ticket); + + // + int iSupportsCount = iProtected.CountSupports(); + supportsCount += iSupportsCount; + + // + if (IsValidSize(iSupportsCount)) + { + // + // Collectiong Supports Positions Data ... + for (int j = 0; j < iSupportsCount; j++) + { + // + XPosition jSupport = iProtected.supports[j]; + + // + swaps += jSupport.swap; + profits += jSupport.profit; + volumes += jSupport.volume; + + // + commissions += mTrader.GetPositionCommission(jSupport.ticket); + } + } + } + + // + // First Step is Handle HE Hedge ... + + // + int minOpenPositions = MinimumOpenPositionsForHEHedge(); + double heMinProfitPerVolumeStep = HedgeHEMinProfitPerVolumeStep(); + double beMinProfitPerVolumeStep = HedgeBEMinProfitPerVolumeStep(); + + // + // Check HE Hedge Conditions ... + bool allowHEHedge = minOpenPositions > 0 && heMinProfitPerVolumeStep > 0; + if (allowHEHedge) + { + // + // Implement HE Hedge ... + + // + // Check Main Positions Count and also not Support Positions ... + result = supportsCount == 0 && + positionsCount >= minOpenPositions; + if (result) + { + // + // Check Profits ... + result = profits > 0; + if (result) + { + // + // Calculate Required Profit ... + double volumeSteps = volumes / minVolumeStep; + double minRequiredProfit = (volumeSteps * heMinProfitPerVolumeStep) + + commissions + (-1 * swaps); + + // + // Check Profits Satisfied Required Profit's For Hedge or not ... + result = profits >= minRequiredProfit; + if (result) + { + // + int flatPositionsCount = ArraySize(flatPositions); + result = IsValidSize(flatPositionsCount); + if (result) + { + // + string comment = "EQM HE Hedge ..."; + int closed = mTrader.Close( + flatPositions, + comment // + ); + + // + result = closed > 0; + if (result) + { + // + string message = "EQM HE Hedge Close (" + ToString(flatPositionsCount) + ") Positions by: " + ToString(profits); + Alert(message); + + // + return result; + } + } + } + } + } + } + + // + // Check BE Hedge Conditions ... + bool allowBEHedge = positionsCount >= 1 && + supportsCount >= 1 && + beMinProfitPerVolumeStep > 0; + if (allowBEHedge) + { + // + // Implement BE Hedge ... + + // + // Check Profits ... + result = profits > 0; + if (result) + { + // + // Calculate Required Profit ... + double volumeSteps = volumes / minVolumeStep; + double minRequiredProfit = (volumeSteps * beMinProfitPerVolumeStep) + + commissions + (-1 * swaps); + + // + // Check Profits Satisfied Required Profit's For Hedge or not ... + result = profits >= minRequiredProfit; + if (result) + { + // + int flatPositionsCount = ArraySize(flatPositions); + result = IsValidSize(flatPositionsCount); + if (result) + { + // + string comment = "EQM BE Hedge ..."; + int closed = mTrader.Close( + flatPositions, + comment // + ); + + // + result = closed > 0; + if (result) + { + // + string message = "EQM BE Hedge Close (" + ToString(flatPositionsCount) + ") Positions by: " + ToString(profits); + Alert(message); + + // + return result; + } + } + } + } + + // + return result; + } + + // + return result; + } + + /** + * Handle Protecting Position ... + */ + bool HandlePositionProtecting( + XPosition &position, // Main Position + XPosition &supports[], // Supports + X121SMCProtectedPosition &positions[] // All Positions + ) + { + // + bool result = false; + + // + // Find Position's Item Data ... + int iDX = -1; + result = HasItem( + position.ticket, + iDX // + ); + if (!result) + { + return result; + } + + // + int supportsCount = ArraySize(supports); + + // + // Handle Protection Of Protection Signals ... + if (supportsCount > 0) + { + HandleProtectionOfProtectors(supports); + } + + // + // Here we Make Sure this Position has reached Proper distance ... + + // + bool isLong = IsLong(position.type); + bool isInProfit = position.profit > 0; + datetime currentTime = TimeCurrent(); + + // + double profitInPoint = position.GetProfitInPoint(); + double pointValue = position.GetPointsValue(); + + // + // Determines there is a Freezed Position or not ... + bool hasFreezed = false; + int positionsCount = ArraySize(positions); + if (IsValidSize(positionsCount)) + { + // + for (int i = 0; i < positionsCount; i++) + { + // + int iSupportsCount = ArraySize(positions[i].supports); + + // + hasFreezed = iSupportsCount == 1 && + positions[i].main.tp == 0 && + positions[i].main.sl == 0 && + positions[i].supports[0].tp == 0 && + positions[i].supports[0].sl == 0 && + positions[i].main.volume == positions[i].supports[0].volume; + if (hasFreezed) + { + break; + } + } + } + + // + // Reading Requirements for Trailling Stops ... + bool allowTrail = AllowTrail() || mData[iDX].forceTrail; + double trailStep = TrailStep(); + double trailStartDistance = TrailStartDistance(); + bool allowOnlyUnprotecteds = OnlyTrailUnprotected(); + int removeTPAfterTrailedLevel = RemoveTPAfterTrailedLevel(); + bool disableTrailWhenFreezedPosition = false; // DisableTrailWhenFreezedPosition(); + bool canTrail = isInProfit && + allowTrail && + trailStep > 0 && + profitInPoint > 0 && + trailStartDistance > 0 && + (!allowOnlyUnprotecteds + ? true + : supportsCount <= 0) && + profitInPoint >= trailStartDistance && + (!disableTrailWhenFreezedPosition + ? true + : !hasFreezed); + + // + // Reading Requirements for Partial Close ... + // In Profit ... + double partialCloseInProfitDistance = PartialCloseInProfitDistance(); + double partialCloseInProfitVolume = PartialCloseInProfitVolume(); + bool canPartialCloseInProfit = isInProfit && + profitInPoint > 0 && + !mData[iDX].partiallyClosed && + partialCloseInProfitVolume > 0 && + profitInPoint >= partialCloseInProfitDistance; + + // + // In Drawdown ... + double partialCloseInDrawdownDistance = PartialCloseInProfitDistance(); + double partialCloseInDrawdownVolume = PartialCloseInProfitVolume(); + bool canPartialCloseInDrawdown = !isInProfit && + profitInPoint < 0 && + !mData[iDX].partiallyClosed && + partialCloseInDrawdownVolume > 0 && + MathAbs(profitInPoint) >= partialCloseInDrawdownDistance; + + // + double partialCloseVolume = canPartialCloseInProfit + ? partialCloseInProfitVolume + : canPartialCloseInDrawdown + ? partialCloseInDrawdownVolume + : 0; + + // + bool canPartialClose = partialCloseVolume > 0 && + (canPartialCloseInProfit || + canPartialCloseInDrawdown); + + // + // Reading Requirement for Freezing Positions ... + + // + // Protect ... + bool allowProtect = AllowProtect(); + int protectionDelay = ProtectionDelay(); + bool protectOnConditions = ProtectOnConditions(); + int maxAllowedProtection = MaxAllowedProtection(); + bool useEntryAsProtectionSL = UseEntryAsProtectionSL(); + double protectDistance = ProtectionStartDistance(); + bool allowDirectionProtect = AllowDirectionProtct(); + double protectVolumeMultiplier = ProtectionVolumeMultiplier(); + bool canProtect = + !isInProfit && + allowProtect && + protectDistance > 0 && + protectionDelay >= 0 && + protectVolumeMultiplier >= 1 && + (maxAllowedProtection <= 0 + ? true + : supportsCount < maxAllowedProtection) && + MathAbs(profitInPoint) >= MathAbs(protectDistance); + + // + result = + canTrail || + canProtect || + canPartialClose; + if (!result) + { + return result; + } + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + // Last Bar ... + XOHCL cBar; + result = cBar.Init( + position.symbol, + position.period, + cIndex // + ); + if (!result) + { + return result; + } + + // + // Previous Bar of Last Bar ... + XOHCL pBar; + result = cBar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // Last Swing Low Bar ... + XOHCL lastSwingLow; + result = cBar.FindLastSwingLow(lastSwingLow); + if (!result) + { + return result; + } + + // + // Last Swing High Bar ... + XOHCL lastSwingHigh; + result = cBar.FindLastSwingHigh(lastSwingHigh); + if (!result) + { + return result; + } + + // + // Common Conditions For Bullish and Bearish Powers ... + + // + // Detect Bullish/Bearish Patterns and Trends ... + + // + // Bullish ... + bool hasBullishPower = cBar.HasBullishPower(); + bool hasBullishPattern = mBarAnalyser.HasBullishPattern(cBar); + bool hasBullishPressure = cBar.HasBullishPressure(); + bool hasBullishTrend = mBarAnalyser.HasBullishTrend(cBar, true); + + // + // Bearish ... + bool hasBearishPower = cBar.HasBearishPower(); + bool hasBearishPattern = mBarAnalyser.HasBearishPattern(cBar); + bool hasBearishPressure = cBar.HasBearishPressure(); + bool hasBearishTrend = mBarAnalyser.HasBearishTrend(cBar, true); + + // + // Define Conditions ... + MqlTick ticks[]; + int ticksCount = CopyTicks( + position.symbol, + ticks, + COPY_TICKS_ALL, + 0, + 5 // + ); + + // + bool isTicksBullishForLong = + // + GetTickEntry(ticks[0], POSITION_TYPE_BUY, position.symbol) > GetTickEntry(ticks[1], POSITION_TYPE_BUY, position.symbol) && + GetTickEntry(ticks[1], POSITION_TYPE_BUY, position.symbol) > GetTickEntry(ticks[2], POSITION_TYPE_BUY, position.symbol) && + GetTickEntry(ticks[2], POSITION_TYPE_BUY, position.symbol) > GetTickEntry(ticks[3], POSITION_TYPE_BUY, position.symbol) + // + ; + + // + bool isTicksBearishForLong = + // + GetTickEntry(ticks[0], POSITION_TYPE_BUY, position.symbol) < GetTickEntry(ticks[1], POSITION_TYPE_BUY, position.symbol) && + GetTickEntry(ticks[1], POSITION_TYPE_BUY, position.symbol) < GetTickEntry(ticks[2], POSITION_TYPE_BUY, position.symbol) && + GetTickEntry(ticks[2], POSITION_TYPE_BUY, position.symbol) < GetTickEntry(ticks[3], POSITION_TYPE_BUY, position.symbol) + // + ; + + // + bool isTicksBullishForShort = + // + GetTickEntry(ticks[0], POSITION_TYPE_SELL, position.symbol) > GetTickEntry(ticks[1], POSITION_TYPE_SELL, position.symbol) && + GetTickEntry(ticks[1], POSITION_TYPE_SELL, position.symbol) > GetTickEntry(ticks[2], POSITION_TYPE_SELL, position.symbol) && + GetTickEntry(ticks[2], POSITION_TYPE_SELL, position.symbol) > GetTickEntry(ticks[3], POSITION_TYPE_SELL, position.symbol) + // + ; + + // + bool isTicksBearishForShort = + // + GetTickEntry(ticks[0], POSITION_TYPE_SELL, position.symbol) < GetTickEntry(ticks[1], POSITION_TYPE_SELL, position.symbol) && + GetTickEntry(ticks[1], POSITION_TYPE_SELL, position.symbol) < GetTickEntry(ticks[2], POSITION_TYPE_SELL, position.symbol) && + GetTickEntry(ticks[2], POSITION_TYPE_SELL, position.symbol) < GetTickEntry(ticks[3], POSITION_TYPE_SELL, position.symbol) + // + ; + + // + // News Momentum Change ... + + // + double hh5 = cBar.FindHighest( + 5, + MODE_HIGH // + ); + + // + double ll5 = cBar.FindLowest( + 5, + MODE_LOW // + ); + + // + bool isForecBullishMomentum = false; + bool isForceBearishMomentum = false; + bool useForceMomentum = UseForceMomentumsInProtection(); + if (ticksCount == 5 && useForceMomentum) + { + // + isForecBullishMomentum = + // + GetTickEntry(ticks[0], POSITION_TYPE_BUY, position.symbol) >= hh5 + // + && + // + ( + // + GetTickEntry(ticks[0], POSITION_TYPE_BUY, position.symbol) > GetTickEntry(ticks[1], POSITION_TYPE_BUY, position.symbol) && + GetTickEntry(ticks[1], POSITION_TYPE_BUY, position.symbol) > GetTickEntry(ticks[2], POSITION_TYPE_BUY, position.symbol) && + GetTickEntry(ticks[2], POSITION_TYPE_BUY, position.symbol) > GetTickEntry(ticks[3], POSITION_TYPE_BUY, position.symbol) && + GetTickEntry(ticks[3], POSITION_TYPE_BUY, position.symbol) > GetTickEntry(ticks[4], POSITION_TYPE_BUY, position.symbol) + // + ) + // + ; + + // + isForceBearishMomentum = + // + GetTickEntry(ticks[0], POSITION_TYPE_SELL, position.symbol) <= ll5 + // + && + // + ( + // + GetTickEntry(ticks[0], POSITION_TYPE_SELL, position.symbol) < GetTickEntry(ticks[1], POSITION_TYPE_SELL, position.symbol) && + GetTickEntry(ticks[1], POSITION_TYPE_SELL, position.symbol) < GetTickEntry(ticks[2], POSITION_TYPE_SELL, position.symbol) && + GetTickEntry(ticks[2], POSITION_TYPE_SELL, position.symbol) < GetTickEntry(ticks[3], POSITION_TYPE_SELL, position.symbol) && + GetTickEntry(ticks[3], POSITION_TYPE_SELL, position.symbol) < GetTickEntry(ticks[4], POSITION_TYPE_SELL, position.symbol) + // + ) + // + ; + } + + // + bool hasBullishDecision = + // + cBar.IsBullishDecision() + // + ; + + // + bool hasBearishDecision = + // + cBar.IsBearishDecision() + // + ; + + // + bool hasBullishConditions = + // + ( + // + hasBullishTrend && + hasBullishDecision && + (hasBullishPower || + hasBullishPattern || + hasBullishPressure) + // + ) + // + ; + + // + bool hasBearishConditions = + // + ( + // + hasBearishTrend && + hasBearishDecision && + (hasBearishPower || + hasBearishPattern || + hasBearishPressure) + // + ) + // + ; + + // + // Do Trail ... + bool isTrailed = false; + if (canTrail) + { + // + bool hasTrailConditions = + isLong + ? (isForecBullishMomentum || + (isTicksBullishForLong && + hasBullishConditions)) + : (isForceBearishMomentum || + (isTicksBearishForShort && + hasBearishConditions)); + if (hasTrailConditions) + { + // + double entry = position.entry; + int lastTrailedStep = mData[iDX].trailStep; + + // + double requiredProfit = + lastTrailedStep == 0 + ? trailStartDistance + : trailStartDistance + (lastTrailedStep * trailStep); + + // + bool isProfitsPassed = profitInPoint > requiredProfit; + if (isProfitsPassed) + { + // + double delta = (requiredProfit * pointValue); + + // + double sl = + isLong + ? entry + delta + : entry - delta; + + // + string comment = "EQM Trail Stop ..."; + + // + bool canRemoveTP = + position.tp != 0 && + removeTPAfterTrailedLevel > 0 && + mData[iDX].trailStep == removeTPAfterTrailedLevel; + double tp = + canRemoveTP + ? 0 + : position.tp; + + // + // Try to Modify Position ... + isTrailed = mTrader.Modify( + position.ticket, + sl, + tp, + comment // + ); + if (isTrailed) + { + // + mData[iDX].trailStep++; + + // + string message = "EQM Trail (" + ToString(position.ticket) + ") Stop in Level: " + ToString(mData[iDX].trailStep) + " ..."; + Alert(message); + } + } + } + // + // Force Trail When passed half way ... + else + { + // + // Handle Force Trail ... + double requiredProfit = position.GetRewardInPoint(); + if (position.sl > 0 && + position.sl < position.entry && + profitInPoint >= requiredProfit) + { + // + double delta = requiredProfit - (requiredProfit / 3); + double sl = + isLong + ? position.entry + (delta * pointValue) + : position.entry - (delta * pointValue); + + // + string comment = "EQM Force Trail Stop ..."; + + // + // Try to Modify Position ... + isTrailed = mTrader.Modify( + position.ticket, + sl, + position.tp, + comment // + ); + if (isTrailed) + { + // + mData[iDX].trailStep++; + + // + string message = "EQM Force Trail (" + ToString(position.ticket) + ") Stop ..."; + Alert(message); + } + } + } + } + + // + // Do Partial Close ... + bool isPartialClosed = false; + if (canPartialClose) + { + // + string comment = "EQM Partial Close ..."; + + // + // Do Partial Closing ... + isPartialClosed = mTrader.ClosePartial( + position.ticket, + partialCloseVolume, + comment // + ); + if (isPartialClosed) + { + // + mData[iDX].partiallyClosed = true; + + // + string message = "EQM Partially Closed " + ToString(partialCloseVolume) + " of (" + ToString(position.ticket) + ") ..."; + Alert(message); + } + } + + // + // Protect ... + bool isProtected = false; + if (canProtect) + { + // + // Protection Conditions ... + bool hasLongProtectConditions = isForecBullishMomentum || + (isTicksBullishForLong && + hasBullishConditions); + bool hasShortProtectConditions = isForceBearishMomentum || + (isTicksBearishForShort && + hasBearishConditions); + + // + // Check Protection Delay ... + datetime currentTime = TimeCurrent(); + datetime lastProtectedOn = mData[iDX].lastProtectedOn; + bool isProtectionDelayPassed = + protectionDelay <= 0 + ? true + : !IsValid(lastProtectedOn) + ? true + : (TimeToSeconds(currentTime) - TimeToSeconds(lastProtectedOn)) > (ulong)protectionDelay; + + // + // Checking Protection Conditions ... + bool hasProtectConditions = + isProtectionDelayPassed && + (!protectOnConditions + ? true + : allowDirectionProtect + ? (hasLongProtectConditions || + hasShortProtectConditions) + : isLong + ? hasShortProtectConditions + : hasLongProtectConditions); + + // + // Check Protection Conditions Happens ... + if (hasProtectConditions) + { + // + bool isInDirectProtection = + !protectOnConditions + ? true + : isLong + ? hasShortProtectConditions + : hasLongProtectConditions; + + // + double sl = + !isInDirectProtection + ? position.sl + : useEntryAsProtectionSL + ? position.entry + : position.tp; + double tp = + !isInDirectProtection + ? position.tp + : position.sl; + double volume = protectVolumeMultiplier * position.volume; + ENUM_POSITION_TYPE type = + !isInDirectProtection + ? position.type + : GetOpposit(position.type); + double entry = GetEntry( + position.symbol, + type // + ); + ENUM_X_ORDER_MODES mode = X_ORDER_MODE_MARKET; + + // + // Prepare Signal ... + XSignal signal; + bool isPrepared = signal.Prepare( + position.symbol, + position.provider, + position.period, + type, + mode, + entry, + volume, + sl, + tp // + ); + + // + if (isPrepared) + { + // + // Generate Comment for Recover and Support ... + string comment = GenerateSupportTag(position.ticket); + + // + signal.comment = comment; + + // + ENUM_X_SIGNAL_EXECUTION_RESULT state; + isProtected = ExecuteSignal( + signal, + state, + true // Support Signal need to Ignore Policies ... + ); + if (isProtected) + { + // + // Update Last Protected On Data Handler ... + mData[iDX].lastProtectedOn = currentTime; + + // + // Alert ... + string message = "EQM Open " + (IsLong(type) ? "Long" : "Short") + " Protect Position for (" + ToString(position.ticket) + ") ..."; + Alert(message); + } + } + } + } + + // + result = + isTrailed || + isProtected || + isPartialClosed; + + // + return result; + } + + /** + * Handle Protection of Support(s) ... + * + * @param supports: Supports Array ... + */ + void HandleProtectionOfProtectors(XPosition &supports[]) + { + // + int supportsCount = ArraySize(supports); + + // + if (!IsValidSize(supportsCount)) + { + return; + } + + // + // TODO: Implement Supports Protection ... + + // + // Trailling ... + } + + /** + * Pause Specified Symbol Trading ... + * + * @param symbol: String ... + */ + void HandlePauseSymbol(string symbol) + { + // + if (!IsValid(symbol)) + { + return; + } + + // + int idx = -1; + bool hasItem = HasSymbol( + symbol, + idx // + ); + if (!hasItem) + { + return; + } + + // + int maxAllowedSLToPause = MaxAllowedSLToPause(); + int pauseDelay = MaxAllowedSLReachedPauseDelay(); + if (maxAllowedSLToPause <= 0 || pauseDelay <= 0) + { + return; + } + + // + bool canPauseSymbol = + mSymbolInfos[idx].IsEnable() && + mSymbolInfos[idx].countedSLs >= maxAllowedSLToPause; + if (!canPauseSymbol) + { + return; + } + + // + mSymbolInfos[idx].Pause(pauseDelay); + + // + string message = "Pause (" + symbol + ") until: (" + ToString(mSymbolInfos[idx].enableAt) + ") ..."; + Alert(message); + + // + } + + // + // Private ... + private: + // + // Props ... + double mAdditionalVolume; // Volume Additional + XSymbolLastPosition mLastExecutedSignals[]; // Last Executed Signals + + // + // Read Only ... + int maxSameTimeTrades; // Max Same Time Trades + double maxDrawdown; // Max Drawdown + double drawdownPercent; // Drawdown Percent + double staticBalanceForCalculateDrawdown; // Static Balance for Max Drawdown Calculation + + // + bool mSaveSignals; // Save Signals + bool mSaveTrades; // Save Trades + bool mSaveConditions; // Save SL Conditions + + // + bool mAllowLong; // Allow Long/Buy Trade Type + bool mAllowShort; // Allow Short/Sell Trade Type + int mMaxAllowedLongs; // Max Allowe Long/Buy Trades + int mMaxAllowedShorts; // Max Allowe Short/Sell Trades + bool mUseMaxAllowedTradesPerSymbol; // Use Max Allowed Trades Per Symbol + double mMaxDrawdownPercentForOpenTrades; // Max Drawdown Percent for Open Trades + + // + // Protector ... + + // + int mDelayBarBetweenTwoSignal; // Delay Bars Between Two Signal + int mMaxAllowedSLToPause; // Max Allowed SL Per Symbol + int mMaxAllowedSLReachedPauseDelay; // Pause Symbol Trading After Mx Allowed SL Reached + bool mUseForceMomentumsInProtection; // Use Force Momentums In Protection + double mAcceptNextSameTypeSignalWhenLastInProfit; // Accept Next Same Type Signal When Last in Profit in Point + + // + // In Profit Positions Protecting ... + + // + // Trail ... + bool mAllowTrail; // Allow Trail Stop for Positions + double mTrailStartDistance; // Specify Trail Start in Point + double mTrailStep; // Trail Step in Point + int mRemoveTPAfterTrailedLevel; // Remove Trailed Position TP after Level + bool mOnlyTrailUnprotected; // Only Trail Unprotected Positionss + + // + // Partial Close (In Profit) ... + double mPartialCloseInProfitDistance; // Specify Partial Close Profit in Point + double mPartialCloseInProfitVolume; // Specify Partial Close in Profit Volume + + // + // In Drawdown Positions Protecting ... + + // + // Protect ... + bool mAllowProtect; // Allow Proptecting + double mProtectionStartDistance; // Protection Start Drawdown in Profit + double mProtectionVolumeMultiplier; // Protection Volume Multiplier + int mMaxAllowedProtection; // Max Allowed Protection + bool mUseEntryAsProtectionSL; // Use Position Entry For SL of Protect + bool mAllowDirectionProtct; // Allow also Directional Protect + bool mProtectOnConditions; // Do Protection only when Conditions happens + int mProtectionDelay; // Delay Between two Protection in Secconds + + // + // Partial Close (In Drawdown) ... + double mPartialCloseInDrawdownDistance; // Specify Partial Close Drawdown in Point + double mPartialCloseInDrawdownVolume; // Specify Partial Close in Drawdown Volume + + // + // Hedging Properties ... + bool mAllowHedge; // Allow Protector to Hedge Positions + double mHedgeMinVolumeStep; // Minimum Volume Step For Hedge + int mMinimumOpenPositionsForHEHedge; // Minimum Open Positions For HE Hedge + double mHedgeHEMinProfitPerVolumeStep; // Minimum Required Profit For HE Hedge Per Volume Step + double mHedgeBEMinProfitPerVolumeStep; // Minimum Required Profit For BE Hedge Per Volume Step + + // + XCBarAnalyser mBarAnalyser; + X121SMCSymbolPositionInfo mSymbolInfos[]; + + /** + * Find Specific Symbo Indo Item index ... + * + * @param symbol: String ... + * @param index: Integer ... + * + * @return ( bool ) + */ + bool HasSymbol( + string symbol, + int &index // + ) + { + // + bool result = false; + + // + index = -1; + + // + result = IsValid(symbol); + if (!result) + { + return result; + } + + // + int count = ArraySize(mSymbolInfos); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + bool isOwn = mSymbolInfos[i] + .IsOwn(symbol); + if (isOwn) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + // + // Common Functions ... + + // + // Count Data ... + int Count() + { + return ArraySize(mData); + } + + // + // Add Item ... + bool Add(X121SMCTradeData &item) + { + // + bool result = false; + + // + result = item.IsValid(); + if (!result) + { + return result; + } + + // + int index = -1; + if (item.ticket > 0) + { + // + result = !HasItem( + item.ticket, + index // + ); + } + else + { + // + result = !HasItem( + item.symbol, + item.provider, + item.period, + item.type, + index // + ); + } + if (!result || IsValidIndex(index)) + { + // + result = false; + return result; + } + + // + AddRef( + item, + mData // + ); + + // + return result; + } + + // + // Find Item Index ... + bool HasItem( + ulong ticket, + int &index // + ) + { + // + bool result = false; + + // + index = -1; + + // + int count = Count(); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + result = mData[i].IsOwn(ticket); + if (result) + { + // + index = i; + break; + } + } + + // + return result; + } + + // + // Find Item Index ... + bool HasItem( + string symbol, + string provider, + ENUM_TIMEFRAMES period, + ENUM_X_POSITION_TYPES type, + int &index // + ) + { + // + bool result = false; + + // + index = -1; + + // + // Validate ... + result = + // + IsValid(symbol) && + IsValid(period) && + IsValid(provider) && + type != X_POSITION_TYPE_ALL && + type != X_POSITION_TYPE_NONE + // + ; + if (!result) + { + return result; + } + + // + int count = Count(); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + result = mData[i].IsOwn( + symbol, + provider, + period, + type // + ); + if (result) + { + // + index = i; + break; + } + } + + // + return result; + } + + // + void Save(int index) + { + // + int count = Count(); + if (!IsValidIndex(index) || index > count - 1) + { + return; + } + + // + // Save Trade ... + if (mSaveTrades) + { + mCollector.Save(mData[index]); + } + + // + if (mSaveConditions) + { + mCollector.SaveConditions(mData[index]); + } + + // + // Remove Item From List ... + ArrayRemove( + mData, + index, + 1 // + ); + } + + // + void SaveSignal(X121SMCTradeData &item) + { + // + if (!mSaveSignals) + { + return; + } + + // + // Save Signal ... + mCollector.SaveSignal(item); + } + + // + int FindLastExecutedSignalItem(XSignal &signal) + { + // + int result = -1; + + // + if (!signal.IsValid()) + { + return result; + } + + // + int count = ArraySize(mLastExecutedSignals); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XSymbolLastPosition iLast = mLastExecutedSignals[i]; + if (iLast.symbol == signal.symbol && + iLast.provider == signal.provider) + { + // + result = i; + break; + } + } + + // + return result; + } + + // + void HandleSignalExecuted(XSignal &signal) + { + // + if (!signal.IsValid()) + { + return; + } + + // + datetime cTime = TimeCurrent(); + int symbolIDX = FindLastExecutedSignalItem(signal); + bool hasItem = IsValidIndex(symbolIDX); + if (hasItem) + { + mLastExecutedSignals[symbolIDX].time = cTime; + } + else + { + // + XSymbolLastPosition item; + + // + item.time = cTime; + item.symbol = signal.symbol; + item.provider = signal.provider; + + // + AddRef( + item, + mLastExecutedSignals // + ); + } + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14031003/X121SMCEA/Experts/x-121.smc.expert.class.ex5 b/BKPS/14031003/X121SMCEA/Experts/x-121.smc.expert.class.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..b891e1fe52b648f20fa35141e4ad7dd1332621ef GIT binary patch literal 17726 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 literal 0 HcmV?d00001 diff --git a/BKPS/14031003/X121SMCEA/Experts/x-121.smc.expert.class.mq5 b/BKPS/14031003/X121SMCEA/Experts/x-121.smc.expert.class.mq5 new file mode 100644 index 0000000..b27dc41 --- /dev/null +++ b/BKPS/14031003/X121SMCEA/Experts/x-121.smc.expert.class.mq5 @@ -0,0 +1,1111 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XC121SMCExpert +// 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-expert.class.mq5" +#include "../Classes/x-121.smc.x-tradehandler.class.mq5" +#include "../Libraries/x-121.smc.lib.mq5" +#include "../Strategy/x-121.smc.test.strategy.class.mq5" + +// +// Definitions ... +string XC121SMCExpertToken = "XC121SMCEA"; + +// +// Implementation ... + +class XC121SMCExpert : public XCBaseExpert +{ + // + public: + // + + // + // Signal Event Listener ... + TOnStopLoss OnPositionSLEventListener; + TOnTakeProfit OnPositionTPEventListener; + TOnPartialClose OnPositionPartialCloseEventListener; + TOnModify OnPositionModifiedEventListener; + TOnForceClose OnPositionForceCloseEventListener; + + // + TOnX121SMCSignal OnSignalEventListener; + + // + // Getter(s) / Setter(s) ... + + /** + * Get Risk to Reward Ratio ... + * + * @return ( double ) + */ + double R2R() + { + return mR2R; + } + + /** + * Set Risk to Reward Ratio ... + * + * @param value: Double ... + */ + void R2R(double value) + { + // + if (value < 1) + { + value = 1; + } + + // + mR2R = value; + ReConfigureAllStrategies(); + } + + /** + * Get Use Dynamic Volume State ... + * + * @return ( bool ) + */ + bool UseDynamicVolume() + { + return mUseDynamicVolume; + } + + /** + * Set Use Dynamic Volume State ... + * + * @param value: Boolean ... + */ + void UseDynamicVolume(bool value) + { + mUseDynamicVolume = value; + } + + /** + * Get Increase Volume Step ... + * + * @return ( double ) + */ + double DynamicVolumeStep() + { + return mDynamicVolumeStep; + } + + /** + * Set Increase Volume Step ... + * + * @param value: Double ... + */ + void DynamicVolumeStep(double value) + { + // + if (value < 0.01) + { + value = 0.01; + } + + // + mDynamicVolumeStep = value; + } + + /** + * Get Balance Factor for Generate Dynamic Volume ... + * + * @return ( double ) + */ + double DynamicVolumeBalanceFactor() + { + return mDynamicVolumeBalanceFactor; + } + + /** + * Set Balance Factor for Generate Dynamic Volume ... + * + * @param value: Double ... + */ + void DynamicVolumeBalanceFactor(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mDynamicVolumeBalanceFactor = value; + } + + /** + * Get Risk Percent Per Balance in Each Trade ... + * + * @return ( double ) + */ + double RiskPercentPerBalance() + { + return mRiskPercentPerBalance; + } + + /** + * Set Risk Percent Per Balance in Each Trade ... + * + * @param value: Double + */ + void RiskPercentPerBalance(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mRiskPercentPerBalance = value; + } + + /** + * Get Dynamic Risk Management State ... + * + * @return ( bool ) + */ + bool DynamicRiskManagement() + { + return mDynamicRiskManagement; + } + + /** + * Set Dynamic Risk Management State ... + * + * @param value: Boolean ... + */ + void DynamicRiskManagement(bool value) + { + mDynamicRiskManagement = value; + } + + /** + * Get Static Volume ... + * + * @return ( double ) + */ + double Volume() + { + return mVolume; + } + + /** + * Set Static Volume ... + * + * @param value: Double ... + */ + void Volume(double value) + { + // + if (value < 0.01) + { + value = 0.01; + } + + // + mVolume = value; + } + + // + // Actions ... + + /** + * Handle OnSignalRecieved Event ... + * + * @param signal: XSignal instance ... + * @param conditions: X121SMCStrategyConditions instance ... + */ + void HandleOnSignalRecieved( + XSignal &signal, + X121SMCStrategyConditions &conditions // + ) + { + // + // Check Signal and Conditions Validations ... + + // + if (!signal.IsValid()) + { + return; + } + + // + if (!conditions.IsValid()) + { + return; + } + + // + bool isLong = IsLong(signal.type); + + // + // Notify When a Raw (Unfiltered) Signal Recieved + // if it's Provided ... + bool mAlertRawSignals = false; + if (mAlertRawSignals) + { + // + string msg = "Raw " + (IsLong(signal.type) ? "Long" : "Short") + " Signal Recieved: (" + signal.provider + "," + signal.symbol + "," + ToString(signal.period) + ") ..."; + Alert(msg); + } + + // + // Apply Volume On Signal ... + ApplyVolumeOnSignal(signal); + + // + // Chekc Signalling Enable or not ... + bool canContinue = + isLong + ? AllowLong() + : AllowShort(); + if (!canContinue) + { + return; + } + + // + // TODO: Apply Filtering On Signal ... + bool isFiltered = false; + if (isFiltered) + { + // + mTradeHandler.RemoveSignal(signal); + return; + } + + // + // Attach Conditions Summary to Signal ... + string conditionsSummary = conditions.GenerateSummary( + false, + false, + true, + false // + ); + + // + // TODO: Retrieve Conditions Summary based on Filter ... + signal.conditions = conditionsSummary; + + // + datetime currentTime = TimeCurrent(); + + // + // Check Signal Protections ... + bool canTrail = false; + ENUM_X_121_SMC_PROVIDERS signalProvider = ParseProvider(signal.provider); + if (IsValid(signalProvider)) + { + // + // Complete this in Force States ... + // canTrail = true; + } + + // + // Execute Signal Using Trade Handler ... + ENUM_X_SIGNAL_EXECUTION_RESULT state; + bool isExecuted = mTradeHandler.ExecuteSignal( + signal, + state, + false, // ignore Policies ... + // + // Force Protections ... + canTrail // + ); + + // + if (isExecuted) + { + mLastSignalOn = currentTime; + } + } + + // + // Override Actions ... + + /** + * Apply Default Configurations ... + */ + void DefaultConfigure() override + { + // + // 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); + + // + R2R(1); + + // + // Volume Default Configurations ... + Volume(0.01); + UseDynamicVolume(false); + DynamicVolumeStep(0.01); + DynamicVolumeBalanceFactor(200); + + // + RiskPercentPerBalance(0); + DynamicRiskManagement(false); + } + + /** + * Vaslidate Inputs ... + * + * @return ( bool ) + */ + bool ValidateInputs() override + { + // + bool result = false; + + // + string errMessage = ""; + + // + bool isCommonValid = ( + // + Slippage() > 0 && + MagicNumber() > 0 + // + ); + if (!isCommonValid) + { + // + errMessage += "common configurations error;" + "\n"; + } + + // + // Checking Volume ... + bool isVolumeValid = true; + if (UseDynamicVolume()) + { + // + isVolumeValid = + DynamicVolumeStep() > 0 && + DynamicVolumeBalanceFactor() > 0; + if (!isVolumeValid) + { + errMessage += "Dynamic Volume configurations error;" + "\n"; + } + } + isVolumeValid = isVolumeValid && + Volume() > 0; + if (!isVolumeValid) + { + errMessage += "Static Volume configurations error;" + "\n"; + } + + // + result = + // + // Common ... + isCommonValid && + // + // Volume Coniguration ... + isVolumeValid && + // + // 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 ( bool ) + */ + bool InitEA() override + { + // + bool result = false; + + // + // Initialize Indicator Helpers ... + + // + // Bar Timer ... + XCTInputs ctInputs; + ctInputs.Default(); // Default Configurations ... + mCTHelper = new XCXCTHelper(); + result = mCTHelper.Init( + GetSymbol(), + GetPeriod(), + ctInputs // + ); + if (!result) + { + return result; + } + + // + // Bar Styles ... + XCCInputs ccInputs; + ccInputs.Default(); // Default Configurations ... + mCCHelper = new XCXCCHelper(); + result = mCCHelper.Init( + GetSymbol(), + GetPeriod(), + ccInputs // + ); + if (!result) + { + return result; + } + + // + // Configure Alerts ... + SetAlertPrefix(GetTag()); + SetAlertEnableAlerts(GetAlertEnableAlerts()); + SetAlertLogAlerts(GetAlertLogAlerts()); + SetAlertMailAlerts(GetAlertMailAlerts()); + SetAlertPushAlerts(GetAlertPushAlerts()); + SetAlertTerminalAlerts(GetAlertTerminalAlerts()); + + // + // Create Trader Instance and Configure it ... + mTrader = new XCTrade( + Slippage(), + MagicNumber() // + ); + mTrader.AddOnStopLossEventHandler(OnPositionSLEventListener); + mTrader.AddOnTakeProfitEventHandler(OnPositionTPEventListener); + mTrader.AddOnModifyPositionEventHandler(OnPositionModifiedEventListener); + mTrader.AddOnForceClosePositionEventHandler(OnPositionForceCloseEventListener); + mTrader.AddOnPartialClosePositionEventHandler(OnPositionPartialCloseEventListener); + + // + // Initialize Trade Handler ... + mTradeHandler = new XC121SMCTradeHandler(mTrader); + mTradeHandler.SaveTrades(true); + mTradeHandler.SaveSignals(true); + mTradeHandler.SaveConditions(true); + + // + // Configure Alerts ... + mTradeHandler.SetAlertPrefix(GetTag()); + mTradeHandler.SetAlertEnableAlerts(GetAlertEnableAlerts()); + mTradeHandler.SetAlertLogAlerts(GetAlertLogAlerts()); + mTradeHandler.SetAlertMailAlerts(GetAlertMailAlerts()); + mTradeHandler.SetAlertPushAlerts(GetAlertPushAlerts()); + mTradeHandler.SetAlertTerminalAlerts(GetAlertTerminalAlerts()); + + // + mTradeHandler.MaxAllowedSLToPause(0); + mTradeHandler.DelayBarBetweenTwoSignal(7); + mTradeHandler.MaxAllowedSLReachedPauseDelay(HoursToSeconds(24)); + + // + // Configure Trade Management ... + mTradeHandler.AllowLong(AllowLong()); + mTradeHandler.AllowShort(AllowShort()); + mTradeHandler.MaxAllowedLongs(0); + mTradeHandler.MaxAllowedShorts(0); + mTradeHandler.UseMaxAllowedTradesPerSymbol(true); + mTradeHandler.MaxDrawdownPercentForOpenTrades(5); + + // + // Configure Position Protector ... + + // + mTradeHandler.UseForceMomentumsInProtection(true); + + // + // Configure Hedging ... + mTradeHandler.AllowHedge(false); + mTradeHandler.HedgeMinVolumeStep(0.01); + mTradeHandler.MinimumOpenPositionsForHEHedge(2); + mTradeHandler.HedgeHEMinProfitPerVolumeStep(0.2); + mTradeHandler.HedgeBEMinProfitPerVolumeStep(0.06); + + // + // In Profit Position Protecting ... + + // + // Trail ... + mTradeHandler.AllowTrail(false); + mTradeHandler.TrailStep(15); + mTradeHandler.TrailStartDistance(30); + mTradeHandler.OnlyTrailUnprotected(true); + mTradeHandler.RemoveTPAfterTrailedLevel(3); + + // + // Partial Close (In Profit) ... + mTradeHandler.PartialCloseInProfitDistance(0); + mTradeHandler.PartialCloseInProfitVolume(0); + + // + // In Drawdown Positions Protecting ... + + // + // Protect ... + mTradeHandler.AllowProtect(false); + mTradeHandler.ProtectionDelay(20); + mTradeHandler.MaxAllowedProtection(0); + mTradeHandler.UseEntryAsProtectionSL(true); + mTradeHandler.ProtectOnConditions(true); + mTradeHandler.AllowDirectionProtct(false); + mTradeHandler.ProtectionStartDistance(50); + mTradeHandler.ProtectionVolumeMultiplier(2); + + // + // Partial Close (In Profit) ... + mTradeHandler.PartialCloseInDrawdownDistance(0); + mTradeHandler.PartialCloseInDrawdownVolume(0); + + // + // Parsers ... + XSymbolParser _symbolParser; + + // + // Single Symbol ... + if (!MultiSymbol()) + { + // + // Register Strategy ... + + // + // Create Class Instance ... + XCX121SMCBaseStrategy *iX121SMCStrategy; + iX121SMCStrategy = new XCX121SMCTestStrategy( + _Symbol, + _Period // + ); + + // + iX121SMCStrategy.AddXSignalEventHandler(OnSignalEventListener); + + // + ConfigureStrategy(iX121SMCStrategy); + RegisterStrategy(iX121SMCStrategy); + } + // + // Multi Symbol ... + else + { + // + // Parse Symbols ... + string symbols[]; + int symbolsCount = SplitContent( + symbols, + Symbols() // + ); + result = IsValidSize(symbolsCount); + if (!result) + { + return result; + } + + // + for (int i = 0; i < symbolsCount; i++) + { + // + // Select Symbol ... + string iSymbol = symbols[i]; + + // + // Register Strategy Based On Symbol ... + + // + // Parse Symbol ... + bool isEURUSD = _symbolParser.IsEURUSD(_Symbol); + bool isGBPUSD = _symbolParser.IsGBPUSD(_Symbol); + bool isEURGBP = _symbolParser.IsEURGBP(_Symbol); + bool isUSDCHF = _symbolParser.IsUSDCHF(_Symbol); + bool isEURCHF = _symbolParser.IsEURCHF(_Symbol); + bool isUSDJPY = _symbolParser.IsUSDJPY(_Symbol); + bool isEURJPY = _symbolParser.IsEURJPY(_Symbol); + bool isUSDCAD = _symbolParser.IsUSDCAD(_Symbol); + bool isEURCAD = _symbolParser.IsEURCAD(_Symbol); + bool isAUDUSD = _symbolParser.IsAUDUSD(_Symbol); + bool isEURAUD = _symbolParser.IsEURAUD(_Symbol); + bool isNZDUSD = _symbolParser.IsNZDUSD(_Symbol); + bool isEURNZD = _symbolParser.IsEURNZD(_Symbol); + + // + // Check Symbol Can Register or not ... + bool canRegisterStrategy = true; + + // + if (canRegisterStrategy) + { + // + // Create Class Instance ... + XCX121SMCBaseStrategy *iX121SMCStrategy; + iX121SMCStrategy = new XCX121SMCTestStrategy( + iSymbol, + _Period // + ); + + // + iX121SMCStrategy.AddXSignalEventHandler(OnSignalEventListener); + + // + // Register Strategy ... + ConfigureStrategy(iX121SMCStrategy); + RegisterStrategy(iX121SMCStrategy); + } + } + } + + // + return result; + } + + /** + * Destroy all Initialized EA Requirements ... + */ + void DestroyEA() override + { + // + delete mCTHelper; + delete mCCHelper; + delete mTradeHandler; + + // + Clean(mStrategies); + } + + /** + * Call all Registered Strategies On Tick ... + */ + void HandleStrategiesOnTick() override + { + // + // Calling Protection Handler of TradeHandler ... + mTradeHandler.HandleProtection(); + + // + int count = ArraySize(mStrategies); + if (!IsValidSize(count)) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + // Call Tick Handler Function ... + mStrategies[i].HandleTick(); + } + } + + // + // Event Handlers ... + + /** + * Calls When a Position's SL Triggered ... + * + * @param deal: XDeal instance ... + */ + void HandleOnStopLossTriggered(const XDeal &deal) override + { + // + // Finish ... + mTradeHandler.Finish(deal); + + // + HandleReportBalance(); + } + + /** + * Calls When a Position's TP Triggered ... + * + * @param deal: XDeal instance ... + */ + void HandleOnTakeProfitTriggered(const XDeal &deal) override + { + // + // Finish ... + mTradeHandler.Finish(deal); + + // + bool useDynamicRiskManagement = DynamicRiskManagement(); + if (useDynamicRiskManagement) + { + mTradeHandler.ResetSymbolInfo(deal.symbol); + } + + // + HandleReportBalance(); + } + + /** + * Handle Force Close a Position ... + * + * @param ticket: Position Ticket ... + * @param position: XPosition ... + * @param comment: Closing Comment ... + */ + void HandleOnPositionForceClosed( + const ulong ticket, + const XPosition &position, + const string comment // + ) override + { + // + // Finish ... + mTradeHandler.Finish( + ticket, + position, + comment // + ); + + // + HandleReportBalance(); + } + + /** + * Reset All Paused Symbols on Each New Days ... + */ + void HandleOnNewDay() override + { + mTradeHandler.ResumePausedSymbols(); + } + + /** + * Generate Identifier Tag ... + * + * @return ( string ) + */ + string GetTag() override + { + // + string result = NULL; + + // + string tagPrefix = TagPrefix(); + if (IsValid(tagPrefix)) + { + result = tagPrefix; + } + else + { + result = ""; + } + + // + result = + XC121SMCExpertToken + result; + + // + return result; + } + + // + protected: + // + + // + // Props ... + + // + datetime mLastSignalOn; + + // + XC121SMCTradeHandler *mTradeHandler; // Trade Handler ... + XCX121SMCBaseStrategy *mStrategies[]; // Registere Strategies in EA ... + + // + // Actions ... + + /** + * Apply Volume Based On Configurations on Signal ... + * + * @param signal: XSignal instance + */ + void ApplyVolumeOnSignal(XSignal &signal) + { + // + // Prepare Signal Dynamic Volume + // if Provided ... + if (UseDynamicVolume() && + DynamicVolumeStep() > 0 && + DynamicVolumeBalanceFactor() > 0) + { + // + double dVolume = mTrader.GetDynamicVolume( + signal.symbol, + DynamicVolumeBalanceFactor(), + DynamicVolumeStep() // + ); + + // + if (dVolume > 0) + { + signal.volume = dVolume; + } + else + { + signal.volume = Volume(); + } + } + else if (RiskPercentPerBalance() > 0) + { + // + double riskPercent = RiskPercentPerBalance(); + + // + double balance = mTrader.mAccount.GetBalance(); + double riskAmountPerBalance = (riskPercent * balance) / 100; + + // + double risk = signal.GetRisk(); + double points = GetPoints(signal.symbol); + double riskInPoints = risk / points; + + // + double volume = mTrader.mAccount.CalculateVolume( + signal.symbol, + riskAmountPerBalance, + riskInPoints // + ); + + // + // Check Dynamic Risk Management ... + bool allowDynamicRiskManagement = DynamicRiskManagement(); + if (allowDynamicRiskManagement) + { + // + // Calculate Dynamic Additional Risk Management Volume Multiplier ... + double mAdditionalRiskMultiplier = CalculateAdditionalVolumeMultiplier(signal); + if (mAdditionalRiskMultiplier < 1) + { + mAdditionalRiskMultiplier = 1; + } + + // + volume *= mAdditionalRiskMultiplier; + } + + // + if (volume > 0) + { + volume = NormalizeVolume(volume, signal.symbol); + } + + // + signal.volume = volume; + } + else + { + signal.volume = Volume(); + } + + // + mTradeHandler.UpdateSignal(signal); + } + + /** + * Configure Startegy ... + */ + void ConfigureStrategy(XCX121SMCBaseStrategy *&strategy) + { + // + if (strategy == NULL) + { + return; + } + + // + // Configure Alerts ... + strategy.SetAlertPrefix(GetTag()); + strategy.SetAlertLogAlerts(GetAlertLogAlerts()); + strategy.SetAlertMailAlerts(GetAlertMailAlerts()); + strategy.SetAlertPushAlerts(GetAlertPushAlerts()); + strategy.SetAlertEnableAlerts(GetAlertEnableAlerts()); + strategy.SetAlertTerminalAlerts(GetAlertTerminalAlerts()); + + // + // Confiugre Signalling ... + + // + strategy.R2R(R2R()); + strategy.AllowLong(AllowLong()); + strategy.AllowShort(AllowShort()); + strategy.MaxAllowedSpread(20); + strategy.MaxAllowedSaveTicks(150); + strategy.MinRequiredTicksForSpreadPass(100); + + // + if (Disabled()) + { + strategy.Disable(); + } + else + { + strategy.Enable(); + } + + // + } + + /** + * Register an Strategy in EA ... + * + * @param strategy: XCX121SMCBaseStrategy instance ... + */ + void RegisterStrategy(XCX121SMCBaseStrategy *strategy) + { + // + if (strategy == NULL) + { + return; + } + + // + ArrayResize( + mStrategies, + ArraySize(mStrategies) + 1 // + ); + + // + mStrategies[ArraySize(mStrategies) - 1] = strategy; + } + + /** + * Re Configure All Registered Strategies ... + */ + void ReConfigureAllStrategies() + { + // + int count = ArraySize(mStrategies); + if (!IsValidSize(count)) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + ConfigureStrategy(mStrategies[i]); + } + } + + // + private: + // + + // + // Props ... + + // + // Volume Management ... + double mR2R; // Signallers Risk to Reward Ratio ... + bool mUseDynamicVolume; // Use Dynamic Volume ... + double mDynamicVolumeStep; // Increase Volume Step ... + double mDynamicVolumeBalanceFactor; // Balance Factor for Generate Dynamic Volume ... + double mVolume; // Static Volume ... + bool mDynamicRiskManagement; // Dynamic Risk Management ... + double mRiskPercentPerBalance; // Risk Percent Per Balance in Each Trade ... + + // + double CalculateAdditionalVolumeMultiplier(XSignal &signal) + { + // + double result = 0; + + // + if (!signal.IsValid()) + { + return result; + } + + // + X121SMCSymbolPositionInfo info; + bool hasInfo = mTradeHandler.GetSymbolInfo( + signal.symbol, + info // + ); + if (!hasInfo) + { + return result; + } + + // + if (info.countedSLs >= 2) + { + result = (info.countedSLs / 2) + 1; + } + + // + return result; + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14031003/X121SMCEA/Libraries/x-121.smc.lib.ex5 b/BKPS/14031003/X121SMCEA/Libraries/x-121.smc.lib.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..3d763ff7e592bb8112d771b7a30cacdd1f6bcdba GIT binary patch literal 13226 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 F`+sFDQ40V7 literal 0 HcmV?d00001 diff --git a/BKPS/14031003/X121SMCEA/Libraries/x-121.smc.lib.mq5 b/BKPS/14031003/X121SMCEA/Libraries/x-121.smc.lib.mq5 new file mode 100644 index 0000000..4e2bc4b --- /dev/null +++ b/BKPS/14031003/X121SMCEA/Libraries/x-121.smc.lib.mq5 @@ -0,0 +1,2117 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Common Library +// -------------------------------------- +// Name: X121SMCLib +// Description: provide all commonly used functions ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.base.class.mq5" +#include "../../Helpers/x-saherelm.x121.helper.mq5" +#include "../../Libraries/x-saherelm.common.lib.mq5" +#include "../../Libraries/x-saherelm.x-poi.lib.mq5" +#include "../../Libraries/x-saherelm.x-trade.lib.mq5" + +// +// Definitions ... + +// +const string X121SMCStrategyToken = "X121SMC"; + +// +const string X121SMCSMPVToken = "X121SMCSMPV"; +const string X121SMCRJBPVToken = "X121SMCRJBPV"; +const string X121SMCVWAPCToken = "X121SMCVWAPC"; + +// +// X121 SMC Providers ... +enum ENUM_X_121_SMC_PROVIDERS +{ + // + X_121_SMC_PROVIDER_NONE, + X_121_SMC_PROVIDER_SMPV, + X_121_SMC_PROVIDER_RJBPV, + X_121_SMC_PROVIDER_VWAPC, +}; + +// +// X121 SL Method ... +enum ENUM_X_121_SMC_SL_TYPES +{ + X_121_SMC_SL_TYPE_NONE, + X_121_SMC_SL_TYPE_LAST_SAR_CHANGED_BAR, + X_121_SMC_SL_TYPE_CURRENT_SAR_BOX, + X_121_SMC_SL_TYPE_LAST_DIRECTIONAL_SAR, + X_121_SMC_SL_TYPE_CURRENT_SAR, + X_121_SMC_SL_TYPE_DON_CLOSE_BOX, + X_121_SMC_SL_TYPE_FIBO_LEVEL_1_5, + X_121_SMC_SL_TYPE_FIBO_LEVEL_3, + X_121_SMC_SL_TYPE_VWAP_FAST, + X_121_SMC_SL_TYPE_VWAP_MID, + X_121_SMC_SL_TYPE_VWAP_SLOW, + X_121_SMC_SL_TYPE_SWING, + X_121_SMC_SL_TYPE_MOMENTUM, + X_121_SMC_SL_TYPE_REJECTION, + X_121_SMC_SL_TYPE_TENKAN_SEN, +}; + +// +// Pivot Types ... +enum ENUM_XPV_PIVOTS +{ + XPV_NONE, + XPV_PEAK, + XPV_VALE, +}; + +// +// Model a Pivot structure ... +struct XPVPivot +{ + // + string symbol; + ENUM_TIMEFRAMES period; + + // + double upper; + double lower; + + // + datetime from; + datetime to; + + // + int repetition; + + // + ENUM_XPV_PIVOTS type; + + // + // Combined all States ... + XPOIState state; + + // + XPVPivot() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + upper = 0; + lower = 0; + + // + to = NULL; + from = NULL; + symbol = NULL; + period = NULL; + + // + repetition = 0; + + // + type = XPV_NONE; + + // + state.Clean(); + } + + /** + * Validation ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsValid(to) && + IsValid(from) && + IsValid(symbol) && + IsValid(period) && + repetition > 0 && + type != XPV_NONE && + (upper > 0 || lower > 0) + // + ; + + // + return result; + } + + /** + * Check Pivot is Peak ... + * + * @return ( bool ) + */ + bool IsPeak() + { + // + bool result = false; + + // + result = IsValid() && + type == XPV_PEAK; + + // + return result; + } + + /** + * Check Pivot is Vale ... + * + * @return ( bool ) + */ + bool IsVale() + { + // + bool result = false; + + // + result = IsValid() && + type == XPV_VALE; + + // + return result; + } + + /** + * Calculate Lower for Peaks ... + * + * @return ( double ) + */ + double CalculateLower() + { + // + double result = 0; + + // + if (!IsValid() || + !IsPeak()) + { + return result; + } + + // + int fromIndex = iBarShift( + symbol, + period, + from // + ); + + // + int toIndex = iBarShift( + symbol, + period, + to // + ); + + // + int count = + fromIndex - toIndex; + + // + int llIDX = iLowest( + symbol, + period, + MODE_LOW, + count, + toIndex // + ); + + // + result = + iLow( + symbol, + period, + llIDX // + ); + + // + return result; + } + + /** + * Calculate Upper for Vales ... + * + * @return ( double ) + */ + double CalculateUpper() + { + // + double result = 0; + + // + if (!IsValid() || + !IsVale()) + { + return result; + } + + // + int fromIndex = iBarShift( + symbol, + period, + from // + ); + + // + int toIndex = iBarShift( + symbol, + period, + to // + ); + + // + int count = + fromIndex - toIndex; + + // + int hhIDX = iHighest( + symbol, + period, + MODE_HIGH, + count, + toIndex // + ); + + // + result = + iHigh( + symbol, + period, + hhIDX // + ); + + // + return result; + } + + /** + * Calculate Range of Pivot ... + * + * @return ( double ) + */ + double CalculateRange() + { + // + double result = 0; + + // + if (!IsValid() || + upper <= 0 || + lower <= 0) + { + return result; + } + + // + result = upper - lower; + + // + return result; + } + + /** + * Calculate Middle of Pivot ... + * Used for + * @return ( double ) + */ + double CalculateMid() + { + // + double result = 0; + + // + double range = CalculateRange(); + if (range <= 0) + { + return result; + } + + // + result = lower + (range / 2); + + // + return result; + } + + /** + * 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 = 0 // + ) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = state + .CalculateLiquidityPercent( + forDirection, + price // + ); + + // + return result; + } + + // + + /** + * Get Unique Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + string hash = symbol + "_" + + ToString(period) + "_" + + ToString(upper) + "," + + ToString(lower) + "_" + + ToString(from) + "," + + ToString(to); + hash = ToMD5(hash); + + // + string typeStr = + type == XPV_PEAK + ? "Peak" + : "Vale"; + + // + result = + // + "XPV_" + + typeStr + "_" + + symbol + "_" + + ToString(period) + + "_" + hash + // + ; + + // + return result; + } + + // +}; + +// +// Pivots ... +struct XPVPivotPoint +{ + // + // Props ... + double value; + int repetition; + datetime time; + ENUM_XPV_PIVOTS type; + + // + // Constructor ... + XPVPivotPoint() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + value = 0; + time = NULL; + repetition = 0; + type = XPV_NONE; + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + // + value > 0 && + IsValid(time) && + repetition > 0 && + type != XPV_NONE + // + ; + + // + return result; + } + + /** + * Check current Pivot Point is Peak or not ... + * + * @return ( bool ) + */ + bool IsPeak() + { + // + bool result = false; + + // + result = IsValid() && + type == XPV_PEAK; + + // + return result; + } + + /** + * Check current Pivot Point is Vale or not ... + * + * @return ( bool ) + */ + bool IsVale() + { + // + bool result = false; + + // + result = IsValid() && + type == XPV_VALE; + + // + return result; + } + + // +}; + +// +// Each Market Cycle (Time Frame) Conditions +// Model as this Structure ... +struct X121SMCCycleConditions +{ + // + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + X121Conditions x121Conditions; + + // + XPOIState state; + + // + void X121SMCStrategyConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + symbol = NULL; + period = NULL; + time = NULL; + + // + state.Clean(); + x121Conditions.Clean(); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = IsSpecifiedValid(symbol) && + IsSpecifiedValid(period) && + IsSpecifiedValid(time); + // + ; + + // + return result; + } + + // + // Reporter Functions ... + + /** + * Generate Provided Scores ... + * + * @param bullishScore: Integer, reference ... + * @param bearishScore: Integer, referenceF ... + */ + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + // + bullishScore = 0; + bearishScore = 0; + + // + if (!IsValid()) + { + return; + } + + // + double bullScore = 0; + double bearScore = 0; + } + + /** + * Generate Summary ... + * + * @param onlyCommons: Boolean ... + * @param onlyConditions: Boolean ... + * @param includeScores: Boolean ... + * @param ignoreFalseConditions: Boolean ... + * @param separator: String ... + * + * @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 commonStr = GenerateSpecifiedCommonSummary( + this, + separator, + includeScores, + true // + ); + + // + string conditionsStr = + // + "" + // + ; + + // + result = + // + "[" + GetTag() + "]" + separator + + "----------" + separator + + (onlyConditions + ? "" + : commonStr) + + " " + separator + + (onlyCommons + ? "" + : conditionsStr) + + "" + // + ; + + // + return result; + } + + /** + * Get Unique Identifier ... + * + * @param forObject: Boolean ... + * + * @return ( string ) + */ + string GetTag( + bool forObject = false // + ) + { + // + string result = NULL; + + // + string typeName = GetTypeName(this); + + // + if (!forObject) + { + result = typeName; + } + else + { + // + result = typeName + "_" + + symbol + "_" + ToString(period) + "_" + + ToMD5(time); + } + + // + return result; + } + + // +}; + +// +// Model Signalling Conditions ... +struct X121SMCStrategyConditions +{ + // + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + // Cycles Conditions here ... + X121SMCCycleConditions triggerConditions; + X121SMCCycleConditions decisionConditions; + X121SMCCycleConditions analyseConditions; + X121SMCCycleConditions verificationConditions; + X121SMCCycleConditions consolidationConditions; + X121SMCCycleConditions visionConditions; + + // + double sl; + double tp; + string provider; + ENUM_X_DIRECTION signalDir; + ENUM_X_DIRECTION marketStructureDir; + + // + + // + void X121SMCStrategyConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + symbol = NULL; + period = NULL; + time = NULL; + + // + sl = 0; + tp = 0; + provider = NULL; + signalDir = X_DIRECTION_NONE; + marketStructureDir = X_DIRECTION_NONE; + + // + triggerConditions.Clean(); + decisionConditions.Clean(); + analyseConditions.Clean(); + verificationConditions.Clean(); + consolidationConditions.Clean(); + visionConditions.Clean(); + } + + /** + * 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(signalDir); + if (!result) + { + return result; + } + + // + result = + IsBullish(signalDir); + + // + return result; + } + + /** + * Check Conditions Has Valid Bearish Signal ... + * + * @return ( bool ) + */ + bool HasBearishSignal() + { + // + bool result = false; + + // + result = + (sl > 0 || + tp > 0) && + IsValid() && + HasDirection(signalDir); + if (!result) + { + return result; + } + + // + result = + IsBearish(signalDir); + + // + return result; + } + + // + // Reporter Functions ... + + /** + * Generate Provided Scores ... + * + * @param bullishScore: Integer, reference ... + * @param bearishScore: Integer, referenceF ... + */ + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + // + bullishScore = 0; + bearishScore = 0; + + // + if (!IsValid()) + { + return; + } + + // + double bullScore = 0; + double bearScore = 0; + } + + /** + * Generate Summary ... + * + * @param onlyCommons: Boolean ... + * @param onlyConditions: Boolean ... + * @param includeScores: Boolean ... + * @param ignoreFalseConditions: Boolean ... + * @param separator: String ... + * + * @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 commonStr = GenerateSpecifiedCommonSummary( + this, + separator, + includeScores, + true // + ); + + // + string conditionsStr = + // + "" + // + ; + + // + result = + // + "[" + GetTag() + "]" + separator + + "----------" + separator + + (onlyConditions + ? "" + : commonStr) + + " " + separator + + (onlyCommons + ? "" + : conditionsStr) + + "" + // + ; + + // + return result; + } + + /** + * Get Unique Identifier ... + * + * @param forObject: Boolean ... + * + * @return ( string ) + */ + string GetTag( + bool forObject = false // + ) + { + // + string result = NULL; + + // + string typeName = GetTypeName(this); + + // + if (!forObject) + { + result = typeName; + } + else + { + // + result = typeName + "_" + + symbol + "_" + ToString(period) + "_" + + ToMD5(time); + } + + // + return result; + } + + // +}; + +// +// +// + +typedef void (*TOnX121SMCSignal)( + XSignal &signal, + X121SMCStrategyConditions &conditions // +); + +// +// Extentions ... + +/** + * Find Oldest Pivot Index ... + * + * @param pivots: XPVPivot instance ... + * @return ( int ) + */ +int FindOldestPivotIndex( + XPVPivot &pivots[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(pivots); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XPVPivot iPivot = pivots[i]; + + // + bool isOldest = true; + for (int j = 0; j < count; j++) + { + // + XPVPivot jPivot = pivots[j]; + + // + isOldest = iPivot.from <= jPivot.from; + if (!isOldest) + { + break; + } + } + + // + if (isOldest) + { + // + result = i; + break; + } + } + + // + return result; +} + +/** + * Sort Pivots Based On From Date ... + * + * @param pivots: XPVPivot instance Collection reference ... + */ +void SortPivots( + XPVPivot &pivots[] // +) +{ + // + XPVPivot tmp[]; + Copy( + pivots, + tmp // + ); + + // + Clean(pivots); + + // + while (ArraySize(tmp) > 0) + { + // + if (ArraySize(tmp) == 1) + { + // + AddRef( + tmp[0], + pivots // + ); + + // + ArrayRemove( + tmp, + 0, + 1); + } + else + { + // + int idx = FindOldestPivotIndex(tmp); + if (IsValidIndex(idx)) + { + // + AddRef( + tmp[idx], + pivots // + ); + + // + ArrayRemove( + tmp, + idx, + 1 // + ); + } + } + } + + // + Clean(tmp); +} + +bool IsPivotBreaked( + XPVPivot &pivot, + XPVPivot &pivots[] // +) +{ + // + bool result = false; + + // + result = pivot.IsValid(); + if (!result) + { + return result; + } + + // + int count = ArraySize(pivots); + result = IsValidSize(pivots); + if (!result) + { + return result; + } + + // + // For Peaks Highs Must not Broked ... + // For Vales Lows Must not Broked ... + bool isPeak = pivot.IsPeak(); + + // + for (int i = 0; i < count; i++) + { + // + XPVPivot iPivot = pivots[i]; + + // + result = isPeak + ? iPivot.upper > pivot.upper + : iPivot.lower < pivot.lower; + if (result) + { + break; + } + } + + // + return result; +} + +/** + * Filter Broken Pivots for Detect Order Flow ... + * + * @param pivots: XPVPivot instance Collection reference ... + */ +void FilterBrokenPivots( + XPVPivot &pivots[] // +) +{ + // + XPVPivot tmp[]; + Copy( + pivots, + tmp // + ); + + // + Clean(pivots); + + // + while (ArraySize(tmp) > 0) + { + // + if (ArraySize(tmp) == 1) + { + // + AddRef( + tmp[0], + pivots // + ); + + // + ArrayRemove( + tmp, + 0, + 1 // + ); + } + else + { + // + XPVPivot pivot = tmp[0]; + + // + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + bool isBreaked = IsPivotBreaked( + pivot, + tmp // + ); + if (!isBreaked) + { + // + AddRef( + pivot, + pivots // + ); + } + } + } + + // + Clean(tmp); +} + +/** + * Calculate Order Flow Direction ... + * + * @param orderFlow: XPVPivot instance Collection reference ... + * @param dir: ENUM_X_DIRECTION member reference, Hold's Calculated Direction ... + * + * @return ( bool ) + */ +bool DetectPivotDirection( + XPVPivot &orderFlow[], + ENUM_X_DIRECTION &dir // +) +{ + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + int count = ArraySize(orderFlow); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + // For Bullish Direction all Exists lowers must be Greater or Equal Prev ... + bool isBullish = false; + bool canLookupForBullish = true; + + // + // For Bearish Direction all Exists uppers must be Lesser or Equal Prev ... + bool isBearish = false; + bool canLookupForBearish = true; + + // + for (int i = 0; i < count; i++) + { + // + XPVPivot iPivot = orderFlow[i]; + + // + XPVPivot tmp[]; + Copy( + orderFlow, + tmp // + ); + ArrayRemove( + tmp, + 0, + i + 1 // + ); + + // + int tmpCount = ArraySize(tmp); + if (IsValidSize(tmpCount)) + { + // + for (int j = 0; j < tmpCount; j++) + { + // + XPVPivot jPivot = tmp[j]; + + // + // Check Bullish Direction ... + isBullish = + canLookupForBullish && + jPivot.lower >= iPivot.lower; + if (!isBullish) + { + canLookupForBullish = false; + } + + // + // Check Bearish Direction ... + isBearish = + canLookupForBearish && + jPivot.upper <= iPivot.upper; + if (!isBearish) + { + canLookupForBearish = false; + } + + // + if (!canLookupForBullish && + !canLookupForBearish) + { + break; + } + } + } + Clean(tmp); + } + + // + if (isBullish && + !isBearish) + { + dir = X_DIRECTION_BULLISH; + } + else if (isBearish && + !isBullish) + { + dir = X_DIRECTION_BEARISH; + } + + // + result = dir != X_DIRECTION_NONE; + + // + return result; +} + +/** + * Detect all POIs which inside a Pivot ... + * + * @param pivot: XPVPivot instance, Specified Pivot ... + * @param source: XPOIState instance, Reference to Source State ... + * @param state: XPOIState instance, Reference to Detected Pivots ... + * @param lookupSwingHighs: Boolean ... + * @param lookupSwingLows: Boolean ... + * @param lookupSupportZones: Boolean ... + * @param lookupResistanceZones: Boolean ... + * @param lookupSupplyZones: Boolean ... + * @param lookupDemandZones: Boolean ... + * @param lookupBullishOrderBlocks: Boolean ... + * @param lookupBearishOrderBlocks: Boolean ... + * @param lookupBullishFairValueGaps: Boolean ... + * @param lookupBearishFairValueGaps: Boolean ... + * @param lookupBullishRejectionBars: Boolean ... + * @param lookupBearishRejectionBars: Boolean ... + * @param lookupBullishMomentumBars: Boolean ... + * @param lookupBearishMomentumBars: Boolean ... + */ +void DetectPivotPOIs( + XPVPivot &pivot, + XPOIState &source, + XPOIState &state, + bool lookupSwingHighs = true, + bool lookupSwingLows = true, + bool lookupSupportZones = true, + bool lookupResistanceZones = true, + bool lookupSupplyZones = true, + bool lookupDemandZones = true, + bool lookupBullishOrderBlocks = true, + bool lookupBearishOrderBlocks = true, + bool lookupBullishFairValueGaps = true, + bool lookupBearishFairValueGaps = true, + bool lookupBullishRejectionBars = true, + bool lookupBearishRejectionBars = true, + bool lookupBullishMomentumBars = true, + bool lookupBearishMomentumBars = true // +) +{ + // + state.Clean(); + + // + if (!pivot.IsValid()) + { + return; + } + + // + int count = 0; + + // + state.symbol = pivot.symbol; + state.period = pivot.period; + state.time = TimeCurrent(); + + // + // Swings ... + + // + // Swing High ... + if (lookupSwingHighs) + { + // + count = ArraySize(source.swingHighs); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSwing *iSwing = source.swingHighs[i]; + + // + XOHCL iBar; + bool isFilled = iSwing.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isInside = iBar.high <= pivot.upper; + if (isInside) + { + // + Add( + iSwing, + state.swingHighs // + ); + } + } + } + } + + // + // Swing Low ... + if (lookupSwingLows) + { + // + count = ArraySize(source.swingLows); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSwing *iSwing = source.swingLows[i]; + + // + XOHCL iBar; + bool isFilled = iSwing.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isInside = iBar.low >= pivot.lower; + if (isInside) + { + // + Add( + iSwing, + state.swingLows // + ); + } + } + } + } + + // + // Support and Resistance Zones ... + + // + // Support Zones ... + if (lookupSupportZones) + { + // + count = ArraySize(source.supportZones); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSupportZone *iZone = source.supportZones[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.supportZones // + ); + } + } + } + } + + // + // Resistance Zones ... + if (lookupResistanceZones) + { + // + count = ArraySize(source.resistanceZones); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCResistanceZone *iZone = source.resistanceZones[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.resistanceZones // + ); + } + } + } + } + + // + // Supply and Demand Zones ... + + // + // Supply Zones ... + if (lookupSupplyZones) + { + // + count = ArraySize(source.supplyZones); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSupplyZone *iZone = source.supplyZones[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.supplyZones // + ); + } + } + } + } + + // + // Demand Zones ... + if (lookupDemandZones) + { + // + count = ArraySize(source.demandZones); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCDemandZone *iZone = source.demandZones[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.demandZones // + ); + } + } + } + } + + // + // Order Blocks ... + + // + // Bullish Order Blocks ... + if (lookupBullishOrderBlocks) + { + // + count = ArraySize(source.bullishOrderBlocks); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iZone = source.bullishOrderBlocks[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.bullishOrderBlocks // + ); + } + } + } + } + + // + // Bearish Order Blocks ... + if (lookupBearishOrderBlocks) + { + // + count = ArraySize(source.bearishOrderBlocks); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iZone = source.bearishOrderBlocks[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.bearishOrderBlocks // + ); + } + } + } + } + + // + // Fair Value Gaps ... + + // + // Bullish Fair Value Gaps ... + if (lookupBullishFairValueGaps) + { + // + count = ArraySize(source.bullishFairValueGaps); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCFVG *iZone = source.bullishFairValueGaps[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.bullishFairValueGaps // + ); + } + } + } + } + + // + // Bearish Fair Value Gaps ... + if (lookupBearishFairValueGaps) + { + // + count = ArraySize(source.bearishFairValueGaps); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCFVG *iZone = source.bearishFairValueGaps[i]; + + // + bool isInside = + iZone.Upper() <= pivot.upper && + iZone.Lower() >= pivot.lower; + if (isInside) + { + // + Add( + iZone, + state.bearishFairValueGaps // + ); + } + } + } + } + + // + // Rejection Bars ... + + // + // Bullish Rejection Bars ... + if (lookupBullishRejectionBars) + { + // + count = ArraySize(source.bullishRejectionBars); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCRejectionBar *iRejection = source.bullishRejectionBars[i]; + + // + XOHCL iBar; + bool isFilled = iRejection.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isInside = iBar.low <= pivot.upper && + iBar.low >= pivot.lower; + if (isInside) + { + // + Add( + iRejection, + state.bullishRejectionBars // + ); + } + } + } + } + + // + // Bearish Rejection Bars ... + if (lookupBearishRejectionBars) + { + // + count = ArraySize(source.bearishRejectionBars); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCRejectionBar *iRejection = source.bearishRejectionBars[i]; + + // + XOHCL iBar; + bool isFilled = iRejection.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isInside = iBar.high <= pivot.upper && + iBar.high >= pivot.lower; + if (isInside) + { + // + Add( + iRejection, + state.bearishRejectionBars // + ); + } + } + } + } + + // + // Momentum Bars ... + + // + // Bullish Momentum Bars ... + if (lookupBullishMomentumBars) + { + // + count = ArraySize(source.bullishMomentumBars); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCMomentumBar *iMomentum = source.bullishMomentumBars[i]; + + // + XOHCL iBar; + bool isFilled = iMomentum.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isInside = iBar.low <= pivot.upper && + iBar.low >= pivot.lower; + if (isInside) + { + // + Add( + iMomentum, + state.bullishMomentumBars // + ); + } + } + } + } + + // + // Bearish Momenum Bars ... + if (lookupBearishMomentumBars) + { + // + count = ArraySize(source.bearishMomentumBars); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCMomentumBar *iMomentum = source.bearishMomentumBars[i]; + + // + XOHCL iBar; + bool isFilled = iMomentum.FillBar(iBar); + if (!isFilled) + { + continue; + } + + // + bool isInside = iBar.high <= pivot.upper && + iBar.high >= pivot.lower; + if (isInside) + { + // + Add( + iMomentum, + state.bearishMomentumBars // + ); + } + } + } + } +} + +// +// Provider Extensions ... + +/** + * Validate a Signal Provider ... + * + * @param value: ENUM_X_121_SMC_PROVIDERS member ... + * + * @return ( bool ) + */ +bool IsValid(ENUM_X_121_SMC_PROVIDERS value) +{ + // + bool result = false; + + // + result = value != X_121_SMC_PROVIDER_NONE; + + // + return result; +} + +/** + * Converts a Signal Provider to String ... + * + * @param value: ENUM_X_121_SMC_PROVIDERS member ... + * + * @return ( string ) + */ +string ToString(ENUM_X_121_SMC_PROVIDERS value) +{ + // + string result = NULL; + + // + if (!IsValid(value)) + { + return result; + } + + // + switch (value) + { + // + case X_121_SMC_PROVIDER_SMPV: + result = X121SMCSMPVToken; + break; + + // + case X_121_SMC_PROVIDER_RJBPV: + result = X121SMCRJBPVToken; + break; + + // + case X_121_SMC_PROVIDER_VWAPC: + result = X121SMCVWAPCToken; + break; + } + + // + return result; +} + +/** + * Parse Specified String as a Signal Provider ... + * + * @param value: String ... + * + * @return ( ENUM_X_121_SMC_PROVIDERS ) + */ +ENUM_X_121_SMC_PROVIDERS ParseProvider(string value) +{ + // + ENUM_X_121_SMC_PROVIDERS result = X_121_SMC_PROVIDER_NONE; + + // + if (!IsValid(value)) + { + return result; + } + + // + if (Contains(X121SMCSMPVToken, value)) + { + result = X_121_SMC_PROVIDER_SMPV; + } + else if (Contains(X121SMCRJBPVToken, value)) + { + result = X_121_SMC_PROVIDER_RJBPV; + } + else if (Contains(X121SMCVWAPCToken, value)) + { + result = X_121_SMC_PROVIDER_VWAPC; + } + + // + return result; +} + +// +// Custom Providers Conditions ... +struct XSMCStrategySetupConditions +{ + // + // Props ... + + // + string symbol; + ENUM_TIMEFRAMES period; + + // + double sl; + ENUM_X_DIRECTION dir; + ENUM_X_POSITION_TYPES type; + + // + // Setup Props ... + + // + datetime setupTime; + datetime triggerTime; + + // + // Trigger Props ... + + // + // Constructor ... + XSMCStrategySetupConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + sl = 0; + + // + dir = X_DIRECTION_NONE; + type = X_POSITION_TYPE_NONE; + + // + symbol = NULL; + period = NULL; + setupTime = NULL; + triggerTime = NULL; + } + + /** + * 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; + } + + /** + * 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; + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14031003/X121SMCEA/Signals/x-121.smc.test.signal.class.mq5 b/BKPS/14031003/X121SMCEA/Signals/x-121.smc.test.signal.class.mq5 new file mode 100644 index 0000000..e2c06d9 --- /dev/null +++ b/BKPS/14031003/X121SMCEA/Signals/x-121.smc.test.signal.class.mq5 @@ -0,0 +1,1669 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 X121 SMC Signal Class +// ------------------------------------------------- +// Name: +// Description: provide all Signalling functions ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-121.smc.market.cycle.helper.class.mq5" +#include "../Libraries/x-121.smc.lib.mq5" + +// +// Definitions ... +struct X121SMCStrategyTestSignalConditions +{ + // + // Props ... + + // + string symbol; + ENUM_TIMEFRAMES period; + + // + double sl; + ENUM_X_DIRECTION dir; + ENUM_X_POSITION_TYPES type; + + // + // Setup Props ... + + // + datetime setupTime; + datetime triggerTime; + + // + XCOrderBlock *bullishOBs[]; + XCOrderBlock *bearishOBs[]; + + // + XCFVG *activeFVG; + XCFVG *bullishFVGs[]; + XCFVG *bearishFVGs[]; + + // + // Trigger Props ... + + // + // Constructor ... + X121SMCStrategyTestSignalConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + sl = 0; + + // + dir = X_DIRECTION_NONE; + type = X_POSITION_TYPE_NONE; + + // + symbol = NULL; + period = NULL; + setupTime = NULL; + triggerTime = NULL; + + // + activeFVG = NULL; + Clean(bullishOBs); + Clean(bearishOBs); + } + + /** + * 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; + } + + // + // Extensions ... + + // + int CountBullishOBs() + { + return ArraySize(bullishOBs); + } + + // + int CountBearishOBs() + { + return ArraySize(bearishOBs); + } + + // + bool HasBullishOB() + { + return IsValidSize(CountBullishOBs()); + } + + // + bool HasBearishOB() + { + return IsValidSize(CountBearishOBs()); + } + + // + int CountBullishFVGs() + { + return ArraySize(bullishFVGs); + } + + // + int CountBearishFVGs() + { + return ArraySize(bearishFVGs); + } + + // + bool HasBullishFVG() + { + return IsValidSize(CountBullishFVGs()); + } + + // + bool HasBearishFVG() + { + return IsValidSize(CountBearishFVGs()); + } + + // +}; + +// +// Extension Functions ... + +// +// Detect Setup Conditions ... +bool DetectX121SMCTestSiganlSetup( + string _symbol, + ENUM_TIMEFRAMES _period, + // + X121SMCStrategyTestSignalConditions &conditions, + // + XC121SMCCycleHelper *triggerCycleHelper, + XC121SMCCycleHelper *decisionCycleHelper, + XC121SMCCycleHelper *analyseCycleHelper, + XC121SMCCycleHelper *verificationCycleHelper, + XC121SMCCycleHelper *consolidationCycleHelper, + XC121SMCCycleHelper *visionCycleHelper + // +) +{ + // + bool result = false; + + // + bool isBullish = false; + bool isBearish = false; + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + int loopback = 10; + + // + string symbol = _symbol; + ENUM_TIMEFRAMES period = _period; + + // + conditions.symbol = symbol; + conditions.period = period; + + // + XOHCL zBar; + result = zBar.Init( + symbol, + period, + zIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL cBar; + result = cBar.Init( + symbol, + period, + cIndex // + ); + if (!result) + { + return result; + } + + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + + // + double ll = cBar.FindLowest(9, MODE_LOW); + double hh = cBar.FindHighest(9, MODE_HIGH); + + // + int zoneValidationDivider = 10; + int validPivotRepetition = triggerCycleHelper.mX121Helper + .GetDonChainLength(); + + // + double selectedSL = 0; + + // + // Cycles Conditions ... + + // + // Trigger ... + ENUM_XPOI_EVENTS triggerPoiEvents[]; + ENUM_X_CYCLE_EVENTS triggerCycleEvents[]; + X121SMCCycleConditions triggerConditions; + result = triggerCycleHelper.GetConditions( + triggerCycleEvents, + triggerPoiEvents, + triggerConditions, + zIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // Decision ... + ENUM_XPOI_EVENTS decisionPoiEvents[]; + ENUM_X_CYCLE_EVENTS decisionCycleEvents[]; + X121SMCCycleConditions decisionConditions; + result = decisionCycleHelper.GetConditions( + decisionCycleEvents, + decisionPoiEvents, + decisionConditions, + zIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // Analyse ... + ENUM_XPOI_EVENTS analysePoiEvents[]; + ENUM_X_CYCLE_EVENTS analyseCycleEvents[]; + X121SMCCycleConditions analyseConditions; + result = analyseCycleHelper.GetConditions( + analyseCycleEvents, + analysePoiEvents, + analyseConditions, + zIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // Verification ... + ENUM_XPOI_EVENTS verificationPoiEvents[]; + ENUM_X_CYCLE_EVENTS verificationCycleEvents[]; + X121SMCCycleConditions verificationConditions; + result = verificationCycleHelper.GetConditions( + verificationCycleEvents, + verificationPoiEvents, + verificationConditions, + zIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // Consolidation ... + ENUM_XPOI_EVENTS consolidationPoiEvents[]; + ENUM_X_CYCLE_EVENTS consolidationCycleEvents[]; + X121SMCCycleConditions consolidationConditions; + result = consolidationCycleHelper.GetConditions( + consolidationCycleEvents, + consolidationPoiEvents, + consolidationConditions, + zIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // Vision ... + ENUM_XPOI_EVENTS visionPoiEvents[]; + ENUM_X_CYCLE_EVENTS visionCycleEvents[]; + X121SMCCycleConditions visionConditions; + result = visionCycleHelper.GetConditions( + visionCycleEvents, + visionPoiEvents, + visionConditions, + zIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // Cycles POI States ... + XPOIState triggerState = triggerConditions.state; + XPOIState decisionState = decisionConditions.state; + XPOIState analyseState = analyseConditions.state; + XPOIState verificationState = verificationConditions.state; + XPOIState consolidationState = consolidationConditions.state; + XPOIState visionState = visionConditions.state; + + // + // Detect Imbalances ... + + // + XPOIState state = decisionState; + + // + bool hasBullishOB = conditions.HasBullishOB(); + if (!hasBullishOB) + { + // + int count = state.CountBullishOrderBlocks(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iOB = state.bullishOrderBlocks[i]; + + // + // Validate Order Block ... + bool isValid = + // + cBar.low > iOB.Upper() + // + ; + if (isValid) + { + // + Add( + iOB, + conditions.bullishOBs // + ); + } + } + } + + // + hasBullishOB = conditions.HasBullishOB(); + } + + // + bool hasBearishOB = conditions.HasBearishOB(); + if (!hasBearishOB) + { + // + int count = state.CountBearishOrderBlocks(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iOB = state.bearishOrderBlocks[i]; + + // + // Validate Order Block ... + bool isValid = + // + cBar.high < iOB.Lower() + // + ; + if (isValid) + { + // + Add( + iOB, + conditions.bearishOBs // + ); + } + } + } + + // + hasBearishOB = conditions.HasBearishOB(); + } + + // + result = hasBullishOB || + hasBearishOB; + if (!result) + { + return result; + } + + // + int fvgValidationLength = 5; + + // + bool hasBullishFVG = conditions.HasBullishFVG(); + if (!hasBullishFVG) + { + // + if (hasBullishOB) + { + // + int obsCount = conditions.CountBullishOBs(); + int count = state.CountBullishFairValueGaps(); + for (int i = 0; i < obsCount; i++) + { + // + XCOrderBlock *iOB = conditions.bullishOBs[i]; + + // + for (int j = 0; j < count; j++) + { + // + XCFVG *jFVG = state.bullishFairValueGaps[j]; + + // + bool isValid = + // + cBar.low > iOB.Upper() && + cBar.low > jFVG.Upper() && + // + jFVG.From() > iOB.From() && + (((int)(jFVG.From() - iOB.From())) / PeriodSeconds(state.period)) <= fvgValidationLength + // + ; + if (isValid) + { + // + Add( + jFVG, + conditions.bullishFVGs // + ); + } + } + } + } + + // + hasBullishFVG = conditions.HasBullishFVG(); + } + + // + bool hasBearishFVG = conditions.HasBearishFVG(); + if (!hasBearishFVG) + { + // + if (hasBullishOB) + { + // + int obsCount = conditions.CountBearishOBs(); + int count = state.CountBearishFairValueGaps(); + for (int i = 0; i < obsCount; i++) + { + // + XCOrderBlock *iOB = conditions.bearishOBs[i]; + + // + for (int j = 0; j < count; j++) + { + // + XCFVG *jFVG = state.bearishFairValueGaps[j]; + + // + bool isValid = + // + cBar.high < iOB.Lower() && + cBar.high < jFVG.Lower() && + // + jFVG.From() > iOB.From() && + (((int)(jFVG.From() - iOB.From())) / PeriodSeconds(state.period)) <= fvgValidationLength + // + ; + if (isValid) + { + // + Add( + jFVG, + conditions.bearishFVGs // + ); + } + } + } + } + + // + hasBearishFVG = conditions.HasBearishFVG(); + } + + // + result = (hasBullishOB && + hasBullishFVG) || + (hasBearishOB && + hasBearishFVG); + if (!result) + { + return result; + } + + // + // Detect new Peak or new Vale ... + + // + bool isNewPeak = triggerConditions.x121Conditions.isNewPeak; + double peak = triggerConditions.x121Conditions.peaksBuffer[1]; + bool isNewPeakOverLast = triggerConditions.x121Conditions.isNewPeakOverLast; + bool isNewPeakUnderLast = triggerConditions.x121Conditions.isNewPeakUnderLast; + + // + bool isNewVale = triggerConditions.x121Conditions.isNewVale; + double vale = triggerConditions.x121Conditions.valesBuffer[1]; + bool isNewValeOverLast = triggerConditions.x121Conditions.isNewValeOverLast; + bool isNewValeUnderLast = triggerConditions.x121Conditions.isNewValeUnderLast; + + // + result = isNewPeak || + isNewVale; + if (!result) + { + return result; + } + + // + // Detect Setup Conditions based on Peaks or Vales Occurance ... + bool lookupForLong = isNewVale && hasBullishOB && hasBullishFVG; + bool lookupForShort = isNewPeak && hasBearishOB && hasBearishFVG; + result = lookupForLong || + lookupForShort; + if (!result) + { + return result; + } + + // + XCFVG *fvg = NULL; + double fvgZoneValidationRangePercent = 0; + if (lookupForLong) + { + // + // Long Conditions ... + // Vales must be Happens Inside Bullish Fair Value Gaps ... + int count = conditions.CountBullishFVGs(); + for (int i = 0; i < count; i++) + { + // + XCFVG *iFVG = conditions.bullishFVGs[i]; + + // + bool isValid = + // + vale <= iFVG.Upper() && + vale >= iFVG.Lower() && + (fvgZoneValidationRangePercent <= 0 + ? true + : (vale < iFVG.Upper() - (iFVG.RangePercent() * fvgZoneValidationRangePercent))) + // + ; + if (isValid) + { + // + fvg = iFVG; + break; + } + } + + // + isBullish = + // + fvg != NULL && + fvg.IsValid() + // + ; + if (isBullish) + { + conditions.activeFVG = fvg; + } + } + else if (lookupForShort) + { + // + // Short Conditions ... + // Peaks Must be Happens Inside Bearish Fair Value Gaps ... + int count = conditions.CountBearishFVGs(); + for (int i = 0; i < count; i++) + { + // + XCFVG *iFVG = conditions.bearishFVGs[i]; + + // + bool isValid = + // + peak <= iFVG.Upper() && + peak >= iFVG.Lower() && + (fvgZoneValidationRangePercent <= 0 + ? true + : (peak > iFVG.Lower() + (iFVG.RangePercent() * fvgZoneValidationRangePercent))) + // + ; + if (isValid) + { + // + fvg = iFVG; + break; + } + } + + // + isBearish = + // + fvg != NULL && + fvg.IsValid() + // + ; + if (isBearish) + { + conditions.activeFVG = fvg; + } + } + + // + result = isBullish || + isBearish; + if (!result) + { + // + if (lookupForLong) + { + // + conditions.activeFVG = NULL; + Clean(conditions.bullishOBs); + Clean(conditions.bullishFVGs); + } + else if (lookupForShort) + { + // + conditions.activeFVG = NULL; + Clean(conditions.bearishOBs); + Clean(conditions.bearishFVGs); + } + + // + return result; + } + + // + conditions.setupTime = cTime; + conditions.dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; +} + +// +// Detect Trigger Conditions ... +bool DetectX121SMCTestSiganlTrigger( + // + X121SMCStrategyTestSignalConditions &conditions, + // + string _symbol, + ENUM_TIMEFRAMES _period, + // + XC121SMCCycleHelper *triggerCycleHelper, + XC121SMCCycleHelper *decisionCycleHelper, + XC121SMCCycleHelper *analyseCycleHelper, + XC121SMCCycleHelper *verificationCycleHelper, + XC121SMCCycleHelper *consolidationCycleHelper, + XC121SMCCycleHelper *visionCycleHelper, + // + 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 = false; + bool isBearish = false; + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + int loopback = 10; + + // + ENUM_X_121_SMC_PROVIDERS provider = X_121_SMC_PROVIDER_SMPV; + string providerStr = ToString(provider); + + // + string symbol = _symbol; + ENUM_TIMEFRAMES period = _period; + + // + XOHCL zBar; + result = zBar.Init( + symbol, + period, + zIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL cBar; + result = cBar.Init( + symbol, + period, + cIndex // + ); + if (!result) + { + return result; + } + + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + + // + double ll = cBar.FindLowest(9, MODE_LOW); + double hh = cBar.FindHighest(9, MODE_HIGH); + + // + int zoneValidationDivider = 10; + int validPivotRepetition = triggerCycleHelper.mX121Helper + .GetDonChainLength(); + + // + double selectedSL = 0; + + // + // Cycles Conditions ... + + // + // Trigger ... + ENUM_XPOI_EVENTS triggerPoiEvents[]; + ENUM_X_CYCLE_EVENTS triggerCycleEvents[]; + X121SMCCycleConditions triggerConditions; + result = triggerCycleHelper.GetConditions( + triggerCycleEvents, + triggerPoiEvents, + triggerConditions, + zIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // Decision ... + ENUM_XPOI_EVENTS decisionPoiEvents[]; + ENUM_X_CYCLE_EVENTS decisionCycleEvents[]; + X121SMCCycleConditions decisionConditions; + result = decisionCycleHelper.GetConditions( + decisionCycleEvents, + decisionPoiEvents, + decisionConditions, + zIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // Analyse ... + ENUM_XPOI_EVENTS analysePoiEvents[]; + ENUM_X_CYCLE_EVENTS analyseCycleEvents[]; + X121SMCCycleConditions analyseConditions; + result = analyseCycleHelper.GetConditions( + analyseCycleEvents, + analysePoiEvents, + analyseConditions, + zIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // Verification ... + ENUM_XPOI_EVENTS verificationPoiEvents[]; + ENUM_X_CYCLE_EVENTS verificationCycleEvents[]; + X121SMCCycleConditions verificationConditions; + result = verificationCycleHelper.GetConditions( + verificationCycleEvents, + verificationPoiEvents, + verificationConditions, + zIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // Consolidation ... + ENUM_XPOI_EVENTS consolidationPoiEvents[]; + ENUM_X_CYCLE_EVENTS consolidationCycleEvents[]; + X121SMCCycleConditions consolidationConditions; + result = consolidationCycleHelper.GetConditions( + consolidationCycleEvents, + consolidationPoiEvents, + consolidationConditions, + zIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // Vision ... + ENUM_XPOI_EVENTS visionPoiEvents[]; + ENUM_X_CYCLE_EVENTS visionCycleEvents[]; + X121SMCCycleConditions visionConditions; + result = visionCycleHelper.GetConditions( + visionCycleEvents, + visionPoiEvents, + visionConditions, + zIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // Cycles POI States ... + XPOIState triggerState = triggerConditions.state; + XPOIState decisionState = decisionConditions.state; + XPOIState analyseState = analyseConditions.state; + XPOIState verificationState = verificationConditions.state; + XPOIState consolidationState = consolidationConditions.state; + XPOIState visionState = visionConditions.state; + + // + // Trigger Conditions ... + XCFVG *iFVG = conditions.activeFVG; + result = iFVG != NULL && + iFVG.IsValid(); + if (!result) + { + return result; + } + + // + bool lookupLong = IsBullish(setupDir) && + iFVG.IsBullish(); + bool lookupShort = IsBearish(setupDir) && + iFVG.IsBearish(); + result = lookupLong || + lookupShort; + if (!result) + { + return result; + } + + // + // Check PEAKS and Vales ... + + // + // Trigger ... + + // + // Peaks and Vales ... + double triggerPeak = triggerConditions.x121Conditions.peaksBuffer[1]; + double triggerVale = triggerConditions.x121Conditions.valesBuffer[1]; + + // + bool isTriggerPeakInsideFVG = + // + triggerPeak <= iFVG.Upper() && + triggerPeak >= iFVG.Lower() + // + ; + bool isTriggerValeInsideFVG = + // + triggerVale <= iFVG.Upper() && + triggerVale >= iFVG.Lower() + // + ; + + // + // VWap ... + + // + bool isTriggerVWapFastBullish = triggerConditions.x121Conditions.isVWapFastBullish; + bool isTriggerVWapMidBullish = triggerConditions.x121Conditions.isVWapMidBullish; + bool isTriggerVWapSlowBullish = triggerConditions.x121Conditions.isVWapSlowBullish; + + // + bool isTriggerVWapFastOverMid = triggerConditions.x121Conditions.isVWapFastOverMid; + bool isTriggerVWapMidOverSlow = triggerConditions.x121Conditions.isVWapMidOverSlow; + + // + bool isTriggerVWapFastBearish = triggerConditions.x121Conditions.isVWapFastBearish; + bool isTriggerVWapMidBearish = triggerConditions.x121Conditions.isVWapMidBearish; + bool isTriggerVWapSlowBearish = triggerConditions.x121Conditions.isVWapSlowBearish; + + // + bool isTriggerVWapFastUnderMid = triggerConditions.x121Conditions.isVWapFastUnderMid; + bool isTriggerVWapMidUnderSlow = triggerConditions.x121Conditions.isVWapMidUnderSlow; + + // + bool isTriggerMarketBullish = + // + // State ... + ( + // + (isTriggerVWapFastBullish && + isTriggerVWapMidBullish && + isTriggerVWapSlowBullish) + // + || + // + (isTriggerVWapMidBullish && + isTriggerVWapSlowBullish) + // + ) + // + && + // + // Order ... + ( + // + (isTriggerVWapFastOverMid && + isTriggerVWapMidOverSlow) + // + || + // + isTriggerVWapMidOverSlow + // + ) + // + ; + + // + bool isTriggerMarketBearish = + // + // State ... + ( + // + (isTriggerVWapFastBearish && + isTriggerVWapMidBearish && + isTriggerVWapSlowBearish) + // + || + // + (isTriggerVWapMidBearish && + isTriggerVWapSlowBearish) + // + ) + // + && + // + // Order ... + ( + // + (isTriggerVWapFastUnderMid && + isTriggerVWapMidUnderSlow) + // + || + // + isTriggerVWapMidUnderSlow + // + ) + // + ; + + // + // Decision ... + + // + double decisionPeak = decisionConditions.x121Conditions.peaksBuffer[1]; + double decisionVale = decisionConditions.x121Conditions.valesBuffer[1]; + + // + bool isDecisionPeakInsideFVG = + // + decisionPeak <= iFVG.Upper() && + decisionPeak >= iFVG.Lower() + // + ; + bool isDecisionValeInsideFVG = + // + decisionVale <= iFVG.Upper() && + decisionVale >= iFVG.Lower() + // + ; + + // + // VWap ... + + // + bool isDecisionVWapFastBullish = decisionConditions.x121Conditions.isVWapFastBullish; + bool isDecisionVWapMidBullish = decisionConditions.x121Conditions.isVWapMidBullish; + bool isDecisionVWapSlowBullish = decisionConditions.x121Conditions.isVWapSlowBullish; + + // + bool isDecisionVWapFastOverMid = decisionConditions.x121Conditions.isVWapFastOverMid; + bool isDecisionVWapMidOverSlow = decisionConditions.x121Conditions.isVWapMidOverSlow; + + // + bool isDecisionVWapFastBearish = decisionConditions.x121Conditions.isVWapFastBearish; + bool isDecisionVWapMidBearish = decisionConditions.x121Conditions.isVWapMidBearish; + bool isDecisionVWapSlowBearish = decisionConditions.x121Conditions.isVWapSlowBearish; + + // + bool isDecisionVWapFastUnderMid = decisionConditions.x121Conditions.isVWapFastUnderMid; + bool isDecisionVWapMidUnderSlow = decisionConditions.x121Conditions.isVWapMidUnderSlow; + + // + bool isDecisionMarketBullish = + // + // State ... + ( + // + (isDecisionVWapFastBullish && + isDecisionVWapMidBullish && + isDecisionVWapSlowBullish) + // + || + // + (isDecisionVWapMidBullish && + isDecisionVWapSlowBullish) + // + ) + // + && + // + // Order ... + ( + // + (isDecisionVWapFastOverMid && + isDecisionVWapMidOverSlow) + // + || + // + isDecisionVWapMidOverSlow + // + ) + // + ; + + // + bool isDecisionMarketBearish = + // + // State ... + ( + // + (isDecisionVWapFastBearish && + isDecisionVWapMidBearish && + isDecisionVWapSlowBearish) + // + || + // + (isDecisionVWapMidBearish && + isDecisionVWapSlowBearish) + // + ) + // + && + // + // Order ... + ( + // + (isDecisionVWapFastUnderMid && + isDecisionVWapMidUnderSlow) + // + || + // + isDecisionVWapMidUnderSlow + // + ) + // + ; + + // + // Analyse ... + + // + double analysePeak = analyseConditions.x121Conditions.peaksBuffer[1]; + double analyseVale = analyseConditions.x121Conditions.valesBuffer[1]; + + // + bool isAnalysePeakInsideFVG = + // + analysePeak <= iFVG.Upper() && + analysePeak >= iFVG.Lower() + // + ; + bool isAnalyseValeInsideFVG = + // + analyseVale <= iFVG.Upper() && + analyseVale >= iFVG.Lower() + // + ; + + // + // VWap ... + + // + bool isAnalyseVWapFastBullish = analyseConditions.x121Conditions.isVWapFastBullish; + bool isAnalyseVWapMidBullish = analyseConditions.x121Conditions.isVWapMidBullish; + bool isAnalyseVWapSlowBullish = analyseConditions.x121Conditions.isVWapSlowBullish; + + // + bool isAnalyseVWapFastOverMid = analyseConditions.x121Conditions.isVWapFastOverMid; + bool isAnalyseVWapMidOverSlow = analyseConditions.x121Conditions.isVWapMidOverSlow; + + // + bool isAnalyseVWapFastBearish = analyseConditions.x121Conditions.isVWapFastBearish; + bool isAnalyseVWapMidBearish = analyseConditions.x121Conditions.isVWapMidBearish; + bool isAnalyseVWapSlowBearish = analyseConditions.x121Conditions.isVWapSlowBearish; + + // + bool isAnalyseVWapFastUnderMid = analyseConditions.x121Conditions.isVWapFastUnderMid; + bool isAnalyseVWapMidUnderSlow = analyseConditions.x121Conditions.isVWapMidUnderSlow; + + // + bool isAnalyseMarketBullish = + // + // State ... + ( + // + (isAnalyseVWapFastBullish && + isAnalyseVWapMidBullish && + isAnalyseVWapSlowBullish) + // + || + // + (isAnalyseVWapMidBullish && + isAnalyseVWapSlowBullish) + // + ) + // + && + // + // Order ... + ( + // + (isAnalyseVWapFastOverMid && + isAnalyseVWapMidOverSlow) + // + || + // + isAnalyseVWapMidOverSlow + // + ) + // + ; + + // + bool isAnalyseMarketBearish = + // + // State ... + ( + // + (isAnalyseVWapFastBearish && + isAnalyseVWapMidBearish && + isAnalyseVWapSlowBearish) + // + || + // + (isAnalyseVWapMidBearish && + isAnalyseVWapSlowBearish) + // + ) + // + && + // + // Order ... + ( + // + (isAnalyseVWapFastUnderMid && + isAnalyseVWapMidUnderSlow) + // + || + // + isAnalyseVWapMidUnderSlow + // + ) + // + ; + + // + // Verification ... + + // + double verificationPeak = verificationConditions.x121Conditions.peaksBuffer[1]; + double verificationVale = verificationConditions.x121Conditions.valesBuffer[1]; + + // + bool isVerificationPeakInsideFVG = + // + verificationPeak <= iFVG.Upper() && + verificationPeak >= iFVG.Lower() + // + ; + bool isVerificationValeInsideFVG = + // + verificationVale <= iFVG.Upper() && + verificationVale >= iFVG.Lower() + // + ; + + // + // VWap ... + + // + bool isVerificationVWapFastBullish = verificationConditions.x121Conditions.isVWapFastBullish; + bool isVerificationVWapMidBullish = verificationConditions.x121Conditions.isVWapMidBullish; + bool isVerificationVWapSlowBullish = verificationConditions.x121Conditions.isVWapSlowBullish; + + // + bool isVerificationVWapFastOverMid = verificationConditions.x121Conditions.isVWapFastOverMid; + bool isVerificationVWapMidOverSlow = verificationConditions.x121Conditions.isVWapMidOverSlow; + + // + bool isVerificationVWapFastBearish = verificationConditions.x121Conditions.isVWapFastBearish; + bool isVerificationVWapMidBearish = verificationConditions.x121Conditions.isVWapMidBearish; + bool isVerificationVWapSlowBearish = verificationConditions.x121Conditions.isVWapSlowBearish; + + // + bool isVerificationVWapFastUnderMid = verificationConditions.x121Conditions.isVWapFastUnderMid; + bool isVerificationVWapMidUnderSlow = verificationConditions.x121Conditions.isVWapMidUnderSlow; + + // + bool isVerificationMarketBullish = + // + // State ... + ( + // + (isVerificationVWapFastBullish && + isVerificationVWapMidBullish && + isVerificationVWapSlowBullish) + // + || + // + (isVerificationVWapMidBullish && + isVerificationVWapSlowBullish) + // + ) + // + && + // + // Order ... + ( + // + (isVerificationVWapFastOverMid && + isVerificationVWapMidOverSlow) + // + || + // + isVerificationVWapMidOverSlow + // + ) + // + ; + + // + bool isVerificationMarketBearish = + // + // State ... + ( + // + (isVerificationVWapFastBearish && + isVerificationVWapMidBearish && + isVerificationVWapSlowBearish) + // + || + // + (isVerificationVWapMidBearish && + isVerificationVWapSlowBearish) + // + ) + // + && + // + // Order ... + ( + // + (isVerificationVWapFastUnderMid && + isVerificationVWapMidUnderSlow) + // + || + // + isVerificationVWapMidUnderSlow + // + ) + // + ; + + // + // Consolidation ... + + // + double consolidationPeak = consolidationConditions.x121Conditions.peaksBuffer[1]; + double consolidationVale = consolidationConditions.x121Conditions.valesBuffer[1]; + + // + bool isConsolidationPeakInsideFVG = + // + consolidationPeak <= iFVG.Upper() && + consolidationPeak >= iFVG.Lower() + // + ; + bool isConsolidationValeInsideFVG = + // + consolidationVale <= iFVG.Upper() && + consolidationVale >= iFVG.Lower() + // + ; + + // + // VWap ... + + // + bool isConsolidationVWapFastBullish = consolidationConditions.x121Conditions.isVWapFastBullish; + bool isConsolidationVWapMidBullish = consolidationConditions.x121Conditions.isVWapMidBullish; + bool isConsolidationVWapSlowBullish = consolidationConditions.x121Conditions.isVWapSlowBullish; + + // + bool isConsolidationVWapFastOverMid = consolidationConditions.x121Conditions.isVWapFastOverMid; + bool isConsolidationVWapMidOverSlow = consolidationConditions.x121Conditions.isVWapMidOverSlow; + + // + bool isConsolidationVWapFastBearish = consolidationConditions.x121Conditions.isVWapFastBearish; + bool isConsolidationVWapMidBearish = consolidationConditions.x121Conditions.isVWapMidBearish; + bool isConsolidationVWapSlowBearish = consolidationConditions.x121Conditions.isVWapSlowBearish; + + // + bool isConsolidationVWapFastUnderMid = consolidationConditions.x121Conditions.isVWapFastUnderMid; + bool isConsolidationVWapMidUnderSlow = consolidationConditions.x121Conditions.isVWapMidUnderSlow; + + // + bool isConsolidationMarketBullish = + // + // State ... + ( + // + (isConsolidationVWapFastBullish && + isConsolidationVWapMidBullish && + isConsolidationVWapSlowBullish) + // + || + // + (isConsolidationVWapMidBullish && + isConsolidationVWapSlowBullish) + // + ) + // + && + // + // Order ... + ( + // + (isConsolidationVWapFastOverMid && + isConsolidationVWapMidOverSlow) + // + || + // + isConsolidationVWapMidOverSlow + // + ) + // + ; + + // + bool isConsolidationMarketBearish = + // + // State ... + ( + // + (isConsolidationVWapFastBearish && + isConsolidationVWapMidBearish && + isConsolidationVWapSlowBearish) + // + || + // + (isConsolidationVWapMidBearish && + isConsolidationVWapSlowBearish) + // + ) + // + && + // + // Order ... + ( + // + (isConsolidationVWapFastUnderMid && + isConsolidationVWapMidUnderSlow) + // + || + // + isConsolidationVWapMidUnderSlow + // + ) + // + ; + + // + // Sar ... + + // + bool isSarSwitchedToBullish = triggerConditions.x121Conditions.isSarSwitchedToBullish; + bool isSarSwitchedToBearish = triggerConditions.x121Conditions.isSarSwitchedToBearish; + + // + // Summarize Conditions ... + + // + bool isSamePeak = + triggerPeak == decisionPeak && + triggerPeak == analysePeak && + triggerPeak == verificationPeak; + + // + bool isPeaksInsideFVG = + // + isTriggerPeakInsideFVG && + isDecisionPeakInsideFVG && + isAnalysePeakInsideFVG && + isVerificationPeakInsideFVG + // + ; + + // + bool isSameVale = + triggerVale == decisionVale && + triggerVale == analyseVale && + triggerVale == verificationVale; + + // + bool isValesInsideFVG = + // + isTriggerValeInsideFVG && + isDecisionValeInsideFVG && + isAnalyseValeInsideFVG && + isVerificationValeInsideFVG + // + ; + + // + bool isMarketReadyForLong = + // + // !isTriggerMarketBearish && + // !isDecisionMarketBearish && + !isAnalyseMarketBearish && + !isVerificationMarketBearish && + !isConsolidationMarketBearish + // + ; + + // + bool isMarketReadyForShort = + // + // !isTriggerMarketBullish && + // !isDecisionMarketBullish && + !isAnalyseMarketBullish && + !isVerificationMarketBullish && + !isConsolidationMarketBullish + // + ; + + // + // Create Trigger ... + + // + isBullish = + // isSameVale && + lookupLong && + isValesInsideFVG && + isMarketReadyForLong && + isSarSwitchedToBullish && + triggerVale <= iFVG.Upper() && + triggerVale >= iFVG.Lower(); + + // + isBearish = + // isSamePeak && + lookupShort && + isPeaksInsideFVG && + isMarketReadyForShort && + isSarSwitchedToBearish && + triggerPeak <= iFVG.Upper() && + triggerPeak >= iFVG.Lower(); + + // + result = isBullish || + isBearish; + if (!result) + { + // + // Cleanup Setup Conditions ... + int setupAge = conditions.GetSetupAge(); + if (IsValidSize(setupAge) && + IsValidSize(maxAllowedSetupAge) && + setupAge >= maxAllowedSetupAge) + { + conditions.Clean(); + } + + // + return result; + } + + // + conditions.triggerTime = cTime; + conditions.sl = isBullish + ? iFVG.Lower() + : iFVG.Upper(); + conditions.type = isBullish + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_SHORT; + + // + return result; +} + +// +// Tools Functions ... + +// \ No newline at end of file diff --git a/BKPS/14031003/X121SMCEA/Strategy/x-121.smc.test.strategy.class.ex5 b/BKPS/14031003/X121SMCEA/Strategy/x-121.smc.test.strategy.class.ex5 new file mode 100644 index 0000000000000000000000000000000000000000..48517c9dd4233f893e47991d185201b3faed2cb7 GIT binary patch literal 16784 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 dr7rdwK@x#N0S065Q{$EPJs&TjW iZone.Upper()) || + (bar.high > iZone.Lower() && + bar.low < iZone.Lower()) || + (bar.low > iZone.Lower() && + bar.high < iZone.Upper()) + // + ; + if (isValid) + { + Add( + iZone, + supports // + ); + } + } + + // + Clean(tmpState.supportZones); + Copy( + supports, + tmpState.supportZones // + ); + } + + // + // Resistance Zones ... + int resistanceZonesCount = ArraySize(tmpState.resistanceZones); + if (IsValidSize(resistanceZonesCount)) + { + // + XCResistanceZone *resistances[]; + for (int i = 0; i < resistanceZonesCount; i++) + { + // + XCResistanceZone *iZone = tmpState.resistanceZones[i]; + + // + bool isValid = + // + (bar.low < iZone.Upper() && + bar.high > iZone.Upper()) || + (bar.high > iZone.Lower() && + bar.low < iZone.Lower()) || + (bar.low > iZone.Lower() && + bar.high < iZone.Upper()) + // + ; + if (isValid) + { + Add( + iZone, + resistances // + ); + } + } + + // + Clean(tmpState.resistanceZones); + Copy( + resistances, + tmpState.resistanceZones // + ); + } + + // + // Supply Zones ... + int supplyZonesCount = ArraySize(tmpState.supplyZones); + if (IsValidSize(supplyZonesCount)) + { + // + XCSupplyZone *supplies[]; + for (int i = 0; i < supplyZonesCount; i++) + { + // + XCSupplyZone *iZone = tmpState.supplyZones[i]; + + // + bool isValid = + // + (bar.low < iZone.Upper() && + bar.high > iZone.Upper()) || + (bar.high > iZone.Lower() && + bar.low < iZone.Lower()) || + (bar.low > iZone.Lower() && + bar.high < iZone.Upper()) + // + ; + if (isValid) + { + Add( + iZone, + supplies // + ); + } + } + + // + Clean(tmpState.supplyZones); + Copy( + supplies, + tmpState.supplyZones // + ); + } + + // + // Demand Zones ... + int demandZonesCount = ArraySize(tmpState.demandZones); + if (IsValidSize(demandZonesCount)) + { + // + XCDemandZone *demands[]; + for (int i = 0; i < demandZonesCount; i++) + { + // + XCDemandZone *iZone = tmpState.demandZones[i]; + + // + bool isValid = + // + (bar.low < iZone.Upper() && + bar.high > iZone.Upper()) || + (bar.high > iZone.Lower() && + bar.low < iZone.Lower()) || + (bar.low > iZone.Lower() && + bar.high < iZone.Upper()) + // + ; + if (isValid) + { + Add( + iZone, + demands // + ); + } + } + + // + Clean(tmpState.demandZones); + Copy( + demands, + tmpState.demandZones // + ); + } + + // + // Bullish Order Blocks ... + int bullishOrderBlocksCount = ArraySize(tmpState.bullishOrderBlocks); + if (IsValidSize(bullishOrderBlocksCount)) + { + // + XCOrderBlock *obs[]; + for (int i = 0; i < bullishOrderBlocksCount; i++) + { + // + XCOrderBlock *iZone = tmpState.bullishOrderBlocks[i]; + + // + bool isValid = + // + (bar.low < iZone.Upper() && + bar.high > iZone.Upper()) || + (bar.high > iZone.Lower() && + bar.low < iZone.Lower()) || + (bar.low > iZone.Lower() && + bar.high < iZone.Upper()) + // + ; + if (isValid) + { + Add( + iZone, + obs // + ); + } + } + + // + Clean(tmpState.bullishOrderBlocks); + Copy( + obs, + tmpState.bullishOrderBlocks // + ); + } + + // + // Bearish Order Blocks ... + int bearishOrderBlocksCount = ArraySize(tmpState.bearishOrderBlocks); + if (IsValidSize(bearishOrderBlocksCount)) + { + // + XCOrderBlock *obs[]; + for (int i = 0; i < bearishOrderBlocksCount; i++) + { + // + XCOrderBlock *iZone = tmpState.bearishOrderBlocks[i]; + + // + bool isValid = + // + (bar.low < iZone.Upper() && + bar.high > iZone.Upper()) || + (bar.high > iZone.Lower() && + bar.low < iZone.Lower()) || + (bar.low > iZone.Lower() && + bar.high < iZone.Upper()) + // + ; + if (isValid) + { + Add( + iZone, + obs // + ); + } + } + + // + Clean(tmpState.bearishOrderBlocks); + Copy( + obs, + tmpState.bearishOrderBlocks // + ); + } + + // + // Bullish Fair Value Gaps ... + int bullishFairValueGapsCount = ArraySize(tmpState.bullishFairValueGaps); + if (IsValidSize(bullishFairValueGapsCount)) + { + // + XCFVG *obs[]; + for (int i = 0; i < bullishFairValueGapsCount; i++) + { + // + XCFVG *iZone = tmpState.bullishFairValueGaps[i]; + + // + bool isValid = + // + (bar.low < iZone.Upper() && + bar.high > iZone.Upper()) || + (bar.high > iZone.Lower() && + bar.low < iZone.Lower()) || + (bar.low > iZone.Lower() && + bar.high < iZone.Upper()) + // + ; + if (isValid) + { + Add( + iZone, + obs // + ); + } + } + + // + Clean(tmpState.bullishFairValueGaps); + Copy( + obs, + tmpState.bullishFairValueGaps // + ); + } + + // + // Bearish Fair Value Gaps ... + int bearishFairValueGapsCount = ArraySize(tmpState.bearishFairValueGaps); + if (IsValidSize(bearishFairValueGapsCount)) + { + // + XCFVG *obs[]; + for (int i = 0; i < bearishFairValueGapsCount; i++) + { + // + XCFVG *iZone = tmpState.bearishFairValueGaps[i]; + + // + bool isValid = + // + (bar.low < iZone.Upper() && + bar.high > iZone.Upper()) || + (bar.high > iZone.Lower() && + bar.low < iZone.Lower()) || + (bar.low > iZone.Lower() && + bar.high < iZone.Upper()) + // + ; + if (isValid) + { + Add( + iZone, + obs // + ); + } + } + + // + Clean(tmpState.bearishFairValueGaps); + Copy( + obs, + tmpState.bearishFairValueGaps // + ); + } + } + } + + // + bool drawSwingHighs = true; + bool drawSwingLows = true; + bool drawSupportZones = true; + bool drawResistanceZones = true; + bool drawSupplyZones = true; + bool drawDemandZones = true; + bool drawBullishOrderBlocks = true; + bool drawBearishOrderBlocks = true; + bool drawBullishFairValueGaps = true; + bool drawBearishFairValueGaps = true; + bool drawBullishRejectionBars = true; + bool drawBearishRejectionBars = true; + bool drawBullishMomentumBars = true; + bool drawBearishMomentumBars = true; + + // + // Change Drawing Specs Conditions based on + // Provided Direction ... + if (forDir == X_DIRECTION_BULLISH) + { + // + drawSwingLows = true; + drawDemandZones = true; + drawSupportZones = true; + drawBullishOrderBlocks = true; + drawBullishFairValueGaps = true; + drawBullishRejectionBars = true; + drawBullishMomentumBars = true; + + // + drawSwingHighs = false; + drawSupplyZones = false; + drawResistanceZones = false; + drawBearishOrderBlocks = false; + drawBearishFairValueGaps = false; + drawBearishRejectionBars = false; + drawBearishMomentumBars = false; + } + else if (forDir == X_DIRECTION_BEARISH) + { + // + drawSwingLows = false; + drawDemandZones = false; + drawSupportZones = false; + drawBullishOrderBlocks = false; + drawBullishFairValueGaps = false; + drawBullishRejectionBars = false; + drawBullishMomentumBars = false; + + // + drawSwingHighs = true; + drawSupplyZones = true; + drawResistanceZones = true; + drawBearishOrderBlocks = true; + drawBearishFairValueGaps = true; + drawBearishRejectionBars = true; + drawBearishMomentumBars = true; + } + + // + // Apply Ignore List ... + + // + if (ignoreSwingHighs) + { + drawSwingHighs = false; + } + + // + if (ignoreSwingLows) + { + drawSwingLows = false; + } + + // + if (ignoreSupportZones) + { + drawSupportZones = false; + } + + // + if (ignoreResistanceZones) + { + drawResistanceZones = false; + } + + // + if (ignoreSupplyZones) + { + drawSupplyZones = false; + } + + // + if (ignoreDemandZones) + { + drawDemandZones = false; + } + + // + if (ignoreBullishOrderBlocks) + { + drawBullishOrderBlocks = false; + } + + // + if (ignoreBearishOrderBlocks) + { + drawBearishOrderBlocks = false; + } + + // + if (ignoreBullishFairValueGaps) + { + drawBullishFairValueGaps = false; + } + + // + if (ignoreBearishFairValueGaps) + { + drawBearishFairValueGaps = false; + } + + // + if (ignoreBullishRejectionBars) + { + drawBullishRejectionBars = false; + } + + // + if (ignoreBearishRejectionBars) + { + drawBearishRejectionBars = false; + } + + // + if (ignoreBullishMomentumBars) + { + drawBullishMomentumBars = false; + } + + // + if (ignoreBearishMomentumBars) + { + drawBearishMomentumBars = false; + } + + // + DrawState( + tmpState, // State ... + true, // Update To of all Drawings Till now ... + drawSwingHighs, // Draw SwingHighs .. + drawSwingLows, // Draw SwingLows .. + drawSupportZones, // Draw SupportZones .. + drawResistanceZones, // Draw ResistanceZones .. + drawSupplyZones, // Draw SupplyZones .. + drawDemandZones, // Draw DemandZones .. + drawBullishOrderBlocks, // Draw BullishOrderBlocks .. + drawBearishOrderBlocks, // Draw BearishOrderBlocks .. + drawBullishFairValueGaps, // Draw BullishFairValueGaps .. + drawBearishFairValueGaps, // Draw BearishFairValueGaps .. + drawBullishRejectionBars, // Draw BullishRejectionBars .. + drawBearishRejectionBars, // Draw BearishRejectionBars .. + drawBullishMomentumBars, // Draw BullishMomentumBars .. + drawBearishMomentumBars, // Draw BearishMomentumBars .. + true // Draw Ticks Zone ... + ); + } + + /** + * Draw Specific Pivot ... + * + * @param pivot: XPVPivot instance Reference ... + * @param drawState: Boolean ... + * @param filterByPrice: 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 ... + */ + void DrawPivot( + XPVPivot &pivot, + bool drawState = true, + bool filterByPrice = false, + bool ignoreSwingHighs = false, + bool ignoreSwingLows = false, + bool ignoreSupportZones = false, + bool ignoreResistanceZones = false, + bool ignoreSupplyZones = false, + bool ignoreDemandZones = false, + bool ignoreBullishOrderBlocks = false, + bool ignoreBearishOrderBlocks = false, + bool ignoreBullishFairValueGaps = false, + bool ignoreBearishFairValueGaps = false, + bool ignoreBullishRejectionBars = false, + bool ignoreBearishRejectionBars = false, + bool ignoreBullishMomentumBars = false, + bool ignoreBearishMomentumBars = false // + ) + { + // + if (!pivot.IsValid()) + { + return; + } + + // + // Draw Pivot it self ... + XCXPVPivotObject *iPivotObj; + iPivotObj = new XCXPVPivotObject(); + bool isCreated = iPivotObj.Create( + mPOIDrawer.ChartIdentification(), + mPOIDrawer.SubWindowIdentification(), + pivot // + ); + if (!isCreated) + { + return; + } + + // + color clrPivotColor = pivot.IsPeak() + ? clrAqua + : clrMagenta; + iPivotObj.PivotColor(clrPivotColor); + iPivotObj.PivotWidth(2); + + // + AddObjectIfNotExists(iPivotObj); + + // + if (!drawState) + { + return; + } + + // + if (!pivot.state.IsValid()) + { + return; + } + + // + CustomStateDrawing( + pivot.state, + filterByPrice, + false, // forceDrawSamePeriod + X_DIRECTION_NONE, // forDir + ignoreSwingHighs, + ignoreSwingLows, + ignoreSupportZones, + ignoreResistanceZones, + ignoreSupplyZones, + ignoreDemandZones, + ignoreBullishOrderBlocks, + ignoreBearishOrderBlocks, + ignoreBullishFairValueGaps, + ignoreBearishFairValueGaps, + ignoreBullishRejectionBars, + ignoreBearishRejectionBars, + ignoreBullishMomentumBars, + ignoreBearishMomentumBars // + ); + } + + // +}; + +// \ No newline at end of file

  • `0o?o(596ZB=dia(Va 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