diff --git a/BKPS/14031218/Classes/x-saherelm.base.class.mq5 b/BKPS/14031218/Classes/x-saherelm.base.class.mq5 new file mode 100644 index 0000000..0e7557f --- /dev/null +++ b/BKPS/14031218/Classes/x-saherelm.base.class.mq5 @@ -0,0 +1,101 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XBaseClass +// Description: provides all based classes for use ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// XBase Class ... +class XCBase +{ + // + // Public ... + public: + // + // Protected ... + + // + // Represent Basic Unique Tag ... + virtual string GetTag() { + return NULL; + } + + // + // Retrieve Class Token ... + virtual string GetToken() { + return NULL; + } + + // + // Protected + protected: + // + // Private ... + private: +}; + +// +template +string GenerateSpecifiedCommonSummary( + T &mItem, + string separator = "\n", + bool includeScores = true, + bool setLabel = false // +) +{ + // + string result = NULL; + + // + double bullishScore = 0; + double bearishScore = 0; + mItem.GenerateScore( + bullishScore, + bearishScore // + ); + + // + result = + // + (!setLabel + ? "" + : "Commons:" + separator) + + "---------------" + separator + + "Symbol: " + mItem.symbol + separator + + "Period: " + ToString(mItem.period) + separator + + "Time: " + ToString(mItem.time) + separator + + (includeScores + ? "---------------" + separator + + "Scores:" + separator + + "---------------" + separator + + "Bullish: " + ToString(bullishScore) + separator + + "Bearish: " + ToString(bearishScore) + separator + + "---------------" + separator + : "") + + "" + // + ; + + // + return result; +} + +// diff --git a/BKPS/14031218/Classes/x-saherelm.x-account.class.mq5 b/BKPS/14031218/Classes/x-saherelm.x-account.class.mq5 new file mode 100644 index 0000000..c451091 --- /dev/null +++ b/BKPS/14031218/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/14031218/Classes/x-saherelm.x-alert.class.mq5 b/BKPS/14031218/Classes/x-saherelm.x-alert.class.mq5 new file mode 100644 index 0000000..c92a6d5 --- /dev/null +++ b/BKPS/14031218/Classes/x-saherelm.x-alert.class.mq5 @@ -0,0 +1,1580 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCAlert +// Description: provides all Alerts requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.base.class.mq5" + +// +// Class Definition ... + +class XCAlert : public XCBase +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructor ... + XCAlert( + string prefix = "X-Alert", // Alerts Prefixe + bool enableAlerts = true, // Enable Alerts + bool logAlerts = true, // Log Alerts + bool terminalAlerts = false, // Terminal Alerts + bool mailAlerts = false, // Mail Alerts + bool pushAlerts = false // Push Alerts + ) + { + // + mPrefix = prefix; + mLogAlerts = logAlerts; + mMailAlerts = mailAlerts; + mPushAlerts = pushAlerts; + mEnableAlerts = enableAlerts; + mTerminalAlerts = terminalAlerts; + + // + // Normalize Prefix if Not Provided ... + if (!IsValid(mPrefix)) + { + mPrefix = GetTag(); + } + } + + // + // Deconstructor ... + ~XCAlert() + { + } + + // + // Override ... + string GetTag() override + { + return GetSpecificToken(this); + } + + // + // Properties Getter(s) / Setter(s) ... + + // + string GetPrefix() + { + return mPrefix; + } + + // + void SetPrefix(string value) + { + mPrefix = value; + } + + // + bool GetLogAlerts() + { + return mLogAlerts; + } + + // + void SetLogAlerts(bool value) + { + mLogAlerts = value; + } + + // + bool GetEnableAlerts() + { + return mEnableAlerts; + } + + // + void SetEnableAlerts(bool value) + { + mEnableAlerts = value; + } + + // + bool GetPushAlerts() + { + return mPushAlerts; + } + + // + void SetPushAlerts(bool value) + { + mPushAlerts = value; + } + + // + bool GetMailAlerts() + { + return mMailAlerts; + } + + // + void SetMailAlerts(bool value) + { + mMailAlerts = value; + } + + // + bool GetTerminalAlerts() + { + return mTerminalAlerts; + } + + // + void SetTerminalAlerts(bool value) + { + mTerminalAlerts = value; + } + + // + // Tools Funtions ... + + // + // Alerts ... + + // + // Logging an Alert ... + void LogAlert(string message) + { + // + // Validate Args ... + if (!CanLogAlert()) + { + return; + } + + // + Log(message); + } + + // + // Terminal Alert ... + void TerminalAlert(string message) + { + // + // Validate Args ... + if (!CanTerminalAlert()) + { + return; + } + + // + // Prepare Message ... + message = PrepareMessage(message); + + // Send Terminal Alert ... + Alert(message); + } + + // + // Mail Alert ... + void MailAlert(string message) + { + // + // Validate Args ... + if (!CanMailAlert()) + { + return; + } + + // + // Send Mail Alert ... + SendMail(GetPrefix(), message); + } + + // + // Send Push Notification ... + void PushAlert(string message) + { + // + // Validate Args ... + if (!CanPushAlert()) + { + return; + } + + // + // Prepare Message ... + message = PrepareMessage(message); + + // + // Send Push Notification Alert ... + SendNotification(message); + } + + // + // Send an Alert by Handling all Different Specified + // type's of Alert's if they are Enabled ... + void Alert(string message) + { + // + // Handle Log, if Enabled ... + LogAlert(message); + + // + // Handle Mail if Enabled ... + MailAlert(message); + + // + // Handle Push if Enabled ... + PushAlert(message); + + // + // Handle Terminal if Enabled ... + TerminalAlert(message); + } + + // + // Logs ... + + // + // Log a Message ... + void Log(string message) + { + // + if (!CanLog()) + { + return; + } + + // + Print(GetPrefix(), " > ", message); + } + void Log(string tag, string message) + { + // + if (!CanLog()) + { + return; + } + + // + Print(GetPrefix(), "_", tag, " > ", message); + } + void LogEmpty() + { + // + if (!CanLog()) + { + return; + } + + // + Print(" "); + } + + // + // Log Specific Array ... + template + void LogArray( + T &array[], // Array to Log + string label = NULL // Array Label + ) + { + // + if (!CanLog()) + { + return; + } + + // + Print(GetPrefix(), ">", (IsValid(label) ? label : "")); + ArrayPrint(array); + } + + // + // Error ... + + // + // Log an Error ... + void LogError( + int error = -1 // Specific Error, if it's equal to -1, use Last Error ... + ) + { + // + if (!CanLog()) + { + return; + } + + // + if (error <= -1) + { + error = GetLastError(); + } + + // + string errorMsg = GetErrorDescription(error); + + // + Log("Error: " + errorMsg); + } + + // + // Retrieve Specified Error Code Description ... + string GetErrorDescription(int err_code) + { + // + string result = ""; + + // + switch (err_code) + { + // + //--- Constant Description + + // + case ERR_SUCCESS: + result = "The operation completed successfully"; + break; + + // + case ERR_INTERNAL_ERROR: + result = "Unexpected internal error"; + break; + + // + case ERR_WRONG_INTERNAL_PARAMETER: + result = "Wrong parameter in the inner call of the client terminal function"; + break; + + // + case ERR_INVALID_PARAMETER: + result = "Wrong parameter when calling the system function"; + break; + + // + case ERR_NOT_ENOUGH_MEMORY: + result = "Not enough memory to perform the system function"; + break; + + // + case ERR_STRUCT_WITHOBJECTS_ORCLASS: + result = "The structure contains objects of strings and/or dynamic arrays and/or structure of such objects and/or classes"; + break; + + // + case ERR_INVALID_ARRAY: + result = "Array of a wrong type, wrong size, or a damaged object of a dynamic array"; + break; + + // + case ERR_ARRAY_RESIZE_ERROR: + result = "Not enough memory for the relocation of an array, or an attempt to change the size of a static array"; + break; + + // + case ERR_STRING_RESIZE_ERROR: + result = "Not enough memory for the relocation of string"; + break; + + // + case ERR_NOTINITIALIZED_STRING: + result = "Not initialized string"; + break; + + // + case ERR_INVALID_DATETIME: + result = "Invalid date and/or time"; + break; + + // + case ERR_ARRAY_BAD_SIZE: + result = "Requested array size exceeds 2 GB"; + break; + + // + case ERR_INVALID_POINTER: + result = "Wrong pointer"; + break; + + // + case ERR_INVALID_POINTER_TYPE: + result = "Wrong type of pointer"; + break; + + // + case ERR_FUNCTION_NOT_ALLOWED: + result = "System function is not allowed to call"; + break; + + // + //--- Charts + + // + case ERR_CHART_WRONG_ID: + result = "Wrong chart ID"; + break; + + // + case ERR_CHART_NO_REPLY: + result = "Chart does not respond"; + break; + + // + case ERR_CHART_NOT_FOUND: + result = "Chart not found"; + break; + + // + case ERR_CHART_NO_EXPERT: + result = "No Expert Advisor in the chart that could handle the event"; + break; + + // + case ERR_CHART_CANNOT_OPEN: + result = "Chart opening error"; + break; + + // + case ERR_CHART_CANNOT_CHANGE: + result = "Failed to change chart symbol and period"; + break; + + // + case ERR_CHART_CANNOT_CREATE_TIMER: + result = "Failed to create timer"; + break; + + // + case ERR_CHART_WRONG_PROPERTY: + result = "Wrong chart property ID"; + break; + + // + case ERR_CHART_SCREENSHOT_FAILED: + result = "Error creating screenshots"; + break; + + // + case ERR_CHART_NAVIGATE_FAILED: + result = "Error navigating through chart"; + break; + + // + case ERR_CHART_TEMPLATE_FAILED: + result = "Error applying template"; + break; + + // + case ERR_CHART_WINDOW_NOT_FOUND: + result = "Subwindow containing the indicator was not found"; + break; + + // + case ERR_CHART_INDICATOR_CANNOT_ADD: + result = "Error adding an indicator to chart"; + break; + + // + case ERR_CHART_INDICATOR_CANNOT_DEL: + result = "Error deleting an indicator from the chart"; + break; + + // + case ERR_CHART_INDICATOR_NOT_FOUND: + result = "Indicator not found on the specified chart"; + break; + + // + //--- Graphical Objects + case ERR_OBJECT_ERROR: + result = "Error working with a graphical object"; + break; + + // + case ERR_OBJECT_NOT_FOUND: + result = "Graphical object was not found"; + break; + + // + case ERR_OBJECT_WRONG_PROPERTY: + result = "Wrong ID of a graphical object property"; + break; + + // + case ERR_OBJECT_GETDATE_FAILED: + result = "Unable to get date corresponding to the value"; + break; + + // + case ERR_OBJECT_GETVALUE_FAILED: + result = "Unable to get value corresponding to the date"; + break; + + // + //--- MarketInfo + + // + case ERR_MARKET_UNKNOWN_SYMBOL: + result = "Unknown symbol"; + break; + + // + case ERR_MARKET_NOT_SELECTED: + result = "Symbol is not selected in MarketWatch"; + break; + + // + case ERR_MARKET_WRONG_PROPERTY: + result = "Wrong identifier of a symbol property"; + break; + + // + case ERR_MARKET_LASTTIME_UNKNOWN: + result = "Time of the last tick is not known (no ticks)"; + break; + + // + case ERR_MARKET_SELECT_ERROR: + result = "Error adding or deleting a symbol in MarketWatch"; + break; + + // + //--- History Access + + // + case ERR_HISTORY_NOT_FOUND: + result = "Requested history not found"; + break; + + // + case ERR_HISTORY_WRONG_PROPERTY: + result = "Wrong ID of the history property"; + break; + + // + //--- Global_Variables + + // + case ERR_GLOBALVARIABLE_NOT_FOUND: + result = "Global variable of the client terminal is not found"; + break; + + // + case ERR_GLOBALVARIABLE_EXISTS: + result = "Global variable of the client terminal with the same name already exists"; + break; + + // + case ERR_MAIL_SEND_FAILED: + result = "Email sending failed"; + break; + + // + case ERR_PLAY_SOUND_FAILED: + result = "Sound playing failed"; + break; + + // + case ERR_MQL5_WRONG_PROPERTY: + result = "Wrong identifier of the program property"; + break; + + // + case ERR_TERMINAL_WRONG_PROPERTY: + result = "Wrong identifier of the terminal property"; + break; + + // + case ERR_FTP_SEND_FAILED: + result = "File sending via ftp failed"; + break; + + // + case ERR_NOTIFICATION_SEND_FAILED: + result = "Error in sending notification"; + break; + + // + //--- Custom Indicator Buffers + + // + case ERR_BUFFERS_NO_MEMORY: + result = "Not enough memory for the distribution of indicator buffers"; + break; + + // + case ERR_BUFFERS_WRONG_INDEX: + result = "Wrong indicator buffer index"; + break; + + // + //--- Custom Indicator Properties + + // + case ERR_CUSTOM_WRONG_PROPERTY: + result = "Wrong ID of the custom indicator property"; + break; + + // + //--- Account + + // + case ERR_ACCOUNT_WRONG_PROPERTY: + result = "Wrong account property ID"; + break; + + // + case ERR_TRADE_WRONG_PROPERTY: + result = "Wrong trade property ID"; + break; + + // + case ERR_TRADE_DISABLED: + result = "Trading by Expert Advisors prohibited"; + break; + + // + case ERR_TRADE_POSITION_NOT_FOUND: + result = "Position not found"; + break; + + // + case ERR_TRADE_ORDER_NOT_FOUND: + result = "Order not found"; + break; + + // + case ERR_TRADE_DEAL_NOT_FOUND: + result = "Deal not found"; + break; + + // + case ERR_TRADE_SEND_FAILED: + result = "Trade request sending failed"; + break; + + // + //--- Indicators + + // + case ERR_INDICATOR_UNKNOWN_SYMBOL: + result = "Unknown symbol"; + break; + + // + case ERR_INDICATOR_CANNOT_CREATE: + result = "Indicator cannot be created"; + break; + + // + case ERR_INDICATOR_NO_MEMORY: + result = "Not enough memory to add the indicator"; + break; + + // + case ERR_INDICATOR_CANNOT_APPLY: + result = "The indicator cannot be applied to another indicator"; + break; + + // + case ERR_INDICATOR_CANNOT_ADD: + result = "Error applying an indicator to chart"; + break; + + // + case ERR_INDICATOR_DATA_NOT_FOUND: + result = "Requested data not found"; + break; + + // + case ERR_INDICATOR_WRONG_HANDLE: + result = "Wrong indicator handle"; + break; + + // + case ERR_INDICATOR_WRONG_PARAMETERS: + result = "Wrong number of parameters when creating an indicator"; + break; + + // + case ERR_INDICATOR_PARAMETERS_MISSING: + result = "No parameters when creating an indicator"; + break; + + // + case ERR_INDICATOR_CUSTOM_NAME: + result = "The first parameter in the array must be the name of the custom indicator"; + break; + + // + case ERR_INDICATOR_PARAMETER_TYPE: + result = "Invalid parameter type in the array when creating an indicator"; + break; + + // + case ERR_INDICATOR_WRONG_INDEX: + result = "Wrong index of the requested indicator buffer"; + break; + + // + //--- Depth of Market + + // + case ERR_BOOKS_CANNOT_ADD: + result = "Depth Of Market can not be added"; + break; + + // + case ERR_BOOKS_CANNOT_DELETE: + result = "Depth Of Market can not be removed"; + break; + + // + case ERR_BOOKS_CANNOT_GET: + result = "The data from Depth Of Market can not be obtained"; + break; + + // + case ERR_BOOKS_CANNOT_SUBSCRIBE: + result = "Error in subscribing to receive new data from Depth Of Market"; + break; + + // + //--- File Operations + + // + case ERR_TOO_MANY_FILES: + result = "More than 64 files cannot be opened at the same time"; + break; + + // + case ERR_WRONG_FILENAME: + result = "Invalid file name"; + break; + + // + case ERR_TOO_LONG_FILENAME: + result = "Too long file name"; + break; + + // + case ERR_CANNOT_OPEN_FILE: + result = "File opening error"; + break; + + // + case ERR_FILE_CACHEBUFFER_ERROR: + result = "Not enough memory for cache to read"; + break; + + // + case ERR_CANNOT_DELETE_FILE: + result = "File deleting error"; + break; + + // + case ERR_INVALID_FILEHANDLE: + result = "A file with this handle was closed, or was not opening at all"; + break; + + // + case ERR_WRONG_FILEHANDLE: + result = "Wrong file handle"; + break; + + // + case ERR_FILE_NOTTOWRITE: + result = "The file must be opened for writing"; + break; + + // + case ERR_FILE_NOTTOREAD: + result = "The file must be opened for reading"; + break; + + // + case ERR_FILE_NOTBIN: + result = "The file must be opened as a binary one"; + break; + + // + case ERR_FILE_NOTTXT: + result = "The file must be opened as a text"; + break; + + // + case ERR_FILE_NOTTXTORCSV: + result = "The file must be opened as a text or CSV"; + break; + + // + case ERR_FILE_NOTCSV: + result = "The file must be opened as CSV"; + break; + + // + case ERR_FILE_READERROR: + result = "File reading error"; + break; + + // + case ERR_FILE_BINSTRINGSIZE: + result = "String size must be specified, because the file is opened as binary"; + break; + + // + case ERR_INCOMPATIBLE_FILE: + result = "A text file must be for string arrays, for other arrays - binary"; + break; + + // + case ERR_FILE_IS_DIRECTORY: + result = "This is not a file, this is a directory"; + break; + + // + case ERR_FILE_NOT_EXIST: + result = "File does not exist"; + break; + + // + case ERR_FILE_CANNOT_REWRITE: + result = "File can not be rewritten"; + break; + + // + case ERR_WRONG_DIRECTORYNAME: + result = "Wrong directory name"; + break; + + // + case ERR_DIRECTORY_NOT_EXIST: + result = "Directory does not exist"; + break; + + // + case ERR_FILE_ISNOT_DIRECTORY: + result = "This is a file, not a directory"; + break; + + // + case ERR_CANNOT_DELETE_DIRECTORY: + result = "The directory cannot be removed"; + break; + + // + case ERR_CANNOT_CLEAN_DIRECTORY: + result = "Failed to clear the directory (probably one or more files are blocked and removal operation failed)"; + break; + + // + case ERR_FILE_WRITEERROR: + result = "Failed to write a resource to a file"; + break; + + // + //--- String Casting + + // + case ERR_NO_STRING_DATE: + result = "No date in the string"; + break; + + // + case ERR_WRONG_STRING_DATE: + result = "Wrong date in the string"; + break; + + // + case ERR_WRONG_STRING_TIME: + result = "Wrong time in the string"; + break; + + // + case ERR_STRING_TIME_ERROR: + result = "Error converting string to date"; + break; + + // + case ERR_STRING_OUT_OF_MEMORY: + result = "Not enough memory for the string"; + break; + + // + case ERR_STRING_SMALL_LEN: + result = "The string length is less than expected"; + break; + + // + case ERR_STRING_TOO_BIGNUMBER: + result = "Too large number, more than ULONG_MAX"; + break; + + // + case ERR_WRONG_FORMATSTRING: + result = "Invalid format string"; + break; + + // + case ERR_TOO_MANY_FORMATTERS: + result = "Amount of format specifiers more than the parameters"; + break; + + // + case ERR_TOO_MANY_PARAMETERS: + result = "Amount of parameters more than the format specifiers"; + break; + + // + case ERR_WRONG_STRING_PARAMETER: + result = "Damaged parameter of string type"; + break; + + // + case ERR_STRINGPOS_OUTOFRANGE: + result = "Position outside the string"; + break; + + // + case ERR_STRING_ZEROADDED: + result = "0 added to the string end, a useless operation"; + break; + + // + case ERR_STRING_UNKNOWNTYPE: + result = "Unknown data type when converting to a string"; + break; + + // + case ERR_WRONG_STRING_OBJECT: + result = "Damaged string object"; + break; + + // + //--- Operations with Arrays + + // + case ERR_INCOMPATIBLE_ARRAYS: + result = "Copying incompatible arrays. String array can be copied only to a string array, and a numeric array - in numeric array only"; + break; + + // + case ERR_SMALL_ASSERIES_ARRAY: + result = "The receiving array is declared as AS_SERIES, and it is of insufficient size"; + break; + + // + case ERR_SMALL_ARRAY: + result = "Too small array, the starting position is outside the array"; + break; + + // + case ERR_ZEROSIZE_ARRAY: + result = "An array of zero length"; + break; + + // + case ERR_NUMBER_ARRAYS_ONLY: + result = "Must be a numeric array"; + break; + + // + case ERR_ONEDIM_ARRAYS_ONLY: + result = "Must be a one-dimensional array"; + break; + + // + case ERR_SERIES_ARRAY: + result = "Timeseries cannot be used"; + break; + + // + case ERR_DOUBLE_ARRAY_ONLY: + result = "Must be an array of type double"; + break; + + // + case ERR_FLOAT_ARRAY_ONLY: + result = "Must be an array of type float"; + break; + + // + case ERR_LONG_ARRAY_ONLY: + result = "Must be an array of type long"; + break; + + // + case ERR_INT_ARRAY_ONLY: + result = "Must be an array of type int"; + break; + + // + case ERR_SHORT_ARRAY_ONLY: + result = "Must be an array of type short"; + break; + + // + case ERR_CHAR_ARRAY_ONLY: + result = "Must be an array of type char"; + break; + + // + //--- Operations with OpenCL + + // + case ERR_OPENCL_NOT_SUPPORTED: + result = "OpenCL functions are not supported on this computer"; + break; + + // + case ERR_OPENCL_INTERNAL: + result = "Internal error occurred when running OpenCL"; + break; + + // + case ERR_OPENCL_INVALID_HANDLE: + result = "Invalid OpenCL handle"; + break; + + // + case ERR_OPENCL_CONTEXT_CREATE: + result = "Error creating the OpenCL context"; + break; + + // + case ERR_OPENCL_QUEUE_CREATE: + result = "Failed to create a run queue in OpenCL"; + break; + + // + case ERR_OPENCL_PROGRAM_CREATE: + result = "Error occurred when compiling an OpenCL program"; + break; + + // + case ERR_OPENCL_TOO_LONG_KERNEL_NAME: + result = "Too long kernel name (OpenCL kernel)"; + break; + + // + case ERR_OPENCL_KERNEL_CREATE: + result = "Error creating an OpenCL kernel"; + break; + + // + case ERR_OPENCL_SET_KERNEL_PARAMETER: + result = "Error occurred when setting parameters for the OpenCL kernel"; + break; + + // + case ERR_OPENCL_EXECUTE: + result = "OpenCL program runtime error"; + break; + + // + case ERR_OPENCL_WRONG_BUFFER_SIZE: + result = "Invalid size of the OpenCL buffer"; + break; + + // + case ERR_OPENCL_WRONG_BUFFER_OFFSET: + result = "Invalid offset in the OpenCL buffer"; + break; + + // + case ERR_OPENCL_BUFFER_CREATE: + result = "Failed to create and OpenCL buffer"; + break; + + // + //--- User-Defined Errors + default: + result = "UNKNOWN Erro ..."; + break; + } + + // + return result; + } + + // + // Retrieve Specified Error Code Description ... + string GetTradeServerReturnCodeDescription(int return_code) + { + // + string result = ""; + + // + switch (return_code) + { + // + case TRADE_RETCODE_REQUOTE: + result = "Requote"; + break; + + // + case TRADE_RETCODE_REJECT: + result = "Request rejected"; + break; + + // + case TRADE_RETCODE_CANCEL: + result = "Request canceled by trader"; + break; + + // + case TRADE_RETCODE_PLACED: + result = "Order placed"; + break; + + // + case TRADE_RETCODE_DONE: + result = "Request completed"; + break; + + // + case TRADE_RETCODE_DONE_PARTIAL: + result = "Only part of the request was completed"; + break; + + // + case TRADE_RETCODE_ERROR: + result = "Request processing error"; + break; + + // + case TRADE_RETCODE_TIMEOUT: + result = "Request canceled by timeout"; + break; + + // + case TRADE_RETCODE_INVALID: + result = "Invalid request"; + break; + + // + case TRADE_RETCODE_INVALID_VOLUME: + result = "Invalid volume in the request"; + break; + + // + case TRADE_RETCODE_INVALID_PRICE: + result = "Invalid price in the request"; + break; + + // + case TRADE_RETCODE_INVALID_STOPS: + result = "Invalid stops in the request"; + break; + + // + case TRADE_RETCODE_TRADE_DISABLED: + result = "Trade is disabled"; + break; + + // + case TRADE_RETCODE_MARKET_CLOSED: + result = "Market is closed"; + break; + + // + case TRADE_RETCODE_NO_MONEY: + result = "There is not enough money to complete the request"; + break; + + // + case TRADE_RETCODE_PRICE_CHANGED: + result = "Prices changed"; + break; + + // + case TRADE_RETCODE_PRICE_OFF: + result = "There are no quotes to process the request"; + break; + + // + case TRADE_RETCODE_INVALID_EXPIRATION: + result = "Invalid order expiration date in the request"; + break; + + // + case TRADE_RETCODE_ORDER_CHANGED: + result = "Order state changed"; + break; + + // + case TRADE_RETCODE_TOO_MANY_REQUESTS: + result = "Too frequent requests"; + break; + + // + case TRADE_RETCODE_NO_CHANGES: + result = "No changes in request"; + break; + + // + case TRADE_RETCODE_SERVER_DISABLES_AT: + result = "Autotrading disabled by server"; + break; + + // + case TRADE_RETCODE_CLIENT_DISABLES_AT: + result = "Autotrading disabled by client terminal"; + break; + + // + case TRADE_RETCODE_LOCKED: + result = "Request locked for processing"; + break; + + // + case TRADE_RETCODE_FROZEN: + result = "Order or position frozen"; + break; + + // + case TRADE_RETCODE_INVALID_FILL: + result = "Invalid order filling type"; + break; + + // + case TRADE_RETCODE_CONNECTION: + result = "No connection with the trade server"; + break; + + // + case TRADE_RETCODE_ONLY_REAL: + result = "Operation is allowed only for live accounts"; + break; + + // + case TRADE_RETCODE_LIMIT_ORDERS: + result = "The number of pending orders has reached the limit"; + break; + + // + case TRADE_RETCODE_LIMIT_VOLUME: + result = "The volume of orders and positions for the symbol has reached the limit"; + break; + + // + default: + result = "Invalid return code of the trade server"; + break; + } + + // + return result; + } + + // + // Protected ... + protected: + // + // Private ... + + // + bool CanLog() + { + return mLogAlerts; + } + + // + bool CanLogAlert() + { + // + bool result = GetEnableAlerts() && GetLogAlerts(); + + // + return result; + } + + // + bool CanTerminalAlert() + { + // + bool result = GetEnableAlerts() && GetTerminalAlerts(); + + // + return result; + } + + // + bool CanMailAlert() + { + // + bool result = GetEnableAlerts() && GetMailAlerts(); + + // + return result; + } + + // + bool CanPushAlert() + { + // + bool result = GetEnableAlerts() && GetPushAlerts(); + + // + return result; + } + + private: + // + // Props ... + string mPrefix; // Alerts Prefixe + bool mEnableAlerts; // Enable Alerts + bool mLogAlerts; // Log Alerts + bool mTerminalAlerts; // Terminal Alerts + bool mMailAlerts; // Mail Alerts + bool mPushAlerts; // Push Alerts + + // + // Tools ... + + // + // Clear Escape String and + // Attach Alert Prefix to Message ... + string PrepareMessage(string message) + { + // + StringReplace(message, "\n", " | "); + + // + StringConcatenate(message, GetPrefix(), " > ", message); + + // + return message; + } +}; + +// +// a Base Class by Support Alert ... +class XCBaseAlert : public XCBase +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructor(s) ... + void XCBaseAlert() + { + // + // Instance Alert ... + mAlert = new XCAlert(); + } + + // + // Deconstructors ... + void ~XCBaseAlert() + { + // + delete mAlert; + + // + ZeroMemory(mAlert); + } + + // + // Alert Handler Functions ... + + // + // Alert Functions Getter(s) / Setters(s) ... + + // + string GetAlertPrefix() + { + return mAlert.GetPrefix(); + } + + // + void SetAlertPrefix(string value) + { + mAlert.SetPrefix(value); + } + + // + bool GetAlertLogAlerts() + { + return mAlert.GetLogAlerts(); + } + + // + void SetAlertLogAlerts(bool value) + { + mAlert.SetLogAlerts(value); + } + + // + bool GetAlertEnableAlerts() + { + return mAlert.GetEnableAlerts(); + } + + // + void SetAlertEnableAlerts(bool value) + { + mAlert.SetEnableAlerts(value); + } + + // + bool GetAlertPushAlerts() + { + return mAlert.GetPushAlerts(); + } + + // + void SetAlertPushAlerts(bool value) + { + mAlert.SetPushAlerts(value); + } + + // + bool GetAlertMailAlerts() + { + return mAlert.GetMailAlerts(); + } + + // + void SetAlertMailAlerts(bool value) + { + mAlert.SetMailAlerts(value); + } + + // + bool GetAlertTerminalAlerts() + { + return mAlert.GetTerminalAlerts(); + } + + // + void SetAlertTerminalAlerts(bool value) + { + mAlert.SetTerminalAlerts(value); + } + + // + // Alert Actions ... + + // + // Logging an Alert ... + void LogAlert(string message) + { + mAlert.LogAlert(message); + } + + // + // Terminal Alert ... + void TerminalAlert(string message) + { + mAlert.TerminalAlert(message); + } + + // + // Mail Alert ... + void MailAlert(string message) + { + mAlert.MailAlert(message); + } + + // + // Send Push Notification ... + void PushAlert(string message) + { + mAlert.PushAlert(message); + } + + // + // Send an Alert by Handling all Different Specified + // type's of Alert's if they are Enabled ... + void Alert(string message) + { + mAlert.Alert(message); + } + + // + // Logs ... + + // + // Log a Message ... + void Log(string message) + { + mAlert.Log(message); + } + void Log(string tag, string message) + { + mAlert.Log(tag, message); + } + void LogEmpty() + { + mAlert.LogEmpty(); + } + + // + // Log Specific Array ... + template + void LogArray( + T &array[], // Array to Log + string label = NULL // Array Label + ) + { + mAlert.LogArray(array, label); + } + + // + // Error ... + + // + // Log an Error ... + void LogError( + int error = -1 // Specific Error, if it's equal to -1, use Last Error ... + ) + { + mAlert.LogError(error); + } + + // + // Retrieve Specified Error Code Description ... + string GetErrorDescription(int err_code) + { + return mAlert.GetErrorDescription(err_code); + } + + // + // Retrieve Specified Error Code Description ... + string GetTradeServerReturnCodeDescription(int return_code) + { + return mAlert.GetTradeServerReturnCodeDescription(return_code); + } + + // + // Protected ... + protected: + // + // Alert ... + XCAlert *mAlert; + + // + // Private ... + private: +}; + +// \ No newline at end of file diff --git a/BKPS/14031218/Classes/x-saherelm.x-app-dialog.class.mq5 b/BKPS/14031218/Classes/x-saherelm.x-app-dialog.class.mq5 new file mode 100644 index 0000000..6bfa4d9 --- /dev/null +++ b/BKPS/14031218/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/14031218/Classes/x-saherelm.x-bar.analyser.class.ex5 b/BKPS/14031218/Classes/x-saherelm.x-bar.analyser.class.ex5 new file mode 100644 index 0000000..455bf0c Binary files /dev/null and b/BKPS/14031218/Classes/x-saherelm.x-bar.analyser.class.ex5 differ diff --git a/BKPS/14031218/Classes/x-saherelm.x-bar.analyser.class.mq5 b/BKPS/14031218/Classes/x-saherelm.x-bar.analyser.class.mq5 new file mode 100644 index 0000000..2b4b613 --- /dev/null +++ b/BKPS/14031218/Classes/x-saherelm.x-bar.analyser.class.mq5 @@ -0,0 +1,6043 @@ +/////////////////////////////////////////////////////// +// +// 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() + 1; + bool canContinue = true; + int sameBullishBarsFounded = 0; + int sameBearishBarsFounded = 0; + bool canContinueForBullish = true; + bool canContinueForBearish = true; + while (canContinue) + { + // + XOHCL iBar; + result = iBar.Init( + bar.symbol, + bar.period, + index // + ); + if (!result) + { + break; + } + + // + bool isBullish = iBar.IsBullish(); + bool isBearish = iBar.IsBearish(); + result = isBullish || + isBearish; + if (!result) + { + break; + } + + // + if (isBullish) + { + // + sameBullishBarsFounded++; + canContinueForBearish = false; + } + else if (isBearish) + { + // + sameBearishBarsFounded++; + canContinueForBullish = false; + } + else + { + // + sameBullishBarsFounded = 0; + sameBearishBarsFounded = 0; + canContinueForBullish = false; + canContinueForBearish = false; + } + + // + result = canContinueForBullish || + canContinueForBearish; + if (!result) + { + break; + } + + // + canContinueForBullish = + canContinueForBullish && + sameBullishBarsFounded > 0; + + // + canContinueForBearish = + canContinueForBearish && + sameBearishBarsFounded > 0; + + // + canContinue = + canContinueForBullish || + canContinueForBearish; + if (canContinue) + { + index++; + } + } + + // + bool hasBullishSameBars = + sameBullishBarsFounded >= sameBars; + + // + bool hasBearishSameBars = + sameBearishBarsFounded >= sameBars; + + // + result = hasBullishSameBars || + hasBearishSameBars; + if (!result) + { + return result; + } + + // + index--; + + // + dir = + hasBullishSameBars + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; + } + + /** + * Detect Price Consolidation ... + * + * @param bar: XOHCL instance Reference, Start Bar ... + * @param loopback: Integer, Consolidation Length Finder ... + * @param consolidationRange: 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, + int consolidationRange = 50, + 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; + } + + // + 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; + } + + bool HasConsolidationZone( + XOHCL &bar, + XConsolidationZone &zone, + int minLoopback = 3, + double range = 50, + ENUM_APPLIED_PRICE upperAppliedTo = PRICE_HIGH, + ENUM_APPLIED_PRICE lowerAppliedTo = PRICE_LOW // + ) + { + // + bool result = false; + + // + zone.Clean(); + + // + result = bar.IsValid() && + minLoopback > 0 && + range > 0; + if (!result) + { + return result; + } + + // + double points = GetPoints(bar.symbol); + int index = bar.Index() + 1; + int length = minLoopback; + + // + double upperPrice[]; + int upperPriceCount = FillPrice( + upperPrice, + upperAppliedTo, + bar.symbol, + bar.period, + index, + length // + ); + + // + double lowerPrice[]; + int lowerPriceCount = FillPrice( + lowerPrice, + lowerAppliedTo, + bar.symbol, + bar.period, + index, + length // + ); + + // + result = upperPriceCount == lowerPriceCount && + lowerPriceCount == length; + if (!result) + { + // + Clean(upperPrice); + Clean(lowerPrice); + + // + return result; + } + + // + double upper = upperPrice[ArrayMaximum(upperPrice)]; + double lower = lowerPrice[ArrayMinimum(lowerPrice)]; + + // + bool isBullishBreake = + bar.low > lower && + bar.high > upper && + bar.GetUp() > upper; + bool isBearishBreake = + bar.high < upper && + bar.low < lower && + bar.GetDown() < lower; + result = isBullishBreake || + isBearishBreake; + if (!result) + { + // + Clean(upperPrice); + Clean(lowerPrice); + + // + return result; + } + + // + double delta = upper - lower; + result = delta <= range * points; + if (!result) + { + // + Clean(upperPrice); + Clean(lowerPrice); + + // + return result; + } + + // + while (delta <= range * points) + { + // + length++; + + // + upperPriceCount = FillPrice( + upperPrice, + upperAppliedTo, + bar.symbol, + bar.period, + index, + length // + ); + + // + lowerPriceCount = FillPrice( + lowerPrice, + lowerAppliedTo, + bar.symbol, + bar.period, + index, + length // + ); + + // + bool isValid = upperPriceCount == lowerPriceCount && + lowerPriceCount == length; + if (!isValid) + { + break; + } + + // + double iUpper = upperPrice[ArrayMaximum(upperPrice)]; + double iLower = lowerPrice[ArrayMinimum(lowerPrice)]; + + // + delta = iUpper - iLower; + if (delta <= range * points) + { + // + upper = iUpper; + lower = iLower; + } + } + + // + Clean(upperPrice); + Clean(lowerPrice); + + // + // Filling Zone ... + zone.upper = upper; + zone.lower = lower; + zone.symbol = bar.symbol; + zone.period = bar.period; + zone.to = iTime( + bar.symbol, + bar.period, + bar.Index() + 1 // + ); + zone.from = iTime( + bar.symbol, + bar.period, + bar.Index() + length // + ); + zone.dir = isBullishBreake + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = zone.IsValid(); + if (!result) + { + zone.Clean(); + } + + // + return result; + } + + /** + * 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 = HasBullishTrend( + bar, + tmpHSW, + tmpLSW, + true // + ); + + // + bool trend2 = HasBullishTrend( + bar, + 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 = HasBearishTrend( + bar, + tmpHSW, + tmpLSW, + true // + ); + + // + bool trend2 = HasBearishTrend( + bar, + 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 + : IsHammer(iBar); + if (isHammer) + { + founded++; + } + + // + bool isMorningStar = + !checkMorningStar + ? false + : IsMorningStar(iBar); + if (isMorningStar) + { + founded++; + } + + // + bool isBullishMarubozu = + !checkBullishMarubozu + ? false + : IsBullishMarubozu(iBar); + if (isBullishMarubozu) + { + founded++; + } + + // + bool isBullishEngulfing = + !checkBullishEngulfing + ? false + : IsBullishEngulfing(iBar); + 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 + : IsShootingStar(iBar); + if (isShootingStar) + { + founded++; + } + + // + bool isEveningStar = + !checkEveningStar + ? false + : IsEveningStar(iBar); + if (isEveningStar) + { + founded++; + } + + // + bool isBearishMarubozu = + !checkBearishMarubozu + ? false + : IsBearishMarubozu(iBar); + if (isBearishMarubozu) + { + founded++; + } + + // + bool isBearishEngulfing = + !checkBearishEngulfing + ? false + : IsBearishEngulfing(iBar); + 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 Specified Bar is Swing or not ... + * + * @param bar: XOHCL instnce ... + * @param dir: ENUM_X_DIRECTION member ... + * @param range: Integer, Specified Range ... + * + * @return ( bool ) + */ + bool IsSwing( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + int range = 2 // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + bool isSwingLow = IsSwingLow(bar, range); + bool isSwingHigh = IsSwingHigh(bar, range); + + // + result = isSwingLow || + isSwingHigh; + if (result) + { + // + if (isSwingLow) + { + dir = X_DIRECTION_BULLISH; + } + else + { + dir = X_DIRECTION_BEARISH; + } + } + + // + 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); + result = rangePercent > 0; + if (!result) + { + return result; + } + + // + 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 forDir, + ENUM_X_FIBO_LEVELS level // + ) + { + // + bool result = false; + + // + result = bar.IsValid() && + HasDirection(forDir); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + bool isBearish = IsBearish(forDir); + + // + double fiboLevelValue = GetFibonacciLevel( + bar.high, + bar.low, + level, + forDir // + ); + + // + bool isBullishPressured = + isBullish && + bar.GetDown() > fiboLevelValue; + bool isBearishPressured = + isBearish && + bar.GetUp() < fiboLevelValue; + + // + result = isBullishPressured || + isBearishPressured; + + // + return result; + } + + // + // 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 Has Support or not ... + * + * @param bar: XOHCL instance ... + * @param supportBar: XOHCL instance Specified Support Bar ... + * @param rage: int, + * @return ( bool ) + */ + bool HasSupport( + XOHCL &bar, + XOHCL &supportBar, + int range = 21 // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int barIndex = bar.Index() + range; + result = IsValidIndex(barIndex); + if (!result) + { + // + supportBar.Clean(); + return result; + } + result = supportBar.Init( + bar.symbol, + bar.period, + barIndex // + ); + + // + result = supportBar.low < supportBar.GetDown(); + if (!result) + { + // + supportBar.Clean(); + return result; + } + + // + double selectedValue = supportBar.GetDown(); + + // + int llIDX = bar.FindLowestIndex(range - 1, MODE_LOW); + result = IsValidIndex(llIDX); + if (!result) + { + // + supportBar.Clean(); + return result; + } + + // + double llValue = iLow( + bar.symbol, + bar.period, + llIDX // + ); + + // + result = llValue >= selectedValue; + if (!result) + { + // + supportBar.Clean(); + return result; + } + + // + result = supportBar.IsValid(); + + // + 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; + } + + /** + * Check a Bar Has Resistance or not ... + * + * @param bar: XOHCL instance ... + * @param resistanceBar: XOHCL instance Specified Resistance Bar ... + * @param rage: int, + * @return ( bool ) + */ + bool HasResistance( + XOHCL &bar, + XOHCL &resistanceBar, + int range = 21 // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int barIndex = bar.Index() + range; + result = IsValidIndex(barIndex); + if (!result) + { + // + resistanceBar.Clean(); + return result; + } + result = resistanceBar.Init( + bar.symbol, + bar.period, + barIndex // + ); + + // + result = resistanceBar.low < resistanceBar.GetDown(); + if (!result) + { + // + resistanceBar.Clean(); + return result; + } + + // + double selectedValue = resistanceBar.GetUp(); + + // + int hhIDX = bar.FindHighestIndex(range - 1, MODE_HIGH); + result = IsValidIndex(hhIDX); + if (!result) + { + // + resistanceBar.Clean(); + return result; + } + + // + double hhValue = iHigh( + bar.symbol, + bar.period, + hhIDX // + ); + + // + result = hhValue >= selectedValue; + if (!result) + { + // + resistanceBar.Clean(); + return result; + } + + // + result = resistanceBar.IsValid(); + + // + 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 + 1; + 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(); + int from = + index > (to + sameBars) + ? to + sameBars + : index; + 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; + } + + // + // Tools ... + + // + bool IsStrong( + XOHCL &bar, + double percent = 50 // Percent of Body + ) + { + // + bool result = false; + + // + result = bar.IsValid() && + bar.Index() > 0; + if (!result) + { + return result; + } + + // + result = + (bar.GetRange() * percent) / 100 <= bar.GetBody(); + + // + return result; + } + + // + bool HasStrongLowShadow( + XOHCL &bar, + double percent = 50, // Percent of Body + int __loopback = 2, + double _sharpRatio = 2.5 // + ) + { + // + bool result = false; + + // + result = bar.IsValid() && + bar.Index() > 0; + if (!result) + { + return result; + } + + // + result = + (bar.GetRange() * percent) / 100 <= bar.GetLowShadow(); + if (!result) + { + return result; + } + + // + if (__loopback < 0) + { + __loopback = 2; + } + + // + if (_sharpRatio < 0) + { + _sharpRatio = 2.5; + } + + // + result = bar.Index() > __loopback; + if (!result) + { + return result; + } + + // + // Get Highest High and Lowest Low in loopback Range ... + int startIndex = bar.Index() - __loopback; + int endIndex = bar.Index() + __loopback; + int requiredBars = MathAbs(endIndex - startIndex); + + // + // Highs ... + double highs[]; + int copiedHighs = CopyHigh( + bar.symbol, + bar.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( + bar.symbol, + bar.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 = bar.low == lowestLow && + highestHigh > bar.high; + if (!result) + { + return result; + } + + // + // Try to Validate Sharp Ratio ... + + // + Clean(highs); + Clean(lows); + + // + // Left Side ... + startIndex = bar.Index() + 1; + endIndex = startIndex + (__loopback / 2) - 1; + requiredBars = MathAbs(endIndex - startIndex); + + // + copiedHighs = CopyHigh( + bar.symbol, + bar.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( + bar.symbol, + bar.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 = bar.Index() - 1; + endIndex = startIndex - (__loopback / 2) + 1; + requiredBars = MathAbs(endIndex - startIndex); + + // + copiedHighs = CopyHigh( + bar.symbol, + bar.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( + bar.symbol, + bar.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 = bar.GetLowShadow() >= (diff / 100) * _sharpRatio; + + // + return result; + } + + // + bool HasStrongHighShadow( + XOHCL &bar, + double percent = 50, // Percent of Body + int __loopback = 2, + double _sharpRatio = 2.5 // + ) + { + // + bool result = false; + + // + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + result = + (bar.GetRange() * percent) / 100 <= bar.GetHighShadow(); + if (!result) + { + return result; + } + + // + if (__loopback < 0) + { + __loopback = 2; + } + + // + if (_sharpRatio < 0) + { + _sharpRatio = 2.5; + } + + // + result = bar.Index() > __loopback; + if (!result) + { + return result; + } + + // + // Get Highest High and Lowest Low in loopback Range ... + int startIndex = bar.Index() - __loopback; + int endIndex = bar.Index() + __loopback; + int requiredBars = MathAbs(endIndex - startIndex); + + // + // Highs ... + double highs[]; + int copiedHighs = CopyHigh( + bar.symbol, + bar.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( + bar.symbol, + bar.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 = bar.high == highestHigh && + lowestLow < bar.low; + if (!result) + { + return result; + } + + // + // Try to Validate Sharp Ratio ... + + // + Clean(highs); + Clean(lows); + + // + // Left Side ... + startIndex = bar.Index() + 1; + endIndex = startIndex + (__loopback / 2) - 1; + requiredBars = MathAbs(endIndex - startIndex); + + // + copiedHighs = CopyHigh( + bar.symbol, + bar.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( + bar.symbol, + bar.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 = bar.Index() - 1; + endIndex = startIndex - (__loopback / 2) + 1; + requiredBars = MathAbs(endIndex - startIndex); + + // + copiedHighs = CopyHigh( + bar.symbol, + bar.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( + bar.symbol, + bar.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 = bar.GetHighShadow() >= (diff / 100) * _sharpRatio; + + // + return result; + } + + // + bool IsStrongBullish( + XOHCL &bar, + double percent = 50 // Percent of Body + ) + { + // + bool result = false; + + // + result = + bar.IsValid() && + bar.IsBullish() && + IsStrong(bar, percent); + + // + return result; + } + + // + bool IsStrongBearish( + XOHCL &bar, + double percent = 50 // Percent of Body + ) + { + // + bool result = false; + + // + result = + bar.IsValid() && + bar.IsBearish() && + IsStrong(bar, percent); + + // + return result; + } + + // + bool IsSharpBullish( + XOHCL &bar, + int __loopback = 2, + double _sharpRatio = 2.5 // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + if (__loopback < 0) + { + __loopback = 2; + } + + // + if (_sharpRatio < 0) + { + _sharpRatio = 2.5; + } + + // + int hIDX = bar.FindHighestIndex( + __loopback, + MODE_HIGH // + ); + int lIDX = bar.FindLowestIndex( + __loopback, + MODE_LOW // + ); + + // + result = + // + hIDX >= 0 && + lIDX >= 0 && + MathAbs(hIDX - bar.Index()) < 2 + // + ; + + // + if (!result) + { + return result; + } + + // + XOHCL hBar; + result = hBar.Init( + bar.symbol, + bar.period, + hIDX // + ); + if (!result) + { + return result; + } + + // + XOHCL lBar; + result = lBar.Init( + bar.symbol, + bar.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( + bar.symbol, + bar.period, + hhIDX + hIDX // + ); + if (!result) + { + return result; + } + + // + XOHCL llBar; + result = llBar.Init( + bar.symbol, + bar.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( + XOHCL &bar, + int __loopback = 2, + double _sharpRatio = 2.5 // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + if (__loopback < 0) + { + __loopback = 2; + } + + // + if (_sharpRatio < 0) + { + _sharpRatio = 2.5; + } + + // + int hIDX = bar.FindHighestIndex( + __loopback, + MODE_HIGH // + ); + int lIDX = bar.FindLowestIndex( + __loopback, + MODE_LOW // + ); + + // + result = + // + hIDX >= 0 && + lIDX >= 0 && + MathAbs(hIDX - bar.Index()) < 2 + // + ; + + // + if (!result) + { + return result; + } + + // + XOHCL hBar; + result = hBar.Init( + bar.symbol, + bar.period, + hIDX // + ); + if (!result) + { + return result; + } + + // + XOHCL lBar; + result = lBar.Init( + bar.symbol, + bar.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( + bar.symbol, + bar.period, + hhIDX + hIDX // + ); + if (!result) + { + return result; + } + + // + XOHCL llBar; + result = llBar.Init( + bar.symbol, + bar.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; + } + + // + // + // + + // + // Retrieve Bullish Pressure ... + double GetBullishPressure( + XOHCL &bar, + int __loopback = 7 // + ) + { + // + double result = 0; + + // + if (!bar.IsValid()) + { + return result; + } + + // + XOHCL bars[]; + int barsCount = GetBars( + bars, + bar.symbol, + bar.period, + bar.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( + XOHCL &bar, + int __loopback = 7 // + ) + { + // + double result = 0; + + // + if (!bar.IsValid()) + { + return result; + } + + // + XOHCL bars[]; + int barsCount = GetBars( + bars, + bar.symbol, + bar.period, + bar.Index(), + __loopback // + ); + if (!IsValidSize(barsCount)) + { + return result; + } + + // + for (int i = 0; i < barsCount; i++) + { + result += bars[i].GetHighShadow(); + } + + // + return result; + } + + // + bool HasBullishPressure( + XOHCL &bar, + int __loopback = 7 // + ) + { + // + bool result = false; + + // + if (__loopback < 0) + { + __loopback = 7; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double bullishPressure = GetBullishPressure(bar, __loopback); + double bearishPressure = GetBearishPressure(bar, __loopback); + + // + result = + // + bullishPressure > 0 && + bearishPressure >= 0 && + bullishPressure > bearishPressure + // + ; + + // + return result; + } + + // + bool HasBearishPressure( + XOHCL &bar, + int __loopback = 7 // + ) + { + // + bool result = false; + + // + if (__loopback < 0) + { + __loopback = 7; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double bullishPressure = GetBullishPressure(bar, __loopback); + double bearishPressure = GetBearishPressure(bar, __loopback); + + // + result = + // + bearishPressure > 0 && + bullishPressure >= 0 && + bearishPressure > bullishPressure + // + ; + + // + return result; + } + + // + // Retrieve Bullish Power ... + double GetBullishPower( + XOHCL &bar, + int __loopback = 7 // + ) + { + // + double result = 0; + + // + if (!bar.IsValid()) + { + return result; + } + + // + XOHCL bars[]; + int barsCount = GetBars( + bars, + bar.symbol, + bar.period, + bar.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( + XOHCL &bar, + int __loopback = 7 // + ) + { + // + double result = 0; + + // + if (!bar.IsValid()) + { + return result; + } + + // + XOHCL bars[]; + int barsCount = GetBars( + bars, + bar.symbol, + bar.period, + bar.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( + XOHCL &bar, + int __loopback = 7 // + ) + { + // + bool result = false; + + // + if (__loopback < 0) + { + __loopback = 7; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double bullishPressure = GetBullishPower(bar, __loopback); + double bearishPressure = GetBearishPower(bar, __loopback); + + // + result = + // + bullishPressure > 0 && + bearishPressure >= 0 && + bullishPressure > bearishPressure + // + ; + + // + return result; + } + + // + bool HasBearishPower( + XOHCL &bar, + int __loopback = 7 // + ) + { + // + bool result = false; + + // + if (__loopback < 0) + { + __loopback = 7; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double bullishPressure = GetBullishPower(bar, __loopback); + double bearishPressure = GetBearishPower(bar, __loopback); + + // + result = + // + bearishPressure > 0 && + bullishPressure >= 0 && + bearishPressure > bullishPressure + // + ; + + // + return result; + } + + // + // Decisions ... + + // + bool IsBullishDecision( + XOHCL &bar, + double percent = 70 // Percent of Body + ) + { + // + bool result = false; + + // + result = + // + bar.IsValid() && + bar.Index() > 0 && + bar.IsBullish() && + (bar.GetRange() * percent) / 100 <= bar.GetBody() + // + ; + + // + return result; + } + + // + bool IsBearishDecision( + XOHCL &bar, + double percent = 70 // Percent of Body + ) + { + // + bool result = false; + + // + result = + // + bar.IsValid() && + bar.Index() > 0 && + bar.IsBearish() && + (bar.GetRange() * percent) / 100 <= bar.GetBody() + // + ; + + // + return result; + } + + // + // Candlestic Patterns ... + + // + // Check Doji ... + bool IsDoji( + XOHCL &bar // + ) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + result = bar.open == bar.close; + + // + return result; + } + + // + // Check Hammer ... + bool IsHammer( + XOHCL &bar, + 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 = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + if (_upShadowFactor < 0) + { + _upShadowFactor = 0.1; + } + + // + if (_downShadowFactor < 0) + { + _upShadowFactor = 0.6; + } + + // + double range = bar.GetRange(); + + // + // Check Upper Shadow Must be 0 or Under 10% ... + double upShadow = bar.GetHighShadow(); + result = upShadow < range * _upShadowFactor; + if (!result) + { + return result; + } + + // + // Check Down Shadow Must at least 60% ... + double downShadow = bar.GetLowShadow(); + result = downShadow > range * _downShadowFactor; + if (!result) + { + return result; + } + + // + // Check Fib 382 ... + if (result && applyFib382Check) + { + // + double fib382 = GetFibonacciLevel( + bar.high, + bar.low, + 0.382, + -1 // + ); + result = bar.GetDown() > fib382; + } + + // + // Check Shadow Based on Prev Bar ... + if (result && applyPrevShadowCheck) + { + // + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + result = bar.low < pBar.low; + } + + // + return result; + } + + // + // Check Sgooting Star ... + // Reversal Hammer ... + bool IsShootingStar( + XOHCL &bar, + 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 = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + if (_upShadowFactor < 0) + { + _upShadowFactor = 0.6; + } + + // + if (_downShadowFactor < 0) + { + _upShadowFactor = 0.1; + } + + // + double range = bar.GetRange(); + + // + // Check Upper Shadow Must be 0 or Under 10% ... + double upShadow = bar.GetHighShadow(); + result = upShadow > range * _upShadowFactor; + if (!result) + { + return result; + } + + // + // Check Down Shadow Must at least 60% ... + double downShadow = bar.GetLowShadow(); + result = downShadow < range * _downShadowFactor; + if (!result) + { + return result; + } + + // + // Check Fib 382 ... + if (result && applyFib382Check) + { + // + double fib382 = GetFibonacciLevel( + bar.high, + bar.low, + 0.382, + 1 // + ); + result = bar.GetUp() < fib382; + } + + // + // Check Shadow Based on Prev Bar ... + if (result && applyPrevShadowCheck) + { + // + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + result = bar.high > pBar.high; + } + + // + return result; + } + + // + // Check Bullish Engulfing ... + bool IsBullishEngulfing( + XOHCL &bar, + double _engulfBarBodyFactor = 0.7 // + ) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + if (_engulfBarBodyFactor < 0) + { + _engulfBarBodyFactor = 0.7; + } + + // + // Check Bar Is Bullish ... + result = bar.IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Previous Bar ... + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + double range = bar.GetRange(); + double body = bar.GetBody(); + + // + // Check Prev Bar Must Bearish ... + result = pBar.IsBearish(); + if (!result) + { + return result; + } + + // + // Check Shadows Engulf Prev Bar ... + result = + // + bar.high > pBar.high && + bar.low <= pBar.low + // + ; + if (!result) + { + return result; + } + + // + // Check Engulfed Bar Must Inside Engulfer Body ... + result = + // + bar.GetUp() > pBar.GetUp() && + bar.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( + XOHCL &bar, + double _engulfBarBodyFactor = 0.7 // + ) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + if (_engulfBarBodyFactor < 0) + { + _engulfBarBodyFactor = 0.7; + } + + // + // Check Bar Is Bearish ... + result = bar.IsBearish(); + if (!result) + { + return result; + } + + // + // Retrieve Previous Bar ... + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + double range = bar.GetRange(); + double body = bar.GetBody(); + + // + // Check Prev Bar Must Bullish ... + result = pBar.IsBullish(); + if (!result) + { + return result; + } + + // + // Check Shadows Engulf Prev Bar ... + result = bar.high >= pBar.high && + bar.low < pBar.low; + if (!result) + { + return result; + } + + // + // Check Engulfed Bar Must Inside Engulfer Body ... + result = + // + bar.GetUp() > pBar.GetUp() && + bar.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( + XOHCL &bar, + 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 = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + if (_middleRangeFactor < 0) + { + _middleRangeFactor = 0.3; + } + + // + if (_startBodyFactor < 0) + { + _startBodyFactor = 0.6; + } + + // + // Current Bar Must be Bullish ... + result = bar.IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Previous Bar ... + XOHCL pBar; + result = bar.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 = bar.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( + XOHCL &bar, + 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 = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + if (_middleRangeFactor < 0) + { + _middleRangeFactor = 0.3; + } + + // + if (_startBodyFactor < 0) + { + _startBodyFactor = 0.6; + } + + // + // Current Bar Must be Bearish ... + result = bar.IsBearish(); + if (!result) + { + return result; + } + + // + // Retrieve Previous Bar ... + XOHCL pBar; + result = bar.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 = bar.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(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + result = bar.IsBullish(); + if (!result) + { + return result; + } + + // + result = + // + bar.GetUp() == bar.high && + bar.GetDown() == bar.low + // + ; + + // + return result; + } + + // + // Bearish Marubozu ... + bool IsBearishMarubozu(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + result = bar.IsBearish(); + if (!result) + { + return result; + } + + // + result = + // + bar.GetUp() == bar.high && + bar.GetDown() == bar.low + // + ; + + // + return result; + } + + // + // Contextual Patterns ... + + // + // Check Swing High ... + bool IsBarSwingHigh(XOHCL &bar) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + // Current Bar Must be Bearish ... + result = bar.IsBearish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev Bar ... + XOHCL pBar; + result = bar.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 = + // + bar.high < pBar.high && + pBar.high > ppBar.high + // + ; + + // + return result; + } + + // + // Find Simple 3 Candle Based Swing High ... + bool IsSimpleSwingHigh( + XOHCL &bar, + double thresholdInPoint = 1 // + ) + { + // + bool result = false; + + // + int index = bar.Index(); + result = index > 0; + if (!result) + { + return result; + } + + // + XOHCL nextBar; + result = bar.GetNextBar(nextBar); + if (!result) + { + return result; + } + + // + XOHCL prevBar; + result = bar.GetPreviousBar(prevBar); + if (!result) + { + return result; + } + + // + double point = GetPoints(bar.symbol); + double requiredOffset = point * thresholdInPoint; + + // + result = + bar.high > nextBar.high && + bar.high > prevBar.high && + (thresholdInPoint <= 0 + ? true + : MathAbs( + MathMax( + nextBar.high, + prevBar.high) - + bar.high) >= requiredOffset); + + // + return result; + } + + // + // Find Last Swing High ... + bool FindLastSwingHigh( + XOHCL &bar, + XOHCL &swing // + ) + { + // + bool result = false; + + // + swing.Clean(); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int totalBars = iBars( + bar.symbol, + bar.period // + ); + int maxAllowed = MathMin(100, (totalBars / 100)); + + // + int idx = bar.Index(); + for (int i = idx; i <= idx + maxAllowed; i++) + { + // + swing.Clean(); + result = swing.Init( + bar.symbol, + bar.period, + i // + ); + if (!result) + { + // + swing.Clean(); + break; + } + + // + result = IsBarSwingHigh(swing); + if (result) + { + break; + } + } + + // + return result; + } + + // + // Check Swing Low ... + bool IsBarSwingLow(XOHCL &bar) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + // Current Bar Must be Bullish ... + result = bar.IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev Bar ... + XOHCL pBar; + result = bar.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 = + // + bar.low > pBar.low && + pBar.low < ppBar.low + // + ; + + // + return result; + } + + // + // Find Simple 3 Candle Based Swing Low ... + bool IsSimpleSwingLow( + XOHCL &bar, + double thresholdInPoint = 1 // + ) + { + // + bool result = false; + + // + int index = bar.Index(); + result = index > 0; + if (!result) + { + return result; + } + + // + XOHCL nextBar; + result = bar.GetNextBar(nextBar); + if (!result) + { + return result; + } + + // + XOHCL prevBar; + result = bar.GetPreviousBar(prevBar); + if (!result) + { + return result; + } + + // + double point = GetPoints(bar.symbol); + double requiredOffset = point * thresholdInPoint; + + // + result = + bar.low < nextBar.low && + bar.low < prevBar.low && + (thresholdInPoint <= 0 + ? true + : MathAbs( + MathMax( + nextBar.low, + prevBar.low) - + bar.low) >= requiredOffset); + + // + return result; + } + + // + // Find Last Swing Low ... + bool FindLastSwingLow( + XOHCL &bar, + XOHCL &swing // + ) + { + // + bool result = false; + + // + swing.Clean(); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int totalBars = iBars( + bar.symbol, + bar.period // + ); + int maxAllowed = MathMin(100, (totalBars / 100)); + + // + int idx = bar.Index(); + for (int i = idx; i <= idx + maxAllowed; i++) + { + // + swing.Clean(); + result = swing.Init( + bar.symbol, + bar.period, + i // + ); + if (!result) + { + // + swing.Clean(); + break; + } + + // + result = IsBarSwingLow(swing); + if (result) + { + break; + } + } + + // + return result; + } + + // + // Check Bullish FVG ... + bool HasBullishFVG( + XOHCL &bar, + 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 = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + // Current Bar Must be Bullish ... + result = + !forceCheckLastBarDirection + ? true + : bar.IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev Bar ... + XOHCL pBar; + result = bar.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 = + // + bar.low > ppBar.high + // + ; + + // + // Check Middle Bar Range ... + if (result && forceMiddleBarCheck) + { + // + result = + // + pBar.high > bar.low && + pBar.low < ppBar.high + // + ; + + // + if (!result) + { + return result; + } + } + + // + if (result) + { + // + end = bar.time; + upper = bar.low; + lower = ppBar.high; + start = ppBar.time; + } + + // + return result; + } + + // + // Check Bearish FVG ... + bool HasBearishFVG( + XOHCL &bar, + 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 = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + // Current Bar Must be Bearish ... + result = + !forceCheckLastBarDirection + ? true + : bar.IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev Bar ... + XOHCL pBar; + result = bar.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 = + // + bar.high < ppBar.low + // + ; + + // + // Check Middle Bar Range ... + if (result && forceMiddleBarCheck) + { + // + result = + // + pBar.high > bar.low && + pBar.low < ppBar.high + // + ; + + // + if (!result) + { + return result; + } + } + + // + if (result) + { + // + end = bar.time; + lower = bar.high; + upper = ppBar.low; + start = ppBar.time; + } + + // + return result; + } + + // + // Find Support ... + bool HasSupport( + XOHCL &bar, + XOHCL &dest, + ENUM_X_PRICE type = X_PRICE_CLOSE, + int _loopback = 21, + int tries = 100 // + ) + { + // + bool result = false; + + // + dest.Clean(); + + // + if (_loopback < 0) + { + _loopback = 21; + } + + // + if (tries < 0) + { + tries = 100; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double price = bar.GetPrice(type); + + // + for (int i = 1; i < tries; i++) + { + // + int _length = _loopback * i; + + // + int lowestIDX = bar.FindLowestIndex( + _length, + MODE_LOW // + ); + result = IsValidIndex(lowestIDX); + if (!result) + { + break; + } + + // + XOHCL iLBar; + result = iLBar.Init( + bar.symbol, + bar.period, + lowestIDX // + ); + if (!result) + { + break; + } + + // + result = + // + price > iLBar.high + // + ; + if (result) + { + // + dest = iLBar; + break; + } + } + + // + result = dest.IsValid(); + + // + return result; + } + + // + // Find Resistance ... + bool HasResistance( + XOHCL &bar, + XOHCL &dest, + ENUM_X_PRICE type = X_PRICE_CLOSE, + int _loopback = 21, + int tries = 100 // + ) + { + // + bool result = false; + + // + dest.Clean(); + + // + if (_loopback < 0) + { + _loopback = 21; + } + + // + if (tries < 0) + { + tries = 100; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double price = bar.GetPrice(type); + + // + for (int i = 1; i < tries; i++) + { + // + int _length = _loopback * i; + + // + int highestIDX = bar.FindHighestIndex( + _length, + MODE_LOW // + ); + result = IsValidIndex(highestIDX); + if (!result) + { + break; + } + + // + XOHCL iHBar; + result = iHBar.Init( + bar.symbol, + bar.period, + highestIDX // + ); + if (!result) + { + break; + } + + // + result = + // + price < iHBar.high + // + ; + if (result) + { + // + dest = iHBar; + break; + } + } + + // + result = dest.IsValid(); + + // + return result; + } + + // + // Trend Detection ... + + // + // Find Bullish Trend ... + bool HasBullishTrend( + XOHCL &bar, + 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 = bar.IsValid(); + if (!result) + { + return result; + } + + // + double price = bar.GetPrice(type); + + // + int lastIDX = bar.Index(); + double lastH = 0; + double lastL = 0; + for (int i = 1; i < tries + 1; i++) + { + // + // Use Regular Method ... + if (!forceMethod2) + { + // + int iHIDX = FindSwing( + bar.symbol, + bar.period, + X_SWING_HIGH, + _loopback, + lastIDX // + ); + result = IsValidIndex(iHIDX); + if (!result) + { + break; + } + + // + XOHCL iHBar; + result = iHBar.Init( + bar.symbol, + bar.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( + bar.symbol, + bar.period, + X_SWING_LOW, + _loopback, + lastIDX // + ); + result = IsValidIndex(iLIDX); + if (!result) + { + break; + } + + // + XOHCL iLBar; + result = iLBar.Init( + bar.symbol, + bar.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( + bar.symbol, + bar.period, + MODE_HIGH, + _loopback, + start // + ); + result = IsValidIndex(iHIDX); + if (!result) + { + break; + } + + // + XOHCL iHBar; + result = iHBar.Init( + bar.symbol, + bar.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( + bar.symbol, + bar.period, + MODE_LOW, + _loopback, + start // + ); + result = IsValidIndex(iLIDX); + if (!result) + { + break; + } + + // + XOHCL iLBar; + result = iLBar.Init( + bar.symbol, + bar.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 &bar, + 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 = bar.IsValid(); + if (!result) + { + return result; + } + + // + double price = bar.GetPrice(type); + + // + int lastIDX = bar.Index(); + double lastH = 0; + double lastL = 0; + for (int i = 1; i < tries + 1; i++) + { + // + // Use Regular Method ... + if (!forceMethod2) + { + // + int iHIDX = FindSwing( + bar.symbol, + bar.period, + X_SWING_HIGH, + _loopback, + lastIDX // + ); + result = IsValidIndex(iHIDX); + if (!result) + { + break; + } + + // + XOHCL iHBar; + result = iHBar.Init( + bar.symbol, + bar.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( + bar.symbol, + bar.period, + X_SWING_LOW, + _loopback, + lastIDX // + ); + result = IsValidIndex(iLIDX); + if (!result) + { + break; + } + + // + XOHCL iLBar; + result = iLBar.Init( + bar.symbol, + bar.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( + bar.symbol, + bar.period, + MODE_HIGH, + _loopback, + start // + ); + result = IsValidIndex(iHIDX); + if (!result) + { + break; + } + + // + XOHCL iHBar; + result = iHBar.Init( + bar.symbol, + bar.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( + bar.symbol, + bar.period, + MODE_LOW, + _loopback, + start // + ); + result = IsValidIndex(iLIDX); + if (!result) + { + break; + } + + // + XOHCL iLBar; + result = iLBar.Init( + bar.symbol, + bar.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 &bar, + XOHCL &orderBlock, + int _minimumSameBars = 4 // + ) + { + // + bool result = false; + + // + orderBlock.Clean(); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + if (_minimumSameBars < 0) + { + _minimumSameBars = 4; + } + + // + XOHCL cBar; + int founded = 0; + int cIDX = bar.Index(); + bool isEnough = false; + while (!isEnough) + { + // + result = cBar.Init( + bar.symbol, + bar.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() && + bar.high > cBar.high && + founded >= _minimumSameBars + // + ; + if (!result) + { + return result; + } + + // + result = orderBlock.Init( + bar.symbol, + bar.period, + cIDX // + ); + if (!result) + { + // + orderBlock.Clean(); + return result; + } + + // + return result; + } + + // + // Find Bearish Order Block ... + bool HasBearishOrderBlock( + XOHCL &bar, + XOHCL &orderBlock, + int _minimumSameBars = 4 // + ) + { + // + bool result = false; + + // + orderBlock.Clean(); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + if (_minimumSameBars < 0) + { + _minimumSameBars = 4; + } + + // + XOHCL cBar; + int founded = 0; + int cIDX = bar.Index(); + bool isEnough = false; + while (!isEnough) + { + // + bool isInited = cBar.Init( + bar.symbol, + bar.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() && + bar.high < cBar.low && + founded >= _minimumSameBars + // + ; + if (!result) + { + return result; + } + + // + result = orderBlock.Init( + bar.symbol, + bar.period, + cIDX // + ); + if (!result) + { + // + orderBlock.Clean(); + return result; + } + + // + return result; + } + + // + protected: + // + + // + private: + // + + // + // Props ... + + // + // Actions ... + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14031218/Classes/x-saherelm.x-cobject.class.mq5 b/BKPS/14031218/Classes/x-saherelm.x-cobject.class.mq5 new file mode 100644 index 0000000..2666968 --- /dev/null +++ b/BKPS/14031218/Classes/x-saherelm.x-cobject.class.mq5 @@ -0,0 +1,3878 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XChartObjects +// Description: provides all require Chart Objects ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +#include "../Libraries/x-saherelm.x-poi.lib.mq5" +#include "../Libraries/x-saherelm.x-trade.lib.mq5" + +// +#include +#include +#include +#include +#include +#include + +// +// Definitions ... + +enum ENUM_XCHARTOBJECTS +{ + // + // Global ... + X_ZONE_OBJ = 7860, + X_BOX_OBJ = 7861, + X_BAR_ARROW_OBJ = 7862, + // + X_SIGNAL_OBJ = 8860, + X_TREND_OBJ = 8861, + X_XPVPIVOT_OBJ = 8862, + X_OHCL_OBJ = 8863, + X_RR_OBJ = 8864, + // + // Structured ... + X_TRADE_DAY_OBJ = 9860, + X_MARKET_SESSION_OBJ = 9861, + X_SWING_HIGH_OBJ = 9862, + X_SWING_LOW_OBJ = 9863, + X_BULLISH_MOMENTUM_BAR_OBJ = 9864, + X_BEARISH_MOMENTUM_BAR_OBJ = 9865, + X_BULLISH_REJECTION_BAR_OBJ = 9866, + X_BEARISH_REJECTION_BAR_OBJ = 9867, + X_SUPPORT_ZONE_OBJ = 9868, + X_RESISTANCE_ZONE_OBJ = 9869, + X_SUPPLY_ZONE_OBJ = 9870, + X_DEMAND_ZONE_OBJ = 9871, + X_BULLISH_ORDERBLOCK_OBJ = 9872, + X_BEARISH_ORDERBLOCK_OBJ = 9873, + X_BULLISH_FVG_OBJ = 9874, + X_BEARISH_FVG_OBJ = 9875, + X_TICK_ZONE_OBJ = 9876, + X_TICKS_ZONE_OBJ = 9877, + X_CONSOLIDATION_ZONE_OBJ = 9878, +}; + +enum ENUM_X_CHART_IDS +{ + X_TO, + X_FROM, + X_UPPER, + X_LOWER, + X_ENTRY, + X_TARGET, + X_SL, + X_TP, + X_BAR_H_SHW, + X_BAR_BDY, + X_BAR_L_SHW, +}; + +string ToString(ENUM_X_CHART_IDS value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_TO: + result = "TO"; + break; + + // + case X_FROM: + result = "FROM"; + break; + + // + case X_UPPER: + result = "UPPER"; + break; + + // + case X_LOWER: + result = "LOWER"; + break; + + // + case X_ENTRY: + result = "ENTRY"; + break; + + // + case X_TARGET: + result = "TARGET"; + break; + + // + case X_SL: + result = "SL"; + break; + + // + case X_TP: + result = "TP"; + break; + + // + case X_BAR_H_SHW: + result = "HSHW"; + break; + + // + case X_BAR_BDY: + result = "BODY"; + break; + + // + case X_BAR_L_SHW: + result = "LSHW"; + break; + + // + } + + // + return result; +} + +// +// Implementation ... + +// +// Global Chart Objects ... + +// +// Bas Chart Object ... +class XCBaseObject : public CChartObject +{ + // + public: + // + + // + // Getter(s) / Setter(s) ... + + /** + * Get Object Specified Name ... + * + * @return ( string ) + */ + string ObjName() + { + return mObjName; + } + + /** + * Set Object Specified Name ... + * + * @param value: String ... + */ + void ObjName(string value) + { + mObjName = value; + } + + // + private: + // + + // + // Props ... + string mObjName; // Object Specified Name ... + + // +}; + +class XCBarArrowObject : public XCBaseObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param name: String, Specified Object ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param swing: XCSwing instance ... + * + * @return ( bool ) + */ + bool CreateByBar( + long chart_id, + string name, + int window, + int arrow, + XOHCL &bar, + ENUM_X_PRICE priceType // + ) + { + // + bool result = false; + + // + result = + // + bar.IsValid() && + IsValid(name) + // + ; + if (!result) + { + return result; + } + + // + datetime time = bar.time; + double price = bar.GetPrice(priceType); + + // + result = mArrow.Create( + chart_id, + name, + window, + time, + price, + (char)arrow // + ); + + // + if (result) + { + ObjName(name); + } + + // + return result; + } + + // + // Virtual ... + + // + // Setter(s) ... + + /** + * Set Arrow Anchor ... + * + * @param value: ENUM_ARROW_ANCHOR member ... + */ + void ArrowAnchor(ENUM_ARROW_ANCHOR value) + { + mArrow.Anchor(value); + } + + /** + * Set Arrow Color ... + * + * @param value: Color ... + */ + void ArrowColor(color value) + { + mArrow.Color(value); + } + + /** + * Set Arrow Width ... + * + * @param value: Integer ... + */ + void ArrowWidth(int value) + { + mArrow.Width(value); + } + + // + private: + // + CChartObjectArrow mArrow; + + // +}; + +// +// Swing ... +class XCSwingObject : public XCBarArrowObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param swing: XCSwing instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool CreateBySwing( + long chart_id, + int window, + int arrow, + XCSwing &swing, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = + // + swing.IsValid() + // + ; + if (!result) + { + return result; + } + + // + string name = swing.GetTag(); + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + + // + XOHCL bar; + result = swing.FillBar(bar); + if (!result) + { + return result; + } + + // + ENUM_X_PRICE price = swing.IsSwingHigh() + ? X_PRICE_HIGH + : X_PRICE_LOW; + + // + result = CreateByBar( + chart_id, + name, + window, + arrow, + bar, + price // + ); + + // + if (result) + { + ObjName(name); + } + + // + return result; + } +}; + +// +// Swing High ... +class XCSwingHighObject : public XCSwingObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param arrow: Integer, Specified Arrow Code ... + * @param swing: XCSwing instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + int arrow, + XCSwing &swing, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = swing.IsValid() && + swing.IsSwingHigh(); + if (!result) + { + return result; + } + + // + result = CreateBySwing( + chart_id, + window, + arrow, + swing, + prefix // + ); + + // + return result; + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_SWING_HIGH_OBJ; + } + + // +}; + +// +// Swing Low ... +class XCSwingLowObject : public XCSwingObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param arrow: Integer, Specified Arrow Code ... + * @param swing: XCSwing instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + int arrow, + XCSwing &swing, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = swing.IsValid() && + swing.IsSwingLow(); + if (!result) + { + return result; + } + + // + result = CreateBySwing( + chart_id, + window, + arrow, + swing, + prefix // + ); + + // + return result; + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_SWING_LOW_OBJ; + } + + // +}; + +// +// Momentum ... +class XCMomentumBarObject : public XCBarArrowObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param momentumBar: XCMomentumBar instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool CreateByMomentum( + long chart_id, + int window, + int arrow, + XCMomentumBar &momentumBar, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = + // + momentumBar.IsValid() + // + ; + if (!result) + { + return result; + } + + // + string name = momentumBar.GetTag(); + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + + // + XOHCL bar; + result = momentumBar.FillBar(bar); + if (!result) + { + return result; + } + + // + ENUM_X_PRICE price = momentumBar.IsBullish() + ? X_PRICE_LOW + : X_PRICE_HIGH; + + // + result = CreateByBar( + chart_id, + name, + window, + arrow, + bar, + price // + ); + + // + if (result) + { + ObjName(name); + } + + // + return result; + } +}; + +// +// Bullish Momentum Bar ... +class XCBullishMomentumBarObject : public XCMomentumBarObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param arrow: Integer, Specified Arrow Code ... + * @param momentumBar: XCMomentumBar instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + int arrow, + XCMomentumBar &momentumBar, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = momentumBar.IsValid() && + momentumBar.IsBullish(); + if (!result) + { + return result; + } + + // + result = CreateByMomentum( + chart_id, + window, + arrow, + momentumBar, + prefix // + ); + + // + return result; + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_BULLISH_MOMENTUM_BAR_OBJ; + } + + // +}; + +// +// Bearish Momentum Bar ... +class XCBearishMomentumBarObject : public XCMomentumBarObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param arrow: Integer, Specified Arrow Code ... + * @param momentumBar: XCMomentumBar instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + int arrow, + XCMomentumBar &momentumBar, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = momentumBar.IsValid() && + momentumBar.IsBearish(); + if (!result) + { + return result; + } + + // + result = CreateByMomentum( + chart_id, + window, + arrow, + momentumBar, + prefix // + ); + + // + return result; + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_BEARISH_MOMENTUM_BAR_OBJ; + } + + // +}; + +// +// Rejection ... +class XCRejectionBarObject : public XCBarArrowObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param rejectionBar: XCRejectionBar instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool CreateByRejection( + long chart_id, + int window, + int arrow, + XCRejectionBar &rejectionBar, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = + // + rejectionBar.IsValid() + // + ; + if (!result) + { + return result; + } + + // + string name = rejectionBar.GetTag(); + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + + // + XOHCL bar; + result = rejectionBar.FillBar(bar); + if (!result) + { + return result; + } + + // + ENUM_X_PRICE price = rejectionBar.IsBullish() + ? X_PRICE_LOW + : X_PRICE_HIGH; + + // + result = CreateByBar( + chart_id, + name, + window, + arrow, + bar, + price // + ); + + // + if (result) + { + ObjName(name); + } + + // + return result; + } +}; + +// +// Bullish Rejection Bar ... +class XCBullishRejectionBarObject : public XCRejectionBarObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param arrow: Integer, Specified Arrow Code ... + * @param rejectionBar: XCRejectionBar instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + int arrow, + XCRejectionBar &rejectionBar, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = rejectionBar.IsValid() && + rejectionBar.IsBullish(); + if (!result) + { + return result; + } + + // + result = CreateByRejection( + chart_id, + window, + arrow, + rejectionBar, + prefix // + ); + + // + return result; + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_BULLISH_REJECTION_BAR_OBJ; + } + + // +}; + +// +// Bearish Rejection Bar ... +class XCBearishRejectionBarObject : public XCRejectionBarObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param arrow: Integer, Specified Arrow Code ... + * @param rejectionBar: XCRejectionBar instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + int arrow, + XCRejectionBar &rejectionBar, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = rejectionBar.IsValid() && + rejectionBar.IsBearish(); + if (!result) + { + return result; + } + + // + result = CreateByRejection( + chart_id, + window, + arrow, + rejectionBar, + prefix // + ); + + // + return result; + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_BEARISH_REJECTION_BAR_OBJ; + } + + // +}; + +// +// XCZoneObject ... +class XCZoneObject : public XCBaseObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param name: String, Specified Object Identifier on Chart ... + * @param window: Integer, Specified Chart Window ID ... + * @param zone: XCZone instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool CreateByZone( + long chart_id, + string name, + int window, + XCZone &zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + bool isValidFrom = zone.IsValidFrom(); + bool isValidBoundary = zone.IsValidBoundary(); + + // + result = + // + IsValid(name) && + isValidFrom && + isValidBoundary + // + ; + if (!result) + { + return result; + } + + // + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + + // + datetime from = zone.From(); + datetime to = NormalizeTime(zone.To()); + + // + double upper = zone.Upper(); + double lower = zone.Lower(); + + // + result = mRect.Create( + chart_id, + name, + window, + from, + upper, + to, + lower // + ); + + // + if (result) + { + ObjName(name); + } + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_ZONE_OBJ; + } + + // + // Setter(s) ... + + /** + * Set Zone Width ... + * + * @param value: Integer ... + */ + void ZoneWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mRect.Width(value); + } + + /** + * Set Zone Color ... + * + * @param value: Color ... + */ + void ZoneColor(color value) + { + mRect.Color(value); + } + + /** + * Set Zone Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void ZoneStyle(ENUM_LINE_STYLE value) + { + mRect.Style(value); + } + + /** + * Set Zone Fill ... + * + * @param value: Boolean ... + */ + void ZoneFill(bool value) + { + mRect.Fill(value); + } + + // + private: + // + CChartObjectRectangle mRect; + + // +}; + +// +// Support Zone ... +class XCSupportZoneObject : public XCZoneObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param zone: XCSupportZone instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XCSupportZone &zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + string name = zone.GetTag(); + + // + result = CreateByZone( + chart_id, + name, + window, + zone, + prefix // + ); + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_SUPPORT_ZONE_OBJ; + } +}; + +// +// Resistance Zone ... +class XCResistanceZoneObject : public XCZoneObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param zone: XCResistanceZone instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XCResistanceZone &zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + string name = zone.GetTag(); + + // + result = CreateByZone( + chart_id, + name, + window, + zone, + prefix // + ); + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_RESISTANCE_ZONE_OBJ; + } +}; + +// +// Supply Zone ... +class XCSupplyZoneObject : public XCZoneObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param zone: XCSupplyZone instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XCSupplyZone &zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + string name = zone.GetTag(); + + // + result = CreateByZone( + chart_id, + name, + window, + zone, + prefix // + ); + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_SUPPLY_ZONE_OBJ; + } +}; + +// +// Demand Zone ... +class XCDemandZoneObject : public XCZoneObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param zone: XCDemandZone instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XCDemandZone &zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + string name = zone.GetTag(); + + // + result = CreateByZone( + chart_id, + name, + window, + zone, + prefix // + ); + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_DEMAND_ZONE_OBJ; + } +}; + +// +// Bullish Order Block ... +class XCBullishOrderBlockObject : public XCZoneObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param zone: XCOrderBlock instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XCOrderBlock &zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = zone.IsValid() && + zone.IsBullish(); + if (!result) + { + return result; + } + + // + string name = zone.GetTag(); + + // + result = CreateByZone( + chart_id, + name, + window, + zone, + prefix // + ); + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_BULLISH_ORDERBLOCK_OBJ; + } +}; + +// +// Bearish Order Block ... +class XCBearishOrderBlockObject : public XCZoneObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param zone: XCOrderBlock instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XCOrderBlock &zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = zone.IsValid() && + zone.IsBearish(); + if (!result) + { + return result; + } + + // + string name = zone.GetTag(); + + // + result = CreateByZone( + chart_id, + name, + window, + zone, + prefix // + ); + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_BULLISH_ORDERBLOCK_OBJ; + } +}; + +// +// Bullish Fair Value Gaps ... +class XCBullishFairValueGapObject : public XCZoneObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param zone: XCOrderBlock instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XCFVG &zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = zone.IsValid() && + zone.IsBullish(); + if (!result) + { + return result; + } + + // + string name = zone.GetTag(); + + // + result = CreateByZone( + chart_id, + name, + window, + zone, + prefix // + ); + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_BULLISH_FVG_OBJ; + } +}; + +class XCConsolidationZoneObject : public XCBaseObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param zone: XConsolidationZone instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XConsolidationZone &zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + string name = zone.GetTag(); + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + + // + result = mRect.Create( + chart_id, + name, + window, + zone.from, + zone.upper, + zone.to, + zone.lower // + ); + + // + if (result) + { + ObjName(name); + } + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_CONSOLIDATION_ZONE_OBJ; + } + + // + // Setter(s) ... + + /** + * Set Zone Width ... + * + * @param value: Integer ... + */ + void ZoneWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mRect.Width(value); + } + + /** + * Set Zone Color ... + * + * @param value: Color ... + */ + void ZoneColor(color value) + { + mRect.Color(value); + } + + /** + * Set Zone Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void ZoneStyle(ENUM_LINE_STYLE value) + { + mRect.Style(value); + } + + /** + * Set Zone Fill ... + * + * @param value: Boolean ... + */ + void ZoneFill(bool value) + { + mRect.Fill(value); + } + + // + private: + // + CChartObjectRectangle mRect; + + // +}; + +// +// Bearish Fair Value Gaps ... +class XCBearishFairValueGapObject : public XCZoneObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param zone: XCOrderBlock instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XCFVG &zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = zone.IsValid() && + zone.IsBearish(); + if (!result) + { + return result; + } + + // + string name = zone.GetTag(); + + // + result = CreateByZone( + chart_id, + name, + window, + zone, + prefix // + ); + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_BEARISH_FVG_OBJ; + } +}; + +// +// Signal ... +class XCSignalObject : public XCBaseObject +{ + // + public: + // + + // + // Constructor ... + void XCSignalObject() + { + } + + // + // Deconstructor ... + void ~XCSignalObject() + { + } + + /** + * Create a Signal Object on Chart ... + * + * @param chart_id: Long ... + * @param name: String ... + * @param window: Integer ... + * @param signal: XSignal instance ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + const int window, + XSignal &signal, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = signal.IsValid(); + if (!result) + { + return result; + } + + // + string name = signal.GetTag(); + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + string nameMD5 = ToMD5(name); + + // + int delay = (PeriodSeconds(signal.period) * 2); + datetime time1 = (datetime)((int)signal.time - delay); + datetime time2 = (datetime)((int)signal.time + delay); + + // + // TP ... + string tpName = ToString(X_TP) + "_" + nameMD5; + result = mTPTrend.Create( + chart_id, + tpName, + window, + time1, + signal.tp, + time2, + signal.tp // + ); + if (!result) + { + return result; + } + + // + // SL ... + string slName = ToString(X_SL) + "_" + nameMD5; + result = mSLTrend.Create( + chart_id, + slName, + window, + time1, + signal.sl, + time2, + signal.sl // + ); + if (!result) + { + // + mTPTrend.Delete(); + return result; + } + + // + // TARGET ... + bool hasTargets = HasChild(signal.targets); + if (hasTargets) + { + // + int targetsCount = ArraySize(signal.targets); + for (int i = 0; i < targetsCount; i++) + { + // + string targetName = ToString(X_TARGET) + "_" + ToString(i) + "_" + nameMD5; + CChartObjectTrend *mTargetTrend; + mTargetTrend = new CChartObjectTrend(); + result = mTargetTrend.Create( + chart_id, + targetName, + window, + time1, + signal.targets[i], + time2, + signal.targets[i] // + ); + if (!result) + { + // + mTPTrend.Delete(); + mSLTrend.Delete(); + break; + } + + // + mTargetTrends.Add(mTargetTrend); + } + } + + // + // ENTRY ... + string entrName = ToString(X_ENTRY) + "_" + nameMD5; + result = mEntryTrend.Create( + chart_id, + entrName, + window, + time1, + signal.entry, + time2, + signal.entry // + ); + if (!result) + { + // + mTPTrend.Delete(); + mSLTrend.Delete(); + mTargetTrends.Clear(); + return result; + } + + // + // Set Object Name ... + ObjName(name); + + // + return result; + } + + // + // Setter(s) ... + + // + // TP ... + + /** + * Set TP Width ... + * + * @param value: Integer ... + */ + void TPWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mTPTrend.Width(value); + } + + /** + * Set TP Color ... + * + * @param value: Color ... + */ + void TPColor(color value) + { + mTPTrend.Color(value); + } + + /** + * Set TP Style ... + * + * @param value: ENUM_LINE_STYLE ... + */ + void TPStyle(ENUM_LINE_STYLE value) + { + mTPTrend.Style(value); + } + + // + // SL ... + + /** + * Set SL Width ... + * + * @param value: Integer ... + */ + void SLWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mSLTrend.Width(value); + } + + /** + * Set SL Color ... + * + * @param value: Color ... + */ + void SLColor(color value) + { + mSLTrend.Color(value); + } + + /** + * Set SL Style ... + * + * @param value: ENUM_LINE_STYLE ... + */ + void SLStyle(ENUM_LINE_STYLE value) + { + mSLTrend.Style(value); + } + + // + // TARGET ... + + /** + * Set Target Width ... + * + * @param value: Integer ... + */ + void TargetWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + for (int i = 0; i < mTargetTrends.Total(); i++) + { + // + CChartObjectTrend *iTrend = (CChartObjectTrend *)mTargetTrends.At(i); + iTrend.Width(value); + } + } + + /** + * Set Target Color ... + * + * @param value: Color ... + */ + void TargetColor(color value) + { + // + for (int i = 0; i < mTargetTrends.Total(); i++) + { + // + CChartObjectTrend *iTrend = (CChartObjectTrend *)mTargetTrends.At(i); + iTrend.Color(value); + } + } + + /** + * Set Target Style ... + * + * @param value: ENUM_LINE_STYLE ... + */ + void TargetStyle(ENUM_LINE_STYLE value) + { + // + for (int i = 0; i < mTargetTrends.Total(); i++) + { + // + CChartObjectTrend *iTrend = (CChartObjectTrend *)mTargetTrends.At(i); + iTrend.Style(value); + } + } + + // + // ENTRY ... + + /** + * Set Entry Width ... + * + * @param value: Integer ... + */ + void EntryWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mEntryTrend.Width(value); + } + + /** + * Set Entry Color ... + * + * @param value: Color ... + */ + void EntryColor(color value) + { + mEntryTrend.Color(value); + } + + /** + * Set Entry Style ... + * + * @param value: ENUM_LINE_STYLE ... + */ + void EntryStyle(ENUM_LINE_STYLE value) + { + mEntryTrend.Style(value); + } + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_SIGNAL_OBJ; + } + + // + private: + // + + // + CChartObjectTrend mTPTrend; + CChartObjectTrend mSLTrend; + CChartObjectTrend mEntryTrend; + CArrayObj mTargetTrends; +}; + +class XCOHCLObject : public XCBaseObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param pivot: XPVPivot instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XOHCL &bar, + datetime to, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = bar.IsValid() && + IsValid(to); + if (!result) + { + return result; + } + + // + string name = bar.GetTag(); + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + string nameMD5 = ToMD5(name); + + // + // High Shadow ... + string hShadowName = ToString(X_BAR_H_SHW) + "_" + nameMD5; + + // + result = mHighShadowRect.Create( + chart_id, + hShadowName, + window, + bar.time, + bar.high, + to, + bar.GetUp() // + ); + if (!result) + { + return result; + } + + // + // Body ... + string bodyName = ToString(X_BAR_BDY) + "_" + nameMD5; + + // + result = mBodyRect.Create( + chart_id, + bodyName, + window, + bar.time, + bar.GetUp(), + to, + bar.GetDown() // + ); + if (!result) + { + // + mHighShadowRect.Delete(); + mHighShadowRect.Detach(); + return result; + } + + // + // Low Shadow ... + string lShadowName = ToString(X_BAR_L_SHW) + "_" + nameMD5; + + // + result = mLowShadowRect.Create( + chart_id, + lShadowName, + window, + bar.time, + bar.GetDown(), + to, + bar.low // + ); + if (!result) + { + // + mBodyRect.Delete(); + mBodyRect.Detach(); + mHighShadowRect.Delete(); + mHighShadowRect.Detach(); + return result; + } + + // + if (result) + { + ObjName(name); + } + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Set High Shadow Width ... + * + * @param value: Integer ... + */ + void HighShadowWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mHighShadowRect.Width(value); + } + + /** + * Set High Shadow Color ... + * + * @param value: Color ... + */ + void HighShadowColor(color value) + { + mHighShadowRect.Color(value); + } + + /** + * Set High Shadow Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void HighShadowStyle(ENUM_LINE_STYLE value) + { + mHighShadowRect.Style(value); + } + + /** + * Set High Shadow Fill ... + * + * @param value: Boolean ... + */ + void HighShadowFill(bool value) + { + mHighShadowRect.Fill(value); + } + + /** + * Set Body Width ... + * + * @param value: Integer ... + */ + void BodyWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mBodyRect.Width(value); + } + + /** + * Set Body Color ... + * + * @param value: Color ... + */ + void BodyColor(color value) + { + mBodyRect.Color(value); + } + + /** + * Set Body Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void BodyStyle(ENUM_LINE_STYLE value) + { + mBodyRect.Style(value); + } + + /** + * Set Body Fill ... + * + * @param value: Boolean ... + */ + void BodyFill(bool value) + { + mBodyRect.Fill(value); + } + + /** + * Set Low Shadow Width ... + * + * @param value: Integer ... + */ + void LowShadowWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mLowShadowRect.Width(value); + } + + /** + * Set Low Shadow Color ... + * + * @param value: Color ... + */ + void LowShadowColor(color value) + { + mLowShadowRect.Color(value); + } + + /** + * Set Low Shadow Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void LowShadowStyle(ENUM_LINE_STYLE value) + { + mLowShadowRect.Style(value); + } + + /** + * Set Low Shadow Fill ... + * + * @param value: Boolean ... + */ + void LowShadowFill(bool value) + { + mLowShadowRect.Fill(value); + } + + void BarSpes( + int width = 1, + color clr = clrNONE, + ENUM_LINE_STYLE style = STYLE_SOLID, + bool fill = false // + ) + { + // + BodyWidth(width); + LowShadowWidth(width); + HighShadowWidth(width); + + // + BodyColor(clr); + LowShadowColor(clr); + HighShadowColor(clr); + + // + BodyStyle(style); + LowShadowStyle(style); + HighShadowStyle(style); + + // + BodyFill(fill); + LowShadowFill(fill); + HighShadowFill(fill); + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_OHCL_OBJ; + } + + // + private: + // + + // + // Props ... + CChartObjectRectangle mHighShadowRect; + CChartObjectRectangle mBodyRect; + CChartObjectRectangle mLowShadowRect; +}; + +class XCBoxObject : public XCBaseObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param pivot: XPVPivot instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + string name, + double upper, + double lower, + datetime from, + datetime to, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = + upper > 0 && + lower > 0 && + to > from && + IsValid(to) && + IsValid(name) && + IsValid(from) && + upper > lower; + if (!result) + { + return result; + } + + // + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + string nameMD5 = ToMD5(name); + + // + result = mRect.Create( + chart_id, + name, + window, + from, + upper, + to, + lower // + ); + if (!result) + { + return result; + } + + // + if (result) + { + ObjName(name); + } + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Set Width ... + * + * @param value: Integer ... + */ + void BoxWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mRect.Width(value); + } + + /** + * Set Color ... + * + * @param value: Color ... + */ + void BoxColor(color value) + { + mRect.Color(value); + } + + /** + * Set Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void BoxStyle(ENUM_LINE_STYLE value) + { + mRect.Style(value); + } + + /** + * Set Fill ... + * + * @param value: Boolean ... + */ + void BoxFill(bool value) + { + mRect.Fill(value); + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_BOX_OBJ; + } + + // + private: + // + + // + // Props ... + CChartObjectRectangle mRect; +}; + +class XCRRObject : public XCBaseObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param rr: XRR instance Reference ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XRR &rr, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = rr.IsValid(); + if (!result) + { + return result; + } + + // + string name = rr.GetTag(); + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + string nameMD5 = ToMD5(name); + + // + bool isLong = IsLong(rr.type); + + // + double price1 = rr.entry; + double price2 = rr.sl; + + // + datetime time1 = rr.time; + datetime time2 = (datetime)((int)rr.time + 5 * PeriodSeconds(rr.period)); + + // + result = mFibo.Create( + chart_id, + name, + window, + time1, + price1, + time2, + price2 // + ); + if (!result) + { + return result; + } + + // + mRR = rr; + ObjName(name); + + // + int tpsCount = ArraySize(rr.tps); + int levels = tpsCount + 2; + result = mFibo.LevelsCount(levels); + if (!result) + { + return result; + } + + // + // Set Fibo Levels ... + + // + result = mFibo.LevelValue(0, 0); + if (!result) + { + return result; + } + result = mFibo.LevelDescription(0, "SL"); + if (!result) + { + return result; + } + + // + result = mFibo.LevelValue(1, 1.0); + if (!result) + { + return result; + } + result = mFibo.LevelDescription(1, "Entry"); + if (!result) + { + return result; + } + + // + for (int i = 0; i < tpsCount; i++) + { + // + int idx = i + 2; + double level = 1.0 + rr.tps[i]; + string description = "TP " + ToString(rr.tps[i]); + + // + result = mFibo.LevelValue( + idx, + level // + ); + if (!result) + { + break; + } + + // + result = mFibo.LevelDescription( + idx, + description // + ); + if (!result) + { + break; + } + } + if (!result) + { + return result; + } + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_RR_OBJ; + } + + // + private: + // + + // + // Props ... + XRR mRR; + CChartObjectFibo mFibo; + + // + bool SetSLProps( + int width = 1, + color clr = clrRed, + ENUM_LINE_STYLE style = STYLE_SOLID, + string description = "" // + ) + { + // + bool result = false; + + // + result = SetLevelProps( + 0, + width, + clr, + style, + description // + ); + + // + return result; + } + + // + bool SetEntryProps( + int width = 1, + color clr = clrOrange, + ENUM_LINE_STYLE style = STYLE_SOLID, + string description = "" // + ) + { + // + bool result = false; + + // + result = SetLevelProps( + 0, + width, + clr, + style, + description // + ); + + // + return result; + } + + // + bool SetTPProps( + double tpValue, + int width = 1, + color clr = clrLime, + ENUM_LINE_STYLE style = STYLE_SOLID, + string description = "" // + ) + { + // + bool result = false; + + // + int tpIDX = FindIndex( + tpValue, + mRR.tps // + ); + result = IsValidIndex(tpIDX); + if (!result) + { + return result; + } + + // + tpIDX += 2; + + // + result = SetLevelProps( + tpIDX, + width, + clr, + style, + description // + ); + + // + return result; + } + + // + bool SetLevelProps( + int id, + int width = 1, + color clr = clrYellow, + ENUM_LINE_STYLE style = STYLE_SOLID, + string description = "" // + ) + { + // + bool result = false; + + // + // Color ... + result = mFibo.LevelColor( + id, + clr // + ); + if (!result) + { + return result; + } + + // + // Style ... + result = mFibo.LevelStyle( + id, + style // + ); + if (!result) + { + return result; + } + + // + // Width ... + if (width > 0) + { + // + result = mFibo.LevelWidth( + id, + width // + ); + if (!result) + { + return result; + } + } + + // + // Description ... + if (IsValid(description)) + { + // + result = mFibo.LevelDescription( + id, + description // + ); + if (!result) + { + return result; + } + } + + // + return result; + } +}; + +class XCTrendObject : public XCBaseObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param rr: XRR instance Reference ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XPoint &swings[], + bool useMinAsStart = true, + string prefix = NULL // + ) + { + // + bool result = false; + + // + int count = ArraySize(swings); + result = + count >= 2 && + IsValidSize(count); + if (!result) + { + return result; + } + + // + double min = 0; + datetime minAt = NULL; + + // + double max = 0; + datetime maxAt = NULL; + + // + // Etract Min/Max ... + for (int i = 0; i < count; i++) + { + // + XPoint iPoint = swings[i]; + + // + if (!iPoint.IsValid()) + { + // + iPoint.Clean(); + continue; + } + + // + bool canSetMin = + min == 0 + ? true + : min > iPoint.value; + if (canSetMin) + { + // + minAt = iPoint.at; + min = iPoint.value; + } + + // + bool canSetMax = + max == 0 + ? true + : max < iPoint.value; + if (canSetMax) + { + // + maxAt = iPoint.at; + max = iPoint.value; + } + + // + iPoint.Clean(); + } + + // + double first = + useMinAsStart + ? min + : max; + datetime firstTime = + useMinAsStart + ? minAt + : maxAt; + + // + double second = + useMinAsStart + ? max + : min; + datetime secondTime = + useMinAsStart + ? maxAt + : minAt; + + // + // Validate Points ... + result = + // + first > 0 && + second > 0 && + (useMinAsStart + ? first <= second + : first >= second) && + IsSpecifiedValid(firstTime) && + IsSpecifiedValid(secondTime) + // + ; + if (!result) + { + return result; + } + + // + ENUM_X_DIRECTION dir = + useMinAsStart + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + string name = "XTRND" + ToString(dir) + "_" + ToString(first) + "_" + ToString(second); + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + string nameMD5 = ToMD5(name); + + // + result = mTrend.Create( + chart_id, + name, + window, + firstTime, + first, + secondTime, + second // + ); + if (!result) + { + return result; + } + + // + ObjName(name); + + // + return result; + } + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param rr: XRR instance Reference ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XSwingPoint &swings[], + string prefix = NULL // + ) + { + // + bool result = false; + + // + int count = ArraySize(swings); + result = + count >= 2 && + IsValidSize(count); + if (!result) + { + return result; + } + + // + ENUM_X_SWING_TYPE type = swings[0].type; + bool isSwingLows = type == X_SWING_LOW; + + // + double values[]; + int valuesCount = ExtractSwings( + swings, + values // + ); + result = valuesCount == count; + if (!result) + { + return result; + } + + // + int firstIDX = -1; + double first = 0; + datetime firstTime = NULL; + + // + int secondIDX = -1; + double second = 0; + datetime secondTime = NULL; + + // + if (isSwingLows) + { + // + first = GetMin( + values, + firstIDX, + 0, + 0 // + ); + if (IsValidIndex(firstIDX)) + { + // + firstTime = swings[firstIDX].time; + + // + second = FindBiggerThan( + first, + values, + true // + ); + secondIDX = FindIndex( + second, + values // + ); + if (IsValidIndex(secondIDX)) + { + secondTime = swings[secondIDX].time; + } + } + } + else + { + // + first = GetMax( + values, + firstIDX, + 0, + 0 // + ); + if (IsValidIndex(firstIDX)) + { + // + firstTime = swings[firstIDX].time; + + // + second = FindLesserThan( + first, + values, + true // + ); + secondIDX = FindIndex( + second, + values // + ); + if (IsValidIndex(secondIDX)) + { + secondTime = swings[secondIDX].time; + } + } + } + + // + // Validate Points ... + result = + // + IsValidIndex(firstIDX) && + IsValidIndex(secondIDX) && + // + IsSpecifiedValid(firstTime) && + IsSpecifiedValid(secondTime) && + // + (isSwingLows + ? first < second + : first > second) + // + ; + if (!result) + { + return result; + } + + // + string name = ToString(type) + "_" + ToString(first) + "_" + ToString(second); + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + string nameMD5 = ToMD5(name); + + // + result = mTrend.Create( + chart_id, + name, + window, + firstTime, + first, + secondTime, + second // + ); + if (!result) + { + return result; + } + + // + ObjName(name); + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Set Trend Color ... + * + * @param value: Color ... + */ + void TrendColor(color value) + { + mTrend.Color(value); + } + + void TrendRayLeft(bool value) + { + mTrend.RayLeft(value); + } + + void TrendRayRight(bool value) + { + mTrend.RayRight(value); + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_TREND_OBJ; + } + + // + private: + // + + // + // Props ... + CChartObjectTrend mTrend; +}; + +// +// Zone Ticks ... + +// +// Specify How to Draws Specified Levels ... +struct XTickZoneLevelSpecs +{ + // + double percent; // Max Allowed Percent of Tick Zone ... + + // + // Label Info ... + color labelColor; + string labelFont; + int labelFontSize; + double labelAngel; + + // + // Zone Info ... + bool zoneFill; + int zoneWidth; + color zoneColor; + ENUM_LINE_STYLE zoneStyle; + + // + // Constructor ... + XTickZoneLevelSpecs() + { + Default(); + } + + // + // Tools ... + + /** + * Initialize Drawing Specs ... + * + * @param _percent: Double, Max Allowed Percent ... + * @param _labelColor: Color, Specified Label Color ... + * @param _zoneColoe: Color, Specified Zone Color ... + * @param _zoneFill: Boolean, Specified Fill Zone or not ... + * @param _zoneStyle: ENUM_LINE_STYLE member, Specified Zone Style ... + * @param _labelFontSize: Integer, Specified Label Font Size ... + * @param _labelFont: String, Specified Label Font Name ... + * @param _labelAngel: Double, Specified Label Angel ... + * + * @return ( bool ) + */ + bool Init( + double _percent, + color _labelColor = clrWhite, + color _zoneColor = clrWhite, + bool _zoneFill = false, + ENUM_LINE_STYLE _zoneStyle = STYLE_DOT, + int _zoneWidth = 1, + int _labelFontSize = 12, + string _labelFont = "Arial", + double _labelAngel = 0 // + ) + { + // + bool result = false; + + // + Default(); + + // + result = _percent > 0; + if (!result) + { + return result; + } + + // + percent = _percent; + labelColor = _labelColor; + zoneColor = _zoneColor; + zoneFill = _zoneFill; + zoneStyle = _zoneStyle; + + // + if (_zoneWidth > 0) + { + zoneWidth = _zoneWidth; + } + + // + if (_labelFontSize > 0) + { + labelFontSize = _labelFontSize; + } + + // + if (IsSpecifiedValid(_labelFont)) + { + labelFont = _labelFont; + } + + // + if (_labelAngel >= 0) + { + labelAngel = _labelAngel; + } + + // + result = IsValid(); + + // + return result; + } + + /** + * Set Default Properties ... + */ + void Default() + { + // + percent = 0; + + // + // Label ... + labelAngel = 0; + labelFontSize = 13; + labelFont = "Arial"; + labelColor = clrWhite; + + // + // Zone ... + zoneWidth = 1; + zoneFill = false; + zoneColor = clrWhite; + zoneStyle = STYLE_DOT; + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + // + percent > 0 && + // + // Zone ... + zoneWidth > 0 && + // + // Label ... + labelFontSize > 0 && + IsSpecifiedValid(labelFont) + // + ; + + // + return result; + } + + // +}; + +class XCTickZoneObject : public XCBaseObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param name: String, Specify Chart Object Identifier ... + * @param from: Datetime ... + * @param to: Datetime ... + * @param zone: XCTickZone instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + string name, + datetime from, + datetime to, + XCTickZone *zone, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = + IsValid(name) && + zone.IsValid() && + IsValid(to) && + IsValid(from); + if (!result) + { + return result; + } + + // + double points = GetPoints(zone.symbol); + if (points <= 0) + { + points = 1; + } + double distance = 1 * points; + + // + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + + // + string rectName = "TKZ_" + name; + result = mRect.Create( + chart_id, + rectName, + window, + from, + zone.high, + to, + zone.low // + ); + if (!result) + { + return result; + } + + // + int fromToDiff = ((int)to - (int)from); + datetime labelsDate = (datetime)((int)to - (fromToDiff / 5)); + + // + string lblName = "LBLT_" + name; + result = mTLabel.Create( + chart_id, + lblName, + window, + labelsDate, + zone.high - distance // + ); + if (!result) + { + return result; + } + + // + mTLabel.Description("T: " + ToString(zone.percent) + "%"); + + // + string lblVName = "LBLV_" + name; + result = mVLabel.Create( + chart_id, + lblVName, + window, + labelsDate, + zone.low + (2.5 * distance) // + ); + if (!result) + { + return result; + } + + // + mVLabel.Description("V: " + ToString(zone.volumePercent) + "%"); + + // + ObjName(name); + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_TICK_ZONE_OBJ; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Set Zone Width ... + * + * @param value: Integer ... + */ + void ZoneWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mRect.Width(value); + } + + /** + * Set Zone Color ... + * + * @param value: Color ... + */ + void ZoneColor(color value) + { + mRect.Color(value); + } + + /** + * Set Zone Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void ZoneStyle(ENUM_LINE_STYLE value) + { + mRect.Style(value); + } + + /** + * Set Zone Fill ... + * + * @param value: Boolean ... + */ + void ZoneFill(bool value) + { + mRect.Fill(value); + } + + /** + * Set Label Color ... + * + * @param value: Color ... + */ + void LabelColor(color value) + { + // + mTLabel.Color(value); + mVLabel.Color(value); + } + + /** + * Set Label Size ... + * + * @param value: Integer ... + */ + void LabelSize(int value) + { + // + mTLabel.FontSize(value); + mVLabel.FontSize(value); + } + + /** + * Set Label Font ... + * + * @param value: String ... + */ + void LabelFont(string value) + { + // + mTLabel.Font(value); + mVLabel.Font(value); + } + + /** + * Set Label Angle ... + * + * @param value: double ... + */ + void LabelAngle(double value) + { + // + mTLabel.Angle(value); + mVLabel.Angle(value); + } + + // + private: + // + // Props ... + CChartObjectRectangle mRect; + CChartObjectLabel mTLabel; + CChartObjectLabel mVLabel; + + // +}; +class XCTicksZoneObject : public XCBaseObject +{ + // + public: + // + + // + void ~XCTicksZoneObject() + { + mZones.Clear(); + } + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param zone: XCTicksZone instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XCTicksZone &zone, + XTickZoneLevelSpecs &specs[], + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + string name = zone.GetTag(); + int levels = zone.Levels(); + result = levels > 0; + if (!result) + { + return result; + } + + // + for (int i = 0; i < levels; i++) + { + // + XCTickZone *iZone = zone.GetZone(i); + XCTickZoneObject *iObj; + iObj = new XCTickZoneObject(); + bool isCreated = iObj.Create( + chart_id, + window, + ToString(i) + "_" + name, + zone.From(), + zone.To(), + iZone, + prefix // + ); + if (!isCreated) + { + break; + } + + // + XTickZoneLevelSpecs iSpec; + bool hasSpecs = FindSpecs( + iZone, + iSpec, + specs // + ); + if (hasSpecs) + { + // + // Label ... + iObj.LabelFont(iSpec.labelFont); + iObj.LabelAngle(iSpec.labelAngel); + iObj.LabelColor(iSpec.labelColor); + iObj.LabelSize(iSpec.labelFontSize); + + // + // Zone ... + iObj.ZoneFill(iSpec.zoneFill); + iObj.ZoneColor(iSpec.zoneColor); + iObj.ZoneWidth(iSpec.zoneWidth); + iObj.ZoneStyle(iSpec.zoneStyle); + } + + // + mZones.Add(iObj); + } + + // + if (result) + { + ObjName(name); + } + else + { + mZones.Clear(); + } + + // + return result; + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_TICKS_ZONE_OBJ; + } + + // + // Getter(s) / Setter(s) ... + + // + // Actions ... + + /** + * Destroy Object ... + */ + void Destroy() + { + mZones.Clear(); + } + + /** + * Find Specified TickZone Drawing Specs ... + * + * @param zone: XCTickZone instance, reference to Search For it ... + * @param spec: XTickZoneLevelSpecs instance, reference to Result ... + * @param specs: XTickZoneLevelSpecs instance Collection for Search ... + * + * @return ( bool ) + */ + bool FindSpecs( + XCTickZone *zone, + XTickZoneLevelSpecs &spec, + XTickZoneLevelSpecs &specs[] // + ) + { + // + bool result = false; + + // + int count = ArraySize(specs); + result = + zone.IsValid() && + IsValidSize(count); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XTickZoneLevelSpecs iSpecs = specs[i]; + + // + bool isSpecValidForZone = + !spec.IsValid() + ? zone.percent <= iSpecs.percent + : zone.percent <= iSpecs.percent && + spec.percent > iSpecs.percent; + if (isSpecValidForZone) + { + spec = iSpecs; + } + } + + // + result = spec.IsValid(); + + // + return result; + } + + // + private: + // + // Props ... + CArrayObj mZones; + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14031218/Classes/x-saherelm.x-expert.class.mq5 b/BKPS/14031218/Classes/x-saherelm.x-expert.class.mq5 new file mode 100644 index 0000000..db922b4 --- /dev/null +++ b/BKPS/14031218/Classes/x-saherelm.x-expert.class.mq5 @@ -0,0 +1,967 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XCBaseExpert +// Description: provides all based classes for use ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.x-alert.class.mq5" +#include "../Classes/x-saherelm.x-trade.class.mq5" + +// +// Definitions ... +string XCBaseExpertToken = "XCBaseEA"; + +// +// Inputs ... + +// +// Implementations ... +class XCBaseExpert : public XCBaseAlert +{ + // + public: + // + + // + XCTrade *mTrader; // Trader of Expert Adviser ... + + // + // Constructur(s) ... + void XCBaseExpert() + { + } + + // + // Deconstructor ... + void ~XCBaseExpert() + { + // + delete mTrader; + + // + ZeroMemory(mTrader); + } + + // + // Getter(s) / Setter(s) ... + + // + // Common ... + + /** + * Get Magic Number ... + * + * @return ( long ) + */ + long MagicNumber() + { + return mMagicNumber; + } + + /** + * Set Magic Number ... + * + * @param value: Long ... + */ + void MagicNumber(long value) + { + // + mMagicNumber = value; + ReConfigure(); + } + + /** + * Get Slippage ... + * + * @return ( int ) + */ + int Slippage() + { + return mSlippage; + } + + /** + * Set Slippage ... + * + * @param value: Integer ... + */ + void Slippage(int value) + { + // + mSlippage = value; + ReConfigure(); + } + + /** + * Get Tag Prefix ... + * + * @return ( string ) + */ + string TagPrefix() + { + return mTagPrefix; + } + + /** + * Set Tag Prefix ... + * + * @param value: String ... + */ + void TagPrefix(string value) + { + // + mTagPrefix = value; + ReConfigure(); + } + + // + // Symbol ... + + /** + * Get Period ... + * + * @return ( ENUM_TIMEFRAMES ) + */ + ENUM_TIMEFRAMES GetPeriod() + { + return mPeriod; + } + + /** + * Set Period ... + * + * @param value: ENUM_TIMEFRAMES member ... + */ + void SetPeriod(ENUM_TIMEFRAMES value) + { + // + mPeriod = value; + ReConfigure(); + } + + /** + * Get Symbol ... + * + * @return ( string ) + */ + string GetSymbol() + { + return mSymbol; + } + + /** + * Set Symbol ... + * + * @param value: String ... + */ + void SetSymbol(string value) + { + // + mSymbol = value; + ReConfigure(); + } + + /** + * Get Multi Symbol is Enable or Not ... + * + * @return ( bool ) + */ + bool MultiSymbol() + { + return mMultiSymbol; + } + + /** + * Set Multi Symbol is Enable or Not ... + * + * @param value: Boolean ... + */ + void MultiSymbol(bool value) + { + // + mMultiSymbol = value; + ReConfigure(); + } + + /** + * Get Multi Provided Symbols ... + * + * @return ( string ) + */ + string Symbols() + { + return mSymbols; + } + + /** + * Set Multi Provided Symbols ... + * + * @param value: String ... + */ + void Symbols(string value) + { + // + mSymbols = value; + ReConfigure(); + } + + // + // Signalling ... + + /** + * Get Force Disable Signalling ... + * + * @return ( bool ) + */ + bool Disabled() + { + return mDisabled; + } + + /** + * Set Force Disable Signalling ... + * + * @param value: Boolean ... + */ + void Disabled(bool value) + { + // + mDisabled = value; + ReConfigure(); + } + + /** + * Get Allow Long Signals ... + * + * @return ( bool ) + */ + bool AllowLong() + { + return mAllowLong; + } + + /** + * Set Allow Long Signals ... + * + * @param value: Boolean ... + */ + void AllowLong(bool value) + { + // + mAllowLong = value; + ReConfigure(); + } + + /** + * Get Allow Short Signalling ... + * + * @return ( bool ) + */ + bool AllowShort() + { + return mAllowShort; + } + + /** + * Set Allow Short Signalling ... + * + * @param value: Boolean ... + */ + void AllowShort(bool value) + { + // + mAllowShort = value; + ReConfigure(); + } + + // + // Reports ... + + /** + * Get Report New Month State ... + * + * @return ( bool ) + */ + bool ReportNewMonths() + { + return mReportNewMonths; + } + + /** + * Set Report New Month State ... + * + * @param value: Boolean ... + */ + void ReportNewMonths(bool value) + { + // + mReportNewMonths = value; + ReConfigure(); + } + + /** + * Get Report New Weeks State ... + * + * @return ( bool ) + */ + bool ReportNewWeeks() + { + return mReportNewWeeks; + } + + /** + * Set Report New Weeks State ... + * + * @param value: Boolean ... + */ + void ReportNewWeeks(bool value) + { + // + mReportNewWeeks = value; + ReConfigure(); + } + + /** + * Get Report New Days State ... + * + * @return ( bool ) + */ + bool ReportNewDays() + { + return mReportNewDays; + } + + /** + * Set Report New Days State ... + * + * @param value: Boolean ... + */ + void ReportNewDays(bool value) + { + // + mReportNewDays = value; + ReConfigure(); + } + + /** + * Get Report New Hours State ... + * + * @return ( bool ) + */ + bool ReportNewHours() + { + return mReportNewHours; + } + + /** + * Set Report New Hours State ... + * + * @param value: Boolean ... + */ + void ReportNewHours(bool value) + { + // + mReportNewHours = value; + ReConfigure(); + } + + // + // Actions ... + + /** + * Handle Expert OnInit Event ... + * + * @return ( bool ) + */ + bool HandleOnInit() + { + // + bool result = false; + + // + string message = ""; + + // + // Validate Input ... + result = ValidateInputs(); + if (!result) + { + // + message = "Invalid Inputs ...."; + + // + Alert(message); + } + + // + // Initial All Requirements ... + result = InitEA(); + if (!result) + { + return result; + } + + // + // Initial All GUI Requirements ... + result = InitGUI(); + if (!result) + { + return result; + } + + // + message = "Initialized Successfully ..."; + Alert(message); + + // + return result; + } + + /** + * Handle Expert OnDeInit Event ... + */ + void HandleOnDeInit() + { + // + // Destroy all GUI Requirements ... + DestroyGUI(); + + // + // Alert De Initialization Succeeded ... + string msg = "De Initialized Successfully ..."; + Alert(msg); + + // + // Destroy all EA Requirements ... + DestroyEA(); + } + + /** + * Handle Expert OnTick Event ... + */ + void HandleOnTick() + { + // + UpdateGUI(); + HandleReportTime(); + HandleStrategiesOnTick(); + HandleStrategiesGuard(); + } + + /** + * Handle Expert OnTrade Event ... + */ + void HandleOnTrade() + { + mTrader.HandleOnTrade(); + } + + /** + * Handle Expert OnTimer Event ... + */ + void HandleOnTimer() + { + } + + /** + * Handle Expert OnChart Event ... + */ + void HandleOnChartEvent( + const int id, + const long &lparam, + const double &dparam, + const string &sparam // + ) + { + } + + // + // Virtual Actions ... + + /** + * Apply Default Configurations ... + */ + virtual void DefaultConfigure() + { + // + // Commons ... + Slippage(10); + TagPrefix(""); + MagicNumber(1694056); + + // + // Symbol ... + SetSymbol(_Symbol); + SetPeriod(_Period); + MultiSymbol(false); + Symbols("EURUSDb,GBPUSDb,USDJPYb,USDCHFb,DowJones30,XAUUSDb"); + + // + // Signalling ... + Disabled(false); + AllowLong(true); + AllowShort(true); + + // + string tag = GetTag(); + + // + // Alert ... + SetAlertPrefix(tag); + SetAlertLogAlerts(true); + SetAlertPushAlerts(true); + SetAlertMailAlerts(false); + SetAlertEnableAlerts(true); + SetAlertTerminalAlerts(false); + + // + // Reports ... + ReportNewDays(true); + ReportNewWeeks(false); + ReportNewHours(false); + ReportNewMonths(false); + } + + /** + * Vaslidate Inputs ... + * + * @return ( virtual bool ) + */ + virtual bool ValidateInputs() + { + // + bool result = false; + + // + string errMessage = ""; + + // + bool isCommonValid = ( + // + mSlippage > 0 && + mMagicNumber > 0 + // + ); + if (!isCommonValid) + { + // + errMessage += "common configurations error;" + "\n"; + } + + // + result = + // + // Common ... + isCommonValid && + // + // Otere ... + true + // + ; + + // + if (!result) + { + // + // Since here Logger not Initiallized, we Use Raw Print Command ... + errMessage = " Errors: \n" + errMessage; + Alert(errMessage); + } + + // + return result; + } + + // + // Initializers and DeInitializers ... + + /** + * Initial EA Requirements ... + * + * @return ( virtual bool ) + */ + virtual bool InitEA() + { + // + bool result = false; + + // + // Initialize Indicator Helpers ... + + // + // Create Trader Instance and Configure it ... + mTrader = new XCTrade( + mSlippage, + mMagicNumber // + ); + + // + return result; + } + + /** + * Destroy Initialized Requirements ... + */ + virtual void DestroyEA() + { + // + delete mTrader; + + // + ZeroMemory(mTrader); + } + + /** + * GUI Initialize if required ... + * + * @return ( virtual bool ) + */ + virtual bool InitGUI() + { + // + bool result = false; + + // + result = true; + + // + return result; + } + + /** + * Update All GUI Contents ... + */ + virtual void UpdateGUI() + { + } + + /** + * Destroy all Initialized GUi Elements ... + */ + virtual void DestroyGUI() + { + } + + // + // Event Handlers ... + + /** + * Calls When a Position's SL Triggered ... + * + * @param deal: XDeal instance ... + */ + virtual void HandleOnStopLossTriggered(const XDeal &deal) + { + HandleReportBalance(); + } + + /** + * Calls When a Position's TP Triggered ... + * + * @param deal: XDeal instance ... + */ + virtual void HandleOnTakeProfitTriggered(const XDeal &deal) + { + HandleReportBalance(); + } + + /** + * Handle Force Close a Position ... + * + * @param ticket: Position Ticket ... + * @param position: XPosition ... + * @param comment: Closing Comment ... + */ + virtual void HandleOnPositionForceClosed( + const ulong ticket, + const XPosition &position, + const string comment // + ) + { + HandleReportBalance(); + } + + /** + * Handle Position Modified ... + * + * @param ticket: ULONG ... + * @param profit: Double ... + * @param comment: String ... + */ + virtual void HandleOnPositionModified( + const ulong ticket, + const double profit, + const string comment // + ) + { + } + + /** + * Handle Position Partially Closed ... + * + * @param ticket: ULONG ... + * @param profit: Double ... + * @param comment: String ... + */ + virtual void HandleOnPositionPartialClosed( + const ulong ticket, + const double profit, + const string comment // + ) + { + } + + /** + * Handle Deals Changed ... + * + * @param count: Integer, Number of Changes ... + */ + virtual void HandleOnDealsChanged(int count) + { + } + + /** + * Handle Orders Changed ... + * + * @param count: Integer, Number of Changes ... + */ + virtual void HandleOnOrdersChanged(int count) + { + } + + /** + * Handle Positions Changed ... + * + * @param count: Integer, Number of Changes ... + */ + virtual void HandleOnPositionsChanged(int count) + { + } + + /** + * Do All Signalling Processing Here ... + */ + virtual void HandleStrategiesOnTick() + { + } + + /** + * Check Strategies for Guards and then Apply Them ... + */ + virtual void HandleStrategiesGuard() + { + } + + // + // Time Handlers ... + + virtual void HandleOnNewMonth() + { + } + + virtual void HandleOnNewWeek() + { + } + + virtual void HandleOnNewDay() + { + } + + virtual void HandleOnNewHour() + { + } + + virtual void ReConfigure() + { + } + + /** + * Generate Identifier Tag ... + * + * @return ( virtual string ) + */ + virtual string GetTag() + { + // + string result = NULL; + + // + string tagPrefix = TagPrefix(); + if (IsValid(tagPrefix)) + { + result = tagPrefix; + } + else + { + result = ""; + } + + // + result = + XCBaseExpertToken + result; + + // + return result; + } + + // + protected: + // + + // + // Props ... + + // + XTimeTracker mTimeTracker; // Time Tracker for Providing Reports ... + + // + // Actions ... + + /** + * Report Account Balance ... + */ + void HandleReportBalance() + { + // + if (!IsRunningOnTestMode()) + { + return; + } + + // + string msg = "Balance: " + ToString(mTrader.mAccount.GetBalance()); + Log(msg); + } + + /** + * Time Reporting based on Inputs ... + */ + void HandleReportTime() + { + // + // Monthly Report .... + if (mTimeTracker.IsNewMonth()) + { + // + HandleOnNewMonth(); + + // + if (mReportNewMonths) + { + // + string msg = "New Month ..."; + + // + Alert(msg); + } + } + + // + // Weekly Report .... + if (mTimeTracker.IsNewWeek()) + { + // + HandleOnNewWeek(); + + // + if (mReportNewWeeks) + { + // + string msg = "New Week ..."; + + // + Alert(msg); + } + } + + // + // Daily Report .... + if (mTimeTracker.IsNewDay()) + { + // + HandleOnNewDay(); + + // + if (mReportNewDays) + { + // + string msg = "New Day ..."; + + // + Alert(msg); + } + } + + // + // Hourly Report .... + if (mTimeTracker.IsNewHour()) + { + // + HandleOnNewHour(); + + // + if (mReportNewHours) + { + // + string msg = "New Hour ..."; + + // + Alert(msg); + } + } + } + + // + private: + // + + // + // Props ... + + // + // Common ... + long mMagicNumber; // Magic Number ... + int mSlippage; // Slippage ... + string mTagPrefix; // Tag Prefix ... + + // + // Symbol ... + ENUM_TIMEFRAMES mPeriod; // Period ... + string mSymbol; // Symbol ... + bool mMultiSymbol; // Multi Symbol is Enable or Not ... + string mSymbols; // Multi Provided Symbols ... + + // + // Signalling ... + bool mDisabled; // Force Disable Signalling ... + bool mAllowLong; // Allow Long Signals ... + bool mAllowShort; // Allow Short Signals ... + + // + // Reports ... + bool mReportNewMonths; // Report New Month ... + bool mReportNewWeeks; // Report New Weeks ... + bool mReportNewDays; // Report New Days ... + bool mReportNewHours; // Report New Hours ... + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14031218/Classes/x-saherelm.x-helper.class.mq5 b/BKPS/14031218/Classes/x-saherelm.x-helper.class.mq5 new file mode 100644 index 0000000..945ba69 --- /dev/null +++ b/BKPS/14031218/Classes/x-saherelm.x-helper.class.mq5 @@ -0,0 +1,151 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCBaseHelper +// Description: provides all Base Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Includes ... +#include "../Classes/x-saherelm.base.class.mq5" + +// +// Definitions ... + +// +// a Class for Handle base requirements ... +// for indicators ... +class XCBaseHelper : public XCBase +{ + // + // Public ... + public: + // + // Constructor ... + void XCBaseHelper( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period // Trading Time Frame + ) + { + // + mSymbol = symbol; + mPeriod = period; + } + + // + // Deconstructor ... + void ~XCBaseHelper() + { + // + IndicatorRelease(mHandler); + } + + // + // Setter(s) / Getter(s) ... + + // + // Symbol ... + string GetSymbol() + { + return mSymbol; + } + + // + // Period ... + ENUM_TIMEFRAMES GetPeriod() + { + return mPeriod; + } + + // + // Retrieve Bars ... + int CountBars() + { + // + int result = + Bars( + mSymbol, + mPeriod + // + ); + + // + return result; + } + + // + // Retrieve Indicator Calculated Bars ... + int CountCalculatedBars() + { + return BarsCalculated(mHandler); + } + + // + virtual void Free() {} + + // + // Generate Tag ... + virtual string GetTag() + { + // + string result = NULL; + + // + result = + // + GetToken() + + "[" + + GetSymbol() + "|" + + ToString(GetPeriod()) + + "]" + // + ; + + // + return result; + } + + // + // Functions ... + + // + // Protected ... + protected: + // + // Props ... + + // + // Symbol ... + string mSymbol; + + // + // Period ... + ENUM_TIMEFRAMES mPeriod; + + // + // Indicator Handler ... + int mHandler; + + // + // Private ... + private: + // +}; + +// +// Tools .... \ No newline at end of file diff --git a/BKPS/14031218/Classes/x-saherelm.x-http.class.mq5 b/BKPS/14031218/Classes/x-saherelm.x-http.class.mq5 new file mode 100644 index 0000000..631532f --- /dev/null +++ b/BKPS/14031218/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/14031218/Classes/x-saherelm.x-md5.class.mq5 b/BKPS/14031218/Classes/x-saherelm.x-md5.class.mq5 new file mode 100644 index 0000000..e5cc201 --- /dev/null +++ b/BKPS/14031218/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/14031218/Classes/x-saherelm.x-poi.class.ex5 b/BKPS/14031218/Classes/x-saherelm.x-poi.class.ex5 new file mode 100644 index 0000000..8aef304 Binary files /dev/null and b/BKPS/14031218/Classes/x-saherelm.x-poi.class.ex5 differ diff --git a/BKPS/14031218/Classes/x-saherelm.x-poi.class.mq5 b/BKPS/14031218/Classes/x-saherelm.x-poi.class.mq5 new file mode 100644 index 0000000..5fdbd4d --- /dev/null +++ b/BKPS/14031218/Classes/x-saherelm.x-poi.class.mq5 @@ -0,0 +1,3334 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XPOI +// Description: Provides Point of Interests ... +// - Swing Highs; +// - Swing Lows; +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... + +// +#include "../Classes/x-saherelm.x-alert.class.mq5" +#include "../Classes/x-saherelm.x-bar.analyser.class.mq5" +#include "../Libraries/x-saherelm.x-poi.state.lib.mq5" + +// +#include + +// +// Implementation ... + +// +// POI Detector Class ... +class XCPOIDetector : public XCBaseAlert +{ + // + public: + // + + // + // Constructors ... + /** + * Create an Instance ... + * + * @param symbol: String ... + * @param period: ENUM_TIMEFRAMES member ... + */ + void XCPOIDetector( + string symbol, + ENUM_TIMEFRAMES period) + { + // + // Attach Required Properties ... + mSymbol = symbol; + mPeriod = period; + + // + // Initialize Bar Tracker ... + mBarTracker.Init( + mSymbol, + mPeriod // + ); + + // + mBarAnalyser = new XCBarAnalyser(); + + // + // Apply Default Configurations ... + Default(); + } + + // + // Deconstructor ... + void ~XCPOIDetector() + { + Destroy(); + } + + // + // Getter(s) / Setter(s) ... + + /** + * Retrieve Detector Symbol ... + * + * @return ( string ) + */ + string GetSymbol() + { + return mSymbol; + } + + /** + * Retrieve Detector Period ... + * + * @return ( ENUM_TIMEFRAMES ) + */ + ENUM_TIMEFRAMES GetPeriod() + { + return mPeriod; + } + + /** + * Get Max Required POI(s) allowed to Holds ... + * + * @return ( int ) + */ + int MaxRequiredPOIs() + { + return mMaxRequiredPOIs; + } + + /** + * Set Max Required POI(s) allowed to Holds ... + * + * @param value: int ... + */ + void MaxRequiredPOIs(int value) + { + // + if (value < 0) + { + value = 5; + } + + // + mMaxRequiredPOIs = value; + } + + /** + * Get Max Allowed Loopback for POI(s) Detection on Initialization Process ... + * + * @return ( int ) + */ + int MaxAllowedLoopbackForInit() + { + return maxAllowedLoopbackForInit; + } + + /** + * Set Max Allowed Loopback for POI(s) Detection on Initialization Process ... + * + * @param value: int ... + */ + void MaxAllowedLoopbackForInit(int value) + { + // + if (value < 0) + { + value = 578; + } + + // + maxAllowedLoopbackForInit = value; + } + + /** + * Get Swing Range Validation ... + * + * @return ( int ) + */ + int SwingRange() + { + return mSwingRange; + } + + /** + * Set Swing Range Validation ... + * + * @param value: int ... + */ + void SwingRange(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mSwingRange = value; + } + + /** + * Get Momentum Bar Detection Extends Range ... + * + * @return ( int ) + */ + int MomentumExtend() + { + return mMomentumExtend; + } + + /** + * Set Momentum Bar Detection Extends Range ... + * + * @param value: int ... + */ + void MomentumExtend(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mMomentumExtend = value; + } + + /** + * Get Momentum Bar Detection Body Percent ... + * + * @return ( double ) + */ + double MomentumBodyPercent() + { + return mMomentumBodyPercent; + } + + /** + * Set Momentum Bar Detection Body Percent ... + * + * @param value: double ... + */ + void MomentumBodyPercent(double value) + { + // + if (value < 50) + { + value = 50; + } + + // + if (value > 100) + { + value = 100; + } + + // + mMomentumBodyPercent = value; + } + + /** + * Get Rejection Bar Detection Extends Range ... + * + * @return ( int ) + */ + int RejectionExtend() + { + return mRejectionExtend; + } + + /** + * Set Rejection Bar Detection Extends Range ... + * + * @param value: int ... + */ + void RejectionExtend(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mRejectionExtend = value; + } + + /** + * Get Rejection Bar Detection Shadow Percent ... + * + * @return ( double ) + */ + double RejectionShadowPercent() + { + return mRejectionShadowPercent; + } + + /** + * Set Rejection Bar Detection Shadow Percent ... + * + * @param value: double ... + */ + void RejectionShadowPercent(double value) + { + // + if (value < 50) + { + value = 50; + } + + // + if (value > 100) + { + value = 100; + } + + // + mRejectionShadowPercent = value; + } + + /** + * Get Support and Resistance Detection Range ... + * + * @return ( int ) + */ + int SupResRange() + { + return mSupResRange; + } + + /** + * Set Support and Resistance Detection Range ... + * + * @param value: int ... + */ + void SupResRange(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mSupResRange = value; + } + + /** + * Get use Support and Resistance Range as Start ... + * + * @return ( bool ) + */ + bool SupResRangeAsStart() + { + return mSupResRangeAsStart; + } + + /** + * Set use Support and Resistance Range as Start ... + * @param value: bool ... + */ + void SupResRangeAsStart(bool value) + { + mSupResRangeAsStart = value; + } + + /** + * Get OrderBlock Detection Same Bars ... + * + * @return ( int ) + */ + int OrderBlockSameBars() + { + return mOrderBlockSameBars; + } + + /** + * Set OrderBlock Detection Same Bars ... + * + * @param value: int ... + */ + void OrderBlockSameBars(int value) + { + // + if (value < 2) + { + value = 2; + } + + // + mOrderBlockSameBars = value; + } + + /** + * Get FairValueGap Detection Same Bars ... + * + * @return ( int ) + */ + int FairValueGapSameBars() + { + return mFairValueGapSameBars; + } + + /** + * Set FairValueGap Detection Same Bars ... + * + * @param value: int ... + */ + void FairValueGapSameBars(int value) + { + // + if (value < 2) + { + value = 2; + } + + // + mFairValueGapSameBars = value; + } + + /** + * Get Minimum Length of Cnsolidation Zone ... + * + * @return ( int ) + */ + int ConsolidationZoneMinLoopback() + { + return mConsolidationZoneMinLoopback; + } + + /** + * Set Minimum Length of Cnsolidation Zone ... + * + * @param value: int ... + */ + void ConsolidationZoneMinLoopback(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mConsolidationZoneMinLoopback = value; + } + + /** + * Get Consolidation Zone Range in Point ... + * + * @return ( double ) + */ + double ConsolidationZoneRangeInPoint() + { + return mConsolidationZoneRangeInPoint; + } + + /** + * Set Consolidation Zone Range in Point ... + * + * @param value: double + */ + void ConsolidationZoneRangeInPoint(double value) + { + // + if (value < 50) + { + value = 50; + } + + // + mConsolidationZoneRangeInPoint = value; + } + + /** + * Get Consolidation Zone Upper Applied To ... + * + * @return ( ENUM_APPLIED_PRICE ) + */ + ENUM_APPLIED_PRICE ConsolidationZonesLowerAppliedTo() + { + return mConsolidationZonesLowerAppliedTo; + } + + /** + * Set Consolidation Zone Upper Applied To ... + * + * @param value: ENUM_APPLIED_PRICE + */ + void ConsolidationZonesLowerAppliedTo(ENUM_APPLIED_PRICE value = PRICE_LOW) + { + mConsolidationZonesLowerAppliedTo = value; + } + + /** + * Get Consolidation Zone Lower Applied To ... + * + * @return ( ENUM_APPLIED_PRICE ) + */ + ENUM_APPLIED_PRICE ConsolidationZonesUpperAppliedTo() + { + return mConsolidationZonesUpperAppliedTo; + } + + /** + * Set Consolidation Zone Lower Applied To ... + * + * @param value: ENUM_APPLIED_PRICE + */ + void ConsolidationZonesUpperAppliedTo(ENUM_APPLIED_PRICE value = PRICE_HIGH) + { + mConsolidationZonesUpperAppliedTo = value; + } + + // + // Actions ... + + /** + * Apply Default Configurations ... + */ + virtual void Default() + { + // + // Default Props ... + SwingRange(3); + SupResRange(21); + MomentumExtend(1); + RejectionExtend(1); + MaxRequiredPOIs(100); + OrderBlockSameBars(3); + FairValueGapSameBars(3); + MomentumBodyPercent(70); + SupResRangeAsStart(true); + RejectionShadowPercent(70); + MaxAllowedLoopbackForInit(578); + ConsolidationZoneMinLoopback(5); + ConsolidationZoneRangeInPoint(50); + ConsolidationZonesLowerAppliedTo(PRICE_LOW); + ConsolidationZonesUpperAppliedTo(PRICE_HIGH); + } + + /** + * Add Event Listener ... + * + * @param listener: TOnPOIEvent instance ... + */ + void AddEventListener(TOnPOIEvent listener) + { + // + Add( + listener, + mEventListeners // + ); + } + + /** + * Initialize Instance ... + */ + void Init( + int barIndex = 0, + bool ignoreMaxAllowed = true // + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (maxAllowedLoopbackForInit <= 0) + { + return; + } + + // + mLock = true; + bool canContinue = true; + int index = barIndex + maxAllowedLoopbackForInit; + if (!IsValidIndex(index)) + { + // + mLock = false; + return; + } + + // + while (canContinue) + { + // + XOHCL iBar; + bool has = iBar.Init( + mSymbol, + mPeriod, + index // + ); + index--; + + // + int count = 0; + ENUM_XPOI_EVENTS iEvent = X_POI_EVENT_NONE; + + // + // Swings ... + DetectSwing( + iBar, + iEvent, + false // + ); + + // + // Rejection Bar ... + DetectRejectionBar( + iBar, + iEvent, + false // + ); + // + // Momentum Bar ... + DetectMomentumBar( + iBar, + iEvent, + false // + ); + + // + // Support ... + DetectSupportZone( + iBar, + iEvent, + false // + ); + + // + // Demand ... + DetectDemandZone( + iBar, + iEvent, + false // + ); + + // + // Resistance ... + DetectResistanceZone( + iBar, + iEvent, + false // + ); + + // + // Supply ... + DetectSupplyZone( + iBar, + iEvent, + false // + ); + + // + // OrderBlock ... + DetectOrderBlock( + iBar, + iEvent, + false // + ); + + // + // FairValueGap ... + DetectFairValueGap( + iBar, + iEvent, + false // + ); + + // + // Consolidation Zone ... + DetectConsolidationZone( + iBar, + iEvent, + false // + ); + + // + canContinue = + has && + index >= 0; + + // + iBar.Clean(); + } + + // + ReverseCollections(); + + // + mLock = false; + } + + /** + * Update POI(s) ... + * @param events: ENUM_XPOI_EVENTS member Collection ... + */ + void Update( + ENUM_XPOI_EVENTS &events[], + int barIndex = 0 // + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Clean(events); + + // + if (mLock) + { + return; + } + + // + // Check Bar Tracker if Waits ... + if (!mBarTracker.IsNewBar()) + { + return; + } + + // + mLock = true; + + // + XOHCL iBar; + bool has = iBar.Init( + mSymbol, + mPeriod, + barIndex // + ); + + // + if (!has) + { + // + iBar.Clean(); + + // + return; + } + + // + int count = 0; + ENUM_XPOI_EVENTS iEvent = X_POI_EVENT_NONE; + + // + // Swings ... + has = DetectSwing( + iBar, + iEvent // + ); + if (has) + { + // + Add( + iEvent, + events // + ); + + // + XCBasePOI *item = NULL; + XCSwing *iSwing = NULL; + if (iEvent == X_SWING_LOW_DETECTED) + { + // + has = GetLastItem( + iSwing, + mSwingLows // + ); + } + else if (iEvent == X_SWING_HIGH_DETECTED) + { + // + has = GetLastItem( + iSwing, + mSwingHighs // + ); + } + if (has) + { + item = (XCBasePOI *)iSwing; + } + + // + has = item != NULL; + if (has) + { + // + NotifyEventListeners( + iEvent, + item // + ); + } + } + + // + // Momentum Bar ... + has = DetectMomentumBar( + iBar, + iEvent // + ); + if (has) + { + // + Add( + iEvent, + events // + ); + + // + XCBasePOI *item = NULL; + XCMomentumBar *iMomentum = NULL; + if (iEvent == X_BULLISH_MOMENTUM_BAR_DETECTED) + { + // + has = GetLastItem( + iMomentum, + mBullishMomentumBars // + ); + } + else if (iEvent == X_BEARISH_MOMENTUM_BAR_DETECTED) + { + // + has = GetLastItem( + iMomentum, + mBearishMomentumBars // + ); + } + if (has) + { + item = (XCBasePOI *)iMomentum; + } + + // + has = item != NULL; + if (has) + { + // + NotifyEventListeners( + iEvent, + item // + ); + } + } + + // + // Rejection Bar ... + has = DetectRejectionBar( + iBar, + iEvent // + ); + if (has) + { + // + Add( + iEvent, + events // + ); + + // + XCBasePOI *item = NULL; + XCRejectionBar *iRejection = NULL; + if (iEvent == X_BULLISH_REJECTION_BAR_DETECTED) + { + // + has = GetLastItem( + iRejection, + mBullishRejectionBars // + ); + } + else if (iEvent == X_BEARISH_REJECTION_BAR_DETECTED) + { + // + has = GetLastItem( + iRejection, + mBearishRejectionBars // + ); + } + if (has) + { + item = (XCBasePOI *)iRejection; + } + + // + has = item != NULL; + if (has) + { + // + NotifyEventListeners( + iEvent, + item // + ); + } + } + + // + // Support ... + has = DetectSupportZone( + iBar, + iEvent // + ); + if (has) + { + // + Add( + iEvent, + events // + ); + + // + XCBasePOI *item = NULL; + XCSupportZone *iZone = NULL; + has = GetLastItem( + iZone, + mSupportZones // + ); + if (has) + { + item = (XCBasePOI *)iZone; + } + + // + has = item != NULL; + if (has) + { + // + NotifyEventListeners( + iEvent, + item // + ); + } + } + + // + // Demand ... + has = DetectDemandZone( + iBar, + iEvent // + ); + if (has) + { + // + Add( + iEvent, + events // + ); + + // + XCBasePOI *item = NULL; + XCDemandZone *iZone = NULL; + has = GetLastItem( + iZone, + mDemandZones // + ); + if (has) + { + item = (XCBasePOI *)iZone; + } + + // + has = item != NULL; + if (has) + { + // + NotifyEventListeners( + iEvent, + item // + ); + } + } + + // + // Resistance ... + has = DetectResistanceZone( + iBar, + iEvent // + ); + if (has) + { + // + Add( + iEvent, + events // + ); + + // + XCBasePOI *item = NULL; + XCResistanceZone *iZone = NULL; + has = GetLastItem( + iZone, + mResistanceZones // + ); + if (has) + { + item = (XCBasePOI *)iZone; + } + + // + has = item != NULL; + if (has) + { + // + NotifyEventListeners( + iEvent, + item // + ); + } + } + + // + // Supply ... + has = DetectSupplyZone( + iBar, + iEvent // + ); + if (has) + { + // + Add( + iEvent, + events // + ); + + // + XCBasePOI *item = NULL; + XCSupplyZone *iZone = NULL; + has = GetLastItem( + iZone, + mSupplyZones // + ); + if (has) + { + item = (XCBasePOI *)iZone; + } + + // + has = item != NULL; + if (has) + { + // + NotifyEventListeners( + iEvent, + item // + ); + } + } + + // + // OrderBlock ... + has = DetectOrderBlock( + iBar, + iEvent // + ); + if (has) + { + // + Add( + iEvent, + events // + ); + + // + XCBasePOI *item = NULL; + XCOrderBlock *iZone = NULL; + if (iEvent == X_BULLISH_ORDERBLOCK_DETECTED) + { + // + has = GetLastItem( + iZone, + mBullishOrderBlocks // + ); + } + else if (iEvent == X_BEARISH_ORDERBLOCK_DETECTED) + { + // + has = GetLastItem( + iZone, + mBearishOrderBlocks // + ); + } + if (has) + { + item = (XCBasePOI *)iZone; + } + + // + has = item != NULL; + if (has) + { + // + NotifyEventListeners( + iEvent, + item // + ); + } + } + + // + // FairValueGap ... + has = DetectFairValueGap( + iBar, + iEvent // + ); + if (has) + { + // + Add( + iEvent, + events // + ); + + // + XCBasePOI *item = NULL; + XCFVG *iZone = NULL; + if (iEvent == X_BULLISH_FVG_DETECTED) + { + // + has = GetLastItem( + iZone, + mBullishFairValueGaps // + ); + } + else if (iEvent == X_BEARISH_FVG_DETECTED) + { + // + has = GetLastItem( + iZone, + mBearishFairValueGaps // + ); + } + if (has) + { + item = (XCBasePOI *)iZone; + } + + // + has = item != NULL; + if (has) + { + // + NotifyEventListeners( + iEvent, + item // + ); + } + } + + // + has = DetectConsolidationZone( + iBar, + iEvent // + ); + if (has) + { + // + Add( + iEvent, + events // + ); + } + + // + iBar.Clean(); + mLock = false; + // mBarTracker.Waits(); + + // + if (HasChild(events)) + { + CleanupUnusedCollections(); + } + } + + /** + * Get Current State of POIs ... + * + * @param state: XPOIState instance ... + */ + void GetState( + XPOIState &state // + ) + { + // + state.Clean(); + + // + state.symbol = mSymbol; + state.period = mPeriod; + state.time = TimeCurrent(); + + // + Copy( + mSwings, + state.swings // + ); + + // + Copy( + mSwingHighs, + state.swingHighs // + ); + + // + Copy( + mSwingLows, + state.swingLows // + ); + + // + Copy( + mMomentumBars, + state.momentumBars // + ); + + // + Copy( + mBullishMomentumBars, + state.bullishMomentumBars // + ); + + // + Copy( + mBearishMomentumBars, + state.bearishMomentumBars // + ); + + // + Copy( + mRejectionBars, + state.rejectionBars // + ); + + // + 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( + mOrderBlocks, + state.orderBlocks // + ); + + // + Copy( + mBullishOrderBlocks, + state.bullishOrderBlocks // + ); + + // + Copy( + mBearishOrderBlocks, + state.bearishOrderBlocks // + ); + + // + Copy( + mFairValueGaps, + state.fairValueGaps // + ); + + // + Copy( + mBullishFairValueGaps, + state.bullishFairValueGaps // + ); + + // + Copy( + mBearishFairValueGaps, + state.bearishFairValueGaps // + ); + + // + Copy( + mConsolidationZones, + state.consolidationZones // + ); + + // + Copy( + mBullishConsolidationZones, + state.bullishConsolidationZones // + ); + + // + Copy( + mBearishConsolidationZones, + state.bearishConsolidationZones // + ); + + // + } + + /** + * Destroy Instance ... + */ + void Destroy() + { + // + mBarTracker.Clean(); + ZeroMemory(mBarAnalyser); + + // + CleanCollections(); + } + + // + // + // + // + // + // + + /** + * Detect Swing Bars ... + * + * @param bar: XOHCL instance ... + * @param reversal: boolean reversal add to collection ... + * + * @return ( bool ) + */ + bool DetectSwing( + XOHCL &bar, + ENUM_XPOI_EVENTS &state, + bool reversal = false // + ) + { + // + bool result = false; + + // + state = X_POI_EVENT_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + ENUM_X_DIRECTION iDir; + result = mBarAnalyser.IsSwing( + bar, + iDir, + mSwingRange // + ); + + // + result = result && + HasDirection(iDir); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(iDir); + bool isBearish = IsBearish(iDir); + + // + ENUM_XPOIS type = + isBullish + ? X_POI_SWING_LOW + : X_POI_SWING_HIGH; + + // + // Swing Object ... + XCSwing *swing; + swing = new XCSwing(); + result = swing.Init( + bar, + type // + ); + if (!result) + { + return result; + } + + // + // Add ... + + // + int idx = FindIndex( + swing, + mSwings // + ); + result = !IsValidIndex(idx); + if (!result) + { + return result; + } + + // + if (reversal) + { + // + ArrayReverse(mSwings); + + // + Add( + swing, + mSwings // + ); + + // + ArrayReverse(mSwings); + } + else + { + // + Add( + swing, + mSwings // + ); + } + + // + if (isBullish) + { + // + // Add Swings ... + if (reversal) + { + // + ArrayReverse(mSwings); + + // + Add( + swing, + mSwings // + ); + + // + ArrayReverse(mSwings); + } + else + { + // + Add( + swing, + mSwingLows // + ); + } + } + else if (isBearish) + { + // + // Add Swings ... + if (reversal) + { + // + ArrayReverse(mSwingHighs); + + // + Add( + swing, + mSwingHighs // + ); + + // + ArrayReverse(mSwingHighs); + } + else + { + // + Add( + swing, + mSwingHighs // + ); + } + } + + // + state = + isBullish + ? X_SWING_LOW_DETECTED + : X_SWING_HIGH_DETECTED; + + // + return result; + } + + /** + * Detect Momentum Bars ... + * + * @param bar: XOHCL instance ... + * @param reversal: boolean reversal add to collection ... + * + * @return ( bool ) + */ + bool DetectMomentumBar( + XOHCL &bar, + ENUM_XPOI_EVENTS &state, + bool reversal = false // + ) + { + // + bool result = false; + + // + state = X_POI_EVENT_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + ENUM_X_DIRECTION iDir; + result = mBarAnalyser.IsMomentumBar( + bar, + iDir, + mMomentumExtend, // Extends ... + mMomentumBodyPercent // Body Percent ... + ); + + // + result = result && + HasDirection(iDir); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(iDir); + bool isBearish = IsBearish(iDir); + + // + ENUM_XPOIS type = + isBullish + ? X_POI_MOMENTUM_BAR + : X_POI_MOMENTUM_BAR; + + // + // Swing Object ... + XCMomentumBar *momentum; + momentum = new XCMomentumBar(); + result = momentum.Init( + bar // + ); + if (!result) + { + return result; + } + + // + int idx = FindIndex( + momentum, + mMomentumBars // + ); + result = !IsValidIndex(idx); + if (!result) + { + return result; + } + + // + // Add ... + if (reversal) + { + // + ArrayReverse(mMomentumBars); + + // + Add( + momentum, + mMomentumBars // + ); + + // + ArrayReverse(mMomentumBars); + } + else + { + // + Add( + momentum, + mMomentumBars // + ); + } + + // + if (isBullish) + { + // + // Add Swings ... + if (reversal) + { + // + ArrayReverse(mBullishMomentumBars); + + // + Add( + momentum, + mBullishMomentumBars // + ); + + // + ArrayReverse(mBullishMomentumBars); + } + else + { + // + Add( + momentum, + mBullishMomentumBars // + ); + } + } + else if (isBearish) + { + // + // Add Swings ... + if (reversal) + { + // + ArrayReverse(mBearishMomentumBars); + + // + Add( + momentum, + mBearishMomentumBars // + ); + + // + ArrayReverse(mBearishMomentumBars); + } + else + { + // + Add( + momentum, + mBearishMomentumBars // + ); + } + } + + // + state = + isBullish + ? X_BULLISH_MOMENTUM_BAR_DETECTED + : X_BEARISH_MOMENTUM_BAR_DETECTED; + + // + return result; + } + + /** + * Detect Rejection Bars ... + * + * @param bar: XOHCL instance ... + * @param reversal: boolean reversal add to collection ... + * + * @return ( bool ) + */ + bool DetectRejectionBar( + XOHCL &bar, + ENUM_XPOI_EVENTS &state, + bool reversal = false // + ) + { + // + bool result = false; + + // + state = X_POI_EVENT_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + ENUM_X_DIRECTION iDir; + result = mBarAnalyser.IsRejectionBar( + bar, + iDir, + mRejectionExtend, // Extends ... + mRejectionShadowPercent // Shadow Percent ... + ); + + // + result = result && + HasDirection(iDir); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(iDir); + bool isBearish = IsBearish(iDir); + + // + ENUM_XPOIS type = + isBullish + ? X_POI_MOMENTUM_BAR + : X_POI_MOMENTUM_BAR; + + // + // Swing Object ... + XCRejectionBar *rejection; + rejection = new XCRejectionBar(); + result = rejection.Init( + bar // + ); + if (!result) + { + return result; + } + + // + int idx = FindIndex( + rejection, + mRejectionBars // + ); + result = !IsValidIndex(idx); + if (!result) + { + return result; + } + + // + // Add ... + if (reversal) + { + // + ArrayReverse(mRejectionBars); + + // + Add( + rejection, + mRejectionBars // + ); + + // + ArrayReverse(mRejectionBars); + } + else + { + // + Add( + rejection, + mRejectionBars // + ); + } + + // + if (isBullish) + { + // + // Add Swings ... + if (reversal) + { + // + ArrayReverse(mBullishRejectionBars); + + // + Add( + rejection, + mBullishRejectionBars // + ); + + // + ArrayReverse(mBullishRejectionBars); + } + else + { + // + Add( + rejection, + mBullishRejectionBars // + ); + } + } + else if (isBearish) + { + // + // Add Swings ... + if (reversal) + { + // + ArrayReverse(mBearishRejectionBars); + + // + Add( + rejection, + mBearishRejectionBars // + ); + + // + ArrayReverse(mBearishRejectionBars); + } + else + { + // + Add( + rejection, + mBearishRejectionBars // + ); + } + } + + // + state = + isBullish + ? X_BULLISH_REJECTION_BAR_DETECTED + : X_BEARISH_REJECTION_BAR_DETECTED; + + // + return result; + } + + /** + * Detect Support Zone ... + * + * @param bar: XOHCL instance ... + * @param reversal: boolean reversal add to collection ... + * + * @return ( bool ) + */ + bool DetectSupportZone( + XOHCL &bar, + ENUM_XPOI_EVENTS &state, + bool reversal = false, + bool forceActivation = false // + ) + { + // + bool result = false; + + // + state = X_POI_EVENT_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL supportBar; + result = mBarAnalyser + .HasSupport( + bar, + supportBar, + mSupResRange // + ); + if (!result) + { + // + supportBar.Clean(); + + // + return result; + } + + // + XCSupportZone *supportZone; + supportZone = new XCSupportZone(); + result = supportZone.Init( + supportBar, + mSupResRange, + mSupResRangeAsStart // Use Range As Start ... + ); + if (!result) + { + // + supportBar.Clean(); + ZeroMemory(supportZone); + + // + return result; + } + + // + // Check Zone Not Activated ... + if (forceActivation) + { + // + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = supportZone.IsActivated( + X_DIRECTION_BULLISH, + activationBar, + isActivationBarBodyIn, + false, + bar.period // + ); + result = !isActivated; + if (!result) + { + // + supportBar.Clean(); + activationBar.Clean(); + ZeroMemory(supportZone); + + // + return result; + } + + // + activationBar.Clean(); + } + + // + // Add ... + + // + int idx = FindIndex( + supportZone, + mSupportZones // + ); + result = !IsValidIndex(idx); + if (!result) + { + // + supportBar.Clean(); + ZeroMemory(supportZone); + + // + return result; + } + + // + if (reversal) + { + // + ArrayReverse(mSupportZones); + + // + Add( + supportZone, + mSupportZones // + ); + + // + ArrayReverse(mSupportZones); + } + else + { + // + Add( + supportZone, + mSupportZones // + ); + } + + // + state = X_SUPPORT_ZONE_DETECTED; + + // + supportBar.Clean(); + + // + return result; + } + + /** + * Detect Resistance Zone ... + * + * @param bar: XOHCL instance ... + * @param reversal: boolean reversal add to collection ... + * + * @return ( bool ) + */ + bool DetectResistanceZone( + XOHCL &bar, + ENUM_XPOI_EVENTS &state, + bool reversal = false, + bool forceActivation = false // + ) + { + // + bool result = false; + + // + state = X_POI_EVENT_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL resistanceBar; + result = mBarAnalyser + .HasResistance( + bar, + resistanceBar, + mSupResRange // + ); + if (!result) + { + // + resistanceBar.Clean(); + + // + return result; + } + + // + XCResistanceZone *resistanceZone; + resistanceZone = new XCResistanceZone(); + result = resistanceZone.Init( + resistanceBar, + mSupResRange, + mSupResRangeAsStart // Use Range As Start ... + ); + if (!result) + { + // + resistanceBar.Clean(); + ZeroMemory(resistanceZone); + + // + return result; + } + + // + // Check Zone Not Activated ... + if (forceActivation) + { + // + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = resistanceZone.IsActivated( + X_DIRECTION_BULLISH, + activationBar, + isActivationBarBodyIn, + false, + bar.period // + ); + result = !isActivated; + if (!result) + { + // + resistanceBar.Clean(); + activationBar.Clean(); + ZeroMemory(resistanceZone); + + // + return result; + } + + // + activationBar.Clean(); + } + + // + // Add ... + + // + int idx = FindIndex( + resistanceZone, + mResistanceZones // + ); + result = !IsValidIndex(idx); + if (!result) + { + // + resistanceBar.Clean(); + ZeroMemory(resistanceZone); + + // + return result; + } + + // + if (reversal) + { + // + ArrayReverse(mResistanceZones); + + // + Add( + resistanceZone, + mResistanceZones // + ); + + // + ArrayReverse(mResistanceZones); + } + else + { + // + Add( + resistanceZone, + mResistanceZones // + ); + } + + // + state = X_RESISTANCE_ZONE_DETECTED; + + // + resistanceBar.Clean(); + + // + return result; + } + + /** + * Detect Supply Zone ... + * + * @param bar: XOHCL instance ... + * @param reversal: boolean reversal add to collection ... + * + * @return ( bool ) + */ + bool DetectSupplyZone( + XOHCL &bar, + ENUM_XPOI_EVENTS &state, + bool reversal = false, + bool forceActivation = false // + ) + { + // + bool result = false; + + // + state = X_POI_EVENT_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int mSupDemRange = mSupResRange * 2; + + // + XOHCL supplyBar; + result = mBarAnalyser + .HasResistance( + bar, + supplyBar, + mSupDemRange // + ); + if (!result) + { + // + supplyBar.Clean(); + + // + return result; + } + + // + XCSupplyZone *supplyZone; + supplyZone = new XCSupplyZone(); + result = supplyZone.Init( + supplyBar, + mSupDemRange, + mSupResRangeAsStart // Use Range As Start ... + ); + if (!result) + { + // + supplyBar.Clean(); + ZeroMemory(supplyZone); + + // + return result; + } + + // + // Check Zone Not Activated ... + if (forceActivation) + { + // + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = supplyZone.IsActivated( + X_DIRECTION_BULLISH, + activationBar, + isActivationBarBodyIn, + false, + bar.period // + ); + result = !isActivated; + if (!result) + { + // + supplyBar.Clean(); + activationBar.Clean(); + ZeroMemory(supplyZone); + + // + return result; + } + + // + activationBar.Clean(); + } + + // + // Add ... + + // + int idx = FindIndex( + supplyZone, + mSupplyZones // + ); + result = !IsValidIndex(idx); + if (!result) + { + // + supplyBar.Clean(); + ZeroMemory(supplyZone); + + // + return result; + } + + // + if (reversal) + { + // + ArrayReverse(mSupplyZones); + + // + Add( + supplyZone, + mSupplyZones // + ); + + // + ArrayReverse(mSupplyZones); + } + else + { + // + Add( + supplyZone, + mSupplyZones // + ); + } + + // + state = X_SUPPLY_ZONE_DETECTED; + + // + supplyBar.Clean(); + + // + return result; + } + + /** + * Detect Demand Zone ... + * + * @param bar: XOHCL instance ... + * @param reversal: boolean reversal add to collection ... + * + * @return ( bool ) + */ + bool DetectDemandZone( + XOHCL &bar, + ENUM_XPOI_EVENTS &state, + bool reversal = false, + bool forceActivation = false // + ) + { + // + bool result = false; + + // + state = X_POI_EVENT_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int mSupDemRange = mSupResRange * 2; + + // + XOHCL demandBar; + result = mBarAnalyser + .HasSupport( + bar, + demandBar, + mSupDemRange // + ); + if (!result) + { + // + demandBar.Clean(); + + // + return result; + } + + // + XCDemandZone *demandZone; + demandZone = new XCDemandZone(); + result = demandZone.Init( + demandBar, + mSupDemRange, + mSupResRangeAsStart // Use Range As Start ... + ); + if (!result) + { + // + demandBar.Clean(); + ZeroMemory(demandZone); + + // + return result; + } + + // + // Check Zone Not Activated ... + if (forceActivation) + { + // + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = demandZone.IsActivated( + X_DIRECTION_BULLISH, + activationBar, + isActivationBarBodyIn, + false, + bar.period // + ); + result = !isActivated; + if (!result) + { + // + demandBar.Clean(); + activationBar.Clean(); + ZeroMemory(demandZone); + + // + return result; + } + + // + activationBar.Clean(); + } + + // + // Add ... + + // + int idx = FindIndex( + demandZone, + mDemandZones // + ); + result = !IsValidIndex(idx); + if (!result) + { + // + demandBar.Clean(); + ZeroMemory(demandZone); + + // + return result; + } + + // + if (reversal) + { + // + ArrayReverse(mDemandZones); + + // + Add( + demandZone, + mDemandZones // + ); + + // + ArrayReverse(mDemandZones); + } + else + { + // + Add( + demandZone, + mDemandZones // + ); + } + + // + state = X_DEMAND_ZONE_DETECTED; + + // + demandBar.Clean(); + + // + return result; + } + + /** + * Detect Order Blocks ... + * + * @param bar: XOHCL instance ... + * @param reversal: boolean reversal add to collection ... + * + * @return ( bool ) + */ + bool DetectOrderBlock( + XOHCL &bar, + ENUM_XPOI_EVENTS &state, + bool reversal = false, + bool forceActivation = false // + ) + { + // + bool result = false; + + // + state = X_POI_EVENT_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL obBar; + ENUM_X_DIRECTION obDir; + result = mBarAnalyser.HasOrderBlock( + bar, + obBar, + obDir, + mOrderBlockSameBars // + ); + if (!result) + { + // + obBar.Clean(); + + // + return result; + } + + // + XCOrderBlock *ob; + ob = new XCOrderBlock(); + result = ob.Init( + obBar, + obDir // + ); + if (!result) + { + // + obBar.Clean(); + ZeroMemory(ob); + + // + return result; + } + + // + bool isBullish = IsBullish(obDir); + bool isBearish = IsBearish(obDir); + + // + // Check Zone Not Activated ... + if (forceActivation) + { + // + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = ob.IsActivated( + obDir, + activationBar, + isActivationBarBodyIn, + false, + bar.period // + ); + result = !isActivated; + if (!result) + { + // + obBar.Clean(); + activationBar.Clean(); + ZeroMemory(ob); + + // + return result; + } + + // + activationBar.Clean(); + } + + // + int idx = FindIndex( + ob, + mOrderBlocks // + ); + result = !IsValidIndex(idx); + if (!result) + { + // + obBar.Clean(); + ZeroMemory(ob); + + // + return result; + } + + // + // Add ... + if (reversal) + { + // + ArrayReverse(mOrderBlocks); + + // + Add( + ob, + mOrderBlocks // + ); + + // + ArrayReverse(mOrderBlocks); + } + else + { + // + Add( + ob, + mOrderBlocks // + ); + } + + // + if (isBullish) + { + // + // Add Swings ... + if (reversal) + { + // + ArrayReverse(mBullishOrderBlocks); + + // + Add( + ob, + mBullishOrderBlocks // + ); + + // + ArrayReverse(mBullishOrderBlocks); + } + else + { + // + Add( + ob, + mBullishOrderBlocks // + ); + } + } + else if (isBearish) + { + // + // Add Swings ... + if (reversal) + { + // + ArrayReverse(mBearishOrderBlocks); + + // + Add( + ob, + mBearishOrderBlocks // + ); + + // + ArrayReverse(mBearishOrderBlocks); + } + else + { + // + Add( + ob, + mBearishOrderBlocks // + ); + } + } + + // + state = + isBullish + ? X_BULLISH_ORDERBLOCK_DETECTED + : X_BEARISH_ORDERBLOCK_DETECTED; + + // + obBar.Clean(); + + // + return result; + } + + /** + * Detect Fair Value Gaps ... + * + * @param bar: XOHCL instance ... + * @param reversal: boolean reversal add to collection ... + * + * @return ( bool ) + */ + bool DetectFairValueGap( + XOHCL &bar, + ENUM_XPOI_EVENTS &state, + bool reversal = false, + bool forceActivation = false // + ) + { + // + bool result = false; + + // + state = X_POI_EVENT_NONE; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL fvgStartBar; + XOHCL fvgEndBar; + ENUM_X_DIRECTION fvgDir; + result = mBarAnalyser.HasFairValueGap( + bar, + fvgStartBar, + fvgEndBar, + fvgDir, + mFairValueGapSameBars // + ); + if (!result) + { + // + fvgEndBar.Clean(); + fvgStartBar.Clean(); + + // + return result; + } + + // + XCFVG *fvg; + fvg = new XCFVG(); + result = fvg.Init( + fvgStartBar, + fvgEndBar, + fvgDir // + ); + if (!result) + { + // + ZeroMemory(fvg); + fvgEndBar.Clean(); + fvgStartBar.Clean(); + + // + return result; + } + + // + bool isBullish = IsBullish(fvgDir); + bool isBearish = IsBearish(fvgDir); + + // + // Check Zone Not Activated ... + if (forceActivation) + { + // + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = fvg.IsActivated( + fvgDir, + activationBar, + isActivationBarBodyIn, + false, + bar.period // + ); + result = !isActivated; + if (!result) + { + // + ZeroMemory(fvg); + fvgEndBar.Clean(); + fvgStartBar.Clean(); + activationBar.Clean(); + + // + return result; + } + + // + activationBar.Clean(); + } + + // + int idx = FindIndex( + fvg, + mFairValueGaps // + ); + result = !IsValidIndex(idx); + if (!result) + { + // + ZeroMemory(fvg); + fvgEndBar.Clean(); + fvgStartBar.Clean(); + + // + return result; + } + + // + // Add ... + if (reversal) + { + // + ArrayReverse(mFairValueGaps); + + // + Add( + fvg, + mFairValueGaps // + ); + + // + ArrayReverse(mFairValueGaps); + } + else + { + // + Add( + fvg, + mFairValueGaps // + ); + } + + // + if (isBullish) + { + // + // Add Swings ... + if (reversal) + { + // + ArrayReverse(mBullishFairValueGaps); + + // + Add( + fvg, + mBullishFairValueGaps // + ); + + // + ArrayReverse(mBullishFairValueGaps); + } + else + { + // + Add( + fvg, + mBullishFairValueGaps // + ); + } + } + else if (isBearish) + { + // + // Add Swings ... + if (reversal) + { + // + ArrayReverse(mBearishFairValueGaps); + + // + Add( + fvg, + mBearishFairValueGaps // + ); + + // + ArrayReverse(mBearishFairValueGaps); + } + else + { + // + Add( + fvg, + mBearishFairValueGaps // + ); + } + } + + // + state = + isBullish + ? X_BULLISH_FVG_DETECTED + : X_BEARISH_FVG_DETECTED; + + // + fvgEndBar.Clean(); + fvgStartBar.Clean(); + + // + return result; + } + + /** + * Detect Consolidation Zones ... + * + * @param bar: XOHCL instance ... + * @param reversal: boolean reversal add to collection ... + * + * @return ( bool ) + */ + bool DetectConsolidationZone( + XOHCL &bar, + ENUM_XPOI_EVENTS &state, + bool reversal = false // + ) + { + // + bool result = false; + + // + state = X_POI_EVENT_NONE; + + // + XConsolidationZone cZone; + result = mBarAnalyser.HasConsolidationZone( + bar, + cZone, + mConsolidationZoneMinLoopback, + mConsolidationZoneRangeInPoint, + mConsolidationZonesUpperAppliedTo, + mConsolidationZonesLowerAppliedTo // + ); + if (!result) + { + // + cZone.Clean(); + + // + return result; + } + + // + // Add ... + + // + bool isBullish = IsBullish(cZone.dir); + bool isBearish = IsBearish(cZone.dir); + + // + int idx = FindIndex( + cZone, + mConsolidationZones // + ); + result = !IsValidIndex(idx); + if (!result) + { + // + cZone.Clean(); + + // + return result; + } + + // + if (reversal) + { + // + ArrayReverse(mConsolidationZones); + + // + AddRef( + cZone, + mConsolidationZones // + ); + + // + ArrayReverse(mConsolidationZones); + } + else + { + // + AddRef( + cZone, + mConsolidationZones // + ); + } + + // + if (isBullish) + { + // + // Add Swings ... + if (reversal) + { + // + ArrayReverse(mBullishConsolidationZones); + + // + AddRef( + cZone, + mBullishConsolidationZones // + ); + + // + ArrayReverse(mBullishConsolidationZones); + } + else + { + // + AddRef( + cZone, + mBullishConsolidationZones // + ); + } + } + else if (isBearish) + { + // + // Add Swings ... + if (reversal) + { + // + ArrayReverse(mBearishConsolidationZones); + + // + AddRef( + cZone, + mBearishConsolidationZones // + ); + + // + ArrayReverse(mBearishConsolidationZones); + } + else + { + // + AddRef( + cZone, + mBearishConsolidationZones // + ); + } + } + + // + state = + IsBullish(cZone.dir) + ? X_BULLISH_CONSOLIDATION_ZONE_DETECTED + : X_BEARISH_CONSOLIDATION_ZONE_DETECTED; + + // + cZone.Clean(); + + // + return result; + } + + // + protected: + // + + // + void CleanCollections() + { + // + Clean(mSwings); + Clean(mSwingLows); + Clean(mSwingHighs); + Clean(mDemandZones); + Clean(mSupplyZones); + Clean(mOrderBlocks); + Clean(mMomentumBars); + Clean(mSupportZones); + Clean(mRejectionBars); + Clean(mFairValueGaps); + Clean(mEventListeners); + Clean(mResistanceZones); + Clean(mBullishOrderBlocks); + Clean(mBearishOrderBlocks); + Clean(mConsolidationZones); + Clean(mBullishMomentumBars); + Clean(mBearishMomentumBars); + Clean(mBullishRejectionBars); + Clean(mBearishRejectionBars); + Clean(mBullishFairValueGaps); + Clean(mBearishFairValueGaps); + Clean(mBullishConsolidationZones); + Clean(mBearishConsolidationZones); + } + + // + void ReverseCollections() + { + // + ArrayReverse(mSwings); + ArrayReverse(mSwingLows); + ArrayReverse(mSwingHighs); + ArrayReverse(mDemandZones); + ArrayReverse(mSupplyZones); + ArrayReverse(mOrderBlocks); + ArrayReverse(mMomentumBars); + ArrayReverse(mSupportZones); + ArrayReverse(mRejectionBars); + ArrayReverse(mFairValueGaps); + ArrayReverse(mEventListeners); + ArrayReverse(mResistanceZones); + ArrayReverse(mBullishOrderBlocks); + ArrayReverse(mBearishOrderBlocks); + ArrayReverse(mConsolidationZones); + ArrayReverse(mBullishMomentumBars); + ArrayReverse(mBearishMomentumBars); + ArrayReverse(mBullishRejectionBars); + ArrayReverse(mBearishRejectionBars); + ArrayReverse(mBullishFairValueGaps); + ArrayReverse(mBearishFairValueGaps); + ArrayReverse(mBullishConsolidationZones); + ArrayReverse(mBearishConsolidationZones); + } + + // + void CleanupUnusedCollections( + int maxAllowed = 0 // + ) + { + // + maxAllowed = MaxRequiredPOIs(); + + // + if (maxAllowed <= 0) + { + return; + } + + // + CleanupArray( + mEventListeners, + maxAllowed // + ); + + // + CleanupArray( + mSwings, + maxAllowed // + ); + + // + CleanupArray( + mSwingLows, + maxAllowed // + ); + + // + CleanupArray( + mSwingHighs, + maxAllowed // + ); + + // + CleanupArray( + mMomentumBars, + maxAllowed // + ); + + // + CleanupArray( + mBullishMomentumBars, + maxAllowed // + ); + + // + CleanupArray( + mBearishMomentumBars, + maxAllowed // + ); + + // + CleanupArray( + mRejectionBars, + maxAllowed // + ); + + // + CleanupArray( + mBullishRejectionBars, + maxAllowed // + ); + + // + CleanupArray( + mBearishRejectionBars, + maxAllowed // + ); + + // + CleanupArray( + mSupportZones, + maxAllowed // + ); + + // + CleanupArray( + mDemandZones, + maxAllowed // + ); + + // + CleanupArray( + mSupplyZones, + maxAllowed // + ); + + // + CleanupArray( + mResistanceZones, + maxAllowed // + ); + + // + CleanupArray( + mFairValueGaps, + maxAllowed // + ); + + // + CleanupArray( + mBullishFairValueGaps, + maxAllowed // + ); + + // + CleanupArray( + mBearishFairValueGaps, + maxAllowed // + ); + + // + CleanupArray( + mOrderBlocks, + maxAllowed // + ); + + // + CleanupArray( + mBullishOrderBlocks, + maxAllowed // + ); + + // + CleanupArray( + mBearishOrderBlocks, + maxAllowed // + ); + + // + CleanupArray( + mConsolidationZones, + maxAllowed // + ); + + // + CleanupArray( + mBullishConsolidationZones, + maxAllowed // + ); + + // + CleanupArray( + mBearishConsolidationZones, + maxAllowed // + ); + + // + } + + /** + * Notify Event Listeners ... + * + * @param event: ENUM_XPOI_EVENTS member, Specified Occured Event ... + * @param param: XCBasePOI implementation, Specified Event Object ... + */ + void NotifyEventListeners( + ENUM_XPOI_EVENTS event, + XCBasePOI *param // + ) + { + // + int count = ArraySize(mEventListeners); + if (!IsValidSize(count)) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + mEventListeners[i]( + event, + param // + ); + } + } + + // + private: + // + + // + // Props ... + string mSymbol; // Market Symbol ... + ENUM_TIMEFRAMES mPeriod; // Market Period ... + XBarTracker mBarTracker; // Market Bar Tracker ... + XCBarAnalyser *mBarAnalyser; // Bar Analyser ... + + // + bool mLock; + + // + int mMaxRequiredPOIs; // Max Allowed Holds POI(s) ... + int maxAllowedLoopbackForInit; // Max Allowed Loopback for POI(s) Detection on Initialization Process ... + + // + TOnPOIEvent mEventListeners[]; // Event Listeners ... + + // + XCSwing *mSwings[]; // Holds Founded Swing ... + XCSwing *mSwingLows[]; // Holds Founded Swing Lows ... + XCSwing *mSwingHighs[]; // Holds Founded Swing Highs ... + int mSwingRange; // Swing Detection Range ... + + // + XCMomentumBar *mMomentumBars[]; // Holds Founded Momentum Bars ... + XCMomentumBar *mBullishMomentumBars[]; // Holds Founded Bullish Momentum Bars ... + XCMomentumBar *mBearishMomentumBars[]; // Holds Founded Bearish Momentum Bars ... + int mMomentumExtend; // Momentum Bar Detection Extends Range ... + double mMomentumBodyPercent; // Momentum Bar Detection Body Percent ... + + // + XCRejectionBar *mRejectionBars[]; // Holds Founded Rejection Bars ... + XCRejectionBar *mBullishRejectionBars[]; // Holds Founded Bullish Rejection Bars ... + XCRejectionBar *mBearishRejectionBars[]; // Holds Founded Bearish Rejection Bars ... + int mRejectionExtend; // Rejection Bar Detection Extends Range ... + double mRejectionShadowPercent; // Rejection Bar Detection Body Percent ... + + // + XCSupplyZone *mSupplyZones[]; // Holds Detected Supply Zones ... + XCDemandZone *mDemandZones[]; // Holds Detected Demand Zones ... + + // + int mSupResRange; // Support and Resistance Detection Range ... + bool mSupResRangeAsStart; // use Support and Resistance Range as Start ... + XCSupportZone *mSupportZones[]; // Holds Detected Support Zones ... + XCResistanceZone *mResistanceZones[]; // Holds Detected Resistance Zones ... + + // + XCFVG *mFairValueGaps[]; // Holds Founded FairValueGaps ... + XCFVG *mBullishFairValueGaps[]; // Holds Founded Bullish FairValueGaps ... + XCFVG *mBearishFairValueGaps[]; // Holds Founded Bearish FairValueGaps ... + int mFairValueGapSameBars; // FairValueGap Detection Same Bars ... + + // + XCOrderBlock *mOrderBlocks[]; // Holds Founded OrderBlocks ... + XCOrderBlock *mBullishOrderBlocks[]; // Holds Founded Bullish OrderBlocks ... + XCOrderBlock *mBearishOrderBlocks[]; // Holds Founded Bearish OrderBlocks ... + int mOrderBlockSameBars; // OrderBlock Detection Same Bars ... + + // + int mConsolidationZoneMinLoopback; // Minimum Length of Cnsolidation Zone ... + double mConsolidationZoneRangeInPoint; // Consolidation Zone Range in Point ... + XConsolidationZone mConsolidationZones[]; // Holds Founded Consolidation Zones ... + XConsolidationZone mBullishConsolidationZones[]; // Holds Founded Bullish Consolidation Zones ... + XConsolidationZone mBearishConsolidationZones[]; // Holds Founded Bearish Consolidation Zones ... + ENUM_APPLIED_PRICE mConsolidationZonesLowerAppliedTo; // Consolidation Zone Upper Applied To ... + ENUM_APPLIED_PRICE mConsolidationZonesUpperAppliedTo; // Consolidation Zone Lower Applied To ... + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14031218/Classes/x-saherelm.x-poi.drawer.class.ex5 b/BKPS/14031218/Classes/x-saherelm.x-poi.drawer.class.ex5 new file mode 100644 index 0000000..6b8cbb3 Binary files /dev/null and b/BKPS/14031218/Classes/x-saherelm.x-poi.drawer.class.ex5 differ diff --git a/BKPS/14031218/Classes/x-saherelm.x-poi.drawer.class.mq5 b/BKPS/14031218/Classes/x-saherelm.x-poi.drawer.class.mq5 new file mode 100644 index 0000000..29c9f88 --- /dev/null +++ b/BKPS/14031218/Classes/x-saherelm.x-poi.drawer.class.mq5 @@ -0,0 +1,4922 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XPOIDrawer +// Description: Provides Point of Interests +// Drawing Tools ... +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.base.class.mq5" +#include "../Classes/x-saherelm.x-cobject.class.mq5" +#include "../Libraries/x-saherelm.x-poi.extensions.lib.mq5" + +// +// Definitions ... +class XCPOIDrawer : public XCBase +{ + // + public: + // + + // + // Constructor ... + void XCPOIDrawer() + { + // + Default(); + } + + // + // Deconstructor ... + void ~XCPOIDrawer() + { + // + Clean(mTicksZoneSpecs); + } + + // + // Setter Getter (s) ... + + /** + * Get Prefix ... + * + * @return ( string ) + */ + string Prefix() + { + return mPrefix; + } + + /** + * Set Prifx ... + * + * @param value: String ... + */ + void Prefix(string value) + { + mPrefix = value; + } + + /** + * Get Chart ID ... + * + * @return ( long ) + */ + long ChartIdentification() + { + return mChartIdentification; + } + + /** + * Set Chart ID ... + * + * @param value: Long ... + */ + void ChartIdentification(long value) + { + // + if (value < 0) + { + value = 0; + } + + // + mChartIdentification = value; + } + + /** + * Get SubWindow Id ... + * + * @return ( int ) + */ + int SubWindowIdentification() + { + return mSubWindowIdentification; + } + + /** + * Set SubWindow Id ... + * + * @param value: Integer ... + */ + void SubWindowIdentification(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mSubWindowIdentification = value; + } + + // + // XOHCL ... + + /** + * Get Bar Width ... + * + * @return ( int ) + */ + int BarWidth() + { + return mBarWidth; + } + + /** + * Set Bar Width ... + * + * @param value: Integer ... + */ + void BarWidth(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mBarWidth = value; + } + + /** + * Get Bar Bullish Color ... + * + * @return ( color ) + */ + color BarBullishColor() + { + return mBarBullishColor; + } + + /** + * Set Bar Bullish Color ... + * + * @param value: Color ... + */ + void BarBullishColor(color value) + { + mBarBullishColor = value; + } + + /** + * Get Bar Bearish Color ... + * + * @return ( color ) + */ + color BarBearishColor() + { + return mBarBearishColor; + } + + /** + * Set Bar Bearish Color ... + * + * @param value: Color ... + */ + void BarBearishColor(color value) + { + mBarBearishColor = value; + } + + /** + * Get Fill Bar High Shadow State ... + * + * @return ( bool ) + */ + bool BarFillHighShadow() + { + return mBarFillHighShadow; + } + + /** + * Set Fill Bar High Shadow State ... + * + * @param value: Boolean ... + */ + void BarFillHighShadow(bool value) + { + mBarFillHighShadow = value; + } + + /** + * Get Bar High Shadow Style ... + * + * @return ( ENUM_LINE_STYLE ) + */ + ENUM_LINE_STYLE BarHighShadowStyle() + { + return mBarHighShadowStyle; + } + + /** + * Set Bar High Shadow Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void BarHighShadowStyle(ENUM_LINE_STYLE value) + { + mBarHighShadowStyle = value; + } + + /** + * Get Fill Bar Body State ... + * + * @return ( bool ) + */ + bool BarFillBody() + { + return mBarFillBody; + } + + /** + * Set Fill Bar Body State ... + * + * @param value: Boolean ... + */ + void BarFillBody(bool value) + { + mBarFillBody = value; + } + + /** + * Get Bar Body Style ... + * + * @return ( ENUM_LINE_STYLE ) + */ + ENUM_LINE_STYLE BarBodyStyle() + { + return mBarBodyStyle; + } + + /** + * Set Bar Body Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void BarBodyStyle(ENUM_LINE_STYLE value) + { + mBarBodyStyle = value; + } + + /** + * Get Fill Bar Low Show State ... + * + * @return ( bool ) + */ + bool BarFillLowShadow() + { + return mBarFillLowShadow; + } + + /** + * Set Fill Bar Low Show State ... + * + * @param value: Boolean ... + */ + void BarFillLowShadow(bool value) + { + mBarFillLowShadow = value; + } + + /** + * Get Bar Low Shadow Style ... + * + * @return ( ENUM_LINE_STYLE ) + */ + ENUM_LINE_STYLE BarLowShadowStyle() + { + return mBarLowShadowStyle; + } + + /** + * Set Bar Low Shadow Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void BarLowShadowStyle(ENUM_LINE_STYLE value) + { + mBarLowShadowStyle = value; + } + + // + // Swing Low ... + + /** + * Get Swing Low Width ... + * + * @return ( int ) + */ + int SwingLowWidth() + { + return mSwingLowWidth; + } + + /** + * Set Swing Low Width ... + * + * @param value: Integer ... + */ + void SwingLowWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mSwingLowWidth = value; + } + + /** + * Get Swing Low Arrow Code ... + * + * @return ( int ) + */ + int SwingLowArrow() + { + return mSwingLowArrow; + } + + /** + * Set Swing Low Arrow Code ... + * + * @param value: Integer ... + */ + void SwingLowArrow(int value) + { + // + mSwingLowArrow = value; + } + + /** + * Get Swing Low Color ... + * + * @return ( color ) + */ + color SwingLowColor() + { + return mSwingLowColor; + } + + /** + * Set Swing Low Color ... + * + * @param value: Color ... + */ + void SwingLowColor(color value) + { + mSwingLowColor = value; + } + + // + // Swing High ... + + /** + * Get Swing High Width ... + * + * @return ( int ) + */ + int SwingHighWidth() + { + return mSwingHighWidth; + } + + /** + * Set Swing High Width ... + * + * @param value: Integer ... + */ + void SwingHighWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mSwingHighWidth = value; + } + + /** + * Get Swing High Arrow Code ... + * + * @return ( int ) + */ + int SwingHighArrow() + { + return mSwingHighArrow; + } + + /** + * Set Swing High Arrow Code ... + * + * @param value: Integer ... + */ + void SwingHighArrow(int value) + { + // + mSwingHighArrow = value; + } + + /** + * Get Swing High Color ... + * + * @return ( color ) + */ + color SwingHighColor() + { + return mSwingHighColor; + } + + /** + * Set Swing High Color ... + * + * @param value: Color ... + */ + void SwingHighColor(color value) + { + mSwingHighColor = value; + } + + // + // Bullish Momentum Bar ... + + /** + * Get Bullish Momentum Bar Width ... + * + * @return ( int ) + */ + int BullishMomentumBarWidth() + { + return mBullishMomentumBarWidth; + } + + /** + * Set Bullish Momentum Bar Width ... + * + * @param value: Integer ... + */ + void BullishMomentumBarWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mBullishMomentumBarWidth = value; + } + + /** + * Get Bullish Momentum Bar Arrow Code ... + * + * @return ( int ) + */ + int BullishMomentumBarArrow() + { + return mBullishMomentumBarArrow; + } + + /** + * Set Bullish Momentum Bar Arrow Code ... + * + * @param value: Integer ... + */ + void BullishMomentumBarArrow(int value) + { + // + mBullishMomentumBarArrow = value; + } + + /** + * Get Bullish Momentum Bar Color ... + * + * @return ( color ) + */ + color BullishMomentumBarColor() + { + return mBullishMomentumBarColor; + } + + /** + * Set Bullish Momentum Bar Color ... + * + * @param value: Color ... + */ + void BullishMomentumBarColor(color value) + { + mBullishMomentumBarColor = value; + } + + // + // Bearish Momentum Bar ... + + /** + * Get Bearish Momentum Bar Width ... + * + * @return ( int ) + */ + int BearishMomentumBarWidth() + { + return mBearishMomentumBarWidth; + } + + /** + * Set Bearish Momentum Bar Width ... + * + * @param value: Integer ... + */ + void BearishMomentumBarWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mBearishMomentumBarWidth = value; + } + + /** + * Get Bearish Momentum Bar Arrow Code ... + * + * @return ( int ) + */ + int BearishMomentumBarArrow() + { + return mBearishMomentumBarArrow; + } + + /** + * Set Bearish Momentum Bar Arrow Code ... + * + * @param value: Integer ... + */ + void BearishMomentumBarArrow(int value) + { + // + mBearishMomentumBarArrow = value; + } + + /** + * Get Bearish Momentum Bar Color ... + * + * @return ( color ) + */ + color BearishMomentumBarColor() + { + return mBearishMomentumBarColor; + } + + /** + * Set Bearish Momentum Bar Color ... + * + * @param value: Color ... + */ + void BearishMomentumBarColor(color value) + { + mBearishMomentumBarColor = value; + } + + // + // Bullish Rejection Bar ... + + /** + * Get Bullish Rejection Bar Width ... + * + * @return ( int ) + */ + int BullishRejectionBarWidth() + { + return mBullishRejectionBarWidth; + } + + /** + * Set Bullish Rejection Bar Width ... + * + * @param value: Integer ... + */ + void BullishRejectionBarWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mBullishRejectionBarWidth = value; + } + + /** + * Get Bullish Rejection Bar Arrow Code ... + * + * @return ( int ) + */ + int BullishRejectionBarArrow() + { + return mBullishRejectionBarArrow; + } + + /** + * Set Bullish Rejection Bar Arrow Code ... + * + * @param value: Integer ... + */ + void BullishRejectionBarArrow(int value) + { + // + mBullishRejectionBarArrow = value; + } + + /** + * Get Bullish Rejection Bar Color ... + * + * @return ( color ) + */ + color BullishRejectionBarColor() + { + return mBullishRejectionBarColor; + } + + /** + * Set Bullish Rejection Bar Color ... + * + * @param value: Color ... + */ + void BullishRejectionBarColor(color value) + { + mBullishRejectionBarColor = value; + } + + // + // Bearish Rejection Bar ... + + /** + * Get Bearish Rejection Bar Width ... + * + * @return ( int ) + */ + int BearishRejectionBarWidth() + { + return mBearishRejectionBarWidth; + } + + /** + * Set Bearish Rejection Bar Width ... + * + * @param value: Integer ... + */ + void BearishRejectionBarWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mBearishRejectionBarWidth = value; + } + + /** + * Get Bearish Rejection Bar Arrow Code ... + * + * @return ( int ) + */ + int BearishRejectionBarArrow() + { + return mBearishRejectionBarArrow; + } + + /** + * Set Bearish Rejection Bar Arrow Code ... + * + * @param value: Integer ... + */ + void BearishRejectionBarArrow(int value) + { + // + mBearishRejectionBarArrow = value; + } + + /** + * Get Bearish Rejection Bar Color ... + * + * @return ( color ) + */ + color BearishRejectionBarColor() + { + return mBearishRejectionBarColor; + } + + /** + * Set Bearish Rejection Bar Color ... + * + * @param value: Color ... + */ + void BearishRejectionBarColor(color value) + { + mBearishRejectionBarColor = value; + } + + // + // Supply Zone ... + + /** + * Get Fill Supply Zone ... + * + * @return ( bool ) + */ + bool SupplyZoneFill() + { + return mSupplyZoneFill; + } + + /** + * Set Fill Supply Zone ... + * + * @param value: Boolean ... + */ + void SupplyZoneFill(bool value) + { + mSupplyZoneFill = value; + } + + /** + * Get Supply Zone Width ... + * + * @return ( int ) + */ + int SupplyZoneWidth() + { + return mSupplyZoneWidth; + } + + /** + * Set Supply Zone Width ... + * + * @param value: Integer ... + */ + void SupplyZoneWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mSupplyZoneWidth = value; + } + + /** + * Get Supply Zone Color ... + * + * @return ( color ) + */ + color SupplyZoneColor() + { + return mSupplyZoneColor; + } + + /** + * Set Supply Zone Color ... + * + * @param value: Color ... + */ + void SupplyZoneColor(color value) + { + mSupplyZoneColor = value; + } + + /** + * Get Supply Zone Style ... + * + * @return ( ENUM_LINE_STYLE ) + */ + ENUM_LINE_STYLE SupplyZoneStyle() + { + return mSupplyZoneStyle; + } + + /** + * Set Supply Zone Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void SupplyZoneStyle(ENUM_LINE_STYLE value) + { + mSupplyZoneStyle = value; + } + + // + // Demand Zone ... + + /** + * Get Fill Demand Zone ... + * + * @return ( bool ) + */ + bool DemandZoneFill() + { + return mDemandZoneFill; + } + + /** + * Set Fill Demand Zone ... + * + * @param value: Boolean ... + */ + void DemandZoneFill(bool value) + { + mDemandZoneFill = value; + } + + /** + * Get Demand Zone Width ... + * + * @return ( int ) + */ + int DemandZoneWidth() + { + return mDemandZoneWidth; + } + + /** + * Set Demand Zone Width ... + * + * @param value: Integer ... + */ + void DemandZoneWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mDemandZoneWidth = value; + } + + /** + * Get Demand Zone Color ... + * + * @return ( color ) + */ + color DemandZoneColor() + { + return mDemandZoneColor; + } + + /** + * Set Demand Zone Color ... + * + * @param value: Color ... + */ + void DemandZoneColor(color value) + { + mDemandZoneColor = value; + } + + /** + * Get Demand Zone Style ... + * + * @return ( ENUM_LINE_STYLE ) + */ + ENUM_LINE_STYLE DemandZoneStyle() + { + return mDemandZoneStyle; + } + + /** + * Set Demand Zone Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void DemandZoneStyle(ENUM_LINE_STYLE value) + { + mDemandZoneStyle = value; + } + + // + // Resistance Zone ... + + /** + * Get Fill Resistance Zone ... + * + * @return ( bool ) + */ + bool ResistanceZoneFill() + { + return mResistanceZoneFill; + } + + /** + * Set Fill Resistance Zone ... + * + * @param value: Boolean ... + */ + void ResistanceZoneFill(bool value) + { + mResistanceZoneFill = value; + } + + /** + * Get Resistance Zone Width ... + * + * @return ( int ) + */ + int ResistanceZoneWidth() + { + return mResistanceZoneWidth; + } + + /** + * Set Resistance Zone Width ... + * + * @param value: Integer ... + */ + void ResistanceZoneWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mResistanceZoneWidth = value; + } + + /** + * Get Resistance Zone Color ... + * + * @return ( color ) + */ + color ResistanceZoneColor() + { + return mResistanceZoneColor; + } + + /** + * Set Resistance Zone Color ... + * + * @param value: Color ... + */ + void ResistanceZoneColor(color value) + { + mResistanceZoneColor = value; + } + + /** + * Get Resistance Zone Style ... + * + * @return ( ENUM_LINE_STYLE ) + */ + ENUM_LINE_STYLE ResistanceZoneStyle() + { + return mResistanceZoneStyle; + } + + /** + * Set Resistance Zone Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void ResistanceZoneStyle(ENUM_LINE_STYLE value) + { + mResistanceZoneStyle = value; + } + + // + // Support Zone ... + + /** + * Get Fill Support Zone ... + * + * @return ( bool ) + */ + bool SupportZoneFill() + { + return mSupportZoneFill; + } + + /** + * Set Fill Support Zone ... + * + * @param value: Boolean ... + */ + void SupportZoneFill(bool value) + { + mSupportZoneFill = value; + } + + /** + * Get Support Zone Width ... + * + * @return ( int ) + */ + int SupportZoneWidth() + { + return mSupportZoneWidth; + } + + /** + * Set Support Zone Width ... + * + * @param value: Integer ... + */ + void SupportZoneWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mSupportZoneWidth = value; + } + + /** + * Get Support Zone Color ... + * + * @return ( color ) + */ + color SupportZoneColor() + { + return mSupportZoneColor; + } + + /** + * Set Support Zone Color ... + * + * @param value: Color ... + */ + void SupportZoneColor(color value) + { + mSupportZoneColor = value; + } + + /** + * Get Support Zone Style ... + * + * @return ( ENUM_LINE_STYLE ) + */ + ENUM_LINE_STYLE SupportZoneStyle() + { + return mSupportZoneStyle; + } + + /** + * Set Support Zone Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void SupportZoneStyle(ENUM_LINE_STYLE value) + { + mSupportZoneStyle = value; + } + + // + // Bullish Order Block ... + + /** + * Get Fill Bullish Order Block ... + * + * @return ( bool ) + */ + bool BullishOrderBlockFill() + { + return mBullishOrderBlockFill; + } + + /** + * Set Fill Bullish Order Block ... + * + * @param value: Boolean ... + */ + void BullishOrderBlockFill(bool value) + { + mBullishOrderBlockFill = value; + } + + /** + * Get Bullish Order Block Width ... + * + * @return ( int ) + */ + int BullishOrderBlockWidth() + { + return mBullishOrderBlockWidth; + } + + /** + * Set Bullish Order Block Width ... + * + * @param value: Integer ... + */ + void BullishOrderBlockWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mBullishOrderBlockWidth = value; + } + + /** + * Get Bullish Order Block Color ... + * + * @return ( color ) + */ + color BullishOrderBlockColor() + { + return mBullishOrderBlockColor; + } + + /** + * Set Bullish Order Block Color ... + * + * @param value: Color ... + */ + void BullishOrderBlockColor(color value) + { + mBullishOrderBlockColor = value; + } + + /** + * Get Bullish Order Block Style ... + * + * @return ( ENUM_LINE_STYLE ) + */ + ENUM_LINE_STYLE BullishOrderBlockStyle() + { + return mBullishOrderBlockStyle; + } + + /** + * Set Bullish Order Block Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void BullishOrderBlockStyle(ENUM_LINE_STYLE value) + { + mBullishOrderBlockStyle = value; + } + + // + // Bearish Order Block ... + + /** + * Get Fill Bearish Order Block ... + * + * @return ( bool ) + */ + bool BearishOrderBlockFill() + { + return mBearishOrderBlockFill; + } + + /** + * Set Fill Bearish Order Block ... + * + * @param value: Boolean ... + */ + void BearishOrderBlockFill(bool value) + { + mBearishOrderBlockFill = value; + } + + /** + * Get Bearish Order Block Width ... + * + * @return ( int ) + */ + int BearishOrderBlockWidth() + { + return mBearishOrderBlockWidth; + } + + /** + * Set Bearish Order Block Width ... + * + * @param value: Integer ... + */ + void BearishOrderBlockWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mBearishOrderBlockWidth = value; + } + + /** + * Get Bearish Order Block Color ... + * + * @return ( color ) + */ + color BearishOrderBlockColor() + { + return mBearishOrderBlockColor; + } + + /** + * Set Bearish Order Block Color ... + * + * @param value: Color ... + */ + void BearishOrderBlockColor(color value) + { + mBearishOrderBlockColor = value; + } + + /** + * Get Bearish Order Block Style ... + * + * @return ( ENUM_LINE_STYLE ) + */ + ENUM_LINE_STYLE BearishOrderBlockStyle() + { + return mBearishOrderBlockStyle; + } + + /** + * Set Bearish Order Block Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void BearishOrderBlockStyle(ENUM_LINE_STYLE value) + { + mBearishOrderBlockStyle = value; + } + + // + // Bullish FVG ... + + /** + * Get Fill Bullish FVG ... + * + * @return ( bool ) + */ + bool BullishFVGFill() + { + return mBullishFVGFill; + } + + /** + * Set Fill Bullish FVG ... + * + * @param value: Boolean ... + */ + void BullishFVGFill(bool value) + { + mBullishFVGFill = value; + } + + /** + * Get Bullish FVG Width ... + * + * @return ( int ) + */ + int BullishFVGWidth() + { + return mBullishFVGWidth; + } + + /** + * Set Bullish FVG Width ... + * + * @param value: Integer ... + */ + void BullishFVGWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mBullishFVGWidth = value; + } + + /** + * Get Bullish FVG Color ... + * + * @return ( color ) + */ + color BullishFVGColor() + { + return mBullishFVGColor; + } + + /** + * Set Bullish FVG Color ... + * + * @param value: Color ... + */ + void BullishFVGColor(color value) + { + mBullishFVGColor = value; + } + + /** + * Get Bullish FVG Style ... + * + * @return ( ENUM_LINE_STYLE ) + */ + ENUM_LINE_STYLE BullishFVGStyle() + { + return mBullishFVGStyle; + } + + /** + * Set Bullish FVG Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void BullishFVGStyle(ENUM_LINE_STYLE value) + { + mBullishFVGStyle = value; + } + + // + // Bearish FVG ... + + /** + * Get Fill Bearish FVG ... + * + * @return ( bool ) + */ + bool BearishFVGFill() + { + return mBearishFVGFill; + } + + /** + * Set Fill Bearish FVG ... + * + * @param value: Boolean ... + */ + void BearishFVGFill(bool value) + { + mBearishFVGFill = value; + } + + /** + * Get Bearish FVG Width ... + * + * @return ( int ) + */ + int BearishFVGWidth() + { + return mBearishFVGWidth; + } + + /** + * Set Bearish FVG Width ... + * + * @param value: Integer ... + */ + void BearishFVGWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mBearishFVGWidth = value; + } + + /** + * Get Bearish FVG Color ... + * + * @return ( color ) + */ + color BearishFVGColor() + { + return mBearishFVGColor; + } + + /** + * Set Bearish FVG Color ... + * + * @param value: Color ... + */ + void BearishFVGColor(color value) + { + mBearishFVGColor = value; + } + + /** + * Get Bearish FVG Style ... + * + * @return ( ENUM_LINE_STYLE ) + */ + ENUM_LINE_STYLE BearishFVGStyle() + { + return mBearishFVGStyle; + } + + /** + * Set Bearish FVG Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void BearishFVGStyle(ENUM_LINE_STYLE value) + { + mBearishFVGStyle = value; + } + + // + // Virtuals ... + + /** + * Apply Default Configurations ... + */ + virtual void Default() + { + // + // Apply Default Props ... + + // + Prefix(NULL); + ChartIdentification(0); + SubWindowIdentification(0); + + // + BarWidth(1); + BarBearishColor(clrRed); + BarBullishColor(clrLime); + BarFillBody(false); + BarFillHighShadow(false); + BarFillLowShadow(false); + BarBodyStyle(STYLE_DOT); + BarLowShadowStyle(STYLE_DOT); + BarHighShadowStyle(STYLE_DOT); + + // + int arrowWidth = 1; + + // + SwingLowArrow(108); + SwingLowColor(clrAqua); + SwingLowWidth(arrowWidth); + + // + SwingHighArrow(108); + SwingHighWidth(arrowWidth); + SwingHighColor(clrMagenta); + + // + arrowWidth++; + + // + BullishMomentumBarArrow(225); + BullishMomentumBarWidth(arrowWidth); + BullishMomentumBarColor(clrAqua); + + // + BearishMomentumBarArrow(226); + BearishMomentumBarWidth(arrowWidth); + BearishMomentumBarColor(clrMagenta); + + // + arrowWidth++; + + // + BullishRejectionBarArrow(217); + BullishRejectionBarWidth(arrowWidth); + BullishRejectionBarColor(clrAqua); + + // + BearishRejectionBarArrow(218); + BearishRejectionBarWidth(arrowWidth); + BearishRejectionBarColor(clrMagenta); + + // + SupportZoneFill(false); + SupportZoneWidth(1); + SupportZoneStyle(STYLE_DOT); + SupportZoneColor(clrLime); + + // + ResistanceZoneFill(false); + ResistanceZoneWidth(1); + ResistanceZoneStyle(STYLE_DOT); + ResistanceZoneColor(clrRed); + + // + SupplyZoneFill(false); + SupplyZoneWidth(1); + SupplyZoneStyle(STYLE_DOT); + SupplyZoneColor(clrRed); + + // + DemandZoneFill(false); + DemandZoneWidth(1); + DemandZoneStyle(STYLE_DOT); + DemandZoneColor(clrGreen); + + // + BullishOrderBlockFill(false); + BullishOrderBlockWidth(1); + BullishOrderBlockStyle(STYLE_DASHDOT); + BullishOrderBlockColor(clrLime); + + // + BearishOrderBlockFill(false); + BearishOrderBlockWidth(1); + BearishOrderBlockStyle(STYLE_DASHDOT); + BearishOrderBlockColor(clrRed); + + // + BullishFVGFill(false); + BullishFVGWidth(1); + BullishFVGStyle(STYLE_DOT); + BullishFVGColor(clrLime); + + // + BearishFVGFill(false); + BearishFVGWidth(1); + BearishFVGStyle(STYLE_DOT); + BearishFVGColor(clrRed); + + // + // Add Default TickZone Specs ... + bool isSpecsInited = false; + bool fillTickZone = false; + XTickZoneLevelSpecs specs10; + isSpecsInited = specs10.Init( + 10, + clrWhite, + clrWhite, + fillTickZone // + ); + if (isSpecsInited) + { + AddTickZoneLevelSpecs(specs10); + } + + // + XTickZoneLevelSpecs specs20; + isSpecsInited = specs20.Init( + 20, + clrOrange, + clrOrange, + fillTickZone // + ); + if (isSpecsInited) + { + AddTickZoneLevelSpecs(specs20); + } + + // + XTickZoneLevelSpecs specs30; + isSpecsInited = specs30.Init( + 30, + clrOrange, + clrOrange, + fillTickZone // + ); + if (isSpecsInited) + { + AddTickZoneLevelSpecs(specs30); + } + + // + XTickZoneLevelSpecs specs40; + isSpecsInited = specs40.Init( + 40, + clrOrange, + clrOrange, + fillTickZone // + ); + if (isSpecsInited) + { + AddTickZoneLevelSpecs(specs40); + } + + // + XTickZoneLevelSpecs specs50; + isSpecsInited = specs50.Init( + 50, + clrYellow, + clrYellow, + fillTickZone // + ); + if (isSpecsInited) + { + AddTickZoneLevelSpecs(specs50); + } + + // + XTickZoneLevelSpecs specs60; + isSpecsInited = specs60.Init( + 60, + clrYellow, + clrYellow, + fillTickZone // + ); + if (isSpecsInited) + { + AddTickZoneLevelSpecs(specs60); + } + + // + XTickZoneLevelSpecs specs70; + isSpecsInited = specs70.Init( + 70, + clrYellow, + clrYellow, + fillTickZone // + ); + if (isSpecsInited) + { + AddTickZoneLevelSpecs(specs70); + } + + // + XTickZoneLevelSpecs specs80; + isSpecsInited = specs80.Init( + 80, + clrRed, + clrRed, + fillTickZone // + ); + if (isSpecsInited) + { + AddTickZoneLevelSpecs(specs80); + } + + // + XTickZoneLevelSpecs specs90; + isSpecsInited = specs90.Init( + 90, + clrRed, + clrRed, + fillTickZone // + ); + if (isSpecsInited) + { + AddTickZoneLevelSpecs(specs90); + } + + // + XTickZoneLevelSpecs specs100; + isSpecsInited = specs100.Init( + 100, + clrRed, + clrRed, + fillTickZone // + ); + if (isSpecsInited) + { + AddTickZoneLevelSpecs(specs100); + } + + // + } + + // + // Object Creators ... + + // + // Swings ... + + /** + * Create Swing High Object ... + * + * @param swing: XCSwing instance ... + * @param object: XCSwingHighObject pointer ... + * + * @return ( bool ) + */ + bool CreateSwingHigh( + XCSwing &swing, + XCSwingHighObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + swing.IsValid() && + swing.IsSwingHigh(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + int arrow = SwingHighArrow(); + int width = SwingHighWidth(); + color crl = SwingHighColor(); + + // + object = new XCSwingHighObject(); + result = object.Create( + chartID, + window, + arrow, + swing, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ArrowColor(crl); + object.ArrowWidth(width); + object.ArrowAnchor(ANCHOR_BOTTOM); + + // + return result; + } + + /** + * Create Swing Low Object ... + * + * @param swing: XCSwing instance ... + * @param object: XCSwingLowObject pointer ... + * + * @return ( bool ) + */ + bool CreateSwingLow( + XCSwing &swing, + XCSwingLowObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + swing.IsValid() && + swing.IsSwingLow(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + int arrow = SwingLowArrow(); + int width = SwingLowWidth(); + color crl = SwingLowColor(); + + // + object = new XCSwingLowObject(); + result = object.Create( + chartID, + window, + arrow, + swing, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ArrowColor(crl); + object.ArrowWidth(width); + object.ArrowAnchor(ANCHOR_TOP); + + // + return result; + } + + // + // Momentum Bars ... + + /** + * Create Bullish Momentum Bar Object ... + * + * @param momentumBar: XCMomentumBar instance ... + * @param object: XCBullishMomentumObject pointer ... + * + * @return ( bool ) + */ + bool CreateBullishMomentumBar( + XCMomentumBar &momentumBar, + XCBullishMomentumBarObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + momentumBar.IsValid() && + momentumBar.IsBullish(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + int arrow = BullishMomentumBarArrow(); + int width = BullishMomentumBarWidth(); + color crl = BullishMomentumBarColor(); + + // + object = new XCBullishMomentumBarObject(); + result = object.Create( + chartID, + window, + arrow, + momentumBar, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ArrowColor(crl); + object.ArrowWidth(width); + object.ArrowAnchor(ANCHOR_TOP); + + // + return result; + } + + /** + * Create Bearish Momentum Bar Object ... + * + * @param momentumBar: XCMomentumBar instance ... + * @param object: XCBearishMomentumObject pointer ... + * + * @return ( bool ) + */ + bool CreateBearishMomentumBar( + XCMomentumBar &momentumBar, + XCBearishMomentumBarObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + momentumBar.IsValid() && + momentumBar.IsBearish(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + int arrow = BearishMomentumBarArrow(); + int width = BearishMomentumBarWidth(); + color crl = BearishMomentumBarColor(); + + // + object = new XCBearishMomentumBarObject(); + result = object.Create( + chartID, + window, + arrow, + momentumBar, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ArrowColor(crl); + object.ArrowWidth(width); + object.ArrowAnchor(ANCHOR_BOTTOM); + + // + return result; + } + + // + // Rejection Bars ... + + /** + * Create Bullish Rejection Bar Object ... + * + * @param momentumBar: XCRejectionBar instance ... + * @param object: XCBullishRejectionObject pointer ... + * + * @return ( bool ) + */ + bool CreateBullishRejectionBar( + XCRejectionBar &rejectionBar, + XCBullishRejectionBarObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + rejectionBar.IsValid() && + rejectionBar.IsBullish(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + int arrow = BullishRejectionBarArrow(); + int width = BullishRejectionBarWidth(); + color crl = BullishRejectionBarColor(); + + // + object = new XCBullishRejectionBarObject(); + result = object.Create( + chartID, + window, + arrow, + rejectionBar, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ArrowColor(crl); + object.ArrowWidth(width); + object.ArrowAnchor(ANCHOR_TOP); + + // + return result; + } + + /** + * Create Bearish Rejection Bar Object ... + * + * @param rejectionBar: XCRejectionBar instance ... + * @param object: XCBearishRejectionObject pointer ... + * + * @return ( bool ) + */ + bool CreateBearishRejectionBar( + XCRejectionBar &rejectionBar, + XCBearishRejectionBarObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + rejectionBar.IsValid() && + rejectionBar.IsBearish(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + int arrow = BearishRejectionBarArrow(); + int width = BearishRejectionBarWidth(); + color crl = BearishRejectionBarColor(); + + // + object = new XCBearishRejectionBarObject(); + result = object.Create( + chartID, + window, + arrow, + rejectionBar, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ArrowColor(crl); + object.ArrowWidth(width); + object.ArrowAnchor(ANCHOR_BOTTOM); + + // + return result; + } + + // + // Support and Resistance ... + + /** + * Create Support Object ... + * + * @param zone: XCSupportZone instance ... + * @param object: XCSupportZoneObject pointer ... + * + * @return ( bool ) + */ + bool CreateSupportZone( + XCSupportZone &zone, + XCSupportZoneObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + zone.IsValid(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + bool fill = SupportZoneFill(); + int width = SupportZoneWidth(); + color crl = SupportZoneColor(); + ENUM_LINE_STYLE style = SupportZoneStyle(); + + // + object = new XCSupportZoneObject(); + result = object.Create( + chartID, + window, + zone, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ZoneFill(fill); + object.ZoneColor(crl); + object.ZoneWidth(width); + object.ZoneStyle(style); + + // + return result; + } + + /** + * Create Resistance Object ... + * + * @param zone: XCResistanceZone instance ... + * @param object: XCResistanceZoneObject pointer ... + * + * @return ( bool ) + */ + bool CreateResistanceZone( + XCResistanceZone &zone, + XCResistanceZoneObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + zone.IsValid(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + bool fill = ResistanceZoneFill(); + int width = ResistanceZoneWidth(); + color crl = ResistanceZoneColor(); + ENUM_LINE_STYLE style = ResistanceZoneStyle(); + + // + object = new XCResistanceZoneObject(); + result = object.Create( + chartID, + window, + zone, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ZoneFill(fill); + object.ZoneColor(crl); + object.ZoneWidth(width); + object.ZoneStyle(style); + + // + return result; + } + + // + // Supply and Demand Zones ... + + /** + * Create Supply Object ... + * + * @param zone: XCSupplyZone instance ... + * @param object: XCSupplyZoneObject pointer ... + * + * @return ( bool ) + */ + bool CreateSupplyZone( + XCSupplyZone &zone, + XCSupplyZoneObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + zone.IsValid(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + bool fill = SupplyZoneFill(); + int width = SupplyZoneWidth(); + color crl = SupplyZoneColor(); + ENUM_LINE_STYLE style = SupplyZoneStyle(); + + // + object = new XCSupplyZoneObject(); + result = object.Create( + chartID, + window, + zone, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ZoneFill(fill); + object.ZoneColor(crl); + object.ZoneWidth(width); + object.ZoneStyle(style); + + // + return result; + } + + /** + * Create Demand Object ... + * + * @param zone: XCDemandZone instance ... + * @param object: XCDemandZoneObject pointer ... + * + * @return ( bool ) + */ + bool CreateDemandZone( + XCDemandZone &zone, + XCDemandZoneObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + zone.IsValid(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + bool fill = DemandZoneFill(); + int width = DemandZoneWidth(); + color crl = DemandZoneColor(); + ENUM_LINE_STYLE style = DemandZoneStyle(); + + // + object = new XCDemandZoneObject(); + result = object.Create( + chartID, + window, + zone, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ZoneFill(fill); + object.ZoneColor(crl); + object.ZoneWidth(width); + object.ZoneStyle(style); + + // + return result; + } + + // + // Order Blocks ... + + /** + * Create Bullish Order Block Object ... + * + * @param zone: XCOrderBlock instance ... + * @param object: XCBullishOrderBlockObject pointer ... + * + * @return ( bool ) + */ + bool CreateBullishOrderBlock( + XCOrderBlock &zone, + XCBullishOrderBlockObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + zone.IsValid() && + zone.IsBullish(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + bool fill = BullishOrderBlockFill(); + int width = BullishOrderBlockWidth(); + color crl = BullishOrderBlockColor(); + ENUM_LINE_STYLE style = BullishOrderBlockStyle(); + + // + object = new XCBullishOrderBlockObject(); + result = object.Create( + chartID, + window, + zone, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ZoneFill(fill); + object.ZoneColor(crl); + object.ZoneWidth(width); + object.ZoneStyle(style); + + // + return result; + } + + /** + * Create Bearish Order Block Object ... + * + * @param zone: XCOrderBlock instance ... + * @param object: XCBearishOrderBlockObject pointer ... + * + * @return ( bool ) + */ + bool CreateBearishOrderBlock( + XCOrderBlock &zone, + XCBearishOrderBlockObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = + zone.IsValid() && + zone.IsBearish(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + bool fill = BearishOrderBlockFill(); + int width = BearishOrderBlockWidth(); + color crl = BearishOrderBlockColor(); + ENUM_LINE_STYLE style = BearishOrderBlockStyle(); + + // + object = new XCBearishOrderBlockObject(); + result = object.Create( + chartID, + window, + zone, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ZoneFill(fill); + object.ZoneColor(crl); + object.ZoneWidth(width); + object.ZoneStyle(style); + + // + return result; + } + + bool CreateOrderBlock( + XCOrderBlock &zone, + XCBaseObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + bool isBullish = zone.IsBullish(); + if (isBullish) + { + // + XCBullishOrderBlockObject *iObj; + result = CreateBullishOrderBlock( + zone, + iObj // + ); + if (result) + { + object = (XCBaseObject *)iObj; + } + } + else + { + // + XCBearishOrderBlockObject *iObj; + result = CreateBearishOrderBlock( + zone, + iObj // + ); + if (result) + { + object = (XCBaseObject *)iObj; + } + } + + // + return result; + } + + // + // Fair Value Gaps ... + + /** + * Create Bullish Fair Value Gap Object ... + * + * @param zone: XCFVG instance ... + * @param object: XCBullishOrderBlockObject pointer ... + * + * @return ( bool ) + */ + bool CreateBullishFairValueGap( + XCFVG &zone, + XCBullishFairValueGapObject *&object // + ) + { + // + bool result = false; + + // + result = zone.IsValid() && + zone.IsBullish(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + bool fill = BullishFVGFill(); + int width = BullishFVGWidth(); + color crl = BullishFVGColor(); + ENUM_LINE_STYLE style = BullishFVGStyle(); + + // + object = new XCBullishFairValueGapObject(); + result = object.Create( + chartID, + window, + zone, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ZoneFill(fill); + object.ZoneColor(crl); + object.ZoneWidth(width); + object.ZoneStyle(style); + + // + return result; + } + + /** + * Create Bearish Fair Value Gap Object ... + * + * @param zone: XCFVG instance ... + * @param object: XCBearishOrderBlockObject pointer ... + * + * @return ( bool ) + */ + bool CreateBearishFairValueGap( + XCFVG &zone, + XCBearishFairValueGapObject *&object // + ) + { + // + bool result = false; + + // + result = zone.IsValid() && + zone.IsBearish(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + bool fill = BearishFVGFill(); + int width = BearishFVGWidth(); + color crl = BearishFVGColor(); + ENUM_LINE_STYLE style = BearishFVGStyle(); + + // + object = new XCBearishFairValueGapObject(); + result = object.Create( + chartID, + window, + zone, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.ZoneFill(fill); + object.ZoneColor(crl); + object.ZoneWidth(width); + object.ZoneStyle(style); + + // + return result; + } + + bool CreateFairValueGap( + XCFVG &zone, + XCBaseObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + bool isBullish = zone.IsBullish(); + if (isBullish) + { + // + XCBullishFairValueGapObject *iObj; + result = CreateBullishFairValueGap( + zone, + iObj // + ); + if (result) + { + object = (XCBaseObject *)iObj; + } + } + else + { + // + XCBearishFairValueGapObject *iObj; + result = CreateBearishFairValueGap( + zone, + iObj // + ); + if (result) + { + object = (XCBaseObject *)iObj; + } + } + + // + return result; + } + + // + // Ticks Zone ... + + /** + * Add Tick Zone Draw Specifications ... + * + * @param specs: XTickZoneLevelSpecs instance ... + */ + void AddTickZoneLevelSpecs( + XTickZoneLevelSpecs &specs // + ) + { + // + if (!specs.IsValid()) + { + return; + } + + // + bool isExists = false; + int count = ArraySize(mTicksZoneSpecs); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XTickZoneLevelSpecs iSpec = mTicksZoneSpecs[i]; + + // + isExists = specs.percent == iSpec.percent; + if (isExists) + { + break; + } + } + } + if (isExists) + { + return; + } + + // + AddRef( + specs, + mTicksZoneSpecs // + ); + } + + /** + * Draw Specified Ticker Zone ... + * + * @param zone: XCTicksZone instance Specified Ticker Zone ... + * @param object: XCTicksZoneObject pointer ... + * + * @return ( bool ) + */ + bool CreateTicksZone( + XCTicksZone &zone, + XCTicksZoneObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + object = new XCTicksZoneObject(); + result = object.Create( + chartID, + window, + zone, + mTicksZoneSpecs, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Create Trend Line Object ... + * + * @param swings: XSwingPoint instance Collection ... + * + * @return ( bool ) + */ + bool CreateTrend( + XSwingPoint &swings[], + XCTrendObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = ArraySize(swings) >= 2 && + IsValidSize(ArraySize(swings)); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + object = new XCTrendObject(); + result = object.Create( + chartID, + window, + swings, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + color clrTrend = swings[0].type == X_SWING_LOW + ? SwingLowColor() + : SwingHighColor(); + object.TrendColor(clrTrend); + object.TrendRayRight(true); + + // + return result; + } + + /** + * Create Trend Line Object ... + * + * @param swings: XSwingPoint instance Collection ... + * @param useMinAsStart: Specified Min Value as Start ... + * + * @return ( bool ) + */ + bool CreateTrend( + XPoint &swings[], + XCTrendObject *&object, + bool useMinAsStart = true // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = ArraySize(swings) >= 2 && + IsValidSize(ArraySize(swings)); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + object = new XCTrendObject(); + result = object.Create( + chartID, + window, + swings, + useMinAsStart, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + color clrTrend = useMinAsStart + ? SwingLowColor() + : SwingHighColor(); + object.TrendColor(clrTrend); + object.TrendRayRight(true); + + // + return result; + } + + /** + * Create Consolidation Zone Object ... + * + * @param zone: XConsolidationZone instance Reference ... + * + * @return ( bool ) + */ + bool CreateConsolidationZone( + XConsolidationZone &zone, + XCConsolidationZoneObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = zone.IsValid(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + color czColor = IsBullish(zone.dir) + ? BarBullishColor() + : BarBearishColor(); + + // + object = new XCConsolidationZoneObject(); + result = object.Create( + chartID, + window, + zone, + prefix // + ); + + // + if (result) + { + object.ZoneColor(czColor); + } + + // + return result; + } + + /** + * Create Bar Object ... + * + * @param bar: XOHCL instance Reference ... + * @param object: XCOHCLObject pointer Reference .. + * @param to: Datetime ... + * + * @return ( bool ) + */ + bool CreateBar( + XOHCL &bar, + XCOHCLObject *&object, + datetime to = NULL // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + to = NormalizeTime(to); + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + int width = BarWidth(); + + // + color mBullishColor = BarBullishColor(); + color mBearishColor = BarBearishColor(); + + // + bool fillBody = BarFillBody(); + bool fillHighShadow = BarFillHighShadow(); + bool fillLowShadow = BarFillLowShadow(); + + // + ENUM_LINE_STYLE bodyStyle = BarBodyStyle(); + ENUM_LINE_STYLE highShadowStyle = BarHighShadowStyle(); + ENUM_LINE_STYLE lowShadowStyle = BarLowShadowStyle(); + + // + object = new XCOHCLObject(); + result = object.Create( + chartID, + window, + bar, + to, + prefix // + ); + if (result) + { + // + // Apply Styling ... + + // + object.BodyWidth(width); + object.LowShadowWidth(width); + object.HighShadowWidth(width); + + // + object.BodyStyle(bodyStyle); + object.LowShadowStyle(lowShadowStyle); + object.HighShadowStyle(highShadowStyle); + + // + bool isBullish = bar.IsBullish(); + if (isBullish) + { + // + object.BodyColor(mBullishColor); + object.LowShadowColor(mBullishColor); + object.HighShadowColor(mBullishColor); + } + else + { + // + object.BodyColor(mBearishColor); + object.LowShadowColor(mBearishColor); + object.HighShadowColor(mBearishColor); + } + + // + object.BodyFill(fillBody); + object.HighShadowFill(fillHighShadow); + object.LowShadowFill(fillLowShadow); + } + + // + return result; + } + + /** + * Create Bar Arrow Object ... + * + * @param bar: XOHCL instance Reference ... + * @param priceType: ENUM_X_PRICE member ... + * @param arrow: int, Arrow Code ... + * @param clr: color, Arro Color ... + * @param width: int, Arrow Width ... + * @param anchor: ENUM_ARROW_ANCHOR, anchor of Arrow ... + * @param name: string, name of Arrow ... + * + * @return ( bool ) + */ + bool CreateBarArrow( + XOHCL &bar, + XCBarArrowObject *&object, + ENUM_X_PRICE priceType, + int arrow = 159, + color clr = clrYellow, + int width = 3, + ENUM_ARROW_ANCHOR anchor = ANCHOR_BOTTOM, + string name = NULL // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + string barTag = bar.GetTag(name); + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + color mBullishColor = BarBullishColor(); + color mBearishColor = BarBearishColor(); + + // + prefix = + (IsValid(prefix) + ? prefix + "_" + : prefix) + + barTag; + + // + object = new XCBarArrowObject(); + result = object + .CreateByBar( + chartID, + prefix, + window, + arrow, + bar, + priceType // + ); + if (result) + { + // + object.ArrowColor(clr); + object.ArrowWidth(width); + } + + // + return result; + } + + /** + * Create Specific Box on Chart ... + * + * @param upper: Double ... + * @param lower: Double ... + * @param from: Datetime ... + * @param to: Datetime ... + * @param clr: Color ... + * @param width: Integer ... + * @param fill: Boolean ... + * @param style: ENUM_LINE_STYLE member ... + * + * @return ( bool ) + */ + bool CreateBox( + XCBoxObject *&object, + string name, + double upper, + double lower, + datetime from, + datetime to, + color clr = clrYellowGreen, + int width = 1, + bool fill = false, + ENUM_LINE_STYLE style = STYLE_SOLID // + ) + { + // + bool result = false; + + // + object = NULL; + + // + to = NormalizeTime(to); + + // + string dateStr = ToFormatString(from) + "|" + ToFormatString(to); + string dateMD5 = ToMD5(dateStr); + if (!IsValid(name)) + { + // + name = "XBox_" + + ToString(upper) + "_" + + ToString(lower) + "_" + + dateMD5; + } + + // + result = + upper > 0 && + lower > 0 && + to > from && + IsValid(to) && + IsValid(name) && + IsValid(from) && + upper > lower; + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + object = new XCBoxObject(); + result = object.Create( + chartID, + window, + name, + upper, + lower, + from, + to, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + object.BoxColor(clr); + object.BoxFill(fill); + object.BoxWidth(width); + object.BoxStyle(style); + + // + return result; + } + + /** + * Create Specific Box on Chart ... + * + * @param box: XBoxZone instance Reference ... + * @param clr: Color ... + * @param width: Integer ... + * @param fill: Boolean ... + * @param style: ENUM_LINE_STYLE member ... + * + * @return ( bool ) + */ + bool DrawBox( + XBoxZone &box, + XCBoxObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = box.IsValid(); + if (!result) + { + return result; + } + + // + int width = 1; + bool fill = false; + color clr = + box.IsBullish() + ? BullishFVGColor() + : BearishFVGColor(); + ENUM_LINE_STYLE style = STYLE_DASHDOTDOT; + string name = box.GetTag(); + + // + result = CreateBox( + object, + name, + box.upper, + box.lower, + box.from, + box.to, + clr, + width, + fill, + style // + ); + + // + return result; + } + + /** + * Create Specific Box on Chart ... + * + * @param box: XBoxZone instance Reference ... + * @param clr: Color ... + * @param width: Integer ... + * @param fill: Boolean ... + * @param style: ENUM_LINE_STYLE member ... + * + * @return ( bool ) + */ + bool CreateBox( + XBoxZone &box, + XCBoxObject *&object, + color clr = clrYellowGreen, + int width = 1, + bool fill = false, + ENUM_LINE_STYLE style = STYLE_SOLID // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = box.IsValid(); + if (!result) + { + return result; + } + + // + string name = box.GetTag(); + + // + result = CreateBox( + object, + name, + box.upper, + box.lower, + box.from, + box.to, + clr, + width, + fill, + style // + ); + + // + return result; + } + + /** + * Create Specific Risk Reward (RR) on Chart ... + * + * @param rr: XRR instance Reference ... + * + * @return ( bool ) + */ + bool CreateRR( + XRR &rr, + XCRRObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = rr.IsValid(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + object = new XCRRObject(); + result = object.Create( + chartID, + window, + rr, + prefix // + ); + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Draw Specified Signal ... + * + * @param signal: XSignal instance ... + */ + bool DrawSignal( + XSignal &signal, + XCSignalObject *&object // + ) + { + // + bool result = false; + + // + object = NULL; + + // + result = signal.IsValid(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + object = new XCSignalObject(); + result = object.Create( + chartID, + window, + signal, + prefix // + ); + if (!result) + { + return result; + } + + // + object.TPWidth(1); + object.TPColor(clrGreen); + object.TPWidth(STYLE_DOT); + + // + object.SLWidth(1); + object.SLColor(clrRed); + object.SLWidth(STYLE_DOT); + + // + object.TargetWidth(1); + object.TargetColor(clrLightBlue); + object.TargetWidth(STYLE_DOT); + + // + object.EntryWidth(1); + object.EntryColor(clrYellow); + object.EntryWidth(STYLE_DOT); + + // + return result; + } + + /** + * Draw Specified POI State ... + * + * @param state: XPOIState instance Reference ... + * @param drawnObjects: CArrayObj instance for Holding Drawn Objects ... + * @param drawTicksZone: Boolean ... + * @param ignoreSwingHighs: Boolean ... + * @param ignoreSwingLows: Boolean ... + * @param ignoreSupportZones: Boolean ... + * @param ignoreResistanceZones: Boolean ... + * @param ignoreSupplyZones: Boolean ... + * @param ignoreDemandZones: Boolean ... + * @param ignoreBullishOrderBlocks: Boolean ... + * @param ignoreBearishOrderBlocks: Boolean ... + * @param ignoreBullishFairValueGaps: Boolean ... + * @param ignoreBearishFairValueGaps: Boolean ... + * @param ignoreBullishRejectionBars: Boolean ... + * @param ignoreBearishRejectionBars: Boolean ... + * @param ignoreBullishMomentumBars: Boolean ... + * @param ignoreBearishMomentumBars: Boolean ... + */ + int DrawState( + XPOIState &state, + XCBaseObject *&drawnObjects[], + bool drawTicksZone = 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, + bool ignoreBullishConsolidationZones = false, + bool ignoreBearishConsolidationZones = false // + ) + { + // + int result = 0; + + // + if (!state.IsValid() || + !state.HasChild()) + { + return result; + } + + // + Clean(drawnObjects); + + // + // SwingHighs ... + if (!ignoreSwingHighs) + { + // + int count = state.CountSwingHighs(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSwing *iSwing = state.swingHighs[i]; + XCSwingHighObject *iObj; + + // + bool isCreated = CreateSwingHigh( + iSwing, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // SwingLows ... + if (!ignoreSwingLows) + { + // + int count = state.CountSwingLows(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSwing *iSwing = state.swingLows[i]; + XCSwingLowObject *iObj; + + // + bool isCreated = CreateSwingLow( + iSwing, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // SupportZones ... + if (!ignoreSupportZones) + { + // + int count = state.CountSupportZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSupportZone *iZone = state.supportZones[i]; + XCSupportZoneObject *iObj; + + // + bool isCreated = CreateSupportZone( + iZone, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // ResistanceZones ... + if (!ignoreResistanceZones) + { + // + int count = state.CountResistanceZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCResistanceZone *iZone = state.resistanceZones[i]; + XCResistanceZoneObject *iObj; + + // + bool isCreated = CreateResistanceZone( + iZone, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // SupplyZones ... + if (!ignoreSupplyZones) + { + // + int count = state.CountSupplyZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCSupplyZone *iZone = state.supplyZones[i]; + XCSupplyZoneObject *iObj; + + // + bool isCreated = CreateSupplyZone( + iZone, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // DemandZones ... + if (!ignoreDemandZones) + { + // + int count = state.CountDemandZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCDemandZone *iZone = state.demandZones[i]; + XCDemandZoneObject *iObj; + + // + bool isCreated = CreateDemandZone( + iZone, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // BullishOrderBlocks ... + if (!ignoreBullishOrderBlocks) + { + // + int count = state.CountBullishOrderBlocks(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iZone = state.bullishOrderBlocks[i]; + XCBullishOrderBlockObject *iObj; + + // + bool isCreated = CreateBullishOrderBlock( + iZone, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // BearishOrderBlocks ... + if (!ignoreBearishOrderBlocks) + { + // + int count = state.CountBearishOrderBlocks(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iZone = state.bearishOrderBlocks[i]; + XCBearishOrderBlockObject *iObj; + + // + bool isCreated = CreateBearishOrderBlock( + iZone, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // BullishFairValueGaps ... + if (!ignoreBullishFairValueGaps) + { + // + int count = state.CountBullishFairValueGaps(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCFVG *iZone = state.bullishFairValueGaps[i]; + XCBullishFairValueGapObject *iObj; + + // + bool isCreated = CreateBullishFairValueGap( + iZone, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // BearishFairValueGaps ... + if (!ignoreBearishFairValueGaps) + { + // + int count = state.CountBearishFairValueGaps(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCFVG *iZone = state.bearishFairValueGaps[i]; + XCBearishFairValueGapObject *iObj; + + // + bool isCreated = CreateBearishFairValueGap( + iZone, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // BullishRejectionBars ... + if (!ignoreBullishRejectionBars) + { + // + int count = state.CountBullishRejectionBars(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCRejectionBar *iBar = state.bullishRejectionBars[i]; + XCBullishRejectionBarObject *iObj; + + // + bool isCreated = CreateBullishRejectionBar( + iBar, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // BearishRejectionBars ... + if (!ignoreBearishRejectionBars) + { + // + int count = state.CountBearishRejectionBars(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCRejectionBar *iBar = state.bearishRejectionBars[i]; + XCBearishRejectionBarObject *iObj; + + // + bool isCreated = CreateBearishRejectionBar( + iBar, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // BullishMomentumBars ... + if (!ignoreBullishMomentumBars) + { + // + int count = state.CountBullishMomentumBars(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCMomentumBar *iBar = state.bullishMomentumBars[i]; + XCBullishMomentumBarObject *iObj; + + // + bool isCreated = CreateBullishMomentumBar( + iBar, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // BearishMomentumBars ... + if (!ignoreBearishMomentumBars) + { + // + int count = state.CountBearishMomentumBars(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCMomentumBar *iBar = state.bearishMomentumBars[i]; + XCBearishMomentumBarObject *iObj; + + // + bool isCreated = CreateBearishMomentumBar( + iBar, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // Bullish Consolidation Zones ... + if (!ignoreBullishConsolidationZones) + { + // + int count = state.CountBullishConsolidationZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCConsolidationZoneObject *iObj; + bool isCreated = CreateConsolidationZone( + state.bullishConsolidationZones[i], + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + // Bearish Consolidation Zones ... + if (!ignoreBearishConsolidationZones) + { + // + int count = state.CountBearishConsolidationZones(); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XCConsolidationZoneObject *iObj; + bool isCreated = CreateConsolidationZone( + state.bearishConsolidationZones[i], + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + drawnObjects // + ); + } + } + } + } + + // + result = ArraySize(drawnObjects); + + // + return result; + } + + // + int DrawOrderBlock( + XCOrderBlock *zone, + XCBaseObject *&objects[], + // + bool drawStartedBar = true, + bool drawActivatedBar = true, + bool drawBreakedBar = true, + bool drawWorkedBar = true, + // + int widthStartedBar = 1, + color clrStartedBar = clrYellow, + ENUM_LINE_STYLE styleStartedBar = STYLE_SOLID, + // + int widthActivatedBar = 1, + color clrActivatedBar = clrLime, + ENUM_LINE_STYLE styleActivatedBar = STYLE_SOLID, + // + int widthBreakedBar = 1, + color clrBreakedBar = clrRed, + ENUM_LINE_STYLE styleBreakedBar = STYLE_SOLID, + // + int widthWorkedBar = 1, + color clrWorkedBar = clrAqua, + ENUM_LINE_STYLE styleWorkedBar = STYLE_SOLID + // + ) + { + // + int result = 0; + + // + Clean(objects); + + // + if (zone == NULL || + !zone.IsValid()) + { + return result; + } + + // + ENUM_X_DIRECTION zoneDir = zone.GetDirection(); + + // + // Started Bar ... + XOHCL startedBar; + bool isBodyOut = false; + bool isStarted = zone + .IsStarted( + zoneDir, + startedBar, + isBodyOut // + ); + if (isStarted) + { + // + datetime iBarTo = startedBar.NextAt(); + + // + XCOHCLObject *iBarObj; + bool isCreated = CreateBar( + startedBar, + iBarObj, + iBarTo // + ); + if (isCreated) + { + // + iBarObj.BodyWidth(widthStartedBar); + iBarObj.LowShadowWidth(widthStartedBar); + iBarObj.HighShadowWidth(widthStartedBar); + + // + iBarObj.BodyStyle(styleStartedBar); + iBarObj.LowShadowStyle(styleStartedBar); + iBarObj.HighShadowStyle(styleStartedBar); + + // + iBarObj.BodyColor(clrStartedBar); + iBarObj.LowShadowColor(clrStartedBar); + iBarObj.HighShadowColor(clrStartedBar); + + // + Add( + (XCBaseObject *)iBarObj, + objects // + ); + } + } + + // + // Activated Bar ... + XOHCL activatedBar; + bool isBodyIn = false; + bool isActivated = zone + .IsActivated( + zoneDir, + activatedBar, + isBodyIn, + false // Force Body Out Started ... + ); + if (isActivated) + { + // + datetime iBarTo = activatedBar.NextAt(); + + // + XCOHCLObject *iBarObj; + bool isCreated = CreateBar( + activatedBar, + iBarObj, + iBarTo // + ); + if (isCreated) + { + // + iBarObj.BodyWidth(widthActivatedBar); + iBarObj.LowShadowWidth(widthActivatedBar); + iBarObj.HighShadowWidth(widthActivatedBar); + + // + iBarObj.BodyStyle(styleActivatedBar); + iBarObj.LowShadowStyle(styleActivatedBar); + iBarObj.HighShadowStyle(styleActivatedBar); + + // + iBarObj.BodyColor(clrActivatedBar); + iBarObj.LowShadowColor(clrActivatedBar); + iBarObj.HighShadowColor(clrActivatedBar); + + // + Add( + (XCBaseObject *)iBarObj, + objects // + ); + } + } + + // + // Breaked Bar ... + XOHCL breakedBar; + isBodyOut = false; + bool isBreaked = zone + .IsBreaked( + zoneDir, + breakedBar, + isBodyOut, + false, // Ignore Start ... + false // Force Body Out Started ... + ); + if (isBreaked) + { + // + datetime iBarTo = breakedBar.NextAt(); + + // + XCOHCLObject *iBarObj; + bool isCreated = CreateBar( + breakedBar, + iBarObj, + iBarTo // + ); + if (isCreated) + { + // + iBarObj.BodyWidth(widthBreakedBar); + iBarObj.LowShadowWidth(widthBreakedBar); + iBarObj.HighShadowWidth(widthBreakedBar); + + // + iBarObj.BodyStyle(styleBreakedBar); + iBarObj.LowShadowStyle(styleBreakedBar); + iBarObj.HighShadowStyle(styleBreakedBar); + + // + iBarObj.BodyColor(clrBreakedBar); + iBarObj.LowShadowColor(clrBreakedBar); + iBarObj.HighShadowColor(clrBreakedBar); + + // + Add( + (XCBaseObject *)iBarObj, + objects // + ); + } + } + + // + // Worked Bar ... + XOHCL workedBar; + isBodyOut = false; + bool isWorked = zone + .IsWorked( + zoneDir, + workedBar, + isBodyOut, + false, // Ignore Activation ... + false, // Force Body Out Started ... + false // Force Body In Activated ... + ); + if (isWorked) + { + // + datetime iBarTo = workedBar.NextAt(); + + // + XCOHCLObject *iBarObj; + bool isCreated = CreateBar( + workedBar, + iBarObj, + iBarTo // + ); + if (isCreated) + { + // + iBarObj.BodyWidth(widthWorkedBar); + iBarObj.LowShadowWidth(widthWorkedBar); + iBarObj.HighShadowWidth(widthWorkedBar); + + // + iBarObj.BodyStyle(styleWorkedBar); + iBarObj.LowShadowStyle(styleWorkedBar); + iBarObj.HighShadowStyle(styleWorkedBar); + + // + iBarObj.BodyColor(clrWorkedBar); + iBarObj.LowShadowColor(clrWorkedBar); + iBarObj.HighShadowColor(clrWorkedBar); + + // + Add( + (XCBaseObject *)iBarObj, + objects // + ); + } + } + + // + XCBaseObject *iObj; + bool isCreated = CreateOrderBlock( + zone, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + objects // + ); + } + + // + result = ArraySize(objects); + + // + return result; + } + + // + int DrawFairValueGap( + XCFVG *zone, + XCBaseObject *&objects[], + // + bool drawStartedBar = true, + bool drawActivatedBar = true, + bool drawBreakedBar = true, + bool drawWorkedBar = true, + // + int widthStartedBar = 1, + color clrStartedBar = clrYellow, + ENUM_LINE_STYLE styleStartedBar = STYLE_SOLID, + // + int widthActivatedBar = 1, + color clrActivatedBar = clrLime, + ENUM_LINE_STYLE styleActivatedBar = STYLE_SOLID, + // + int widthBreakedBar = 1, + color clrBreakedBar = clrRed, + ENUM_LINE_STYLE styleBreakedBar = STYLE_SOLID, + // + int widthWorkedBar = 1, + color clrWorkedBar = clrAqua, + ENUM_LINE_STYLE styleWorkedBar = STYLE_SOLID + // + ) + { + // + int result = 0; + + // + Clean(objects); + + // + if (zone == NULL || + !zone.IsValid()) + { + return result; + } + + // + ENUM_X_DIRECTION zoneDir = zone.GetDirection(); + + // + // Started Bar ... + XOHCL startedBar; + bool isBodyOut = false; + bool isStarted = zone + .IsStarted( + zoneDir, + startedBar, + isBodyOut // + ); + if (isStarted) + { + // + datetime iBarTo = startedBar.NextAt(); + + // + XCOHCLObject *iBarObj; + bool isCreated = CreateBar( + startedBar, + iBarObj, + iBarTo // + ); + if (isCreated) + { + // + iBarObj.BodyWidth(widthStartedBar); + iBarObj.LowShadowWidth(widthStartedBar); + iBarObj.HighShadowWidth(widthStartedBar); + + // + iBarObj.BodyStyle(styleStartedBar); + iBarObj.LowShadowStyle(styleStartedBar); + iBarObj.HighShadowStyle(styleStartedBar); + + // + iBarObj.BodyColor(clrStartedBar); + iBarObj.LowShadowColor(clrStartedBar); + iBarObj.HighShadowColor(clrStartedBar); + + // + Add( + (XCBaseObject *)iBarObj, + objects // + ); + } + } + + // + // Activated Bar ... + XOHCL activatedBar; + bool isBodyIn = false; + bool isActivated = zone + .IsActivated( + zoneDir, + activatedBar, + isBodyIn, + false // Force Body Out Started ... + ); + if (isActivated) + { + // + datetime iBarTo = activatedBar.NextAt(); + + // + XCOHCLObject *iBarObj; + bool isCreated = CreateBar( + activatedBar, + iBarObj, + iBarTo // + ); + if (isCreated) + { + // + iBarObj.BodyWidth(widthActivatedBar); + iBarObj.LowShadowWidth(widthActivatedBar); + iBarObj.HighShadowWidth(widthActivatedBar); + + // + iBarObj.BodyStyle(styleActivatedBar); + iBarObj.LowShadowStyle(styleActivatedBar); + iBarObj.HighShadowStyle(styleActivatedBar); + + // + iBarObj.BodyColor(clrActivatedBar); + iBarObj.LowShadowColor(clrActivatedBar); + iBarObj.HighShadowColor(clrActivatedBar); + + // + Add( + (XCBaseObject *)iBarObj, + objects // + ); + } + } + + // + // Breaked Bar ... + XOHCL breakedBar; + isBodyOut = false; + bool isBreaked = zone + .IsBreaked( + zoneDir, + breakedBar, + isBodyOut, + false, // Ignore Start ... + false // Force Body Out Started ... + ); + if (isBreaked) + { + // + datetime iBarTo = breakedBar.NextAt(); + + // + XCOHCLObject *iBarObj; + bool isCreated = CreateBar( + breakedBar, + iBarObj, + iBarTo // + ); + if (isCreated) + { + // + iBarObj.BodyWidth(widthBreakedBar); + iBarObj.LowShadowWidth(widthBreakedBar); + iBarObj.HighShadowWidth(widthBreakedBar); + + // + iBarObj.BodyStyle(styleBreakedBar); + iBarObj.LowShadowStyle(styleBreakedBar); + iBarObj.HighShadowStyle(styleBreakedBar); + + // + iBarObj.BodyColor(clrBreakedBar); + iBarObj.LowShadowColor(clrBreakedBar); + iBarObj.HighShadowColor(clrBreakedBar); + + // + Add( + (XCBaseObject *)iBarObj, + objects // + ); + } + } + + // + // Worked Bar ... + XOHCL workedBar; + isBodyOut = false; + bool isWorked = zone + .IsWorked( + zoneDir, + workedBar, + isBodyOut, + false, // Ignore Activation ... + false, // Force Body Out Started ... + false // Force Body In Activated ... + ); + if (isWorked) + { + // + datetime iBarTo = workedBar.NextAt(); + + // + XCOHCLObject *iBarObj; + bool isCreated = CreateBar( + workedBar, + iBarObj, + iBarTo // + ); + if (isCreated) + { + // + iBarObj.BodyWidth(widthWorkedBar); + iBarObj.LowShadowWidth(widthWorkedBar); + iBarObj.HighShadowWidth(widthWorkedBar); + + // + iBarObj.BodyStyle(styleWorkedBar); + iBarObj.LowShadowStyle(styleWorkedBar); + iBarObj.HighShadowStyle(styleWorkedBar); + + // + iBarObj.BodyColor(clrWorkedBar); + iBarObj.LowShadowColor(clrWorkedBar); + iBarObj.HighShadowColor(clrWorkedBar); + + // + Add( + (XCBaseObject *)iBarObj, + objects // + ); + } + } + + // + XCBaseObject *iObj; + bool isCreated = CreateFairValueGap( + zone, + iObj // + ); + if (isCreated) + { + // + Add( + (XCBaseObject *)iObj, + objects // + ); + } + + // + result = ArraySize(objects); + + // + return result; + } + + // + int DrawOBFVG( + // + XOBFVG &item, + XCBaseObject *&objects[], + // + bool drawOrderBlock = true, + bool drawFairValueGaps = true, + bool drawAllFVGs = true, + // + bool drawOBStartedBar = true, + bool drawOBActivatedBar = true, + bool drawOBBreakedBar = true, + bool drawOBWorkedBar = true, + // + bool drawFVGStartedBar = true, + bool drawFVGActivatedBar = true, + bool drawFVGBreakedBar = true, + bool drawFVGWorkedBar = true, + // + // Order Block Specs ... + // + int widthOBStartedBar = 1, + color clrOBStartedBar = clrYellow, + ENUM_LINE_STYLE styleOBStartedBar = STYLE_SOLID, + // + int widthOBActivatedBar = 1, + color clrOBActivatedBar = clrLime, + ENUM_LINE_STYLE styleOBActivatedBar = STYLE_SOLID, + // + int widthOBBreakedBar = 1, + color clrOBBreakedBar = clrRed, + ENUM_LINE_STYLE styleOBBreakedBar = STYLE_SOLID, + // + int widthOBWorkedBar = 1, + color clrOBWorkedBar = clrAqua, + ENUM_LINE_STYLE styleOBWorkedBar = STYLE_SOLID, + // + // Fair Value Gap Specs ... + // + int widthFVGStartedBar = 1, + color clrFVGStartedBar = clrYellow, + ENUM_LINE_STYLE styleFVGStartedBar = STYLE_SOLID, + // + int widthFVGActivatedBar = 1, + color clrFVGActivatedBar = clrLime, + ENUM_LINE_STYLE styleFVGActivatedBar = STYLE_SOLID, + // + int widthFVGBreakedBar = 1, + color clrFVGBreakedBar = clrRed, + ENUM_LINE_STYLE styleFVGBreakedBar = STYLE_SOLID, + // + int widthFVGWorkedBar = 1, + color clrFVGWorkedBar = clrAqua, + ENUM_LINE_STYLE styleFVGWorkedBar = STYLE_SOLID + // + ) + { + // + int result = 0; + + // + Clean(objects); + + // + bool isValid = item.IsValid(); + if (!isValid) + { + return result; + } + + // + int count = 0; + bool has = false; + bool isCreated = false; + XCBaseObject *tmpObjects[]; + + // + // Order Block ... + has = item.HasOB(); + if (has && + drawOrderBlock) + { + // + Clean(tmpObjects); + count = DrawOrderBlock( + item.ob, + tmpObjects, + drawOBStartedBar, + drawOBActivatedBar, + drawOBBreakedBar, + drawOBWorkedBar, + widthOBStartedBar, + clrOBStartedBar, + styleOBStartedBar, + widthOBActivatedBar, + clrOBActivatedBar, + styleOBActivatedBar, + widthOBBreakedBar, + clrOBBreakedBar, + styleOBBreakedBar, + widthOBWorkedBar, + clrOBWorkedBar, + styleOBWorkedBar // + ); + has = IsValidSize(count); + if (has) + { + // + Copy( + tmpObjects, + objects, + false // + ); + } + } + + // + // Fair Value Gap ... + if (!drawAllFVGs) + { + XCFVG *fvg; + has = item.GetMainFVG(fvg); + if (has && + drawFairValueGaps) + { + // + Clean(tmpObjects); + int fvgsCount = DrawFairValueGap( + fvg, + tmpObjects, + drawFVGStartedBar, + drawFVGActivatedBar, + drawFVGBreakedBar, + drawFVGWorkedBar, + widthFVGStartedBar, + clrFVGStartedBar, + styleFVGStartedBar, + widthFVGActivatedBar, + clrFVGActivatedBar, + styleFVGActivatedBar, + widthFVGBreakedBar, + clrFVGBreakedBar, + styleFVGBreakedBar, + widthFVGWorkedBar, + clrFVGWorkedBar, + styleFVGWorkedBar // + ); + has = IsValidSize(fvgsCount); + if (has) + { + // + Copy( + tmpObjects, + objects, + false // + ); + } + } + } + else + { + // + has = item.HasFVGs(); + if (has && + drawFairValueGaps) + { + // + count = item.CountFVGs(); + for (int i = 0; i < count; i++) + { + // + Clean(tmpObjects); + int fvgsCount = DrawFairValueGap( + item.fvgs[i], + tmpObjects, + drawFVGStartedBar, + drawFVGActivatedBar, + drawFVGBreakedBar, + drawFVGWorkedBar, + widthFVGStartedBar, + clrFVGStartedBar, + styleFVGStartedBar, + widthFVGActivatedBar, + clrFVGActivatedBar, + styleFVGActivatedBar, + widthFVGBreakedBar, + clrFVGBreakedBar, + styleFVGBreakedBar, + widthFVGWorkedBar, + clrFVGWorkedBar, + styleFVGWorkedBar // + ); + has = IsValidSize(fvgsCount); + if (has) + { + // + Copy( + tmpObjects, + objects, + false // + ); + } + } + } + } + + // + Clean(tmpObjects); + + // + result = ArraySize(objects); + + // + return result; + } + + // + protected: + // + + // + private: + // + + // + // Props ... + + // + string mPrefix; // Prefix of Created Objects ... + long mChartIdentification; // Chart Id ... + int mSubWindowIdentification; // Sub Window ... + + // + // XOHCL ... + int mBarWidth; // Bar Width ... + color mBarBullishColor; // Bar Bullish Color ... + color mBarBearishColor; // Bar Bearish Color ... + bool mBarFillHighShadow; // Fill Bar High Shadow ... + ENUM_LINE_STYLE mBarHighShadowStyle; // Bar High Shadow Style ... + bool mBarFillBody; // Fill Bar Body ... + ENUM_LINE_STYLE mBarBodyStyle; // Bar Body Style ... + bool mBarFillLowShadow; // Fill Bar Low Show ... + ENUM_LINE_STYLE mBarLowShadowStyle; // Bar Low Shadow Style ... + + // + // Swing Low ... + int mSwingLowWidth; // Swing Low Width ... + int mSwingLowArrow; // Swing Low Arrow Code ... + color mSwingLowColor; // Swing Low Color ... + + // + // Swing High ... + int mSwingHighWidth; // Swing High Width ... + int mSwingHighArrow; // Swing High Arrow Code ... + color mSwingHighColor; // Swing High Color ... + + // + // Bullish Momentum Bar ... + int mBullishMomentumBarWidth; // Bullish Momentum Bar Width ... + int mBullishMomentumBarArrow; // Bullish Momentum Bar Arrow Code ... + color mBullishMomentumBarColor; // Bullish Momentum Bar Color ... + + // + // Bearish Momentum Bar ... + int mBearishMomentumBarWidth; // Bearish Momentum Bar Width ... + int mBearishMomentumBarArrow; // Bearish Momentum Bar Arrow Code ... + color mBearishMomentumBarColor; // Bearish Momentum Bar Color ... + + // + // Bullish Rejection Bar ... + int mBullishRejectionBarWidth; // Bullish Rejection Bar High Width ... + int mBullishRejectionBarArrow; // Bullish Rejection Bar High Arrow Code ... + color mBullishRejectionBarColor; // Bullish Rejection Bar High Color ... + + // + // Bearish Rejection Bar ... + int mBearishRejectionBarWidth; // Bearish Rejection Bar Width ... + int mBearishRejectionBarArrow; // Bearish Rejection Bar Arrow Code ... + color mBearishRejectionBarColor; // Bearish Rejection Bar Color ... + + // + // Supply Zone ... + bool mSupplyZoneFill; // Fill Supply Zone ... + int mSupplyZoneWidth; // Supply Zone Width ... + color mSupplyZoneColor; // Supply Zone Color ... + ENUM_LINE_STYLE mSupplyZoneStyle; // Supply Zone Style ... + + // + // Demand Zone ... + bool mDemandZoneFill; // Fill Demand Zone ... + int mDemandZoneWidth; // Demand Zone Width ... + color mDemandZoneColor; // Demand Zone Color ... + ENUM_LINE_STYLE mDemandZoneStyle; // Demand Zone Style ... + + // + // Resistance Zone ... + bool mResistanceZoneFill; // Fill Resistance Zone ... + int mResistanceZoneWidth; // Resistance Zone Width ... + color mResistanceZoneColor; // Resistance Zone Color ... + ENUM_LINE_STYLE mResistanceZoneStyle; // Resistance Zone Style ... + + // + // Support Zone ... + bool mSupportZoneFill; // Fill Support Zone ... + int mSupportZoneWidth; // Support Zone Width ... + color mSupportZoneColor; // Support Zone Color ... + ENUM_LINE_STYLE mSupportZoneStyle; // Support Zone Style ... + + // + // Bullish Order Block ... + bool mBullishOrderBlockFill; // Fill Bullish Order Block ... + int mBullishOrderBlockWidth; // Bullish Order Block Width ... + color mBullishOrderBlockColor; // Bullish Order Block Color ... + ENUM_LINE_STYLE mBullishOrderBlockStyle; // Bullish Order Block Style ... + + // + // Bearish Order Block ... + bool mBearishOrderBlockFill; // Fill Bearish Order Block ... + int mBearishOrderBlockWidth; // Bearish Order Block Width ... + color mBearishOrderBlockColor; // Bearish Order Block Color ... + ENUM_LINE_STYLE mBearishOrderBlockStyle; // Bearish Order Block Style ... + + // + // Bullish FVG ... + bool mBullishFVGFill; // Fill Bullish FVG ... + int mBullishFVGWidth; // Bullish FVG Width ... + color mBullishFVGColor; // Bullish FVG Color ... + ENUM_LINE_STYLE mBullishFVGStyle; // Bullish FVG Style ... + + // + // Bearish FVG ... + bool mBearishFVGFill; // Fill Bearish FVG ... + int mBearishFVGWidth; // Bearish FVG Width ... + color mBearishFVGColor; // Bearish FVG Color ... + ENUM_LINE_STYLE mBearishFVGStyle; // Bearish FVG Style ... + + // + // Ticks Zone ... + XTickZoneLevelSpecs mTicksZoneSpecs[]; // Zone Draw Specifications ... + + // +}; \ No newline at end of file diff --git a/BKPS/14031218/Classes/x-saherelm.x-trade.class.mq5 b/BKPS/14031218/Classes/x-saherelm.x-trade.class.mq5 new file mode 100644 index 0000000..7bdd19f --- /dev/null +++ b/BKPS/14031218/Classes/x-saherelm.x-trade.class.mq5 @@ -0,0 +1,3934 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCTrade +// Description: provides all Trade requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.base.class.mq5" +#include "../Classes/x-saherelm.x-account.class.mq5" +#include "../Classes/x-saherelm.x-alert.class.mq5" +#include "../Libraries/x-saherelm.x-trade.lib.mq5" + +// +// Definitions ... + +// +// Overrides ... + +// +// XCTrade Base Class ... +class XCTradeBase : public CTrade +{ + public: + // + // Modify Specific Position, by Specific Comment ... + bool PositionModify( + const string symbol, // Symbol + const double sl, // Stop Loss + const double tp, // Take Profit + const string comment = "" // Comment For Modify + ) + { + // + // check stopped + if (IsStopped(__FUNCTION__)) + { + return (false); + } + + // + // check position existence + if (!SelectPosition(symbol)) + { + return (false); + } + + // + // clean + ClearStructures(); + + // + // setting request + m_request.action = TRADE_ACTION_SLTP; + m_request.symbol = symbol; + m_request.magic = m_magic; + m_request.sl = sl; + m_request.tp = tp; + m_request.position = PositionGetInteger(POSITION_TICKET); + + // + // Specified Comment ... + if (StringLen(comment) > 0) + { + m_request.comment = comment; + } + + // + // action and return the result + return (OrderSend(m_request, m_result)); + } + bool PositionModify( + const ulong ticket, // Position Ticket + const double sl, // Stop Loss + const double tp, // Take Profit + const string comment = "" // Comment For Modify + ) + { + // + // check stopped + if (IsStopped(__FUNCTION__)) + { + return (false); + } + + // + // check position existence + if (!PositionSelectByTicket(ticket)) + { + return (false); + } + + // + // clean + ClearStructures(); + + // + // setting request + m_request.action = TRADE_ACTION_SLTP; + m_request.position = ticket; + m_request.symbol = PositionGetString(POSITION_SYMBOL); + m_request.magic = m_magic; + m_request.sl = sl; + m_request.tp = tp; + + // + // Specified Comment ... + if (StringLen(comment) > 0) + { + m_request.comment = comment; + } + + // + // action and return the result + return (OrderSend(m_request, m_result)); + } + + // + // Close Specific Position, by Specific Comment ... + bool PositionClose( + const string symbol, // Symbol + const ulong deviation, // Deviation + const string comment = "" // Comment For Close + ) + { + // + bool partial_close = false; + int retry_count = 10; + uint retcode = TRADE_RETCODE_REJECT; + + // + // check stopped + if (IsStopped(__FUNCTION__)) + { + return (false); + } + + // + // clean + ClearStructures(); + + // + // check filling + if (!FillingCheck(symbol)) + { + return (false); + } + + // + do + { + // + // check + if (SelectPosition(symbol)) + { + // + if ((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) + { + // + // prepare request for close BUY position + m_request.type = ORDER_TYPE_SELL; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_BID); + } + else + { + // + // prepare request for close SELL position + m_request.type = ORDER_TYPE_BUY; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_ASK); + } + } + else + { + // + // position not found + m_result.retcode = retcode; + return (false); + } + + // + // setting request + m_request.action = TRADE_ACTION_DEAL; + m_request.symbol = symbol; + m_request.volume = PositionGetDouble(POSITION_VOLUME); + m_request.magic = m_magic; + m_request.deviation = (deviation == ULONG_MAX) ? m_deviation : deviation; + m_request.position = PositionGetInteger(POSITION_TICKET); + + // + // Specify Comment ... + m_request.comment = comment; + + // + // check volume + double max_volume = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX); + if (m_request.volume > max_volume) + { + // + m_request.volume = max_volume; + partial_close = true; + } + else + { + partial_close = false; + } + + // + // hedging? just send order + if (IsHedging()) + { + return (OrderSend(m_request, m_result)); + } + + // + // order send + if (!OrderSend(m_request, m_result)) + { + // + if (--retry_count != 0) + { + continue; + } + + // + if (retcode == TRADE_RETCODE_DONE_PARTIAL) + { + m_result.retcode = retcode; + } + + // + return (false); + } + + // + //--- WARNING. If position volume exceeds the maximum volume allowed for deal, + //--- and when the asynchronous trade mode is on, for safety reasons, position is closed not completely, + //--- but partially. It is decreased by the maximum volume allowed for deal. + if (m_async_mode) + { + break; + } + + // + retcode = TRADE_RETCODE_DONE_PARTIAL; + if (partial_close) + { + Sleep(1000); + } + } while (partial_close); + + // + // succeed + return (true); + } + bool PositionClose( + const ulong ticket, // Position Ticket + const ulong deviation, // Deviation + const string comment = "" // Comment For Close + ) + { + // + // check stopped + if (IsStopped(__FUNCTION__)) + { + return (false); + } + + // + // check position existence + if (!PositionSelectByTicket(ticket)) + { + return (false); + } + + // + string symbol = PositionGetString(POSITION_SYMBOL); + + // + // clean + ClearStructures(); + + // + // check filling + if (!FillingCheck(symbol)) + { + return (false); + } + + // + // check + if ((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) + { + // + // prepare request for close BUY position + m_request.type = ORDER_TYPE_SELL; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_BID); + } + else + { + // + // prepare request for close SELL position + m_request.type = ORDER_TYPE_BUY; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_ASK); + } + + // + // setting request + m_request.action = TRADE_ACTION_DEAL; + m_request.position = ticket; + m_request.symbol = symbol; + m_request.volume = PositionGetDouble(POSITION_VOLUME); + m_request.magic = m_magic; + m_request.deviation = (deviation == ULONG_MAX) ? m_deviation : deviation; + + // + // Specify Comment ... + m_request.comment = comment; + + // + // close position + return (OrderSend(m_request, m_result)); + } + + // + // Partial Close Specific Position, by Specific Comment ... + bool PositionClosePartial( + const string symbol, // Symbol + const double volume, // Partial Closing Volume + const ulong deviation, // Deviation + const string comment = "" // Comment For Close + ) + { + // + uint retcode = TRADE_RETCODE_REJECT; + + // + // check stopped + if (IsStopped(__FUNCTION__)) + { + return (false); + } + + // + // for hedging mode only + if (!IsHedging()) + { + return (false); + } + + // + // clean + ClearStructures(); + + // + // check filling + if (!FillingCheck(symbol)) + { + return (false); + } + + // + // check + if (SelectPosition(symbol)) + { + // + if ((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) + { + // + // prepare request for close BUY position + m_request.type = ORDER_TYPE_SELL; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_BID); + } + else + { + // + // prepare request for close SELL position + m_request.type = ORDER_TYPE_BUY; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_ASK); + } + } + else + { + // + // position not found + m_result.retcode = retcode; + return (false); + } + + // + // check volume + double position_volume = PositionGetDouble(POSITION_VOLUME); + if (position_volume > volume) + { + position_volume = volume; + } + + // + // setting request + m_request.action = TRADE_ACTION_DEAL; + m_request.symbol = symbol; + m_request.volume = position_volume; + m_request.magic = m_magic; + m_request.deviation = (deviation == ULONG_MAX) ? m_deviation : deviation; + m_request.position = PositionGetInteger(POSITION_TICKET); + + // + // Specifieng Comment ... + m_request.comment = comment; + + // + // hedging? just send order + return (OrderSend(m_request, m_result)); + } + bool PositionClosePartial( + const ulong ticket, // Position Ticket + const double volume, // Partial Closing Volume + const ulong deviation, // Deviation + const string comment = "" // Comment For Close + ) + { + // + // check stopped + if (IsStopped(__FUNCTION__)) + { + return (false); + } + + // + // for hedging mode only + if (!IsHedging()) + { + return (false); + } + + // + // check position existence + if (!PositionSelectByTicket(ticket)) + { + return (false); + } + + // + string symbol = PositionGetString(POSITION_SYMBOL); + + // + // clean + ClearStructures(); + + // + // check filling + if (!FillingCheck(symbol)) + { + return (false); + } + + // + // check + if ((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) + { + // + // prepare request for close BUY position + m_request.type = ORDER_TYPE_SELL; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_BID); + } + else + { + // + // prepare request for close SELL position + m_request.type = ORDER_TYPE_BUY; + m_request.price = SymbolInfoDouble(symbol, SYMBOL_ASK); + } + + // + // check volume + double position_volume = PositionGetDouble(POSITION_VOLUME); + if (position_volume > volume) + { + position_volume = volume; + } + + // + // setting request + m_request.action = TRADE_ACTION_DEAL; + m_request.position = ticket; + m_request.symbol = symbol; + m_request.volume = position_volume; + m_request.magic = m_magic; + m_request.deviation = (deviation == ULONG_MAX) ? m_deviation : deviation; + + // + // Specifieng Comment ... + m_request.comment = comment; + + // + // close position + return (OrderSend(m_request, m_result)); + } +}; + +// +// Implementation ... + +// +// a Class For Manage Trades and Handle Trading Actions ... +class XCTrade : public XCBase +{ + // + // Public ... + public: + // + // Props ... + XCAccount *mAccount; // Account Info Provider + + // + // Constructors ... + void XCTrade( + int slippage, // Specify Slippage + ulong magicNumber, // Specify Magic Number + double maxAllowedSpread = 0, // Max Allowed Spred for Opening Trades + int maxAllowedPositions = 0, // Max Allowed Positions + double maxAllowedDrawdownFactor = 0 // Max Allowed Drawdown Factor + ) + { + // + // Setting Props ... + mSlippage = slippage; + mMagicNumber = magicNumber; + + // + mMaxAllowedSpread = maxAllowedSpread; + mMaxAllowedPositions = maxAllowedPositions; + mMaxAllowedDrawdownFactor = maxAllowedDrawdownFactor; + + // + mAccount = new XCAccount(); + + // + // Instance Base Trader Class ... + mTrader = new XCTradeBase(); + + // + // Configuring Base Trader Class ... + mTrader.SetAsyncMode(false); + mTrader.SetDeviationInPoints(mSlippage); + mTrader.SetExpertMagicNumber(mMagicNumber); + + // + // Setting Log Level ... + mTrader.LogLevel(LOG_LEVEL_ERRORS); + + // + // OnTrade Context ... + + // + mDaysForRead = 1; + mScanStarted = false; + + // + // Reset On Trade Counter ... + ResetOnTradeContext(); + + // + // Init On Trade Context ... + InitOnTradeContext(); + } + + // + // Deconstructor ... + ~XCTrade() + { + // + // Remove Pointer ... + delete mTrader; + delete mAccount; + + // + ZeroMemory(mTrader); + ZeroMemory(mAccount); + + // + Clean(mOnModifyEventHandlers); + Clean(mStopLossEventHandlers); + Clean(mTakeProfitEventHandlers); + Clean(mOnForceCloseEventHandlers); + Clean(mDealsChangedEventHandlers); + Clean(mOrdersChangedEventHandlers); + Clean(mOnPartialCloseEventHandlers); + Clean(mPositionsChangedEventHandlers); + Clean(mTradeStateChangedEventHandlers); + } + + // + // Props ... + + // + // Retrieve Slippage ... + int GetSlippage() + { + return mSlippage; + } + + // + // Retrieve Magic Number ... + ulong GetMagicNumber() + { + return mMagicNumber; + } + + // + double GetMaxAllowedSpread() + { + return mMaxAllowedSpread; + } + + // + int GetMaxAllowedPositions() + { + return mMaxAllowedPositions; + } + + // + void SetMaxAllowedPositions(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mMaxAllowedPositions = value; + } + + // + double GetMaxAllowedDrawdownFactor() + { + return mMaxAllowedDrawdownFactor; + } + + // + // Add Event Listeners ... + + // + void AddOnModifyPositionEventHandler(TOnModify handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnModifyEventHandlers + // + ); + } + + // + void AddOnForceClosePositionEventHandler(TOnForceClose handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnForceCloseEventHandlers + // + ); + } + + // + void AddOnPartialClosePositionEventHandler(TOnPartialClose handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnPartialCloseEventHandlers + // + ); + } + + // + // Add New Deals Changed Event Handler ... + void AddOnTradeStateChangedEventHandler(TOnTradeStateChanged handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mTradeStateChangedEventHandlers + // + ); + } + + // + // Add New Deals Changed Event Handler ... + void AddOnDealsChangedEventHandler(TOnDealsChanged handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mDealsChangedEventHandlers + // + ); + } + + // + // Add New Orders Changed Event Handler ... + void AddOnOrdersChangedEventHandler(TOnOrdersChanged handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOrdersChangedEventHandlers + // + ); + } + + // + // Add New Positions Changed Event Handler ... + void AddOnPositionsChangedEventHandler(TOnPositionsChanged handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mPositionsChangedEventHandlers + // + ); + } + + // + // Add New Stop Loss Event Handler ... + void AddOnStopLossEventHandler(TOnStopLoss handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mStopLossEventHandlers + // + ); + } + + // + // Add New Stop Loss Event Handler ... + void AddOnTakeProfitEventHandler(TOnTakeProfit handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mTakeProfitEventHandlers + // + ); + } + + // + // Functions ... + + // + // Handlers ... + + // + // Process On Trade Requirement ... + // this Only Used when we Have to Proccess OnTrade Event in EA(s) ... + void HandleOnTradeEvent( + XOnTradeHandlerState &result // Hold's Result + ) + { + // + result.Clean(); + + // + if (mScanStarted) + { + // + ProcessOnTradeContext(result); + } + else + { + // + // Init Trade Context ... + InitOnTradeContext(); + + // + return; + } + + // + // Here we Can Check the Start ... + bool isValid = + // + result.IsValid() && + // + !result.hasNewDeal && + !result.hasNewOrder && + !result.hasNewPosition && + !result.hasNewHistoryOrder + // + ; + if (!isValid) + { + return; + } + + // + // State ... + + // + // Notfy Trade State Changed Event ... + NotifyTradeStateChangeEvent(result); + + // + // Deals ... + if (result.hasNewDeal) + { + // + // Notfy Deals Changed Event ... + NotifyDealsChangeEvent(result.newDeals); + + // + // Retrieve Last Deal ... + XDeal deals[]; + int dealsCount = GetDeals(deals); + if (dealsCount > 0) + { + // + XDeal lastDeal = deals[0]; + + // + if (lastDeal.reason == DEAL_REASON_TP) + { + NotifyTakeProfitEvent(lastDeal); + } + else if (lastDeal.reason == DEAL_REASON_SL) + { + NotifyStopLossEvent(lastDeal); + } + } + } + + // + // Orders ... + if (result.hasNewOrder || result.hasNewHistoryOrder) + { + // + // Notfy Orders Changed Event ... + NotifyOrdersChangeEvent(result.newOrders + result.newHistoryOrders); + } + + // + // Positions ... + if (result.hasNewPosition) + { + // + // Notfy Positions Changed Event ... + NotifyPositionsChangeEvent(result.newPositions); + } + } + + // + // This Must be Called Every time OnTrade Event Happening ... + // this Used for Implementing Custom Senarios ... + XOnTradeHandlerState HandleOnTrade() + { + // + // Handle OnTrade Event ... + XOnTradeHandlerState state; + HandleOnTradeEvent(state); + if ( + !state.hasNewDeal && + !state.hasNewOrder && + !state.hasNewPosition && + !state.hasNewHistoryOrder) + { + return state; + } + + // + // State ... + + // + // Notfy Trade State Changed Event ... + NotifyTradeStateChangeEvent(state); + + // + // DEALS ... + if (state.hasNewDeal) + { + // + // Notfy Deals Changed Event ... + NotifyDealsChangeEvent(state.newDeals); + + // + // Retrieve Last Deal ... + XDeal deals[]; + GetDeals(deals); + int dealsCount = ArraySize(deals); + if (dealsCount > 0) + { + // + XDeal lastDeal = deals[0]; + + // + if (lastDeal.reason == DEAL_REASON_TP) + { + NotifyTakeProfitEvent(lastDeal); + } + else if (lastDeal.reason == DEAL_REASON_SL) + { + NotifyStopLossEvent(lastDeal); + } + } + } + + // + // ORDERS ... + if (state.hasNewOrder || state.hasNewHistoryOrder) + { + // + // Notfy Orders Changed Event ... + NotifyOrdersChangeEvent(state.newOrders + state.newHistoryOrders); + } + + // + // POSITIONS ... + if (state.hasNewPosition) + { + // + // Notfy Positions Changed Event ... + NotifyPositionsChangeEvent(state.newPositions); + } + + // + return state; + } + + // + // Trade Actions ... + + // + // Main ... + + // + // Policies ... + + // + // Check Acocunt Balance is Allow new Trades or not ... + bool CheckEquityForTrade() + { + // + bool result = false; + + // + if (mMaxAllowedDrawdownFactor <= 0) + { + // + result = true; + return result; + } + + // + double equity = mAccount.GetEquity(); + double balance = mAccount.GetBalance(); + + // + double selectedBalance = MathMax(equity, balance) - MathMin(equity, balance); + + // + double maxAllowedBalanceDrawDown = GetMaxAllowedEquity(); + + // + result = equity > balance || + (equity <= balance && + selectedBalance <= maxAllowedBalanceDrawDown); + + // + return result; + } + + // + // Check Max Allowed Positions Policy for Trade ... + bool CheckPositionsForTrade() + { + // + bool result = false; + + // + if (mMaxAllowedPositions <= 0) + { + // + result = true; + return result; + } + + // + XPosition positions[]; + int positionsCount = GetPositions(positions); + if (positionsCount <= 0) + { + // + result = true; + return result; + } + + // + result = positionsCount < mMaxAllowedPositions; + + // + return result; + } + + // + // Check Spread is Ok for Executing Specific Signal ... + bool CheckSpreadForSignalExecution(XSignal &mSignal) + { + // + bool result = false; + + // + bool isSpreadCheckEnable = mMaxAllowedSpread > 0; + if (!isSpreadCheckEnable) + { + result = true; + } + else + { + // + // Retrieve Signal Spread ... + double spread = GetSpread(mSignal.symbol); + result = spread <= mMaxAllowedSpread; + } + + // + return result; + } + + // + // Check Account Policy ... + bool CheckAccountPolicy( + XSignal &mSignal, // For Executing Signal + ENUM_X_SIGNAL_EXECUTION_RESULT &state // State Holder + ) + { + // + bool result = false; + + // + // Check Positions For Trade ... + result = CheckPositionsForTrade(); + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_MAX_REACHED; + return result; + } + + // + // Check Equity For Trade ... + result = CheckEquityForTrade(); + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_NO_EQUITY; + return result; + } + + // + // Check Spread for Trade ... + result = CheckSpreadForSignalExecution(mSignal); + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_SPREAD; + return result; + } + + // + return result; + } + + // + // Execute a Signal ... + bool ExecuteSignal( + XSignal &mSignal, // Signal + ENUM_X_SIGNAL_EXECUTION_RESULT &state, // Result + ENUM_ORDER_TYPE_TIME lifetime = ORDER_TIME_GTC, // Order LifeTime + datetime expiration = NULL, // order expiration time + bool checkPolicies = true // Check Account Policies + ) + { + // + bool result = false; + state = X_SIGNAL_EXECUTION_UNKNOWN; + + // + double currentEntry = GetEntry( + mSignal.symbol, + mSignal.type + // + ); + bool isLong = IsLong(mSignal.type); + + // + if (!mSignal.IsValid()) + { + // + state = X_SIGNAL_EXECUTION_FAILED_INVALID_PARAMS; + return result; + } + + // + // Prepare Signal Comment ... + string mSComment = mSignal.GenerateComment(); + if (!Contains(mSComment, mSignal.comment)) + { + mSignal.comment += mSComment; + } + + // + // Handle Market Execution ... + if (mSignal.mode == X_ORDER_MODE_MARKET) + { + // + // Do Apply Policies here ... + bool hasPolicy = !checkPolicies + ? true + : CheckAccountPolicy(mSignal, state); + if (!hasPolicy) + { + result = false; + } + else + { + // + if (isLong) + { + // + result = Buy( + mSignal.symbol, + mSignal.period, + mSignal.volume, + mSignal.entry, + mSignal.sl, + mSignal.tp, + mSignal.comment + // + ); + } + else + { + // + result = Sell( + mSignal.symbol, + mSignal.period, + mSignal.volume, + mSignal.entry, + mSignal.sl, + mSignal.tp, + mSignal.comment + // + ); + } + } + } + // + // Handle Stop Execution ... + else if (mSignal.mode == X_ORDER_MODE_STOP) + { + + // + // Check Conditions ... + + // + // Check Price ... + result = isLong + ? mSignal.entry > currentEntry + : mSignal.entry < currentEntry; + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_PRICE_ERROR; + return result; + } + + // + // Execute Order ... + if (isLong) + { + // + result = BuyStop( + mSignal.symbol, + mSignal.period, + mSignal.volume, + mSignal.entry, + mSignal.sl, + mSignal.tp, + lifetime, + expiration, + mSignal.comment + // + ); + } + else + { + // + result = SellStop( + mSignal.symbol, + mSignal.period, + mSignal.volume, + mSignal.entry, + mSignal.sl, + mSignal.tp, + lifetime, + expiration, + mSignal.comment + // + ); + } + } + // + // Handle Limit Execution ... + else if (mSignal.mode == X_ORDER_MODE_LIMIT) + { + // + // Check Conditions ... + + // + // Check Price ... + result = isLong + ? mSignal.entry < currentEntry + : mSignal.entry > currentEntry; + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_PRICE_ERROR; + return result; + } + + // + // Execute Order ... + if (isLong) + { + // + result = BuyLimit( + mSignal.symbol, + mSignal.period, + mSignal.volume, + mSignal.entry, + mSignal.sl, + mSignal.tp, + lifetime, + expiration, + mSignal.comment + // + ); + } + else + { + // + result = SellLimit( + mSignal.symbol, + mSignal.period, + mSignal.volume, + mSignal.entry, + mSignal.sl, + mSignal.tp, + lifetime, + expiration, + mSignal.comment + // + ); + } + } + + // + // Handle Ticket ... + if (result) + { + // + state = X_SIGNAL_EXECUTION_SUCCEED; + + // + ulong ticket; + if (mSignal.mode == X_ORDER_MODE_MARKET) + { + ticket = GetLastOpenPositionTicket(); + } + else + { + ticket = GetLastPlacedOrderTicket(); + } + + // + mSignal.positionId = ticket; + + // + // Handle Store XPositionInfo ... + if (mSignal.mode == X_ORDER_MODE_MARKET) + { + // + // TODO: Implement this ... + } + + // + // Handle Executing Support Signals ... + int supportsCount = ArraySize(mSignal.supports); + if (supportsCount > 0) + { + // + int executed = 0; + for (int i = 0; i < supportsCount; i++) + { + // + XSignal iSupport = mSignal.supports[i]; + + // + int supIndex = i + 1; + string iComment = GenerateSupportTag(ticket); + iSupport.comment = iComment; + + // + bool isExecuted = ExecuteSignal( + iSupport, + state, + lifetime, + expiration + // + ); + if (isExecuted) + { + executed++; + } + } + + // + result = executed == supportsCount; + } + } + + // + return result; + } + + // + // Execute a Collection Of Signals ... + int ExecuteSignals( + XSignal &signals[], // Collection of Signal for Execution + ENUM_X_SIGNAL_EXECUTION_RESULT &states[], // Signal Execution Result + ENUM_ORDER_TYPE_TIME lifetime = ORDER_TIME_GTC, // Order LifeTime + datetime expiration = NULL, // order expiration time + bool checkPolicies = true // Check Account Policies + ) + { + // + int result = 0; + + // + Clean(states); + + // + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return result; + } + + // + ArrayResize(states, signalsCount); + ArrayInitialize(states, X_SIGNAL_EXECUTION_UNKNOWN); + for (int i = 0; i < signalsCount; i++) + { + // + bool isExecuted = ExecuteSignal( + signals[i], + states[i], + lifetime, + expiration, + checkPolicies + // + ); + + // + if (isExecuted) + { + result++; + } + } + + // + return result; + } + + // + int ExecuteSpecifiedSignals( + XSignal &signals[], // Collection of Signal for Execution + XSignal ¬Executeds[], // Not Executed Signal + ENUM_X_SIGNAL_EXECUTION_RESULT &states[], // Signal Execution Result + ENUM_ORDER_TYPE_TIME lifetime = ORDER_TIME_GTC, // Order LifeTime + datetime expiration = NULL, // order expiration time + bool checkPolicies = true // Check Account Policies + ) + { + // + int result = 0; + + // + Clean(states); + Clean(notExecuteds); + + // + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return result; + } + + // + ArrayResize(states, signalsCount); + ArrayInitialize(states, X_SIGNAL_EXECUTION_UNKNOWN); + for (int i = 0; i < signalsCount; i++) + { + // + bool isExecuted = ExecuteSignal( + signals[i], + states[i], + lifetime, + expiration + // + ); + + // + if (isExecuted) + { + result++; + } + else + { + // + AddRef( + signals[i], + notExecuteds // + ); + } + } + + // + return result; + } + + // + // Regular Trade Actions ... + + // + // Buy ... + + // + // Force Open a Buy/Long Position ... + bool Buy( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // position volume + double price, // execution price + double sl = 0, // stop loss price + double tp = 0, // take profit price + string comment = NULL // comment + ) + { + // + bool result = false; + + // + ENUM_TIMEFRAMES mPeriod = ExtractPeriod(comment); + if (!IsValid(comment) || + !IsValid(mPeriod)) + { + // + string mPeriodStr = GeneratePeriodTag(period); + + // + comment += mPeriodStr; + } + + // + result = mTrader.Buy( + volume, + symbol, + price, + sl, + tp, + comment + // + ); + + // + return result; + } + + // + // Send BUY LIMIT order ... + bool BuyLimit( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // order volume + double price, // order price + double sl = 0.0, // stop loss price + double tp = 0.0, // take profit price + ENUM_ORDER_TYPE_TIME typeTime = ORDER_TIME_GTC, // order lifetime + datetime expiration = 0, // order expiration time + string comment = NULL // comment + ) + { + // + bool result = false; + + // + ENUM_TIMEFRAMES mPeriod = ExtractPeriod(comment); + if (!IsValid(comment) || + !IsValid(mPeriod)) + { + // + string mPeriodStr = GeneratePeriodTag(period); + + // + comment += mPeriodStr; + } + + // + result = mTrader.BuyLimit( + volume, + price, + symbol, + sl, + tp, + typeTime, + expiration, + comment + // + ); + + // + return result; + } + + // + // Send BUY STOP order ... + bool BuyStop( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // order volume + double price, // order price + double sl = 0.0, // stop loss price + double tp = 0.0, // take profit price + ENUM_ORDER_TYPE_TIME typeTime = ORDER_TIME_GTC, // order lifetime + datetime expiration = 0, // order expiration time + string comment = NULL // comment + ) + { + // + bool result = false; + + // + ENUM_TIMEFRAMES mPeriod = ExtractPeriod(comment); + if (!IsValid(comment) || + !IsValid(mPeriod)) + { + // + string mPeriodStr = GeneratePeriodTag(period); + + // + comment += mPeriodStr; + } + + // + result = mTrader.BuyStop( + volume, + price, + symbol, + sl, + tp, + typeTime, + expiration, + comment + // + ); + + // + return result; + } + + // + // Sell ... + + // + // Force Open a Sell/Short Position ... + bool Sell( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // position volume + double price, // execution price + double sl = 0, // stop loss price + double tp = 0, // take profit price + string comment = NULL // comment + ) + { + // + bool result = false; + + // + ENUM_TIMEFRAMES mPeriod = ExtractPeriod(comment); + if (!IsValid(comment) || + !IsValid(mPeriod)) + { + // + string mPeriodStr = GeneratePeriodTag(period); + + // + comment += mPeriodStr; + } + + // + result = mTrader.Sell( + volume, + symbol, + price, + sl, + tp, + comment + // + ); + + // + return result; + } + + // + // Send SELL LIMIT order ... + bool SellLimit( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // order volume + double price, // order price + double sl = 0.0, // stop loss price + double tp = 0.0, // take profit price + ENUM_ORDER_TYPE_TIME typeTime = ORDER_TIME_GTC, // order lifetime + datetime expiration = 0, // order expiration time + string comment = NULL // comment + ) + { + // + bool result = false; + + // + ENUM_TIMEFRAMES mPeriod = ExtractPeriod(comment); + if (!IsValid(comment) || + !IsValid(mPeriod)) + { + // + string mPeriodStr = GeneratePeriodTag(period); + + // + comment += mPeriodStr; + } + + // + result = mTrader.SellLimit( + volume, + price, + symbol, + sl, + tp, + typeTime, + expiration, + comment + // + ); + + // + return result; + } + + // + // Send SELL STOP order ... + bool SellStop( + string symbol, // Specified Symbol + ENUM_TIMEFRAMES period, // Specified Trade's Period + double volume, // order volume + double price, // order price + double sl = 0.0, // stop loss price + double tp = 0.0, // take profit price + ENUM_ORDER_TYPE_TIME typeTime = ORDER_TIME_GTC, // order lifetime + datetime expiration = 0, // order expiration time + string comment = NULL // comment + ) + { + // + bool result = false; + + // + ENUM_TIMEFRAMES mPeriod = ExtractPeriod(comment); + if (!IsValid(comment) || + !IsValid(mPeriod)) + { + // + string mPeriodStr = GeneratePeriodTag(period); + + // + comment += mPeriodStr; + } + + // + result = mTrader.SellStop( + volume, + price, + symbol, + sl, + tp, + typeTime, + expiration, + comment + // + ); + + // + return result; + } + + // + // Check a Position is Exists Open or not ... + bool IsOpen( + ulong ticket // Specified Position Ticket + ) + { + // + bool result = false; + + // + result = mPositionInfo + .SelectByTicket(ticket); + + // + return result; + } + + // + // Modify Position ... + bool Modify( + const ulong ticket, // position ticket + double sl = 0, // stop loss price + double tp = 0, // take profit + string comment = NULL // comment + ) + { + // + bool result = false; + + // + // Validate Args ... + XPosition position; + result = + GetPosition( + ticket, + position // + ) && + (tp >= 0 || sl >= 0); + if (!result) + { + return result; + } + + // + // Use Position Comment when there isn't new One ... + if (!IsValid(comment) == 0) + { + // + // if there isn't provided Comment + // Use Position Comment for default ... + comment = "Modify " + GetPositionComment(ticket); + } + + // + result = mTrader.PositionModify( + ticket, + sl, + tp, + comment + // + ); + if (result) + { + // + NotifyModifyEvent( + ticket, + position.profit, + comment // + ); + } + + // + return result; + } + + // + // Close Position By Ticket ... + bool Close( + ulong ticket, // Position Ticket + string comment = NULL // Close Position By Specific Comment + ) + { + // + bool result = false; + + // + // Check Position Open ... + XPosition position; + result = GetPosition( + ticket, + position // + ); + if (!result) + { + return result; + } + + // + // Use Default Position Comment if it's Not Provided ... + if (!IsValid(comment)) + { + comment = "Close " + GetPositionComment(ticket); + } + + // + // Close Position By Specific Comment ... + result = mTrader.PositionClose( + ticket, + mSlippage, + comment + // + ); + if (result) + { + // + NotifyForceCloseEvent( + ticket, + position, + comment // + ); + } + + // + return result; + } + + // + // Close Specified Positions ... + int Close( + string comment = NULL, // Close Position By Specific Comment + string symbol = NULL, // Trading Symbol + string provider = NULL, // Signal Provider + ENUM_TIMEFRAMES period = NULL, // Trading Period + ENUM_X_POSITION_TYPES type = NULL, // Long (Buy) or Short (Sell) + bool filterByMagic = true // Get Only Self Open Positions + ) + { + // + int result = 0; + + // + XPosition positions[]; + int positionsCount = GetPositions( + positions, + symbol, + provider, + period, + type, + filterByMagic); + if (positionsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + bool isClosed = Close( + iPosition.ticket, + comment + // + ); + if (isClosed) + { + result++; + } + } + + // + return result; + } + + // + // Close a Collection of Positions ... + int Close( + XPosition &positions[], // Collection of Positions + string comment // Close Comment + ) + { + // + int result = 0; + + // + int positionsCount = ArraySize(positions); + if (positionsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + bool isClosed = Close( + iPosition.ticket, + comment + // + ); + if (isClosed) + { + result++; + } + } + + // + return result; + } + + // + // Close Partial By Ticket ... + bool ClosePartial( + ulong ticket, // Position Ticket + double volume, // Volume Size for Partial Closing + string comment = NULL // Close Position By Specific Comment + ) + { + // + bool result = false; + + // + XPosition position; + result = GetPosition( + ticket, + position // + ); + if (!result) + { + return result; + } + + // + // Use Default Partial Close Comment ... + if (!IsValid(comment)) + { + // + comment += "PClose " + GetPositionComment(ticket); + } + + // + result = mTrader.PositionClosePartial( + ticket, + volume, + mSlippage, + comment + // + ); + if (result) + { + // + NotifyPartialCloseEvent( + ticket, + position.profit, + comment // + ); + } + + // + return result; + } + + // + // Cancel Specific Order ... + bool CancelOrder(ulong ticket) + { + return mTrader + .OrderDelete(ticket); + } + + // + // Cancel Specific Orders ... + int CancelOrders( + XOrder &orders[] // Specified Orders ... + ) + { + // + int result = 0; + + // + int ordersCount = ArraySize(orders); + if (ordersCount <= 0) + { + return result; + } + + // + for (int i = 0; i < ordersCount; i++) + { + // + XOrder iOrder = orders[i]; + + // + bool isDeleted = mTrader + .OrderDelete(iOrder.ticket); + if (isDeleted && !result) + { + result++; + } + } + + // + return result; + } + + // + // Extractors ... + + // + // Positions ... + + // + // Calculate Positions Profit ... + double Profit( + string symbol = NULL, // Trading Symbol + string provider = NULL, // Signal Provider + ENUM_TIMEFRAMES period = NULL, // Trading Period + ENUM_X_POSITION_TYPES type = NULL, // Long (Buy) or Short (Sell) + bool filterByMagic = true // Get Only Self Open Positions + ) + { + // + double result = 0; + + // + // Retrieve Positions ... + XPosition positions[]; + int positionsCount = GetPositions( + positions, + symbol, + provider, + period, + type, + filterByMagic + // + ); + if (positionsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + result += positions[i].profit; + } + + // + return result; + } + + // + // Retrieve Specific Position by Index ... + bool GetPosition( + int index, // Specified Index + XPosition &result // Hold's Result + ) + { + // + bool isInited = result + .ByIndex(index); + + // + return isInited; + } + + // + // Retrieve Specific Position by Ticket ... + bool GetPosition( + ulong ticket, // Specified Ticket + XPosition &result // Hold's Result + ) + { + // + bool isInited = result + .ByTicket(ticket); + + // + return isInited; + } + + // + double GetPositionCommission( + ulong ticket // Specified Ticket + ) + { + // + double result = 0; + + // + XPosition position; + bool hasPosition = GetPosition( + ticket, + position // + ); + if (!hasPosition) + { + return result; + } + + // + XDeal deals[]; + int dealsCount = GetDeals( + deals, + position.symbol, + position.provider, + position.period, + NULL, + DEAL_ENTRY_IN // + ); + if (IsValidSize(dealsCount)) + { + // + for (int i = 0; i < dealsCount; i++) + { + // + XDeal iDeal = deals[i]; + if (iDeal.positionId == ticket) + { + // + result = iDeal.commission; + break; + } + } + } + + // + return result; + } + + // + // Retrieve Positions ... + int GetPositions( + XPosition &result[], // Hold's Result + string symbol = NULL, // Trading Symbol + string provider = NULL, // Signal Provider + ENUM_TIMEFRAMES period = NULL, // Trading Period + ENUM_X_POSITION_TYPES type = NULL, // Long (Buy) or Short (Sell) + bool filterByMagic = true, // Get Only Self Open Positions + bool forceClean = true // Clean Result Array + ) + { + // + int mResult = 0; + + // + int before = ArraySize(result); + + // + if (forceClean) + { + Clean(result); + } + + // + // Count Positions ... + int itemsCount = PositionsTotal(); + if (itemsCount <= 0) + { + return mResult; + } + + // + // Loop Through all Positions ... + for (int i = itemsCount - 1; i >= 0; i--) + { + // + XPosition iItem; + bool isLoaded = iItem.ByIndex(i); + if (!isLoaded) + { + continue; + } + + // + // Now we have to Check Given Filters ... + bool isFiltersPassed = + iItem.IsFiltersPassed( + symbol, + provider, + period, + type, + mMagicNumber, + filterByMagic + // + ); + if (!isFiltersPassed) + { + continue; + } + + // + // Add Filtered Item into Result ... + AddRef( + iItem, + result + // + ); + } + + // + int after = ArraySize(result); + + // + mResult = after - before; + + // + return mResult; + } + + // + void GetPositions( + XPosition &longs[], // Hold's Longs Result + XPosition &shorts[], // Hold's Shorts Result + string symbol = NULL, // Trading Symbol + string provider = NULL, // Signal Provider + ENUM_TIMEFRAMES period = NULL, // Trading Period + bool filterByMagic = true, // Get Only Self Open Positions + bool forceClean = true // Clean Result Array + ) + { + // + // Retrieve Long Positions ... + GetPositions( + longs, + symbol, + provider, + period, + X_POSITION_TYPE_LONG, + filterByMagic, + forceClean // + ); + + // + // Retrieve Short Positions ... + GetPositions( + shorts, + symbol, + provider, + period, + X_POSITION_TYPE_SHORT, + filterByMagic, + forceClean // + ); + } + + // + // Select In Profit Positions ... + int GetInProfitPositions( + XPosition &result[], // Hold's Result + string symbol = NULL, // Trading Symbol + string provider = NULL, // Signal Provider + ENUM_TIMEFRAMES period = NULL, // Trading Period + ENUM_X_POSITION_TYPES type = NULL, // Long (Buy) or Short (Sell) + ENUM_X_POSITION_SELECT_METHODS method = NULL, // Selection Method + bool filterByMagic = true, // Get Only Self Open Positions + bool forceClean = true // Clean Result Array + ) + { + // + int mResult = 0; + + // + int before = ArraySize(result); + + // + if (forceClean) + { + Clean(result); + } + + // + XPosition positions[]; + int positionsCount = GetPositions( + positions, + symbol, + provider, + period, + type, + filterByMagic, + forceClean); + if (positionsCount <= 0) + { + return mResult; + } + + // + XPosition min; + XPosition max; + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + if (iPosition.profit <= 0) + { + continue; + } + + // + // Calculate Min and Max ... + + // + // Min ... + if (!min.IsValid() || min.profit <= 0 || min.profit > iPosition.profit) + { + min = iPosition; + } + + // + // Max ... + if (!max.IsValid() || max.profit <= 0 || max.profit < iPosition.profit) + { + max = iPosition; + } + + // + bool isSelectionMethodFilterPassed = + // + (method == NULL || + method == X_POSITION_SELECT_ALL) + ? true + : false; + // + ; + if (!isSelectionMethodFilterPassed) + { + continue; + } + + // + AddRef( + iPosition, + result + // + ); + } + + // + if (min.IsValid() && + (method == X_POSITION_SELECT_MIN || + method == X_POSITION_SELECT_BOTH)) + { + // + AddRef( + min, + result + // + ); + } + + // + if (max.IsValid() && + (method == X_POSITION_SELECT_MAX || + method == X_POSITION_SELECT_BOTH)) + { + // + AddRef( + max, + result + // + ); + } + + // + int after = ArraySize(result); + + // + mResult = after - before; + + // + return mResult; + } + + // + // Select In Drawdown Positions ... + int GetInDrawdownPositions( + XPosition &result[], // Hold's Result + string symbol = NULL, // Trading Symbol + string provider = NULL, // Signal Provider + ENUM_TIMEFRAMES period = NULL, // Trading Period + ENUM_X_POSITION_TYPES type = NULL, // Long (Buy) or Short (Sell) + ENUM_X_POSITION_SELECT_METHODS method = NULL, // Selection Method + bool filterByMagic = true, // Get Only Self Open Positions + bool forceClean = true // Clean Result Array + ) + { + // + int mResult = 0; + + // + int before = ArraySize(result); + + // + if (forceClean) + { + Clean(result); + } + + // + XPosition positions[]; + int positionsCount = GetPositions( + positions, + symbol, + provider, + period, + type, + filterByMagic, + forceClean); + if (positionsCount <= 0) + { + return mResult; + } + + // + XPosition min; + XPosition max; + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + if (iPosition.profit >= 0) + { + continue; + } + + // + // Calculate Min and Max ... + + // + // Min ... + if (!min.IsValid() || min.profit <= 0 || min.profit > iPosition.profit) + { + min = iPosition; + } + + // + // Max ... + if (!max.IsValid() || max.profit <= 0 || max.profit < iPosition.profit) + { + max = iPosition; + } + + // + bool isSelectionMethodFilterPassed = + // + (method == NULL || + method == X_POSITION_SELECT_ALL) + ? true + : false; + // + ; + if (!isSelectionMethodFilterPassed) + { + continue; + } + + // + AddRef( + iPosition, + result + // + ); + } + + // + if (min.IsValid() && + (method == X_POSITION_SELECT_MIN || + method == X_POSITION_SELECT_BOTH)) + { + // + AddRef( + min, + result + // + ); + } + + // + if (max.IsValid() && + (method == X_POSITION_SELECT_MAX || + method == X_POSITION_SELECT_BOTH)) + { + // + AddRef( + max, + result + // + ); + } + + // + int after = ArraySize(result); + + // + mResult = after - before; + + // + return mResult; + } + + // + // Orders ... + + // + // Retrieve Specific Order by Index ... + bool GetOrder( + int index, // Specified Index + XOrder &result // Hold's Result + ) + { + // + return result + .ByIndex(index); + } + + // + // Retrieve Specific Positions Orders ... + int GetOrders( + ulong ticket, // Positions Ticket + XOrder &result[], // Hold's Result + bool forceClean = true // Clean Result Array + ) + { + // + int mResult = 0; + + // + // Select History by Specified Ticket ... + bool isHistorySelected = HistorySelectByPosition(ticket); + if (!isHistorySelected) + { + return mResult; + } + + // + int ordersCount = HistoryOrdersTotal(); + if (ordersCount <= 0) + { + return mResult; + } + + // + int before = ArraySize(result); + + // + if (forceClean) + { + Clean(result); + } + + // + for (int i = 0; i < ordersCount; i++) + { + // + XOrder iOrder; + bool isLoaded = iOrder.HistoryByIndex(i); + if (!isLoaded) + { + continue; + } + + // + bool isTicketFilterPassed = + // + iOrder.ticket = ticket + // + ; + if (!isTicketFilterPassed) + { + continue; + } + + // + AddRef( + iOrder, + result + // + ); + } + + // + int after = ArraySize(result); + + // + mResult = after - before; + + // + return mResult; + } + + // + // Retrieve All Orders ... + int GetOrders( + XOrder &result[], // Hold's Result + string symbol = NULL, // Trading Symbol + string provider = NULL, // Signal Provider + ENUM_TIMEFRAMES period = NULL, // Trading Period + ENUM_X_POSITION_TYPES type = NULL, // Long (Buy) or Short (Sell) + ENUM_ORDER_STATE state = NULL, // Order State + bool filterByMagic = true, // Get Only Self Open Positions + bool forceClean = true // Clean Result Array + ) + { + // + int mResult = 0; + + // + int before = ArraySize(result); + + // + if (forceClean) + { + Clean(result); + } + + // + // Count Positions ... + int itemsCount = OrdersTotal(); + if (itemsCount <= 0) + { + return mResult; + } + + // + // Loop Through all Positions ... + for (int i = itemsCount - 1; i >= 0; i--) + { + // + XOrder iItem; + bool isLoaded = iItem.ByIndex(i); + if (!isLoaded) + { + continue; + } + + // + // Now we have to Check Given Filters ... + bool isFiltersPassed = + iItem.IsFiltersPassed( + symbol, + provider, + period, + type, + state, + mMagicNumber, + filterByMagic + // + ); + if (!isFiltersPassed) + { + continue; + } + + // + // Add Filtered Item into Result ... + AddRef( + iItem, + result + // + ); + } + + // + int after = ArraySize(result); + + // + mResult = after - before; + + // + return mResult; + } + + // + // Retrieve Historical Orders ... + int GetOrders( + XOrder &result[], // Hold's Result + string symbol = NULL, // Trading Symbol + string provider = NULL, // Signal Provider + ENUM_TIMEFRAMES period = NULL, // Trading Period + ENUM_X_POSITION_TYPES type = NULL, // Long (Buy) or Short (Sell) + ENUM_ORDER_STATE state = NULL, // Order State + datetime startDate = NULL, // Specify Start Date + datetime endDate = NULL, // Specify End Date + bool filterByMagic = true, // Get Only Self Open Positions + bool forceClean = true // Clean Result Array + ) + { + // + int mResult = 0; + + // + endDate = NormalizeTime(endDate); + + // + if (!IsValid(startDate)) + { + startDate = endDate - PeriodSeconds(PERIOD_D1); + } + + // + bool isHistorySelected = HistorySelect( + startDate, + endDate); + if (!isHistorySelected) + { + return mResult; + } + + // + int before = ArraySize(result); + + // + if (forceClean) + { + Clean(result); + } + + // + // Count Positions ... + int itemsCount = OrdersTotal(); + if (itemsCount <= 0) + { + return mResult; + } + + // + // Loop Through all Positions ... + for (int i = itemsCount - 1; i >= 0; i--) + { + // + XOrder iItem; + bool isLoaded = iItem.HistoryByIndex(i); + if (!isLoaded) + { + continue; + } + + // + // Now we have to Check Given Filters ... + bool isFiltersPassed = + iItem.IsFiltersPassed( + symbol, + provider, + period, + type, + state, + mMagicNumber, + filterByMagic + // + ); + if (!isFiltersPassed) + { + continue; + } + + // + // Add Filtered Item into Result ... + AddRef( + iItem, + result + // + ); + } + + // + int after = ArraySize(result); + + // + mResult = after - before; + + // + return mResult; + } + + // + // Deals ... + + // + // Retrieve Specific Deal by Index ... + bool GetDeal( + int index, // Specified Index + XDeal &result // Hold's Result + ) + { + // + return result + .ByIndex(index); + } + + // + bool GetLastDeal( + XDeal &result // Hold's Result + ) + { + // + bool mResult = false; + + // + mResult = HistorySelect(0, TimeCurrent()); + if (!mResult) + { + return mResult; + } + + // + int lastDealIndex = HistoryDealsTotal() - 1; + + // + mResult = GetDeal( + lastDealIndex, + result // + ); + + // + return mResult; + } + + // + // Retrieve Specified Deal's History ... + int GetDealsHistory( + XDeal &deal, // Specified Deal + XOrder &history[], // Deals History + bool forceClean = true // Clean Result Array + ) + { + // + int result = 0; + + // + if (!deal.IsValid()) + { + return result; + } + + // + result = GetOrders( + deal.positionId, + history, + forceClean); + + // + return result; + } + + // + // Retrieve All Deals ... + int GetDeals( + XDeal &result[], // Hold's Result + string symbol = NULL, // Trading Symbol + string provider = NULL, // Signal Provider + ENUM_TIMEFRAMES period = NULL, // Trading Period + ENUM_DEAL_TYPE type = NULL, // Deal Type + ENUM_DEAL_ENTRY entry = NULL, // Deal Entry + ENUM_DEAL_REASON reason = NULL, // Deal Reason + datetime startDate = NULL, // Specify Start Date + datetime endDate = NULL, // Specify End Date + bool filterByMagic = true, // Get Only Self Open Positions + bool forceClean = true // Clean Result Array + ) + { + // + int mResult = 0; + + // + endDate = NormalizeTime(endDate); + + // + if (!IsValid(startDate)) + { + startDate = endDate - PeriodSeconds(PERIOD_D1); + } + + // + bool isHistorySelected = HistorySelect( + startDate, + endDate); + if (!isHistorySelected) + { + return mResult; + } + + // + int before = ArraySize(result); + + // + if (forceClean) + { + Clean(result); + } + + // + // Count Positions ... + int itemsCount = HistoryDealsTotal(); + if (itemsCount <= 0) + { + return mResult; + } + + // + // Loop Through all Positions ... + for (int i = itemsCount - 1; i >= 0; i--) + { + // + XDeal iItem; + bool isLoaded = iItem.ByIndex(i); + if (!isLoaded) + { + continue; + } + + // + // Now we have to Check Given Filters ... + bool isFiltersPassed = + iItem.IsFiltersPassed( + symbol, + provider, + period, + type, + entry, + reason, + mMagicNumber, + filterByMagic + // + ); + if (!isFiltersPassed) + { + continue; + } + + // + // Add Filtered Item into Result ... + AddRef( + iItem, + result + // + ); + } + + // + int after = ArraySize(result); + + // + mResult = after - before; + + // + return mResult; + } + + // + // Support Functions ... + + // + // Check a Position has Support or not ... + bool HasSupport( + ulong ticket, + bool forceOpen = true // + ) + { + // + bool result = false; + + // + result = ticket > 0; + if (!result) + { + return result; + } + + // + if (forceOpen) + { + // + result = IsOpen(ticket); + if (!result) + { + return result; + } + } + + // + XPosition positions[]; + int positionsCount = GetPositions(positions); + result = IsValidSize(positionsCount); + if (!result) + { + return result; + } + + // + // Extract Support Positions ... + XPosition supports[]; + int supportsCount = ExtractSupports( + positions, + supports // + ); + result = IsValidSize(supportsCount); + if (!result) + { + return result; + } + + // + // Loop Through Supports ... + for (int i = 0; i < supportsCount; i++) + { + // + XPosition iSupport = supports[i]; + + // + ulong supportedTicket = ExtractSupportedTicket(iSupport.comment); + ulong eqmSupportedTicket = ExtractEQMSupportedTicket(iSupport.comment); + + // + result = + // + (supportedTicket > 0 && ticket == supportedTicket) + // + || + // + (eqmSupportedTicket > 0 && ticket == eqmSupportedTicket) + // + ; + if (result) + { + break; + } + } + + // + return result; + } + + // + // Retrieve Specific Position's Supports ... + int GetSupports( + ulong ticket, + XPosition &dest[], // Result ... + bool forceOpen = true // + ) + { + // + int result = 0; + + // + Clean(dest); + + // + bool hasSupport = HasSupport( + ticket, + forceOpen // + ); + if (!hasSupport) + { + return result; + } + + // + XPosition positions[]; + int positionsCount = GetPositions(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + // Extract Support Positions ... + XPosition supports[]; + int supportsCount = ExtractSupports( + positions, + supports // + ); + if (!IsValidSize(supportsCount)) + { + return result; + } + + // + // Loop Through Supports ... + for (int i = 0; i < supportsCount; i++) + { + // + XPosition iSupport = supports[i]; + + // + ulong supportedTicket = ExtractSupportedTicket(iSupport.comment); + ulong eqmSupportedTicket = ExtractEQMSupportedTicket(iSupport.comment); + + // + bool isOwn = + // + (supportedTicket > 0 && ticket == supportedTicket) + // + || + // + (eqmSupportedTicket > 0 && ticket == eqmSupportedTicket) + // + ; + if (isOwn) + { + // + AddRef( + iSupport, + dest // + ); + } + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // Retrieve Specific Position's Supports ... + int GetSupports( + ulong ticket, + XOrder &dest[], // Result ... + bool forceOpen = true // + ) + { + // + int result = 0; + + // + Clean(dest); + + // + bool hasSupport = HasSupport( + ticket, + forceOpen // + ); + if (!hasSupport) + { + return result; + } + + // + XOrder orders[]; + int ordersCount = GetOrders( + orders, + NULL, // All Symbols ... + NULL, // All Providers ... + NULL, // All Periods ... + X_POSITION_TYPE_ALL, // All Types ... + ORDER_STATE_PLACED, // Untriggere Orders ... + true // + ); + if (!IsValidSize(ordersCount)) + { + return result; + } + + // + // Extract Support Positions ... + XOrder supports[]; + int supportsCount = ExtractSupports( + orders, + supports // + ); + if (!IsValidSize(supportsCount)) + { + return result; + } + + // + // Loop Through Supports ... + for (int i = 0; i < supportsCount; i++) + { + // + XOrder iSupport = supports[i]; + + // + ulong supportedTicket = ExtractSupportedTicket(iSupport.comment); + ulong eqmSupportedTicket = ExtractEQMSupportedTicket(iSupport.comment); + + // + bool isOwn = + // + (supportedTicket > 0 && ticket == supportedTicket) + // + || + // + (eqmSupportedTicket > 0 && ticket == eqmSupportedTicket) + // + ; + if (isOwn) + { + // + AddRef( + iSupport, + dest // + ); + } + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // Tools ... + + // + // Retrieve Last Open Position Ticket ... + ulong GetLastOpenPositionTicket() + { + // + ulong result = 0; + + int positionsCount = PositionsTotal(); + if (positionsCount <= 0) + { + return result; + } + + // + result = PositionGetTicket(PositionsTotal() - 1); + + // + return result; + } + + // + // Retrieve Last Placed Order Ticket ... + ulong GetLastPlacedOrderTicket() + { + // + ulong result = 0; + + int ordersCount = OrdersTotal(); + if (ordersCount <= 0) + { + return result; + } + + // + if (mOrderInfo.SelectByIndex(ordersCount - 1)) + { + result = mOrderInfo.Ticket(); + } + + // + return result; + } + + // + // Prepare Dynamic Volume ... + double GetDynamicVolume( + string _symbol, + double _balanceFactor, + double _volumeStep // + ) + { + // + double result = 0; + + // + // Validate Inputs ... + if (!IsValid(_symbol) || + _volumeStep <= 0 || + _balanceFactor <= 0) + { + return result; + } + + // + // Retrieve Account Balance ... + double balance = mAccount.GetBalance(); + + // + double bStep = balance / _balanceFactor; + bStep = MathFloor(bStep); + if (bStep == 0) + { + bStep = 1; + } + + // + result = bStep * _volumeStep; + + // + result = NormalizeVolume( + result, + _symbol // + ); + + // + return result; + } + + // + // Protected ... + protected: + // + // Props ... + + // + // Event Listener Notifiers ... + + // + // State ... + void NotifyTradeStateChangeEvent(const XOnTradeHandlerState &state) + { + // + int count = ArraySize(mTradeStateChangedEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + TOnTradeStateChanged iHandler = mTradeStateChangedEventHandlers[i]; + iHandler(state); + } + } + + // + // Deals ... + void NotifyDealsChangeEvent(int changes) + { + // + int count = ArraySize(mDealsChangedEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + TOnDealsChanged iHandler = mDealsChangedEventHandlers[i]; + iHandler(changes); + } + } + + // + // Orders ... + void NotifyOrdersChangeEvent(int changes) + { + // + int count = ArraySize(mOrdersChangedEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + TOnOrdersChanged iHandler = mOrdersChangedEventHandlers[i]; + iHandler(changes); + } + } + + // + // Positions ... + void NotifyPositionsChangeEvent(int changes) + { + // + int count = ArraySize(mPositionsChangedEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + TOnPositionsChanged iHandler = mPositionsChangedEventHandlers[i]; + iHandler(changes); + } + } + + // + // StopLoss ... + void NotifyStopLossEvent(const XDeal &deal) + { + // + int count = ArraySize(mStopLossEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + TOnStopLoss iHandler = mStopLossEventHandlers[i]; + iHandler(deal); + } + } + + // + // Take Profit ... + void NotifyTakeProfitEvent(const XDeal &deal) + { + // + int count = ArraySize(mTakeProfitEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + TOnTakeProfit iHandler = mTakeProfitEventHandlers[i]; + iHandler(deal); + } + } + + // + void NotifyModifyEvent( + ulong ticket, + double profit, + string comment // + ) + { + // + int count = ArraySize(mOnModifyEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + TOnModify iHandler = mOnModifyEventHandlers[i]; + iHandler( + ticket, + profit, + comment // + ); + } + } + + // + void NotifyForceCloseEvent( + ulong ticket, + XPosition &position, + string comment // + ) + { + // + int count = ArraySize(mOnForceCloseEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + TOnForceClose iHandler = mOnForceCloseEventHandlers[i]; + iHandler( + ticket, + position, + comment // + ); + } + } + + // + void NotifyPartialCloseEvent( + ulong ticket, + double profit, + string comment // + ) + { + // + int count = ArraySize(mOnPartialCloseEventHandlers); + if (count <= 0) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + TOnModify iHandler = mOnPartialCloseEventHandlers[i]; + iHandler( + ticket, + profit, + comment // + ); + } + } + + // + // Tools ... + + // + // Retrieve Specified Position Comment ... + string GetPositionComment(ulong ticket) + { + // + string result = NULL; + + // + if (!IsOpen(ticket)) + { + return result; + } + + // + XPosition position; + bool isLoaded = position.ByTicket(ticket); + if (!isLoaded) + { + return result; + } + + // + result = position.comment; + + // + return result; + } + + // + ENUM_TIMEFRAMES GetDealPeriod(XDeal &deal) + { + // + ENUM_TIMEFRAMES result = NULL; + + // + XOrder orders[]; + int ordersCount = GetDealsHistory( + deal, + orders); + if (!ordersCount) + { + return result; + } + + // + for (int i = 0; i < ordersCount; i++) + { + // + XOrder iOrder = orders[i]; + + // + if (IsValid(iOrder.comment)) + { + // + ENUM_TIMEFRAMES iPeriod = ExtractPeriod(iOrder.comment); + if (IsValid(iPeriod)) + { + result = iPeriod; + break; + } + } + } + + // + return result; + } + + // + double GetMaxAllowedEquity() + { + // + double equity = mAccount.GetEquity(); + double balance = mAccount.GetBalance(); + + // + double balanceForFactor = MathAbs(equity - balance); + if (balanceForFactor <= 0) + { + balanceForFactor = balance; + } + else + { + balanceForFactor = equity; + } + + // + double result = balanceForFactor * mMaxAllowedDrawdownFactor; + + // + return result; + } + + // + // Private ... + private: + // + // Props ... + + // + int mSlippage; // Slippage ... + ulong mMagicNumber; // Magic Number (Unique Identifier) ... + + // + double mMaxAllowedSpread; // Max Allowed Spred for Opening Trades + int mMaxAllowedPositions; // Max Allowed Same Positions + double mMaxAllowedDrawdownFactor; // Max Allowed Drawdown Factor + + // + XCTradeBase *mTrader; // Base CTrade Manipulated Instance ... + + // + CDealInfo mDealInfo; // Deals Info ... + COrderInfo mOrderInfo; // Order Info ... + CPositionInfo mPositionInfo; // Positions Info + CHistoryOrderInfo mHistoryOrderInfo; // History Orders Info ... + + // + // Position Info Collector ... + + // + // Tools ... + + // + // OnTrade Event Handlers Section ... + + // + // Props ... + + // + int mDaysForRead; // Reading Dates for Trade History Checker ... + datetime mEndDate; // End Date for Trade history Checking ... + datetime mStartDate; // Start Date for Trade history Checking ... ... + int mOrdersCount; // Number of Active orders ... + int mPositionsCount; // Number of Open positions ... + int mDealsCount; // Number of Deals in the Trade History Checking ... + int mHistoryOrdersCount; // Number of Orders in the Trade History Checking ... + bool mScanStarted; // a Flag of counter relevance ... + + // + // Event Listeners ... + + // + // Deals Changed Event Handlers ... + TOnDealsChanged mDealsChangedEventHandlers[]; + + // + // Orders Changed Event Handlers ... + TOnOrdersChanged mOrdersChangedEventHandlers[]; + + // + // Positions Changed Event Handlers ... + TOnPositionsChanged mPositionsChangedEventHandlers[]; + + // + // Trade State Changed Event Handlers ... + TOnTradeStateChanged mTradeStateChangedEventHandlers[]; + + // + TOnModify mOnModifyEventHandlers[]; + TOnForceClose mOnForceCloseEventHandlers[]; + TOnPartialClose mOnPartialCloseEventHandlers[]; + + // + // TPSL ... + TOnStopLoss mStopLossEventHandlers[]; + TOnTakeProfit mTakeProfitEventHandlers[]; + + // + // Reset On Trade Scanner Context ... + void ResetOnTradeContext() + { + // + mEndDate = TimeCurrent(); + mStartDate = mEndDate - (mDaysForRead * PeriodSeconds(PERIOD_D1)); + } + + // + // Initial Context Of Trade Scanner ... + void InitOnTradeContext() + { + // + ResetLastError(); + + // + mOrdersCount = OrdersTotal(); + mPositionsCount = PositionsTotal(); + + // + // load history ... + bool selected = HistorySelect(mStartDate, mEndDate); + if (!selected) + { + return; + } + + // + // get the current value ... + mDealsCount = HistoryDealsTotal(); + mHistoryOrdersCount = HistoryOrdersTotal(); + + // + mScanStarted = true; + } + + // + // Check Statrt Date In Trade History ... + void CheckStartDateInTradeHistory() + { + // + // initial interval, if we were to start working right now .. + datetime currStart = TimeCurrent() - (mDaysForRead * PeriodSeconds(PERIOD_D1)); + + // + // make sure that the start limit of the trade history has not gone + // more than 1 day over the intended date ... + if (currStart - mStartDate > PeriodSeconds(PERIOD_D1)) + { + // + // correct the start date of history to be loaded in the cache ... + mStartDate = currStart; + + // + // now reload the trade history for the updated interval ... + HistorySelect(mStartDate, mEndDate); + + // + // correct the deal and order counters in history for further comparison + mHistoryOrdersCount = HistoryOrdersTotal(); + mDealsCount = HistoryDealsTotal(); + } + } + + // + // Process On Trade Context ... + void ProcessOnTradeContext( + XOnTradeHandlerState &result // Hold's Result + ) + { + // + mEndDate = TimeCurrent(); + + // + ResetLastError(); + + // + // download trading history from the specified interval to the program cache ... + bool selected = HistorySelect(mStartDate, mEndDate); + if (!selected) + { + return; + } + + // + // get the current values ... + int currOrders = OrdersTotal(); + int currPositions = PositionsTotal(); + int currDeals = HistoryDealsTotal(); + int currHistoryOrders = HistoryOrdersTotal(); + + // + // Orders ... + // check if the number of active orders has been changed ... + if (currOrders != mOrdersCount) + { + // + // number of active orders has been changed ... + result.hasNewOrder = true; + result.newOrders = currOrders - mOrdersCount; + + // + // update the value ... + mOrdersCount = currOrders; + } + + // + // Positions ... + // changes in the number of open positions ... + if (currPositions != mPositionsCount) + { + // + // number of open positions has been changed ... + result.hasNewPosition = true; + result.newPositions = currPositions - mPositionsCount; + + // + // update the value ... + mPositionsCount = currPositions; + } + + // + // Deals ... + // changes in the number of deals in the trade history cache ... + if (currDeals != mDealsCount) + { + // + // number of deals in the trade history cache has been changed ... + result.hasNewDeal = true; + result.newDeals = currDeals - mDealsCount; + + // + // update the value ... + mDealsCount = currDeals; + } + + // + // History Orders ... + // changes in the number of history orders in the trade history cache ... + if (currHistoryOrders != mHistoryOrdersCount) + { + // + // number of history orders in the trade history cache has been changed ... + result.hasNewHistoryOrder = true; + result.newHistoryOrders = currHistoryOrders - mHistoryOrdersCount; + + // + // update the value ... + mHistoryOrdersCount = currHistoryOrders; + } + + // + // checking if it is necessary to change the limits of the trade history to be requested in cache ... + CheckStartDateInTradeHistory(); + } +}; + +// \ No newline at end of file diff --git a/BKPS/14031218/Documents/BKP/1.ind.ai.mq5 b/BKPS/14031218/Documents/BKP/1.ind.ai.mq5 new file mode 100644 index 0000000..34d2e5f --- /dev/null +++ b/BKPS/14031218/Documents/BKP/1.ind.ai.mq5 @@ -0,0 +1,196 @@ +//+------------------------------------------------------------------+ +//| HH_LH_LL_HL.mq5 | +//| Indicator for detecting HH, LH, LL, HL | +//| Created by [Your Name] | +//+------------------------------------------------------------------+ + +#property copyright "Your Name" +#property link "yourwebsite.com" +#property version "1.00" +#property indicator_chart_window +#property indicator_buffers 4 +#property indicator_plots 4 + +//--- Input parameters +input int LookbackPeriod = 20; // Number of bars to look back for pattern detection + +//--- Buffer declarations +double HH_Buffer[]; // Buffer for Higher Highs +double HL_Buffer[]; // Buffer for Higher Lows +double LH_Buffer[]; // Buffer for Lower Highs +double LL_Buffer[]; // Buffer for Lower Lows + +//--- Plot settings +#property indicator_label1 "Higher Highs" +#property indicator_type1 DRAW_ARROW +#property indicator_color1 clrGreen +#property indicator_style1 STYLE_SOLID +#property indicator_width1 1 + +#property indicator_label2 "Higher Lows" +#property indicator_type2 DRAW_ARROW +#property indicator_color2 clrBlue +#property indicator_style2 STYLE_SOLID +#property indicator_width2 1 + +#property indicator_label3 "Lower Highs" +#property indicator_type3 DRAW_ARROW +#property indicator_color3 clrRed +#property indicator_style3 STYLE_SOLID +#property indicator_width3 1 + +#property indicator_label4 "Lower Lows" +#property indicator_type4 DRAW_ARROW +#property indicator_color4 clrYellow +#property indicator_style4 STYLE_SOLID +#property indicator_width4 1 + +//+------------------------------------------------------------------+ +//| Initialization function | +//+------------------------------------------------------------------+ +int OnInit() +{ + // Set buffer properties + SetIndexBuffer(0, HH_Buffer); + SetIndexBuffer(1, HL_Buffer); + SetIndexBuffer(2, LH_Buffer); + SetIndexBuffer(3, LL_Buffer); + + // Clear buffers at each bar + ArrayInitialize(HH_Buffer, 0.0); + ArrayInitialize(HL_Buffer, 0.0); + ArrayInitialize(LH_Buffer, 0.0); + ArrayInitialize(LL_Buffer, 0.0); + + return(INIT_SUCCEEDED); +} + +//+------------------------------------------------------------------+ +//| Deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) +{ + // Cleanup if necessary +} + +//+------------------------------------------------------------------+ +//| Calculate function | +//+------------------------------------------------------------------+ +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[]) +{ + // Start from the last calculated bar + int start_bar = MathMax(prev_calculated - 1, 0); + + // Loop through bars + for (int i = start_bar; i < rates_total; i++) + { + // Get current high and low + double current_high = high[i]; + double current_low = low[i]; + + // Check for Higher High (HH) + if (IsHigherHigh(i, high, LookbackPeriod)) + { + HH_Buffer[i] = current_high; + HL_Buffer[i] = 0.0; // Reset other buffers + LH_Buffer[i] = 0.0; + LL_Buffer[i] = 0.0; + } + // Check for Higher Low (HL) + else if (IsHigherLow(i, low, LookbackPeriod)) + { + HL_Buffer[i] = current_low; + HH_Buffer[i] = 0.0; + LH_Buffer[i] = 0.0; + LL_Buffer[i] = 0.0; + } + // Check for Lower High (LH) + else if (IsLowerHigh(i, high, LookbackPeriod)) + { + LH_Buffer[i] = current_high; + HH_Buffer[i] = 0.0; + HL_Buffer[i] = 0.0; + LL_Buffer[i] = 0.0; + } + // Check for Lower Low (LL) + else if (IsLowerLow(i, low, LookbackPeriod)) + { + LL_Buffer[i] = current_low; + HH_Buffer[i] = 0.0; + HL_Buffer[i] = 0.0; + LH_Buffer[i] = 0.0; + } + else + { + // Reset all buffers if no pattern is detected + HH_Buffer[i] = 0.0; + HL_Buffer[i] = 0.0; + LH_Buffer[i] = 0.0; + LL_Buffer[i] = 0.0; + } + } + + // + return rates_total; +} + +//+------------------------------------------------------------------+ +//| Function to detect Higher High | +//+------------------------------------------------------------------+ +bool IsHigherHigh(int index, const double &high[], int lookback) +{ + for (int i = 1; i <= lookback; i++) + { + if (index - i < 0) continue; // Ensure we don't go out of bounds + if (high[index] <= high[index - i]) return false; + } + return true; +} + +//+------------------------------------------------------------------+ +//| Function to detect Higher Low | +//+------------------------------------------------------------------+ +bool IsHigherLow(int index, const double &low[], int lookback) +{ + for (int i = 1; i <= lookback; i++) + { + if (index - i < 0) continue; // Ensure we don't go out of bounds + if (low[index] <= low[index - i]) return false; + } + return true; +} + +//+------------------------------------------------------------------+ +//| Function to detect Lower High | +//+------------------------------------------------------------------+ +bool IsLowerHigh(int index, const double &high[], int lookback) +{ + for (int i = 1; i <= lookback; i++) + { + if (index - i < 0) continue; // Ensure we don't go out of bounds + if (high[index] >= high[index - i]) return false; + } + return true; +} + +//+------------------------------------------------------------------+ +//| Function to detect Lower Low | +//+------------------------------------------------------------------+ +bool IsLowerLow(int index, const double &low[], int lookback) +{ + for (int i = 1; i <= lookback; i++) + { + if (index - i < 0) continue; // Ensure we don't go out of bounds + if (low[index] >= low[index - i]) return false; + } + return true; +} \ No newline at end of file diff --git a/BKPS/14031218/Documents/BKP/1.mq5 b/BKPS/14031218/Documents/BKP/1.mq5 new file mode 100644 index 0000000..fd7da80 --- /dev/null +++ b/BKPS/14031218/Documents/BKP/1.mq5 @@ -0,0 +1,10874 @@ + +// +// Fix Signal TP Based On Working Zone ... +// double maxAllowedTP = +// hasLong +// ? mXWZConditions.workingZone.upper +// : mXWZConditions.workingZone.lower; +// bool canApplyMaxAlowedTP = (hasLong && +// signal.tp > maxAllowedTP) || +// (!hasLong && signal.tp < maxAllowedTP); +// if (canApplyMaxAlowedTP) +// { +// signal.tp = maxAllowedTP; +// } + +// +// Configuring Global Protector ... +// signal.trailSL = true; +// signal.trailSLStartOnReachTPLevel = 3; +// signal.fullTPLevel = signal.GetRiskRewardRatio(); + +// // +// mXSupDemOBSSignalDetector.RemoveDraws(); +// mXSupDemOBSSignalDetector.DrawConditions( +// mXSupDemOBSConditions, +// mVisionCycleHelper.mPOIDrawer // +// ); + +// // +// mXSupDemOBSSignalDetector.RemoveWorkingZoneDraws(); +// mXSupDemOBSSignalDetector.DrawWorkingZone( +// mXSupDemOBSConditions, +// mVisionCycleHelper.mPOIDrawer // +// ); + +// +// bool canReplaceTarget = +// signal.target > 0 && +// (hasLong +// ? signal.target > signal.tp +// : signal.target < signal.tp); +// if (canReplaceTarget) +// { +// // +// signal.tp = conditions.target; +// signal.target = tp; +// } + +// +// consolidationState.UpdateTo(cTime); +// XPOIState filtered; +// consolidationState.Filter( +// filtered, +// NULL, +// XZONE_STATE_PASSED, +// false, +// XZONE_STATE_FAILED, +// false, +// XZONE_STATE_FAILED, +// false, +// XZONE_STATE_IGNORED, +// false // +// ); +// XCBaseObject *objects[]; +// int objectsCount = drawer.DrawState( +// filtered, +// objects // +// ); +// if (IsValidSize(objectsCount)) +// { +// // +// Print(""); +// } + +// // +// XOBFVG activeObfvgs[]; +// int activeObfvgsCount = ExtractOBFVGs( +// activeObfvgs, +// consolidationState, +// analyseState // +// ); +// bool hasActiveOBFVGs = IsValidSize(activeObfvgsCount); +// if (hasActiveOBFVGs) +// { +// // +// SpecifiedUpdateTo(activeObfvgs); +// for (int i = 0; i < activeObfvgsCount; i++) +// { +// // +// XCBaseObject *objects[]; +// int objectsCount = drawer.DrawOBFVG( +// activeObfvgs[i], +// objects // +// ); +// } +// } + +// // +// // Swings ... +// bool lookupSwings = ArraySize(mSwingLows) < mMaxRequiredPOIs || +// ArraySize(mSwingHighs) < mMaxRequiredPOIs; +// lookupSwings = +// ignoreMaxAllowed +// ? true +// : lookupSwings; +// if (has && +// lookupSwings) +// { +// } + +// // +// // Momentum Bar ... +// bool lookupMomentums = ArraySize(mBullishMomentumBars) < mMaxRequiredPOIs || +// ArraySize(mBearishMomentumBars) < mMaxRequiredPOIs; +// lookupMomentums = +// ignoreMaxAllowed +// ? true +// : lookupMomentums; +// if (has && +// lookupMomentums) +// { +// } + +// // +// // Rejection Bar ... +// bool lookupRejections = ArraySize(mBullishRejectionBars) < mMaxRequiredPOIs || +// ArraySize(mBearishRejectionBars) < mMaxRequiredPOIs; +// lookupRejections = +// ignoreMaxAllowed +// ? true +// : lookupRejections; +// if (has && +// lookupRejections) +// { +// } + +// // +// // Support ... +// bool lookupSupports = ArraySize(mSupportZones) < mMaxRequiredPOIs; +// lookupSupports = +// ignoreMaxAllowed +// ? true +// : lookupSupports; +// if (has && +// lookupSupports) +// { +// } + +// // +// // Demand ... +// bool lookupDemands = ArraySize(mDemandZones) < mMaxRequiredPOIs; +// lookupDemands = +// ignoreMaxAllowed +// ? true +// : lookupDemands; +// if (has && +// lookupDemands) +// { +// } + +// // +// // Resistance ... +// bool lookupResistance = ArraySize(mResistanceZones) < mMaxRequiredPOIs; +// lookupResistance = +// ignoreMaxAllowed +// ? true +// : lookupResistance; +// if (has && +// lookupResistance) +// { +// } + +// // +// // Supply ... +// bool lookupSupplies = ArraySize(mSupplyZones) < mMaxRequiredPOIs; +// lookupSupplies = +// ignoreMaxAllowed +// ? true +// : lookupSupplies; +// if (has && +// lookupSupplies) +// { +// } + +// // +// // OrderBlock ... +// bool lookupOrderBlocks = ArraySize(mBullishOrderBlocks) < mMaxRequiredPOIs || +// ArraySize(mBearishOrderBlocks) < mMaxRequiredPOIs; +// lookupOrderBlocks = +// ignoreMaxAllowed +// ? true +// : lookupOrderBlocks; +// if (has && +// lookupOrderBlocks) +// { +// } + +// // +// // FairValueGap ... +// bool lookupFairValeGaps = ArraySize(mBullishFairValueGaps) < mMaxRequiredPOIs || +// ArraySize(mBearishFairValueGaps) < mMaxRequiredPOIs; +// lookupFairValeGaps = +// ignoreMaxAllowed +// ? true +// : lookupFairValeGaps; +// if (has && +// (lookupFairValeGaps)) +// { +// } + +// +XCBaseObject *stateObjects[]; +int stateObjectsCount = drawer.DrawState( + decisionState, + stateObjects, + false, // + true, // ignoreSwingHighs + true, // ignoreSwingLows + true, // ignoreSupportZones + true, // ignoreResistanceZones + true, // ignoreSupplyZones + true, // ignoreDemandZones + true, // ignoreBullishOrderBlocks + true, // ignoreBearishOrderBlocks + true, // ignoreBullishFairValueGaps + true, // ignoreBearishFairValueGaps + true, // ignoreBullishRejectionBars + true, // ignoreBearishRejectionBars + true, // ignoreBullishMomentumBars + true, // ignoreBearishMomentumBars + false, // ignoreBullishConsolidationZones + false // ignoreBearishConsolidationZones +); + +// +// Draw ... +if (hasSelectedConsolidationZone) +{ + // + XCConsolidationZoneObject *iObj; + selectedConsolidationZone.to = cTime; + bool isCreated = drawer.CreateConsolidationZone( + selectedConsolidationZone, + iObj // + ); +} + +///////////////////////////////////////////////////////////////////////////////////// + +// // +// // Based On Waiting Zones ... +// has = isBarInited && +// hasWorkingZone; +// if (has) +// { +// // +// XOBFVG tmpZones[]; +// Copy( +// workingZone.waitingZones, +// tmpZones // +// ); + +// // +// while (HasChild(tmpZones)) +// { +// // +// XOBFVG iOBFVG; + +// // +// idx = GetYoungest(tmpZones); +// if (!IsValidIndex(idx)) +// { +// // +// iOBFVG.Clean(); +// break; +// } + +// // +// iOBFVG = tmpZones[idx]; +// ArrayRemove( +// tmpZones, +// idx, +// 1 // +// ); + +// // +// double iTarget = +// isSelectedZonDirBullish +// ? iOBFVG.ob.Lower() +// : iOBFVG.ob.Upper(); + +// // +// has = +// isSelectedZonDirBullish +// ? cBar.high < iTarget +// : cBar.low > iTarget; + +// // +// if (has) +// { +// // +// Add( +// iTarget, +// targets // +// ); +// } + +// // +// iOBFVG.Clean(); +// } + +// // +// Clean(tmpZones); +// } + +// // +// // Based On Breaked Zones ... +// has = isBarInited && +// hasBreakedZones; +// if (has) +// { +// // +// XOBFVG tmpZones[]; +// Copy( +// workingZone.breakedZones, +// tmpZones // +// ); + +// // +// while (HasChild(tmpZones)) +// { +// // +// XOBFVG iOBFVG; + +// // +// idx = GetYoungest(tmpZones); +// if (!IsValidIndex(idx)) +// { +// // +// iOBFVG.Clean(); +// break; +// } + +// // +// iOBFVG = tmpZones[idx]; +// ArrayRemove( +// tmpZones, +// idx, +// 1 // +// ); + +// // +// double iTarget = +// isSelectedZonDirBullish +// ? iOBFVG.ob.Lower() +// : iOBFVG.ob.Upper(); + +// // +// has = +// isSelectedZonDirBullish +// ? cBar.high < iTarget +// : cBar.low > iTarget; + +// // +// if (has) +// { +// // +// Add( +// iTarget, +// targets // +// ); +// } + +// // +// iOBFVG.Clean(); +// } + +// // +// Clean(tmpZones); +// } + +// // +// // Based On Priority ... +// if (hasPriority) +// { +// // +// switch (priority) +// { +// // +// case X121SMC_XWZ_PRIORITY_WEAK: +// // +// if (isSelectedZonDirBullish) +// { +// // +// // Weak ... +// Add( +// workingZone.supplyZone.Lower(), +// targets // +// ); +// } +// else +// { +// // +// // Weak ... +// Add( +// workingZone.demandZone.Upper(), +// targets // +// ); +// } +// break; + +// // +// case X121SMC_XWZ_PRIORITY_LOW: +// // +// if (isSelectedZonDirBullish) +// { +// // +// // Weak ... +// Add( +// workingZone.supplyZone.Lower(), +// targets // +// ); + +// // +// // Low ... +// Add( +// workingZone.quarter1, +// targets // +// ); +// } +// else +// { +// // +// // Weak ... +// Add( +// workingZone.demandZone.Upper(), +// targets // +// ); + +// // +// // Low ... +// Add( +// workingZone.quarter3, +// targets // +// ); +// } +// break; + +// // +// case X121SMC_XWZ_PRIORITY_REGULAR: +// // +// if (isSelectedZonDirBullish) +// { +// // +// // Weak ... +// Add( +// workingZone.supplyZone.Lower(), +// targets // +// ); + +// // +// // Low ... +// Add( +// workingZone.quarter1, +// targets // +// ); + +// // +// // Regular ... +// Add( +// workingZone.quarter2, +// targets // +// ); +// } +// else +// { +// // +// // Weak ... +// Add( +// workingZone.demandZone.Upper(), +// targets // +// ); + +// // +// // Low ... +// Add( +// workingZone.quarter3, +// targets // +// ); + +// // +// // Regular ... +// Add( +// workingZone.quarter2, +// targets // +// ); +// } +// break; + +// // +// case X121SMC_XWZ_PRIORITY_HIGH: +// // +// if (isSelectedZonDirBullish) +// { +// // +// // Weak ... +// Add( +// workingZone.supplyZone.Lower(), +// targets // +// ); + +// // +// // Low ... +// Add( +// workingZone.quarter1, +// targets // +// ); + +// // +// // Regular ... +// Add( +// workingZone.quarter2, +// targets // +// ); + +// // +// // High ... +// Add( +// workingZone.quarter3, +// targets // +// ); +// } +// else +// { +// // +// // Weak ... +// Add( +// workingZone.demandZone.Upper(), +// targets // +// ); + +// // +// // Low ... +// Add( +// workingZone.quarter3, +// targets // +// ); + +// // +// // Regular ... +// Add( +// workingZone.quarter2, +// targets // +// ); + +// // +// // High ... +// Add( +// workingZone.quarter1, +// targets // +// ); +// } +// break; + +// // +// case X121SMC_XWZ_PRIORITY_STRONG_HIGH: +// // +// if (isSelectedZonDirBullish) +// { +// // +// // Weak ... +// Add( +// workingZone.supplyZone.Lower(), +// targets // +// ); + +// // +// // Low ... +// Add( +// workingZone.quarter1, +// targets // +// ); + +// // +// // Regular ... +// Add( +// workingZone.quarter2, +// targets // +// ); + +// // +// // High ... +// Add( +// workingZone.quarter3, +// targets // +// ); + +// // +// // Strong High ... +// Add( +// workingZone.demandZone.Upper(), +// targets // +// ); +// } +// else +// { +// // +// // Weak ... +// Add( +// workingZone.demandZone.Upper(), +// targets // +// ); + +// // +// // Low ... +// Add( +// workingZone.quarter3, +// targets // +// ); + +// // +// // Regular ... +// Add( +// workingZone.quarter2, +// targets // +// ); + +// // +// // High ... +// Add( +// workingZone.quarter1, +// targets // +// ); + +// // +// // Strong High ... +// Add( +// workingZone.supplyZone.Lower(), +// targets // +// ); +// } +// break; +// } +// } + +//////////////////////////////////////////////////////////////////// + +// +// Based On Consolidation Zones ... +has = isBarInited && + decisionState.HasConsolidationZones(); +if (has) +{ + // + XConsolidationZone tmpZones[]; + if (isSelectedZonDirBullish) + { + // + Copy( + decisionState.bullishConsolidationZones, + tmpZones // + ); + } + else + { + // + Copy( + decisionState.bearishConsolidationZones, + tmpZones // + ); + } + + // + while (HasChild(tmpZones)) + { + // + idx = GetYoungest(tmpZones); + if (!IsValidIndex(idx)) + { + break; + } + + // + XConsolidationZone iZone = tmpZones[idx]; + + // + ArrayRemove( + tmpZones, + idx, + 1 // + ); + + // + hasSelectedConsolidationZone = + isSelectedZonDirBullish + ? cBar.low < iZone.upper + : cBar.high < iZone.lower; + if (hasSelectedConsolidationZone) + { + // + selectedConsolidationZone = iZone; + iZone.Clean(); + break; + } + + // + iZone.Clean(); + } + + // + Clean(tmpZones); + + // + if (hasSelectedConsolidationZone) + { + // + XCConsolidationZoneObject *iObj; + selectedConsolidationZone.to = cTime; + bool isCreated = drawer.CreateConsolidationZone( + selectedConsolidationZone, + iObj // + ); + + // + double iSL = + isSelectedZonDirBullish + ? selectedConsolidationZone.lower + : selectedConsolidationZone.upper; + double iSLDiff = MathAbs(iSL - pivot); + has = + iSLDiff > 0 && + iSLDiff <= maxAllowedSLDistanceInPoint * points; + if (has) + { + // + Add( + iSL, + sls // + ); + } + } +} + +// +// Based On Supply and Demand Zones ... + +// +// Demand Zones ... +has = hasWorkingZone && + workingZone.HasDemandZones(); +if (has) +{ + // + XCDemandZone *tmpZones[]; + Copy( + workingZone.demandZones, + tmpZones // + ); + XCDemandZone *selectedDemand = NULL; + + // + while (HasChild(tmpZones)) + { + // + idx = GetLowest(tmpZones); + has = IsValidIndex(idx); + if (!has) + { + break; + } + + // + XCDemandZone *iZone = tmpZones[idx]; + ArrayRemove( + tmpZones, + idx, + 1 // + ); + + // + // Validate Zone ... + has = + isSelectedZonDirBullish + ? IsBelowDiff( + iZone, + selectedZone.ob, + true // Ignore Inside ... + ) + : IsAboveDiff( + iZone, + selectedZone.ob, + true // Ignore Inside ... + ); + if (!has) + { + continue; + } + + // + has = + selectedDemand == NULL + ? true + : isSelectedZonDirBullish + ? selectedDemand.Lower() < iZone.Lower() + : selectedDemand.Upper() > iZone.Upper(); + if (!has) + { + continue; + } + + // + selectedDemand = iZone; + + // + } + + // + has = selectedDemand != NULL; + if (has) + { + // + XCDemandZoneObject *iObj; + bool isCreated = drawer.CreateDemandZone( + selectedDemand, + iObj // + ); + + // + double iSL = + isSelectedZonDirBullish + ? selectedDemand.Lower() + : selectedDemand.Upper(); + double iSLDiff = MathAbs(iSL - pivot); + has = + iSLDiff > 0 && + iSLDiff <= maxAllowedSLDistanceInPoint * points; + if (has) + { + // + Add( + iSL, + sls // + ); + } + } + + // + Clean(tmpZones); + ZeroMemory(selectedDemand); +} + +// +// Support Zones ... +has = hasWorkingZone && + workingZone.HasSupportZones(); +if (has) +{ + // + XCSupportZone *tmpZones[]; + Copy( + workingZone.supportZones, + tmpZones // + ); + XCSupportZone *selectedSupport = NULL; + + // + while (HasChild(tmpZones)) + { + // + idx = GetLowest(tmpZones); + has = IsValidIndex(idx); + if (!has) + { + break; + } + + // + XCSupportZone *iZone = tmpZones[idx]; + ArrayRemove( + tmpZones, + idx, + 1 // + ); + + // + // Validate Zone ... + has = + isSelectedZonDirBullish + ? IsBelowDiff( + iZone, + selectedZone.ob, + true // Ignore Inside ... + ) + : IsAboveDiff( + iZone, + selectedZone.ob, + true // Ignore Inside ... + ); + if (!has) + { + continue; + } + + // + has = + selectedSupport == NULL + ? true + : isSelectedZonDirBullish + ? selectedSupport.Lower() < iZone.Lower() + : selectedSupport.Upper() > iZone.Upper(); + if (!has) + { + continue; + } + + // + selectedSupport = iZone; + + // + } + + // + has = selectedSupport != NULL; + if (has) + { + // + XCSupportZoneObject *iObj; + bool isCreated = drawer.CreateSupportZone( + selectedSupport, + iObj // + ); + + // + double iSL = isSelectedZonDirBullish + ? selectedSupport.Lower() + : selectedSupport.Upper(); + double iSLDiff = MathAbs(iSL - pivot); + has = + iSLDiff > 0 && + iSLDiff <= maxAllowedSLDistanceInPoint * points; + if (has) + { + // + Add( + iSL, + sls // + ); + } + } + + // + Clean(tmpZones); + ZeroMemory(selectedSupport); +} + +// +// Supply Zones ... +has = hasWorkingZone && + workingZone.HasSupplyZones(); +if (has) +{ + // + XCSupplyZone *tmpZones[]; + Copy( + workingZone.supplyZones, + tmpZones // + ); + XCSupplyZone *selectedSupply = NULL; + + // + while (HasChild(tmpZones)) + { + // + idx = GetHighest(tmpZones); + has = IsValidIndex(idx); + if (!has) + { + break; + } + + // + XCSupplyZone *iZone = tmpZones[idx]; + ArrayRemove( + tmpZones, + idx, + 1 // + ); + + // + // Validate Zone ... + has = + !isSelectedZonDirBullish + ? IsAboveDiff( + iZone, + selectedZone.ob, + true // Ignore Inside ... + ) + : IsBelowDiff( + iZone, + selectedZone.ob, + true // Ignore Inside ... + ); + if (!has) + { + continue; + } + + // + has = + selectedSupply == NULL + ? true + : !isSelectedZonDirBullish + ? selectedSupply.Upper() > iZone.Upper() + : selectedSupply.Lower() < iZone.Lower(); + if (!has) + { + continue; + } + + // + selectedSupply = iZone; + + // + } + + // + has = selectedSupply != NULL; + if (has) + { + // + XCSupplyZoneObject *iObj; + bool isCreated = drawer.CreateSupplyZone( + selectedSupply, + iObj // + ); + + // + double iSL = + !isSelectedZonDirBullish + ? selectedSupply.Upper() + : selectedSupply.Lower(); + double iSLDiff = MathAbs(iSL - pivot); + has = + iSLDiff > 0 && + iSLDiff <= maxAllowedSLDistanceInPoint * points; + if (has) + { + // + Add( + iSL, + sls // + ); + } + } + + // + Clean(tmpZones); + ZeroMemory(selectedSupply); +} + +// +// Resistance Zones ... +has = hasWorkingZone && + workingZone.HasDemandZones(); +if (has) +{ + // + XCResistanceZone *tmpZones[]; + Copy( + workingZone.resistanceZones, + tmpZones // + ); + XCResistanceZone *selectedResistance = NULL; + + // + while (HasChild(tmpZones)) + { + // + idx = GetHighest(tmpZones); + has = IsValidIndex(idx); + if (!has) + { + break; + } + + // + XCResistanceZone *iZone = tmpZones[idx]; + ArrayRemove( + tmpZones, + idx, + 1 // + ); + + // + // Validate Zone ... + has = + !isSelectedZonDirBullish + ? IsAboveDiff( + iZone, + selectedZone.ob, + true // Ignore Inside ... + ) + : IsBelowDiff( + iZone, + selectedZone.ob, + true // Ignore Inside ... + ); + if (!has) + { + continue; + } + + // + has = + selectedResistance == NULL + ? true + : !isSelectedZonDirBullish + ? selectedResistance.Upper() < iZone.Upper() + : selectedResistance.Lower() > iZone.Lower(); + if (!has) + { + continue; + } + + // + selectedResistance = iZone; + + // + } + + // + has = selectedResistance != NULL; + if (has) + { + // + XCResistanceZoneObject *iObj; + bool isCreated = drawer.CreateResistanceZone( + selectedResistance, + iObj // + ); + + // + double iSL = + !isSelectedZonDirBullish + ? selectedResistance.Upper() + : selectedResistance.Lower(); + double iSLDiff = MathAbs(iSL - pivot); + has = + iSLDiff > 0 && + iSLDiff <= maxAllowedSLDistanceInPoint * points; + if (has) + { + // + Add( + iSL, + sls // + ); + } + } + + // + Clean(tmpZones); + ZeroMemory(selectedResistance); +} + +// +// Based On Passed Bars ... +XOHCL passedBar; +bool isPassed = false; +bool isBodyState = false; +ENUM_X_DIRECTION passedDir = selectedZone.GetDirection(); + +// +// Started Bar ... +isPassed = selectedZone.ob.IsStarted( + passedDir, + passedBar, + isBodyState // +); +if (isPassed) +{ + // + double iSL = + isSelectedZonDirBullish + ? passedBar.low + : passedBar.high; + double iSLDiff = MathAbs(iSL - pivot); + has = + iSLDiff > 0 && + iSLDiff <= maxAllowedSLDistanceInPoint * points; + if (has) + { + // + Add( + iSL, + sls // + ); + } +} + +// +// Activation Bar ... +passedBar.Clean(); +isPassed = selectedZone.ob.IsActivated( + passedDir, + passedBar, + isBodyState // +); +if (isPassed) +{ + // + double iSL = + isSelectedZonDirBullish + ? passedBar.low + : passedBar.high; + double iSLDiff = MathAbs(iSL - pivot); + has = + iSLDiff > 0 && + iSLDiff <= maxAllowedSLDistanceInPoint * points; + if (has) + { + // + Add( + iSL, + sls // + ); + } +} + +// +// Worked Bar ... +passedBar.Clean(); +isPassed = selectedZone.ob.IsActivated( + passedDir, + passedBar, + isBodyState // +); +if (isPassed) +{ + // + double iSL = + isSelectedZonDirBullish + ? passedBar.low + : passedBar.high; + double iSLDiff = MathAbs(iSL - pivot); + has = + iSLDiff > 0 && + iSLDiff <= maxAllowedSLDistanceInPoint * points; + if (has) + { + // + Add( + iSL, + sls // + ); + } +} + +// +// Breaked Bar ... +passedBar.Clean(); +isPassed = selectedZone.ob.IsActivated( + passedDir, + passedBar, + isBodyState // +); +if (isPassed) +{ + // + double iSL = + isSelectedZonDirBullish + ? passedBar.low + : passedBar.high; + double iSLDiff = MathAbs(iSL - pivot); + has = + iSLDiff > 0 && + iSLDiff <= maxAllowedSLDistanceInPoint * points; + if (has) + { + // + Add( + iSL, + sls // + ); + } +} + +//////////////////////////////////////////////////////////////////// + +// // +// // Trail Stops Using Swings ... + +// // +// bool canTrailLongUsingSwings = +// // +// isLong && +// isInProfit && +// (isSwingLow || +// isStrongSwingLow) && +// pBar.low > iPosition.sl && +// pBar.low > iPosition.entry +// // +// ; +// if (canTrailLongUsingSwings) +// { +// sl = pBar.low; +// } + +// // +// bool canTraiShortlUsingSwings = +// // +// !isLong && +// isInProfit && +// (isSwingHigh || +// isStrongSwingHigh) && +// pBar.high < iPosition.sl && +// pBar.high < iPosition.entry +// // +// ; +// if (canTraiShortlUsingSwings) +// { +// sl = pBar.high; +// } + +// // +// bool canTrailUsingSwings = +// canTrailLongUsingSwings || +// canTraiShortlUsingSwings; + +// // +// // +// // + +//////////////////////////////////////////////////////////////////////////// + +// // +// XOHCL zBar; +// result = zBar.Init( +// symbol, +// period, +// zIndex // +// ); +// if (!result) +// { +// // +// result = HasChild(guards); +// return result; +// } + +// // +// XOHCL cBar; +// result = cBar.Init( +// symbol, +// period, +// cIndex // +// ); +// if (!result) +// { +// // +// zBar.Clean(); +// result = HasChild(guards); +// return result; +// } + +// // +// XOHCL pBar; +// result = pBar.Init( +// symbol, +// period, +// pIndex // +// ); +// if (!result) +// { +// // +// zBar.Clean(); +// cBar.Clean(); +// result = HasChild(guards); +// return result; +// } + +// // +// XOHCL ppBar; +// result = ppBar.Init( +// symbol, +// period, +// ppIndex // +// ); +// if (!result) +// { +// // +// zBar.Clean(); +// cBar.Clean(); +// pBar.Clean(); +// result = HasChild(guards); +// return result; +// } + +// +// zBar.Clean(); +// cBar.Clean(); +// pBar.Clean(); +// ppBar.Clean(); + +// +// Detect High Probability Swings ... +// bool isSwingLow = +// // +// cBar.low > pBar.low && +// ppBar.low > pBar.low && +// // +// zBar.low > pBar.low +// // +// ; +// bool isSwingHigh = +// // +// cBar.high < pBar.high && +// ppBar.high < pBar.high && +// // +// zBar.high < pBar.high +// // +// ; +// bool isStrongSwingLow = +// pBar.IsBullish() && +// pBar.GetLowShadow() >= pBar.GetBody() * 2; +// bool isStrongSwingHigh = +// pBar.IsBearish() && +// pBar.GetHighShadow() >= pBar.GetBody() * 2; + +/////////////////////////////////////////////////////////////////////////////// + +// +// +// + +bool DetectX121Conditions( + double &pivot, + double &point, + double &sls[], + double &targets[], + ENUM_X_DIRECTION &dir, + XPOIState &stfState, + XPOIState &ttfState, + X121Conditions &conditions, + XCPOIDrawer *drawer = NULL // +) +{ + // + bool result = false; + + // + bool canDraw = drawer != NULL; + + // + pivot = 0; + point = 0; + Clean(sls); + Clean(targets); + dir = X_DIRECTION_NONE; + + // + result = + stfState.IsValid() && + ttfState.IsValid() && + stfState.HasChild() && + ttfState.HasChild(); + if (!result) + { + return result; + } + + // + int idx = -1; + int count = 0; + bool has = false; + + // + // Detect Inside STF Order Blocks Zones ... + + // + XOBFVG tmpWaitingZones[]; + count = ExtractOBFVGs( + tmpWaitingZones, + stfState, + ttfState // + ); + has = IsValidSize(count); + if (has) + { + // + if (canDraw) + { + // + for (int i = 0; i < count; i++) + { + // + XOBFVG iOBFVG = tmpWaitingZones[i]; + + // + iOBFVG.UpdateTo(); + + // + XCBaseObject *iOBFVGObjects[]; + int iOBFVGObjectsCount = drawer.DrawOBFVG( + iOBFVG, + iOBFVGObjects // + ); + } + } + } + + // + + // + return result; +} + +////////////////////////////////////////////////////////////////////////// + +/** + * Check an XOBFVG instance has Required Conditions ... + * + * @param zone: XBoxZone instance ... + * @param state: XPOIState instance ... + * @param conditions: X121Conditions instance ... + * + * @return ( bool ) + */ +bool DetectSelectedBoxConditions( + bool &isReversal, + XBoxZone &zone, + XPOIState &state, + X121Conditions &conditions // +) +{ + // + bool result = false; + + // + isReversal = false; + + // + result = + zone.IsValid() && + state.IsValid() && + state.HasChild(); + if (!result) + { + return result; + } + + // + bool isBullish = zone.IsBullish(); + bool isBearish = zone.IsBearish(); + + // + bool isBullishTrend = conditions.isTrendBullish || + conditions.isTrendSwitchedToBullish; + bool isBearishTrend = conditions.isTrendBearish || + conditions.isTrendSwitchedToBearish; + + // + double bullishScore = 0; + double bearishScore = 0; + double scoreMultiplier = 1.5; + conditions.GenerateScore( + bullishScore, + bearishScore // + ); + + // + bool isBullishScorePassed = bullishScore > 0 && + bearishScore >= 0 && + bullishScore > bearishScore * scoreMultiplier; + + // + bool isBearishScorePassed = bearishScore > 0 && + bullishScore >= 0 && + bearishScore > bullishScore * scoreMultiplier; + + // + // VWap ... + + // + double vwapFast = conditions.vwapFastBuffer[0]; + double vwapMid = conditions.vwapMidBuffer[0]; + double vwapSlow = conditions.vwapSlowBuffer[0]; + + // + bool isVWapInside = + // + vwapFast > zone.lower && + vwapFast < zone.upper + // + && + vwapMid > zone.lower && + vwapMid < zone.upper + // + ; + + // + bool isVWapBullish = + // + (conditions.isVWapBullishState && + conditions.isVWapSwitchedToBullishOrdered) + // + || + // + (conditions.isVWapBullishOrdered && + conditions.isVWapSwitchedToBullishState) + // + ; + + // + bool isVWapBearish = + // + (conditions.isVWapBearishState && + conditions.isVWapSwitchedToBearishOrdered) + // + || + // + (conditions.isVWapBearishOrdered && + conditions.isVWapSwitchedToBearishState) + // + ; + + // + // X3Ma ... + + // + double x3maFast = conditions.x3maFastBuffer[0]; + double x3maMid = conditions.x3maMidBuffer[0]; + double x3maSlow = conditions.x3maSlowBuffer[0]; + + // + bool isX3MaInside = + // + x3maFast > zone.lower && + x3maFast < zone.upper + // + && + x3maMid > zone.lower && + x3maMid < zone.upper + // + ; + + // + bool isX3MaBullish = + // + (conditions.isX3MaBullishState && + conditions.isX3MaSwitchedToBullishOrdered) + // + || + // + (conditions.isX3MaBullishOrdered && + conditions.isX3MaSwitchedToBullishState) + // + ; + + // + bool isX3MaBearish = + // + (conditions.isX3MaBearishState && + conditions.isX3MaSwitchedToBearishOrdered) + // + || + // + (conditions.isX3MaBearishOrdered && + conditions.isX3MaSwitchedToBearishState) + // + ; + + // + // + // + + // + bool isInside = + // + isVWapInside || + isX3MaInside + // + ; + + // + bool isVWap3MaBullish = + isVWapBullish || + isX3MaBullish; + + // + bool isVWap3MaBearish = + isVWapBearish || + isX3MaBearish; + + // + // + // + + // + bool isDirectionalBullishPassed = + // + isInside && + isBullish && + isBullishTrend && + isVWap3MaBullish && + isBullishScorePassed + // + ; + + // + bool isDirectionalBearishPassed = + // + isInside && + isBearish && + isBearishTrend && + isVWap3MaBearish && + isBearishScorePassed + // + ; + + // + bool isDirectionalPassed = + isDirectionalBullishPassed || + isDirectionalBearishPassed; + + // + bool isReversalBullishPassed = + // + isInside && + isBullish && + isBearishTrend && + isVWap3MaBearish && + isBearishScorePassed + // + ; + + // + bool isReversalBearishPassed = + // + isInside && + isBearish && + isBullishTrend && + isVWap3MaBullish && + isBullishScorePassed + // + ; + + // + bool isReversalPassed = isReversalBullishPassed || + isReversalBearishPassed; + + // + result = isReversalPassed || + isDirectionalPassed; + + // + if (result) + { + isReversal = isReversalPassed; + } + + // + return result; +} + +/////////////////////////////////////////////////////////////////////////////// + +// if (hasWaitingZones) +// { +// // +// int idx = -1; +// int count = 0; +// XOBFVG youngest; +// bool has = false; +// XCFVG *selectedFVG; +// XCFVG *unActivatedFVGs[]; + +// // +// idx = GetYoungest(workingZone.waitingZones); +// has = IsValidIndex(idx); +// if (has) +// { +// // +// youngest = workingZone.waitingZones[idx]; +// selectedZoneDir = youngest.GetDirection(); + +// // +// if (IsBullish(selectedZoneDir)) +// { +// // +// Copy( +// analyseState.bullishFairValueGaps, +// unActivatedFVGs // +// ); +// } +// else +// { +// // +// Copy( +// analyseState.bearishFairValueGaps, +// unActivatedFVGs // +// ); +// } +// } + +// // +// count = ArraySize(unActivatedFVGs); +// has = IsValidSize(count); +// if (has) +// { +// // +// idx = GetYoungest(unActivatedFVGs); +// has = IsValidIndex(idx); +// if (has) +// { +// selectedFVG = unActivatedFVGs[idx]; +// } +// } + +// // +// has = selectedFVG != NULL; +// if (has) +// { +// // +// XCBaseObject *iObj; +// bool isCreated = drawer.CreateFairValueGap( +// selectedFVG, +// iObj // +// ); + +// // +// if (isCreated) +// { +// Print("Salam"); +// } +// } +// } + +////////////////////////////////////////////////////////////////////////////////////////// + +/** + * Check an XOBFVG instance has Required Conditions ... + * + * @param zone: XOBFVG instance ... + * @param state: XPOIState instance ... + * @param conditions: X121Conditions instance ... + * + * @return ( bool ) + */ +bool DetectInsideSelectedZoneConditions( + bool &isReversal, + XOBFVG &zone, + XPOIState &state, + X121Conditions &conditions // +) +{ + // + bool result = false; + + // + isReversal = false; + + // + result = + zone.IsValid() && + state.IsValid() && + state.HasChild(); + if (!result) + { + return result; + } + + // + bool isBullish = zone.IsBullish(); + bool isBearish = zone.IsBearish(); + + // + bool isBullishTrend = conditions.isTrendBullish || + conditions.isTrendSwitchedToBullish; + bool isBearishTrend = conditions.isTrendBearish || + conditions.isTrendSwitchedToBearish; + + // + double bullishScore = 0; + double bearishScore = 0; + double scoreMultiplier = 1.5; + conditions.GenerateScore( + bullishScore, + bearishScore // + ); + + // + bool isBullishScorePassed = bullishScore > 0 && + bearishScore >= 0 && + bullishScore > bearishScore * scoreMultiplier; + + // + bool isBearishScorePassed = bearishScore > 0 && + bullishScore >= 0 && + bearishScore > bullishScore * scoreMultiplier; + + // + // VWap ... + + // + double vwapFast = conditions.vwapFastBuffer[0]; + double vwapMid = conditions.vwapMidBuffer[0]; + double vwapSlow = conditions.vwapSlowBuffer[0]; + + // + bool isVWapInside = + // + vwapFast > zone.ob.Lower() && + vwapFast < zone.ob.Upper() + // + && + vwapMid > zone.ob.Lower() && + vwapMid < zone.ob.Upper() + // + ; + + // + bool isVWapBullish = + // + (conditions.isVWapBullishState && + conditions.isVWapSwitchedToBullishOrdered) + // + || + // + (conditions.isVWapBullishOrdered && + conditions.isVWapSwitchedToBullishState) + // + ; + + // + bool isVWapBearish = + // + (conditions.isVWapBearishState && + conditions.isVWapSwitchedToBearishOrdered) + // + || + // + (conditions.isVWapBearishOrdered && + conditions.isVWapSwitchedToBearishState) + // + ; + + // + // X3Ma ... + + // + double x3maFast = conditions.x3maFastBuffer[0]; + double x3maMid = conditions.x3maMidBuffer[0]; + double x3maSlow = conditions.x3maSlowBuffer[0]; + + // + bool isX3MaInside = + // + x3maFast > zone.ob.Lower() && + x3maFast < zone.ob.Upper() + // + && + x3maMid > zone.ob.Lower() && + x3maMid < zone.ob.Upper() + // + ; + + // + bool isX3MaBullish = + // + (conditions.isX3MaBullishState && + conditions.isX3MaSwitchedToBullishOrdered) + // + || + // + (conditions.isX3MaBullishOrdered && + conditions.isX3MaSwitchedToBullishState) + // + ; + + // + bool isX3MaBearish = + // + (conditions.isX3MaBearishState && + conditions.isX3MaSwitchedToBearishOrdered) + // + || + // + (conditions.isX3MaBearishOrdered && + conditions.isX3MaSwitchedToBearishState) + // + ; + + // + // + // + + // + bool isInside = + // + isVWapInside || + isX3MaInside + // + ; + + // + bool isVWap3MaBullish = + isVWapBullish || + isX3MaBullish; + + // + bool isVWap3MaBearish = + isVWapBearish || + isX3MaBearish; + + // + // + // + + // + bool isDirectionalBullishPassed = + // + isInside && + isBullish && + isBullishTrend && + isVWap3MaBullish && + isBullishScorePassed + // + ; + + // + bool isDirectionalBearishPassed = + // + isInside && + isBearish && + isBearishTrend && + isVWap3MaBearish && + isBearishScorePassed + // + ; + + // + bool isDirectionalPassed = + isDirectionalBullishPassed || + isDirectionalBearishPassed; + + // + bool isReversalBullishPassed = + // + isInside && + isBullish && + isBearishTrend && + isVWap3MaBearish && + isBearishScorePassed + // + ; + + // + bool isReversalBearishPassed = + // + isInside && + isBearish && + isBullishTrend && + isVWap3MaBullish && + isBullishScorePassed + // + ; + + // + bool isReversalPassed = isReversalBullishPassed || + isReversalBearishPassed; + + // + result = isReversalPassed || + isDirectionalPassed; + + // + if (result) + { + isReversal = isReversalPassed; + } + + // + return result; +} + +bool DetectBreakedSelectedZoneConditions( + bool &isReversal, + XOBFVG &zone, + XPOIState &mtfState, + XPOIState &stfState, + XPOIState &ttfState, + X121Conditions &conditions // +) +{ + // + bool result = false; + + // + isReversal = false; + + // + result = + // + zone.IsValid() && + mtfState.IsValid() && + stfState.IsValid() && + ttfState.IsValid() && + mtfState.HasChild() && + stfState.HasChild() && + ttfState.HasChild() + // + ; + if (!result) + { + return result; + } + + // + XBoxZone iBox; + result = ToBox( + iBox, + zone.ob // + ); + if (!result) + { + return result; + } + + // + ENUM_X_DIRECTION iDir = iBox.dir; + bool isBullish = IsBullish(iDir); + bool isBearish = IsBearish(iDir); + + // + // X3Ma ... + + // + double x3maFast = conditions.x3maFastBuffer[0]; + double x3maMid = conditions.x3maMidBuffer[0]; + double x3maSlow = conditions.x3maSlowBuffer[0]; + + // + bool isX3mInside = + // + (x3maFast < iBox.upper && + x3maMid < iBox.upper && + x3maSlow < iBox.upper) + // + && + // + (x3maFast > iBox.lower && + x3maMid > iBox.lower && + x3maSlow > iBox.lower) + // + ; + + // + bool isBullishConditions = + isBullish && + isX3mInside; + + // + bool isBearishConditions = + isBearish && + isX3mInside; + + // + result = isBullishConditions || + isBearishConditions; + + // + return result; +} + +/** + * Detect Targets Based on Selected Zone for Specified type of Directions ... + * + * @param targets: double Collection ... + * @param selectedZone: XOBFVG instance, selected Zone ... + * @param forDir: ENUM_X_DIRECTION specified Position Direction ... + * @param workingone: X121SMCStrategyXWZWorkingZone instance, Specified Working Zone ... + * @param barIndex: int Specified Bar Index ... + * + * @return ( bool ) + */ +bool DetectSelectedZonesTargets( + double &targets[], + XOBFVG &selectedZone, + ENUM_X_DIRECTION forDir, + ENUM_X121SMC_XWZ_PRIORITY forPriority, + X121SMCStrategyXWZWorkingZone &workingZone, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + Clean(targets); + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (barIndex == 0) + { + barIndex++; + } + + // + result = + // + selectedZone.IsValid() && + HasDirection(forDir) && + workingZone.IsValid() && + forPriority != X121SMC_XWZ_PRIORITY_NONE + // + ; + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + XOHCL cBar; + result = cBar.Init( + workingZone.symbol, + workingZone.period, + barIndex // + ); + if (!result) + { + // + cBar.Clean(); + return result; + } + + // + int idx = -1; + bool has = false; + XOBFVG tmpZones[]; + + // + // Based On Waiting Zones ... + has = workingZone.HasWaitingZones(); + if (has) + { + // + Copy( + workingZone.waitingZones, + tmpZones // + ); + + // + while (HasChild(tmpZones)) + { + // + XOBFVG iOBFVG; + + // + idx = GetYoungest(tmpZones); + if (!IsValidIndex(idx)) + { + // + iOBFVG.Clean(); + break; + } + + // + iOBFVG = tmpZones[idx]; + ArrayRemove( + tmpZones, + idx, + 1 // + ); + + // + double iTarget = + isBullish + ? iOBFVG.ob.Lower() + : iOBFVG.ob.Upper(); + + // + has = + isBullish + ? cBar.high < iTarget + : cBar.low > iTarget; + + // + if (has) + { + // + Add( + iTarget, + targets // + ); + } + + // + iOBFVG.Clean(); + } + + // + Clean(tmpZones); + } + + // + // Based On Breaked Zones ... + has = workingZone.HasBreakedZones(); + if (has) + { + Copy( + workingZone.breakedZones, + tmpZones // + ); + + // + while (HasChild(tmpZones)) + { + // + XOBFVG iOBFVG; + + // + idx = GetYoungest(tmpZones); + if (!IsValidIndex(idx)) + { + // + iOBFVG.Clean(); + break; + } + + // + iOBFVG = tmpZones[idx]; + ArrayRemove( + tmpZones, + idx, + 1 // + ); + + // + double iTarget = + isBullish + ? iOBFVG.ob.Lower() + : iOBFVG.ob.Upper(); + + // + has = + isBullish + ? cBar.high < iTarget + : cBar.low > iTarget; + + // + if (has) + { + // + Add( + iTarget, + targets // + ); + } + + // + iOBFVG.Clean(); + } + + // + Clean(tmpZones); + } + + // + // Based On Priority ... + has = forPriority != X121SMC_XWZ_PRIORITY_NONE; + if (has) + { + // + switch (forPriority) + { + // + case X121SMC_XWZ_PRIORITY_WEAK: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + } + break; + + // + case X121SMC_XWZ_PRIORITY_LOW: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter1, + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter3, + targets // + ); + } + break; + + // + case X121SMC_XWZ_PRIORITY_REGULAR: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter1, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter3, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + } + break; + + // + case X121SMC_XWZ_PRIORITY_HIGH: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter1, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + + // + // High ... + Add( + workingZone.quarter3, + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter3, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + + // + // High ... + Add( + workingZone.quarter1, + targets // + ); + } + break; + + // + case X121SMC_XWZ_PRIORITY_STRONG_HIGH: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter1, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + + // + // High ... + Add( + workingZone.quarter3, + targets // + ); + + // + // Strong High ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter3, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + + // + // High ... + Add( + workingZone.quarter1, + targets // + ); + + // + // Strong High ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + } + break; + } + } + + // + result = HasChild(targets); + + // + // Cleanup ... + cBar.Clean(); + Clean(tmpZones); + + // + return result; +} + +/** + * Detect Targets Based on Selected Zone for Specified type of Directions ... + * + * @param targets: double Collection ... + * @param selectedZone: XBoxZone instance, selected Zone ... + * @param forDir: ENUM_X_DIRECTION specified Position Direction ... + * @param workingone: X121SMCStrategyXWZWorkingZone instance, Specified Working Zone ... + * @param barIndex: int Specified Bar Index ... + * + * @return ( bool ) + */ +bool DetectSelectedZonesTargets( + double &targets[], + XBoxZone &selectedZone, + ENUM_X_DIRECTION forDir, + ENUM_X121SMC_XWZ_PRIORITY forPriority, + X121SMCStrategyXWZWorkingZone &workingZone, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + Clean(targets); + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (barIndex == 0) + { + barIndex++; + } + + // + result = + // + selectedZone.IsValid() && + HasDirection(forDir) && + workingZone.IsValid() && + forPriority != X121SMC_XWZ_PRIORITY_NONE + // + ; + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + XOHCL cBar; + result = cBar.Init( + workingZone.symbol, + workingZone.period, + barIndex // + ); + if (!result) + { + // + cBar.Clean(); + return result; + } + + // + int idx = -1; + bool has = false; + XOBFVG tmpZones[]; + + // + // Based On Waiting Zones ... + has = workingZone.HasWaitingZones(); + if (has) + { + // + Copy( + workingZone.waitingZones, + tmpZones // + ); + + // + while (HasChild(tmpZones)) + { + // + XOBFVG iOBFVG; + + // + idx = GetYoungest(tmpZones); + if (!IsValidIndex(idx)) + { + // + iOBFVG.Clean(); + break; + } + + // + iOBFVG = tmpZones[idx]; + ArrayRemove( + tmpZones, + idx, + 1 // + ); + + // + double iTarget = + isBullish + ? iOBFVG.ob.Lower() + : iOBFVG.ob.Upper(); + + // + has = + isBullish + ? cBar.high < iTarget + : cBar.low > iTarget; + + // + if (has) + { + // + Add( + iTarget, + targets // + ); + } + + // + iOBFVG.Clean(); + } + + // + Clean(tmpZones); + } + + // + // Based On Breaked Zones ... + has = workingZone.HasBreakedZones(); + if (has) + { + Copy( + workingZone.breakedZones, + tmpZones // + ); + + // + while (HasChild(tmpZones)) + { + // + XOBFVG iOBFVG; + + // + idx = GetYoungest(tmpZones); + if (!IsValidIndex(idx)) + { + // + iOBFVG.Clean(); + break; + } + + // + iOBFVG = tmpZones[idx]; + ArrayRemove( + tmpZones, + idx, + 1 // + ); + + // + double iTarget = + isBullish + ? iOBFVG.ob.Lower() + : iOBFVG.ob.Upper(); + + // + has = + isBullish + ? cBar.high < iTarget + : cBar.low > iTarget; + + // + if (has) + { + // + Add( + iTarget, + targets // + ); + } + + // + iOBFVG.Clean(); + } + + // + Clean(tmpZones); + } + + // + // Based On Priority ... + has = forPriority != X121SMC_XWZ_PRIORITY_NONE; + if (has) + { + // + switch (forPriority) + { + // + case X121SMC_XWZ_PRIORITY_WEAK: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + } + break; + + // + case X121SMC_XWZ_PRIORITY_LOW: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter1, + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter3, + targets // + ); + } + break; + + // + case X121SMC_XWZ_PRIORITY_REGULAR: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter1, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter3, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + } + break; + + // + case X121SMC_XWZ_PRIORITY_HIGH: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter1, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + + // + // High ... + Add( + workingZone.quarter3, + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter3, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + + // + // High ... + Add( + workingZone.quarter1, + targets // + ); + } + break; + + // + case X121SMC_XWZ_PRIORITY_STRONG_HIGH: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter1, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + + // + // High ... + Add( + workingZone.quarter3, + targets // + ); + + // + // Strong High ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter3, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + + // + // High ... + Add( + workingZone.quarter1, + targets // + ); + + // + // Strong High ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + } + break; + } + } + + // + result = HasChild(targets); + + // + // Cleanup ... + cBar.Clean(); + Clean(tmpZones); + + // + return result; +} + +/** + * Detect SL Candidates Based on Selected Zone for Specified type of Directions ... + * + * @param sls: double Collection ... + * @param selectedZone: XOBFVG instance, selected Zone ... + * @param forDir: ENUM_X_DIRECTION specified Position Direction ... + * @param workingZone: X121SMCStrategyXWZWorkingZone instance, Specified Working Zone ... + * @param barIndex: int Specified Bar Index ... + * @param maxAllowedSLDistanceInPoint: doube max Allowe SL distance ... + * + * @return ( bool ) + */ +bool DetectSelectedZoneSLCandidates( + double &sls[], + XOBFVG &selectedZone, + ENUM_X_DIRECTION forDir, + X121SMCStrategyXWZWorkingZone &workingZone, + X121Conditions &conditions, + int barIndex = 0, + double maxAllowedSLDistanceInPoint = 300 // +) +{ + // + bool result = false; + + // + Clean(sls); + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (barIndex == 0) + { + barIndex++; + } + + // + result = + // + selectedZone.IsValid() && + HasDirection(forDir) && + workingZone.IsValid() + // + ; + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + double pivot = + isBullish + ? selectedZone.ob.Lower() + : selectedZone.ob.Upper(); + double points = GetPoints(workingZone.symbol); + + // + XOHCL cBar; + result = cBar.Init( + workingZone.symbol, + workingZone.period, + barIndex // + ); + if (!result) + { + // + cBar.Clean(); + return result; + } + + // + int idx = -1; + bool has = false; + + // + double pvSL = isBullish + ? conditions.valesBuffer[0] + : conditions.peaksBuffer[1]; + + // + Add( + pvSL, + sls // + ); + + // + // Based On Passed Bars ... + // XOHCL passedBar; + // bool isPassed = false; + // bool isBodyState = false; + // ENUM_X_DIRECTION passedDir = selectedZone.GetDirection(); + + // // + // // Started Bar ... + // isPassed = selectedZone.ob.IsStarted( + // passedDir, + // passedBar, + // isBodyState // + // ); + // if (isPassed) + // { + // // + // double iSL = + // isBullish + // ? passedBar.low + // : passedBar.high; + // double iSLDiff = MathAbs(iSL - pivot); + // has = + // iSLDiff > 0 && + // iSLDiff <= maxAllowedSLDistanceInPoint * points; + // if (has) + // { + // // + // Add( + // iSL, + // sls // + // ); + // } + // } + + // // + // // Activation Bar ... + // passedBar.Clean(); + // isPassed = selectedZone.ob.IsActivated( + // passedDir, + // passedBar, + // isBodyState // + // ); + // if (isPassed) + // { + // // + // double iSL = + // isBullish + // ? passedBar.low + // : passedBar.high; + // double iSLDiff = MathAbs(iSL - pivot); + // has = + // iSLDiff > 0 && + // iSLDiff <= maxAllowedSLDistanceInPoint * points; + // if (has) + // { + // // + // Add( + // iSL, + // sls // + // ); + // } + // } + + // // + // // Worked Bar ... + // passedBar.Clean(); + // isPassed = selectedZone.ob.IsActivated( + // passedDir, + // passedBar, + // isBodyState // + // ); + // if (isPassed) + // { + // // + // double iSL = + // isBullish + // ? passedBar.low + // : passedBar.high; + // double iSLDiff = MathAbs(iSL - pivot); + // has = + // iSLDiff > 0 && + // iSLDiff <= maxAllowedSLDistanceInPoint * points; + // if (has) + // { + // // + // Add( + // iSL, + // sls // + // ); + // } + // } + + // // + // // Breaked Bar ... + // passedBar.Clean(); + // isPassed = selectedZone.ob.IsActivated( + // passedDir, + // passedBar, + // isBodyState // + // ); + // if (isPassed) + // { + // // + // double iSL = + // isBullish + // ? passedBar.low + // : passedBar.high; + // double iSLDiff = MathAbs(iSL - pivot); + // has = + // iSLDiff > 0 && + // iSLDiff <= maxAllowedSLDistanceInPoint * points; + // if (has) + // { + // // + // Add( + // iSL, + // sls // + // ); + // } + // } + + // + // Based On Consolidation Zones ... + has = workingZone.HasConsolidationZones(); + if (has) + { + // + XConsolidationZone tmpZones[]; + Copy( + workingZone.consolidationZones, + tmpZones // + ); + XConsolidationZone selectedConsolidationZone; + + // + while (HasChild(tmpZones)) + { + // + idx = GetYoungest(tmpZones); + if (!IsValidIndex(idx)) + { + break; + } + + // + XConsolidationZone iZone = tmpZones[idx]; + + // + ArrayRemove( + tmpZones, + idx, + 1 // + ); + + // + has = + !selectedConsolidationZone.IsValid() + ? isBullish + ? cBar.low < iZone.upper + : cBar.high < iZone.lower + : isBullish + ? selectedConsolidationZone.lower < iZone.lower + : selectedConsolidationZone.upper > iZone.upper; + if (has) + { + // + selectedConsolidationZone = iZone; + iZone.Clean(); + break; + } + + // + iZone.Clean(); + } + + // + Clean(tmpZones); + has = selectedConsolidationZone.IsValid(); + if (has) + { + // + double iSL = + isBullish + ? selectedConsolidationZone.lower + : selectedConsolidationZone.upper; + double iSLDiff = MathAbs(iSL - pivot); + has = + iSLDiff > 0 && + iSLDiff <= maxAllowedSLDistanceInPoint * points; + if (has) + { + // + Add( + iSL, + sls // + ); + } + } + } + + // + // Based On Supply and Demand Zones ... + + // + // Demand Zones ... + has = workingZone.HasDemandZones(); + if (has) + { + // + XCDemandZone *tmpZones[]; + Copy( + workingZone.demandZones, + tmpZones // + ); + XCDemandZone *selectedDemand = NULL; + + // + while (HasChild(tmpZones)) + { + // + idx = GetLowest(tmpZones); + has = IsValidIndex(idx); + if (!has) + { + break; + } + + // + XCDemandZone *iZone = tmpZones[idx]; + ArrayRemove( + tmpZones, + idx, + 1 // + ); + + // + // Validate Zone ... + has = + isBullish + ? IsBelowDiff( + iZone, + selectedZone.ob, + true // Ignore Inside ... + ) + : IsAboveDiff( + iZone, + selectedZone.ob, + true // Ignore Inside ... + ); + if (!has) + { + continue; + } + + // + has = + selectedDemand == NULL + ? true + : isBullish + ? selectedDemand.Lower() < iZone.Lower() + : selectedDemand.Upper() > iZone.Upper(); + if (!has) + { + continue; + } + + // + selectedDemand = iZone; + } + + // + has = selectedDemand != NULL; + if (has) + { + // + double iSL = + isBullish + ? selectedDemand.Lower() + : selectedDemand.Upper(); + double iSLDiff = MathAbs(iSL - pivot); + has = + iSLDiff > 0 && + iSLDiff <= maxAllowedSLDistanceInPoint * points; + if (has) + { + // + Add( + iSL, + sls // + ); + } + } + + // + Clean(tmpZones); + ZeroMemory(selectedDemand); + } + + // + // Support Zones ... + // has = workingZone.HasSupportZones(); + // if (has) + // { + // // + // XCSupportZone *tmpZones[]; + // Copy( + // workingZone.supportZones, + // tmpZones // + // ); + // XCSupportZone *selectedSupport = NULL; + + // // + // while (HasChild(tmpZones)) + // { + // // + // idx = GetLowest(tmpZones); + // has = IsValidIndex(idx); + // if (!has) + // { + // break; + // } + + // // + // XCSupportZone *iZone = tmpZones[idx]; + // ArrayRemove( + // tmpZones, + // idx, + // 1 // + // ); + + // // + // // Validate Zone ... + // has = + // isBullish + // ? IsBelowDiff( + // iZone, + // selectedZone.ob, + // true // Ignore Inside ... + // ) + // : IsAboveDiff( + // iZone, + // selectedZone.ob, + // true // Ignore Inside ... + // ); + // if (!has) + // { + // continue; + // } + + // // + // has = + // selectedSupport == NULL + // ? true + // : isBullish + // ? selectedSupport.Lower() < iZone.Lower() + // : selectedSupport.Upper() > iZone.Upper(); + // if (!has) + // { + // continue; + // } + + // // + // selectedSupport = iZone; + + // // + // } + + // // + // has = selectedSupport != NULL; + // if (has) + // { + // // + // double iSL = isBullish + // ? selectedSupport.Lower() + // : selectedSupport.Upper(); + // double iSLDiff = MathAbs(iSL - pivot); + // has = + // iSLDiff > 0 && + // iSLDiff <= maxAllowedSLDistanceInPoint * points; + // if (has) + // { + // // + // Add( + // iSL, + // sls // + // ); + // } + // } + + // // + // Clean(tmpZones); + // ZeroMemory(selectedSupport); + // } + + // + // Supply Zones ... + has = workingZone.HasSupplyZones(); + if (has) + { + // + XCSupplyZone *tmpZones[]; + Copy( + workingZone.supplyZones, + tmpZones // + ); + XCSupplyZone *selectedSupply = NULL; + + // + while (HasChild(tmpZones)) + { + // + idx = GetHighest(tmpZones); + has = IsValidIndex(idx); + if (!has) + { + break; + } + + // + XCSupplyZone *iZone = tmpZones[idx]; + ArrayRemove( + tmpZones, + idx, + 1 // + ); + + // + // Validate Zone ... + has = + !isBullish + ? IsAboveDiff( + iZone, + selectedZone.ob, + true // Ignore Inside ... + ) + : IsBelowDiff( + iZone, + selectedZone.ob, + true // Ignore Inside ... + ); + if (!has) + { + continue; + } + + // + has = + selectedSupply == NULL + ? true + : !isBullish + ? selectedSupply.Upper() > iZone.Upper() + : selectedSupply.Lower() < iZone.Lower(); + if (!has) + { + continue; + } + + // + selectedSupply = iZone; + + // + } + + // + has = selectedSupply != NULL; + if (has) + { + // + double iSL = + !isBullish + ? selectedSupply.Upper() + : selectedSupply.Lower(); + double iSLDiff = MathAbs(iSL - pivot); + has = + iSLDiff > 0 && + iSLDiff <= maxAllowedSLDistanceInPoint * points; + if (has) + { + // + Add( + iSL, + sls // + ); + } + } + + // + Clean(tmpZones); + ZeroMemory(selectedSupply); + } + + // + // Resistance Zones ... + // has = workingZone.HasDemandZones(); + // if (has) + // { + // // + // XCResistanceZone *tmpZones[]; + // Copy( + // workingZone.resistanceZones, + // tmpZones // + // ); + // XCResistanceZone *selectedResistance = NULL; + + // // + // while (HasChild(tmpZones)) + // { + // // + // idx = GetHighest(tmpZones); + // has = IsValidIndex(idx); + // if (!has) + // { + // break; + // } + + // // + // XCResistanceZone *iZone = tmpZones[idx]; + // ArrayRemove( + // tmpZones, + // idx, + // 1 // + // ); + + // // + // // Validate Zone ... + // has = + // !isBullish + // ? IsAboveDiff( + // iZone, + // selectedZone.ob, + // true // Ignore Inside ... + // ) + // : IsBelowDiff( + // iZone, + // selectedZone.ob, + // true // Ignore Inside ... + // ); + // if (!has) + // { + // continue; + // } + + // // + // has = + // selectedResistance == NULL + // ? true + // : !isBullish + // ? selectedResistance.Upper() < iZone.Upper() + // : selectedResistance.Lower() > iZone.Lower(); + // if (!has) + // { + // continue; + // } + + // // + // selectedResistance = iZone; + + // // + // } + + // // + // has = selectedResistance != NULL; + // if (has) + // { + // // + // double iSL = + // !isBullish + // ? selectedResistance.Upper() + // : selectedResistance.Lower(); + // double iSLDiff = MathAbs(iSL - pivot); + // has = + // iSLDiff > 0 && + // iSLDiff <= maxAllowedSLDistanceInPoint * points; + // if (has) + // { + // // + // Add( + // iSL, + // sls // + // ); + // } + // } + + // // + // Clean(tmpZones); + // ZeroMemory(selectedResistance); + // } + + // + // Cleanp Resources ... + + // + cBar.Clean(); + // passedBar.Clean(); + result = HasChild(sls); + + // + return result; +} + +//////////////////////////////////////////////////////////////////////////////// + +/** + * Detect Targets Based on Selected Zone for Specified type of Directions ... + * + * @param targets: double Collection ... + * @param selectedZone: XBoxZone instance, selected Zone ... + * @param forDir: ENUM_X_DIRECTION specified Position Direction ... + * @param workingone: X121SMCStrategyXWZWorkingZone instance, Specified Working Zone ... + * @param barIndex: int Specified Bar Index ... + * + * @return ( bool ) + */ +bool DetectSelectedZonesTargets( + double &targets[], + XBoxZone &selectedZone, + ENUM_X_DIRECTION forDir, + ENUM_X121SMC_XWZ_PRIORITY forPriority, + X121SMCStrategyXWZWorkingZone &workingZone, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + Clean(targets); + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (barIndex == 0) + { + barIndex++; + } + + // + result = + // + selectedZone.IsValid() && + HasDirection(forDir) && + workingZone.IsValid() && + forPriority != X121SMC_XWZ_PRIORITY_NONE + // + ; + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + XOHCL cBar; + result = cBar.Init( + workingZone.symbol, + workingZone.period, + barIndex // + ); + if (!result) + { + // + cBar.Clean(); + return result; + } + + // + int idx = -1; + bool has = false; + XOBFVG tmpZones[]; + + // + // Based On Waiting Zones ... + has = workingZone.HasWaitingZones(); + if (has) + { + // + Copy( + workingZone.waitingZones, + tmpZones // + ); + + // + while (HasChild(tmpZones)) + { + // + XOBFVG iOBFVG; + + // + idx = GetYoungest(tmpZones); + if (!IsValidIndex(idx)) + { + // + iOBFVG.Clean(); + break; + } + + // + iOBFVG = tmpZones[idx]; + ArrayRemove( + tmpZones, + idx, + 1 // + ); + + // + double iTarget = + isBullish + ? iOBFVG.ob.Lower() + : iOBFVG.ob.Upper(); + + // + has = + isBullish + ? cBar.high < iTarget + : cBar.low > iTarget; + + // + if (has) + { + // + Add( + iTarget, + targets // + ); + } + + // + iOBFVG.Clean(); + } + + // + Clean(tmpZones); + } + + // + // Based On Breaked Zones ... + has = workingZone.HasBreakedZones(); + if (has) + { + Copy( + workingZone.breakedZones, + tmpZones // + ); + + // + while (HasChild(tmpZones)) + { + // + XOBFVG iOBFVG; + + // + idx = GetYoungest(tmpZones); + if (!IsValidIndex(idx)) + { + // + iOBFVG.Clean(); + break; + } + + // + iOBFVG = tmpZones[idx]; + ArrayRemove( + tmpZones, + idx, + 1 // + ); + + // + double iTarget = + isBullish + ? iOBFVG.ob.Lower() + : iOBFVG.ob.Upper(); + + // + has = + isBullish + ? cBar.high < iTarget + : cBar.low > iTarget; + + // + if (has) + { + // + Add( + iTarget, + targets // + ); + } + + // + iOBFVG.Clean(); + } + + // + Clean(tmpZones); + } + + // + // Based On Priority ... + has = forPriority != X121SMC_XWZ_PRIORITY_NONE; + if (has) + { + // + switch (forPriority) + { + // + case X121SMC_XWZ_PRIORITY_WEAK: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + } + break; + + // + case X121SMC_XWZ_PRIORITY_LOW: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter1, + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter3, + targets // + ); + } + break; + + // + case X121SMC_XWZ_PRIORITY_REGULAR: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter1, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter3, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + } + break; + + // + case X121SMC_XWZ_PRIORITY_HIGH: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter1, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + + // + // High ... + Add( + workingZone.quarter3, + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter3, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + + // + // High ... + Add( + workingZone.quarter1, + targets // + ); + } + break; + + // + case X121SMC_XWZ_PRIORITY_STRONG_HIGH: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter1, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + + // + // High ... + Add( + workingZone.quarter3, + targets // + ); + + // + // Strong High ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter3, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + + // + // High ... + Add( + workingZone.quarter1, + targets // + ); + + // + // Strong High ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + } + break; + } + } + + // + result = HasChild(targets); + + // + // Cleanup ... + cBar.Clean(); + Clean(tmpZones); + + // + return result; +} + +/////////////////////////////////////////////////////////////////////// + +// +struct X121SMCStrategyXWZWorkingZone +{ + // + // Props ... + + // + string symbol; + ENUM_TIMEFRAMES period; + + // + double quarter1; + double quarter2; + double quarter3; + + // + XCSupplyZone *supplyZone; + XCDemandZone *demandZone; + + // + XCSupplyZone *supplyZones[]; + XCDemandZone *demandZones[]; + + // + XCSupportZone *supportZones[]; + XCResistanceZone *resistanceZones[]; + + // + XOBFVG insideZones[]; + XOBFVG breakedZones[]; + XOBFVG waitingZones[]; + + // + XBoxZone insideBoxes[]; + XBoxZone breakedBoxes[]; + XConsolidationZone consolidationZones[]; + + // + CArrayObj mInsideZoneObjects; + CArrayObj mBreakedZoneObjects; + CArrayObj mWaitingZoneObjects; + CArrayObj mWorkingZoneObjects; + + // + // Constructor ... + X121SMCStrategyXWZWorkingZone() + { + Clean(); + } + + // + // Tools ... + + // + void Clean() + { + // + quarter1 = 0; + quarter2 = 0; + quarter3 = 0; + + // + symbol = NULL; + period = NULL; + + // + Clean(supplyZones); + Clean(demandZones); + + // + Clean(insideZones); + Clean(waitingZones); + Clean(breakedZones); + + // + Clean(insideBoxes); + Clean(breakedBoxes); + + // + Clean(supportZones); + Clean(resistanceZones); + + // + ZeroMemory(supplyZone); + ZeroMemory(demandZone); + + // + mInsideZoneObjects.Clear(); + mBreakedZoneObjects.Clear(); + mWaitingZoneObjects.Clear(); + mWorkingZoneObjects.Clear(); + } + + // + bool IsValid() + { + // + bool result = false; + + // + result = + // + quarter1 > 0 && + quarter2 > 0 && + quarter3 > 0 && + HasSupplyZone() && + HasDemandZone() && + quarter1 > quarter2 && + quarter2 > quarter3 + // + ; + + // + return result; + } + + // + bool Init( + string _symbol, + ENUM_TIMEFRAMES _period, + int barIndex, + XPOIState &htfState, + XPOIState &mtfState, + XPOIState &stfState, // + XPOIState &ttfState // + ) + { + // + bool result = false; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + result = + // + IsValid(_symbol) && + IsValid(_period) && + // + htfState.IsValid() && + mtfState.IsValid() && + stfState.IsValid() && + ttfState.IsValid() && + // + htfState.HasChild() && + mtfState.HasChild() && + stfState.HasChild() && + ttfState.HasChild() + // + ; + if (!result) + { + return result; + } + + // + symbol = _symbol; + period = _period; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + XOHCL zBar; + has = zBar.Init( + symbol, + period, + barIndex // + ); + result = has; + if (!result) + { + zBar.Clean(); + return result; + } + double ll5 = zBar.FindLowest(5, MODE_LOW); + double hh5 = zBar.FindHighest(5, MODE_HIGH); + zBar.Clean(); + + // + // Supply Zone ... + has = HasSupplyZone(); + if (!has) + { + // + idx = GetHighest(htfState.supplyZones); + has = IsValidIndex(idx); + if (has) + { + // + supplyZone = htfState.supplyZones[idx]; + has = hh5 < supplyZone.Lower(); + if (!has) + { + supplyZone = NULL; + } + } + } + + // + // Demand Zone ... + has = HasDemandZone(); + if (!has) + { + // + idx = GetLowest(htfState.demandZones); + has = IsValidIndex(idx); + if (has) + { + // + demandZone = htfState.demandZones[idx]; + has = ll5 > demandZone.Upper(); + if (!has) + { + demandZone = NULL; + } + } + } + + // + // Supply Zones ... + has = HasSupplyZones(); + if (!has) + { + // + count = mtfState.FilterSupplyZones( + supplyZones, + period, + XZONE_STATE_PASSED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_IGNORED, + false // + ); + } + + // + // Demand Zones ... + has = HasDemandZones(); + if (!has) + { + // + count = mtfState.FilterDemandZones( + demandZones, + period, + XZONE_STATE_PASSED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_IGNORED, + false // + ); + } + + // + has = ttfState.HasConsolidationZones(); + if (has) + { + // + Copy( + ttfState.consolidationZones, + consolidationZones // + ); + CleanupArray( + consolidationZones, + 50 // + ); + } + + // + if (supplyZone != NULL && + demandZone != NULL && + supplyZone.IsValid() && + demandZone.IsValid()) + { + // + double upper = supplyZone.Lower(); + double lower = demandZone.Upper(); + + // + double delta = ((upper - lower) / 100) * 25; + + // + quarter1 = upper - (1 * delta); + quarter2 = upper - (2 * delta); + quarter3 = upper - (3 * delta); + } + + // + // Detect OBFVG(s) ... + ExtractOBFVGs( + waitingZones, + mtfState, + stfState); + + // + result = IsValid(); + if (!result) + { + Clean(); + } + + // + return result; + } + + // + void Update( + int barIndex, + XPOIState &htfState, + XPOIState &mtfState, + XPOIState &stfState, + XPOIState &ttfState // + ) + { + // + int idx = -1; + int count = 0; + bool has = false; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + has = + // + IsValid() && + // + htfState.IsValid() && + mtfState.IsValid() && + stfState.IsValid() && + // + htfState.HasChild() && + mtfState.HasChild() && + stfState.HasChild() + // + ; + if (!has) + { + return; + } + + // + XOHCL zBar; + has = zBar.Init( + symbol, + period, + barIndex // + ); + if (!has) + { + // + zBar.Clean(); + return; + } + + // + XOHCL cBar; + has = zBar.GetPreviousBar(cBar); + if (!has) + { + // + zBar.Clean(); + cBar.Clean(); + + // + return; + } + + // + // Adding New OBFVG to Waiting Zones if not Exists ... + XOBFVG tmpWaitingZones[]; + count = ExtractOBFVGs( + tmpWaitingZones, + mtfState, + stfState // + ); + has = IsValidSize(count); + if (has) + { + // + AddIfNotExists( + tmpWaitingZones, + waitingZones // + ); + } + + // + // Since Usig States for Extracting Supply/Demand or + // Support/Resistance Zones and State's has Max Alllowed Restrication ... + // we have to Manage new Zones and also Hold's Breaked Zones ... + + // + // MTF STF ... + + // + // Supply Zones ... + XCSupplyZone *tmpSupplies[]; + count = mtfState.FilterSupplyZones( + tmpSupplies, + NULL, + XZONE_STATE_PASSED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_IGNORED, + false // + ); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = ToBox( + iBox, + tmpSupplies[i] // + ); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + // Find Index ... + + // + idx = FindIndex( + iBox, + insideBoxes // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + idx = FindIndex( + iBox, + breakedBoxes // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + idx = FindIndex( + tmpSupplies[i], + supplyZones // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + // Checking Price Validation ... + has = cBar.high < tmpSupplies[i].Lower(); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + Add( + tmpSupplies[i], + supplyZones // + ); + + // + iBox.Clean(); + } + } + Clean(tmpSupplies); + + // + // Demand Zones ... + XCDemandZone *tmpDemands[]; + count = mtfState.FilterDemandZones( + tmpDemands, + NULL, + XZONE_STATE_PASSED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_IGNORED, + false // + ); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = ToBox( + iBox, + tmpDemands[i] // + ); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + // Find Index ... + + // + idx = FindIndex( + iBox, + insideBoxes // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + idx = FindIndex( + iBox, + breakedBoxes // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + idx = FindIndex( + tmpDemands[i], + demandZones // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + // Checking Price Validation ... + has = cBar.low > tmpDemands[i].Upper(); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + Add( + tmpDemands[i], + demandZones // + ); + + // + iBox.Clean(); + } + } + Clean(tmpDemands); + + // + // + // + + // + // Consolidation Zones ... + has = ttfState.HasConsolidationZones(); + if (has) + { + // + Copy( + ttfState.consolidationZones, + consolidationZones // + ); + CleanupArray( + consolidationZones, + 50 // + ); + } + + // + // + // + + // + // Detect Price Inside Zones ... + has = HasWaitingZones(); + if (has) + { + // + int mustRemove[]; + count = CountWaitingZones(); + for (int i = 0; i < count; i++) + { + // + XOBFVG iOBFVG = waitingZones[i]; + + // + bool isInside = + // + zBar.high < iOBFVG.ob.Upper() && + zBar.low > iOBFVG.ob.Lower() && + // + cBar.high < iOBFVG.ob.Upper() && + cBar.low > iOBFVG.ob.Lower() + // + ; + if (isInside) + { + // + idx = FindIndex( + iOBFVG, + insideZones // + ); + has = IsValidSize(idx); + if (!has) + { + // + Add( + i, + mustRemove // + ); + + // + AddRef( + iOBFVG, + insideZones // + ); + } + } + } + + // + has = HasChild(mustRemove); + if (has) + { + // + count = ArraySize(mustRemove); + for (int i = 0; i < count; i++) + { + // + ArrayRemove( + waitingZones, + mustRemove[i], + 1 // + ); + } + } + + // + Clean(mustRemove); + } + + // + // Here we Looking for Price Inside Supply or Demand Zones ... + + // + // Supply Zones ... + has = HasSupplyZones(); + if (has) + { + // + int mustRemove[]; + count = CountSupplyZones(); + for (int i = 0; i < count; i++) + { + // + XCSupplyZone *iZone = supplyZones[i]; + + // + bool isInside = + // + zBar.high < iZone.Upper() && + zBar.low > iZone.Lower() && + // + cBar.high < iZone.Upper() && + cBar.low > iZone.Lower() + // + ; + if (isInside) + { + // + XBoxZone iBox; + has = ToBox( + iBox, + iZone // + ); + if (has) + { + // + idx = FindIndex( + iBox, + insideBoxes // + ); + has = IsValidSize(idx); + if (!has) + { + // + Add( + i, + mustRemove // + ); + + // + AddRef( + iBox, + insideBoxes // + ); + } + } + + // + iBox.Clean(); + } + } + + // + has = HasChild(mustRemove); + if (has) + { + // + count = ArraySize(mustRemove); + for (int i = 0; i < count; i++) + { + // + ArrayRemove( + supplyZones, + mustRemove[i], + 1 // + ); + } + } + + // + Clean(mustRemove); + } + + // + // Demand Zones ... + has = HasDemandZones(); + if (has) + { + // + int mustRemove[]; + count = CountDemandZones(); + for (int i = 0; i < count; i++) + { + // + XCDemandZone *iZone = demandZones[i]; + + // + bool isInside = + // + zBar.high < iZone.Upper() && + zBar.low > iZone.Lower() && + // + cBar.high < iZone.Upper() && + cBar.low > iZone.Lower() + // + ; + if (isInside) + { + // + XBoxZone iBox; + has = ToBox( + iBox, + iZone // + ); + if (has) + { + // + idx = FindIndex( + iBox, + insideBoxes // + ); + has = IsValidSize(idx); + if (!has) + { + // + Add( + i, + mustRemove // + ); + + // + AddRef( + iBox, + insideBoxes // + ); + } + } + + // + iBox.Clean(); + } + } + + // + has = HasChild(mustRemove); + if (has) + { + // + count = ArraySize(mustRemove); + for (int i = 0; i < count; i++) + { + // + ArrayRemove( + demandZones, + mustRemove[i], + 1 // + ); + } + } + + // + Clean(mustRemove); + } + + // + // Here we Detect Breaked Zone/Box (s) ... + + // // + // // Detect Breaked Zones ... + // has = HasInsideZones(); + // if (has) + // { + // // + // int mustRemove[]; + // count = CountInsideZones(); + // for (int i = 0; i < count; i++) + // { + // // + // XOBFVG iOBFVG = insideZones[i]; + // ENUM_X_DIRECTION iDir = iOBFVG.GetDirection(); + // bool isBullish = IsBullish(iDir); + + // // + // bool isBullishBreaked = + // // + // zBar.high < iOBFVG.ob.Lower() && + // cBar.high < iOBFVG.ob.Lower() + // // + // ; + + // // + // bool isBearishBreaked = + // // + // zBar.low > iOBFVG.ob.Upper() && + // cBar.low > iOBFVG.ob.Upper() + // // + // ; + + // // + // bool isBreaked = + // isBullish + // ? isBullishBreaked + // : isBearishBreaked; + + // // + // if (isBreaked) + // { + // // + // idx = FindIndex( + // iOBFVG, + // breakedZones // + // ); + // has = IsValidIndex(idx); + // if (!has) + // { + // // + // Add( + // i, + // mustRemove // + // ); + + // // + // AddRef( + // iOBFVG, + // breakedZones // + // ); + // } + // } + // } + + // // + // has = HasChild(mustRemove); + // if (has) + // { + // // + // count = ArraySize(mustRemove); + // for (int i = 0; i < count; i++) + // { + // // + // ArrayRemove( + // insideZones, + // mustRemove[i], + // 1 // + // ); + // } + // } + + // // + // Clean(mustRemove); + // } + + // // + // // Detect Breaked Boxes ... + // has = HasInsideBoxes(); + // if (has) + // { + // // + // int mustRemove[]; + // count = CountInsideBoxes(); + // for (int i = 0; i < count; i++) + // { + // // + // XBoxZone iBox = insideBoxes[i]; + // ENUM_X_DIRECTION iDir = iBox.dir; + // bool isBullish = iBox.IsBullish(); + + // // + // bool isBullishBreaked = + // // + // zBar.high < iBox.lower && + // cBar.high < iBox.lower + // // + // ; + + // // + // bool isBearishBreaked = + // // + // zBar.low > iBox.upper && + // cBar.low > iBox.upper + // // + // ; + + // // + // bool isBreaked = + // isBullish + // ? isBullishBreaked + // : isBearishBreaked; + + // // + // if (isBreaked) + // { + // // + // idx = FindIndex( + // iBox, + // breakedBoxes // + // ); + // has = IsValidIndex(idx); + // if (!has) + // { + // // + // Add( + // i, + // mustRemove // + // ); + + // // + // AddRef( + // iBox, + // breakedBoxes // + // ); + // } + // } + // } + + // // + // has = HasChild(mustRemove); + // if (has) + // { + // // + // count = ArraySize(mustRemove); + // for (int i = 0; i < count; i++) + // { + // // + // ArrayRemove( + // insideBoxes, + // mustRemove[i], + // 1 // + // ); + // } + // } + + // // + // Clean(mustRemove); + // } + + // + // Cleanup Resource ... + + // + zBar.Clean(); + cBar.Clean(); + } + + // + bool HasSupplyZone() + { + return supplyZone != NULL && + supplyZone.IsValid(); + } + + // + bool HasDemandZone() + { + return demandZone != NULL && + demandZone.IsValid(); + } + + // + bool HasSupplyZones() + { + return HasChild(supplyZones); + } + + // + int CountSupplyZones() + { + return ArraySize(supplyZones); + } + + // + bool HasDemandZones() + { + return HasChild(demandZones); + } + + // + int CountDemandZones() + { + return ArraySize(demandZones); + } + + // + bool HasSupportZones() + { + return HasChild(supportZones); + } + + // + int CountSupportZones() + { + return ArraySize(supportZones); + } + + // + bool HasResistanceZones() + { + return HasChild(resistanceZones); + } + + // + int CountResistanceZones() + { + return ArraySize(resistanceZones); + } + + // + bool HasWaitingZones() + { + return HasChild(waitingZones); + } + + // + int CountWaitingZones() + { + return ArraySize(waitingZones); + } + + // + bool HasInsideZones() + { + return HasChild(insideZones); + } + + // + int CountInsideZones() + { + return ArraySize(insideZones); + } + + // + bool HasBreakedZones() + { + return HasChild(breakedZones); + } + + // + int CountBreakedZones() + { + return ArraySize(breakedZones); + } + + // + bool HasConsolidationZones() + { + return HasChild(consolidationZones); + } + + // + int CountConsolidationZones() + { + return ArraySize(consolidationZones); + } + + // + bool HasInsideBoxes() + { + return HasChild(insideBoxes); + } + + // + int CountInsideBoxes() + { + return ArraySize(insideBoxes); + } + + // + bool HasBreakedBoxes() + { + return HasChild(breakedBoxes); + } + + // + int CountBreakedBoxes() + { + return ArraySize(breakedBoxes); + } + + // + // + // + + // + bool IsDestroyed( + int barIndex = 0, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init( + symbol, + period, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + XOHCL cBar; + result = bar.GetPreviousBar(cBar); + if (!result) + { + // + bar.Clean(); + cBar.Clean(); + + // + return result; + } + + // + bool isSupplyZoneBreaked = + // + bar.low > supplyZone.Upper() && + cBar.low > supplyZone.Upper() + // + ; + + // + bool isDemandZoneBreaked = + // + bar.high < demandZone.Lower() && + cBar.high < demandZone.Lower() + // + ; + + // + bar.Clean(); + cBar.Clean(); + + // + result = isSupplyZoneBreaked || + isDemandZoneBreaked; + + // + return result; + } + + // + bool DetectPriority( + ENUM_X121SMC_XWZ_PRIORITY &priority, + ENUM_X_DIRECTION forDir, + int barIndex = 0, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + priority = X121SMC_XWZ_PRIORITY_NONE; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + result = IsValid() && + HasDirection(forDir); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + XOHCL bar; + result = bar.Init( + symbol, + forPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + if (bar.high < supplyZone.Upper() && + bar.low > supplyZone.Lower()) + { + // + priority = + isBullish + ? X121SMC_XWZ_PRIORITY_NONE + : X121SMC_XWZ_PRIORITY_STRONG_HIGH; + } + else if (bar.high < supplyZone.Lower() && + bar.low > quarter1) + { + // + priority = + isBullish + ? X121SMC_XWZ_PRIORITY_WEAK + : X121SMC_XWZ_PRIORITY_HIGH; + } + else if (bar.high < quarter1 && + bar.low > quarter2) + { + // + priority = + isBullish + ? X121SMC_XWZ_PRIORITY_LOW + : X121SMC_XWZ_PRIORITY_REGULAR; + } + else if (bar.high < quarter2 && + bar.low > quarter3) + { + // + priority = + isBullish + ? X121SMC_XWZ_PRIORITY_REGULAR + : X121SMC_XWZ_PRIORITY_LOW; + } + else if (bar.high < quarter3 && + bar.low > demandZone.Upper()) + { + // + priority = + isBullish + ? X121SMC_XWZ_PRIORITY_HIGH + : X121SMC_XWZ_PRIORITY_WEAK; + } + else if (bar.high < demandZone.Upper() && + bar.low > demandZone.Lower()) + { + // + priority = + isBullish + ? X121SMC_XWZ_PRIORITY_STRONG_HIGH + : X121SMC_XWZ_PRIORITY_NONE; + } + + // + result = priority != X121SMC_XWZ_PRIORITY_NONE && + priority != X121SMC_XWZ_PRIORITY_WEAK; + + // + bar.Clean(); + + // + return result; + } + + // + // + // + + // + void UpdateTo(datetime value = NULL) + { + // + value = NormalizeTime(value); + + // + int count = 0; + bool has = false; + + // + has = HasSupplyZone(); + if (has) + { + supplyZone.To(value); + } + + // + has = HasDemandZone(); + if (has) + { + demandZone.To(value); + } + + // + has = HasSupplyZones(); + if (has) + { + // + count = CountSupplyZones(); + for (int i = 0; i < count; i++) + { + supplyZones[i].To(value); + } + } + + // + has = HasDemandZones(); + if (has) + { + // + count = CountDemandZones(); + for (int i = 0; i < count; i++) + { + demandZones[i].To(value); + } + } + + // + has = HasSupportZones(); + if (has) + { + // + count = CountSupportZones(); + for (int i = 0; i < count; i++) + { + supportZones[i].To(value); + } + } + + // + has = HasResistanceZones(); + if (has) + { + // + count = CountResistanceZones(); + for (int i = 0; i < count; i++) + { + resistanceZones[i].To(value); + } + } + + // + has = HasWaitingZones(); + if (has) + { + // + count = CountWaitingZones(); + for (int i = 0; i < count; i++) + { + waitingZones[i].UpdateTo(value); + } + } + + // + has = HasInsideZones(); + if (has) + { + // + count = CountInsideZones(); + for (int i = 0; i < count; i++) + { + insideZones[i].UpdateTo(value); + } + } + + // + has = HasInsideBoxes(); + if (has) + { + // + count = CountInsideBoxes(); + for (int i = 0; i < count; i++) + { + insideBoxes[i].to = value; + } + } + + // + } + + // + void Draw( + XCPOIDrawer *drawer, + bool drawWaitingZones = true, + bool drawInsideZones = false, + bool drawBreakedZones = false, + bool drawSupplyZone = false, + bool drawDemandZone = false, + bool drawSupplyZones = false, + bool drawDemandZones = false, + bool drawSupportZones = false, + bool drawResistanceZones = false // + ) + { + // + if (drawer == NULL) + { + return; + } + + // + int count = 0; + bool has = false; + bool isCreated = false; + + // + ulong chartID = drawer.ChartIdentification(); + int subWindow = drawer.SubWindowIdentification(); + color bullishColor = drawer.BarBullishColor(); + color bearishColor = drawer.BarBearishColor(); + + // + // Supply Zone ... + if (drawSupplyZone) + { + // + has = HasSupplyZone(); + if (has) + { + // + XCSupplyZoneObject *iObj; + isCreated = drawer.CreateSupplyZone( + supplyZone, + iObj // + ); + + // + if (isCreated) + { + mWorkingZoneObjects.Add(iObj); + } + } + } + + // + // Demand Zone ... + if (drawDemandZone) + { + // + has = HasDemandZone(); + if (has) + { + // + XCDemandZoneObject *iObj; + isCreated = drawer.CreateDemandZone( + demandZone, + iObj // + ); + + // + if (isCreated) + { + mWorkingZoneObjects.Add(iObj); + } + } + } + + // + // + // + + // + // Supply Zones ... + if (drawSupplyZones) + { + // + has = HasSupplyZones(); + if (has) + { + // + count = CountSupplyZones(); + for (int i = 0; i < count; i++) + { + // + XCSupplyZoneObject *iObj; + isCreated = drawer.CreateSupplyZone( + supplyZones[i], + iObj // + ); + + // + if (isCreated) + { + mWorkingZoneObjects.Add(iObj); + } + } + } + } + + // + // Demand Zones ... + if (drawDemandZones) + { + // + has = HasDemandZones(); + if (has) + { + // + count = CountDemandZones(); + for (int i = 0; i < count; i++) + { + // + XCDemandZoneObject *iObj; + isCreated = drawer.CreateDemandZone( + demandZones[i], + iObj // + ); + + // + if (isCreated) + { + mWorkingZoneObjects.Add(iObj); + } + } + } + } + + // + // Support Zones ... + if (drawSupportZones) + { + // + has = HasSupportZones(); + if (has) + { + // + count = CountSupportZones(); + for (int i = 0; i < count; i++) + { + // + XCSupportZoneObject *iObj; + isCreated = drawer.CreateSupportZone( + supportZones[i], + iObj // + ); + + // + if (isCreated) + { + mWorkingZoneObjects.Add(iObj); + } + } + } + } + + // + // Resistance Zones ... + if (drawResistanceZones) + { + // + has = HasResistanceZones(); + if (has) + { + // + count = CountResistanceZones(); + for (int i = 0; i < count; i++) + { + // + XCResistanceZoneObject *iObj; + isCreated = drawer.CreateResistanceZone( + resistanceZones[i], + iObj // + ); + + // + if (isCreated) + { + mWorkingZoneObjects.Add(iObj); + } + } + } + } + + // + // + // + + // + // Waiting Zones ... + if (drawWaitingZones) + { + // + has = HasWaitingZones(); + if (has) + { + // + count = CountWaitingZones(); + for (int i = 0; i < count; i++) + { + // + XCBaseObject *objects[]; + int objectsCount = drawer.DrawOBFVG( + waitingZones[i], + objects // + ); + has = IsValidSize(objectsCount); + if (has) + { + // + for (int j = 0; j < objectsCount; j++) + { + mWaitingZoneObjects.Add(objects[j]); + } + } + } + } + } + + // + // Inside Zones ... + if (drawInsideZones) + { + // + // Zones ... + has = HasInsideZones(); + if (has) + { + // + count = CountInsideZones(); + for (int i = 0; i < count; i++) + { + // + XCBaseObject *objects[]; + int objectsCount = drawer.DrawOBFVG( + insideZones[i], + objects // + ); + + // + has = IsValidSize(objectsCount); + if (has) + { + // + for (int i = 0; i < objectsCount; i++) + { + mInsideZoneObjects.Add(objects[i]); + } + } + } + } + + // // + // // Boxes ... + // has = HasInsideBoxes(); + // if (has) + // { + // // + // count = CountInsideBoxes(); + // for (int i = 0; i < count; i++) + // { + // // + // XCBoxObject *object; + // bool isCreated = drawer.DrawBox( + // insideBoxes[i], + // object // + // ); + + // // + // if (isCreated) + // { + // mInsideZoneObjects.Add(object); + // } + // } + // } + } + + // + // Breaked Zones ... + if (drawBreakedZones) + { + // + has = HasBreakedZones(); + if (has) + { + // + count = CountBreakedZones(); + for (int i = 0; i < count; i++) + { + // + XCBaseObject *objects[]; + int objectsCount = drawer.DrawOBFVG( + breakedZones[i], + objects // + ); + + // + has = IsValidSize(objectsCount); + if (has) + { + // + for (int i = 0; i < objectsCount; i++) + { + mBreakedZoneObjects.Add(objects[i]); + } + } + } + } + + // // + // // Boxes ... + // has = HasBreakedBoxes(); + // if (has) + // { + // // + // count = CountBreakedBoxes(); + // for (int i = 0; i < count; i++) + // { + // // + // XCBoxObject *object; + // bool isCreated = drawer.DrawBox( + // breakedBoxes[i], + // object // + // ); + + // // + // if (isCreated) + // { + // mInsideZoneObjects.Add(object); + // } + // } + // } + } + + // + // + // + + // + // Quarters ... + has = IsValid(); + if (has) + { + // + double zoneUpper = supplyZone.Upper(); + double upper = supplyZone.Lower(); + + // + double lower = demandZone.Upper(); + double zoneLower = demandZone.Lower(); + + // + string prefix = "X121WZone_" + symbol + "_" + ToString(period); + + // + // Zone Upper ... + CChartObjectHLine *zoneUpperLine; + zoneUpperLine = new CChartObjectHLine(); + isCreated = zoneUpperLine.Create( + chartID, + prefix + "_ZoneTop", + subWindow, + zoneUpper // + ); + if (isCreated) + { + // + zoneUpperLine.Color(clrRed); + + // + mWaitingZoneObjects.Add(zoneUpperLine); + } + + // + // Zone Lower ... + CChartObjectHLine *zoneLowerLine; + zoneLowerLine = new CChartObjectHLine(); + isCreated = zoneLowerLine.Create( + chartID, + prefix + "_ZoneDown", + subWindow, + zoneLower // + ); + if (isCreated) + { + // + zoneLowerLine.Color(clrRed); + + // + mWaitingZoneObjects.Add(zoneLowerLine); + } + + // + // Upper ... + CChartObjectHLine *upperLine; + upperLine = new CChartObjectHLine(); + isCreated = upperLine.Create( + chartID, + prefix + "_Upper", + subWindow, + upper // + ); + if (isCreated) + { + // + upperLine.Color(clrLime); + + // + mWaitingZoneObjects.Add(upperLine); + } + + // + // Lower ... + CChartObjectHLine *lowerLine; + lowerLine = new CChartObjectHLine(); + isCreated = lowerLine.Create( + chartID, + prefix + "_Lower", + subWindow, + lower // + ); + if (isCreated) + { + // + lowerLine.Color(clrLime); + + // + mWaitingZoneObjects.Add(lowerLine); + } + + // + // Quarters ... + + // + // Quarter 1 ... + CChartObjectHLine *q1Line; + q1Line = new CChartObjectHLine(); + isCreated = q1Line.Create( + chartID, + prefix + "_Q1", + subWindow, + quarter1 // + ); + if (isCreated) + { + // + q1Line.Color(clrYellow); + + // + mWaitingZoneObjects.Add(q1Line); + } + + // + // Quarter 2 ... + CChartObjectHLine *q2Line; + q2Line = new CChartObjectHLine(); + isCreated = q2Line.Create( + chartID, + prefix + "_Q2", + subWindow, + quarter2 // + ); + if (isCreated) + { + // + q2Line.Color(clrYellow); + + // + mWaitingZoneObjects.Add(q2Line); + } + + // + // Quarter 3 ... + CChartObjectHLine *q3Line; + q3Line = new CChartObjectHLine(); + isCreated = q3Line.Create( + chartID, + prefix + "_Q3", + subWindow, + quarter3 // + ); + if (isCreated) + { + // + q3Line.Color(clrYellow); + + // + mWaitingZoneObjects.Add(q3Line); + } + } + } + + // +}; + +////////////////////////////////////////////////////// + +/** + * Detect Targets Based on Selected Zone for Specified type of Directions ... + * + * @param targets: double Collection ... + * @param selectedZone: XOBFVG instance, selected Zone ... + * @param forDir: ENUM_X_DIRECTION specified Position Direction ... + * @param workingone: X121SMCStrategyXWZWorkingZone instance, Specified Working Zone ... + * @param barIndex: int Specified Bar Index ... + * + * @return ( bool ) + */ +bool DetectSelectedZonesTargets( + double &targets[], + XOBFVG &selectedZone, + ENUM_X_DIRECTION forDir, + ENUM_X121SMC_XWZ_PRIORITY forPriority, + X121SMCStrategyXWZWorkingZone &workingZone, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + Clean(targets); + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (barIndex == 0) + { + barIndex++; + } + + // + result = + // + selectedZone.IsValid() && + HasDirection(forDir) && + workingZone.IsValid() && + forPriority != X121SMC_XWZ_PRIORITY_NONE + // + ; + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + XOHCL cBar; + result = cBar.Init( + workingZone.symbol, + workingZone.period, + barIndex // + ); + if (!result) + { + // + cBar.Clean(); + return result; + } + + // + int idx = -1; + bool has = false; + + // + // Based On Priority ... + has = forPriority != X121SMC_XWZ_PRIORITY_NONE; + if (has) + { + // + switch (forPriority) + { + // + case X121SMC_XWZ_PRIORITY_WEAK: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + } + break; + + // + case X121SMC_XWZ_PRIORITY_LOW: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter1, + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter3, + targets // + ); + } + break; + + // + case X121SMC_XWZ_PRIORITY_REGULAR: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter1, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter3, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + } + break; + + // + case X121SMC_XWZ_PRIORITY_HIGH: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter1, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + + // + // High ... + Add( + workingZone.quarter3, + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter3, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + + // + // High ... + Add( + workingZone.quarter1, + targets // + ); + } + break; + + // + case X121SMC_XWZ_PRIORITY_STRONG_HIGH: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter1, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + + // + // High ... + Add( + workingZone.quarter3, + targets // + ); + + // + // Strong High ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter3, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + + // + // High ... + Add( + workingZone.quarter1, + targets // + ); + + // + // Strong High ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + } + break; + } + } + + // + result = HasChild(targets); + + // + // Cleanup ... + cBar.Clean(); + Clean(tmpZones); + + // + return result; +} + +///////////////////////////////////////////////////////////// + +/** + * Check an XOBFVG instance has Required Conditions ... + * + * @param zone: XOBFVG instance ... + * @param state: XPOIState instance ... + * @param conditions: X121Conditions instance ... + * + * @return ( bool ) + */ +bool DetectInsideSelectedZoneConditions( + bool &isReversal, + XOBFVG &zone, + XPOIState &state, + X121Conditions &conditions, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + isReversal = false; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (barIndex == 0) + { + barIndex++; + } + + // + XOHCL bar; + result = bar.Init( + state.symbol, + state.period, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + result = + zone.IsValid() && + state.IsValid() && + state.HasChild(); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + bool isBullish = zone.IsBullish(); + bool isBearish = zone.IsBearish(); + + // + double points = GetPoints(bar.symbol); + + // + double bullishScore = 0; + double bearishScore = 0; + double scoreMultiplier = 1.5; + conditions.GenerateScore( + bullishScore, + bearishScore // + ); + + // // + // bool isLowerBreaked = + // // + // conditions.isSarBearish && + // conditions.isCheBearish && + // bar.high < zone.ob.Lower() && + // bearishScore > bullishScore && + // conditions.isX3MaBearishState && + // conditions.isVWapBearishState && + // conditions.isX3MaBearishOrdered && + // conditions.isVWapBearishOrdered && + // bar.low < conditions.atrLowerBuffer[1] && + // conditions.atrLowerBuffer[1] < zone.ob.Lower() + // // + // ; + + // // + // bool isUpperBreaked = + // // + // conditions.isSarBullish && + // conditions.isCheBullish && + // bar.low > zone.ob.Upper() && + // bullishScore > bearishScore && + // conditions.isX3MaBullishState && + // conditions.isVWapBullishState && + // conditions.isX3MaBullishOrdered && + // conditions.isVWapBullishOrdered && + // bar.high > conditions.atrUpperBuffer[1] && + // conditions.atrUpperBuffer[1] > zone.ob.Upper() + // // + // ; + + // // + // bool isPeakEqualsToUpper = + // MathAbs(conditions.peaksBuffer[0] - zone.ob.Upper()) > points * 1; + + // // + // bool isValeEqualsToLower = + // MathAbs(conditions.valesBuffer[0] - zone.ob.Lower()) > points * 1; + + // + // bool isDirectionalBullishPassed = + // // + // isBullish && + // isUpperBreaked + // // ( + + // // || + // // isValeEqualsToLower) + // // + // ; + + // + // bool isDirectionalBearishPassed = + // // + // isBearish && + // isLowerBreaked + // // || + // // isPeakEqualsToUpper) + // // + // ; + + // + // bool isDirectionalPassed = + // isDirectionalBullishPassed || + // isDirectionalBearishPassed; + + // // + // bool isReversalBullishPassed = + // // + // // isBullish && + // // isLowerBreaked + // // ( || + // // isPeakEqualsToUpper) + // // + // ; + + // // + // bool isReversalBearishPassed = + // // + // // isBearish && + // // isUpperBreaked + // // || + // // isValeEqualsToLower) + // // + // ; + + // + // bool isReversalPassed = isReversalBullishPassed || + // isReversalBearishPassed; + + // + // result = isReversalPassed || + // isDirectionalPassed; + + // + result = false; + + // + if (result) + { + // isReversal = isReversalPassed; + } + + // + bar.Clean(); + return result; +} + +bool DetectBreakedSelectedZoneConditions( + bool &isReversal, + XOBFVG &zone, + XPOIState &mtfState, + XPOIState &stfState, + XPOIState &ttfState, + X121Conditions &conditions // +) +{ + // + bool result = false; + + // + isReversal = false; + + // + result = + // + zone.IsValid() && + mtfState.IsValid() && + stfState.IsValid() && + ttfState.IsValid() && + mtfState.HasChild() && + stfState.HasChild() && + ttfState.HasChild() + // + ; + if (!result) + { + return result; + } + + // + XBoxZone iBox; + result = ToBox( + iBox, + zone.ob // + ); + if (!result) + { + return result; + } + + // + ENUM_X_DIRECTION iDir = iBox.dir; + bool isBullish = IsBullish(iDir); + bool isBearish = IsBearish(iDir); + + // + // X3Ma ... + + // + double x3maFast = conditions.x3maFastBuffer[0]; + double x3maMid = conditions.x3maMidBuffer[0]; + double x3maSlow = conditions.x3maSlowBuffer[0]; + + // + bool isX3mInside = + // + (x3maFast < iBox.upper && + x3maMid < iBox.upper && + x3maSlow < iBox.upper) + // + && + // + (x3maFast > iBox.lower && + x3maMid > iBox.lower && + x3maSlow > iBox.lower) + // + ; + + // + bool isBullishConditions = + isBullish && + isX3mInside; + + // + bool isBearishConditions = + isBearish && + isX3mInside; + + // + result = isBullishConditions || + isBearishConditions; + + // + return result; +} + +/** + * Detect SL Candidates Based on Selected Zone for Specified type of Directions ... + * + * @param sls: double Collection ... + * @param selectedZone: XOBFVG instance, selected Zone ... + * @param forDir: ENUM_X_DIRECTION specified Position Direction ... + * @param workingZone: X121SMCStrategyXWZWorkingZone instance, Specified Working Zone ... + * @param barIndex: int Specified Bar Index ... + * @param maxAllowedSLDistanceInPoint: doube max Allowe SL distance ... + * + * @return ( bool ) + */ +bool DetectSelectedZoneSLCandidates( + double &sls[], + XOBFVG &selectedZone, + ENUM_X_DIRECTION forDir, + X121SMCStrategyXWZWorkingZone &workingZone, + X121Conditions &conditions, + int barIndex = 0, + double maxAllowedSLDistanceInPoint = 300 // +) +{ + // + bool result = false; + + // + Clean(sls); + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (barIndex == 0) + { + barIndex++; + } + + // + result = + // + selectedZone.IsValid() && + HasDirection(forDir) && + workingZone.IsValid() + // + ; + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + double pivot = + isBullish + ? selectedZone.ob.Lower() + : selectedZone.ob.Upper(); + double points = GetPoints(workingZone.symbol); + + // + XOHCL cBar; + result = cBar.Init( + workingZone.symbol, + workingZone.period, + barIndex // + ); + if (!result) + { + // + cBar.Clean(); + return result; + } + + // + int idx = -1; + bool has = false; + + // // + // double pvSL = isBullish + // ? conditions.valesBuffer[0] + // : conditions.peaksBuffer[1]; + + // // + // Add( + // pvSL, + // sls // + // ); + + // + // Based On Passed Bars ... + // XOHCL passedBar; + // bool isPassed = false; + // bool isBodyState = false; + // ENUM_X_DIRECTION passedDir = selectedZone.GetDirection(); + + // // + // // Started Bar ... + // isPassed = selectedZone.ob.IsStarted( + // passedDir, + // passedBar, + // isBodyState // + // ); + // if (isPassed) + // { + // // + // double iSL = + // isBullish + // ? passedBar.low + // : passedBar.high; + // double iSLDiff = MathAbs(iSL - pivot); + // has = + // iSLDiff > 0 && + // iSLDiff <= maxAllowedSLDistanceInPoint * points; + // if (has) + // { + // // + // Add( + // iSL, + // sls // + // ); + // } + // } + + // // + // // Activation Bar ... + // passedBar.Clean(); + // isPassed = selectedZone.ob.IsActivated( + // passedDir, + // passedBar, + // isBodyState // + // ); + // if (isPassed) + // { + // // + // double iSL = + // isBullish + // ? passedBar.low + // : passedBar.high; + // double iSLDiff = MathAbs(iSL - pivot); + // has = + // iSLDiff > 0 && + // iSLDiff <= maxAllowedSLDistanceInPoint * points; + // if (has) + // { + // // + // Add( + // iSL, + // sls // + // ); + // } + // } + + // // + // // Worked Bar ... + // passedBar.Clean(); + // isPassed = selectedZone.ob.IsActivated( + // passedDir, + // passedBar, + // isBodyState // + // ); + // if (isPassed) + // { + // // + // double iSL = + // isBullish + // ? passedBar.low + // : passedBar.high; + // double iSLDiff = MathAbs(iSL - pivot); + // has = + // iSLDiff > 0 && + // iSLDiff <= maxAllowedSLDistanceInPoint * points; + // if (has) + // { + // // + // Add( + // iSL, + // sls // + // ); + // } + // } + + // // + // // Breaked Bar ... + // passedBar.Clean(); + // isPassed = selectedZone.ob.IsActivated( + // passedDir, + // passedBar, + // isBodyState // + // ); + // if (isPassed) + // { + // // + // double iSL = + // isBullish + // ? passedBar.low + // : passedBar.high; + // double iSLDiff = MathAbs(iSL - pivot); + // has = + // iSLDiff > 0 && + // iSLDiff <= maxAllowedSLDistanceInPoint * points; + // if (has) + // { + // // + // Add( + // iSL, + // sls // + // ); + // } + // } + + // + // Based On Consolidation Zones ... + // has = workingZone.HasConsolidationZones(); + // if (has) + // { + // // + // XConsolidationZone tmpZones[]; + // Copy( + // workingZone.consolidationZones, + // tmpZones // + // ); + // XConsolidationZone selectedConsolidationZone; + + // // + // while (HasChild(tmpZones)) + // { + // // + // idx = GetYoungest(tmpZones); + // if (!IsValidIndex(idx)) + // { + // break; + // } + + // // + // XConsolidationZone iZone = tmpZones[idx]; + + // // + // ArrayRemove( + // tmpZones, + // idx, + // 1 // + // ); + + // // + // has = + // !selectedConsolidationZone.IsValid() + // ? isBullish + // ? cBar.low < iZone.upper + // : cBar.high < iZone.lower + // : isBullish + // ? selectedConsolidationZone.lower < iZone.lower + // : selectedConsolidationZone.upper > iZone.upper; + // if (has) + // { + // // + // selectedConsolidationZone = iZone; + // iZone.Clean(); + // break; + // } + + // // + // iZone.Clean(); + // } + + // // + // Clean(tmpZones); + // has = selectedConsolidationZone.IsValid(); + // if (has) + // { + // // + // double iSL = + // isBullish + // ? selectedConsolidationZone.lower + // : selectedConsolidationZone.upper; + // double iSLDiff = MathAbs(iSL - pivot); + // has = + // iSLDiff > 0 && + // iSLDiff <= maxAllowedSLDistanceInPoint * points; + // if (has) + // { + // // + // Add( + // iSL, + // sls // + // ); + // } + // } + // } + + // + // Based On Supply and Demand Zones ... + + // + // Demand Zones ... + // has = workingZone.HasDemandZones(); + // if (has) + // { + // // + // XCDemandZone *tmpZones[]; + // Copy( + // workingZone.demandZones, + // tmpZones // + // ); + // XCDemandZone *selectedDemand = NULL; + + // // + // while (HasChild(tmpZones)) + // { + // // + // idx = GetLowest(tmpZones); + // has = IsValidIndex(idx); + // if (!has) + // { + // break; + // } + + // // + // XCDemandZone *iZone = tmpZones[idx]; + // ArrayRemove( + // tmpZones, + // idx, + // 1 // + // ); + + // // + // // Validate Zone ... + // has = + // isBullish + // ? IsBelowDiff( + // iZone, + // selectedZone.ob, + // true // Ignore Inside ... + // ) + // : IsAboveDiff( + // iZone, + // selectedZone.ob, + // true // Ignore Inside ... + // ); + // if (!has) + // { + // continue; + // } + + // // + // has = + // selectedDemand == NULL + // ? true + // : isBullish + // ? selectedDemand.Lower() < iZone.Lower() + // : selectedDemand.Upper() > iZone.Upper(); + // if (!has) + // { + // continue; + // } + + // // + // selectedDemand = iZone; + // } + + // // + // has = selectedDemand != NULL; + // if (has) + // { + // // + // double iSL = + // isBullish + // ? selectedDemand.Lower() + // : selectedDemand.Upper(); + // double iSLDiff = MathAbs(iSL - pivot); + // has = + // iSLDiff > 0 && + // iSLDiff <= maxAllowedSLDistanceInPoint * points; + // if (has) + // { + // // + // Add( + // iSL, + // sls // + // ); + // } + // } + + // // + // Clean(tmpZones); + // ZeroMemory(selectedDemand); + // } + + // + // Support Zones ... + // has = workingZone.HasSupportZones(); + // if (has) + // { + // // + // XCSupportZone *tmpZones[]; + // Copy( + // workingZone.supportZones, + // tmpZones // + // ); + // XCSupportZone *selectedSupport = NULL; + + // // + // while (HasChild(tmpZones)) + // { + // // + // idx = GetLowest(tmpZones); + // has = IsValidIndex(idx); + // if (!has) + // { + // break; + // } + + // // + // XCSupportZone *iZone = tmpZones[idx]; + // ArrayRemove( + // tmpZones, + // idx, + // 1 // + // ); + + // // + // // Validate Zone ... + // has = + // isBullish + // ? IsBelowDiff( + // iZone, + // selectedZone.ob, + // true // Ignore Inside ... + // ) + // : IsAboveDiff( + // iZone, + // selectedZone.ob, + // true // Ignore Inside ... + // ); + // if (!has) + // { + // continue; + // } + + // // + // has = + // selectedSupport == NULL + // ? true + // : isBullish + // ? selectedSupport.Lower() < iZone.Lower() + // : selectedSupport.Upper() > iZone.Upper(); + // if (!has) + // { + // continue; + // } + + // // + // selectedSupport = iZone; + + // // + // } + + // // + // has = selectedSupport != NULL; + // if (has) + // { + // // + // double iSL = isBullish + // ? selectedSupport.Lower() + // : selectedSupport.Upper(); + // double iSLDiff = MathAbs(iSL - pivot); + // has = + // iSLDiff > 0 && + // iSLDiff <= maxAllowedSLDistanceInPoint * points; + // if (has) + // { + // // + // Add( + // iSL, + // sls // + // ); + // } + // } + + // // + // Clean(tmpZones); + // ZeroMemory(selectedSupport); + // } + + // + // Supply Zones ... + // has = workingZone.HasSupplyZones(); + // if (has) + // { + // // + // XCSupplyZone *tmpZones[]; + // Copy( + // workingZone.supplyZones, + // tmpZones // + // ); + // XCSupplyZone *selectedSupply = NULL; + + // // + // while (HasChild(tmpZones)) + // { + // // + // idx = GetHighest(tmpZones); + // has = IsValidIndex(idx); + // if (!has) + // { + // break; + // } + + // // + // XCSupplyZone *iZone = tmpZones[idx]; + // ArrayRemove( + // tmpZones, + // idx, + // 1 // + // ); + + // // + // // Validate Zone ... + // has = + // !isBullish + // ? IsAboveDiff( + // iZone, + // selectedZone.ob, + // true // Ignore Inside ... + // ) + // : IsBelowDiff( + // iZone, + // selectedZone.ob, + // true // Ignore Inside ... + // ); + // if (!has) + // { + // continue; + // } + + // // + // has = + // selectedSupply == NULL + // ? true + // : !isBullish + // ? selectedSupply.Upper() > iZone.Upper() + // : selectedSupply.Lower() < iZone.Lower(); + // if (!has) + // { + // continue; + // } + + // // + // selectedSupply = iZone; + + // // + // } + + // // + // has = selectedSupply != NULL; + // if (has) + // { + // // + // double iSL = + // !isBullish + // ? selectedSupply.Upper() + // : selectedSupply.Lower(); + // double iSLDiff = MathAbs(iSL - pivot); + // has = + // iSLDiff > 0 && + // iSLDiff <= maxAllowedSLDistanceInPoint * points; + // if (has) + // { + // // + // Add( + // iSL, + // sls // + // ); + // } + // } + + // // + // Clean(tmpZones); + // ZeroMemory(selectedSupply); + // } + + // + // Resistance Zones ... + // has = workingZone.HasDemandZones(); + // if (has) + // { + // // + // XCResistanceZone *tmpZones[]; + // Copy( + // workingZone.resistanceZones, + // tmpZones // + // ); + // XCResistanceZone *selectedResistance = NULL; + + // // + // while (HasChild(tmpZones)) + // { + // // + // idx = GetHighest(tmpZones); + // has = IsValidIndex(idx); + // if (!has) + // { + // break; + // } + + // // + // XCResistanceZone *iZone = tmpZones[idx]; + // ArrayRemove( + // tmpZones, + // idx, + // 1 // + // ); + + // // + // // Validate Zone ... + // has = + // !isBullish + // ? IsAboveDiff( + // iZone, + // selectedZone.ob, + // true // Ignore Inside ... + // ) + // : IsBelowDiff( + // iZone, + // selectedZone.ob, + // true // Ignore Inside ... + // ); + // if (!has) + // { + // continue; + // } + + // // + // has = + // selectedResistance == NULL + // ? true + // : !isBullish + // ? selectedResistance.Upper() < iZone.Upper() + // : selectedResistance.Lower() > iZone.Lower(); + // if (!has) + // { + // continue; + // } + + // // + // selectedResistance = iZone; + + // // + // } + + // // + // has = selectedResistance != NULL; + // if (has) + // { + // // + // double iSL = + // !isBullish + // ? selectedResistance.Upper() + // : selectedResistance.Lower(); + // double iSLDiff = MathAbs(iSL - pivot); + // has = + // iSLDiff > 0 && + // iSLDiff <= maxAllowedSLDistanceInPoint * points; + // if (has) + // { + // // + // Add( + // iSL, + // sls // + // ); + // } + // } + + // // + // Clean(tmpZones); + // ZeroMemory(selectedResistance); + // } + + // + // Cleanp Resources ... + + // + cBar.Clean(); + // passedBar.Clean(); + result = HasChild(sls); + + // + return result; +} + +///////////////////////////////////////////////////////////////////////// + +// +// Support Zones ... +// has = HasSupportZones(); +// if (has) +// { +// // +// int removeIDXs[]; +// count = CountSupportZones(); +// for (int i = 0; i < count; i++) +// { +// // +// XCSupportZone *iZone = supportZones[i]; +// ENUM_X_DIRECTION iDir = X_DIRECTION_BULLISH; + +// // +// XBoxZone iBox; +// bool hasBox = ToBox( +// iBox, +// iZone // +// ); +// if (!hasBox) +// { +// // +// iBox.Clean(); +// continue; +// } + +// // +// XOHCL passedBar; +// bool isBodyIn = false; +// bool isBodyOut = false; + +// // +// // Check Activation ... +// bool isActivated = iZone.IsActivated( +// iDir, +// passedBar, +// isBodyIn, +// true, +// period // +// ); +// if (isActivated) +// { +// // +// // AddRef( +// // iBox, +// // insideBoxes // +// // ); + +// // +// Add( +// i, +// removeIDXs // +// ); + +// // +// iBox.Clean(); +// passedBar.Clean(); +// continue; +// } + +// // +// // Checking Breaked ... +// bool isBreaked = iZone.IsBreaked( +// iDir, +// passedBar, +// isBodyOut, +// false, +// true, +// period // +// ); +// if (isBreaked) +// { +// // // +// // AddRef( +// // iBox, +// // breakedBoxes // +// // ); + +// // +// Add( +// i, +// removeIDXs // +// ); + +// // +// iBox.Clean(); +// passedBar.Clean(); +// continue; +// } + +// // +// passedBar.Clean(); +// } + +// // +// count = ArraySize(removeIDXs); +// has = IsValidSize(count); +// if (has) +// { +// // +// CleanupArray( +// removeIDXs, +// supportZones // +// ); +// } + +// // +// Clean(removeIDXs); +// } + +// +// Resistance Zones ... +// has = HasResistanceZones(); +// if (has) +// { +// // +// int removeIDXs[]; +// count = CountResistanceZones(); +// for (int i = 0; i < count; i++) +// { +// // +// XCResistanceZone *iZone = resistanceZones[i]; +// ENUM_X_DIRECTION iDir = X_DIRECTION_BEARISH; + +// // +// XBoxZone iBox; +// bool hasBox = ToBox( +// iBox, +// iZone // +// ); +// if (!hasBox) +// { +// // +// iBox.Clean(); +// continue; +// } + +// // +// XOHCL passedBar; +// bool isBodyIn = false; +// bool isBodyOut = false; + +// // +// // Check Activation ... +// bool isActivated = iZone.IsActivated( +// iDir, +// passedBar, +// isBodyIn, +// true, +// period // +// ); +// if (isActivated) +// { +// // +// // AddRef( +// // iBox, +// // insideBoxes // +// // ); + +// // +// Add( +// i, +// removeIDXs // +// ); + +// // +// iBox.Clean(); +// passedBar.Clean(); +// continue; +// } + +// // +// // Checking Breaked ... +// bool isBreaked = iZone.IsBreaked( +// iDir, +// passedBar, +// isBodyOut, +// false, +// true, +// period // +// ); +// if (isBreaked) +// { +// // // +// // AddRef( +// // iBox, +// // breakedBoxes // +// // ); + +// // +// Add( +// i, +// removeIDXs // +// ); + +// // +// iBox.Clean(); +// passedBar.Clean(); +// continue; +// } + +// // +// passedBar.Clean(); +// } + +// // +// count = ArraySize(removeIDXs); +// has = IsValidSize(count); +// if (has) +// { +// // +// CleanupArray( +// removeIDXs, +// resistanceZones // +// ); +// } + +// // +// Clean(removeIDXs); +// } + +//////////////////////////////////////////////////////// + +// +// Waiting Zone Detection ... +// XPOIState iState = mtfState; + +// +// Detect Waiting Zones ... + +// // +// // Using Order Blocks ... +// if (mUseOrderBlocks) +// { +// // +// has = iState.HasOrderBlocks(); +// if (has) +// { +// // +// XCOrderBlock *obs[]; +// count = iState.FilterOrderBlocks( +// obs, +// period, +// XZONE_STATE_PASSED, +// false, +// XZONE_STATE_FAILED, +// false, +// XZONE_STATE_FAILED, +// false, +// XZONE_STATE_IGNORED, +// false // +// ); + +// // +// has = IsValidSize(count); +// if (has) +// { +// // +// ToBox( +// obs, +// waitingBoxes // +// ); +// } + +// // +// Clean(obs); +// } +// } + +// // +// // Using Fair Value Gaps ... +// if (mUseFairValueGaps) +// { +// // +// has = iState.HasFairValueGaps(); +// if (has) +// { +// // +// XBoxZone boxes[]; +// XCFVG *fvgs[]; +// count = iState.FilterFairValueGaps( +// fvgs, +// period, +// XZONE_STATE_PASSED, +// false, +// XZONE_STATE_FAILED, +// false, +// XZONE_STATE_FAILED, +// false, +// XZONE_STATE_IGNORED, +// false // +// ); + +// // +// has = IsValidSize(count); +// if (has) +// { +// // +// count = ToBox( +// fvgs, +// boxes // +// ); + +// // +// for (int i = 0; i < count; i++) +// { +// // +// XBoxZone iBox = boxes[i]; + +// // +// int idx = FindIndex( +// iBox, +// waitingBoxes // +// ); +// has = !IsValidIndex(idx); +// if (has) +// { +// // +// AddRef( +// iBox, +// waitingBoxes // +// ); +// } + +// // +// iBox.Clean(); +// } +// } + +// // +// Clean(fvgs); +// Clean(boxes); +// } +// } + +// +// Cleaning State ... +// iState.Clean(); + +/////////////////////////////////////////////////////////////////////////// + +// +// Waiting Box Detected ... +bool hasWaitingBoxes = hasWorkingZone && + workingZone.HasWaitingBoxes(); +if (hasWaitingBoxes) +{ + // + XOHCL zBar; + XOHCL cBar; + XOHCL pBar; + int count = 0; + int idx = -1; + bool has = false; + + // + bool isInited = zBar.Init( + symbol, + period, + zIndex // + ); + isInited = + isInited && + zBar.GetPreviousBar(cBar); + isInited = + isInited && + cBar.GetPreviousBar(pBar); + + // + count = workingZone.CountWaitingBoxes(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = workingZone.waitingBoxes[i]; + ENUM_X_DIRECTION iDir = iBox.dir; + bool isBullish = IsBullish(iDir); + + // + // Check Price Rejection ... + + // + bool hasBullishFiboPressure = + decisionCycleHelper + .mBarAnalyser + .HasFiboPressure( + cBar, + X_DIRECTION_BULLISH, + X_FIBO_LEVEL_382 // + ); + + // + bool hasBearishFiboPressure = + decisionCycleHelper + .mBarAnalyser + .HasFiboPressure( + cBar, + X_DIRECTION_BEARISH, + X_FIBO_LEVEL_382 // + ); + + // + // Bullish Rejection ... + bool isBullishRejected = + // + isInited && + isBullish && + cBar.low < pBar.low && + zBar.low > iBox.upper && + cBar.low <= iBox.upper && + zBar.open > iBox.upper && + hasBullishFiboPressure && + cBar.GetLowShadow() > pBar.GetLowShadow() + // + ; + + // + // Bearish Rejection ... + bool isBearishhRejected = + // + isInited && + !isBullish && + cBar.high > pBar.high && + zBar.open < iBox.lower && + zBar.high < iBox.lower && + hasBearishFiboPressure && + cBar.high >= iBox.lower && + cBar.GetHighShadow() > pBar.GetHighShadow() + // + ; + + // + has = isBullishRejected || + isBearishhRejected; + if (has) + { + // + idx = i; + signalBox = iBox; + hasSignalBox = has; + signalBox.to = cTime; + signalBoxDir = iBox.dir; + isSignalBoxReversal = false; + provider = X121SMC_XWZ_PROVIDER_ACTIVATED_ZONE; + } + + // + iBox.Clean(); + } + + // + // Remove Signal Box from Waiting Boxes of + // Working Zone ... + if (hasSignalBox) + { + // + if (IsValidIndex(idx)) + { + // + ArrayRemove( + workingZone.waitingBoxes, + idx, + 1 // + ); + } + } + + // + // Ignore Zone's Signals ... + hasSignalBox = false; + + // + // Cleanup Resources ... + + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); +} + +// +// Check Conditions if Has Inside Boxes ... +bool hasInsideBoxes = hasWorkingZone && + workingZone.HasInsideBoxes(); +if (hasInsideBoxes) +{ +} + +// +// Check Conditions if has Breaked Boxes ... +bool hasBreakedBoxes = hasWorkingZone && + workingZone.HasBreakedBoxes(); +if (hasBreakedBoxes) +{ +} + +// +// Checking Other Conditions ... +if (!hasSignalBox) +{ + // + // Senari A ... + // hasSignalBox = hasWorkingZone && + // workingZone.DetectSenarioASignalBox( + // signalBox, + // signalBoxDir, + // decisionXConditions, + // analyseXConditions, + // decisionCycleHelper, + // drawer, + // zIndex // + // ); + // if (hasSignalBox) + // { + // // + // signalBox.to = cTime; + // isSignalBoxReversal = false; + // provider = X121SMC_XWZ_PROVIDER_PV_ZONE; + // } + + // // + // // Validating Signal Box if Exists ... + // if (hasSignalBox) + // { + // // + // // Validate Signal Boxes using Inside Box ... + // if (hasInsideBoxes) + // { + // // + // int idx = -1; + // bool has = false; + + // // + // idx = + // IsBullish(signalBoxDir) + // ? GetLowest(workingZone.insideBoxes) + // : GetHighest(workingZone.insideBoxes); + // has = IsValidIndex(idx); + // if (has) + // { + // // + // hasSignalBox = + // signalBoxDir == workingZone.insideBoxes[idx].dir; + // } + // } + + // // + // // Validate Signal Box Using Overal Trend ... + // if (hasWorkingZoneOveralDirection) + // { + // // + // hasSignalBox = + // signalBoxDir == wzOveralDir; + // } + // } +} + +////////////////////////////////////////////////////////////////////////////////// + +// +// +// + +// +// Supply Zones ... +has = HasSupplyZones(); +if (has) +{ + // + int removeIDXs[]; + count = CountSupplyZones(); + for (int i = 0; i < count; i++) + { + // + XCSupplyZone *iZone = supplyZones[i]; + ENUM_X_DIRECTION iDir = X_DIRECTION_BEARISH; + + // + XBoxZone iBox; + bool hasBox = ToBox( + iBox, + iZone // + ); + if (!hasBox) + { + // + iBox.Clean(); + continue; + } + + // + XOHCL passedBar; + bool isBodyIn = false; + bool isBodyOut = false; + + // + // Check Activation ... + bool isActivated = iZone.IsActivated( + iDir, + passedBar, + isBodyIn, + true, + period // + ); + if (isActivated) + { + // + // AddRef( + // iBox, + // insideBoxes // + // ); + + // + Add( + i, + removeIDXs // + ); + + // + iBox.Clean(); + passedBar.Clean(); + continue; + } + + // + // Checking Breaked ... + bool isBreaked = iZone.IsBreaked( + iDir, + passedBar, + isBodyOut, + false, + true, + period // + ); + if (isBreaked) + { + // // + // AddRef( + // iBox, + // breakedBoxes // + // ); + + // + Add( + i, + removeIDXs // + ); + + // + iBox.Clean(); + passedBar.Clean(); + continue; + } + + // + passedBar.Clean(); + } + + // + count = ArraySize(removeIDXs); + has = IsValidSize(count); + if (has) + { + // + CleanupArray( + removeIDXs, + supplyZones // + ); + } + + // + Clean(removeIDXs); +} + +// +// Demand Zones ... +has = HasDemandZones(); +if (has) +{ + // + int removeIDXs[]; + count = CountDemandZones(); + for (int i = 0; i < count; i++) + { + // + XCDemandZone *iZone = demandZones[i]; + ENUM_X_DIRECTION iDir = X_DIRECTION_BULLISH; + + // + XBoxZone iBox; + bool hasBox = ToBox( + iBox, + iZone // + ); + if (!hasBox) + { + // + iBox.Clean(); + continue; + } + + // + XOHCL passedBar; + bool isBodyIn = false; + bool isBodyOut = false; + + // + // Check Activation ... + bool isActivated = iZone.IsActivated( + iDir, + passedBar, + isBodyIn, + true, + period // + ); + if (isActivated) + { + // + // AddRef( + // iBox, + // insideBoxes // + // ); + + // + Add( + i, + removeIDXs // + ); + + // + iBox.Clean(); + passedBar.Clean(); + continue; + } + + // + // Checking Breaked ... + bool isBreaked = iZone.IsBreaked( + iDir, + passedBar, + isBodyOut, + false, + true, + period // + ); + if (isBreaked) + { + // // + // AddRef( + // iBox, + // breakedBoxes // + // ); + + // + Add( + i, + removeIDXs // + ); + + // + iBox.Clean(); + passedBar.Clean(); + continue; + } + + // + passedBar.Clean(); + } + + // + count = ArraySize(removeIDXs); + has = IsValidSize(count); + if (has) + { + // + CleanupArray( + removeIDXs, + demandZones // + ); + } + + // + Clean(removeIDXs); +} + +// +// Update Boxes ... + +// +// Waiting Boxes ... +has = HasWaitingBoxes(); +if (has) +{ + // + int removeIDXs[]; + count = CountWaitingBoxes(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = waitingBoxes[i]; + ENUM_X_DIRECTION iDir = iBox.dir; + bool isBullish = IsBullish(iDir); + + // + bool isInside = + // + zBar.low < iBox.upper && + zBar.low > iBox.lower + // + ; + if (isInside) + { + // + AddRef( + iBox, + insideBoxes // + ); + + // + Add( + i, + removeIDXs // + ); + + // + iBox.Clean(); + break; + } + + // + bool isBreakedUpper = + // + cBar.low < iBox.upper && + cBar.low > iBox.lower && + zBar.low > iBox.upper + // + ; + + // + bool isBreakedLower = + // + cBar.high > iBox.lower && + cBar.high < iBox.upper && + zBar.high < iBox.lower + // + ; + + // + bool isBreaked = + (isBullish && + isBreakedLower) || + (!isBullish && + isBreakedUpper); + + // + if (isBreaked) + { + // + AddRef( + iBox, + breakedBoxes // + ); + + // + Add( + i, + removeIDXs // + ); + + // + iBox.Clean(); + break; + } + } + + // + count = ArraySize(removeIDXs); + has = IsValidSize(count); + if (has) + { + // + CleanupArray( + removeIDXs, + waitingBoxes // + ); + } + + // + Clean(removeIDXs); +} + +// +// Inside Boxes ... +has = HasInsideBoxes(); +if (has) +{ + // + int removeIDXs[]; + count = CountInsideBoxes(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = insideBoxes[i]; + ENUM_X_DIRECTION iDir = iBox.dir; + bool isBullish = IsBullish(iDir); + + // + bool isBreakedUpper = + // + cBar.low < iBox.upper && + cBar.low > iBox.lower && + zBar.low > iBox.upper + // + ; + + // + bool isBreakedLower = + // + cBar.high > iBox.lower && + cBar.high < iBox.upper && + zBar.high < iBox.lower + // + ; + + // + bool isBreaked = + (isBullish && + isBreakedLower) || + (!isBullish && + isBreakedUpper); + + // + if (isBreaked) + { + // + AddRef( + iBox, + breakedBoxes // + ); + + // + Add( + i, + removeIDXs // + ); + + // + iBox.Clean(); + break; + } + } + + // + count = ArraySize(removeIDXs); + has = IsValidSize(count); + if (has) + { + // + CleanupArray( + removeIDXs, + insideBoxes // + ); + } + + // + Clean(removeIDXs); +} + +// +has = HasBreakedBoxes(); +if (has) +{ + // + int removeIDXs[]; + count = CountBreakedBoxes(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = breakedBoxes[i]; + ENUM_X_DIRECTION iDir = iBox.dir; + bool isBullish = IsBullish(iDir); + + // + bool isInside = false; + + // + if (isInside) + { + // + AddRef( + iBox, + breakedInsideBoxes // + ); + + // + Add( + i, + removeIDXs // + ); + + // + iBox.Clean(); + break; + } + } + + // + count = ArraySize(removeIDXs); + has = IsValidSize(count); + if (has) + { + // + CleanupArray( + removeIDXs, + breakedBoxes // + ); + } + + // + Clean(removeIDXs); +} + +// +// Update Waiting Boxes ... + +// +XPOIState iState = mtfState; + +// +// Use Order Blocks ... +if (mUseOrderBlocks) +{ + // + has = iState.HasOrderBlocks(); + if (has) + { + // + XCOrderBlock *obs[]; + count = iState.FilterOrderBlocks( + obs, + period, + XZONE_STATE_PASSED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_IGNORED, + false // + ); + + // + has = IsValidSize(count); + if (has) + { + // + // Try to Add new OBs into Waiting Zones ... + // if it's not exists ... + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + bool hasBox = ToBox( + iBox, + obs[i] // + ); + if (!hasBox) + { + // + iBox.Clean(); + continue; + } + + // + // Check Index in Waiting Boxes ... + idx = FindIndex( + iBox, + waitingBoxes // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + // Check Index in Inside Boxes ... + idx = FindIndex( + iBox, + insideBoxes // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + // Check Index in Breaked Boxes ... + idx = FindIndex( + iBox, + breakedBoxes // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + AddRef( + iBox, + waitingBoxes // + ); + } + } + + // + Clean(obs); + } +} + +// +// Use Fair Value Gaps ... +if (mUseFairValueGaps) +{ + // + has = iState.HasFairValueGaps(); + if (has) + { + // + XCFVG *fvgs[]; + count = iState.FilterFairValueGaps( + fvgs, + period, + XZONE_STATE_PASSED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_IGNORED, + false // + ); + + // + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + bool hasBox = ToBox( + iBox, + fvgs[i] // + ); + if (!hasBox) + { + // + iBox.Clean(); + continue; + } + + // + // Check Index in Waiting Boxes ... + idx = FindIndex( + iBox, + waitingBoxes // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + // Check Index in Inside Boxes ... + idx = FindIndex( + iBox, + insideBoxes // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + // Check Index in Breaked Boxes ... + idx = FindIndex( + iBox, + breakedBoxes // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + AddRef( + iBox, + waitingBoxes // + ); + + // + iBox.Clean(); + } + } + + // + Clean(fvgs); + } +} + +// +iState.Clean(); + +///////////////////////////////////////////////////////////////////////////// + +// +// Update Working Zone ... +// workingZone.Update( +// zIndex, +// visionState, +// consolidationState, +// analyseState, +// decisionState // +// ); + +////////////////////////////////////////////////////////////////////////////////// + +// +// +// + +// +// Supply Zones ... +if (drawSupplyZones) +{ + // + has = HasSupplyZones(); + if (has) + { + // + count = CountSupplyZones(); + for (int i = 0; i < count; i++) + { + // + XCSupplyZoneObject *iObj; + isCreated = drawer.CreateSupplyZone( + supplyZones[i], + iObj // + ); + + // + if (isCreated) + { + mWorkingZoneObjects.Add(iObj); + } + } + } +} + +// +// Demand Zones ... +if (drawDemandZones) +{ + // + has = HasDemandZones(); + if (has) + { + // + count = CountDemandZones(); + for (int i = 0; i < count; i++) + { + // + XCDemandZoneObject *iObj; + isCreated = drawer.CreateDemandZone( + demandZones[i], + iObj // + ); + + // + if (isCreated) + { + mWorkingZoneObjects.Add(iObj); + } + } + } +} + +// +// Support Zones ... +if (drawSupportZones) +{ + // + has = HasSupportZones(); + if (has) + { + // + count = CountSupportZones(); + for (int i = 0; i < count; i++) + { + // + XCSupportZoneObject *iObj; + isCreated = drawer.CreateSupportZone( + supportZones[i], + iObj // + ); + + // + if (isCreated) + { + mWorkingZoneObjects.Add(iObj); + } + } + } +} + +// +// Resistance Zones ... +if (drawResistanceZones) +{ + // + has = HasResistanceZones(); + if (has) + { + // + count = CountResistanceZones(); + for (int i = 0; i < count; i++) + { + // + XCResistanceZoneObject *iObj; + isCreated = drawer.CreateResistanceZone( + resistanceZones[i], + iObj // + ); + + // + if (isCreated) + { + mWorkingZoneObjects.Add(iObj); + } + } + } +} + +// +// +// + +// +// Waiting Boxes ... +if (drawWaitingBoxes) +{ + // + has = HasWaitingBoxes(); + if (has) + { + // + count = CountWaitingBoxes(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = waitingBoxes[i]; + + // + XCBoxObject *iObj; + bool isCreated = drawer.DrawBox( + iBox, + iObj // + ); + + // + if (isCreated) + { + mWorkingZoneObjects.Add(iObj); + } + + // + iBox.Clean(); + } + } +} + +// +// Inside Boxes ... +if (drawInsideBoxes) +{ + // + has = HasInsideBoxes(); + if (has) + { + } +} + +// +// Breaked Boxes ... +if (drawBreakedBoxes) +{ + // + has = HasBreakedBoxes(); + if (has) + { + // + } +} + +// +// Breaked Inside Boxes ... +if (drawBreakedInsideBoxes) +{ + // + has = HasBreakedInsideBoxes(); + if (has) + { + // + count = CountBreakedInsideBoxes(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = breakedInsideBoxes[i]; + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxWidth(1); + mBreakedInsideZoneObjects.Add(iObj); + } + } + } +} + +////////////////////////////////////////////////////////////////////////////////// + +// +XCSupplyZone *supplyZone; +XCDemandZone *demandZone; + +// +XCSupplyZone *supplyZones[]; +XCDemandZone *demandZones[]; + +// +XCSupportZone *supportZones[]; +XCResistanceZone *resistanceZones[]; + +// +XBoxZone insideBoxes[]; +XBoxZone breakedBoxes[]; +XBoxZone waitingBoxes[]; +XBoxZone breakedInsideBoxes[]; +XConsolidationZone consolidationZones[]; + +// +bool mUseSupDems; +bool mUseOrderBlocks; +bool mUseFairValueGaps; + +// +// +// + +// // +// // Supply Zones ... +// has = HasSupplyZones(); +// if (!has) +// { +// // +// count = mtfState.FilterSupplyZones( +// supplyZones, +// period, +// XZONE_STATE_PASSED, +// false, +// XZONE_STATE_FAILED, +// false, +// XZONE_STATE_FAILED, +// false, +// XZONE_STATE_IGNORED, +// false // +// ); +// } + +// // +// // Demand Zones ... +// has = HasDemandZones(); +// if (!has) +// { +// // +// count = mtfState.FilterDemandZones( +// demandZones, +// period, +// XZONE_STATE_PASSED, +// false, +// XZONE_STATE_FAILED, +// false, +// XZONE_STATE_FAILED, +// false, +// XZONE_STATE_IGNORED, +// false // +// ); +// } + +// +// Support Zones ... +// has = HasSupportZones(); +// if (!has) +// { +// // +// count = mtfState.FilterSupportZones( +// supportZones, +// period, +// XZONE_STATE_PASSED, +// false, +// XZONE_STATE_FAILED, +// false, +// XZONE_STATE_FAILED, +// false, +// XZONE_STATE_IGNORED, +// false // +// ); +// } + +// +// Resistance Zones ... +// has = HasResistanceZones(); +// if (!has) +// { +// // +// count = mtfState.FilterResistanceZones( +// resistanceZones, +// period, +// XZONE_STATE_PASSED, +// false, +// XZONE_STATE_FAILED, +// false, +// XZONE_STATE_FAILED, +// false, +// XZONE_STATE_IGNORED, +// false // +// ); +// } + +// +// Update Exists Zones ... + +// +// Supply Zones ... +has = mtfState.HasSupplyZones(); +if (has) +{ + // + XCSupplyZone *zone; + idx = GetYoungest(mtfState.supplyZones); + has = IsValidIndex(idx); + if (has) + { + // + zone = mtfState.supplyZones[idx]; + has = IsSupplyExists(zone); + if (!has) + { + // + Add( + zone, + supplyZones // + ); + } + else + { + ZeroMemory(zone); + } + } +} + +// +// Demand Zones ... +has = mtfState.HasDemandZones(); +if (has) +{ + // + XCDemandZone *zone; + idx = GetYoungest(mtfState.demandZones); + has = IsValidIndex(idx); + if (has) + { + // + zone = mtfState.demandZones[idx]; + has = IsDemandExists(zone); + if (!has) + { + // + Add( + zone, + demandZones // + ); + } + else + { + ZeroMemory(zone); + } + } +} + +/////////////////////////////////////////////////////////////////////////// + +// +bool IsExists(XBoxZone &box) +{ + // + bool result = false; + + // + result = box.IsValid(); + if (!result) + { + return result; + } + + // + int idx = -1; + bool has = false; + + // + // Checking Index Waiting Box ... + has = HasWaitingBoxes(); + if (has) + { + // + idx = FindIndex( + box, + waitingBoxes // + ); + result = !IsValidIndex(idx); + if (!result) + { + return result; + } + } + + // + // Checking Index Inside Boxes ... + has = HasInsideBoxes(); + if (has) + { + // + idx = FindIndex( + box, + insideBoxes // + ); + result = !IsValidIndex(idx); + if (!result) + { + return result; + } + } + + // + // Checking Index Breaked Boxes ... + has = HasBreakedBoxes(); + if (has) + { + // + idx = FindIndex( + box, + breakedBoxes // + ); + result = !IsValidIndex(idx); + if (!result) + { + return result; + } + } + + // + // Checking Index BreakedInside Boxes ... + has = HasBreakedInsideBoxes(); + if (has) + { + // + idx = FindIndex( + box, + breakedInsideBoxes // + ); + result = !IsValidIndex(idx); + if (!result) + { + return result; + } + } + + // + return result; +} + +// +bool IsSupplyExists(XCSupplyZone *zone) +{ + // + bool result = false; + + // + result = zone != NULL && + zone.IsValid(); + if (!result) + { + return result; + } + + // + // Converts Zone to Box ... + XBoxZone box; + result = ToBox( + box, + zone // + ); + if (!result) + { + // + box.Clean(); + return result; + } + + // + // Checking Index in SupplyZones ... + int idx = FindIndex( + zone, + supplyZones // + ); + result = !IsValidIndex(idx); + if (!result) + { + // + box.Clean(); + return result; + } + + // + result = IsExists(box); + + // + box.Clean(); + + // + return result; +} + +// +bool IsDemandExists(XCDemandZone *zone) +{ + // + bool result = false; + + // + result = zone != NULL && + zone.IsValid(); + if (!result) + { + return result; + } + + // + // Converts Zone to Box ... + XBoxZone box; + result = ToBox( + box, + zone // + ); + if (!result) + { + // + box.Clean(); + return result; + } + + // + // Checking Index in SupplyZones ... + int idx = FindIndex( + zone, + demandZones // + ); + result = !IsValidIndex(idx); + if (!result) + { + // + box.Clean(); + return result; + } + + // + result = IsExists(box); + + // + box.Clean(); + + // + return result; +} + +////////////////////////////////////////////////////////////////////////////// + +// +Clean(supplyZones); +Clean(demandZones); + +// +Clean(insideBoxes); +Clean(breakedBoxes); +Clean(waitingBoxes); + +// +Clean(supportZones); +Clean(resistanceZones); + +// +mUseSupDems = false; +mUseOrderBlocks = true; +mUseFairValueGaps = true; + +///////////////////////////////////////////////////////////////////////////// + +// +bool HasInsideBox( + XBoxZone &box // +) +{ + // + bool result = false; + + // + int index = -1; + + // + result = box.IsValid(); + if (!result) + { + return result; + } + + // + int count = 0; + bool has = false; + + // + has = HasWaitingBoxes(); + if (has) + { + // + result = HasInsideBox( + index, + box, + waitingBoxes // + ); + } + + // + // Supply Zones ... + if (!result) + { + // + has = HasSupplyZones(); + if (has) + { + // + XBoxZone tmpBoxes[]; + count = ToBox( + supplyZones, + tmpBoxes // + ); + + // + has = IsValidSize(count); + if (has) + { + // + result = HasInsideBox( + index, + box, + tmpBoxes // + ); + } + + // + Clean(tmpBoxes); + } + } + + // + // Demand Zones ... + if (!result) + { + // + has = HasDemandZones(); + if (has) + { + // + XBoxZone tmpBoxes[]; + count = ToBox( + demandZones, + tmpBoxes // + ); + + // + has = IsValidSize(count); + if (has) + { + // + result = HasInsideBox( + index, + box, + tmpBoxes // + ); + } + + // + Clean(tmpBoxes); + } + } + + // + result = IsValidIndex(index); + + // + return result; +} + +// +bool DetectSenarioASignalBox( + XBoxZone &signalBox, + ENUM_X_DIRECTION &signalDir, + X121Conditions &decisionXConditions, + X121Conditions &analyseXConditions, + XC121SMCCycleHelper *decisionCycleHelper, + XCPOIDrawer *drawer = NULL, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + signalBox.Clean(); + signalDir = X_DIRECTION_NONE; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + result = decisionCycleHelper != NULL; + if (!result) + { + return result; + } + + // + // Decision ... + double decisionBullishScore = 0; + double decisionBearishScore = 0; + decisionXConditions.GenerateScore( + decisionBullishScore, + decisionBearishScore // + ); + + // + // Analyse ... + double analyseBullishScore = 0; + double analyseBearishScore = 0; + analyseXConditions.GenerateScore( + analyseBullishScore, + analyseBearishScore // + ); + + // + // Score Conditions ... + double scoreMultiplier = 3; + bool isBullishScorePassed = + // + analyseBullishScore > (analyseBearishScore * scoreMultiplier) && + decisionBullishScore > (decisionBearishScore * scoreMultiplier) + // + ; + bool isBearishScorePassed = + // + analyseBearishScore > (analyseBullishScore * scoreMultiplier) && + decisionBearishScore > (decisionBullishScore * scoreMultiplier) + // + ; + + // + // Checking Other Conditions + + // + bool isCommonBullish = + // + decisionXConditions.isSarBullish && + decisionXConditions.isStrBullish && + decisionXConditions.isCheBullish && + decisionXConditions.isSMHKBullish && + decisionXConditions.isRawHKBullish && + decisionXConditions.isRawHKClosedOverSMHK + // + ; + + // + bool isCommonBearish = + // + decisionXConditions.isSarBearish && + decisionXConditions.isStrBearish && + decisionXConditions.isCheBearish && + decisionXConditions.isSMHKBearish && + decisionXConditions.isRawHKBearish && + decisionXConditions.isRawHKClosedUnderSMHK + // + ; + + // + // X3Ma ... + + // + // X3Ma Bullish ... + bool isX3MaBullish = + // + decisionXConditions.isX3MaBullishState && + decisionXConditions.isX3MaSwitchedToBullishOrdered && + decisionXConditions.x3maMidBuffer[1] > decisionXConditions.x3maSlowBuffer[1] + // + ; + + // + // X3Ma Bearish ... + bool isX3MaBearish = + // + decisionXConditions.isX3MaBearishState && + decisionXConditions.isX3MaSwitchedToBearishOrdered && + decisionXConditions.x3maMidBuffer[1] < decisionXConditions.x3maSlowBuffer[1] + // + ; + + // + bool isX3MaHasCondition = + (isX3MaBullish && + isCommonBullish && + isBullishScorePassed) || + (isX3MaBearish && + isCommonBearish && + isBearishScorePassed); + + // + // VWap ... + + // + // VWap Bullish ... + bool isVWapBullish = + // + decisionXConditions.isVWapBullishState && + decisionXConditions.isVWapSwitchedToBullishOrdered && + decisionXConditions.vwapMidBuffer[1] > decisionXConditions.vwapSlowBuffer[1] + // + ; + + // + // VWap Bearish ... + bool isVWapBearish = + // + decisionXConditions.isVWapBearishState && + decisionXConditions.isVWapSwitchedToBearishOrdered && + decisionXConditions.vwapMidBuffer[1] < decisionXConditions.vwapSlowBuffer[1] + // + ; + + // + bool isVWapHasCondition = + (isVWapBullish && + isBullishScorePassed) || + (isVWapBearish && + isBearishScorePassed); + + // + // Senario .... + // - a vale Under X3MA Slow when X3MA Bullish Ordered ... + + // + bool isX3MASenarioBBullish = + // + decisionXConditions.isX3MaBullishOrdered && + decisionXConditions.valesBuffer[1] < decisionXConditions.x3maSlowBuffer[1] && + decisionXConditions.valesBuffer[2] >= decisionXConditions.x3maSlowBuffer[2] + // + ; + if (isX3MASenarioBBullish) + { + } + + // + bool isX3MASenarioBBearish = + // + decisionXConditions.isX3MaBearishOrdered && + decisionXConditions.peaksBuffer[1] > decisionXConditions.x3maSlowBuffer[1] && + decisionXConditions.peaksBuffer[2] <= decisionXConditions.x3maSlowBuffer[2] + // + ; + if (isX3MASenarioBBearish) + { + } + + // + // Checking Other Conditions XWZ Reject on EMA 20 ... + + // + // Check Has Conditions ... + bool hasXConditions = + (isX3MaHasCondition || + isVWapHasCondition); + + // + result = hasXConditions; + if (!result) + { + return result; + } + + // + if (isX3MaHasCondition) + { + // + signalDir = + isX3MaBullish + ? X_DIRECTION_BULLISH + : isX3MaBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + } + + // + if (isVWapHasCondition) + { + // + signalDir = + isVWapBullish + ? X_DIRECTION_BULLISH + : isVWapBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + } + + // + // Creating SignalBox ... + + // + // Detect Box based on PV ... + bool hasSignalBox = decisionCycleHelper.GeneratePVBox( + signalBox, + barIndex // + ); + + // + result = + hasSignalBox && + signalDir == signalBox.dir; + + // + if (result) + { + // + XCBoxObject *iObj; + bool isCreated = drawer.DrawBox( + signalBox, + iObj // + ); + if (isCreated) + { + // + iObj.BoxWidth(1); + iObj.BoxColor(clrYellow); + iObj.BoxStyle(STYLE_SOLID); + } + + // + Print("Senario A ..."); + } + + // + return result; +} + +// +bool DetetctSenarioBSignalBox( + XBoxZone &signalBox, + ENUM_X_DIRECTION &signalDir, + X121Conditions &decisionXConditions, + X121Conditions &analyseXConditions, + XC121SMCCycleHelper *decisionCycleHelper, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + signalBox.Clean(); + signalDir = X_DIRECTION_NONE; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + result = decisionCycleHelper != NULL; + if (!result) + { + return result; + } + + // + // Decision ... + double decisionBullishScore = 0; + double decisionBearishScore = 0; + decisionXConditions.GenerateScore( + decisionBullishScore, + decisionBearishScore // + ); + + // + // Analyse ... + double analyseBullishScore = 0; + double analyseBearishScore = 0; + analyseXConditions.GenerateScore( + analyseBullishScore, + analyseBearishScore // + ); + + // + // Score Conditions ... + double scoreMultiplier = 3; + bool isBullishScorePassed = + // + analyseBullishScore > (analyseBearishScore * scoreMultiplier) && + decisionBullishScore > (decisionBearishScore * scoreMultiplier) + // + ; + bool isBearishScorePassed = + // + analyseBearishScore > (analyseBullishScore * scoreMultiplier) && + decisionBearishScore > (decisionBullishScore * scoreMultiplier) + // + ; + + // + // Senario .... + // - a vale Under X3MA Slow when X3MA Bullish Ordered ... + + // + bool isX3MASenarioBBullish = + // + decisionXConditions.isX3MaBullishOrdered && + decisionXConditions.valesBuffer[1] < decisionXConditions.x3maSlowBuffer[1] && + decisionXConditions.valesBuffer[2] >= decisionXConditions.x3maSlowBuffer[2] + // + ; + if (isX3MASenarioBBullish) + { + } + + // + bool isX3MASenarioBBearish = + // + decisionXConditions.isX3MaBearishOrdered && + decisionXConditions.peaksBuffer[1] > decisionXConditions.x3maSlowBuffer[1] && + decisionXConditions.peaksBuffer[2] <= decisionXConditions.x3maSlowBuffer[2] + // + ; + if (isX3MASenarioBBearish) + { + } + + // + return result; +} + +// +bool HasSupplyZones() +{ + return HasChild(supplyZones); +} + +// +int CountSupplyZones() +{ + return ArraySize(supplyZones); +} + +// +bool HasDemandZones() +{ + return HasChild(demandZones); +} + +// +int CountDemandZones() +{ + return ArraySize(demandZones); +} + +// +bool HasSupportZones() +{ + return HasChild(supportZones); +} + +// +int CountSupportZones() +{ + return ArraySize(supportZones); +} + +// +bool HasResistanceZones() +{ + return HasChild(resistanceZones); +} + +// +int CountResistanceZones() +{ + return ArraySize(resistanceZones); +} + +// +bool HasConsolidationZones() +{ + return HasChild(consolidationZones); +} + +// +int CountConsolidationZones() +{ + return ArraySize(consolidationZones); +} + +// +bool HasWaitingBoxes() +{ + return HasChild(waitingBoxes); +} + +// +int CountWaitingBoxes() +{ + return ArraySize(waitingBoxes); +} + +// +bool HasInsideBoxes() +{ + return HasChild(insideBoxes); +} + +// +int CountInsideBoxes() +{ + return ArraySize(insideBoxes); +} + +// +bool HasBreakedBoxes() +{ + return HasChild(breakedBoxes); +} + +// +int CountBreakedBoxes() +{ + return ArraySize(breakedBoxes); +} + +// +bool HasBreakedInsideBoxes() +{ + return HasChild(breakedInsideBoxes); +} + +// +int CountBreakedInsideBoxes() +{ + return ArraySize(breakedInsideBoxes); +} + +/////////////////////////////////////////////////////////////////////////////////// + +// +has = ttfState.HasConsolidationZones(); +if (has) +{ + // + Copy( + ttfState.consolidationZones, + consolidationZones // + ); + CleanupArray( + consolidationZones, + 50 // + ); +} + +// +has = HasSupplyZones(); +if (has) +{ + // + count = CountSupplyZones(); + for (int i = 0; i < count; i++) + { + supplyZones[i].To(value); + } +} + +// +has = HasDemandZones(); +if (has) +{ + // + count = CountDemandZones(); + for (int i = 0; i < count; i++) + { + demandZones[i].To(value); + } +} + +// +has = HasSupportZones(); +if (has) +{ + // + count = CountSupportZones(); + for (int i = 0; i < count; i++) + { + supportZones[i].To(value); + } +} + +// +has = HasResistanceZones(); +if (has) +{ + // + count = CountResistanceZones(); + for (int i = 0; i < count; i++) + { + resistanceZones[i].To(value); + } +} + +// +// +// + +// +has = HasWaitingBoxes(); +if (has) +{ + // + count = ArraySize(waitingBoxes); + for (int i = 0; i < count; i++) + { + waitingBoxes[i].to = value; + } +} + +// +has = HasInsideBoxes(); +if (has) +{ + // + count = CountInsideBoxes(); + for (int i = 0; i < count; i++) + { + insideBoxes[i].to = value; + } +} + +// +has = HasBreakedBoxes(); +if (has) +{ +} + +// +has = HasBreakedInsideBoxes(); +if (has) +{ + // + count = CountBreakedInsideBoxes(); + for (int i = 0; i < count; i++) + { + breakedInsideBoxes[i].to = value; + } +} + +/////////////////////////////////////////////////////////////////////////////////// + +// +XBoxZone waitingBoxes[]; +has = workingZone.HasWaitingBoxes(); +if (has) +{ + // + Copy( + workingZone.waitingBoxes, + waitingBoxes // + ); + + // + while (HasChild(waitingBoxes)) + { + // + XBoxZone iBox; + idx = GetYoungest(waitingBoxes); + has = IsValidIndex(idx); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + iBox = waitingBoxes[idx]; + ArrayRemove( + waitingBoxes, + idx, + 1 // + ); + + // + bool hasInside = workingZone.HasInsideBox(iBox); + if (!hasInside) + { + continue; + } + + // + double iTarget = + IsBullish(signalBoxDir) + ? iBox.lower + : iBox.upper; + + // + Add( + iTarget, + targets // + ); + + // + iBox.Clean(); + } +} + +/////////////////////////////////////////////////////////////////////////////////// + +// +void Update( + int barIndex, + XPOIState &htfState, + XPOIState &mtfState, + XPOIState &stfState, + XPOIState &ttfState // +) +{ + // + int idx = -1; + int count = 0; + bool has = false; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + has = + // + IsValid() && + // + htfState.IsValid() && + mtfState.IsValid() && + stfState.IsValid() && + // + htfState.HasChild() && + mtfState.HasChild() && + stfState.HasChild() + // + ; + if (!has) + { + return; + } + + // + XOHCL zBar; + has = zBar.Init( + symbol, + period, + barIndex // + ); + if (!has) + { + // + zBar.Clean(); + return; + } + + // + XOHCL cBar; + has = zBar.GetPreviousBar(cBar); + if (!has) + { + // + zBar.Clean(); + cBar.Clean(); + + // + return; + } + + // + // Cleanup Resource ... + + // + zBar.Clean(); + cBar.Clean(); +} + +/////////////////////////////////////////////////////////////////////////////////// + +// +int ExtractOBFVGs( + XOBFVG &dest[], + XPOIState &obState, + XPOIState &fvgState, + // + ENUM_X_OBFVG_FVG_FILTERS filterFVGs = X_OBFVG_FVG_FILTER_INSIDE_OR, + ENUM_X_OBFVG_FVG_SELECTION selectFVG = X_OBFVG_FVG_SELECT_OLDEST, + // + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_IGNORED, + bool forceWorkedBodyOut = false // +) +{ + // + int result = 0; + + // + bool has = false; + + // + Clean(dest); + + // + has = obState.IsValid() && + fvgState.IsValid() && + obState.HasChild() && + fvgState.HasChild() && + selectFVG != X_OBFVG_FVG_SELECT_NONE && + filterFVGs != X_OBFVG_FVG_FILTER_NONE; + if (!has) + { + return result; + } + + // + XCOrderBlock *obs[]; + int obsCount = obState.FilterOrderBlocks( + obs, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + has = IsValidSize(obsCount); + if (!has) + { + return result; + } + + // + XCFVG *fvgs[]; + int fvgsCount = fvgState.FilterFairValueGaps( + fvgs, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + has = IsValidSize(fvgsCount); + if (!has) + { + return result; + } + + // + for (int i = 0; i < obsCount; i++) + { + // + XCOrderBlock *iOB = obs[i]; + XCFVG *iFVG = NULL; + + // + ENUM_X_DIRECTION iOBDir = iOB.GetDirection(); + bool isIOBBullish = IsBullish(iOBDir); + + // + XCFVG *iFVGs[]; + for (int j = 0; j < fvgsCount; j++) + { + // + XCFVG *jFVG = fvgs[j]; + ENUM_X_DIRECTION jFVGDir = jFVG.GetDirection(); + + // + bool isSameDir = iOBDir == jFVGDir; + bool isFromPassed = jFVG.From() >= iOB.From(); + bool isInsideOr = IsInsideOrDiff( + jFVG, + iOB // + ); + bool isAbove = IsAboveDiff( + jFVG, + iOB, + true // + ); + bool isBelow = IsBelowDiff( + jFVG, + iOB, + true // + ); + + // + bool isFilterPassed = + filterFVGs == X_OBFVG_FVG_FILTER_ABOVE_BELOW + ? isIOBBullish + ? isAbove + : isBelow + : filterFVGs == X_OBFVG_FVG_FILTER_INSIDE_OR + ? isInsideOr + : false; + + // + has = + isSameDir && + isFromPassed && + isFilterPassed; + if (has) + { + // + Add( + jFVG, + iFVGs // + ); + } + } + has = HasChild(iFVGs); + if (!has) + { + continue; + } + + // + int idx = -1; + idx = selectFVG == X_OBFVG_FVG_SELECT_OLDEST + ? GetOldest(iFVGs) + : selectFVG == X_OBFVG_FVG_SELECT_YOUNGEST + ? GetYoungest(iFVGs) + : selectFVG == X_OBFVG_FVG_SELECT_HIGHEST_LOWEST + ? isIOBBullish + ? GetHighest(iFVGs) + : GetLowest(iFVGs) + : selectFVG == X_OBFVG_FVG_SELECT_LOWEST_HIGHEST + ? isIOBBullish + ? GetLowest(iFVGs) + : GetHighest(iFVGs) + : selectFVG == X_OBFVG_FVG_SELECT_LOWEST + ? GetLowest(iFVGs) + : selectFVG == X_OBFVG_FVG_SELECT_HIGHEST + ? GetHighest(iFVGs) + : -1; + + // + has = IsValidIndex(idx); + if (!has) + { + continue; + } + + // + iFVG = iFVGs[idx]; + Clean(iFVGs); + + // + XOBFVG iOBFVG; + iOBFVG.ob = iOB; + iOBFVG.fvg = iFVG; + + // + has = iOBFVG.IsValid(); + if (!has) + { + // + iOBFVG.Clean(); + continue; + } + + // + AddRef( + iOBFVG, + dest // + ); + + // + iOBFVG.Clean(); + } + + // + result = ArraySize(dest); + + // + return result; +} + +/////////////////////////////////////////////////////////////////////////////////// + +// // +// XCBaseObject *obObject; +// bool isCreated = drawer.CreateOrderBlock( +// obFVG.ob, +// obObject // +// ); + +// // +// count = obFVG.CountFVGs(); +// for (int i = 0; i < count; i++) +// { +// // +// XCBaseObject *fvgObject; +// isCreated = drawer.CreateFairValueGap( +// obFVG.fvgs[i], +// fvgObject // +// ); +// } + +/////////////////////////////////////////////////////////////////////////////////// + +// +// Detect OB FVG ... +// result = +// hasNewOrderBlock && +// hasNewFairValueGap && +// ob.GetDirection() == fvg.GetDirection(); +// if (result) +// { +// // +// obFVG.ob = ob; +// obFVG.AddFVG(fvg); + +// // +// has = obFVG.IsValid(); +// if (has) +// { +// // +// has = IsExists(obFVG); +// if (!has) +// { +// // +// // New Waiting Zone ... +// AddRef( +// obFVG, +// waitingZones // +// ); +// } +// else +// { +// // +// // Check Item Is not Exists ... +// idx = FindIndex( +// obFVG, +// waitingZones // +// ); +// has = !IsValidIndex(idx); +// if (!has) +// { +// // +// // Update Exists Waiting Zone ... +// waitingZones[idx].AddFVG(fvg); +// } +// } +// } +// } + +// // +// XCFVG *decisionFVG; +// bool hasNewDecisionFVG = +// Contains( +// X_BULLISH_FVG_DETECTED, +// provider +// .decisionPoiEvents // +// ) || +// Contains( +// X_BEARISH_FVG_DETECTED, +// provider +// .decisionPoiEvents // +// ); +// if (hasNewDecisionFVG) +// { +// // +// idx = GetYoungest(provider +// .decisionState +// .fairValueGaps // +// ); +// has = IsValidIndex(idx); +// if (has) +// { +// // +// decisionFVG = provider +// .decisionState +// .fairValueGaps[idx]; + +// // +// XCBaseObject *iObj; +// bool isCreated = drawer.CreateFairValueGap( +// decisionFVG, +// iObj // +// ); + +// // +// if (isCreated) +// { +// Print("New Fair Value Gap ..."); +// } +// } +// } + +// +// Detect SupDem FVG ... +// if (!result) +// { +// // +// result = hasNewFairValueGap && +// (hasNewSupply || +// hasNewDemand); +// if (result) +// { +// // +// // Converts Supply or Demand Zone to OrderBlock ... +// XOHCL bar; +// ob = new XCOrderBlock(); +// if (hasNewSupply) +// { +// // +// has = supply.FillBar(bar); +// if (has) +// { +// // +// has = ob.Init( +// bar, +// X_DIRECTION_BEARISH // +// ); +// if (has) +// { +// // +// ob.Upper(supply.Upper()); +// ob.Lower(supply.Lower()); +// } +// } +// } +// else if (hasNewDemand) +// { +// // +// has = demand.FillBar(bar); +// if (has) +// { +// // +// has = ob.Init( +// bar, +// X_DIRECTION_BULLISH // +// ); +// if (has) +// { +// // +// ob.Upper(demand.Upper()); +// ob.Lower(demand.Lower()); +// } +// } +// } + +// // +// obFVG.ob = ob; +// obFVG.AddFVG(fvg); + +// // +// has = obFVG.IsValid(); +// if (has) +// { +// // +// // Check Item Is not Exists ... +// idx = FindIndex( +// obFVG, +// waitingZones // +// ); +// has = !IsValidIndex(idx); +// if (has) +// { +// // +// // New Waiting Zone ... +// AddRef( +// obFVG, +// waitingZones // +// ); +// } +// else +// { +// // +// // Update Exists Waiting Zone ... +// waitingZones[idx].AddFVG(fvg); +// } +// } + +// // +// bar.Clean(); +// } +// } + +/////////////////////////////////////////////////////////////////////////////////// + +// +bool IsValidZone( + XOHCL &invalidBar, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + invalidBar.Clean(); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + XCFVG *fvg; + result = GetMainFVG(fvg); + if (!result) + { + // + ZeroMemory(fvg); + return result; + } + + // + XOHCL startedBar; + bool isBodyOut = false; + result = fvg.IsStarted( + fvg.GetDirection(), + startedBar, + isBodyOut // + ); + if (!result) + { + // + ZeroMemory(fvg); + startedBar.Clean(); + + // + return result; + } + + // + XOHCL bar; + bool isBullish = fvg.IsBullish(); + + // + int fromIndex = iBarShift( + fvg.GetSymbol(), + fvg.GetPeriod(), + startedBar.NextAt() // + ); + result = IsValidIndex(fromIndex); + if (!result) + { + // + bar.Clean(); + ZeroMemory(fvg); + startedBar.Clean(); + + // + return result; + } + + // + bool isInited = false; + for (int i = barIndex; i < fromIndex; i++) + { + // + isInited = bar.Init( + fvg.GetSymbol(), + fvg.GetPeriod(), + i // + ); + if (!isInited) + { + // + bar.Clean(); + continue; + } + + // + bool isBarAbove = + bar.low > fvg.Upper(); + bool isBarBelow = + bar.high < fvg.Lower(); + + // + result = + isBullish + ? isBarAbove + : isBarBelow; + if (!result) + { + // + invalidBar = bar; + bar.Clean(); + + // + break; + } + + // + bar.Clean(); + } + + // + bar.Clean(); + ZeroMemory(fvg); + startedBar.Clean(); + + // + return result; +} + +/////////////////////////////////////////////////////////////////////////////////// + +// +// XBoxZone iBox; +// result = iOBFVG.ToZone(iBox); +// if (!result) +// { +// // +// iBox.Clean(); +// iOBFVG.Clean(); + +// // +// continue; +// } + +// +// XCFVG *fvg; +// result = iOBFVG.GetMainFVG(fvg); +// if (!result) +// { +// // +// iOBFVG.Clean(); +// ZeroMemory(fvg); + +// // +// continue; +// } + +/////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////// diff --git a/BKPS/14031218/Documents/BKP/Test.mq5 b/BKPS/14031218/Documents/BKP/Test.mq5 new file mode 100644 index 0000000..02e4a71 --- /dev/null +++ b/BKPS/14031218/Documents/BKP/Test.mq5 @@ -0,0 +1,243 @@ +//+------------------------------------------------------------------+ +//| Test.mq5 | +//| Copyright 2025, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2025, MetaQuotes Ltd." +#property link "https://www.mql5.com" +#property version "1.00" + +// +#include "../Classes/x-saherelm.x-bar.analyser.class.mq5" +#include "../Classes/x-saherelm.x-poi.class.mq5" +#include "../Classes/x-saherelm.x-poi.drawer.class.mq5" + +// +XCPOIDrawer *mPOIDrawer; +XCPOIDetector *mPOIDetector; +XCBarAnalyser *mBarAnalyser; + +// +XBarTracker mBarTracker; + +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() +{ + //--- + mPOIDetector = new XCPOIDetector( + _Symbol, + _Period // + ); + mPOIDetector.Init(); + + //--- + mPOIDrawer = new XCPOIDrawer(); + + //--- + mBarAnalyser = new XCBarAnalyser(); + + //--- + mBarTracker.Init( + _Symbol, + _Period // + ); + + //--- + return (INIT_SUCCEEDED); +} +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) +{ + //--- + ZeroMemory(mPOIDrawer); + ZeroMemory(mBarAnalyser); + ZeroMemory(mPOIDetector); +} +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() +{ + + // + bool isNewBar = mBarTracker.IsNewBar(); + if (!isNewBar) + { + return; + } + + // + ENUM_XPOI_EVENTS mPOIEvents[]; + mPOIDetector.Update(mPOIEvents); + + // + XPOIState mPOIState; + mPOIDetector.GetState(mPOIState); + + // + bool has = Contains( + X_BULLISH_FVG_DETECTED, + mPOIEvents // + ) || + Contains( + X_BEARISH_FVG_DETECTED, + mPOIEvents // + ); + if (has) + { + // + XCFVG *fvg; + int idx = GetYoungest(mPOIState.fairValueGaps); + has = IsValidIndex(idx); + if (has) + { + // + fvg = mPOIState.fairValueGaps[idx]; + + // + XCBaseObject *iObj; + has = mPOIDrawer.CreateFairValueGap( + fvg, + iObj // + ); + + // + if (has) + { + // + Print("New Fair Value Gap ..."); + } + } + } + + // // + // bool has = mPOIState.HasFairValueGaps(); + // if (has) + // { + // // + // int count = mPOIState.CountFairValueGaps(); + // for (int i = 0; i < count; i++) + // { + // // + // mPOIState.fairValueGaps[i].To(TimeCurrent()); + + // // + // XCBaseObject *iObj; + // bool isCreated = mPOIDrawer.CreateFairValueGap( + // mPOIState.fairValueGaps[i], + // iObj // + // ); + // } + + // + // Print("Salam"); + + // + return; + + // // + // XOHCL bar; + // bool isInited = bar.Init( + // _Symbol, + // _Period, + // 0 // + // ); + // if (!isInited) + // { + // return; + // } + + // // + // int index = 0; + // ENUM_X_DIRECTION sameBarDir; + // bool hasSameBars = mBarAnalyser.HasSameBars( + // bar, + // sameBarDir, + // index, + // 3 // + // ); + // if (hasSameBars) + // { + // } + + // // + // // Detect Fair Value Gap ... + // XOHCL fvgEndBar; + // XOHCL fvgStartBar; + // ENUM_X_DIRECTION fvgDir; + // bool hasFVG = mBarAnalyser.HasFairValueGap( + // bar, + // fvgStartBar, + // fvgEndBar, + // fvgDir, + // 3 // + // ); + // if (hasFVG) + // { + // // + // XCFVG *fvg; + // fvg = new XCFVG(); + // bool isInit = fvg.Init( + // fvgStartBar, + // fvgEndBar, + // fvgDir // + // ); + // // if (isInit) + // // { + // // // + // // XCBaseObject *iObj; + // // bool isCreated = mPOIDrawer.CreateFairValueGap( + // // fvg, + // // iObj // + // // ); + // // + // // // + // // if (isCreated) + // // { + // // } + // // } + // } + + // // + // XOHCL obBar; + // ENUM_X_DIRECTION obDir; + // bool hasOB = mBarAnalyser.HasOrderBlock( + // bar, + // obBar, + // obDir, + // 3 // + // ); + // if (hasOB) + // { + // // + // XCOrderBlock *ob; + // ob = new XCOrderBlock(); + // bool isInit = ob.Init( + // obBar, + // obDir // + // ); + // if (isInit) + // { + // // // + // // XCBaseObject *iObj; + // // bool isCreated = mPOIDrawer.CreateOrderBlock( + // // ob, + // // iObj // + // // ); + + // // // + // // if (isCreated) + // // { + // // Print("Order Block ..."); + // // } + // // } + // } + + // // + // } +} +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Documents/BKP/smc.ea.ex5 b/BKPS/14031218/Documents/BKP/smc.ea.ex5 new file mode 100644 index 0000000..4a90a92 Binary files /dev/null and b/BKPS/14031218/Documents/BKP/smc.ea.ex5 differ diff --git a/BKPS/14031218/Documents/BKP/smc.ea.mq5 b/BKPS/14031218/Documents/BKP/smc.ea.mq5 new file mode 100644 index 0000000..d8e5e61 --- /dev/null +++ b/BKPS/14031218/Documents/BKP/smc.ea.mq5 @@ -0,0 +1,418 @@ +//+------------------------------------------------------------------+ +//| SMC_OrderBlock_EA.mq5| +//| Copyright 2023, MetaQuotes Software Corp. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2023, MetaQuotes Software Corp." +#property link "https://www.mql5.com" +#property version "1.00" +#property strict + +#include +#include + +// +// Input parameters +input ENUM_TIMEFRAMES TimeFrame = PERIOD_M15; // Timeframe for analysis +input double RiskPercent = 1.0; // Risk per trade (1-2%) +input int ATR_Period = 14; // ATR period for volatility +input int OrderBlockLength = 20; // Bars for consolidation +input int ConfirmationCandles = 3; // Candles to confirm breakout +input double StopLossMultiplier = 1.5; // Stop loss buffer +input double TakeProfitRatio = 2.0; // Risk:Reward ratio +input int TrailingStopPips = 50; // Trailing stop in pips + +// +CTrade trade; +CAccountInfo accountInfo; + +// +double Ask = 0; +double Bid = 0; + +// +// Order Block structure +struct OrderBlock +{ + datetime startTime; + double high; + double low; +}; + +// +int atrHandler = INVALID_HANDLE; +int maFastHandler = INVALID_HANDLE; +int maSlowHandler = INVALID_HANDLE; + +// +double atrs[]; +double fastMAs[]; +double slowMAs[]; + +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() +{ + // + trade.SetExpertMagicNumber(123456); // Unique magic number + + // + atrHandler = iATR(_Symbol, TimeFrame, ATR_Period); + maFastHandler = iMA(_Symbol, TimeFrame, 20, 0, MODE_SMA, PRICE_CLOSE); + maSlowHandler = iMA(_Symbol, TimeFrame, 50, 0, MODE_SMA, PRICE_CLOSE); + + // + bool isValid = + atrHandler != INVALID_HANDLE && + maFastHandler != INVALID_HANDLE && + maSlowHandler != INVALID_HANDLE; + if (!isValid) + { + return (INIT_FAILED); + } + + // + return (INIT_SUCCEEDED); +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) +{ + // + // Cleanup code if needed ... + IndicatorRelease(atrHandler); + IndicatorRelease(maFastHandler); + IndicatorRelease(maSlowHandler); + + // + ZeroMemory(atrs); + ZeroMemory(fastMAs); + ZeroMemory(slowMAs); +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() +{ + // Avoid multiple orders + if (CheckOpenOrders()) + return; + + // + CopyBuffer(atrHandler, MAIN_LINE, 0, 200, atrs); + + // + CopyBuffer(maFastHandler, MAIN_LINE, 0, 2, fastMAs); + CopyBuffer(maSlowHandler, MAIN_LINE, 0, 2, slowMAs); + + // + Ask = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits); // Get the Ask Price + Bid = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits); // Get the Bid Price + + // + // Check for trend and execute trades + if (IsUptrend()) + { + OrderBlock block = FindBullishOrderBlock(); + if (block.startTime != 0 && IsPriceInBlock(block)) + { + if (ConfirmBullishEntry()) + ExecuteTrade(block, ORDER_TYPE_BUY); + } + } + else if (IsDowntrend()) + { + OrderBlock block = FindBearishOrderBlock(); + if (block.startTime != 0 && IsPriceInBlock(block)) + { + if (ConfirmBearishEntry()) + ExecuteTrade(block, ORDER_TYPE_SELL); + } + } + + // Manage trailing stops + TrailStop(); +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Check if price is within the order block | +//+------------------------------------------------------------------+ +bool IsPriceInBlock(OrderBlock &block) +{ + double currentPrice = (Ask + Bid) / 2; // Mid-price + return (currentPrice >= block.low && currentPrice <= block.high); +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Detect uptrend using moving averages | +//+------------------------------------------------------------------+ +bool IsUptrend() +{ + // + double maFast = fastMAs[0]; + double maSlow = slowMAs[0]; + + // + return (maFast > maSlow); +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Detect downtrend using moving averages | +//+------------------------------------------------------------------+ +bool IsDowntrend() +{ + // + double maFast = fastMAs[0]; + double maSlow = slowMAs[0]; + + // + return (maFast < maSlow); +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Find bullish order blocks | +//+------------------------------------------------------------------+ +OrderBlock FindBullishOrderBlock() +{ + // + OrderBlock block; + block.startTime = 0; + + // + for (int i = 1; i < 100; i++) + { + double prevHigh = iHigh(NULL, TimeFrame, i); + double prevLow = iLow(NULL, TimeFrame, i); + double prevClose = iClose(NULL, TimeFrame, i); + double prevOpen = iOpen(NULL, TimeFrame, i); + + double atr = atrs[i]; + if (prevClose - prevOpen > 1.5 * atr) + { // Strong bullish candle + double consolidationHigh = prevHigh; + double consolidationLow = prevLow; + bool isConsolidation = true; + + for (int j = 1; j <= OrderBlockLength; j++) + { + double newHigh = iHigh(NULL, TimeFrame, i - j); + double newLow = iLow(NULL, TimeFrame, i - j); + consolidationHigh = MathMax(consolidationHigh, newHigh); + consolidationLow = MathMin(consolidationLow, newLow); + + if ((consolidationHigh - consolidationLow) > 0.5 * atr) + { + isConsolidation = false; + break; + } + } + + if (isConsolidation) + { + block.high = consolidationHigh; + block.low = consolidationLow; + block.startTime = iTime(NULL, TimeFrame, i); + return block; + } + } + } + return block; +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Find bearish order blocks | +//+------------------------------------------------------------------+ +OrderBlock FindBearishOrderBlock() +{ + // + OrderBlock block; + block.startTime = 0; + + // + for (int i = 1; i < 100; i++) + { + double prevHigh = iHigh(NULL, TimeFrame, i); + double prevLow = iLow(NULL, TimeFrame, i); + double prevClose = iClose(NULL, TimeFrame, i); + double prevOpen = iOpen(NULL, TimeFrame, i); + + double atr = atrs[i]; + if (prevOpen - prevClose > 1.5 * atr) + { // Strong bearish candle + double consolidationHigh = prevHigh; + double consolidationLow = prevLow; + bool isConsolidation = true; + + for (int j = 1; j <= OrderBlockLength; j++) + { + double newHigh = iHigh(NULL, TimeFrame, i - j); + double newLow = iLow(NULL, TimeFrame, i - j); + consolidationHigh = MathMax(consolidationHigh, newHigh); + consolidationLow = MathMin(consolidationLow, newLow); + + if ((consolidationHigh - consolidationLow) > 0.5 * atr) + { + isConsolidation = false; + break; + } + } + + if (isConsolidation) + { + block.high = consolidationHigh; + block.low = consolidationLow; + block.startTime = iTime(NULL, TimeFrame, i); + return block; + } + } + } + return block; +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Confirm bullish entry with candle pattern | +//+------------------------------------------------------------------+ +bool ConfirmBullishEntry() +{ + // + int shift = iBarShift(NULL, TimeFrame, TimeCurrent()); + double prevLow = iLow(NULL, TimeFrame, shift + 1); + double currentClose = iClose(NULL, TimeFrame, shift); + return (currentClose > prevLow && iOpen(NULL, TimeFrame, shift) < currentClose); +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Confirm bearish entry with candle pattern | +//+------------------------------------------------------------------+ +bool ConfirmBearishEntry() +{ + // + int shift = iBarShift(NULL, TimeFrame, TimeCurrent()); + double prevHigh = iHigh(NULL, TimeFrame, shift + 1); + double currentClose = iClose(NULL, TimeFrame, shift); + return (currentClose < prevHigh && iOpen(NULL, TimeFrame, shift) > currentClose); +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Execute trade with risk management | +//+------------------------------------------------------------------+ +void ExecuteTrade(OrderBlock &block, ENUM_ORDER_TYPE orderType) +{ + // + double atr = atrs[0]; + double stopLoss, takeProfit, lotSize; + double entryPrice = (orderType == ORDER_TYPE_BUY) ? Ask : Bid; + + // Calculate stop loss and take profit + if (orderType == ORDER_TYPE_BUY) + { + stopLoss = block.low - StopLossMultiplier * atr; + takeProfit = entryPrice + (entryPrice - stopLoss) * TakeProfitRatio; + } + else + { + stopLoss = block.high + StopLossMultiplier * atr; + takeProfit = entryPrice - (stopLoss - entryPrice) * TakeProfitRatio; + } + + // Calculate lot size based on risk + lotSize = CalculateLotSize(stopLoss, entryPrice, orderType); + if (lotSize <= 0) + return; + + // Place order + if (orderType == ORDER_TYPE_BUY) + { + trade.Buy(lotSize, _Symbol, entryPrice, stopLoss, takeProfit, "SMC Bullish Order Block"); + } + else + { + trade.Sell(lotSize, _Symbol, entryPrice, stopLoss, takeProfit, "SMC Bearish Order Block"); + } +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Calculate lot size based on risk per trade | +//+------------------------------------------------------------------+ +double CalculateLotSize(double stopLoss, double entryPrice, ENUM_ORDER_TYPE orderType) +{ + double riskAmount = AccountBalance() * RiskPercent / 100; + double stopLossPips = MathAbs((entryPrice - stopLoss) / SymbolInfoDouble(_Symbol, SYMBOL_POINT)); + + if (stopLossPips == 0) + return 0; + + double pipValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE); + double lotSize = riskAmount / (stopLossPips * pipValue); + lotSize = NormalizeDouble(lotSize, 2); // Adjust to symbol's lot precision + + return MathMax(lotSize, SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN)); +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Check for existing open orders | +//+------------------------------------------------------------------+ +bool CheckOpenOrders() +{ + for (int i = 0; i < PositionsTotal(); i++) + { + if (PositionGetSymbol(i) == _Symbol) + return true; + } + return false; +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Trailing stop logic | +//+------------------------------------------------------------------+ +void TrailStop() +{ + for (int i = 0; i < PositionsTotal(); i++) + { + if (PositionGetSymbol(i) != _Symbol) + continue; + + ulong ticket = PositionGetInteger(POSITION_TICKET); + ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); + double currentPrice = (type == POSITION_TYPE_BUY) ? Bid : Ask; + double openPrice = PositionGetDouble(POSITION_PRICE_OPEN); + double stopLoss = PositionGetDouble(POSITION_SL); + double trailingStopPrice = (type == POSITION_TYPE_BUY) + ? currentPrice - TrailingStopPips * SymbolInfoDouble(_Symbol, SYMBOL_POINT) + : currentPrice + TrailingStopPips * SymbolInfoDouble(_Symbol, SYMBOL_POINT); + + // Update stop loss if price moves favorably + if ((type == POSITION_TYPE_BUY && trailingStopPrice > stopLoss) || + (type == POSITION_TYPE_SELL && trailingStopPrice < stopLoss)) + { + trade.PositionModify(ticket, trailingStopPrice, PositionGetDouble(POSITION_TP)); + } + } +} +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Calculate Account Balance | +//+------------------------------------------------------------------+ +double AccountBalance() +{ + return accountInfo.Balance(); +} +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Documents/BKP/testob.mq5 b/BKPS/14031218/Documents/BKP/testob.mq5 new file mode 100644 index 0000000..8910672 --- /dev/null +++ b/BKPS/14031218/Documents/BKP/testob.mq5 @@ -0,0 +1,275 @@ +//+------------------------------------------------------------------+ +//| OrderBlockDetector.mq5| +//| Copyright 2023, MetaQuotes Software Corp. | +//| https://www.mql5.com| +//+------------------------------------------------------------------+ +#property strict + +// +// Input Parameters +input int ConsolidationPeriod = 20; // Bars for consolidation detection +input int AtrPeriod = 14; // ATR period for volatility +input double AtrMultiplier = 2.0; // Threshold multiplier (ATR * multiplier) +input int VolumeThreshold = 1000; // Minimum volume for breakout +input bool RequireRetest = true; // Retest confirmation required? +input int VpvrBars = 50; // Bars for VPVR calculation +input int TrendCheckPeriod = 30; // Bars for trend structure analysis +input int MACDFast = 12; // MACD Fast EMA period +input int MACDSlow = 26; // MACD Slow EMA period +input int MACDSignal = 9; // MACD Signal period +input int RSIPeriod = 14; // RSI period +input double RSILevel = 50; // RSI threshold level + +// Global Variables +int ObjectId = 0; +string Prefix = "OrderBlock_"; + +// +enum ENUM_X_DIRECTION +{ + X_DIRECTION_NONE, + X_DIRECTION_BULISH, + X_DIRECTION_BEARISH, +}; + +// +int atrHandler = INVALID_HANDLE; +double atrBuffer[]; + +// +int rsiHandler = INVALID_HANDLE; +double rsiBuffer[]; + +// +int macdHandler = INVALID_HANDLE; +double macdMainBuffer[]; +double macdSignalBuffer[]; + +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() +{ + // + ArraySetAsSeries(atrBuffer, true); + atrHandler = iATR(_Symbol, _Period, AtrPeriod); + + // + ArraySetAsSeries(rsiBuffer, true); + rsiHandler = iRSI(_Symbol, _Period, RSIPeriod, PRICE_CLOSE); + + // + ArraySetAsSeries(macdMainBuffer, true); + ArraySetAsSeries(macdSignalBuffer, true); + macdHandler = iMACD(_Symbol, _Period, MACDFast, MACDSlow, MACDSignal, PRICE_CLOSE); + + // + ObjectsDeleteAll(0, Prefix); + return (INIT_SUCCEEDED); +} + +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) +{ + // + IndicatorRelease(atrHandler); + ObjectsDeleteAll(0, Prefix); +} + +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() +{ + DetectOrderBlocks(); +} + +//+------------------------------------------------------------------+ +//| Detect Order Blocks with ATR Dynamic Threshold | +//+------------------------------------------------------------------+ +void DetectOrderBlocks() +{ + double high, low, vpvrPrice, atr, dynamicThreshold; + datetime startTime, endTime; + bool isBullish, isBearish; + int bars = Bars(_Symbol, _Period); + + for (int i = ConsolidationPeriod; i < bars; i++) + { + // + // Get consolidation range + high = iHigh(_Symbol, _Period, iHighest(_Symbol, _Period, MODE_HIGH, ConsolidationPeriod, i)); + low = iLow(_Symbol, _Period, iLowest(_Symbol, _Period, MODE_LOW, ConsolidationPeriod, i)); + double range = high - low; + + // + // Calculate dynamic threshold using ATR + CopyBuffer(atrHandler, MAIN_LINE, i, 2, atrBuffer); + atr = atrBuffer[0]; + dynamicThreshold = atr * AtrMultiplier; + + // Check if consolidation range is within ATR-based threshold + if (range <= dynamicThreshold) + { + // VPVR Integration + vpvrPrice = CalculateVPVR(i, ConsolidationPeriod); + bool validVPVR = (vpvrPrice > low && vpvrPrice < high); + + // Check breakout direction + isBullish = iClose(_Symbol, _Period, i - ConsolidationPeriod) > high; + isBearish = iClose(_Symbol, _Period, i - ConsolidationPeriod) < low; + + // Trend Verification + ENUM_X_DIRECTION trend = CheckTrendStructure(TrendCheckPeriod); + + // MACD/RSI Verification + bool macdValid = CheckMACD(trend); + bool rsiValid = CheckRSI(trend); + + // Validate all conditions + if ((isBullish || isBearish) && validVPVR && + (trend != -1) && macdValid && rsiValid) + { + double breakoutVolume = (double)iVolume(_Symbol, _Period, i - ConsolidationPeriod); + if (breakoutVolume < VolumeThreshold) + continue; + + // Define order block time window + startTime = iTime(_Symbol, _Period, i); + endTime = iTime(_Symbol, _Period, i + ConsolidationPeriod); + + // Check retest (if required) + if (RequireRetest) + { + bool retestFound = false; + for (int j = i - ConsolidationPeriod; j > 0; j--) + { + if ((isBullish && iLow(_Symbol, _Period, j) <= low && iLow(_Symbol, _Period, j) >= high) || + (isBearish && iHigh(_Symbol, _Period, j) >= high && iHigh(_Symbol, _Period, j) <= low)) + { + retestFound = true; + break; + } + } + if (!retestFound) + continue; + } + + // Draw order block with ATR annotation + string name = Prefix + IntegerToString(ObjectId++); + DrawOrderBlock(name, startTime, endTime, low, high, + isBullish ? clrGreen : clrRed, vpvrPrice, dynamicThreshold); + } + } + } +} + +//+------------------------------------------------------------------+ +//| Trend Detection using Price Structure | +//+------------------------------------------------------------------+ +ENUM_X_DIRECTION CheckTrendStructure(int period) +{ + int currentStart = 1; + int previousStart = period + 1; + + double currentHigh = iHigh(_Symbol, _Period, iHighest(_Symbol, _Period, MODE_HIGH, period, currentStart)); + double previousHigh = iHigh(_Symbol, _Period, iHighest(_Symbol, _Period, MODE_HIGH, period, previousStart)); + double currentLow = iLow(_Symbol, _Period, iLowest(_Symbol, _Period, MODE_LOW, period, currentStart)); + double previousLow = iLow(_Symbol, _Period, iLowest(_Symbol, _Period, MODE_LOW, period, previousStart)); + + if (currentHigh > previousHigh && currentLow > previousLow) + return (X_DIRECTION_BULISH); // Uptrend + else if (currentHigh < previousHigh && currentLow < previousLow) + return (X_DIRECTION_BEARISH); // Downtrend + else + return (X_DIRECTION_NONE); // No clear trend +} + +//+------------------------------------------------------------------+ +//| MACD Trend Verification | +//+------------------------------------------------------------------+ +bool CheckMACD(ENUM_X_DIRECTION trend) +{ + // + CopyBuffer(macdHandler, MAIN_LINE, 0, 1, macdMainBuffer); + CopyBuffer(macdHandler, SIGNAL_LINE, 0, 1, macdSignalBuffer); + double macdMain = macdMainBuffer[0]; + double macdSignal = macdSignalBuffer[0]; + + // + if (trend == X_DIRECTION_BULISH) + return (macdMain > macdSignal); + if (trend == X_DIRECTION_BEARISH) + return (macdMain < macdSignal); + return (false); +} + +//+------------------------------------------------------------------+ +//| RSI Trend Verification | +//+------------------------------------------------------------------+ +bool CheckRSI(ENUM_X_DIRECTION trend) +{ + // + CopyBuffer(rsiHandler, MAIN_LINE, 0, 1, rsiBuffer); + double rsiValue = rsiBuffer[0]; + + // + if (trend == X_DIRECTION_BULISH) + return (rsiValue > RSILevel); + if (trend == X_DIRECTION_BEARISH) + return (rsiValue < RSILevel); + return (false); +} + +//+------------------------------------------------------------------+ +//| Calculate VPVR High Volume Node | +//+------------------------------------------------------------------+ +double CalculateVPVR(int startIdx, int period) +{ + double maxVolume = 0; + double vpvrPrice = 0; + double price, volume; + + for (int i = startIdx; i < startIdx + period; i++) + { + price = (iHigh(_Symbol, _Period, i) + iLow(_Symbol, _Period, i)) / 2; + volume = (double)iVolume(_Symbol, _Period, i); + if (volume > maxVolume) + { + maxVolume = volume; + vpvrPrice = price; + } + } + return (vpvrPrice); +} + +//+------------------------------------------------------------------+ +//| Draw Order Block with ATR Annotation | +//+------------------------------------------------------------------+ +void DrawOrderBlock(string name, datetime startTime, datetime endTime, + double bottom, double top, color clr, double vpvrPrice, double atrThreshold) +{ + // Draw rectangle + ObjectCreate(0, name + "_rect", OBJ_RECTANGLE, 0, startTime, top, endTime, bottom); + ObjectSetInteger(0, name + "_rect", OBJPROP_COLOR, clr); + ObjectSetInteger(0, name + "_rect", OBJPROP_FILL, true); + ObjectSetInteger(0, name + "_rect", OBJPROP_BACK, true); + ObjectSetInteger(0, name + "_rect", OBJPROP_WIDTH, 2); + + // Draw VPVR marker + if (vpvrPrice > 0) + { + ObjectCreate(0, name + "_vpvr", OBJ_HLINE, 0, 0, vpvrPrice); + ObjectSetInteger(0, name + "_vpvr", OBJPROP_COLOR, clrYellow); + ObjectSetInteger(0, name + "_vpvr", OBJPROP_WIDTH, 1); + } + + // Add ATR threshold label + string atrLabel = StringFormat("ATR Threshold: %.5f", atrThreshold); + ObjectCreate(0, name + "_atr", OBJ_TEXT, 0, startTime, top); + ObjectSetString(0, name + "_atr", OBJPROP_TEXT, atrLabel); + ObjectSetInteger(0, name + "_atr", OBJPROP_COLOR, clrWhite); +} +//+------------------------------------------------------------------+ \ No newline at end of file diff --git a/BKPS/14031218/Documents/BKP/x-121.smc.xwz.signal.class copy 2.mq5 b/BKPS/14031218/Documents/BKP/x-121.smc.xwz.signal.class copy 2.mq5 new file mode 100644 index 0000000..1f79c25 --- /dev/null +++ b/BKPS/14031218/Documents/BKP/x-121.smc.xwz.signal.class copy 2.mq5 @@ -0,0 +1,2295 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 X121 SMC Signal Class +// ------------------------------------------------- +// Name: XWZ +// 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.guard.lib.mq5" +#include "../Libraries/x-121.smc.lib.mq5" +#include "./x-121.smc.xwz.signal.lib.mq5" + +// +// Definition ... +class XCX121SMCXWZSignalDetector : public XCBase +{ + // + public: + // + // Props ... + X121SMCStrategyXWZWorkingZone workingZone; + X121SMCStrategyXWZSignalConditions mConditions; + X121SMCStrategyXWZSignalConditions mConditionsCollection[]; + + // + // Constructor(s) ... + XCX121SMCXWZSignalDetector( + string _symbol, + ENUM_TIMEFRAMES _period // + ) + { + // + symbol = _symbol; + period = _period; + Init(); + } + + // + // Deconstructor ... + ~XCX121SMCXWZSignalDetector() + { + DeInit(); + } + + // + // + // + + // + // Detect Setup Conditions ... + bool DetectSignalSetup( + // + XC121SMCCycleHelper *decisionCycleHelper, + XC121SMCCycleHelper *analyseCycleHelper, + XC121SMCCycleHelper *consolidationCycleHelper, + XC121SMCCycleHelper *visionCycleHelper, + // + double maxAllowedSLDistanceInPoint = 300 + // + ) + { + // + bool result = false; + + // + // Validate Cycle Helpers ... + result = + // + visionCycleHelper != NULL && + analyseCycleHelper != NULL && + decisionCycleHelper != NULL && + consolidationCycleHelper != NULL + // + ; + if (!result) + { + // + mConditions.Clean(); + + // + return result; + } + + // + bool isBullish = false; + bool isBearish = false; + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + int loopback = 10; + + // + mConditions.symbol = symbol; + mConditions.period = period; + + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + double points = GetPoints(symbol); + + // + // Cycles Conditions ... + + // + XOHCL consolidationZBar; + result = consolidationCycleHelper.GetBar( + consolidationZBar, + zIndex // + ); + if (!result) + { + // + consolidationZBar.Clean(); + return result; + } + + // + bool drawBar = false; + if (drawBar) + { + // + DrawBar( + consolidationZBar, + decisionCycleHelper.mPOIDrawer // + ); + } + + // + // Decision ... + ENUM_XPOI_EVENTS decisionPoiEvents[]; + ENUM_X_CYCLE_EVENTS decisionCycleEvents[]; + X121SMCCycleConditions decisionConditions; + result = decisionCycleHelper.GetConditions( + decisionCycleEvents, + decisionPoiEvents, + decisionConditions, + zIndex, + loopback // + ); + if (!result) + { + // + Clean(decisionPoiEvents); + Clean(decisionCycleEvents); + + // + decisionConditions.Clean(); + + // + mConditions.Clean(); + consolidationZBar.Clean(); + + // + return result; + } + + // + // Analyse ... + ENUM_XPOI_EVENTS analysePoiEvents[]; + ENUM_X_CYCLE_EVENTS analyseCycleEvents[]; + X121SMCCycleConditions analyseConditions; + result = analyseCycleHelper.GetConditions( + analyseCycleEvents, + analysePoiEvents, + analyseConditions, + zIndex, + loopback // + ); + if (!result) + { + // + Clean(analysePoiEvents); + Clean(decisionPoiEvents); + + // + Clean(analyseCycleEvents); + Clean(decisionCycleEvents); + + // + analyseConditions.Clean(); + decisionConditions.Clean(); + + // + mConditions.Clean(); + consolidationZBar.Clean(); + + // + return result; + } + + // + // Consolidation ... + ENUM_XPOI_EVENTS consolidationPoiEvents[]; + ENUM_X_CYCLE_EVENTS consolidationCycleEvents[]; + X121SMCCycleConditions consolidationConditions; + result = consolidationCycleHelper.GetConditions( + consolidationCycleEvents, + consolidationPoiEvents, + consolidationConditions, + zIndex, + loopback // + ); + if (!result) + { + // + Clean(analysePoiEvents); + Clean(decisionPoiEvents); + Clean(consolidationPoiEvents); + + // + Clean(analyseCycleEvents); + Clean(decisionCycleEvents); + Clean(consolidationCycleEvents); + + // + analyseConditions.Clean(); + decisionConditions.Clean(); + consolidationConditions.Clean(); + + // + mConditions.Clean(); + consolidationZBar.Clean(); + + // + return result; + } + + // + // Vision ... + ENUM_XPOI_EVENTS visionPoiEvents[]; + ENUM_X_CYCLE_EVENTS visionCycleEvents[]; + X121SMCCycleConditions visionConditions; + result = visionCycleHelper.GetConditions( + visionCycleEvents, + visionPoiEvents, + visionConditions, + zIndex, + loopback // + ); + if (!result) + { + // + Clean(visionPoiEvents); + Clean(analysePoiEvents); + Clean(decisionPoiEvents); + Clean(consolidationPoiEvents); + + // + Clean(visionCycleEvents); + Clean(analyseCycleEvents); + Clean(decisionCycleEvents); + Clean(consolidationCycleEvents); + + // + visionConditions.Clean(); + analyseConditions.Clean(); + decisionConditions.Clean(); + consolidationConditions.Clean(); + + // + mConditions.Clean(); + consolidationZBar.Clean(); + + // + return result; + } + + // + // Cycles POI States ... + XPOIState decisionState = decisionConditions.state; + XPOIState analyseState = analyseConditions.state; + XPOIState consolidationState = consolidationConditions.state; + XPOIState visionState = visionConditions.state; + + // + // Cycle X121Conditions ... + X121Conditions decisionXConditions = decisionConditions.x121Conditions; + X121Conditions analyseXConditions = analyseConditions.x121Conditions; + X121Conditions consolidationXConditions = consolidationConditions.x121Conditions; + X121Conditions visionXConditions = visionConditions.x121Conditions; + + // + // Scores ... + + // + // Decision ... + double decisionBullishScore = 0; + double decisionBearishScore = 0; + decisionXConditions.GenerateScore( + decisionBullishScore, + decisionBearishScore // + ); + + // + // Analyse ... + double analyseBullishScore = 0; + double analyseBearishScore = 0; + analyseXConditions.GenerateScore( + analyseBullishScore, + analyseBearishScore // + ); + + // + // + // + + // + bool hasNewSupply = Contains( + X_SUPPLY_ZONE_DETECTED, + analysePoiEvents // + ); + + // + bool hasNewDemand = Contains( + X_DEMAND_ZONE_DETECTED, + analysePoiEvents // + ); + + // + bool hasNewFairValueGap = + Contains( + X_BULLISH_FVG_DETECTED, + analysePoiEvents // + ) || + Contains( + X_BEARISH_FVG_DETECTED, + analysePoiEvents // + ); + + // + bool hasNewOrderBlock = + Contains( + X_BULLISH_ORDERBLOCK_DETECTED, + analysePoiEvents // + ) || + Contains( + X_BEARISH_ORDERBLOCK_DETECTED, + analysePoiEvents // + ); + + // + // + // + + // + // Select Drawer Class ... + XCPOIDrawer *drawer = visionCycleHelper.mPOIDrawer; + + // + // Setup Conditions ... + double sls[]; + double sl = 0; + double pivot = 0; + double point = 0; + double targets[]; + double reward = 0; + XBoxZone signalBox; + double amountPercent = 0; + bool hasPriority = false; + bool hasSignalBox = false; + bool hasRewardAmount = false; + bool isSignalBoxReversal = false; + bool hasWorkingZoneOveralDirection = false; + ENUM_X_DIRECTION wzOveralDir = X_DIRECTION_NONE; + ENUM_X_DIRECTION signalBoxDir = X_DIRECTION_NONE; + ENUM_X121SMC_XWZ_PRIORITY priority = X121SMC_XWZ_PRIORITY_NONE; + ENUM_X121SMC_XWZ_PROVIDERS provider = X121SMC_XWZ_PROVIDER_NONE; + + // + // + // + + // + // First We Have to Has Working Zone ... + bool hasWorkingZone = workingZone.IsValid(); + if (!hasWorkingZone) + { + // + hasWorkingZone = workingZone.Init( + symbol, + period, + zIndex, + visionState, + consolidationState, + analyseState, + decisionState // + ); + } + + // + // Update Working Zone ... + if (hasWorkingZone) + { + // + // Reset POI Detector Required POI(s) ... + visionCycleHelper.mPOIDetector.MaxRequiredPOIs(50); + analyseCycleHelper.mPOIDetector.MaxRequiredPOIs(50); + decisionCycleHelper.mPOIDetector.MaxRequiredPOIs(50); + consolidationCycleHelper.mPOIDetector.MaxRequiredPOIs(50); + + // + // Reset POI Detector Allowed Loopback ... + visionCycleHelper.mPOIDetector.MaxAllowedLoopbackForInit(578); + analyseCycleHelper.mPOIDetector.MaxAllowedLoopbackForInit(578); + decisionCycleHelper.mPOIDetector.MaxAllowedLoopbackForInit(578); + consolidationCycleHelper.mPOIDetector.MaxAllowedLoopbackForInit(578); + + // + // Update Working Zone ... + // workingZone.Update( + // zIndex, + // visionState, + // consolidationState, + // analyseState, + // decisionState // + // ); + + // + // Check Working Zone Overal Direction ... + hasWorkingZoneOveralDirection = workingZone + .DetectOveralDirection(wzOveralDir); + + // + // Checking Working Zone Destory or not ... + bool isWorkingZoneDestroyed = workingZone.IsDestroyed( + zIndex, + period // + ); + + // + // Cleanup WorkingZone and ignore all conditions ... + if (isWorkingZoneDestroyed) + { + // + result = false; + workingZone.Clean(); + hasWorkingZone = false; + + // + // Cleanup Resources ... + Clean(visionPoiEvents); + Clean(analysePoiEvents); + Clean(decisionPoiEvents); + Clean(consolidationPoiEvents); + + // + Clean(visionCycleEvents); + Clean(analyseCycleEvents); + Clean(decisionCycleEvents); + Clean(consolidationCycleEvents); + + // + visionState.Clean(); + analyseState.Clean(); + decisionState.Clean(); + consolidationState.Clean(); + + // + visionConditions.Clean(); + analyseConditions.Clean(); + decisionConditions.Clean(); + consolidationConditions.Clean(); + + // + visionXConditions.Clean(); + analyseXConditions.Clean(); + decisionXConditions.Clean(); + consolidationXConditions.Clean(); + + // + mConditions.Clean(); + consolidationZBar.Clean(); + + // + return result; + } + } + + // + // + // + + // + // Waiting Box Detected ... + bool hasWaitingBoxes = hasWorkingZone && + workingZone.HasWaitingBoxes(); + if (hasWaitingBoxes) + { + // + XOHCL zBar; + XOHCL cBar; + XOHCL pBar; + int count = 0; + int idx = -1; + bool has = false; + + // + bool isInited = zBar.Init( + symbol, + period, + zIndex // + ); + isInited = + isInited && + zBar.GetPreviousBar(cBar); + isInited = + isInited && + cBar.GetPreviousBar(pBar); + + // + count = workingZone.CountWaitingBoxes(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = workingZone.waitingBoxes[i]; + ENUM_X_DIRECTION iDir = iBox.dir; + bool isBullish = IsBullish(iDir); + + // + // Check Price Rejection ... + + // + bool hasBullishFiboPressure = + decisionCycleHelper + .mBarAnalyser + .HasFiboPressure( + cBar, + X_DIRECTION_BULLISH, + X_FIBO_LEVEL_382 // + ); + + // + bool hasBearishFiboPressure = + decisionCycleHelper + .mBarAnalyser + .HasFiboPressure( + cBar, + X_DIRECTION_BEARISH, + X_FIBO_LEVEL_382 // + ); + + // + // Bullish Rejection ... + bool isBullishRejected = + // + isInited && + isBullish && + cBar.low < pBar.low && + zBar.low > iBox.upper && + cBar.low <= iBox.upper && + zBar.open > iBox.upper && + hasBullishFiboPressure && + cBar.GetLowShadow() > pBar.GetLowShadow() + // + ; + + // + // Bearish Rejection ... + bool isBearishhRejected = + // + isInited && + !isBullish && + cBar.high > pBar.high && + zBar.open < iBox.lower && + zBar.high < iBox.lower && + hasBearishFiboPressure && + cBar.high >= iBox.lower && + cBar.GetHighShadow() > pBar.GetHighShadow() + // + ; + + // + has = isBullishRejected || + isBearishhRejected; + if (has) + { + // + idx = i; + signalBox = iBox; + hasSignalBox = has; + signalBox.to = cTime; + signalBoxDir = iBox.dir; + isSignalBoxReversal = false; + provider = X121SMC_XWZ_PROVIDER_ACTIVATED_ZONE; + } + + // + iBox.Clean(); + } + + // + // Remove Signal Box from Waiting Boxes of + // Working Zone ... + if (hasSignalBox) + { + // + if (IsValidIndex(idx)) + { + // + ArrayRemove( + workingZone.waitingBoxes, + idx, + 1 // + ); + } + } + + // + // Ignore Zone's Signals ... + hasSignalBox = false; + + // + // Cleanup Resources ... + + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + } + + // + // Check Conditions if Has Inside Boxes ... + bool hasInsideBoxes = hasWorkingZone && + workingZone.HasInsideBoxes(); + if (hasInsideBoxes) + { + } + + // + // Check Conditions if has Breaked Boxes ... + bool hasBreakedBoxes = hasWorkingZone && + workingZone.HasBreakedBoxes(); + if (hasBreakedBoxes) + { + } + + // + // Checking Other Conditions ... + if (!hasSignalBox) + { + // + // Senari A ... + // hasSignalBox = hasWorkingZone && + // workingZone.DetectSenarioASignalBox( + // signalBox, + // signalBoxDir, + // decisionXConditions, + // analyseXConditions, + // decisionCycleHelper, + // drawer, + // zIndex // + // ); + // if (hasSignalBox) + // { + // // + // signalBox.to = cTime; + // isSignalBoxReversal = false; + // provider = X121SMC_XWZ_PROVIDER_PV_ZONE; + // } + + // // + // // Validating Signal Box if Exists ... + // if (hasSignalBox) + // { + // // + // // Validate Signal Boxes using Inside Box ... + // if (hasInsideBoxes) + // { + // // + // int idx = -1; + // bool has = false; + + // // + // idx = + // IsBullish(signalBoxDir) + // ? GetLowest(workingZone.insideBoxes) + // : GetHighest(workingZone.insideBoxes); + // has = IsValidIndex(idx); + // if (has) + // { + // // + // hasSignalBox = + // signalBoxDir == workingZone.insideBoxes[idx].dir; + // } + // } + + // // + // // Validate Signal Box Using Overal Trend ... + // if (hasWorkingZoneOveralDirection) + // { + // // + // hasSignalBox = + // signalBoxDir == wzOveralDir; + // } + // } + } + + // + // + // + + // + // Cleanup Signal if UnApproved ... + if (!hasSignalBox) + { + // + signalBox.Clean(); + signalBoxDir = X_DIRECTION_NONE; + } + + // + // + // + + // + // Check Priority Exists ... + hasPriority = workingZone + .DetectPriority( + priority, + signalBoxDir, + zIndex, + period // + ); + + // + // Check Price Reward and Amount Exists ... + hasRewardAmount = CalculateRiskReward( + priority, + reward, + amountPercent // + ); + + // + // Check Signal Conditions ... + if (hasSignalBox) + { + // + int idx = -1; + bool has = false; + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + signalBox, + iObj // + ); + if (has) + { + // + iObj.BoxWidth(1); + iObj.BoxColor(clrYellow); + iObj.BoxStyle(STYLE_SOLID); + } + + // + isBullish = IsBullish(signalBoxDir); + isBearish = IsBearish(signalBoxDir); + + // + pivot = isBullish + ? signalBox.lower + : signalBox.upper; + + // + point = isBullish + ? signalBox.upper + : signalBox.lower; + + // + double iSL = 0; + double signalBoxRange = (signalBox.upper - signalBox.lower); + if (signalBoxRange < points * 100) + { + iSL = pivot; + } + else + { + iSL = signalBox.lower + (signalBox.upper - signalBox.lower) / 2; + } + + // + if (provider == X121SMC_XWZ_PROVIDER_PV_ZONE) + { + } + + // + Add( + iSL, + sls // + ); + + // + // Select Condition SL ... + + // + double entry = GetEntry( + signalBox.symbol, + signalBoxDir // + ); + + // + double slsMin = GetMin(sls); + double slsMax = GetMax(sls); + + // + double longSL = slsMin; + double shortSL = slsMax; + + // + sl = isBullish + ? longSL + : shortSL; + + // + // Targets ... + + // + // Force Add TP 2 as Target ... + double risk = MathAbs(entry - sl); + double reward2 = 2 * risk; + // double iTP2 = isBullish + // ? entry + reward2 + // : entry - reward2; + // Add( + // iTP2, + // targets // + // ); + + // + // Based On Priority ... + has = priority != X121SMC_XWZ_PRIORITY_NONE; + if (has) + { + // + switch (priority) + { + // + case X121SMC_XWZ_PRIORITY_WEAK: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + } + break; + + // + case X121SMC_XWZ_PRIORITY_LOW: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter1, + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter3, + targets // + ); + } + break; + + // + case X121SMC_XWZ_PRIORITY_REGULAR: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter1, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter3, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + } + break; + + // + case X121SMC_XWZ_PRIORITY_HIGH: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter1, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + + // + // High ... + Add( + workingZone.quarter3, + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter3, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + + // + // High ... + Add( + workingZone.quarter1, + targets // + ); + } + break; + + // + case X121SMC_XWZ_PRIORITY_STRONG_HIGH: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter1, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + + // + // High ... + Add( + workingZone.quarter3, + targets // + ); + + // + // Strong High ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter3, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + + // + // High ... + Add( + workingZone.quarter1, + targets // + ); + + // + // Strong High ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + } + break; + } + } + + // + XBoxZone waitingBoxes[]; + has = workingZone.HasWaitingBoxes(); + if (has) + { + // + Copy( + workingZone.waitingBoxes, + waitingBoxes // + ); + + // + while (HasChild(waitingBoxes)) + { + // + XBoxZone iBox; + idx = GetYoungest(waitingBoxes); + has = IsValidIndex(idx); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + iBox = waitingBoxes[idx]; + ArrayRemove( + waitingBoxes, + idx, + 1 // + ); + + // + bool hasInside = workingZone.HasInsideBox(iBox); + if (!hasInside) + { + continue; + } + + // + double iTarget = + IsBullish(signalBoxDir) + ? iBox.lower + : iBox.upper; + + // + Add( + iTarget, + targets // + ); + + // + iBox.Clean(); + } + } + } + + // + // Summarize Results ... + result = hasPriority && + hasSignalBox && + hasRewardAmount; + + // + if (result) + { + // + Copy( + sls, + mConditions.sls // + ); + Copy( + targets, + mConditions.targets // + ); + + // + mConditions.sl = sl; + mConditions.pivot = pivot; + mConditions.point = point; + mConditions.reward = reward; + mConditions.setupTime = cTime; + mConditions.dir = signalBoxDir; + mConditions.priority = priority; + mConditions.provider = provider; + mConditions.signalBox = signalBox; + mConditions.amountPercent = amountPercent; + } + + // + UpdateTo(cTime); + + // + // Draw Working Zone ... + if (hasWorkingZone) + { + // + workingZone.Draw( + drawer, + // + true, // Draw Waiting Boxes ... + true, // Draw Inside Boxes ... + true, // Draw Breaked Boxes ... + true, // Draw Breaked Inside Boxes ... + // + true, // Draw Supply Zone ... + true, // Draw Demand Zone ... + true, // Draw Supply Zones ... + true, // Draw Demand Zones ... + true, // Draw Support Zones ... + true // Draw Resistance Zones ... + ); + } + + // + // + // + + // + // Cleanup Resources ... + + // + Clean(visionPoiEvents); + Clean(analysePoiEvents); + Clean(decisionPoiEvents); + Clean(consolidationPoiEvents); + + // + Clean(visionCycleEvents); + Clean(analyseCycleEvents); + Clean(decisionCycleEvents); + Clean(consolidationCycleEvents); + + // + visionState.Clean(); + analyseState.Clean(); + decisionState.Clean(); + consolidationState.Clean(); + + // + visionConditions.Clean(); + analyseConditions.Clean(); + decisionConditions.Clean(); + consolidationConditions.Clean(); + + // + visionXConditions.Clean(); + analyseXConditions.Clean(); + decisionXConditions.Clean(); + consolidationXConditions.Clean(); + + // + consolidationZBar.Clean(); + + // + return result; + } + + // + // Detect Trigger Conditions ... + bool DetectSignalTrigger( + // + X121SMCStrategyXWZSignalConditions &conditions, + // + XC121SMCCycleHelper *decisionCycleHelper, + XC121SMCCycleHelper *analyseCycleHelper, + XC121SMCCycleHelper *consolidationCycleHelper, + XC121SMCCycleHelper *visionCycleHelper, + // + int maxAllowedSetupAge = 60 + // + ) + { + // + bool result = false; + + // + result = + // + visionCycleHelper != NULL && + analyseCycleHelper != NULL && + decisionCycleHelper != NULL && + consolidationCycleHelper != NULL + // + ; + if (!result) + { + return result; + } + + // + result = conditions.IsSetuped(); + if (!result) + { + return result; + } + + // + datetime setupTime = conditions.setupTime; + ENUM_X_DIRECTION setupDir = conditions.dir; + + // + bool isBullish = IsBullish(setupDir); + bool isBearish = IsBearish(setupDir); + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + int loopback = 10; + + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + double points = GetPoints(symbol); + + // + // Cycles Conditions ... + + // + // Decision ... + ENUM_XPOI_EVENTS decisionPoiEvents[]; + ENUM_X_CYCLE_EVENTS decisionCycleEvents[]; + X121SMCCycleConditions decisionConditions; + result = decisionCycleHelper.GetConditions( + decisionCycleEvents, + decisionPoiEvents, + decisionConditions, + zIndex, + loopback // + ); + if (!result) + { + // + // Cleanup ... + + // + Clean(decisionPoiEvents); + Clean(decisionCycleEvents); + + // + decisionConditions.Clean(); + + // + return result; + } + + // + // Analyse ... + ENUM_XPOI_EVENTS analysePoiEvents[]; + ENUM_X_CYCLE_EVENTS analyseCycleEvents[]; + X121SMCCycleConditions analyseConditions; + result = analyseCycleHelper.GetConditions( + analyseCycleEvents, + analysePoiEvents, + analyseConditions, + zIndex, + loopback // + ); + if (!result) + { + // + Clean(analysePoiEvents); + Clean(decisionPoiEvents); + + // + Clean(analyseCycleEvents); + Clean(decisionCycleEvents); + + // + analyseConditions.Clean(); + decisionConditions.Clean(); + + // + return result; + } + + // + // Cycles POI States ... + XPOIState decisionState = decisionConditions.state; + XPOIState analyseState = analyseConditions.state; + + // + // Cycle X121Conditions ... + X121Conditions decisionXConditions = decisionConditions.x121Conditions; + X121Conditions analyseXConditions = analyseConditions.x121Conditions; + + // + double iAtr = decisionXConditions.atrBuffer[1]; + iAtr *= 1.5; + + // + // Check Signal Validation ... + // IMPORTANT: since all Validations done in SetUp Process ... + // here we only Execute Signal ... + + // + result = isBullish || + isBearish; + + // + if (result) + { + // + conditions.triggerTime = cTime; + conditions.type = isBullish + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_SHORT; + + // + } + + // + // Cleanup ... + + // + Clean(decisionPoiEvents); + Clean(decisionCycleEvents); + + // + decisionState.Clean(); + decisionConditions.Clean(); + decisionXConditions.Clean(); + + // + Clean(analysePoiEvents); + Clean(analyseCycleEvents); + + // + analyseState.Clean(); + analyseConditions.Clean(); + analyseXConditions.Clean(); + + // + return result; + } + + // + // Detect Guards ... + bool DetectGuards( + // + X121SMCGuard &guards[], + const XPosition &positions[], + // + XC121SMCCycleHelper *decisionCycleHelper, + XC121SMCCycleHelper *analyseCycleHelper, + XC121SMCCycleHelper *consolidationCycleHelper, + XC121SMCCycleHelper *visionCycleHelper + // + ) + { + // + bool result = false; + return false; + + // + Clean(guards); + + // + bool isCycleHelpersValid = + // + visionCycleHelper != NULL && + analyseCycleHelper != NULL && + decisionCycleHelper != NULL && + consolidationCycleHelper != NULL + // + ; + + // + // Set Provider for Common Guards ... + string provider = ToString(X_121_SMC_PROVIDER_XWZ); + + // + // Check Cycle Helpers Validation ... + result = isCycleHelpersValid; + if (!result) + { + return result; + } + + // + // Select Own Positions ... + int count = ArraySize(positions); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + XPosition ownPositions[]; + XPosition ownLongPositions[]; + XPosition ownShortPositions[]; + for (int i = 0; i < count; i++) + { + // + XPosition iPosition = positions[i]; + bool isOwn = iPosition + .IsFiltersPassed( + symbol, + provider, + NULL, + X_POSITION_TYPE_ALL, + iPosition.magic // + ); + if (isOwn) + { + // + AddRef( + iPosition, + ownPositions // + ); + + // + bool isLong = IsLong(positions[i].type); + if (isLong) + { + // + AddRef( + iPosition, + ownLongPositions // + ); + } + else + { + // + AddRef( + iPosition, + ownShortPositions // + ); + } + } + } + + // + // Check Extracted Positions ... + + // + count = ArraySize(ownPositions); + + // + int longsCount = ArraySize(ownLongPositions); + bool hasLongs = IsValidSize(longsCount); + + // + int shortsCount = ArraySize(ownShortPositions); + bool hasShorts = IsValidSize(shortsCount); + + // + // Validate Own Positions ... + result = IsValidSize(count); + if (!result) + { + // + Clean(ownPositions); + Clean(ownLongPositions); + Clean(ownShortPositions); + + // + return result; + } + + // + // + // + + // + // Get Global and Common Guards ... + + // + ENUM_X_121_SMC_GUARD_ACTIONS ignoreGuards[1] = { + X_121_SMC_GUARD_ACTION_TRAIL_STOP // + }; + result = DetectX121SMCGuards( + provider, + guards, + positions, + decisionCycleHelper, + analyseCycleHelper, + consolidationCycleHelper, + visionCycleHelper, + // + ignoreGuards + // + ); + + // + // + // + + // + // Implement Custom Implemented Guards ... + + // + // Here we Are Sure there is Positions to Guard ... + // based on Current Provider ... + + // + // Detect Required Data for Analyse Market to Guard Positions ... + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + int loopback = 10; + + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + double points = GetPoints(symbol); + + // + // Cycles Conditions ... + + // + // Decision ... + ENUM_XPOI_EVENTS decisionPoiEvents[]; + ENUM_X_CYCLE_EVENTS decisionCycleEvents[]; + X121SMCCycleConditions decisionConditions; + result = decisionCycleHelper.GetConditions( + decisionCycleEvents, + decisionPoiEvents, + decisionConditions, + zIndex, + loopback // + ); + if (!result) + { + // + Clean(decisionPoiEvents); + Clean(decisionCycleEvents); + + // + decisionConditions.Clean(); + + // + result = HasChild(guards); + return result; + } + + // + // Analyse ... + ENUM_XPOI_EVENTS analysePoiEvents[]; + ENUM_X_CYCLE_EVENTS analyseCycleEvents[]; + X121SMCCycleConditions analyseConditions; + result = analyseCycleHelper.GetConditions( + analyseCycleEvents, + analysePoiEvents, + analyseConditions, + zIndex, + loopback // + ); + if (!result) + { + // + Clean(decisionPoiEvents); + Clean(decisionCycleEvents); + + // + decisionConditions.Clean(); + + // + Clean(analysePoiEvents); + Clean(analyseCycleEvents); + + // + analyseConditions.Clean(); + + // + result = HasChild(guards); + return result; + } + + // + // Consolidation ... + ENUM_XPOI_EVENTS consolidationPoiEvents[]; + ENUM_X_CYCLE_EVENTS consolidationCycleEvents[]; + X121SMCCycleConditions consolidationConditions; + result = consolidationCycleHelper.GetConditions( + consolidationCycleEvents, + consolidationPoiEvents, + consolidationConditions, + zIndex, + loopback // + ); + if (!result) + { + // + Clean(decisionPoiEvents); + Clean(decisionCycleEvents); + + // + decisionConditions.Clean(); + + // + Clean(analysePoiEvents); + Clean(analyseCycleEvents); + + // + analyseConditions.Clean(); + + // + Clean(consolidationPoiEvents); + Clean(consolidationCycleEvents); + + // + consolidationConditions.Clean(); + + // + result = HasChild(guards); + return result; + } + + // + // Vision ... + ENUM_XPOI_EVENTS visionPoiEvents[]; + ENUM_X_CYCLE_EVENTS visionCycleEvents[]; + X121SMCCycleConditions visionConditions; + result = visionCycleHelper.GetConditions( + visionCycleEvents, + visionPoiEvents, + visionConditions, + zIndex, + loopback // + ); + if (!result) + { + // + Clean(decisionPoiEvents); + Clean(decisionCycleEvents); + + // + decisionConditions.Clean(); + + // + Clean(analysePoiEvents); + Clean(analyseCycleEvents); + + // + analyseConditions.Clean(); + + // + Clean(consolidationPoiEvents); + Clean(consolidationCycleEvents); + + // + consolidationConditions.Clean(); + + // + Clean(visionPoiEvents); + Clean(visionCycleEvents); + + // + visionConditions.Clean(); + + // + result = HasChild(guards); + return result; + } + + // + // Cycles POI States ... + XPOIState visionState = visionConditions.state; + XPOIState analyseState = analyseConditions.state; + XPOIState decisionState = decisionConditions.state; + XPOIState consolidationState = consolidationConditions.state; + + // + // Cycle X121Conditions ... + X121Conditions visionXConditions = visionConditions.x121Conditions; + X121Conditions analyseXConditions = analyseConditions.x121Conditions; + X121Conditions decisionXConditions = decisionConditions.x121Conditions; + X121Conditions consolidationXConditions = consolidationConditions.x121Conditions; + + // + // + // + + // + // Selected Consolidation Zones ... + + // + int idx = -1; + bool has = false; + + // + bool hasBullishConsolidationZone = false; + XConsolidationZone bullishConsolidationZone; + has = decisionState.HasBullishConsolidationZones(); + if (has) + { + // + idx = GetYoungest(decisionState.bullishConsolidationZones); + hasBullishConsolidationZone = IsValidIndex(idx); + if (hasBullishConsolidationZone) + { + bullishConsolidationZone = decisionState.bullishConsolidationZones[idx]; + } + } + + // + bool hasBearishConsolidationZone = false; + XConsolidationZone bearishConsolidationZone; + has = decisionState.HasBearishConsolidationZones(); + if (has) + { + // + idx = GetYoungest(decisionState.bearishConsolidationZones); + hasBearishConsolidationZone = IsValidIndex(idx); + if (hasBearishConsolidationZone) + { + bearishConsolidationZone = decisionState.bearishConsolidationZones[idx]; + } + } + + // + // Here We Have all Requirements for Guarding Positions ... + + // + // Available Guards: + // X_121_SMC_GUARD_ACTION_NONE + // X_121_SMC_GUARD_ACTION_CLOSE + // X_121_SMC_GUARD_ACTION_CLOSE_ALL + // X_121_SMC_GUARD_ACTION_CLOSE_LONGS + // X_121_SMC_GUARD_ACTION_CLOSE_SHORTS + // X_121_SMC_GUARD_ACTION_PARTIAL_CLOSE + // X_121_SMC_GUARD_ACTION_TRAIL_STOP + // X_121_SMC_GUARD_ACTION_TRAIL_TARGET + // X_121_SMC_GUARD_ACTION_HEDGE + + // + // X_121_SMC_GUARD_ACTION_CLOSE: + // Close Specified Position on Specified Conditions ... + + // + // X_121_SMC_GUARD_ACTION_CLOSE_ALL: + // Close All Positions on Specified Conditions ... + + // + // X_121_SMC_GUARD_ACTION_CLOSE_LONGS: + // Close All Long Positions on Specified Conditions ... + + // + // X_121_SMC_GUARD_ACTION_CLOSE_SHORTS: + // Close All Short Positions on Specified Conditions ... + + // + // X_121_SMC_GUARD_ACTION_PARTIAL_CLOSE: + // Partial Close Specified Position on Specified Conditions ... + + // + // X_121_SMC_GUARD_ACTION_TRAIL_STOP: + // Trail Stop Specified Position on Specified Conditions ... + bool handleStoptrailingBasedOnConsolidationZones = true; + for (int i = 0; i < count; i++) + { + // + XPosition iPosition = ownPositions[i]; + + // + bool isLong = IsLong(iPosition.type); + bool isInProfit = iPosition.profit > 0; + + // + double sl = iPosition.sl; + double tp = iPosition.tp; + + // + // Trail Stops Using Consolidation Zones ... + + // + bool canTraiLonglUsingCZone = + // + handleStoptrailingBasedOnConsolidationZones && + // + (isLong && + isInProfit && + hasBullishConsolidationZone && + bullishConsolidationZone.lower > iPosition.sl && + bullishConsolidationZone.lower > iPosition.entry) + // + ; + if (canTraiLonglUsingCZone) + { + sl = bullishConsolidationZone.lower; + } + + // + bool canTraiShortlUsingCZone = + // + handleStoptrailingBasedOnConsolidationZones && + // + (!isLong && + isInProfit && + hasBearishConsolidationZone && + bearishConsolidationZone.upper < iPosition.sl && + bearishConsolidationZone.upper < iPosition.entry) + // + ; + if (canTraiShortlUsingCZone) + { + sl = bearishConsolidationZone.upper; + } + + // + bool canTrailUsingCZone = + canTraiLonglUsingCZone || + canTraiShortlUsingCZone; + + // + bool isSLPassed = + sl > 0 && + (isLong + ? iPosition.price - sl >= points * 15 + : sl - iPosition.price >= points * 15); + + // + bool canTrail = + isSLPassed && + canTrailUsingCZone; + if (canTrail) + { + // + X121SMCGuard iGuard; + + // + iGuard.time = cTime; + iGuard.symbol = symbol; + iGuard.provider = provider; + iGuard.action = X_121_SMC_GUARD_ACTION_TRAIL_STOP; + + // + iGuard.ticket = iPosition.ticket; + + // + iGuard.sl = sl; + + // + AddGuard( + iGuard, + guards // + ); + } + } + + // + // X_121_SMC_GUARD_ACTION_TRAIL_TARGET: + // Trail Target Specified Position on Specified Conditions ... + + // + // X_121_SMC_GUARD_ACTION_HEDGE: + // Hedge all Positions on Specified Conditions ... + + // + // Cleanup Collections ... + + // + Clean(ownPositions); + Clean(ownLongPositions); + Clean(ownShortPositions); + + // + visionState.Clean(); + analyseState.Clean(); + decisionState.Clean(); + consolidationState.Clean(); + + // + visionConditions.Clean(); + analyseConditions.Clean(); + decisionConditions.Clean(); + consolidationConditions.Clean(); + + // + visionXConditions.Clean(); + analyseXConditions.Clean(); + decisionXConditions.Clean(); + consolidationXConditions.Clean(); + + // + Clean(visionPoiEvents); + Clean(analysePoiEvents); + Clean(decisionPoiEvents); + Clean(consolidationPoiEvents); + + // + Clean(visionCycleEvents); + Clean(analyseCycleEvents); + Clean(decisionCycleEvents); + Clean(consolidationCycleEvents); + + // + count = ArraySize(guards); + result = IsValidSize(count); + + // + return result; + } + + // + // Add Conditions to Conditions Collection ... + int AddConditionsIfNotExists( + int maxAllowed = 10 // + ) + { + // + int result = 0; + + // + bool isSetuped = IsValid(mConditions.setupTime) && + HasDirection(mConditions.dir); + if (!isSetuped) + { + return result; + } + + // + int count = ArraySize(mConditionsCollection); + if (IsValidSize(count)) + { + // + // Copy Original Items ... + X121SMCStrategyXWZSignalConditions tmpItems[]; + Copy( + mConditionsCollection, + tmpItems // + ); + + // + // Prese Item Data ... + bool isBullish = IsBullish(mConditions.dir); + + // + for (int i = 0; i < count; i++) + { + // + X121SMCStrategyXWZSignalConditions iItem = tmpItems[i]; + + // + bool canRemove = mConditions.dir == iItem.dir && + mConditions.pivot == iItem.pivot; + if (canRemove) + { + // + ArrayRemove( + mConditionsCollection, + i, + 1 // + ); + } + } + + // + Clean(tmpItems); + } + + // + AddRef( + mConditions, + mConditionsCollection // + ); + + // + // Remove Olds ... + CleanupArray( + mConditionsCollection, + maxAllowed // + ); + + // + result = ArraySize(mConditionsCollection); + + // + return result; + } + + // + // Draw Functions ... + // + + // + void DrawBar( + XOHCL &bar, + XCPOIDrawer *drawer, + bool forceClean = true // + ) + { + // + if (forceClean) + { + mBarObjects.Clear(); + } + + // + if (drawer == NULL || + !bar.IsValid()) + { + return; + } + + // + bool isBullish = bar.IsBullish(); + + // + int widthBar = 2; + bool fillShadowsBar = true; + ENUM_LINE_STYLE styleBar = STYLE_SOLID; + color clrBar = + isBullish + ? clrAqua + : clrMagenta; + + // + datetime to = bar.NextAt(); + + // + XCOHCLObject *iObj; + bool isCreated = drawer + .CreateBar( + bar, + iObj, + to // + ); + if (isCreated) + { + // + iObj.BarSpes( + widthBar, + clrBar, + styleBar // + ); + + // + iObj.LowShadowFill(fillShadowsBar); + iObj.HighShadowFill(fillShadowsBar); + + // + mBarObjects.Add(iObj); + } + } + + // + protected: + // + + // + private: + // + // Props ... + string symbol; + ENUM_TIMEFRAMES period; + CArrayObj mObjects; + CArrayObj mBarObjects; + CArrayObj mWorkingZoneObjects; + + /** + * Initialize ... + */ + void Init() + { + } + + /** + * DeInitialize ... + */ + void DeInit() + { + // + mConditions.Clean(); + workingZone.Clean(); + Clean(mConditionsCollection); + + // + mBarObjects.Clear(); + } + + /** + * Update To Time of Exists Components ... + * + * @param value: updated time ... + */ + void UpdateTo( + datetime value = NULL // + ) + { + // + value = NormalizeTime(value); + + // + workingZone.UpdateTo(value); + } + + // + // Helpers ... + + // + bool CalculateRiskReward( + ENUM_X121SMC_XWZ_PRIORITY priority, + double &reward, + double &amountPercent // + ) + { + // + bool result = false; + + // + reward = 0; + amountPercent = 0; + + // + result = priority != X121SMC_XWZ_PRIORITY_NONE; + if (!result) + { + return result; + } + + // + switch (priority) + { + // + case X121SMC_XWZ_PRIORITY_STRONG_HIGH: + // + reward = 6; + amountPercent = 2; + break; + + // + case X121SMC_XWZ_PRIORITY_HIGH: + // + reward = 4; + amountPercent = 2; + break; + + // + case X121SMC_XWZ_PRIORITY_REGULAR: + // + reward = 3; + amountPercent = 1.5; + break; + + // + case X121SMC_XWZ_PRIORITY_LOW: + // + reward = 2; + amountPercent = 1; + break; + + // + case X121SMC_XWZ_PRIORITY_WEAK: + // + reward = 1; + amountPercent = 0.5; + break; + } + + // + result = + // + reward > 0 && + amountPercent > 0 + // + ; + + // + return result; + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14031218/Documents/BKP/x-121.smc.xwz.signal.class copy.mq5 b/BKPS/14031218/Documents/BKP/x-121.smc.xwz.signal.class copy.mq5 new file mode 100644 index 0000000..c1e8cc2 --- /dev/null +++ b/BKPS/14031218/Documents/BKP/x-121.smc.xwz.signal.class copy.mq5 @@ -0,0 +1,2124 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 X121 SMC Signal Class +// ------------------------------------------------- +// Name: XWZ +// 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.guard.lib.mq5" +#include "../Libraries/x-121.smc.lib.mq5" +#include "./x-121.smc.xwz.signal.lib.mq5" + +// +// Definition ... +class XCX121SMCXWZSignalDetector : public XCBase +{ + // + public: + // + // Props ... + X121SMCStrategyXWZWorkingZone workingZone; + X121SMCStrategyXWZSignalConditions mConditions; + X121SMCStrategyXWZSignalConditions mConditionsCollection[]; + + // + // Constructor(s) ... + XCX121SMCXWZSignalDetector( + string _symbol, + ENUM_TIMEFRAMES _period // + ) + { + // + symbol = _symbol; + period = _period; + Init(); + } + + // + // Deconstructor ... + ~XCX121SMCXWZSignalDetector() + { + DeInit(); + } + + // + // + // + + // + // Detect Setup Conditions ... + bool DetectSignalSetup( + // + XC121SMCCycleHelper *decisionCycleHelper, + XC121SMCCycleHelper *analyseCycleHelper, + XC121SMCCycleHelper *consolidationCycleHelper, + XC121SMCCycleHelper *visionCycleHelper, + // + double maxAllowedSLDistanceInPoint = 300 + // + ) + { + // + bool result = false; + + // + // Validate Cycle Helpers ... + result = + // + visionCycleHelper != NULL && + analyseCycleHelper != NULL && + decisionCycleHelper != NULL && + consolidationCycleHelper != NULL + // + ; + if (!result) + { + // + mConditions.Clean(); + + // + return result; + } + + // + bool isBullish = false; + bool isBearish = false; + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + int loopback = 10; + + // + mConditions.symbol = symbol; + mConditions.period = period; + + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + double points = GetPoints(symbol); + + // + // Cycles Conditions ... + + // + XOHCL consolidationZBar; + result = consolidationCycleHelper.GetBar( + consolidationZBar, + zIndex // + ); + if (!result) + { + // + consolidationZBar.Clean(); + return result; + } + + // + bool drawBar = false; + if (drawBar) + { + // + DrawBar( + consolidationZBar, + decisionCycleHelper.mPOIDrawer // + ); + } + + // + // Decision ... + ENUM_XPOI_EVENTS decisionPoiEvents[]; + ENUM_X_CYCLE_EVENTS decisionCycleEvents[]; + X121SMCCycleConditions decisionConditions; + result = decisionCycleHelper.GetConditions( + decisionCycleEvents, + decisionPoiEvents, + decisionConditions, + zIndex, + loopback // + ); + if (!result) + { + // + Clean(decisionPoiEvents); + Clean(decisionCycleEvents); + + // + decisionConditions.Clean(); + + // + mConditions.Clean(); + consolidationZBar.Clean(); + + // + return result; + } + + // + // Analyse ... + ENUM_XPOI_EVENTS analysePoiEvents[]; + ENUM_X_CYCLE_EVENTS analyseCycleEvents[]; + X121SMCCycleConditions analyseConditions; + result = analyseCycleHelper.GetConditions( + analyseCycleEvents, + analysePoiEvents, + analyseConditions, + zIndex, + loopback // + ); + if (!result) + { + // + Clean(analysePoiEvents); + Clean(decisionPoiEvents); + + // + Clean(analyseCycleEvents); + Clean(decisionCycleEvents); + + // + analyseConditions.Clean(); + decisionConditions.Clean(); + + // + mConditions.Clean(); + consolidationZBar.Clean(); + + // + return result; + } + + // + // Consolidation ... + ENUM_XPOI_EVENTS consolidationPoiEvents[]; + ENUM_X_CYCLE_EVENTS consolidationCycleEvents[]; + X121SMCCycleConditions consolidationConditions; + result = consolidationCycleHelper.GetConditions( + consolidationCycleEvents, + consolidationPoiEvents, + consolidationConditions, + zIndex, + loopback // + ); + if (!result) + { + // + Clean(analysePoiEvents); + Clean(decisionPoiEvents); + Clean(consolidationPoiEvents); + + // + Clean(analyseCycleEvents); + Clean(decisionCycleEvents); + Clean(consolidationCycleEvents); + + // + analyseConditions.Clean(); + decisionConditions.Clean(); + consolidationConditions.Clean(); + + // + mConditions.Clean(); + consolidationZBar.Clean(); + + // + return result; + } + + // + // Vision ... + ENUM_XPOI_EVENTS visionPoiEvents[]; + ENUM_X_CYCLE_EVENTS visionCycleEvents[]; + X121SMCCycleConditions visionConditions; + result = visionCycleHelper.GetConditions( + visionCycleEvents, + visionPoiEvents, + visionConditions, + zIndex, + loopback // + ); + if (!result) + { + // + Clean(visionPoiEvents); + Clean(analysePoiEvents); + Clean(decisionPoiEvents); + Clean(consolidationPoiEvents); + + // + Clean(visionCycleEvents); + Clean(analyseCycleEvents); + Clean(decisionCycleEvents); + Clean(consolidationCycleEvents); + + // + visionConditions.Clean(); + analyseConditions.Clean(); + decisionConditions.Clean(); + consolidationConditions.Clean(); + + // + mConditions.Clean(); + consolidationZBar.Clean(); + + // + return result; + } + + // + // Cycles POI States ... + XPOIState decisionState = decisionConditions.state; + XPOIState analyseState = analyseConditions.state; + XPOIState consolidationState = consolidationConditions.state; + XPOIState visionState = visionConditions.state; + + // + // Cycle X121Conditions ... + X121Conditions decisionXConditions = decisionConditions.x121Conditions; + X121Conditions analyseXConditions = analyseConditions.x121Conditions; + X121Conditions consolidationXConditions = consolidationConditions.x121Conditions; + X121Conditions visionXConditions = visionConditions.x121Conditions; + + // + // Select Drawer Class ... + XCPOIDrawer *drawer = visionCycleHelper.mPOIDrawer; + + // + // Setup Conditions ... + double sls[]; + double pivot = 0; + double point = 0; + double targets[]; + double reward = 0; + XBoxZone signalBox; + XOBFVG selectedZone; + double amountPercent = 0; + bool hasPriority = false; + bool hasSignalBox = false; + bool hasRewardAmount = false; + bool hasSelectedZone = false; + bool isSignalBoxReversal = false; + bool isSelectedZoneReversal = false; + bool hasSelectedConsolidationZone = false; + XConsolidationZone selectedConsolidationZone; + ENUM_X_DIRECTION selectedZoneDir = X_DIRECTION_NONE; + ENUM_X121SMC_XWZ_PRIORITY priority = X121SMC_XWZ_PRIORITY_NONE; + ENUM_X121SMC_XWZ_PROVIDERS provider = X121SMC_XWZ_PROVIDER_NONE; + + // + // First We Have to Has Working Zone ... + bool hasWorkingZone = workingZone.IsValid(); + if (!hasWorkingZone) + { + // + hasWorkingZone = workingZone.Init( + symbol, + period, + zIndex, + visionState, + consolidationState, + analyseState, + decisionState // + ); + } + + // + if (hasWorkingZone) + { + // + visionCycleHelper.mPOIDetector.MaxRequiredPOIs(50); + analyseCycleHelper.mPOIDetector.MaxRequiredPOIs(50); + decisionCycleHelper.mPOIDetector.MaxRequiredPOIs(50); + consolidationCycleHelper.mPOIDetector.MaxRequiredPOIs(50); + + // + visionCycleHelper.mPOIDetector.MaxAllowedLoopbackForInit(578); + analyseCycleHelper.mPOIDetector.MaxAllowedLoopbackForInit(578); + decisionCycleHelper.mPOIDetector.MaxAllowedLoopbackForInit(578); + consolidationCycleHelper.mPOIDetector.MaxAllowedLoopbackForInit(578); + + // + workingZone.Update( + zIndex, + visionState, + consolidationState, + analyseState, + decisionState // + ); + } + + // + bool hasWaitingZones = hasWorkingZone && + workingZone.HasWaitingZones(); + + // + // + // + + // + // Check Conditions if Has Inside Zones ... + bool hasInsideZones = hasWorkingZone && + workingZone.HasInsideZones(); + if (hasInsideZones) + { + // + int selectedIDX = -1; + int count = workingZone.CountInsideZones(); + for (int i = 0; i < count; i++) + { + // + bool has = DetectSelectedZoneConditions( + isSelectedZoneReversal, + workingZone.insideZones[i], + decisionState, + decisionXConditions // + ); + + // + if (has) + { + // + selectedIDX = i; + selectedZone = workingZone.insideZones[i]; + + // + break; + } + } + + // + if (IsValidIndex(selectedIDX)) + { + // + ArrayRemove( + workingZone.insideZones, + selectedIDX, + 1 // + ); + + // + hasSelectedZone = selectedZone.IsValid(); + provider = X121SMC_XWZ_PROVIDER_PRICE_INSIDE_ZONE; + } + } + + // + // Check Conditions if Has Breaked Zones ... + // bool hasBreakedZones = hasWorkingZone && + // workingZone.HasBreakedZones(); + // if (hasBreakedZones) + // { + // // + // if (!hasSelectedZone) + // { + // // + // int selectedIDX = -1; + // int count = workingZone.CountBreakedZones(); + // for (int i = 0; i < count; i++) + // { + // // + // bool has = DetectSelectedZoneConditions( + // isSelectedZoneReversal, + // workingZone.breakedZones[i], + // decisionState, + // decisionXConditions // + // ); + + // // + // if (has) + // { + // // + // selectedIDX = i; + // selectedZone = workingZone.breakedZones[i]; + + // // + // break; + // } + // } + + // // + // if (IsValidIndex(selectedIDX)) + // { + // // + // ArrayRemove( + // workingZone.breakedZones, + // selectedIDX, + // 1 // + // ); + + // // + // hasSelectedZone = selectedZone.IsValid(); + // provider = X121SMC_XWZ_PROVIDER_ACTIVATED_ZONE; + // } + // } + // } + + // + // + // + + // + bool hasInsideBoxes = hasWorkingZone && + workingZone.HasInsideBoxes(); + if (hasInsideBoxes) + { + // + XOHCL zBar; + XOHCL cBar; + int count = 0; + bool has = false; + XBoxZone tmpSelectedBox; + int tmpSelectedBoxIDX = -1; + + // + has = zBar.Init( + symbol, + period, + zIndex // + ); + has = has && + zBar.GetPreviousBar(cBar); + if (has) + { + // + count = workingZone.CountInsideBoxes(); + for (int i = 0; i < count; i++) + { + // + tmpSelectedBox = workingZone.insideBoxes[i]; + + // + bool isBullish = tmpSelectedBox.IsBullish(); + bool isBearish = tmpSelectedBox.IsBearish(); + + // + bool hasFiboPressure = + visionCycleHelper + .mBarAnalyser + .HasFiboPressure( + cBar, + tmpSelectedBox.dir, + X_FIBO_LEVEL_382 // + ); + + // + bool isBullishRejectedUpper = + cBar.low < tmpSelectedBox.upper && + cBar.GetDown() > tmpSelectedBox.upper; + + // + bool isBullishRejectedLower = + cBar.low < tmpSelectedBox.lower && + cBar.GetDown() > tmpSelectedBox.lower; + + // + bool isBearishRejectedUpper = + cBar.high > tmpSelectedBox.upper && + cBar.GetUp() < tmpSelectedBox.upper; + + // + bool isBearishRejectedLower = + cBar.high > tmpSelectedBox.lower && + cBar.GetUp() < tmpSelectedBox.lower; + + // + bool isBullishRejected = + // isBullishRejectedUpper || + isBullishRejectedLower; + + // + bool isBearishRejected = + isBearishRejectedUpper + // || isBearishRejectedLower + ; + + // + bool isMaWapBullish = + // + (decisionXConditions.isX3MaBullishState && + decisionXConditions.isX3MaBullishOrdered) + // + && + // + (decisionXConditions.isVWapBullishState && + decisionXConditions.isVWapBullishOrdered) + // + ; + + // + bool isMaWapBearish = + // + (decisionXConditions.isX3MaBearishState && + decisionXConditions.isX3MaBearishOrdered) + // + && + // + (decisionXConditions.isVWapBearishState && + decisionXConditions.isVWapBearishOrdered) + // + ; + + // + bool isX2MaWapInside = + // + (decisionXConditions.x3maFastBuffer[cIndex] < tmpSelectedBox.upper && + decisionXConditions.x3maMidBuffer[cIndex] < tmpSelectedBox.upper && + decisionXConditions.x3maFastBuffer[cIndex] > tmpSelectedBox.lower && + decisionXConditions.x3maMidBuffer[cIndex] > tmpSelectedBox.lower) + // + && + // + (decisionXConditions.vwapFastBuffer[cIndex] < tmpSelectedBox.upper && + decisionXConditions.vwapMidBuffer[cIndex] < tmpSelectedBox.upper && + decisionXConditions.vwapFastBuffer[cIndex] > tmpSelectedBox.lower && + decisionXConditions.vwapMidBuffer[cIndex] > tmpSelectedBox.lower) + // + ; + + // + bool isBullishConditions = + // + isBullish && + isMaWapBearish && + isX2MaWapInside && + hasFiboPressure && + isBullishRejected && + cBar.low < cBar.GetDown() + // + ; + + // + bool isBearishConditions = + // + isBearish && + isMaWapBullish && + isX2MaWapInside && + hasFiboPressure && + isBearishRejected && + cBar.high > cBar.GetUp() + // + ; + + // + has = isBullishConditions || + isBearishConditions; + if (!has) + { + // + tmpSelectedBox.Clean(); + continue; + } + + // + tmpSelectedBoxIDX = i; + signalBox = tmpSelectedBox; + + // + tmpSelectedBox.Clean(); + break; + } + } + + // + isSignalBoxReversal = false; + hasSignalBox = signalBox.IsValid(); + if (hasSignalBox) + { + // + ArrayRemove( + workingZone.insideBoxes, + tmpSelectedBoxIDX, + 1 // + ); + } + + // + zBar.Clean(); + cBar.Clean(); + tmpSelectedBox.Clean(); + } + + // + bool hasBreakedBoxes = hasWorkingZone && + workingZone.HasBreakedBoxes(); + if (hasBreakedBoxes) + { + } + + // + if (!hasSignalBox) + { + } + + // + // + // + + // + // Double Check and Prepare Signal Conditions ... + // including Targets and SLs ... + + // + if (hasSelectedZone) + { + // + int idx = -1; + bool has = false; + + // + // Check Consolidation Zones for SL Handling ... + selectedZoneDir = + !isSelectedZoneReversal + ? selectedZone.GetDirection() + : Opposit(selectedZone.GetDirection()); + bool isSelectedZonDirBullish = IsBullish(selectedZoneDir); + + // + if (isSelectedZoneReversal) + { + provider = X121SMC_XWZ_PROVIDER_ACTIVATED_CHOCH; + } + + // + // Calculate Priority ... + hasPriority = + hasWorkingZone && + workingZone + .DetectPriority( + priority, + selectedZoneDir, + zIndex, + period // + ); + + // + // Calculate Risk Reward Ration based on Priority ... + hasRewardAmount = CalculateRiskReward( + priority, + reward, + amountPercent // + ); + + // + // Calculate Pivot and Point ... + + // + pivot = + isSelectedZonDirBullish + ? selectedZone.ob.Lower() + : selectedZone.ob.Upper(); + + // + point = + isSelectedZonDirBullish + ? selectedZone.ob.Upper() + : selectedZone.ob.Lower(); + + // + // Detect Targets ... + DetectSelectedZonesTargets( + targets, + selectedZone, + selectedZoneDir, + priority, + workingZone, + zIndex // + ); + + // + // Detect SLs ... + double iAtr = decisionXConditions.atrBuffer[0]; + iAtr *= 1.5; + + // + // Default SL is Pivot ... + if (pivot > 0) + { + // + Add( + pivot, + sls // + ); + + // + double iSL = iAtr * pivot; + Add( + iSL, + sls // + ); + } + + // + DetectSelectedZoneSLCandidates( + sls, + selectedZone, + selectedZoneDir, + workingZone, + decisionXConditions, + zIndex, + maxAllowedSLDistanceInPoint // + ); + + // + // Summaries Conditions ... + result = + pivot > 0 && + point > 0 && + hasPriority && + hasRewardAmount && + HasDirection(selectedZoneDir); + if (result) + { + // + isBullish = IsBullish(selectedZoneDir); + isBearish = IsBearish(selectedZoneDir); + + // + Copy( + sls, + mConditions.sls // + ); + Copy( + targets, + mConditions.targets // + ); + + // + mConditions.pivot = pivot; + mConditions.point = point; + mConditions.reward = reward; + mConditions.setupTime = cTime; + mConditions.priority = priority; + mConditions.provider = provider; + mConditions.dir = selectedZoneDir; + mConditions.signalBox = signalBox; + mConditions.amountPercent = amountPercent; + } + + // + // Cleanup Resources ... + + // + Clean(sls); + Clean(targets); + selectedZone.Clean(); + selectedConsolidationZone.Clean(); + } + + // + if (hasSignalBox) + { + // // + // workingZone.mInsideZoneObjects.Clear(); + // workingZone.mBreakedZoneObjects.Clear(); + // workingZone.mWaitingZoneObjects.Clear(); + // workingZone.mWorkingZoneObjects.Clear(); + + // // + // XCBoxObject *iObj; + // signalBox.to = cTime; + // bool isCreated = drawer.CreateBox( + // signalBox, + // iObj // + // ); + + // // + // if (isCreated) + // { + // // + // iObj.BoxWidth(2); + // iObj.BoxColor(clrYellow); + // iObj.BoxStyle(STYLE_SOLID); + // } + + // // + // bool isSignalBoxBullishDir = signalBox.IsBullish(); + + // // + // // Calculate Priority ... + // hasPriority = + // hasWorkingZone && + // workingZone + // .DetectPriority( + // priority, + // signalBox.dir, + // zIndex, + // period // + // ); + + // // + // // Calculate Risk Reward Ration based on Priority ... + // hasRewardAmount = CalculateRiskReward( + // priority, + // reward, + // amountPercent // + // ); + + // // + // // Calculate Pivot and Point ... + + // // + // pivot = + // isSignalBoxBullishDir + // ? signalBox.lower + // : signalBox.upper; + + // // + // point = + // isSignalBoxBullishDir + // ? signalBox.upper + // : signalBox.lower; + + // // + // double defaultTarget = + // isSignalBoxBullishDir + // ? signalBox.upper + // : signalBox.lower; + // Add( + // defaultTarget, + // targets // + // ); + + // // + // // Detect SLs ... + // double iAtr = decisionXConditions.atrBuffer[0]; + // iAtr *= 1.5; + + // // + // double defaultSL = + // isSignalBoxBullishDir + // ? decisionXConditions.valesBuffer[0] - iAtr + // : decisionXConditions.peaksBuffer[0] + iAtr; + + // // + // Add( + // defaultSL, + // sls // + // ); + + // // + // // Summaries Conditions ... + // result = + // pivot > 0 && + // point > 0 && + // hasPriority && + // hasRewardAmount; + // if (result) + // { + // // + // isBullish = signalBox.IsBullish(); + // isBearish = signalBox.IsBearish(); + + // // + // Copy( + // sls, + // mConditions.sls // + // ); + // Copy( + // targets, + // mConditions.targets // + // ); + + // // + // mConditions.pivot = pivot; + // mConditions.point = point; + // mConditions.reward = reward; + // mConditions.setupTime = cTime; + // mConditions.priority = priority; + // mConditions.provider = provider; + // mConditions.dir = signalBox.dir; + // mConditions.signalBox = signalBox; + // mConditions.amountPercent = amountPercent; + // } + + // // + // signalBox.Clean(); + // hasSignalBox = false; + } + + // + UpdateTo(cTime); + + // + // Draw Working Zone ... + if (hasWorkingZone) + { + // + workingZone.Draw( + drawer, + true, // Draw Waiting Zones ... + true, // Draw Inside Zones ... + true, // Draw Breaked Zones ... + true, // Draw Supply Zone ... + true, // Draw Demand Zone ... + false, // Draw Supply Zones ... + false, // Draw Demand Zones ... + false, // Draw Support Zones ... + false // Draw Resistance Zones ... + ); + + // + // XCBaseObject *objects[]; + // drawer.DrawState( + // decisionState, + // objects, + // false, // DrawT icksZone ... + // true, // Ignore SwingHighs ... + // true, // Ignore SwingLows ... + // true, // Ignore SupportZones ... + // true, // Ignore ResistanceZones ... + // true, // Ignore SupplyZones ... + // true, // Ignore DemandZones ... + // true, // Ignore BullishOrderBlocks ... + // true, // Ignore BearishOrderBlocks ... + // true, // Ignore BullishFairValueGaps ... + // true, // Ignore BearishFairValueGaps ... + // true, // Ignore BullishRejectionBars ... + // true, // Ignore BearishRejectionBars ... + // true, // Ignore BullishMomentumBars ... + // true, // Ignore BearishMomentumBars ... + // true, // Ignore BullishConsolidationZones ... + // true // Ignore BearishConsolidationZones ... + // ); + + // // + // int count = 0; + // bool has = false; + + // // + // has = workingZone.HasSupplyZones(); + // if (has) + // { + // } + + // // + // has = workingZone.HasDemandZones(); + // if (has) + // { + // // + // count = workingZone.CountDemandZones(); + // for (int i = 0; i < count; i++) + // { + // // + // XCDemandZone *iZone = workingZone.demandZones[i]; + + // // + // XCDemandZoneObject *iObj; + // bool isCreated = drawer.CreateDemandZone( + // iZone, + // iObj // + // ); + // } + // } + + // // + // Print(""); + } + + // + // Cleanup Resources ... + + // + Clean(visionPoiEvents); + Clean(analysePoiEvents); + Clean(decisionPoiEvents); + Clean(consolidationPoiEvents); + + // + Clean(visionCycleEvents); + Clean(analyseCycleEvents); + Clean(decisionCycleEvents); + Clean(consolidationCycleEvents); + + // + visionState.Clean(); + analyseState.Clean(); + decisionState.Clean(); + consolidationState.Clean(); + + // + visionConditions.Clean(); + analyseConditions.Clean(); + decisionConditions.Clean(); + consolidationConditions.Clean(); + + // + visionXConditions.Clean(); + analyseXConditions.Clean(); + decisionXConditions.Clean(); + consolidationXConditions.Clean(); + + // + consolidationZBar.Clean(); + + // + return result; + } + + // + // Detect Trigger Conditions ... + bool DetectSignalTrigger( + // + X121SMCStrategyXWZSignalConditions &conditions, + // + XC121SMCCycleHelper *decisionCycleHelper, + XC121SMCCycleHelper *analyseCycleHelper, + XC121SMCCycleHelper *consolidationCycleHelper, + XC121SMCCycleHelper *visionCycleHelper, + // + int maxAllowedSetupAge = 60 + // + ) + { + // + bool result = false; + + // + result = + // + visionCycleHelper != NULL && + analyseCycleHelper != NULL && + decisionCycleHelper != NULL && + consolidationCycleHelper != NULL + // + ; + if (!result) + { + return result; + } + + // + result = conditions.IsSetuped(); + if (!result) + { + return result; + } + + // + datetime setupTime = conditions.setupTime; + ENUM_X_DIRECTION setupDir = conditions.dir; + + // + bool isBullish = IsBullish(setupDir); + bool isBearish = IsBearish(setupDir); + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + int loopback = 10; + + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + double points = GetPoints(symbol); + + // + // Cycles Conditions ... + + // + // Decision ... + ENUM_XPOI_EVENTS decisionPoiEvents[]; + ENUM_X_CYCLE_EVENTS decisionCycleEvents[]; + X121SMCCycleConditions decisionConditions; + result = decisionCycleHelper.GetConditions( + decisionCycleEvents, + decisionPoiEvents, + decisionConditions, + zIndex, + loopback // + ); + if (!result) + { + // + // Cleanup ... + + // + Clean(decisionPoiEvents); + Clean(decisionCycleEvents); + + // + decisionConditions.Clean(); + + // + return result; + } + + // + // Analyse ... + ENUM_XPOI_EVENTS analysePoiEvents[]; + ENUM_X_CYCLE_EVENTS analyseCycleEvents[]; + X121SMCCycleConditions analyseConditions; + result = analyseCycleHelper.GetConditions( + analyseCycleEvents, + analysePoiEvents, + analyseConditions, + zIndex, + loopback // + ); + if (!result) + { + // + Clean(analysePoiEvents); + Clean(decisionPoiEvents); + + // + Clean(analyseCycleEvents); + Clean(decisionCycleEvents); + + // + analyseConditions.Clean(); + decisionConditions.Clean(); + + // + return result; + } + + // + // Cycles POI States ... + XPOIState decisionState = decisionConditions.state; + XPOIState analyseState = analyseConditions.state; + + // + // Cycle X121Conditions ... + X121Conditions decisionXConditions = decisionConditions.x121Conditions; + X121Conditions analyseXConditions = analyseConditions.x121Conditions; + + // + double iAtr = decisionXConditions.atrBuffer[1]; + iAtr *= 1.5; + + // + // Check Signal Validation ... + // IMPORTANT: since all Validations done in SetUp Process ... + // here we only Execute Signal ... + + // + result = isBullish || + isBearish; + + // + if (result) + { + // + // Retrieve Entry Price ... + double entry = GetEntry( + conditions.symbol, + setupDir // + ); + + // + // Select and Apply SL ... + + // + double slsMin = GetMin(conditions.sls); + double slsMax = GetMax(conditions.sls); + + // + double longSL = slsMin; + double shortSL = slsMax; + + // + double sl = isBullish + ? longSL + : shortSL; + + // + conditions.sl = sl; + conditions.triggerTime = cTime; + conditions.type = isBullish + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_SHORT; + + // + } + + // + // Cleanup ... + + // + Clean(decisionPoiEvents); + Clean(decisionCycleEvents); + + // + decisionState.Clean(); + decisionConditions.Clean(); + decisionXConditions.Clean(); + + // + Clean(analysePoiEvents); + Clean(analyseCycleEvents); + + // + analyseState.Clean(); + analyseConditions.Clean(); + analyseXConditions.Clean(); + + // + return result; + } + + // + // Detect Guards ... + bool DetectGuards( + // + X121SMCGuard &guards[], + const XPosition &positions[], + // + XC121SMCCycleHelper *decisionCycleHelper, + XC121SMCCycleHelper *analyseCycleHelper, + XC121SMCCycleHelper *consolidationCycleHelper, + XC121SMCCycleHelper *visionCycleHelper + // + ) + { + // + bool result = false; + return false; + + // + Clean(guards); + + // + bool isCycleHelpersValid = + // + visionCycleHelper != NULL && + analyseCycleHelper != NULL && + decisionCycleHelper != NULL && + consolidationCycleHelper != NULL + // + ; + + // + // Set Provider for Common Guards ... + string provider = ToString(X_121_SMC_PROVIDER_XWZ); + + // + // Check Cycle Helpers Validation ... + result = isCycleHelpersValid; + if (!result) + { + return result; + } + + // + // Select Own Positions ... + int count = ArraySize(positions); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + XPosition ownPositions[]; + XPosition ownLongPositions[]; + XPosition ownShortPositions[]; + for (int i = 0; i < count; i++) + { + // + XPosition iPosition = positions[i]; + bool isOwn = iPosition + .IsFiltersPassed( + symbol, + provider, + NULL, + X_POSITION_TYPE_ALL, + iPosition.magic // + ); + if (isOwn) + { + // + AddRef( + iPosition, + ownPositions // + ); + + // + bool isLong = IsLong(positions[i].type); + if (isLong) + { + // + AddRef( + iPosition, + ownLongPositions // + ); + } + else + { + // + AddRef( + iPosition, + ownShortPositions // + ); + } + } + } + + // + // Check Extracted Positions ... + + // + count = ArraySize(ownPositions); + + // + int longsCount = ArraySize(ownLongPositions); + bool hasLongs = IsValidSize(longsCount); + + // + int shortsCount = ArraySize(ownShortPositions); + bool hasShorts = IsValidSize(shortsCount); + + // + // Validate Own Positions ... + result = IsValidSize(count); + if (!result) + { + // + Clean(ownPositions); + Clean(ownLongPositions); + Clean(ownShortPositions); + + // + return result; + } + + // + // + // + + // + // Get Global and Common Guards ... + + // + ENUM_X_121_SMC_GUARD_ACTIONS ignoreGuards[1] = { + X_121_SMC_GUARD_ACTION_TRAIL_STOP // + }; + result = DetectX121SMCGuards( + provider, + guards, + positions, + decisionCycleHelper, + analyseCycleHelper, + consolidationCycleHelper, + visionCycleHelper, + // + ignoreGuards + // + ); + + // + // + // + + // + // Implement Custom Implemented Guards ... + + // + // Here we Are Sure there is Positions to Guard ... + // based on Current Provider ... + + // + // Detect Required Data for Analyse Market to Guard Positions ... + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + int loopback = 10; + + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + double points = GetPoints(symbol); + + // + // Cycles Conditions ... + + // + // Decision ... + ENUM_XPOI_EVENTS decisionPoiEvents[]; + ENUM_X_CYCLE_EVENTS decisionCycleEvents[]; + X121SMCCycleConditions decisionConditions; + result = decisionCycleHelper.GetConditions( + decisionCycleEvents, + decisionPoiEvents, + decisionConditions, + zIndex, + loopback // + ); + if (!result) + { + // + Clean(decisionPoiEvents); + Clean(decisionCycleEvents); + + // + decisionConditions.Clean(); + + // + result = HasChild(guards); + return result; + } + + // + // Analyse ... + ENUM_XPOI_EVENTS analysePoiEvents[]; + ENUM_X_CYCLE_EVENTS analyseCycleEvents[]; + X121SMCCycleConditions analyseConditions; + result = analyseCycleHelper.GetConditions( + analyseCycleEvents, + analysePoiEvents, + analyseConditions, + zIndex, + loopback // + ); + if (!result) + { + // + Clean(decisionPoiEvents); + Clean(decisionCycleEvents); + + // + decisionConditions.Clean(); + + // + Clean(analysePoiEvents); + Clean(analyseCycleEvents); + + // + analyseConditions.Clean(); + + // + result = HasChild(guards); + return result; + } + + // + // Consolidation ... + ENUM_XPOI_EVENTS consolidationPoiEvents[]; + ENUM_X_CYCLE_EVENTS consolidationCycleEvents[]; + X121SMCCycleConditions consolidationConditions; + result = consolidationCycleHelper.GetConditions( + consolidationCycleEvents, + consolidationPoiEvents, + consolidationConditions, + zIndex, + loopback // + ); + if (!result) + { + // + Clean(decisionPoiEvents); + Clean(decisionCycleEvents); + + // + decisionConditions.Clean(); + + // + Clean(analysePoiEvents); + Clean(analyseCycleEvents); + + // + analyseConditions.Clean(); + + // + Clean(consolidationPoiEvents); + Clean(consolidationCycleEvents); + + // + consolidationConditions.Clean(); + + // + result = HasChild(guards); + return result; + } + + // + // Vision ... + ENUM_XPOI_EVENTS visionPoiEvents[]; + ENUM_X_CYCLE_EVENTS visionCycleEvents[]; + X121SMCCycleConditions visionConditions; + result = visionCycleHelper.GetConditions( + visionCycleEvents, + visionPoiEvents, + visionConditions, + zIndex, + loopback // + ); + if (!result) + { + // + Clean(decisionPoiEvents); + Clean(decisionCycleEvents); + + // + decisionConditions.Clean(); + + // + Clean(analysePoiEvents); + Clean(analyseCycleEvents); + + // + analyseConditions.Clean(); + + // + Clean(consolidationPoiEvents); + Clean(consolidationCycleEvents); + + // + consolidationConditions.Clean(); + + // + Clean(visionPoiEvents); + Clean(visionCycleEvents); + + // + visionConditions.Clean(); + + // + result = HasChild(guards); + return result; + } + + // + // Cycles POI States ... + XPOIState visionState = visionConditions.state; + XPOIState analyseState = analyseConditions.state; + XPOIState decisionState = decisionConditions.state; + XPOIState consolidationState = consolidationConditions.state; + + // + // Cycle X121Conditions ... + X121Conditions visionXConditions = visionConditions.x121Conditions; + X121Conditions analyseXConditions = analyseConditions.x121Conditions; + X121Conditions decisionXConditions = decisionConditions.x121Conditions; + X121Conditions consolidationXConditions = consolidationConditions.x121Conditions; + + // + // + // + + // + // Selected Consolidation Zones ... + + // + int idx = -1; + bool has = false; + + // + bool hasBullishConsolidationZone = false; + XConsolidationZone bullishConsolidationZone; + has = decisionState.HasBullishConsolidationZones(); + if (has) + { + // + idx = GetYoungest(decisionState.bullishConsolidationZones); + hasBullishConsolidationZone = IsValidIndex(idx); + if (hasBullishConsolidationZone) + { + bullishConsolidationZone = decisionState.bullishConsolidationZones[idx]; + } + } + + // + bool hasBearishConsolidationZone = false; + XConsolidationZone bearishConsolidationZone; + has = decisionState.HasBearishConsolidationZones(); + if (has) + { + // + idx = GetYoungest(decisionState.bearishConsolidationZones); + hasBearishConsolidationZone = IsValidIndex(idx); + if (hasBearishConsolidationZone) + { + bearishConsolidationZone = decisionState.bearishConsolidationZones[idx]; + } + } + + // + // Here We Have all Requirements for Guarding Positions ... + + // + // Available Guards: + // X_121_SMC_GUARD_ACTION_NONE + // X_121_SMC_GUARD_ACTION_CLOSE + // X_121_SMC_GUARD_ACTION_CLOSE_ALL + // X_121_SMC_GUARD_ACTION_CLOSE_LONGS + // X_121_SMC_GUARD_ACTION_CLOSE_SHORTS + // X_121_SMC_GUARD_ACTION_PARTIAL_CLOSE + // X_121_SMC_GUARD_ACTION_TRAIL_STOP + // X_121_SMC_GUARD_ACTION_TRAIL_TARGET + // X_121_SMC_GUARD_ACTION_HEDGE + + // + // X_121_SMC_GUARD_ACTION_CLOSE: + // Close Specified Position on Specified Conditions ... + + // + // X_121_SMC_GUARD_ACTION_CLOSE_ALL: + // Close All Positions on Specified Conditions ... + + // + // X_121_SMC_GUARD_ACTION_CLOSE_LONGS: + // Close All Long Positions on Specified Conditions ... + + // + // X_121_SMC_GUARD_ACTION_CLOSE_SHORTS: + // Close All Short Positions on Specified Conditions ... + + // + // X_121_SMC_GUARD_ACTION_PARTIAL_CLOSE: + // Partial Close Specified Position on Specified Conditions ... + + // + // X_121_SMC_GUARD_ACTION_TRAIL_STOP: + // Trail Stop Specified Position on Specified Conditions ... + bool handleStoptrailingBasedOnConsolidationZones = true; + for (int i = 0; i < count; i++) + { + // + XPosition iPosition = ownPositions[i]; + + // + bool isLong = IsLong(iPosition.type); + bool isInProfit = iPosition.profit > 0; + + // + double sl = iPosition.sl; + double tp = iPosition.tp; + + // + // Trail Stops Using Consolidation Zones ... + + // + bool canTraiLonglUsingCZone = + // + handleStoptrailingBasedOnConsolidationZones && + // + (isLong && + isInProfit && + hasBullishConsolidationZone && + bullishConsolidationZone.lower > iPosition.sl && + bullishConsolidationZone.lower > iPosition.entry) + // + ; + if (canTraiLonglUsingCZone) + { + sl = bullishConsolidationZone.lower; + } + + // + bool canTraiShortlUsingCZone = + // + handleStoptrailingBasedOnConsolidationZones && + // + (!isLong && + isInProfit && + hasBearishConsolidationZone && + bearishConsolidationZone.upper < iPosition.sl && + bearishConsolidationZone.upper < iPosition.entry) + // + ; + if (canTraiShortlUsingCZone) + { + sl = bearishConsolidationZone.upper; + } + + // + bool canTrailUsingCZone = + canTraiLonglUsingCZone || + canTraiShortlUsingCZone; + + // + bool isSLPassed = + sl > 0 && + (isLong + ? iPosition.price - sl >= points * 15 + : sl - iPosition.price >= points * 15); + + // + bool canTrail = + isSLPassed && + canTrailUsingCZone; + if (canTrail) + { + // + X121SMCGuard iGuard; + + // + iGuard.time = cTime; + iGuard.symbol = symbol; + iGuard.provider = provider; + iGuard.action = X_121_SMC_GUARD_ACTION_TRAIL_STOP; + + // + iGuard.ticket = iPosition.ticket; + + // + iGuard.sl = sl; + + // + AddGuard( + iGuard, + guards // + ); + } + } + + // + // X_121_SMC_GUARD_ACTION_TRAIL_TARGET: + // Trail Target Specified Position on Specified Conditions ... + + // + // X_121_SMC_GUARD_ACTION_HEDGE: + // Hedge all Positions on Specified Conditions ... + + // + // Cleanup Collections ... + + // + Clean(ownPositions); + Clean(ownLongPositions); + Clean(ownShortPositions); + + // + visionState.Clean(); + analyseState.Clean(); + decisionState.Clean(); + consolidationState.Clean(); + + // + visionConditions.Clean(); + analyseConditions.Clean(); + decisionConditions.Clean(); + consolidationConditions.Clean(); + + // + visionXConditions.Clean(); + analyseXConditions.Clean(); + decisionXConditions.Clean(); + consolidationXConditions.Clean(); + + // + Clean(visionPoiEvents); + Clean(analysePoiEvents); + Clean(decisionPoiEvents); + Clean(consolidationPoiEvents); + + // + Clean(visionCycleEvents); + Clean(analyseCycleEvents); + Clean(decisionCycleEvents); + Clean(consolidationCycleEvents); + + // + count = ArraySize(guards); + result = IsValidSize(count); + + // + return result; + } + + // + // Add Conditions to Conditions Collection ... + int AddConditionsIfNotExists( + int maxAllowed = 10 // + ) + { + // + int result = 0; + + // + bool isSetuped = IsValid(mConditions.setupTime) && + HasDirection(mConditions.dir); + if (!isSetuped) + { + return result; + } + + // + int count = ArraySize(mConditionsCollection); + if (IsValidSize(count)) + { + // + // Copy Original Items ... + X121SMCStrategyXWZSignalConditions tmpItems[]; + Copy( + mConditionsCollection, + tmpItems // + ); + + // + // Prese Item Data ... + bool isBullish = IsBullish(mConditions.dir); + + // + for (int i = 0; i < count; i++) + { + // + X121SMCStrategyXWZSignalConditions iItem = tmpItems[i]; + + // + bool canRemove = mConditions.dir == iItem.dir && + mConditions.pivot == iItem.pivot; + if (canRemove) + { + // + ArrayRemove( + mConditionsCollection, + i, + 1 // + ); + } + } + + // + Clean(tmpItems); + } + + // + AddRef( + mConditions, + mConditionsCollection // + ); + + // + // Remove Olds ... + CleanupArray( + mConditionsCollection, + maxAllowed // + ); + + // + result = ArraySize(mConditionsCollection); + + // + return result; + } + + // + // Draw Functions ... + // + + // + void DrawBar( + XOHCL &bar, + XCPOIDrawer *drawer, + bool forceClean = true // + ) + { + // + if (forceClean) + { + mBarObjects.Clear(); + } + + // + if (drawer == NULL || + !bar.IsValid()) + { + return; + } + + // + bool isBullish = bar.IsBullish(); + + // + int widthBar = 2; + bool fillShadowsBar = true; + ENUM_LINE_STYLE styleBar = STYLE_SOLID; + color clrBar = + isBullish + ? clrAqua + : clrMagenta; + + // + datetime to = bar.NextAt(); + + // + XCOHCLObject *iObj; + bool isCreated = drawer + .CreateBar( + bar, + iObj, + to // + ); + if (isCreated) + { + // + iObj.BarSpes( + widthBar, + clrBar, + styleBar // + ); + + // + iObj.LowShadowFill(fillShadowsBar); + iObj.HighShadowFill(fillShadowsBar); + + // + mBarObjects.Add(iObj); + } + } + + // + protected: + // + + // + private: + // + // Props ... + string symbol; + ENUM_TIMEFRAMES period; + CArrayObj mObjects; + CArrayObj mBarObjects; + CArrayObj mWorkingZoneObjects; + + /** + * Initialize ... + */ + void Init() + { + } + + /** + * DeInitialize ... + */ + void DeInit() + { + // + mConditions.Clean(); + workingZone.Clean(); + Clean(mConditionsCollection); + + // + mBarObjects.Clear(); + } + + /** + * Update To Time of Exists Components ... + * + * @param value: updated time ... + */ + void UpdateTo( + datetime value = NULL // + ) + { + // + value = NormalizeTime(value); + + // + workingZone.UpdateTo(value); + } + + // + // Helpers ... + + // + bool CalculateRiskReward( + ENUM_X121SMC_XWZ_PRIORITY priority, + double &reward, + double &amountPercent // + ) + { + // + bool result = false; + + // + reward = 0; + amountPercent = 0; + + // + result = priority != X121SMC_XWZ_PRIORITY_NONE; + if (!result) + { + return result; + } + + // + switch (priority) + { + // + case X121SMC_XWZ_PRIORITY_STRONG_HIGH: + // + reward = 6; + amountPercent = 2; + break; + + // + case X121SMC_XWZ_PRIORITY_HIGH: + // + reward = 4; + amountPercent = 2; + break; + + // + case X121SMC_XWZ_PRIORITY_REGULAR: + // + reward = 3; + amountPercent = 1.5; + break; + + // + case X121SMC_XWZ_PRIORITY_LOW: + // + reward = 2; + amountPercent = 1; + break; + + // + case X121SMC_XWZ_PRIORITY_WEAK: + // + reward = 1; + amountPercent = 0.5; + break; + } + + // + result = + // + reward > 0 && + amountPercent > 0 + // + ; + + // + return result; + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14031218/Documents/BKP/x-121.smc.xwz.signal.class.mq5 b/BKPS/14031218/Documents/BKP/x-121.smc.xwz.signal.class.mq5 new file mode 100644 index 0000000..c80b6cc --- /dev/null +++ b/BKPS/14031218/Documents/BKP/x-121.smc.xwz.signal.class.mq5 @@ -0,0 +1,3960 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 X121 SMC Signal Class +// ------------------------------------------------- +// Name: XWZ +// 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.guard.lib.mq5" +#include "../Libraries/x-121.smc.lib.mq5" +#include "./x-121.smc.xwz.signal.lib.mq5" + +// +// Definition ... +class XCX121SMCXWZSignalDetector : public XCBase +{ + // + public: + // + // Props ... + XOBFVG chochZone; + XOBFVG targetZone; + XOBFVG signalZone; + XOBFVG waitingZone; + X121SMCStrategyXWZWorkingZone workingZone; + X121SMCStrategyXWZSignalConditions mConditions; + X121SMCStrategyXWZSignalConditions mConditionsCollection[]; + + // + // Constructor(s) ... + XCX121SMCXWZSignalDetector( + string _symbol, + ENUM_TIMEFRAMES _period // + ) + { + // + symbol = _symbol; + period = _period; + Init(); + } + + // + // Deconstructor ... + ~XCX121SMCXWZSignalDetector() + { + DeInit(); + } + + // + // + // + + // + // Detect Setup Conditions ... + bool DetectSignalSetup( + // + XC121SMCCycleHelper *decisionCycleHelper, + XC121SMCCycleHelper *analyseCycleHelper, + XC121SMCCycleHelper *consolidationCycleHelper, + XC121SMCCycleHelper *visionCycleHelper + // + ) + { + // + bool result = false; + + // + // Validate Cycle Helpers ... + result = + // + visionCycleHelper != NULL && + analyseCycleHelper != NULL && + decisionCycleHelper != NULL && + consolidationCycleHelper != NULL + // + ; + if (!result) + { + // + mConditions.Clean(); + + // + return result; + } + + // + bool isBullish = false; + bool isBearish = false; + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + int loopback = 10; + + // + mConditions.symbol = symbol; + mConditions.period = period; + + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + double points = GetPoints(symbol); + + // + double pivot = 0; + double point = 0; + double target = 0; + double reward = 0; + double amountPercent = 0; + ENUM_X121SMC_XWZ_PRIORITY priority = X121SMC_XWZ_PRIORITY_NONE; + + // + // Cycles Conditions ... + + // + XOHCL consolidationZBar; + result = consolidationCycleHelper.GetBar( + consolidationZBar, + zIndex // + ); + if (!result) + { + // + consolidationZBar.Clean(); + return result; + } + + // + bool drawBar = true; + if (drawBar) + { + // + DrawBar( + consolidationZBar, + decisionCycleHelper.mPOIDrawer // + ); + } + + // + // Decision ... + ENUM_XPOI_EVENTS decisionPoiEvents[]; + ENUM_X_CYCLE_EVENTS decisionCycleEvents[]; + X121SMCCycleConditions decisionConditions; + result = decisionCycleHelper.GetConditions( + decisionCycleEvents, + decisionPoiEvents, + decisionConditions, + zIndex, + loopback // + ); + if (!result) + { + // + Clean(decisionPoiEvents); + Clean(decisionCycleEvents); + + // + decisionConditions.Clean(); + + // + mConditions.Clean(); + consolidationZBar.Clean(); + + // + return result; + } + + // + // Analyse ... + ENUM_XPOI_EVENTS analysePoiEvents[]; + ENUM_X_CYCLE_EVENTS analyseCycleEvents[]; + X121SMCCycleConditions analyseConditions; + result = analyseCycleHelper.GetConditions( + analyseCycleEvents, + analysePoiEvents, + analyseConditions, + zIndex, + loopback // + ); + if (!result) + { + // + Clean(analysePoiEvents); + Clean(decisionPoiEvents); + + // + Clean(analyseCycleEvents); + Clean(decisionCycleEvents); + + // + analyseConditions.Clean(); + decisionConditions.Clean(); + + // + mConditions.Clean(); + consolidationZBar.Clean(); + + // + return result; + } + + // + // Consolidation ... + ENUM_XPOI_EVENTS consolidationPoiEvents[]; + ENUM_X_CYCLE_EVENTS consolidationCycleEvents[]; + X121SMCCycleConditions consolidationConditions; + result = consolidationCycleHelper.GetConditions( + consolidationCycleEvents, + consolidationPoiEvents, + consolidationConditions, + zIndex, + loopback // + ); + if (!result) + { + // + Clean(analysePoiEvents); + Clean(decisionPoiEvents); + Clean(consolidationPoiEvents); + + // + Clean(analyseCycleEvents); + Clean(decisionCycleEvents); + Clean(consolidationCycleEvents); + + // + analyseConditions.Clean(); + decisionConditions.Clean(); + consolidationConditions.Clean(); + + // + mConditions.Clean(); + consolidationZBar.Clean(); + + // + return result; + } + + // + // Vision ... + ENUM_XPOI_EVENTS visionPoiEvents[]; + ENUM_X_CYCLE_EVENTS visionCycleEvents[]; + X121SMCCycleConditions visionConditions; + result = visionCycleHelper.GetConditions( + visionCycleEvents, + visionPoiEvents, + visionConditions, + zIndex, + loopback // + ); + if (!result) + { + // + Clean(visionPoiEvents); + Clean(analysePoiEvents); + Clean(decisionPoiEvents); + Clean(consolidationPoiEvents); + + // + Clean(visionCycleEvents); + Clean(analyseCycleEvents); + Clean(decisionCycleEvents); + Clean(consolidationCycleEvents); + + // + visionConditions.Clean(); + analyseConditions.Clean(); + decisionConditions.Clean(); + consolidationConditions.Clean(); + + // + mConditions.Clean(); + consolidationZBar.Clean(); + + // + return result; + } + + // + // Cycles POI States ... + XPOIState decisionState = decisionConditions.state; + XPOIState analyseState = analyseConditions.state; + XPOIState consolidationState = consolidationConditions.state; + XPOIState visionState = visionConditions.state; + + // + // Cycle X121Conditions ... + X121Conditions decisionXConditions = decisionConditions.x121Conditions; + X121Conditions analyseXConditions = analyseConditions.x121Conditions; + X121Conditions consolidationXConditions = consolidationConditions.x121Conditions; + X121Conditions visionXConditions = visionConditions.x121Conditions; + + // + // Setup Conditions ... + + // + // Choch Trading Senario ... + bool hasChochBullishConditions = false; + bool hasChochBearishConditions = false; + + // + // Order Flow Side Trading Senario ... + bool hasOrderFlowhBullishConditions = false; + bool hasOrderFlowhBearishConditions = false; + + // + // Trend Line Trading Senario ... + bool hasTrendLineBullishConditions = false; + bool hasTrendLineBearishConditions = false; + + // + // Quarter Line Trading Senario ... + bool hasBQuarterLineBullishConditions = false; + bool hasBQuarterLineBearishConditions = false; + + // + // Supply and Demand Trading Senario ... + bool hasSupDemBullishConditions = false; + bool hasSupDemBearishConditions = false; + + // + // Support and Resistance Trading Senario ... + bool hasSupResBullishConditions = false; + bool hasSupResBearishConditions = false; + + // + ENUM_X121SMC_XWZ_PROVIDERS provider = X121SMC_XWZ_PROVIDER_NONE; + + // + // Detect Working Zone ... + bool hasWorkingZone = workingZone.IsValid(); + if (!hasWorkingZone) + { + hasWorkingZone = DetectWorkingZone(visionState); + } + + // + // result = hasWorkingZone; + // if (!result) + // { + // // + // Clean(visionPoiEvents); + // Clean(analysePoiEvents); + // Clean(decisionPoiEvents); + // Clean(consolidationPoiEvents); + + // // + // Clean(visionCycleEvents); + // Clean(analyseCycleEvents); + // Clean(decisionCycleEvents); + // Clean(consolidationCycleEvents); + + // // + // visionState.Clean(); + // analyseState.Clean(); + // decisionState.Clean(); + // consolidationState.Clean(); + + // // + // visionConditions.Clean(); + // analyseConditions.Clean(); + // decisionConditions.Clean(); + // consolidationConditions.Clean(); + + // // + // visionXConditions.Clean(); + // analyseXConditions.Clean(); + // decisionXConditions.Clean(); + // consolidationXConditions.Clean(); + + // // + // mConditions.Clean(); + // consolidationZBar.Clean(); + + // // + // return result; + // } + + // + // Supply Zones ... + bool hasSupplyZones = workingZone.HasSupplyZones(); + int supplyZonesCount = workingZone.CountSupplyZones(); + if (hasWorkingZone) + { + // + supplyZonesCount = workingZone + .DetectSupplyZones(consolidationState); + hasSupplyZones = IsValidSize(supplyZonesCount); + } + + // + // Demand Zones ... + bool hasDemandZones = workingZone.HasDemandZones(); + int demandZonesCount = workingZone.CountDemandZones(); + if (hasWorkingZone) + { + // + demandZonesCount = workingZone + .DetectDemandZones(consolidationState); + hasDemandZones = IsValidSize(demandZonesCount); + } + + // + // TODO: Remove this ... + UpdateTo(cTime); + + // + // Detect Working Zone Destroy ... + bool isWorkingZoneDetroyed = + hasWorkingZone && + workingZone.IsDestroyed(); + if (isWorkingZoneDetroyed) + { + mWorkingZoneObjects.Clear(); + } + + // + // result = !isWorkingZoneDetroyed; + // if (!result) + // { + // // + // workingZone.Clean(); + // mWorkingZoneObjects.Clear(); + + // // + // Clean(visionPoiEvents); + // Clean(analysePoiEvents); + // Clean(decisionPoiEvents); + // Clean(consolidationPoiEvents); + + // // + // Clean(visionCycleEvents); + // Clean(analyseCycleEvents); + // Clean(decisionCycleEvents); + // Clean(consolidationCycleEvents); + + // // + // visionState.Clean(); + // analyseState.Clean(); + // decisionState.Clean(); + // consolidationState.Clean(); + + // // + // visionConditions.Clean(); + // analyseConditions.Clean(); + // decisionConditions.Clean(); + // consolidationConditions.Clean(); + + // // + // visionXConditions.Clean(); + // analyseXConditions.Clean(); + // decisionXConditions.Clean(); + // consolidationXConditions.Clean(); + + // // + // mConditions.Clean(); + // consolidationZBar.Clean(); + + // // + // return result; + // } + + // + // Checking Target Zone Breaked ... + bool hasTargetZone = targetZone.IsValid(); + if (hasTargetZone) + { + // + XOHCL bar; + bool isInited = bar.Init( + symbol, + period, + zIndex // + ); + + XOHCL cBar; + isInited = + isInited && + bar.GetPreviousBar(cBar); + + // + bool isBullish = targetZone.IsBullish(); + + // + bool isLowerBreaked = + // + bar.high < targetZone.ob.Lower() && + cBar.high < targetZone.ob.Lower() + // + ; + + // + bool isUpperBreaked = + // + bar.low > targetZone.ob.Upper() && + cBar.low > targetZone.ob.Upper() + // + ; + + // + bool isBreaked = isBullish + ? isLowerBreaked + : isUpperBreaked; + if (isBreaked) + { + // + mWorkingZoneObjects.Clear(); + targetZone.Clean(); + } + } + + // + // Detect Order Flow ... + ENUM_X_DIRECTION trend = X_DIRECTION_NONE; + bool hasOrderFlow = + hasWorkingZone && + workingZone.HasOrderFlow(trend); + if (!hasOrderFlow) + { + // + int orderFlowCount = workingZone.DetectOrderFlow( + symbol, + period, + trend, + visionState, + consolidationState, + analyseState, + decisionState // + ); + hasOrderFlow = IsValidSize(orderFlowCount); + } + + // + bool hasTrend = HasDirection(trend); + bool hasBllishTrend = + hasTrend && + IsBullish(trend); + bool hasBearishTrend = + hasTrend && + IsBearish(trend); + + // + UpdateTo(cTime); + + // + isBullish = IsBullish(trend); + isBearish = IsBearish(trend); + + // + bool hasPriority = workingZone + .DetectPriority( + priority, + trend, + zIndex, + period // + ); + + // + bool hasRewardAmount = CalculateRiskReward( + priority, + reward, + amountPercent // + ); + + // + // Checking Order Flow Break ... + int breakedIDX = -1; + bool isOrderFlowBreaked = + hasOrderFlow && + hasWorkingZone && + workingZone.IsOrderFlowBreaked( + breakedIDX, + true, // Force OB Breaked + false, // Force FVG Breaked + zIndex, + period // + ); + + // + // Order Flow Breaked Senario ... + if (isOrderFlowBreaked) + { + // + AddRef( + workingZone.orderFlow[breakedIDX], + workingZone.brokenOrderFlow // + ); + + // + signalZone = workingZone.orderFlow[breakedIDX]; + provider = X121SMC_XWZ_PROVIDER_ACTIVATED_CHOCH; + + // + ArrayRemove( + workingZone.orderFlow, + breakedIDX, + 1 // + ); + Clean(workingZone.orderFlow); + + // + CleanupArray( + workingZone.brokenOrderFlow, + 10 // + ); + } + + // + // First Check Last Order Flow FVG ... + XOBFVG youngestOrderFlow; + int youngestOBFVGIDX = GetYoungest(workingZone.orderFlow); + bool hasYoungestOBFVG = IsValidIndex(youngestOBFVGIDX); + if (hasYoungestOBFVG) + { + // + youngestOrderFlow = workingZone.orderFlow[youngestOBFVGIDX]; + + // + XOHCL obWorkerBar; + XOHCL obActivationBar; + + // + XOHCL fvgWorkerBar; + XOHCL fvgActivationBar; + + // + bool isOBBodyOut = false; + bool isOBWorked = youngestOrderFlow + .ob + .IsWorked( + trend, + obWorkerBar, + isOBBodyOut, + false // + ); + + // + bool isOBBodyIn = false; + bool isOBActivated = youngestOrderFlow + .ob + .IsActivated( + trend, + obActivationBar, + isOBBodyIn, + false // + ); + + // + bool isFVGBodyOut = false; + bool isFVGWorked = youngestOrderFlow + .fvg + .IsWorked( + trend, + fvgWorkerBar, + isFVGBodyOut, + false // + ); + + // + bool isFVGBodyIn = false; + bool isFVGActivated = youngestOrderFlow + .fvg + .IsActivated( + trend, + fvgActivationBar, + isFVGBodyIn, + false // + ); + + // + if (!isFVGWorked && + isFVGActivated) + { + // + youngestOrderFlow + .UpdateZones(decisionState); + + // + signalZone = youngestOrderFlow; + youngestOrderFlow.Clean(); + ArrayRemove( + workingZone.orderFlow, + youngestOBFVGIDX, + 1 // + ); + + // + provider = X121SMC_XWZ_PROVIDER_ACTIVATED_ZONE; + } + else + { + // + bool isPriceInsideFVG = + // + IsInside( + consolidationZBar.high, + youngestOrderFlow.fvg // + ) + // + && + // + IsInside( + consolidationZBar.low, + youngestOrderFlow.fvg // + ) + // + ; + + // + if (isPriceInsideFVG) + { + // + youngestOrderFlow + .UpdateZones(decisionState); + + // + signalZone = youngestOrderFlow; + youngestOrderFlow.Clean(); + ArrayRemove( + workingZone.orderFlow, + youngestOBFVGIDX, + 1 // + ); + + // + provider = X121SMC_XWZ_PROVIDER_PRICE_INSIDE_ZONE; + } + } + + // + fvgWorkerBar.Clean(); + fvgActivationBar.Clean(); + } + + // + // Check New Order Blocks ... + bool hasNewConsolidationBullishOB = Contains( + X_BULLISH_ORDERBLOCK_DETECTED, + consolidationPoiEvents // + ); + bool hasNewConsolidationBearishOB = Contains( + X_BEARISH_ORDERBLOCK_DETECTED, + consolidationPoiEvents // + ); + bool hasNewOB = hasNewConsolidationBullishOB || + hasNewConsolidationBearishOB; + + // + // Check New Fair Value Gaps ... + bool hasNewConsolidationBullishFVG = Contains( + X_BULLISH_FVG_DETECTED, + consolidationPoiEvents // + ); + bool hasNewConsolidationBearishFVG = Contains( + X_BEARISH_FVG_DETECTED, + consolidationPoiEvents // + ); + bool hasNewFVG = hasNewConsolidationBullishFVG || + hasNewConsolidationBearishFVG; + + // + // Check New Order Blocks ... + bool hasNewAnalyseBullishOrderBlock = Contains( + X_BULLISH_ORDERBLOCK_DETECTED, + analysePoiEvents // + ); + bool hasNewAnalyseBearishOrderBlock = Contains( + X_BEARISH_ORDERBLOCK_DETECTED, + analysePoiEvents // + ); + bool hasNewAnalyseOB = hasNewAnalyseBullishOrderBlock || + hasNewAnalyseBearishOrderBlock; + + // + // Check New Fair Value Gaps ... + bool hasNewAnalyseBullishFVG = Contains( + X_BULLISH_FVG_DETECTED, + analysePoiEvents // + ); + bool hasNewAnalyseBearishFVG = Contains( + X_BEARISH_FVG_DETECTED, + analysePoiEvents // + ); + bool hasNewAnalyseFVG = hasNewAnalyseBullishFVG || + hasNewAnalyseBearishFVG; + + // + // Do Order Flow Actions when new Order Blocks + // or FVGs Formed ... + if (hasNewOB || + hasNewFVG || + hasNewAnalyseOB || + hasNewAnalyseFVG) + { + // + XCFVG *newFVG = NULL; + XCOrderBlock *newOB = NULL; + XCFVG *newAnalyseFVG = NULL; + XCOrderBlock *newAnalyseOB = NULL; + + // + bool isValid = false; + bool hasWaitingZone = waitingZone.IsValid(); + + // + int idx = -1; + if (hasNewOB) + { + // + if (hasNewConsolidationBullishOB) + { + // + idx = consolidationState.CountBullishOrderBlocks() - 1; + newOB = consolidationState.bullishOrderBlocks[idx]; + } + else + { + // + idx = consolidationState.CountBearishOrderBlocks() - 1; + newOB = consolidationState.bearishOrderBlocks[idx]; + } + + // + if (hasWaitingZone) + { + } + else + { + // + isValid = + !waitingZone.HasOB() + ? true + : !IsSame( + newOB, + waitingZone.ob // + ); + if (isValid) + { + // + bool isAbove = IsAbove( + newOB, + youngestOrderFlow.ob, + true // Ignore Inside ... + ); + bool isBelow = IsBelow( + newOB, + youngestOrderFlow.ob, + true // Ignore Inside ... + ); + + // + isValid = + isBullish + ? isAbove + : isBelow; + + // + if (isValid) + { + waitingZone.ob = newOB; + } + } + } + } + + // + if (hasNewFVG) + { + // + if (hasNewConsolidationBullishFVG) + { + // + idx = consolidationState.CountBullishFairValueGaps() - 1; + newFVG = consolidationState.bullishFairValueGaps[idx]; + } + else + { + // + idx = consolidationState.CountBearishFairValueGaps() - 1; + newFVG = consolidationState.bearishFairValueGaps[idx]; + } + } + + // + if (hasNewAnalyseOB) + { + // + if (hasNewAnalyseBullishOrderBlock) + { + // + idx = analyseState.CountBullishOrderBlocks() - 1; + newAnalyseOB = analyseState.bullishOrderBlocks[idx]; + } + else + { + // + idx = analyseState.CountBearishOrderBlocks() - 1; + newAnalyseOB = analyseState.bearishOrderBlocks[idx]; + } + } + + // + if (hasNewAnalyseFVG) + { + // + if (hasNewAnalyseBullishFVG) + { + // + idx = analyseState.CountBullishFairValueGaps() - 1; + newAnalyseFVG = analyseState.bullishFairValueGaps[idx]; + } + else + { + // + idx = analyseState.CountBearishFairValueGaps() - 1; + newAnalyseFVG = analyseState.bearishFairValueGaps[idx]; + } + + // + if (hasWaitingZone) + { + } + else + { + // + if (waitingZone.HasOB()) + { + // + XCFVG *tmpFVGs[]; + XCFVG *tmpWorkingFVGs[]; + bool isOBBullish = waitingZone.ob.IsBullish(); + if (isOBBullish) + { + Copy( + analyseState.bullishFairValueGaps, + tmpFVGs // + ); + } + else + { + Copy( + analyseState.bearishFairValueGaps, + tmpFVGs // + ); + } + + // + for (int j = 0; j < ArraySize(tmpFVGs); j++) + { + // + XCFVG *jFVG = tmpFVGs[j]; + + // + // Check Start Date ... + bool isFromPassed = jFVG.From() > waitingZone.ob.From(); + if (!isFromPassed) + { + // + ZeroMemory(jFVG); + continue; + } + + // + // Check Place ... + + // + bool isAbove = IsAboveDiff( + jFVG, + waitingZone.ob, + true // + ); + + // + bool isBelow = IsBelowDiff( + jFVG, + waitingZone.ob, + true // + ); + + // + bool isInside = IsInsideDiff( + jFVG, + waitingZone.ob, + false // + ); + + // + bool isPlacePassed = + isInside || + (isBullish + ? isAbove + : isBelow); + if (!isPlacePassed) + { + // + ZeroMemory(jFVG); + continue; + } + + // + Add( + jFVG, + tmpWorkingFVGs // + ); + } + + // + int fvgsCount = ArraySize(tmpWorkingFVGs); + isValid = IsValidSize(fvgsCount); + if (isValid) + { + // + idx = + isBullish + ? GetLowest(tmpWorkingFVGs) + : GetHighest(tmpWorkingFVGs); + + // + if (IsValidIndex(idx)) + { + // + XCFVG *selectedFVG = tmpWorkingFVGs[idx]; + + // + waitingZone.fvg = selectedFVG; + + // + bool isExists = FindIndex( + idx, + selectedFVG, + tmpFVGs // + ); + if (isExists) + { + // + ArrayRemove( + tmpFVGs, + idx, + 1 // + ); + } + } + } + + // + Clean(tmpFVGs); + Clean(tmpWorkingFVGs); + } + } + } + + // + hasWaitingZone = waitingZone.IsValid(); + if (hasWaitingZone) + { + // + bool isSameDir = waitingZone.GetDirection() == trend; + if (!isSameDir) + { + targetZone = waitingZone; + } + else + { + workingZone.AddOrderFlowItem(waitingZone); + } + + // + waitingZone.Clean(); + } + + // + if (signalZone.IsValid() && + provider == X121SMC_XWZ_PROVIDER_ACTIVATED_CHOCH) + { + // + ENUM_X_DIRECTION iForDir = Opposit(signalZone.GetDirection()); + if (hasNewAnalyseOB && + hasNewAnalyseFVG) + { + // + bool isSameDir = + newAnalyseOB.GetDirection() == iForDir && + newAnalyseFVG.GetDirection() == iForDir; + bool isOneInsideAnoter = + // + (newAnalyseFVG.Upper() < newAnalyseOB.Upper() && + newAnalyseFVG.Upper() > newAnalyseOB.Lower()) + // + || + // + (newAnalyseOB.Upper() < newAnalyseFVG.Upper() && + newAnalyseOB.Upper() > newAnalyseFVG.Lower()) + // + ; + + // + bool isZoneDetected = + isSameDir && + isOneInsideAnoter; + if (isZoneDetected) + { + // + XOBFVG iSignalZone; + iSignalZone.ob = newAnalyseOB; + iSignalZone.fvg = newAnalyseFVG; + + // + chochZone = iSignalZone; + } + } + } + + // + ZeroMemory(newOB); + ZeroMemory(newFVG); + ZeroMemory(newAnalyseOB); + ZeroMemory(newAnalyseFVG); + } + + // + bool isPriceInsideCHOCHZone = false; + bool hasCHOCHZone = chochZone.IsValid(); + if (hasCHOCHZone) + { + // + XOHCL cBar; + bool isInited = cBar.Init( + symbol, + period, + cIndex // + ); + + // + isPriceInsideCHOCHZone = + isInited && + cBar.low >= chochZone.fvg.Lower() && + cBar.high <= chochZone.fvg.Upper(); + if (isPriceInsideCHOCHZone) + { + // + // Reverse Trend and ReCalculate Requirements + // For CHOCH Tradng ... + + // + trend = chochZone.GetDirection(); + + // + isBullish = IsBullish(trend); + isBearish = IsBearish(trend); + + // + bool hasPriority = workingZone + .DetectPriority( + priority, + trend, + zIndex, + period // + ); + + // + bool hasRewardAmount = CalculateRiskReward( + priority, + reward, + amountPercent // + ); + + // + provider = X121SMC_XWZ_PROVIDER_ACTIVATED_CHOCH; + } + + // + cBar.Clean(); + } + + // + // + // + + // + if (hasSupplyZones || + hasDemandZones) + { + // + UpdateTo(cTime); + DrawWorkingZone( + visionCycleHelper.mPOIDrawer // + ); + Print("CHECK ..."); + } + + // + // Reading Trand Line Value ... + double zValue = workingZone.GetOrderFlowTrendLinePrice( + zIndex, + period // + ); + double cValue = workingZone.GetOrderFlowTrendLinePrice( + cIndex, + period // + ); + double pValue = workingZone.GetOrderFlowTrendLinePrice( + pIndex, + period // + ); + double ppValue = workingZone.GetOrderFlowTrendLinePrice( + ppIndex, + period // + ); + + // + // Implementing Signals ... + // + + // + // TODO: Implement Order Flow Side Trading Senario ... + bool hasOrderFlowConditions = + hasTrend && + hasPriority && + hasRewardAmount && + signalZone.IsValid() && + provider == X121SMC_XWZ_PROVIDER_ACTIVATED_ZONE; + + // + hasOrderFlowhBullishConditions = + isBullish && + hasOrderFlowConditions && + signalZone.IsBullish(); + + // + hasOrderFlowhBearishConditions = + isBearish && + hasOrderFlowConditions && + signalZone.IsBearish(); + + // + if (hasOrderFlowConditions) + { + // + mConditions.signalZone = signalZone; + + // + point = hasOrderFlowhBullishConditions + ? signalZone.ob.Upper() + : signalZone.ob.Lower(); + + // + pivot = hasOrderFlowhBullishConditions + ? signalZone.ob.Lower() + : signalZone.ob.Upper(); + + // + signalZone.Clean(); + } + + // + // TODO: Implement Inside Zone Trading Senario ... + bool hasInsideZoneConditions = + hasTrend && + hasPriority && + hasRewardAmount && + signalZone.IsValid() && + provider == X121SMC_XWZ_PROVIDER_PRICE_INSIDE_ZONE; + + // + bool hasInsideZoneBullishConditions = + isBullish && + signalZone.IsBullish() && + hasInsideZoneConditions; + + // + bool hasInsideZoneBearishConditions = + isBearish && + signalZone.IsBearish() && + hasInsideZoneConditions; + + // + if (hasInsideZoneConditions) + { + // + mConditions.signalZone = signalZone; + + // + point = hasOrderFlowhBullishConditions + ? signalZone.ob.Upper() + : signalZone.ob.Lower(); + + // + pivot = hasOrderFlowhBullishConditions + ? signalZone.ob.Lower() + : signalZone.ob.Upper(); + + // + signalZone.Clean(); + } + + // + // TODO: Implement CHOCH Trading Senario ... + bool hasCHOCHConditions = + hasCHOCHZone && + chochZone.IsValid() && + isPriceInsideCHOCHZone && + provider == X121SMC_XWZ_PROVIDER_ACTIVATED_CHOCH; + + // + hasChochBullishConditions = + hasCHOCHConditions && + chochZone.IsBullish(); + hasChochBearishConditions = + hasCHOCHConditions && + chochZone.IsBearish(); + + // + if (hasCHOCHConditions) + { + // + mConditions.signalZone = chochZone; + + // + point = hasChochBullishConditions + ? chochZone.ob.Upper() + : chochZone.ob.Lower(); + + // + pivot = hasChochBearishConditions + ? chochZone.ob.Lower() + : chochZone.ob.Upper(); + + // + chochZone.Clean(); + signalZone.Clean(); + } + + // + // TODO: Implement Trend Line Trading Senario ... + + // + // TODO: Implement Quarter Line Trading Senario ... + + // + // TODO: Implement Supply and Demand Trading Senario ... + + // + // TODO: Implement Support and Resistance Trading Senario ... + + // + // TODO: Implement Mitigation Blocks Trading Senario ... + + // + // Summarize ... + + // + bool hasBullishConditions = + // + hasChochBullishConditions || + hasSupDemBullishConditions || + hasSupResBullishConditions || + hasTrendLineBullishConditions || + hasOrderFlowhBullishConditions || + hasInsideZoneBullishConditions || + hasBQuarterLineBullishConditions + // + ; + + // + bool hasBearishConditions = + // + hasChochBearishConditions || + hasSupDemBearishConditions || + hasSupResBearishConditions || + hasTrendLineBearishConditions || + hasOrderFlowhBearishConditions || + hasInsideZoneBearishConditions || + hasBQuarterLineBearishConditions + // + ; + + // + result = + hasBullishConditions || + hasBearishConditions; + + // + if (result) + { + // + mConditions.dir = trend; + mConditions.pivot = pivot; + mConditions.point = point; + mConditions.reward = reward; + mConditions.setupTime = cTime; + mConditions.priority = priority; + mConditions.provider = provider; + mConditions.amountPercent = amountPercent; + } + + // + // Cleanups ... + + // + Clean(visionPoiEvents); + Clean(analysePoiEvents); + Clean(decisionPoiEvents); + Clean(consolidationPoiEvents); + + // + Clean(visionCycleEvents); + Clean(analyseCycleEvents); + Clean(decisionCycleEvents); + Clean(consolidationCycleEvents); + + // + visionState.Clean(); + analyseState.Clean(); + decisionState.Clean(); + consolidationState.Clean(); + + // + visionConditions.Clean(); + analyseConditions.Clean(); + decisionConditions.Clean(); + consolidationConditions.Clean(); + + // + visionXConditions.Clean(); + analyseXConditions.Clean(); + decisionXConditions.Clean(); + consolidationXConditions.Clean(); + + // + // mConditions.Clean(); + consolidationZBar.Clean(); + + // + return result; + } + + // + // Detect Trigger Conditions ... + bool DetectSignalTrigger( + // + X121SMCStrategyXWZSignalConditions &conditions, + // + string _symbol, + ENUM_TIMEFRAMES _period, + // + XC121SMCCycleHelper *decisionCycleHelper, + XC121SMCCycleHelper *analyseCycleHelper, + XC121SMCCycleHelper *consolidationCycleHelper, + XC121SMCCycleHelper *visionCycleHelper, + // + int maxAllowedSetupAge = 60 + // + ) + { + // + bool result = false; + + // + result = + // + visionCycleHelper != NULL && + analyseCycleHelper != NULL && + decisionCycleHelper != NULL && + consolidationCycleHelper != NULL + // + ; + if (!result) + { + return result; + } + + // + result = conditions.IsSetuped(); + if (!result) + { + return result; + } + + // + datetime setupTime = conditions.setupTime; + ENUM_X_DIRECTION setupDir = conditions.dir; + + // + bool isBullish = IsBullish(setupDir); + bool isBearish = IsBearish(setupDir); + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + int loopback = 10; + + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + double points = GetPoints(symbol); + + // + double sls[]; + + // + // Cycles Conditions ... + + // + // Decision ... + ENUM_XPOI_EVENTS decisionPoiEvents[]; + ENUM_X_CYCLE_EVENTS decisionCycleEvents[]; + X121SMCCycleConditions decisionConditions; + result = decisionCycleHelper.GetConditions( + decisionCycleEvents, + decisionPoiEvents, + decisionConditions, + zIndex, + loopback // + ); + if (!result) + { + // + // Cleanup ... + + // + Clean(decisionPoiEvents); + Clean(decisionCycleEvents); + + // + decisionConditions.Clean(); + + // + return result; + } + + // + // Analyse ... + ENUM_XPOI_EVENTS analysePoiEvents[]; + ENUM_X_CYCLE_EVENTS analyseCycleEvents[]; + X121SMCCycleConditions analyseConditions; + result = analyseCycleHelper.GetConditions( + analyseCycleEvents, + analysePoiEvents, + analyseConditions, + zIndex, + loopback // + ); + if (!result) + { + // + Clean(analysePoiEvents); + Clean(decisionPoiEvents); + + // + Clean(analyseCycleEvents); + Clean(decisionCycleEvents); + + // + analyseConditions.Clean(); + decisionConditions.Clean(); + + // + return result; + } + + // + // Cycles POI States ... + XPOIState decisionState = decisionConditions.state; + XPOIState analyseState = analyseConditions.state; + + // + // Cycle X121Conditions ... + X121Conditions decisionXConditions = decisionConditions.x121Conditions; + X121Conditions analyseXConditions = analyseConditions.x121Conditions; + + // + // Check Signal Validation ... + + // + XOHCL cBar; + bool isInited = cBar.Init( + conditions.symbol, + conditions.period, + cIndex // + ); + XOHCL pBar; + isInited = + isInited && + cBar.GetPreviousBar(pBar); + bool isLowerBreaked = + // + isInited && + cBar.high < conditions.point && + pBar.high >= conditions.point + // + ; + bool isUpperBreaked = + // + isInited && + cBar.low > conditions.point && + pBar.low <= conditions.point + // + ; + bool isZoneBreaked = + (isBullish && + isLowerBreaked) || + (isBearish && + isUpperBreaked); + result = !isZoneBreaked; + if (!result) + { + // + cBar.Clean(); + pBar.Clean(); + conditions.Clean(); + + // + Clean(decisionPoiEvents); + Clean(decisionCycleEvents); + + // + decisionState.Clean(); + decisionConditions.Clean(); + decisionXConditions.Clean(); + + // + Clean(analysePoiEvents); + Clean(analyseCycleEvents); + + // + analyseState.Clean(); + analyseConditions.Clean(); + analyseXConditions.Clean(); + } + + // + cBar.Clean(); + pBar.Clean(); + + // + double bullishScore = 0; + double bearishScore = 0; + decisionXConditions.GenerateScore( + bullishScore, + bearishScore // + ); + bool isBullishScorePassed = + isBullish && + bullishScore > (bearishScore * 1.5); + bool isBearishScorePassed = + isBearish && + bearishScore > (bullishScore * 1.5); + bool isScorePassed = isBullishScorePassed || + isBearishScorePassed; + + // + // Base SL Used Pivot of Conditions ... + // Add( + // conditions.pivot, + // sls // + // ); + + // + int lowestSupportIDX = -1; + int highestResistanceIDX = -1; + bool isSupportRejected = false; + bool isResistanceRejected = false; + bool hasSignalZone = conditions.signalZone.IsValid(); + if (hasSignalZone) + { + // + conditions + .signalZone + .UpdateZones(decisionState); + conditions + .signalZone + .UpdateTo(cTime); + + // + XOHCL cBar; + bool isBarInited = cBar.Init( + conditions.symbol, + conditions.period, + cIndex // + ); + + // + lowestSupportIDX = GetLowest(conditions.signalZone.supportZones); + if (IsValidIndex(lowestSupportIDX)) + { + // + isSupportRejected = + // + isBarInited && + ( + // + (cBar.low < conditions.signalZone.supportZones[lowestSupportIDX].Upper() && + cBar.GetDown() > conditions.signalZone.supportZones[lowestSupportIDX].Upper()) + // + || + // + (cBar.low < conditions.signalZone.supportZones[lowestSupportIDX].Lower() && + cBar.GetDown() > conditions.signalZone.supportZones[lowestSupportIDX].Lower()) + // + ) + // + ; + + // + isSupportRejected = + isBullish && + isSupportRejected; + if (isSupportRejected) + { + // + double vPivot = conditions.signalZone.supportZones[lowestSupportIDX].Lower(); + bool canSetPivot = vPivot > conditions.pivot && + vPivot < conditions.point; + if (canSetPivot) + { + // + Add( + vPivot, + sls // + ); + } + } + } + + // + highestResistanceIDX = GetHighest(conditions.signalZone.resistanceZones); + if (IsValidIndex(highestResistanceIDX)) + { + // + isResistanceRejected = + // + isBarInited && + ( + // + (cBar.high > conditions.signalZone.resistanceZones[highestResistanceIDX].Upper() && + cBar.GetUp() < conditions.signalZone.resistanceZones[highestResistanceIDX].Upper()) + // + || + // + (cBar.high > conditions.signalZone.resistanceZones[highestResistanceIDX].Lower() && + cBar.GetUp() < conditions.signalZone.resistanceZones[highestResistanceIDX].Lower()) + // + ) + // + ; + + // + isResistanceRejected = + isBearish && + isResistanceRejected; + if (isResistanceRejected) + { + // + double vPivot = conditions.signalZone.resistanceZones[highestResistanceIDX].Upper(); + bool canSetPivot = vPivot < conditions.pivot && + vPivot > conditions.point; + if (canSetPivot) + { + // + Add( + vPivot, + sls // + ); + } + } + } + + // + cBar.Clean(); + } + + // + // Consolidation Zone Detection ... + + // + // Detect Consolidation Zones ... + + // + // Bullish Consolidation Zone ... + XConsolidationZone bullishCZones[]; + bool hasBullishConsolidationZone = false; + XConsolidationZone bullishConsolidationZone; + int bullishCZonesCount = decisionCycleHelper.FillConsolidationZones( + X_DIRECTION_BULLISH, + bullishCZones // + ); + bool hasBullishConsolidationZones = IsValidSize(bullishCZonesCount); + if (hasBullishConsolidationZones) + { + // + int idx = -1; + while (HasChild(bullishCZones)) + { + // + idx = GetYoungest(bullishCZones); + hasBullishConsolidationZone = IsValidIndex(idx); + if (hasBullishConsolidationZone) + { + // + bullishConsolidationZone = bullishCZones[idx]; + + // + ArrayRemove( + bullishCZones, + idx, + 1 // + ); + + // + // Check Zone Based On pivot, since this is the SL ... + hasBullishConsolidationZone = + isBullish && + hasBullishConsolidationZone && + bullishConsolidationZone.lower > conditions.pivot && + bullishConsolidationZone.upper <= conditions.point; + if (hasBullishConsolidationZone) + { + // + Add( + bullishConsolidationZone.lower, + sls // + ); + } + } + } + } + Clean(bullishCZones); + bullishConsolidationZone.Clean(); + + // + // Bearish Consolidation Zone ... + XConsolidationZone bearishCZones[]; + bool hasBearishConsolidationZone = false; + XConsolidationZone bearishConsolidationZone; + int bearishCZonesCount = decisionCycleHelper.FillConsolidationZones( + X_DIRECTION_BEARISH, + bearishCZones // + ); + bool hasBearishConsolidationZones = IsValidSize(bearishCZones); + if (hasBearishConsolidationZones) + { + // + int idx = -1; + while (HasChild(bearishCZones)) + { + // + idx = GetYoungest(bearishCZones); + hasBearishConsolidationZone = IsValidIndex(idx); + if (hasBearishConsolidationZone) + { + // + bearishConsolidationZone = bearishCZones[idx]; + + // + ArrayRemove( + bearishCZones, + idx, + 1 // + ); + + // + hasBearishConsolidationZone = + isBearish && + hasBearishConsolidationZone && + bearishConsolidationZone.upper < conditions.pivot && + bearishConsolidationZone.lower >= conditions.point; + if (hasBearishConsolidationZone) + { + // + Add( + bearishConsolidationZone.upper, + sls // + ); + } + } + } + } + Clean(bearishCZones); + bearishConsolidationZone.Clean(); + + // + // Check VWap Crossing ... + + // + bool isVWapSwitchedToBullish = + // + (decisionXConditions.isVWapBullishOrdered && + decisionXConditions.isVWapSwitchedToBullishState) + // + || + // + (decisionXConditions.isVWapBullishState && + decisionXConditions.isVWapSwitchedToBullishOrdered) + // + ; + + // + isVWapSwitchedToBullish = + isBullish && + isVWapSwitchedToBullish; + if (isVWapSwitchedToBullish) + { + // + double vPivot = decisionXConditions.vwapMin; + bool canSetPivot = vPivot > conditions.pivot && + vPivot < conditions.point; + if (canSetPivot) + { + // + Add( + vPivot, + sls // + ); + } + } + + // + bool isVWapSwitchedToBearish = + // + (decisionXConditions.isVWapBearishOrdered && + decisionXConditions.isVWapSwitchedToBearishState) + // + || + // + (decisionXConditions.isVWapBearishState && + decisionXConditions.isVWapSwitchedToBearishOrdered) + // + ; + + // + isVWapSwitchedToBearish = + isBearish && + isVWapSwitchedToBearish; + if (isVWapSwitchedToBearish) + { + // + double vPivot = decisionXConditions.vwapMax; + bool canSetPivot = vPivot < conditions.pivot && + vPivot > conditions.point; + if (canSetPivot) + { + // + Add( + vPivot, + sls // + ); + } + } + + // + // Point Break ... + isInited = cBar.Init( + conditions.symbol, + conditions.period, + cIndex // + ); + double point = conditions.point; + bool isPointBreaked = + isInited && + IsBarBreak( + point, + setupDir, + cBar // + ); + cBar.Clean(); + + // + bool isCommonsPassed = + // + (isSupportRejected || + isResistanceRejected || + isVWapSwitchedToBullish || + isVWapSwitchedToBearish || + hasBullishConsolidationZone || + hasBearishConsolidationZone) + // + ; + + // + // Trigger Conditions ... + + // + bool canTriggerCHOCHZone = + // + isScorePassed && + isCommonsPassed && + conditions.provider == X121SMC_XWZ_PROVIDER_ACTIVATED_CHOCH + // + ; + + // + bool canTriggerActivatedZone = + // + // isPointBreaked && + isScorePassed && + isCommonsPassed && + conditions.provider == X121SMC_XWZ_PROVIDER_ACTIVATED_ZONE + // + ; + + // + bool canTriggerPriceInsideZone = + // + isScorePassed && + isCommonsPassed && + conditions.provider == X121SMC_XWZ_PROVIDER_PRICE_INSIDE_ZONE + // + ; + + // + bool canTrigger = (canTriggerCHOCHZone || + canTriggerActivatedZone || + canTriggerPriceInsideZone); + + // + // Summary ... + + // + isBullish = + // + isBullish && + canTrigger + // + ; + + // + isBearish = + // + isBearish && + canTrigger + // + ; + + // + result = isBullish || + isBearish; + if (!result) + { + // + // Cleanup Setup Conditions ... + int setupAge = conditions.GetSetupAge(); + if (IsValidSize(setupAge) && + IsValidSize(maxAllowedSetupAge) && + setupAge >= maxAllowedSetupAge) + { + conditions.Clean(); + } + + // + // Cleanup ... + + // + cBar.Clean(); + pBar.Clean(); + + // + Clean(decisionPoiEvents); + Clean(decisionCycleEvents); + + // + decisionState.Clean(); + decisionConditions.Clean(); + decisionXConditions.Clean(); + + // + Clean(analysePoiEvents); + Clean(analyseCycleEvents); + + // + analyseState.Clean(); + analyseConditions.Clean(); + analyseXConditions.Clean(); + + // + return result; + } + + // + double entry = GetEntry( + conditions.symbol, + setupDir // + ); + + // + // Manipulate SL Based on Consolidation Zones ... + + // + double iAtr = decisionXConditions.atrBuffer[1]; + iAtr *= 1.5; + + // + // Since Pivot Value almost used + // as Default SL, if there isn't any Refind SL + // we use Default ... + if (!HasChild(sls)) + { + // + Add( + conditions.pivot, + sls // + ); + } + + // + double slsMin = GetMin(sls); + double slsMax = GetMax(sls); + + // + double sl = isBullish + ? slsMin - iAtr + : slsMax + iAtr; + double risk = MathAbs(entry - sl); + + // + // Filling Conditions Props ... + conditions.sl = sl; + conditions.triggerTime = cTime; + conditions.type = isBullish + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_SHORT; + + // + // Checking Targets ... + + // + ENUM_X121SMC_XWZ_PRIORITY priority = X121SMC_XWZ_PRIORITY_NONE; + bool hasPriority = workingZone + .DetectPriority( + priority, + setupDir, + zIndex, + decisionState.period // + ); + + // + // Order Block Targets ... + + // + XCOrderBlock *bullishOBs[]; + Copy( + analyseState.bullishOrderBlocks, + bullishOBs // + ); + + // + // Extract Available Order Blocks ... + int bullishOBsCont = FilterZones( + // + bullishOBs, + // + X_DIRECTION_BULLISH, + analyseState.period, + NULL, + // + // Start ... + XZONE_STATE_IGNORED, + false, + // + // Activation ... + XZONE_STATE_IGNORED, + false, + // + // Breake ... + XZONE_STATE_FAILED, + false, + // + // Work ... + XZONE_STATE_IGNORED, + false, + // + true, // Apply Sore ... + true // Ignore Inside ... + ); + bool hasBullishOBs = HasChild(bullishOBs); + + // + XCOrderBlock *bearishOBs[]; + Copy( + analyseState.bearishOrderBlocks, + bearishOBs // + ); + + // + // Extract Available Order Blocks ... + int bearishOBsCont = FilterZones( + // + bearishOBs, + // + X_DIRECTION_BEARISH, + analyseState.period, + NULL, + // + // Start ... + XZONE_STATE_IGNORED, + false, + // + // Activation ... + XZONE_STATE_IGNORED, + false, + // + // Breake ... + XZONE_STATE_FAILED, + false, + // + // Work ... + XZONE_STATE_IGNORED, + false, + // + true, // Apply Sore ... + true // Ignore Inside ... + ); + bool hasBearishOBs = HasChild(bearishOBs); + + // + if (isBullish && + hasBearishOBs) + { + // + int count = ArraySize(bearishOBs); + for (int i = 0; i < count; i++) + { + // + XCBaseObject *iObj; + bool isCreated = visionCycleHelper + .mPOIDrawer + .CreateOrderBlock( + bearishOBs[i], + iObj // + ); + if (isCreated) + { + mObjects.Add(iObj); + } + + // + double value = bearishOBs[i].Lower(); + bool canSet = value > entry; + if (canSet) + { + // + Add( + value, + conditions.targets // + ); + } + } + } + + // + if (isBearish && + hasBullishOBs) + { + // + int count = ArraySize(bullishOBs); + for (int i = 0; i < count; i++) + { + // + XCBaseObject *iObj; + bool isCreated = visionCycleHelper + .mPOIDrawer + .CreateOrderBlock( + bullishOBs[i], + iObj // + ); + if (isCreated) + { + mObjects.Add(iObj); + } + + // + double value = bullishOBs[i].Upper(); + bool canSet = value < entry; + if (canSet) + { + // + Add( + value, + conditions.targets // + ); + } + } + } + + // + Clean(bullishOBs); + Clean(bearishOBs); + + // + // Detect Quarter Targets ... + + // + double quarterTarget = 0; + if (hasPriority) + { + // + switch (priority) + { + // + case X121SMC_XWZ_PRIORITY_WEAK: + // + quarterTarget = + isBullish + ? workingZone.supplyZone.Lower() + : workingZone.demandZone.Upper(); + break; + + // + case X121SMC_XWZ_PRIORITY_LOW: + // + quarterTarget = + isBullish + ? workingZone.quarter1 + : workingZone.quarter3; + break; + + // + case X121SMC_XWZ_PRIORITY_REGULAR: + // + quarterTarget = + isBullish + ? workingZone.quarter2 + : workingZone.quarter2; + break; + + // + case X121SMC_XWZ_PRIORITY_HIGH: + // + quarterTarget = + isBullish + ? workingZone.quarter3 + : workingZone.quarter1; + break; + + // + case X121SMC_XWZ_PRIORITY_STRONG_HIGH: + // + quarterTarget = + isBullish + ? workingZone.demandZone.Upper() + : workingZone.supplyZone.Lower(); + break; + } + } + + // + if (quarterTarget > 0) + { + // + Add( + quarterTarget, + conditions.targets // + ); + } + + // + // Cleanup ... + + // + cBar.Clean(); + pBar.Clean(); + + // + Clean(decisionPoiEvents); + Clean(decisionCycleEvents); + + // + decisionState.Clean(); + decisionConditions.Clean(); + decisionXConditions.Clean(); + + // + Clean(analysePoiEvents); + Clean(analyseCycleEvents); + + // + analyseState.Clean(); + analyseConditions.Clean(); + analyseXConditions.Clean(); + + // + return result; + } + + // + // Detect Guards ... + bool DetectGuards( + // + X121SMCGuard &guards[], + const XPosition &positions[], + // + XC121SMCCycleHelper *decisionCycleHelper, + XC121SMCCycleHelper *analyseCycleHelper, + XC121SMCCycleHelper *consolidationCycleHelper, + XC121SMCCycleHelper *visionCycleHelper + // + ) + { + // + bool result = false; + + // + Clean(guards); + + // + bool isCycleHelpersValid = + // + visionCycleHelper != NULL && + analyseCycleHelper != NULL && + decisionCycleHelper != NULL && + consolidationCycleHelper != NULL + // + ; + + // + return false; + + // + result = isCycleHelpersValid; + if (!result) + { + return result; + } + + // + int count = ArraySize(positions); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + string provider = ToString(X_121_SMC_PROVIDER_XWZ); + + // + XPosition ownPositions[]; + XPosition ownLongPositions[]; + XPosition ownShortPositions[]; + for (int i = 0; i < count; i++) + { + // + XPosition iPosition = positions[i]; + bool isOwn = iPosition + .IsFiltersPassed( + symbol, + provider, + NULL, + X_POSITION_TYPE_ALL, + iPosition.magic // + ); + if (isOwn) + { + // + AddRef( + iPosition, + ownPositions // + ); + + // + bool isLong = IsLong(positions[i].type); + if (isLong) + { + // + AddRef( + iPosition, + ownLongPositions // + ); + } + else + { + // + AddRef( + iPosition, + ownShortPositions // + ); + } + } + } + + // + count = ArraySize(ownPositions); + + // + int longsCount = ArraySize(ownLongPositions); + bool hasLongs = IsValidSize(longsCount); + + // + int shortsCount = ArraySize(ownShortPositions); + bool hasShorts = IsValidSize(shortsCount); + + // + result = IsValidSize(count); + if (!result) + { + // + Clean(ownPositions); + Clean(ownLongPositions); + Clean(ownShortPositions); + + // + return result; + } + + // + // + // + + // + // Get Global and Common Guards ... + + // + ENUM_X_121_SMC_GUARD_ACTIONS ignoreGuards[1] = { + X_121_SMC_GUARD_ACTION_TRAIL_STOP // + }; + result = DetectX121SMCGuards( + provider, + guards, + positions, + decisionCycleHelper, + analyseCycleHelper, + consolidationCycleHelper, + visionCycleHelper, + // + ignoreGuards + // + ); + + // + // + // + + // + // Get Custom Implemented Guards ... + + // + // Here we Are Sure there is Positions to Guard ... + // based on Current Provider ... + + // + // Detect Required Data for Analyse Market to Guard Positions ... + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + int loopback = 10; + + // + XOHCL zBar; + result = zBar.Init( + symbol, + period, + zIndex // + ); + if (!result) + { + // + result = HasChild(guards); + return result; + } + + // + XOHCL cBar; + result = cBar.Init( + symbol, + period, + cIndex // + ); + if (!result) + { + // + zBar.Clean(); + result = HasChild(guards); + return result; + } + + // + XOHCL pBar; + result = pBar.Init( + symbol, + period, + pIndex // + ); + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + result = HasChild(guards); + return result; + } + + // + XOHCL ppBar; + result = ppBar.Init( + symbol, + period, + ppIndex // + ); + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + result = HasChild(guards); + return result; + } + + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + double points = GetPoints(symbol); + + // + + // + // Cycles Conditions ... + + // + // Decision ... + ENUM_XPOI_EVENTS decisionPoiEvents[]; + ENUM_X_CYCLE_EVENTS decisionCycleEvents[]; + X121SMCCycleConditions decisionConditions; + result = decisionCycleHelper.GetConditions( + decisionCycleEvents, + decisionPoiEvents, + decisionConditions, + zIndex, + loopback // + ); + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + ppBar.Clean(); + result = HasChild(guards); + return result; + } + + // + // Analyse ... + ENUM_XPOI_EVENTS analysePoiEvents[]; + ENUM_X_CYCLE_EVENTS analyseCycleEvents[]; + X121SMCCycleConditions analyseConditions; + result = analyseCycleHelper.GetConditions( + analyseCycleEvents, + analysePoiEvents, + analyseConditions, + zIndex, + loopback // + ); + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + ppBar.Clean(); + + // + Clean(decisionPoiEvents); + Clean(decisionCycleEvents); + + // + decisionConditions.Clean(); + + // + result = HasChild(guards); + return result; + } + + // + // Consolidation ... + ENUM_XPOI_EVENTS consolidationPoiEvents[]; + ENUM_X_CYCLE_EVENTS consolidationCycleEvents[]; + X121SMCCycleConditions consolidationConditions; + result = consolidationCycleHelper.GetConditions( + consolidationCycleEvents, + consolidationPoiEvents, + consolidationConditions, + zIndex, + loopback // + ); + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + ppBar.Clean(); + + // + Clean(decisionPoiEvents); + Clean(decisionCycleEvents); + + // + decisionConditions.Clean(); + + // + Clean(analysePoiEvents); + Clean(analyseCycleEvents); + + // + analyseConditions.Clean(); + + // + result = HasChild(guards); + return result; + } + + // + // Vision ... + ENUM_XPOI_EVENTS visionPoiEvents[]; + ENUM_X_CYCLE_EVENTS visionCycleEvents[]; + X121SMCCycleConditions visionConditions; + result = visionCycleHelper.GetConditions( + visionCycleEvents, + visionPoiEvents, + visionConditions, + zIndex, + loopback // + ); + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + ppBar.Clean(); + + // + Clean(decisionPoiEvents); + Clean(decisionCycleEvents); + + // + decisionConditions.Clean(); + + // + Clean(analysePoiEvents); + Clean(analyseCycleEvents); + + // + analyseConditions.Clean(); + + // + Clean(consolidationPoiEvents); + Clean(consolidationCycleEvents); + + // + consolidationConditions.Clean(); + + // + result = HasChild(guards); + return result; + } + + // + // Cycles POI States ... + XPOIState decisionState = decisionConditions.state; + XPOIState analyseState = analyseConditions.state; + XPOIState consolidationState = consolidationConditions.state; + XPOIState visionState = visionConditions.state; + + // + // Cycle X121Conditions ... + X121Conditions decisionXConditions = decisionConditions.x121Conditions; + X121Conditions analyseXConditions = analyseConditions.x121Conditions; + X121Conditions consolidationXConditions = consolidationConditions.x121Conditions; + X121Conditions visionXConditions = visionConditions.x121Conditions; + + // + // + // + + // + // Detect Consolidation Zone ... + + // + // Bullish ... + XConsolidationZone bullishConsolidationZone; + bool hasBullishConsolidationZone = decisionCycleHelper + .GetLastDirectionalConsolidationZone( + X_DIRECTION_BULLISH, + bullishConsolidationZone // + ); + + // + // Bearish ... + XConsolidationZone bearishConsolidationZone; + bool hasBearishConsolidationZone = decisionCycleHelper + .GetLastDirectionalConsolidationZone( + X_DIRECTION_BEARISH, + bearishConsolidationZone // + ); + + // + // Detect High Probability Swings ... + bool isSwingLow = + // + cBar.low > pBar.low && + ppBar.low > pBar.low && + // + zBar.low > pBar.low + // + ; + bool isSwingHigh = + // + cBar.high < pBar.high && + ppBar.high < pBar.high && + // + zBar.high < pBar.high + // + ; + bool isStrongSwingLow = + pBar.IsBullish() && + pBar.GetLowShadow() >= pBar.GetBody() * 2; + bool isStrongSwingHigh = + pBar.IsBearish() && + pBar.GetHighShadow() >= pBar.GetBody() * 2; + + // + // Here We Have all Requirements for Guarding Positions ... + + // + // Available Guards: + // X_121_SMC_GUARD_ACTION_NONE + // X_121_SMC_GUARD_ACTION_CLOSE + // X_121_SMC_GUARD_ACTION_CLOSE_ALL + // X_121_SMC_GUARD_ACTION_CLOSE_LONGS + // X_121_SMC_GUARD_ACTION_CLOSE_SHORTS + // X_121_SMC_GUARD_ACTION_PARTIAL_CLOSE + // X_121_SMC_GUARD_ACTION_TRAIL_STOP + // X_121_SMC_GUARD_ACTION_TRAIL_TARGET + // X_121_SMC_GUARD_ACTION_HEDGE + + // + // X_121_SMC_GUARD_ACTION_CLOSE: + // Close Specified Position on Specified Conditions ... + + // + // X_121_SMC_GUARD_ACTION_CLOSE_ALL: + // Close All Positions on Specified Conditions ... + + // + // X_121_SMC_GUARD_ACTION_CLOSE_LONGS: + // Close All Long Positions on Specified Conditions ... + + // + // X_121_SMC_GUARD_ACTION_CLOSE_SHORTS: + // Close All Short Positions on Specified Conditions ... + + // + // X_121_SMC_GUARD_ACTION_PARTIAL_CLOSE: + // Partial Close Specified Position on Specified Conditions ... + + // + // X_121_SMC_GUARD_ACTION_TRAIL_STOP: + // Trail Stop Specified Position on Specified Conditions ... + for (int i = 0; i < count; i++) + { + // + XPosition iPosition = ownPositions[i]; + + // + bool isLong = IsLong(iPosition.type); + bool isInProfit = iPosition.profit > 0; + + // + double sl = iPosition.sl; + double tp = iPosition.tp; + + // + // Trail Stops Using Consolidation Zones ... + bool canTraiLonglUsingCZone = + // + (isLong && + isInProfit && + hasBullishConsolidationZone && + bullishConsolidationZone.lower > iPosition.sl && + bullishConsolidationZone.lower > iPosition.entry) + // + ; + if (canTraiLonglUsingCZone) + { + sl = bullishConsolidationZone.lower; + } + + // + bool canTraiShortlUsingCZone = + // + (!isLong && + isInProfit && + hasBearishConsolidationZone && + bearishConsolidationZone.upper < iPosition.sl && + bearishConsolidationZone.upper < iPosition.entry) + // + ; + if (canTraiShortlUsingCZone) + { + sl = bearishConsolidationZone.upper; + } + + // + bool canTrailUsingCZone = + canTraiLonglUsingCZone || + canTraiShortlUsingCZone; + + // + // Trail Stops Using Swings ... + + // + bool canTrailLongUsingSwings = + // + isLong && + isInProfit && + (isSwingLow || + isStrongSwingLow) && + pBar.low > iPosition.sl && + pBar.low > iPosition.entry + // + ; + if (canTrailLongUsingSwings) + { + sl = pBar.low; + } + + // + bool canTraiShortlUsingSwings = + // + !isLong && + isInProfit && + (isSwingHigh || + isStrongSwingHigh) && + pBar.high < iPosition.sl && + pBar.high < iPosition.entry + // + ; + if (canTraiShortlUsingSwings) + { + sl = pBar.high; + } + + // + bool canTrailUsingSwings = + canTrailLongUsingSwings || + canTraiShortlUsingSwings; + + // + // + // + + // + bool canTrail = + sl != iPosition.sl && + (canTrailUsingCZone || + canTrailUsingSwings); + if (canTrail) + { + // + X121SMCGuard iGuard; + + // + iGuard.time = cTime; + iGuard.symbol = symbol; + iGuard.provider = provider; + iGuard.action = X_121_SMC_GUARD_ACTION_TRAIL_STOP; + + // + iGuard.ticket = iPosition.ticket; + + // + iGuard.sl = sl; + + // + AddGuard( + iGuard, + guards // + ); + } + } + + // + // X_121_SMC_GUARD_ACTION_TRAIL_TARGET: + // Trail Target Specified Position on Specified Conditions ... + + // + // X_121_SMC_GUARD_ACTION_HEDGE: + // Hedge all Positions on Specified Conditions ... + + // + // Cleanup Collections ... + + // + Clean(ownPositions); + Clean(ownLongPositions); + Clean(ownShortPositions); + + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + ppBar.Clean(); + + // + Clean(visionPoiEvents); + Clean(analysePoiEvents); + Clean(visionCycleEvents); + Clean(decisionPoiEvents); + Clean(analyseCycleEvents); + Clean(decisionCycleEvents); + Clean(consolidationPoiEvents); + Clean(consolidationCycleEvents); + + // + visionState.Clean(); + analyseState.Clean(); + decisionState.Clean(); + visionConditions.Clean(); + analyseConditions.Clean(); + visionXConditions.Clean(); + decisionConditions.Clean(); + consolidationState.Clean(); + analyseXConditions.Clean(); + decisionXConditions.Clean(); + consolidationConditions.Clean(); + consolidationXConditions.Clean(); + + // + count = ArraySize(guards); + result = IsValidSize(count); + + // + return result; + } + + // + // Add Conditions to Conditions Collection ... + int AddConditionsIfNotExists( + int maxAllowed = 10 // + ) + { + // + int result = 0; + + // + bool isSetuped = IsValid(mConditions.setupTime) && + HasDirection(mConditions.dir); + if (!isSetuped) + { + return result; + } + + // + int count = ArraySize(mConditionsCollection); + if (IsValidSize(count)) + { + // + // Copy Original Items ... + X121SMCStrategyXWZSignalConditions tmpItems[]; + Copy( + mConditionsCollection, + tmpItems // + ); + + // + // Prese Item Data ... + bool isBullish = IsBullish(mConditions.dir); + + // + for (int i = 0; i < count; i++) + { + // + X121SMCStrategyXWZSignalConditions iItem = tmpItems[i]; + + // + bool canRemove = mConditions.dir == iItem.dir && + mConditions.pivot == iItem.pivot; + if (canRemove) + { + // + ArrayRemove( + mConditionsCollection, + i, + 1 // + ); + } + } + + // + Clean(tmpItems); + } + + // + AddRef( + mConditions, + mConditionsCollection // + ); + + // + // Remove Olds ... + CleanupArray( + mConditionsCollection, + maxAllowed // + ); + + // + result = ArraySize(mConditionsCollection); + + // + return result; + } + + // + bool DetectWorkingZone( + XPOIState <fState // + ) + { + // + bool result = false; + + // + result = IsValid(symbol) && + IsValid(period); + if (!result) + { + return result; + } + + // + result = !workingZone.IsValid(); + if (!result) + { + return result; + } + + // + workingZone.symbol = symbol; + workingZone.period = period; + + // + int idx = -1; + bool has = false; + + // + has = ltfState.HasSupplyZones(); + if (has) + { + // + idx = GetHighest(ltfState.supplyZones); + if (IsValidIndex(idx)) + { + workingZone.supplyZone = ltfState.supplyZones[idx]; + } + } + + // + has = ltfState.HasDemandZones(); + if (has) + { + // + idx = GetLowest(ltfState.demandZones); + if (IsValidIndex(idx)) + { + workingZone.demandZone = ltfState.demandZones[idx]; + } + } + + // + bool hasWorkingZone = workingZone.HasSupplyZone() && + workingZone.HasDemandZone(); + if (hasWorkingZone) + { + // + double upper = workingZone.supplyZone.Lower(); + double lower = workingZone.demandZone.Upper(); + + // + double delta = ((upper - lower) / 100) * 25; + + // + workingZone.quarter1 = upper - (1 * delta); + workingZone.quarter2 = upper - (2 * delta); + workingZone.quarter3 = upper - (3 * delta); + + // + hasWorkingZone = workingZone.IsValid(); + } + + // + result = hasWorkingZone; + + // + return result; + } + + // + // Draw Functions ... + // + + // + void RemoveDraws() + { + mObjects.Clear(); + } + + // + void DrawBar( + XOHCL &bar, + XCPOIDrawer *drawer, + bool forceClean = true // + ) + { + // + if (forceClean) + { + mBarObjects.Clear(); + } + + // + if (drawer == NULL || + !bar.IsValid()) + { + return; + } + + // + bool isBullish = bar.IsBullish(); + + // + int widthBar = 2; + bool fillShadowsBar = true; + ENUM_LINE_STYLE styleBar = STYLE_SOLID; + color clrBar = + isBullish + ? clrAqua + : clrMagenta; + + // + datetime to = bar.NextAt(); + + // + XCOHCLObject *iObj; + bool isCreated = drawer + .CreateBar( + bar, + iObj, + to // + ); + if (isCreated) + { + // + iObj.BarSpes( + widthBar, + clrBar, + styleBar // + ); + + // + iObj.LowShadowFill(fillShadowsBar); + iObj.HighShadowFill(fillShadowsBar); + + // + mBarObjects.Add(iObj); + } + } + + // + void DrawWorkingZone( + XCPOIDrawer *drawer, + bool drawTrendLine = true, + bool forceClean = false // + ) + { + // + if (drawer == NULL) + { + return; + } + + // + if (forceClean) + { + mWorkingZoneObjects.Clear(); + } + + // + int count = 0; + bool has = false; + bool isCreated = false; + + // + ulong chartID = drawer.ChartIdentification(); + int subWindow = drawer.SubWindowIdentification(); + color bullishColor = drawer.BarBullishColor(); + color bearishColor = drawer.BarBearishColor(); + + // + // Supply Zone ... + has = workingZone.HasSupplyZone(); + if (has) + { + // + XCSupplyZoneObject *iObj; + isCreated = drawer.CreateSupplyZone( + workingZone.supplyZone, + iObj // + ); + + // + if (isCreated) + { + mWorkingZoneObjects.Add(iObj); + } + } + + // + has = workingZone.HasSupplyZones(); + if (has) + { + // + count = workingZone.CountSupplyZones(); + for (int i = 0; i < count; i++) + { + // + XCSupplyZoneObject *iObj; + isCreated = drawer.CreateSupplyZone( + workingZone.supplyZones[i], + iObj // + ); + + // + if (isCreated) + { + mWorkingZoneObjects.Add(iObj); + } + } + } + + // + // Demand Zone ... + has = workingZone.HasDemandZone(); + if (has) + { + // + XCDemandZoneObject *iObj; + isCreated = drawer.CreateDemandZone( + workingZone.demandZone, + iObj // + ); + + // + if (isCreated) + { + mWorkingZoneObjects.Add(iObj); + } + } + + // + has = workingZone.HasDemandZones(); + if (has) + { + // + count = workingZone.CountDemandZones(); + for (int i = 0; i < count; i++) + { + // + XCDemandZoneObject *iObj; + isCreated = drawer.CreateDemandZone( + workingZone.demandZones[i], + iObj // + ); + + // + if (isCreated) + { + mWorkingZoneObjects.Add(iObj); + } + } + } + + // + // Quarters ... + has = workingZone.IsValid(); + if (has) + { + // + double zoneUpper = workingZone.supplyZone.Upper(); + double upper = workingZone.supplyZone.Lower(); + + // + double lower = workingZone.demandZone.Upper(); + double zoneLower = workingZone.demandZone.Lower(); + + // + string prefix = "X121WZone_" + workingZone.symbol + "_" + ToString(workingZone.period); + + // + // Zone Upper ... + CChartObjectHLine *zoneUpperLine; + zoneUpperLine = new CChartObjectHLine(); + isCreated = zoneUpperLine.Create( + chartID, + prefix + "_ZoneTop", + subWindow, + zoneUpper // + ); + if (isCreated) + { + // + zoneUpperLine.Color(clrRed); + + // + mWorkingZoneObjects.Add(zoneUpperLine); + } + + // + // Zone Lower ... + CChartObjectHLine *zoneLowerLine; + zoneLowerLine = new CChartObjectHLine(); + isCreated = zoneLowerLine.Create( + chartID, + prefix + "_ZoneDown", + subWindow, + zoneLower // + ); + if (isCreated) + { + // + zoneLowerLine.Color(clrRed); + + // + mWorkingZoneObjects.Add(zoneLowerLine); + } + + // + // Upper ... + CChartObjectHLine *upperLine; + upperLine = new CChartObjectHLine(); + isCreated = upperLine.Create( + chartID, + prefix + "_Upper", + subWindow, + upper // + ); + if (isCreated) + { + // + upperLine.Color(clrLime); + + // + mWorkingZoneObjects.Add(upperLine); + } + + // + // Lower ... + CChartObjectHLine *lowerLine; + lowerLine = new CChartObjectHLine(); + isCreated = lowerLine.Create( + chartID, + prefix + "_Lower", + subWindow, + lower // + ); + if (isCreated) + { + // + lowerLine.Color(clrLime); + + // + mWorkingZoneObjects.Add(lowerLine); + } + + // + // Quarters ... + + // + // Quarter 1 ... + CChartObjectHLine *q1Line; + q1Line = new CChartObjectHLine(); + isCreated = q1Line.Create( + chartID, + prefix + "_Q1", + subWindow, + workingZone.quarter1 // + ); + if (isCreated) + { + // + q1Line.Color(clrYellow); + + // + mWorkingZoneObjects.Add(q1Line); + } + + // + // Quarter 2 ... + CChartObjectHLine *q2Line; + q2Line = new CChartObjectHLine(); + isCreated = q2Line.Create( + chartID, + prefix + "_Q2", + subWindow, + workingZone.quarter2 // + ); + if (isCreated) + { + // + q2Line.Color(clrYellow); + + // + mWorkingZoneObjects.Add(q2Line); + } + + // + // Quarter 3 ... + CChartObjectHLine *q3Line; + q3Line = new CChartObjectHLine(); + isCreated = q3Line.Create( + chartID, + prefix + "_Q3", + subWindow, + workingZone.quarter3 // + ); + if (isCreated) + { + // + q3Line.Color(clrYellow); + + // + mWorkingZoneObjects.Add(q3Line); + } + } + + // + // Draw Order Flow ... + ENUM_X_DIRECTION trend; + has = workingZone.HasOrderFlow(trend); + if (has) + { + // + bool isBullish = IsBullish(trend); + + // + count = workingZone.CountOrderFlow(); + for (int i = 0; i < count; i++) + { + // + XOBFVG iOBFVG = workingZone.orderFlow[i]; + + // + XCBaseObject *drawnObjects[]; + int drawnObjectsCount = drawer + .DrawOBFVG( + // + iOBFVG, + drawnObjects, + // + true, // Draw Order Block ... + true, // Draw Fair Value Gap ... + false, // Draw Supply Zones ... + false, // Draw Demand Zones ... + false, // Draw Support Zones ... + false // Draw Resistance Zones ... + ); + if (IsValidSize(drawnObjectsCount)) + { + AddDrawnWorkingZoneObjects(drawnObjects); + } + } + + // + // Draw Trend Line ... + if (drawTrendLine) + { + // + XOBFVGPivot pivots[]; + count = workingZone.GetSwings(pivots); + has = count >= 2; + if (has) + { + // + // Get Max / Min ... + double max = 0; + double min = 0; + datetime maxAt = NULL; + datetime minAt = NULL; + for (int i = 0; i < count; i++) + { + // + XOBFVGPivot iPivot = pivots[i]; + + // + if (!iPivot.IsValid()) + { + // + iPivot.Clean(); + continue; + } + + // + // Min ... + bool canSetMin = + min == 0 + ? true + : min > iPivot.value; + if (canSetMin) + { + // + minAt = iPivot.at; + min = iPivot.value; + } + + // + // Max ... + bool canSetMax = + max == 0 + ? true + : max < iPivot.value; + if (canSetMax) + { + // + maxAt = iPivot.at; + max = iPivot.value; + } + + // + iPivot.Clean(); + } + + // + double price1 = + isBullish + ? min + : max; + double price2 = + isBullish + ? max + : min; + datetime time1 = + isBullish + ? minAt + : maxAt; + datetime time2 = + isBullish + ? maxAt + : minAt; + + // + color clrTrend = + isBullish + ? bullishColor + : bearishColor; + + // + string trendName = + ToString(trend) + "_" + "XTRNDL_" + + ToString(period) + "_" + + ToString(price1) + "_" + + ToString(price2) + "_"; + // + ToMD5(ToString(time1)); + + // + CChartObjectTrend *mTrend; + mTrend = new CChartObjectTrend(); + isCreated = mTrend.Create( + chartID, + trendName, + subWindow, + time1, + price1, + time2, + price2 // + ); + + // + if (isCreated) + { + // + mTrend.Width(2); + mTrend.Color(clrTrend); + mTrend.RayRight(true); + + // + mWorkingZoneObjects.Add(mTrend); + } + } + } + + // + // Draw Target Zone ... + has = targetZone.IsValid(); + if (has) + { + // + XCBaseObject *drawnObjects[]; + int drawnObjectsCount = drawer + .DrawOBFVG( + // + targetZone, + drawnObjects, + // + true, // Draw Order Block ... + true, // Draw Fair Value Gap ... + false, // Draw Supply Zones ... + false, // Draw Demand Zones ... + false, // Draw Support Zones ... + false // Draw Resistance Zones ... + ); + if (IsValidSize(drawnObjectsCount)) + { + AddDrawnWorkingZoneObjects(drawnObjects); + } + } + } + + // + } + + // + void DrawConditions( + X121SMCStrategyXWZSignalConditions &conditions, + XCPOIDrawer *drawer, + bool forceClean = false // + ) + { + // + if (drawer == NULL) + { + return; + } + + // + if (forceClean) + { + mObjects.Clear(); + } + + // + bool hasSignalZone = conditions.signalZone.IsValid(); + if (hasSignalZone) + { + // + XCBaseObject *iObjects[]; + int iObjectsCount = drawer.DrawOBFVG( + conditions.signalZone, + iObjects // + ); + AddDrawnObjects(iObjects); + } + } + + // + protected: + // + + // + private: + // + // Props ... + string symbol; + ENUM_TIMEFRAMES period; + CArrayObj mObjects; + CArrayObj mBarObjects; + CArrayObj mWorkingZoneObjects; + + /** + * Initialize ... + */ + void Init() + { + } + + /** + * DeInitialize ... + */ + void DeInit() + { + // + chochZone.Clean(); + signalZone.Clean(); + targetZone.Clean(); + mConditions.Clean(); + workingZone.Clean(); + Clean(mConditionsCollection); + + // + mObjects.Clear(); + mBarObjects.Clear(); + mWorkingZoneObjects.Clear(); + } + + /** + * Update To Time of Exists Components ... + * + * @param value: updated time ... + */ + void UpdateTo( + datetime value = NULL // + ) + { + // + value = NormalizeTime(value); + + // + chochZone.UpdateTo(value); + targetZone.UpdateTo(value); + signalZone.UpdateTo(value); + workingZone.UpdateTo(value); + mConditions.UpdateTo(value); + waitingZone.UpdateTo(value); + } + + // + // Helpers ... + + // + bool CalculateRiskReward( + ENUM_X121SMC_XWZ_PRIORITY priority, + double &reward, + double &amountPercent // + ) + { + // + bool result = false; + + // + reward = 0; + amountPercent = 0; + + // + result = priority != X121SMC_XWZ_PRIORITY_NONE; + if (!result) + { + return result; + } + + // + switch (priority) + { + // + case X121SMC_XWZ_PRIORITY_STRONG_HIGH: + // + reward = 6; + amountPercent = 2; + break; + + // + case X121SMC_XWZ_PRIORITY_HIGH: + // + reward = 4; + amountPercent = 2; + break; + + // + case X121SMC_XWZ_PRIORITY_REGULAR: + // + reward = 3; + amountPercent = 1.5; + break; + + // + case X121SMC_XWZ_PRIORITY_LOW: + // + reward = 2; + amountPercent = 1; + break; + + // + case X121SMC_XWZ_PRIORITY_WEAK: + // + reward = 1; + amountPercent = 0.5; + break; + } + + // + result = + // + reward > 0 && + amountPercent > 0 + // + ; + + // + return result; + } + + // + void AddDrawnObjects(XCBaseObject *&objects[]) + { + // + int count = ArraySize(objects); + bool has = IsValidSize(count); + if (!has) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + mObjects.Add(objects[i]); + } + } + + // + void AddDrawnWorkingZoneObjects(XCBaseObject *&objects[]) + { + // + int count = ArraySize(objects); + bool has = IsValidSize(count); + if (!has) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + mWorkingZoneObjects.Add(objects[i]); + } + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14031218/Documents/BKP/x-121.smc.xwz.signal.lib copy 2.mq5 b/BKPS/14031218/Documents/BKP/x-121.smc.xwz.signal.lib copy 2.mq5 new file mode 100644 index 0000000..8aa5b9c --- /dev/null +++ b/BKPS/14031218/Documents/BKP/x-121.smc.xwz.signal.lib copy 2.mq5 @@ -0,0 +1,3189 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 X121 SMC Signal Class +// ------------------------------------------------- +// Name: XWZ +// 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 "../../Libraries/x-trade.lib" +#include "../Classes/x-121.smc.market.cycle.helper.class.mq5" +#include "../Libraries/x-121.smc.guard.lib.mq5" +#include "../Libraries/x-121.smc.lib.mq5" + +// +enum ENUM_X121SMC_XWZ_PROVIDERS +{ + X121SMC_XWZ_PROVIDER_NONE, + X121SMC_XWZ_PROVIDER_PV_ZONE, + X121SMC_XWZ_PROVIDER_ACTIVATED_ZONE, + X121SMC_XWZ_PROVIDER_ACTIVATED_CHOCH, + X121SMC_XWZ_PROVIDER_PRICE_INSIDE_ZONE, +}; + +// +enum ENUM_X121SMC_XWZ_PRIORITY +{ + X121SMC_XWZ_PRIORITY_NONE, + X121SMC_XWZ_PRIORITY_WEAK, + X121SMC_XWZ_PRIORITY_LOW, + X121SMC_XWZ_PRIORITY_REGULAR, + X121SMC_XWZ_PRIORITY_HIGH, + X121SMC_XWZ_PRIORITY_STRONG_HIGH, +}; + +// +// Definitions ... + +// +struct X121SMCStrategyXWZWorkingZone +{ + // + // Props ... + + // + string symbol; + ENUM_TIMEFRAMES period; + + // + double quarter1; + double quarter2; + double quarter3; + + // + XCSupplyZone *supplyZone; + XCDemandZone *demandZone; + + // + XCSupplyZone *supplyZones[]; + XCDemandZone *demandZones[]; + + // + XCSupportZone *supportZones[]; + XCResistanceZone *resistanceZones[]; + + // + XBoxZone insideBoxes[]; + XBoxZone breakedBoxes[]; + XBoxZone waitingBoxes[]; + XBoxZone breakedInsideBoxes[]; + XConsolidationZone consolidationZones[]; + + // + CArrayObj mInsideZoneObjects; + CArrayObj mBreakedZoneObjects; + CArrayObj mWaitingZoneObjects; + CArrayObj mWorkingZoneObjects; + CArrayObj mBreakedInsideZoneObjects; + + // + bool mUseSupDems; + bool mUseOrderBlocks; + bool mUseFairValueGaps; + + // + // Constructor ... + X121SMCStrategyXWZWorkingZone() + { + Clean(); + } + + // + // Tools ... + + // + void Clean() + { + // + quarter1 = 0; + quarter2 = 0; + quarter3 = 0; + + // + symbol = NULL; + period = NULL; + + // + Clean(supplyZones); + Clean(demandZones); + + // + Clean(insideBoxes); + Clean(breakedBoxes); + Clean(waitingBoxes); + + // + Clean(supportZones); + Clean(resistanceZones); + + // + ZeroMemory(supplyZone); + ZeroMemory(demandZone); + + // + mInsideZoneObjects.Clear(); + mBreakedZoneObjects.Clear(); + mWaitingZoneObjects.Clear(); + mWorkingZoneObjects.Clear(); + mBreakedInsideZoneObjects.Clear(); + + // + mUseSupDems = false; + mUseOrderBlocks = true; + mUseFairValueGaps = true; + } + + // + bool IsValid() + { + // + bool result = false; + + // + result = + // + quarter1 > 0 && + quarter2 > 0 && + quarter3 > 0 && + HasSupplyZone() && + HasDemandZone() && + quarter1 > quarter2 && + quarter2 > quarter3 + // + ; + + // + return result; + } + + // + bool Init( + string _symbol, + ENUM_TIMEFRAMES _period, + int barIndex, + XPOIState &htfState, + XPOIState &mtfState, + XPOIState &stfState, // + XPOIState &ttfState // + ) + { + // + bool result = false; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + result = + // + IsValid(_symbol) && + IsValid(_period) && + // + htfState.IsValid() && + mtfState.IsValid() && + stfState.IsValid() && + ttfState.IsValid() && + // + htfState.HasChild() && + mtfState.HasChild() && + stfState.HasChild() && + ttfState.HasChild() + // + ; + if (!result) + { + return result; + } + + // + symbol = _symbol; + period = _period; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + XOHCL zBar; + has = zBar.Init( + symbol, + period, + barIndex // + ); + result = has; + if (!result) + { + zBar.Clean(); + return result; + } + double ll5 = zBar.FindLowest(5, MODE_LOW); + double hh5 = zBar.FindHighest(5, MODE_HIGH); + zBar.Clean(); + + // + // Supply Zone ... + has = HasSupplyZone(); + if (!has) + { + // + idx = GetHighest(mtfState.supplyZones); + has = IsValidIndex(idx); + if (has) + { + // + supplyZone = mtfState.supplyZones[idx]; + has = hh5 < supplyZone.Lower(); + if (!has) + { + supplyZone = NULL; + } + } + } + + // + // Demand Zone ... + has = HasDemandZone(); + if (!has) + { + // + idx = GetLowest(mtfState.demandZones); + has = IsValidIndex(idx); + if (has) + { + // + demandZone = mtfState.demandZones[idx]; + has = ll5 > demandZone.Upper(); + if (!has) + { + demandZone = NULL; + } + } + } + + // + // + // + + // // + // // Supply Zones ... + // has = HasSupplyZones(); + // if (!has) + // { + // // + // count = mtfState.FilterSupplyZones( + // supplyZones, + // period, + // XZONE_STATE_PASSED, + // false, + // XZONE_STATE_FAILED, + // false, + // XZONE_STATE_FAILED, + // false, + // XZONE_STATE_IGNORED, + // false // + // ); + // } + + // // + // // Demand Zones ... + // has = HasDemandZones(); + // if (!has) + // { + // // + // count = mtfState.FilterDemandZones( + // demandZones, + // period, + // XZONE_STATE_PASSED, + // false, + // XZONE_STATE_FAILED, + // false, + // XZONE_STATE_FAILED, + // false, + // XZONE_STATE_IGNORED, + // false // + // ); + // } + + // + // Support Zones ... + // has = HasSupportZones(); + // if (!has) + // { + // // + // count = mtfState.FilterSupportZones( + // supportZones, + // period, + // XZONE_STATE_PASSED, + // false, + // XZONE_STATE_FAILED, + // false, + // XZONE_STATE_FAILED, + // false, + // XZONE_STATE_IGNORED, + // false // + // ); + // } + + // + // Resistance Zones ... + // has = HasResistanceZones(); + // if (!has) + // { + // // + // count = mtfState.FilterResistanceZones( + // resistanceZones, + // period, + // XZONE_STATE_PASSED, + // false, + // XZONE_STATE_FAILED, + // false, + // XZONE_STATE_FAILED, + // false, + // XZONE_STATE_IGNORED, + // false // + // ); + // } + + // + has = ttfState.HasConsolidationZones(); + if (has) + { + // + Copy( + ttfState.consolidationZones, + consolidationZones // + ); + CleanupArray( + consolidationZones, + 50 // + ); + } + + // + if (supplyZone != NULL && + demandZone != NULL && + supplyZone.IsValid() && + demandZone.IsValid()) + { + // + double upper = supplyZone.Lower(); + double lower = demandZone.Upper(); + + // + double delta = ((upper - lower) / 100) * 25; + + // + quarter1 = upper - (1 * delta); + quarter2 = upper - (2 * delta); + quarter3 = upper - (3 * delta); + } + + // + // Waiting Zone Detection ... + // XPOIState iState = mtfState; + + // + // Detect Waiting Zones ... + + // // + // // Using Order Blocks ... + // if (mUseOrderBlocks) + // { + // // + // has = iState.HasOrderBlocks(); + // if (has) + // { + // // + // XCOrderBlock *obs[]; + // count = iState.FilterOrderBlocks( + // obs, + // period, + // XZONE_STATE_PASSED, + // false, + // XZONE_STATE_FAILED, + // false, + // XZONE_STATE_FAILED, + // false, + // XZONE_STATE_IGNORED, + // false // + // ); + + // // + // has = IsValidSize(count); + // if (has) + // { + // // + // ToBox( + // obs, + // waitingBoxes // + // ); + // } + + // // + // Clean(obs); + // } + // } + + // // + // // Using Fair Value Gaps ... + // if (mUseFairValueGaps) + // { + // // + // has = iState.HasFairValueGaps(); + // if (has) + // { + // // + // XBoxZone boxes[]; + // XCFVG *fvgs[]; + // count = iState.FilterFairValueGaps( + // fvgs, + // period, + // XZONE_STATE_PASSED, + // false, + // XZONE_STATE_FAILED, + // false, + // XZONE_STATE_FAILED, + // false, + // XZONE_STATE_IGNORED, + // false // + // ); + + // // + // has = IsValidSize(count); + // if (has) + // { + // // + // count = ToBox( + // fvgs, + // boxes // + // ); + + // // + // for (int i = 0; i < count; i++) + // { + // // + // XBoxZone iBox = boxes[i]; + + // // + // int idx = FindIndex( + // iBox, + // waitingBoxes // + // ); + // has = !IsValidIndex(idx); + // if (has) + // { + // // + // AddRef( + // iBox, + // waitingBoxes // + // ); + // } + + // // + // iBox.Clean(); + // } + // } + + // // + // Clean(fvgs); + // Clean(boxes); + // } + // } + + // + // Cleaning State ... + // iState.Clean(); + + // + result = IsValid(); + if (!result) + { + Clean(); + } + + // + return result; + } + + // + void Update( + int barIndex, + XPOIState &htfState, + XPOIState &mtfState, + XPOIState &stfState, + XPOIState &ttfState // + ) + { + // + int idx = -1; + int count = 0; + bool has = false; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + has = + // + IsValid() && + // + htfState.IsValid() && + mtfState.IsValid() && + stfState.IsValid() && + // + htfState.HasChild() && + mtfState.HasChild() && + stfState.HasChild() + // + ; + if (!has) + { + return; + } + + // + XOHCL zBar; + has = zBar.Init( + symbol, + period, + barIndex // + ); + if (!has) + { + // + zBar.Clean(); + return; + } + + // + XOHCL cBar; + has = zBar.GetPreviousBar(cBar); + if (!has) + { + // + zBar.Clean(); + cBar.Clean(); + + // + return; + } + + // + // Update Exists Zones ... + + // + // Supply Zones ... + has = mtfState.HasSupplyZones(); + if (has) + { + // + XCSupplyZone *zone; + idx = GetYoungest(mtfState.supplyZones); + has = IsValidIndex(idx); + if (has) + { + // + zone = mtfState.supplyZones[idx]; + has = IsSupplyExists(zone); + if (!has) + { + // + Add( + zone, + supplyZones // + ); + } + else + { + ZeroMemory(zone); + } + } + } + + // + // Demand Zones ... + has = mtfState.HasDemandZones(); + if (has) + { + // + XCDemandZone *zone; + idx = GetYoungest(mtfState.demandZones); + has = IsValidIndex(idx); + if (has) + { + // + zone = mtfState.demandZones[idx]; + has = IsDemandExists(zone); + if (!has) + { + // + Add( + zone, + demandZones // + ); + } + else + { + ZeroMemory(zone); + } + } + } + + // + // + // + + // + // Supply Zones ... + has = HasSupplyZones(); + if (has) + { + // + int removeIDXs[]; + count = CountSupplyZones(); + for (int i = 0; i < count; i++) + { + // + XCSupplyZone *iZone = supplyZones[i]; + ENUM_X_DIRECTION iDir = X_DIRECTION_BEARISH; + + // + XBoxZone iBox; + bool hasBox = ToBox( + iBox, + iZone // + ); + if (!hasBox) + { + // + iBox.Clean(); + continue; + } + + // + XOHCL passedBar; + bool isBodyIn = false; + bool isBodyOut = false; + + // + // Check Activation ... + bool isActivated = iZone.IsActivated( + iDir, + passedBar, + isBodyIn, + true, + period // + ); + if (isActivated) + { + // + // AddRef( + // iBox, + // insideBoxes // + // ); + + // + Add( + i, + removeIDXs // + ); + + // + iBox.Clean(); + passedBar.Clean(); + continue; + } + + // + // Checking Breaked ... + bool isBreaked = iZone.IsBreaked( + iDir, + passedBar, + isBodyOut, + false, + true, + period // + ); + if (isBreaked) + { + // // + // AddRef( + // iBox, + // breakedBoxes // + // ); + + // + Add( + i, + removeIDXs // + ); + + // + iBox.Clean(); + passedBar.Clean(); + continue; + } + + // + passedBar.Clean(); + } + + // + count = ArraySize(removeIDXs); + has = IsValidSize(count); + if (has) + { + // + CleanupArray( + removeIDXs, + supplyZones // + ); + } + + // + Clean(removeIDXs); + } + + // + // Demand Zones ... + has = HasDemandZones(); + if (has) + { + // + int removeIDXs[]; + count = CountDemandZones(); + for (int i = 0; i < count; i++) + { + // + XCDemandZone *iZone = demandZones[i]; + ENUM_X_DIRECTION iDir = X_DIRECTION_BULLISH; + + // + XBoxZone iBox; + bool hasBox = ToBox( + iBox, + iZone // + ); + if (!hasBox) + { + // + iBox.Clean(); + continue; + } + + // + XOHCL passedBar; + bool isBodyIn = false; + bool isBodyOut = false; + + // + // Check Activation ... + bool isActivated = iZone.IsActivated( + iDir, + passedBar, + isBodyIn, + true, + period // + ); + if (isActivated) + { + // + // AddRef( + // iBox, + // insideBoxes // + // ); + + // + Add( + i, + removeIDXs // + ); + + // + iBox.Clean(); + passedBar.Clean(); + continue; + } + + // + // Checking Breaked ... + bool isBreaked = iZone.IsBreaked( + iDir, + passedBar, + isBodyOut, + false, + true, + period // + ); + if (isBreaked) + { + // // + // AddRef( + // iBox, + // breakedBoxes // + // ); + + // + Add( + i, + removeIDXs // + ); + + // + iBox.Clean(); + passedBar.Clean(); + continue; + } + + // + passedBar.Clean(); + } + + // + count = ArraySize(removeIDXs); + has = IsValidSize(count); + if (has) + { + // + CleanupArray( + removeIDXs, + demandZones // + ); + } + + // + Clean(removeIDXs); + } + + // + // Update Boxes ... + + // + // Waiting Boxes ... + has = HasWaitingBoxes(); + if (has) + { + // + int removeIDXs[]; + count = CountWaitingBoxes(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = waitingBoxes[i]; + ENUM_X_DIRECTION iDir = iBox.dir; + bool isBullish = IsBullish(iDir); + + // + bool isInside = + // + zBar.low < iBox.upper && + zBar.low > iBox.lower + // + ; + if (isInside) + { + // + AddRef( + iBox, + insideBoxes // + ); + + // + Add( + i, + removeIDXs // + ); + + // + iBox.Clean(); + break; + } + + // + bool isBreakedUpper = + // + cBar.low < iBox.upper && + cBar.low > iBox.lower && + zBar.low > iBox.upper + // + ; + + // + bool isBreakedLower = + // + cBar.high > iBox.lower && + cBar.high < iBox.upper && + zBar.high < iBox.lower + // + ; + + // + bool isBreaked = + (isBullish && + isBreakedLower) || + (!isBullish && + isBreakedUpper); + + // + if (isBreaked) + { + // + AddRef( + iBox, + breakedBoxes // + ); + + // + Add( + i, + removeIDXs // + ); + + // + iBox.Clean(); + break; + } + } + + // + count = ArraySize(removeIDXs); + has = IsValidSize(count); + if (has) + { + // + CleanupArray( + removeIDXs, + waitingBoxes // + ); + } + + // + Clean(removeIDXs); + } + + // + // Inside Boxes ... + has = HasInsideBoxes(); + if (has) + { + // + int removeIDXs[]; + count = CountInsideBoxes(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = insideBoxes[i]; + ENUM_X_DIRECTION iDir = iBox.dir; + bool isBullish = IsBullish(iDir); + + // + bool isBreakedUpper = + // + cBar.low < iBox.upper && + cBar.low > iBox.lower && + zBar.low > iBox.upper + // + ; + + // + bool isBreakedLower = + // + cBar.high > iBox.lower && + cBar.high < iBox.upper && + zBar.high < iBox.lower + // + ; + + // + bool isBreaked = + (isBullish && + isBreakedLower) || + (!isBullish && + isBreakedUpper); + + // + if (isBreaked) + { + // + AddRef( + iBox, + breakedBoxes // + ); + + // + Add( + i, + removeIDXs // + ); + + // + iBox.Clean(); + break; + } + } + + // + count = ArraySize(removeIDXs); + has = IsValidSize(count); + if (has) + { + // + CleanupArray( + removeIDXs, + insideBoxes // + ); + } + + // + Clean(removeIDXs); + } + + // + has = HasBreakedBoxes(); + if (has) + { + // + int removeIDXs[]; + count = CountBreakedBoxes(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = breakedBoxes[i]; + ENUM_X_DIRECTION iDir = iBox.dir; + bool isBullish = IsBullish(iDir); + + // + bool isInside = false; + + // + if (isInside) + { + // + AddRef( + iBox, + breakedInsideBoxes // + ); + + // + Add( + i, + removeIDXs // + ); + + // + iBox.Clean(); + break; + } + } + + // + count = ArraySize(removeIDXs); + has = IsValidSize(count); + if (has) + { + // + CleanupArray( + removeIDXs, + breakedBoxes // + ); + } + + // + Clean(removeIDXs); + } + + // + // Update Waiting Boxes ... + + // + XPOIState iState = mtfState; + + // + // Use Order Blocks ... + if (mUseOrderBlocks) + { + // + has = iState.HasOrderBlocks(); + if (has) + { + // + XCOrderBlock *obs[]; + count = iState.FilterOrderBlocks( + obs, + period, + XZONE_STATE_PASSED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_IGNORED, + false // + ); + + // + has = IsValidSize(count); + if (has) + { + // + // Try to Add new OBs into Waiting Zones ... + // if it's not exists ... + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + bool hasBox = ToBox( + iBox, + obs[i] // + ); + if (!hasBox) + { + // + iBox.Clean(); + continue; + } + + // + // Check Index in Waiting Boxes ... + idx = FindIndex( + iBox, + waitingBoxes // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + // Check Index in Inside Boxes ... + idx = FindIndex( + iBox, + insideBoxes // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + // Check Index in Breaked Boxes ... + idx = FindIndex( + iBox, + breakedBoxes // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + AddRef( + iBox, + waitingBoxes // + ); + } + } + + // + Clean(obs); + } + } + + // + // Use Fair Value Gaps ... + if (mUseFairValueGaps) + { + // + has = iState.HasFairValueGaps(); + if (has) + { + // + XCFVG *fvgs[]; + count = iState.FilterFairValueGaps( + fvgs, + period, + XZONE_STATE_PASSED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_IGNORED, + false // + ); + + // + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + bool hasBox = ToBox( + iBox, + fvgs[i] // + ); + if (!hasBox) + { + // + iBox.Clean(); + continue; + } + + // + // Check Index in Waiting Boxes ... + idx = FindIndex( + iBox, + waitingBoxes // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + // Check Index in Inside Boxes ... + idx = FindIndex( + iBox, + insideBoxes // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + // Check Index in Breaked Boxes ... + idx = FindIndex( + iBox, + breakedBoxes // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + AddRef( + iBox, + waitingBoxes // + ); + + // + iBox.Clean(); + } + } + + // + Clean(fvgs); + } + } + + // + iState.Clean(); + + // + // Cleanup Resource ... + + // + zBar.Clean(); + cBar.Clean(); + } + + // + bool IsDestroyed( + int barIndex = 0, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init( + symbol, + period, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + XOHCL cBar; + result = bar.GetPreviousBar(cBar); + if (!result) + { + // + bar.Clean(); + cBar.Clean(); + + // + return result; + } + + // + bool isSupplyZoneBreaked = + // + bar.low > supplyZone.Upper() && + cBar.low > supplyZone.Upper() + // + ; + + // + bool isDemandZoneBreaked = + // + bar.high < demandZone.Lower() && + cBar.high < demandZone.Lower() + // + ; + + // + bar.Clean(); + cBar.Clean(); + + // + result = isSupplyZoneBreaked || + isDemandZoneBreaked; + + // + return result; + } + + // + bool DetectPriority( + ENUM_X121SMC_XWZ_PRIORITY &priority, + ENUM_X_DIRECTION forDir, + int barIndex = 0, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + priority = X121SMC_XWZ_PRIORITY_NONE; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + result = IsValid() && + HasDirection(forDir); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + XOHCL bar; + result = bar.Init( + symbol, + forPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + if (bar.high < supplyZone.Upper() && + bar.low > supplyZone.Lower()) + { + // + priority = + isBullish + ? X121SMC_XWZ_PRIORITY_NONE + : X121SMC_XWZ_PRIORITY_STRONG_HIGH; + } + else if (bar.high < supplyZone.Lower() && + bar.low > quarter1) + { + // + priority = + isBullish + ? X121SMC_XWZ_PRIORITY_WEAK + : X121SMC_XWZ_PRIORITY_HIGH; + } + else if (bar.high < quarter1 && + bar.low > quarter2) + { + // + priority = + isBullish + ? X121SMC_XWZ_PRIORITY_LOW + : X121SMC_XWZ_PRIORITY_REGULAR; + } + else if (bar.high < quarter2 && + bar.low > quarter3) + { + // + priority = + isBullish + ? X121SMC_XWZ_PRIORITY_REGULAR + : X121SMC_XWZ_PRIORITY_LOW; + } + else if (bar.high < quarter3 && + bar.low > demandZone.Upper()) + { + // + priority = + isBullish + ? X121SMC_XWZ_PRIORITY_HIGH + : X121SMC_XWZ_PRIORITY_WEAK; + } + else if (bar.high < demandZone.Upper() && + bar.low > demandZone.Lower()) + { + // + priority = + isBullish + ? X121SMC_XWZ_PRIORITY_STRONG_HIGH + : X121SMC_XWZ_PRIORITY_NONE; + } + + // + result = priority != X121SMC_XWZ_PRIORITY_NONE && + priority != X121SMC_XWZ_PRIORITY_WEAK; + + // + bar.Clean(); + + // + return result; + } + + // + bool DetectSenarioASignalBox( + XBoxZone &signalBox, + ENUM_X_DIRECTION &signalDir, + X121Conditions &decisionXConditions, + X121Conditions &analyseXConditions, + XC121SMCCycleHelper *decisionCycleHelper, + XCPOIDrawer *drawer = NULL, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + signalBox.Clean(); + signalDir = X_DIRECTION_NONE; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + result = decisionCycleHelper != NULL; + if (!result) + { + return result; + } + + // + // Decision ... + double decisionBullishScore = 0; + double decisionBearishScore = 0; + decisionXConditions.GenerateScore( + decisionBullishScore, + decisionBearishScore // + ); + + // + // Analyse ... + double analyseBullishScore = 0; + double analyseBearishScore = 0; + analyseXConditions.GenerateScore( + analyseBullishScore, + analyseBearishScore // + ); + + // + // Score Conditions ... + double scoreMultiplier = 3; + bool isBullishScorePassed = + // + analyseBullishScore > (analyseBearishScore * scoreMultiplier) && + decisionBullishScore > (decisionBearishScore * scoreMultiplier) + // + ; + bool isBearishScorePassed = + // + analyseBearishScore > (analyseBullishScore * scoreMultiplier) && + decisionBearishScore > (decisionBullishScore * scoreMultiplier) + // + ; + + // + // Checking Other Conditions + + // + bool isCommonBullish = + // + decisionXConditions.isSarBullish && + decisionXConditions.isStrBullish && + decisionXConditions.isCheBullish && + decisionXConditions.isSMHKBullish && + decisionXConditions.isRawHKBullish && + decisionXConditions.isRawHKClosedOverSMHK + // + ; + + // + bool isCommonBearish = + // + decisionXConditions.isSarBearish && + decisionXConditions.isStrBearish && + decisionXConditions.isCheBearish && + decisionXConditions.isSMHKBearish && + decisionXConditions.isRawHKBearish && + decisionXConditions.isRawHKClosedUnderSMHK + // + ; + + // + // X3Ma ... + + // + // X3Ma Bullish ... + bool isX3MaBullish = + // + decisionXConditions.isX3MaBullishState && + decisionXConditions.isX3MaSwitchedToBullishOrdered && + decisionXConditions.x3maMidBuffer[1] > decisionXConditions.x3maSlowBuffer[1] + // + ; + + // + // X3Ma Bearish ... + bool isX3MaBearish = + // + decisionXConditions.isX3MaBearishState && + decisionXConditions.isX3MaSwitchedToBearishOrdered && + decisionXConditions.x3maMidBuffer[1] < decisionXConditions.x3maSlowBuffer[1] + // + ; + + // + bool isX3MaHasCondition = + (isX3MaBullish && + isCommonBullish && + isBullishScorePassed) || + (isX3MaBearish && + isCommonBearish && + isBearishScorePassed); + + // + // VWap ... + + // + // VWap Bullish ... + bool isVWapBullish = + // + decisionXConditions.isVWapBullishState && + decisionXConditions.isVWapSwitchedToBullishOrdered && + decisionXConditions.vwapMidBuffer[1] > decisionXConditions.vwapSlowBuffer[1] + // + ; + + // + // VWap Bearish ... + bool isVWapBearish = + // + decisionXConditions.isVWapBearishState && + decisionXConditions.isVWapSwitchedToBearishOrdered && + decisionXConditions.vwapMidBuffer[1] < decisionXConditions.vwapSlowBuffer[1] + // + ; + + // + bool isVWapHasCondition = + (isVWapBullish && + isBullishScorePassed) || + (isVWapBearish && + isBearishScorePassed); + + // + // Senario .... + // - a vale Under X3MA Slow when X3MA Bullish Ordered ... + + // + bool isX3MASenarioBBullish = + // + decisionXConditions.isX3MaBullishOrdered && + decisionXConditions.valesBuffer[1] < decisionXConditions.x3maSlowBuffer[1] && + decisionXConditions.valesBuffer[2] >= decisionXConditions.x3maSlowBuffer[2] + // + ; + if (isX3MASenarioBBullish) + { + } + + // + bool isX3MASenarioBBearish = + // + decisionXConditions.isX3MaBearishOrdered && + decisionXConditions.peaksBuffer[1] > decisionXConditions.x3maSlowBuffer[1] && + decisionXConditions.peaksBuffer[2] <= decisionXConditions.x3maSlowBuffer[2] + // + ; + if (isX3MASenarioBBearish) + { + } + + // + // Checking Other Conditions XWZ Reject on EMA 20 ... + + // + // Check Has Conditions ... + bool hasXConditions = + (isX3MaHasCondition || + isVWapHasCondition); + + // + result = hasXConditions; + if (!result) + { + return result; + } + + // + if (isX3MaHasCondition) + { + // + signalDir = + isX3MaBullish + ? X_DIRECTION_BULLISH + : isX3MaBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + } + + // + if (isVWapHasCondition) + { + // + signalDir = + isVWapBullish + ? X_DIRECTION_BULLISH + : isVWapBearish + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + } + + // + // Creating SignalBox ... + + // + // Detect Box based on PV ... + bool hasSignalBox = decisionCycleHelper.GeneratePVBox( + signalBox, + barIndex // + ); + + // + result = + hasSignalBox && + signalDir == signalBox.dir; + + // + if (result) + { + // + XCBoxObject *iObj; + bool isCreated = drawer.DrawBox( + signalBox, + iObj // + ); + if (isCreated) + { + // + iObj.BoxWidth(1); + iObj.BoxColor(clrYellow); + iObj.BoxStyle(STYLE_SOLID); + } + + // + Print("Senario A ..."); + } + + // + return result; + } + + // + bool DetetctSenarioBSignalBox( + XBoxZone &signalBox, + ENUM_X_DIRECTION &signalDir, + X121Conditions &decisionXConditions, + X121Conditions &analyseXConditions, + XC121SMCCycleHelper *decisionCycleHelper, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + signalBox.Clean(); + signalDir = X_DIRECTION_NONE; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + result = decisionCycleHelper != NULL; + if (!result) + { + return result; + } + + // + // Decision ... + double decisionBullishScore = 0; + double decisionBearishScore = 0; + decisionXConditions.GenerateScore( + decisionBullishScore, + decisionBearishScore // + ); + + // + // Analyse ... + double analyseBullishScore = 0; + double analyseBearishScore = 0; + analyseXConditions.GenerateScore( + analyseBullishScore, + analyseBearishScore // + ); + + // + // Score Conditions ... + double scoreMultiplier = 3; + bool isBullishScorePassed = + // + analyseBullishScore > (analyseBearishScore * scoreMultiplier) && + decisionBullishScore > (decisionBearishScore * scoreMultiplier) + // + ; + bool isBearishScorePassed = + // + analyseBearishScore > (analyseBullishScore * scoreMultiplier) && + decisionBearishScore > (decisionBullishScore * scoreMultiplier) + // + ; + + // + // Senario .... + // - a vale Under X3MA Slow when X3MA Bullish Ordered ... + + // + bool isX3MASenarioBBullish = + // + decisionXConditions.isX3MaBullishOrdered && + decisionXConditions.valesBuffer[1] < decisionXConditions.x3maSlowBuffer[1] && + decisionXConditions.valesBuffer[2] >= decisionXConditions.x3maSlowBuffer[2] + // + ; + if (isX3MASenarioBBullish) + { + } + + // + bool isX3MASenarioBBearish = + // + decisionXConditions.isX3MaBearishOrdered && + decisionXConditions.peaksBuffer[1] > decisionXConditions.x3maSlowBuffer[1] && + decisionXConditions.peaksBuffer[2] <= decisionXConditions.x3maSlowBuffer[2] + // + ; + if (isX3MASenarioBBearish) + { + } + + // + return result; + } + + // + bool DetectOveralDirection( + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + result = IsValid() && + HasSupplyZone() && + HasDemandZone(); + if (!result) + { + return result; + } + + // + XBoxZone demBox; + XBoxZone supBox; + result = ToBox( + demBox, + demandZone // + ); + if (!result) + { + // + supBox.Clean(); + demBox.Clean(); + + // + return result; + } + result = ToBox( + supBox, + supplyZone // + ); + if (!result) + { + // + supBox.Clean(); + demBox.Clean(); + + // + return result; + } + + // + XOHCL supPriceOutBar; + XOHCL demPriceOutBar; + result = DetectBoxNearestPriceOut( + supBox, + supPriceOutBar, + period // + ); + if (!result) + { + // + demBox.Clean(); + supBox.Clean(); + supPriceOutBar.Clean(); + demPriceOutBar.Clean(); + + // + return result; + } + result = DetectBoxNearestPriceOut( + demBox, + demPriceOutBar, + period // + ); + if (!result) + { + // + demBox.Clean(); + supBox.Clean(); + supPriceOutBar.Clean(); + demPriceOutBar.Clean(); + + // + return result; + } + + // + // Specified Direction ... + dir = + (supPriceOutBar.IsValid() && + demPriceOutBar.IsValid()) + ? supPriceOutBar.time > demPriceOutBar.time + ? X_DIRECTION_BEARISH + : demPriceOutBar.time > supPriceOutBar.time + ? X_DIRECTION_BULLISH + : X_DIRECTION_NONE + : X_DIRECTION_NONE; + + // + result = HasDirection(dir); + + // + // Clean Up Resources ... + + // + demBox.Clean(); + supBox.Clean(); + supPriceOutBar.Clean(); + demPriceOutBar.Clean(); + + // + return result; + } + + // + bool HasInsideBox( + XBoxZone &box // + ) + { + // + bool result = false; + + // + int index = -1; + + // + result = box.IsValid(); + if (!result) + { + return result; + } + + // + int count = 0; + bool has = false; + + // + has = HasWaitingBoxes(); + if (has) + { + // + result = HasInsideBox( + index, + box, + waitingBoxes // + ); + } + + // + // Supply Zones ... + if (!result) + { + // + has = HasSupplyZones(); + if (has) + { + // + XBoxZone tmpBoxes[]; + count = ToBox( + supplyZones, + tmpBoxes // + ); + + // + has = IsValidSize(count); + if (has) + { + // + result = HasInsideBox( + index, + box, + tmpBoxes // + ); + } + + // + Clean(tmpBoxes); + } + } + + // + // Demand Zones ... + if (!result) + { + // + has = HasDemandZones(); + if (has) + { + // + XBoxZone tmpBoxes[]; + count = ToBox( + demandZones, + tmpBoxes // + ); + + // + has = IsValidSize(count); + if (has) + { + // + result = HasInsideBox( + index, + box, + tmpBoxes // + ); + } + + // + Clean(tmpBoxes); + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + // + bool IsExists(XBoxZone &box) + { + // + bool result = false; + + // + result = box.IsValid(); + if (!result) + { + return result; + } + + // + int idx = -1; + bool has = false; + + // + // Checking Index Waiting Box ... + has = HasWaitingBoxes(); + if (has) + { + // + idx = FindIndex( + box, + waitingBoxes // + ); + result = !IsValidIndex(idx); + if (!result) + { + return result; + } + } + + // + // Checking Index Inside Boxes ... + has = HasInsideBoxes(); + if (has) + { + // + idx = FindIndex( + box, + insideBoxes // + ); + result = !IsValidIndex(idx); + if (!result) + { + return result; + } + } + + // + // Checking Index Breaked Boxes ... + has = HasBreakedBoxes(); + if (has) + { + // + idx = FindIndex( + box, + breakedBoxes // + ); + result = !IsValidIndex(idx); + if (!result) + { + return result; + } + } + + // + // Checking Index BreakedInside Boxes ... + has = HasBreakedInsideBoxes(); + if (has) + { + // + idx = FindIndex( + box, + breakedInsideBoxes // + ); + result = !IsValidIndex(idx); + if (!result) + { + return result; + } + } + + // + return result; + } + + // + bool IsSupplyExists(XCSupplyZone *zone) + { + // + bool result = false; + + // + result = zone != NULL && + zone.IsValid(); + if (!result) + { + return result; + } + + // + // Converts Zone to Box ... + XBoxZone box; + result = ToBox( + box, + zone // + ); + if (!result) + { + // + box.Clean(); + return result; + } + + // + // Checking Index in SupplyZones ... + int idx = FindIndex( + zone, + supplyZones // + ); + result = !IsValidIndex(idx); + if (!result) + { + // + box.Clean(); + return result; + } + + // + result = IsExists(box); + + // + box.Clean(); + + // + return result; + } + + // + bool IsDemandExists(XCDemandZone *zone) + { + // + bool result = false; + + // + result = zone != NULL && + zone.IsValid(); + if (!result) + { + return result; + } + + // + // Converts Zone to Box ... + XBoxZone box; + result = ToBox( + box, + zone // + ); + if (!result) + { + // + box.Clean(); + return result; + } + + // + // Checking Index in SupplyZones ... + int idx = FindIndex( + zone, + demandZones // + ); + result = !IsValidIndex(idx); + if (!result) + { + // + box.Clean(); + return result; + } + + // + result = IsExists(box); + + // + box.Clean(); + + // + return result; + } + + // + void UpdateTo(datetime value = NULL) + { + // + value = NormalizeTime(value); + + // + int count = 0; + bool has = false; + + // + has = HasSupplyZone(); + if (has) + { + supplyZone.To(value); + } + + // + has = HasDemandZone(); + if (has) + { + demandZone.To(value); + } + + // + has = HasSupplyZones(); + if (has) + { + // + count = CountSupplyZones(); + for (int i = 0; i < count; i++) + { + supplyZones[i].To(value); + } + } + + // + has = HasDemandZones(); + if (has) + { + // + count = CountDemandZones(); + for (int i = 0; i < count; i++) + { + demandZones[i].To(value); + } + } + + // + has = HasSupportZones(); + if (has) + { + // + count = CountSupportZones(); + for (int i = 0; i < count; i++) + { + supportZones[i].To(value); + } + } + + // + has = HasResistanceZones(); + if (has) + { + // + count = CountResistanceZones(); + for (int i = 0; i < count; i++) + { + resistanceZones[i].To(value); + } + } + + // + // + // + + // + has = HasWaitingBoxes(); + if (has) + { + // + count = ArraySize(waitingBoxes); + for (int i = 0; i < count; i++) + { + waitingBoxes[i].to = value; + } + } + + // + has = HasInsideBoxes(); + if (has) + { + // + count = CountInsideBoxes(); + for (int i = 0; i < count; i++) + { + insideBoxes[i].to = value; + } + } + + // + has = HasBreakedBoxes(); + if (has) + { + } + + // + has = HasBreakedInsideBoxes(); + if (has) + { + // + count = CountBreakedInsideBoxes(); + for (int i = 0; i < count; i++) + { + breakedInsideBoxes[i].to = value; + } + } + + // + } + + // + void Draw( + XCPOIDrawer *drawer, + bool drawWaitingBoxes = true, + bool drawInsideBoxes = false, + bool drawBreakedBoxes = false, + bool drawBreakedInsideBoxes = false, + bool drawSupplyZone = false, + bool drawDemandZone = false, + bool drawSupplyZones = false, + bool drawDemandZones = false, + bool drawSupportZones = false, + bool drawResistanceZones = false // + ) + { + // + if (drawer == NULL) + { + return; + } + + // + int count = 0; + bool has = false; + bool isCreated = false; + + // + ulong chartID = drawer.ChartIdentification(); + int subWindow = drawer.SubWindowIdentification(); + color bullishColor = drawer.BarBullishColor(); + color bearishColor = drawer.BarBearishColor(); + + // + // Supply Zone ... + if (drawSupplyZone) + { + // + has = HasSupplyZone(); + if (has) + { + // + XCSupplyZoneObject *iObj; + isCreated = drawer.CreateSupplyZone( + supplyZone, + iObj // + ); + + // + if (isCreated) + { + mWorkingZoneObjects.Add(iObj); + } + } + } + + // + // Demand Zone ... + if (drawDemandZone) + { + // + has = HasDemandZone(); + if (has) + { + // + XCDemandZoneObject *iObj; + isCreated = drawer.CreateDemandZone( + demandZone, + iObj // + ); + + // + if (isCreated) + { + mWorkingZoneObjects.Add(iObj); + } + } + } + + // + // + // + + // + // Supply Zones ... + if (drawSupplyZones) + { + // + has = HasSupplyZones(); + if (has) + { + // + count = CountSupplyZones(); + for (int i = 0; i < count; i++) + { + // + XCSupplyZoneObject *iObj; + isCreated = drawer.CreateSupplyZone( + supplyZones[i], + iObj // + ); + + // + if (isCreated) + { + mWorkingZoneObjects.Add(iObj); + } + } + } + } + + // + // Demand Zones ... + if (drawDemandZones) + { + // + has = HasDemandZones(); + if (has) + { + // + count = CountDemandZones(); + for (int i = 0; i < count; i++) + { + // + XCDemandZoneObject *iObj; + isCreated = drawer.CreateDemandZone( + demandZones[i], + iObj // + ); + + // + if (isCreated) + { + mWorkingZoneObjects.Add(iObj); + } + } + } + } + + // + // Support Zones ... + if (drawSupportZones) + { + // + has = HasSupportZones(); + if (has) + { + // + count = CountSupportZones(); + for (int i = 0; i < count; i++) + { + // + XCSupportZoneObject *iObj; + isCreated = drawer.CreateSupportZone( + supportZones[i], + iObj // + ); + + // + if (isCreated) + { + mWorkingZoneObjects.Add(iObj); + } + } + } + } + + // + // Resistance Zones ... + if (drawResistanceZones) + { + // + has = HasResistanceZones(); + if (has) + { + // + count = CountResistanceZones(); + for (int i = 0; i < count; i++) + { + // + XCResistanceZoneObject *iObj; + isCreated = drawer.CreateResistanceZone( + resistanceZones[i], + iObj // + ); + + // + if (isCreated) + { + mWorkingZoneObjects.Add(iObj); + } + } + } + } + + // + // + // + + // + // Waiting Boxes ... + if (drawWaitingBoxes) + { + // + has = HasWaitingBoxes(); + if (has) + { + // + count = CountWaitingBoxes(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = waitingBoxes[i]; + + // + XCBoxObject *iObj; + bool isCreated = drawer.DrawBox( + iBox, + iObj // + ); + + // + if (isCreated) + { + mWorkingZoneObjects.Add(iObj); + } + + // + iBox.Clean(); + } + } + } + + // + // Inside Boxes ... + if (drawInsideBoxes) + { + // + has = HasInsideBoxes(); + if (has) + { + } + } + + // + // Breaked Boxes ... + if (drawBreakedBoxes) + { + // + has = HasBreakedBoxes(); + if (has) + { + // + } + } + + // + // Breaked Inside Boxes ... + if (drawBreakedInsideBoxes) + { + // + has = HasBreakedInsideBoxes(); + if (has) + { + // + count = CountBreakedInsideBoxes(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = breakedInsideBoxes[i]; + XCBoxObject *iObj; + has = drawer.DrawBox( + iBox, + iObj // + ); + if (has) + { + // + iObj.BoxWidth(1); + mBreakedInsideZoneObjects.Add(iObj); + } + } + } + } + + // + // + // + + // + // Quarters ... + has = IsValid(); + if (has) + { + // + double zoneUpper = supplyZone.Upper(); + double upper = supplyZone.Lower(); + + // + double lower = demandZone.Upper(); + double zoneLower = demandZone.Lower(); + + // + string prefix = "X121WZone_" + symbol + "_" + ToString(period); + + // + // Zone Upper ... + CChartObjectHLine *zoneUpperLine; + zoneUpperLine = new CChartObjectHLine(); + isCreated = zoneUpperLine.Create( + chartID, + prefix + "_ZoneTop", + subWindow, + zoneUpper // + ); + if (isCreated) + { + // + zoneUpperLine.Color(clrRed); + + // + mWaitingZoneObjects.Add(zoneUpperLine); + } + + // + // Zone Lower ... + CChartObjectHLine *zoneLowerLine; + zoneLowerLine = new CChartObjectHLine(); + isCreated = zoneLowerLine.Create( + chartID, + prefix + "_ZoneDown", + subWindow, + zoneLower // + ); + if (isCreated) + { + // + zoneLowerLine.Color(clrRed); + + // + mWaitingZoneObjects.Add(zoneLowerLine); + } + + // + // Upper ... + CChartObjectHLine *upperLine; + upperLine = new CChartObjectHLine(); + isCreated = upperLine.Create( + chartID, + prefix + "_Upper", + subWindow, + upper // + ); + if (isCreated) + { + // + upperLine.Color(clrLime); + + // + mWaitingZoneObjects.Add(upperLine); + } + + // + // Lower ... + CChartObjectHLine *lowerLine; + lowerLine = new CChartObjectHLine(); + isCreated = lowerLine.Create( + chartID, + prefix + "_Lower", + subWindow, + lower // + ); + if (isCreated) + { + // + lowerLine.Color(clrLime); + + // + mWaitingZoneObjects.Add(lowerLine); + } + + // + // Quarters ... + + // + // Quarter 1 ... + CChartObjectHLine *q1Line; + q1Line = new CChartObjectHLine(); + isCreated = q1Line.Create( + chartID, + prefix + "_Q1", + subWindow, + quarter1 // + ); + if (isCreated) + { + // + q1Line.Color(clrYellow); + + // + mWaitingZoneObjects.Add(q1Line); + } + + // + // Quarter 2 ... + CChartObjectHLine *q2Line; + q2Line = new CChartObjectHLine(); + isCreated = q2Line.Create( + chartID, + prefix + "_Q2", + subWindow, + quarter2 // + ); + if (isCreated) + { + // + q2Line.Color(clrYellow); + + // + mWaitingZoneObjects.Add(q2Line); + } + + // + // Quarter 3 ... + CChartObjectHLine *q3Line; + q3Line = new CChartObjectHLine(); + isCreated = q3Line.Create( + chartID, + prefix + "_Q3", + subWindow, + quarter3 // + ); + if (isCreated) + { + // + q3Line.Color(clrYellow); + + // + mWaitingZoneObjects.Add(q3Line); + } + } + } + + // + // + // + + // + bool HasSupplyZone() + { + return supplyZone != NULL && + supplyZone.IsValid(); + } + + // + bool HasDemandZone() + { + return demandZone != NULL && + demandZone.IsValid(); + } + + // + bool HasSupplyZones() + { + return HasChild(supplyZones); + } + + // + int CountSupplyZones() + { + return ArraySize(supplyZones); + } + + // + bool HasDemandZones() + { + return HasChild(demandZones); + } + + // + int CountDemandZones() + { + return ArraySize(demandZones); + } + + // + bool HasSupportZones() + { + return HasChild(supportZones); + } + + // + int CountSupportZones() + { + return ArraySize(supportZones); + } + + // + bool HasResistanceZones() + { + return HasChild(resistanceZones); + } + + // + int CountResistanceZones() + { + return ArraySize(resistanceZones); + } + + // + bool HasConsolidationZones() + { + return HasChild(consolidationZones); + } + + // + int CountConsolidationZones() + { + return ArraySize(consolidationZones); + } + + // + bool HasWaitingBoxes() + { + return HasChild(waitingBoxes); + } + + // + int CountWaitingBoxes() + { + return ArraySize(waitingBoxes); + } + + // + bool HasInsideBoxes() + { + return HasChild(insideBoxes); + } + + // + int CountInsideBoxes() + { + return ArraySize(insideBoxes); + } + + // + bool HasBreakedBoxes() + { + return HasChild(breakedBoxes); + } + + // + int CountBreakedBoxes() + { + return ArraySize(breakedBoxes); + } + + // + bool HasBreakedInsideBoxes() + { + return HasChild(breakedInsideBoxes); + } + + // + int CountBreakedInsideBoxes() + { + return ArraySize(breakedInsideBoxes); + } + + // +}; + +// +struct X121SMCStrategyXWZSignalConditions +{ + // + // Props ... + + // + string symbol; + ENUM_TIMEFRAMES period; + + // + double sl; + double reward; + double amountPercent; + ENUM_X_DIRECTION dir; + ENUM_X_POSITION_TYPES type; + + // + // Setup Props ... + + // + datetime setupTime; + datetime triggerTime; + + // + double pivot; + double point; + double sls[]; + double targets[]; + + // + XBoxZone signalBox; + + // + ENUM_X121SMC_XWZ_PRIORITY priority; + ENUM_X121SMC_XWZ_PROVIDERS provider; + + // + // Constructor ... + X121SMCStrategyXWZSignalConditions() + { + 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; + + // + ExtensionClean(); + + // + ZeroMemory(this); + } + + /** + * 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 ... + + /** + * Clean Additional Properties ... + */ + void ExtensionClean() + { + // + pivot = 0; + point = 0; + + // + reward = 0; + amountPercent = 0; + + // + Clean(sls); + Clean(targets); + signalBox.Clean(); + + // + provider = X121SMC_XWZ_PROVIDER_NONE; + } + + // + // + // + + // + void UpdateTo(datetime value = NULL) + { + // + value = NormalizeTime(value); + + // + int count = 0; + bool has = false; + } + + // +}; + +// +// Extension Functions ... + +// \ No newline at end of file diff --git a/BKPS/14031218/Documents/BKP/x-121.smc.xwz.signal.lib copy.mq5 b/BKPS/14031218/Documents/BKP/x-121.smc.xwz.signal.lib copy.mq5 new file mode 100644 index 0000000..fd0c9ab --- /dev/null +++ b/BKPS/14031218/Documents/BKP/x-121.smc.xwz.signal.lib copy.mq5 @@ -0,0 +1,4871 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 X121 SMC Signal Class +// ------------------------------------------------- +// Name: XWZ +// 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 "../../Libraries/x-trade.lib" +#include "../Classes/x-121.smc.market.cycle.helper.class.mq5" +#include "../Libraries/x-121.smc.guard.lib.mq5" +#include "../Libraries/x-121.smc.lib.mq5" + +// +enum ENUM_X121SMC_XWZ_PROVIDERS +{ + X121SMC_XWZ_PROVIDER_NONE, + X121SMC_XWZ_PROVIDER_ACTIVATED_ZONE, + X121SMC_XWZ_PROVIDER_ACTIVATED_CHOCH, + X121SMC_XWZ_PROVIDER_PRICE_INSIDE_ZONE, +}; + +// +enum ENUM_X121SMC_XWZ_PRIORITY +{ + X121SMC_XWZ_PRIORITY_NONE, + X121SMC_XWZ_PRIORITY_WEAK, + X121SMC_XWZ_PRIORITY_LOW, + X121SMC_XWZ_PRIORITY_REGULAR, + X121SMC_XWZ_PRIORITY_HIGH, + X121SMC_XWZ_PRIORITY_STRONG_HIGH, +}; + +// +struct X121SMCStrategyXWZWorkingZone +{ + // + // Props ... + + // + string symbol; + ENUM_TIMEFRAMES period; + + // + double quarter1; + double quarter2; + double quarter3; + + // + XCSupplyZone *supplyZone; + XCDemandZone *demandZone; + + // + XCSupplyZone *supplyZones[]; + XCDemandZone *demandZones[]; + + // + XCSupportZone *supportZones[]; + XCResistanceZone *resistanceZones[]; + + // + XOBFVG insideZones[]; + XOBFVG breakedZones[]; + XOBFVG waitingZones[]; + + // + XBoxZone insideBoxes[]; + XBoxZone breakedBoxes[]; + XConsolidationZone consolidationZones[]; + + // + CArrayObj mInsideZoneObjects; + CArrayObj mBreakedZoneObjects; + CArrayObj mWaitingZoneObjects; + CArrayObj mWorkingZoneObjects; + + // + // Constructor ... + X121SMCStrategyXWZWorkingZone() + { + Clean(); + } + + // + // Tools ... + + // + void Clean() + { + // + quarter1 = 0; + quarter2 = 0; + quarter3 = 0; + + // + symbol = NULL; + period = NULL; + + // + Clean(supplyZones); + Clean(demandZones); + + // + Clean(insideZones); + Clean(waitingZones); + Clean(breakedZones); + + // + Clean(insideBoxes); + Clean(breakedBoxes); + + // + Clean(supportZones); + Clean(resistanceZones); + + // + ZeroMemory(supplyZone); + ZeroMemory(demandZone); + + // + mInsideZoneObjects.Clear(); + mBreakedZoneObjects.Clear(); + mWaitingZoneObjects.Clear(); + mWorkingZoneObjects.Clear(); + } + + // + bool IsValid() + { + // + bool result = false; + + // + result = + // + quarter1 > 0 && + quarter2 > 0 && + quarter3 > 0 && + HasSupplyZone() && + HasDemandZone() && + quarter1 > quarter2 && + quarter2 > quarter3 + // + ; + + // + return result; + } + + // + bool Init( + string _symbol, + ENUM_TIMEFRAMES _period, + int barIndex, + XPOIState &htfState, + XPOIState &mtfState, + XPOIState &stfState, // + XPOIState &ttfState // + ) + { + // + bool result = false; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + result = + // + IsValid(_symbol) && + IsValid(_period) && + // + htfState.IsValid() && + mtfState.IsValid() && + stfState.IsValid() && + ttfState.IsValid() && + // + htfState.HasChild() && + mtfState.HasChild() && + stfState.HasChild() && + ttfState.HasChild() + // + ; + if (!result) + { + return result; + } + + // + symbol = _symbol; + period = _period; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + XOHCL zBar; + has = zBar.Init( + symbol, + period, + barIndex // + ); + result = has; + if (!result) + { + zBar.Clean(); + return result; + } + double ll5 = zBar.FindLowest(5, MODE_LOW); + double hh5 = zBar.FindHighest(5, MODE_HIGH); + zBar.Clean(); + + // + // Supply Zone ... + has = HasSupplyZone(); + if (!has) + { + // + idx = GetHighest(htfState.supplyZones); + has = IsValidIndex(idx); + if (has) + { + // + supplyZone = htfState.supplyZones[idx]; + has = hh5 < supplyZone.Lower(); + if (!has) + { + supplyZone = NULL; + } + } + } + + // + // Demand Zone ... + has = HasDemandZone(); + if (!has) + { + // + idx = GetLowest(htfState.demandZones); + has = IsValidIndex(idx); + if (has) + { + // + demandZone = htfState.demandZones[idx]; + has = ll5 > demandZone.Upper(); + if (!has) + { + demandZone = NULL; + } + } + } + + // + // Supply Zones ... + has = HasSupplyZones(); + if (!has) + { + // + count = mtfState.FilterSupplyZones( + supplyZones, + period, + XZONE_STATE_PASSED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_IGNORED, + false // + ); + } + + // + // Demand Zones ... + has = HasDemandZones(); + if (!has) + { + // + count = mtfState.FilterDemandZones( + demandZones, + period, + XZONE_STATE_PASSED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_IGNORED, + false // + ); + } + + // // + // // Support Zones ... + // has = HasSupportZones(); + // if (!has) + // { + // // + // count = stfState.FilterSupportZones( + // supportZones, + // period, + // XZONE_STATE_PASSED, + // false, + // XZONE_STATE_FAILED, + // false, + // XZONE_STATE_FAILED, + // false, + // XZONE_STATE_IGNORED, + // false // + // ); + // } + + // // + // // Resistance Zones ... + // has = HasResistanceZones(); + // if (!has) + // { + // // + // count = stfState.FilterResistanceZones( + // resistanceZones, + // period, + // XZONE_STATE_PASSED, + // false, + // XZONE_STATE_FAILED, + // false, + // XZONE_STATE_FAILED, + // false, + // XZONE_STATE_IGNORED, + // false // + // ); + // } + + // + has = ttfState.HasConsolidationZones(); + if (has) + { + // + Copy( + ttfState.consolidationZones, + consolidationZones // + ); + CleanupArray( + consolidationZones, + 50 // + ); + } + + // + if (supplyZone != NULL && + demandZone != NULL && + supplyZone.IsValid() && + demandZone.IsValid()) + { + // + double upper = supplyZone.Lower(); + double lower = demandZone.Upper(); + + // + double delta = ((upper - lower) / 100) * 25; + + // + quarter1 = upper - (1 * delta); + quarter2 = upper - (2 * delta); + quarter3 = upper - (3 * delta); + } + + // + // Detect OBFVG(s) ... + ExtractOBFVGs( + waitingZones, + mtfState, + stfState + // , + // X_OBFVG_FVG_FILTER_ABOVE_BELOW, + // X_OBFVG_FVG_SELECT_HIGHEST_LOWEST // + ); + + // // + // // Detect Waiting Zones based on STF and TTF ... + // XOBFVG tmpWaitingZones[]; + // count = ExtractOBFVGs( + // tmpWaitingZones, + // stfState, + // stfState // + // ); + // has = IsValidSize(count); + // if (has) + // { + // // + // for (int i = 0; i < count; i++) + // { + // // + // XOBFVG iOBFVG = tmpWaitingZones[i]; + + // // + // idx = FindIndex( + // iOBFVG, + // waitingZones // + // ); + // has = IsValidIndex(idx); + // if (has) + // { + // // + // iOBFVG.Clean(); + // continue; + // } + + // // + // AddRef( + // iOBFVG, + // waitingZones // + // ); + + // // + // iOBFVG.Clean(); + // } + // } + + // + result = IsValid(); + if (!result) + { + Clean(); + } + + // + return result; + } + + // + void Update( + int barIndex, + XPOIState &htfState, + XPOIState &mtfState, + XPOIState &stfState, + XPOIState &ttfState // + ) + { + // + int idx = -1; + int count = 0; + bool has = false; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + has = + // + IsValid() && + // + htfState.IsValid() && + mtfState.IsValid() && + stfState.IsValid() && + // + htfState.HasChild() && + mtfState.HasChild() && + stfState.HasChild() + // + ; + if (!has) + { + return; + } + + // + XOHCL zBar; + has = zBar.Init( + symbol, + period, + barIndex // + ); + if (!has) + { + // + zBar.Clean(); + return; + } + + // + XOHCL cBar; + has = zBar.GetPreviousBar(cBar); + if (!has) + { + // + zBar.Clean(); + cBar.Clean(); + + // + return; + } + + // + // Adding New OBFVG to Waiting Zones if not Exists ... + XOBFVG tmpWaitingZones[]; + count = ExtractOBFVGs( + tmpWaitingZones, + mtfState, + stfState + // , + // X_OBFVG_FVG_FILTER_ABOVE_BELOW, + // X_OBFVG_FVG_SELECT_HIGHEST_LOWEST // + ); + has = IsValidSize(count); + if (has) + { + // + AddIfNotExists( + tmpWaitingZones, + waitingZones // + ); + } + + // + // Detect Waiting Zones based on STF and TTF ... + // Clean(tmpWaitingZones); + // count = ExtractOBFVGs( + // tmpWaitingZones, + // stfState, + // ttfState // + // ); + // has = IsValidSize(count); + // if (has) + // { + // // + // AddIfNotExists( + // tmpWaitingZones, + // waitingZones // + // ); + // } + + // + // Detect Waiting Zones based on TTF and TTF ... + // Clean(tmpWaitingZones); + // count = ExtractOBFVGs( + // tmpWaitingZones, + // stfState, + // stfState // + // ); + // has = IsValidSize(count); + // if (has) + // { + // // + // AddIfNotExists( + // tmpWaitingZones, + // waitingZones // + // ); + // } + + // + // Since Usig States for Extracting Supply/Demand or + // Support/Resistance Zones and State's has Max Alllowed Restrication ... + // we have to Manage new Zones and also Hold's Breaked Zones ... + + // + // MTF STF ... + + // + // Supply Zones ... + XCSupplyZone *tmpSupplies[]; + count = mtfState.FilterSupplyZones( + tmpSupplies, + NULL, + XZONE_STATE_PASSED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_IGNORED, + false // + ); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = ToBox( + iBox, + tmpSupplies[i] // + ); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + // Find Index ... + + // + idx = FindIndex( + iBox, + insideBoxes // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + idx = FindIndex( + iBox, + breakedBoxes // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + idx = FindIndex( + tmpSupplies[i], + supplyZones // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + // Checking Price Validation ... + has = cBar.high < tmpSupplies[i].Lower(); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + Add( + tmpSupplies[i], + supplyZones // + ); + + // + iBox.Clean(); + } + } + Clean(tmpSupplies); + + // + // Demand Zones ... + XCDemandZone *tmpDemands[]; + count = mtfState.FilterDemandZones( + tmpDemands, + NULL, + XZONE_STATE_PASSED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_FAILED, + false, + XZONE_STATE_IGNORED, + false // + ); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox; + has = ToBox( + iBox, + tmpDemands[i] // + ); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + // Find Index ... + + // + idx = FindIndex( + iBox, + insideBoxes // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + idx = FindIndex( + iBox, + breakedBoxes // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + idx = FindIndex( + tmpDemands[i], + demandZones // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + // Checking Price Validation ... + has = cBar.low > tmpDemands[i].Upper(); + if (!has) + { + // + iBox.Clean(); + continue; + } + + // + Add( + tmpDemands[i], + demandZones // + ); + + // + iBox.Clean(); + } + } + Clean(tmpDemands); + + // // + // // Support Zones ... + // XCSupportZone *tmpSupports[]; + // count = stfState.FilterSupportZones( + // tmpSupports, + // period, + // XZONE_STATE_PASSED, + // false, + // XZONE_STATE_FAILED, + // false, + // XZONE_STATE_FAILED, + // false, + // XZONE_STATE_IGNORED, + // false // + // ); + // has = IsValidSize(count); + // if (has) + // { + // // + // for (int i = 0; i < count; i++) + // { + // // + // XBoxZone iBox; + // has = ToBox( + // iBox, + // tmpSupports[i] // + // ); + // if (!has) + // { + // // + // iBox.Clean(); + // continue; + // } + + // // + // // Find Index ... + + // // + // idx = FindIndex( + // iBox, + // insideBoxes // + // ); + // has = !IsValidIndex(idx); + // if (!has) + // { + // // + // iBox.Clean(); + // continue; + // } + + // // + // idx = FindIndex( + // iBox, + // breakedBoxes // + // ); + // has = !IsValidIndex(idx); + // if (!has) + // { + // // + // iBox.Clean(); + // continue; + // } + + // // + // idx = FindIndex( + // tmpSupports[i], + // supportZones // + // ); + // has = !IsValidIndex(idx); + // if (!has) + // { + // // + // iBox.Clean(); + // continue; + // } + + // // + // // Checking Price Validation ... + // has = cBar.low > tmpSupports[i].Upper(); + // if (!has) + // { + // // + // iBox.Clean(); + // continue; + // } + + // // + // Add( + // tmpSupports[i], + // supportZones // + // ); + + // // + // iBox.Clean(); + // } + // } + // Clean(tmpSupports); + + // // + // // Resistance Zones .. + // XCResistanceZone *tmpResistances[]; + // count = stfState.FilterResistanceZones( + // tmpResistances, + // period, + // XZONE_STATE_PASSED, + // false, + // XZONE_STATE_FAILED, + // false, + // XZONE_STATE_FAILED, + // false, + // XZONE_STATE_IGNORED, + // false // + // ); + // has = IsValidSize(count); + // if (has) + // { + // // + // for (int i = 0; i < count; i++) + // { + // // + // XBoxZone iBox; + // has = ToBox( + // iBox, + // tmpResistances[i] // + // ); + // if (!has) + // { + // // + // iBox.Clean(); + // continue; + // } + + // // + // // Find Index ... + + // // + // idx = FindIndex( + // iBox, + // insideBoxes // + // ); + // has = !IsValidIndex(idx); + // if (!has) + // { + // // + // iBox.Clean(); + // continue; + // } + + // // + // idx = FindIndex( + // iBox, + // breakedBoxes // + // ); + // has = !IsValidIndex(idx); + // if (!has) + // { + // // + // iBox.Clean(); + // continue; + // } + + // // + // idx = FindIndex( + // tmpResistances[i], + // resistanceZones // + // ); + // has = !IsValidIndex(idx); + // if (!has) + // { + // // + // iBox.Clean(); + // continue; + // } + + // // + // // Checking Price Validation ... + // has = cBar.high < tmpResistances[i].Lower(); + // if (!has) + // { + // // + // iBox.Clean(); + // continue; + // } + + // // + // Add( + // tmpResistances[i], + // resistanceZones // + // ); + + // // + // iBox.Clean(); + // } + // } + // Clean(tmpResistances); + + // + // STF TTF ... + + // // + // // Supply Zones ... + // count = stfState.FilterSupplyZones( + // tmpSupplies, + // NULL, + // XZONE_STATE_PASSED, + // false, + // XZONE_STATE_FAILED, + // false, + // XZONE_STATE_FAILED, + // false, + // XZONE_STATE_IGNORED, + // false // + // ); + // has = IsValidSize(count); + // if (has) + // { + // // + // for (int i = 0; i < count; i++) + // { + // // + // XBoxZone iBox; + // has = ToBox( + // iBox, + // tmpSupplies[i] // + // ); + // if (!has) + // { + // // + // iBox.Clean(); + // continue; + // } + + // // + // // Find Index ... + + // // + // idx = FindIndex( + // iBox, + // insideBoxes // + // ); + // has = !IsValidIndex(idx); + // if (!has) + // { + // // + // iBox.Clean(); + // continue; + // } + + // // + // idx = FindIndex( + // iBox, + // breakedBoxes // + // ); + // has = !IsValidIndex(idx); + // if (!has) + // { + // // + // iBox.Clean(); + // continue; + // } + + // // + // idx = FindIndex( + // tmpSupplies[i], + // supplyZones // + // ); + // has = !IsValidIndex(idx); + // if (!has) + // { + // // + // iBox.Clean(); + // continue; + // } + + // // + // // Checking Price Validation ... + // has = cBar.high < tmpSupplies[i].Lower(); + // if (!has) + // { + // // + // iBox.Clean(); + // continue; + // } + + // // + // Add( + // tmpSupplies[i], + // supplyZones // + // ); + + // // + // iBox.Clean(); + // } + // } + // Clean(tmpSupplies); + + // // + // // Demand Zones ... + // count = stfState.FilterDemandZones( + // tmpDemands, + // NULL, + // XZONE_STATE_PASSED, + // false, + // XZONE_STATE_FAILED, + // false, + // XZONE_STATE_FAILED, + // false, + // XZONE_STATE_IGNORED, + // false // + // ); + // has = IsValidSize(count); + // if (has) + // { + // // + // for (int i = 0; i < count; i++) + // { + // // + // XBoxZone iBox; + // has = ToBox( + // iBox, + // tmpDemands[i] // + // ); + // if (!has) + // { + // // + // iBox.Clean(); + // continue; + // } + + // // + // // Find Index ... + + // // + // idx = FindIndex( + // iBox, + // insideBoxes // + // ); + // has = !IsValidIndex(idx); + // if (!has) + // { + // // + // iBox.Clean(); + // continue; + // } + + // // + // idx = FindIndex( + // iBox, + // breakedBoxes // + // ); + // has = !IsValidIndex(idx); + // if (!has) + // { + // // + // iBox.Clean(); + // continue; + // } + + // // + // idx = FindIndex( + // tmpDemands[i], + // demandZones // + // ); + // has = !IsValidIndex(idx); + // if (!has) + // { + // // + // iBox.Clean(); + // continue; + // } + + // // + // // Checking Price Validation ... + // has = cBar.low > tmpDemands[i].Upper(); + // if (!has) + // { + // // + // iBox.Clean(); + // continue; + // } + + // // + // Add( + // tmpDemands[i], + // demandZones // + // ); + + // // + // iBox.Clean(); + // } + // } + // Clean(tmpDemands); + + // // + // // Support Zones ... + // count = ttfState.FilterSupportZones( + // tmpSupports, + // period, + // XZONE_STATE_PASSED, + // false, + // XZONE_STATE_FAILED, + // false, + // XZONE_STATE_FAILED, + // false, + // XZONE_STATE_IGNORED, + // false // + // ); + // has = IsValidSize(count); + // if (has) + // { + // // + // for (int i = 0; i < count; i++) + // { + // // + // XBoxZone iBox; + // has = ToBox( + // iBox, + // tmpSupports[i] // + // ); + // if (!has) + // { + // // + // iBox.Clean(); + // continue; + // } + + // // + // // Find Index ... + + // // + // idx = FindIndex( + // iBox, + // insideBoxes // + // ); + // has = !IsValidIndex(idx); + // if (!has) + // { + // // + // iBox.Clean(); + // continue; + // } + + // // + // idx = FindIndex( + // iBox, + // breakedBoxes // + // ); + // has = !IsValidIndex(idx); + // if (!has) + // { + // // + // iBox.Clean(); + // continue; + // } + + // // + // idx = FindIndex( + // tmpSupports[i], + // supportZones // + // ); + // has = !IsValidIndex(idx); + // if (!has) + // { + // // + // iBox.Clean(); + // continue; + // } + + // // + // // Checking Price Validation ... + // has = cBar.low > tmpSupports[i].Upper(); + // if (!has) + // { + // // + // iBox.Clean(); + // continue; + // } + + // // + // Add( + // tmpSupports[i], + // supportZones // + // ); + + // // + // iBox.Clean(); + // } + // } + // Clean(tmpSupports); + + // // + // // Resistance Zones .. + // count = ttfState.FilterResistanceZones( + // tmpResistances, + // period, + // XZONE_STATE_PASSED, + // false, + // XZONE_STATE_FAILED, + // false, + // XZONE_STATE_FAILED, + // false, + // XZONE_STATE_IGNORED, + // false // + // ); + // has = IsValidSize(count); + // if (has) + // { + // // + // for (int i = 0; i < count; i++) + // { + // // + // XBoxZone iBox; + // has = ToBox( + // iBox, + // tmpResistances[i] // + // ); + // if (!has) + // { + // // + // iBox.Clean(); + // continue; + // } + + // // + // // Find Index ... + + // // + // idx = FindIndex( + // iBox, + // insideBoxes // + // ); + // has = !IsValidIndex(idx); + // if (!has) + // { + // // + // iBox.Clean(); + // continue; + // } + + // // + // idx = FindIndex( + // iBox, + // breakedBoxes // + // ); + // has = !IsValidIndex(idx); + // if (!has) + // { + // // + // iBox.Clean(); + // continue; + // } + + // // + // idx = FindIndex( + // tmpResistances[i], + // resistanceZones // + // ); + // has = !IsValidIndex(idx); + // if (!has) + // { + // // + // iBox.Clean(); + // continue; + // } + + // // + // // Checking Price Validation ... + // has = cBar.high < tmpResistances[i].Lower(); + // if (!has) + // { + // // + // iBox.Clean(); + // continue; + // } + + // // + // Add( + // tmpResistances[i], + // resistanceZones // + // ); + + // // + // iBox.Clean(); + // } + // } + // Clean(tmpResistances); + + // + // + // + + // + // Consolidation Zones ... + has = ttfState.HasConsolidationZones(); + if (has) + { + // + Copy( + ttfState.consolidationZones, + consolidationZones // + ); + CleanupArray( + consolidationZones, + 50 // + ); + } + + // + // + // + + // + // Detect Price Inside Zones ... + has = HasWaitingZones(); + if (has) + { + // + int mustRemove[]; + count = CountWaitingZones(); + for (int i = 0; i < count; i++) + { + // + XOBFVG iOBFVG = waitingZones[i]; + + // + bool isInside = + // + zBar.high < iOBFVG.ob.Upper() && + zBar.low > iOBFVG.ob.Lower() && + // + cBar.high < iOBFVG.ob.Upper() && + cBar.low > iOBFVG.ob.Lower() + // + ; + if (isInside) + { + // + idx = FindIndex( + iOBFVG, + insideZones // + ); + has = IsValidSize(idx); + if (!has) + { + // + Add( + i, + mustRemove // + ); + + // + AddRef( + iOBFVG, + insideZones // + ); + } + } + } + + // + has = HasChild(mustRemove); + if (has) + { + // + count = ArraySize(mustRemove); + for (int i = 0; i < count; i++) + { + // + ArrayRemove( + waitingZones, + mustRemove[i], + 1 // + ); + } + } + + // + Clean(mustRemove); + } + + // + // Here we Looking for Price Inside Supply or Demand Zones ... + + // + // Supply Zones ... + has = HasSupplyZones(); + if (has) + { + // + int mustRemove[]; + count = CountSupplyZones(); + for (int i = 0; i < count; i++) + { + // + XCSupplyZone *iZone = supplyZones[i]; + + // + bool isInside = + // + zBar.high < iZone.Upper() && + zBar.low > iZone.Lower() && + // + cBar.high < iZone.Upper() && + cBar.low > iZone.Lower() + // + ; + if (isInside) + { + // + XBoxZone iBox; + has = ToBox( + iBox, + iZone // + ); + if (has) + { + // + idx = FindIndex( + iBox, + insideBoxes // + ); + has = IsValidSize(idx); + if (!has) + { + // + Add( + i, + mustRemove // + ); + + // + AddRef( + iBox, + insideBoxes // + ); + } + } + + // + iBox.Clean(); + } + } + + // + has = HasChild(mustRemove); + if (has) + { + // + count = ArraySize(mustRemove); + for (int i = 0; i < count; i++) + { + // + ArrayRemove( + supplyZones, + mustRemove[i], + 1 // + ); + } + } + + // + Clean(mustRemove); + } + + // + // Demand Zones ... + has = HasDemandZones(); + if (has) + { + // + int mustRemove[]; + count = CountDemandZones(); + for (int i = 0; i < count; i++) + { + // + XCDemandZone *iZone = demandZones[i]; + + // + bool isInside = + // + zBar.high < iZone.Upper() && + zBar.low > iZone.Lower() && + // + cBar.high < iZone.Upper() && + cBar.low > iZone.Lower() + // + ; + if (isInside) + { + // + XBoxZone iBox; + has = ToBox( + iBox, + iZone // + ); + if (has) + { + // + idx = FindIndex( + iBox, + insideBoxes // + ); + has = IsValidSize(idx); + if (!has) + { + // + Add( + i, + mustRemove // + ); + + // + AddRef( + iBox, + insideBoxes // + ); + } + } + + // + iBox.Clean(); + } + } + + // + has = HasChild(mustRemove); + if (has) + { + // + count = ArraySize(mustRemove); + for (int i = 0; i < count; i++) + { + // + ArrayRemove( + demandZones, + mustRemove[i], + 1 // + ); + } + } + + // + Clean(mustRemove); + } + + // + // Here we Detect Breaked Zone/Box (s) ... + + // + // Detect Breaked Zones ... + has = HasInsideZones(); + if (has) + { + // + int mustRemove[]; + count = CountInsideZones(); + for (int i = 0; i < count; i++) + { + // + XOBFVG iOBFVG = insideZones[i]; + ENUM_X_DIRECTION iDir = iOBFVG.GetDirection(); + bool isBullish = IsBullish(iDir); + + // + bool isBullishBreaked = + // + zBar.high < iOBFVG.ob.Lower() && + cBar.high < iOBFVG.ob.Lower() + // + ; + + // + bool isBearishBreaked = + // + zBar.low > iOBFVG.ob.Upper() && + cBar.low > iOBFVG.ob.Upper() + // + ; + + // + bool isBreaked = + isBullish + ? isBullishBreaked + : isBearishBreaked; + + // + if (isBreaked) + { + // + idx = FindIndex( + iOBFVG, + breakedZones // + ); + has = IsValidIndex(idx); + if (!has) + { + // + Add( + i, + mustRemove // + ); + + // + AddRef( + iOBFVG, + breakedZones // + ); + } + } + } + + // + has = HasChild(mustRemove); + if (has) + { + // + count = ArraySize(mustRemove); + for (int i = 0; i < count; i++) + { + // + ArrayRemove( + insideZones, + mustRemove[i], + 1 // + ); + } + } + + // + Clean(mustRemove); + } + + // + // Detect Breaked Boxes ... + has = HasInsideBoxes(); + if (has) + { + // + int mustRemove[]; + count = CountInsideBoxes(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = insideBoxes[i]; + ENUM_X_DIRECTION iDir = iBox.dir; + bool isBullish = iBox.IsBullish(); + + // + bool isBullishBreaked = + // + zBar.high < iBox.lower && + cBar.high < iBox.lower + // + ; + + // + bool isBearishBreaked = + // + zBar.low > iBox.upper && + cBar.low > iBox.upper + // + ; + + // + bool isBreaked = + isBullish + ? isBullishBreaked + : isBearishBreaked; + + // + if (isBreaked) + { + // + idx = FindIndex( + iBox, + breakedBoxes // + ); + has = IsValidIndex(idx); + if (!has) + { + // + Add( + i, + mustRemove // + ); + + // + AddRef( + iBox, + breakedBoxes // + ); + } + } + } + + // + has = HasChild(mustRemove); + if (has) + { + // + count = ArraySize(mustRemove); + for (int i = 0; i < count; i++) + { + // + ArrayRemove( + insideBoxes, + mustRemove[i], + 1 // + ); + } + } + + // + Clean(mustRemove); + } + + // + // Cleanup Resource ... + + // + zBar.Clean(); + cBar.Clean(); + } + + // + bool HasSupplyZone() + { + return supplyZone != NULL && + supplyZone.IsValid(); + } + + // + bool HasDemandZone() + { + return demandZone != NULL && + demandZone.IsValid(); + } + + // + bool HasSupplyZones() + { + return HasChild(supplyZones); + } + + // + int CountSupplyZones() + { + return ArraySize(supplyZones); + } + + // + bool HasDemandZones() + { + return HasChild(demandZones); + } + + // + int CountDemandZones() + { + return ArraySize(demandZones); + } + + // + bool HasSupportZones() + { + return HasChild(supportZones); + } + + // + int CountSupportZones() + { + return ArraySize(supportZones); + } + + // + bool HasResistanceZones() + { + return HasChild(resistanceZones); + } + + // + int CountResistanceZones() + { + return ArraySize(resistanceZones); + } + + // + bool HasWaitingZones() + { + return HasChild(waitingZones); + } + + // + int CountWaitingZones() + { + return ArraySize(waitingZones); + } + + // + bool HasInsideZones() + { + return HasChild(insideZones); + } + + // + int CountInsideZones() + { + return ArraySize(insideZones); + } + + // + bool HasBreakedZones() + { + return HasChild(breakedZones); + } + + // + int CountBreakedZones() + { + return ArraySize(breakedZones); + } + + // + bool HasConsolidationZones() + { + return HasChild(consolidationZones); + } + + // + int CountConsolidationZones() + { + return ArraySize(consolidationZones); + } + + // + bool HasInsideBoxes() + { + return HasChild(insideBoxes); + } + + // + int CountInsideBoxes() + { + return ArraySize(insideBoxes); + } + + // + bool HasBreakedBoxes() + { + return HasChild(breakedBoxes); + } + + // + int CountBreakedBoxes() + { + return ArraySize(breakedBoxes); + } + + // + // + // + + // + bool IsDestroyed( + int barIndex = 0, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init( + symbol, + period, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + XOHCL cBar; + result = bar.GetPreviousBar(cBar); + if (!result) + { + // + bar.Clean(); + cBar.Clean(); + + // + return result; + } + + // + bool isSupplyZoneBreaked = + // + bar.low > supplyZone.Upper() && + cBar.low > supplyZone.Upper() + // + ; + + // + bool isDemandZoneBreaked = + // + bar.high < demandZone.Lower() && + cBar.high < demandZone.Lower() + // + ; + + // + bar.Clean(); + cBar.Clean(); + + // + result = isSupplyZoneBreaked || + isDemandZoneBreaked; + + // + return result; + } + + // + bool DetectPriority( + ENUM_X121SMC_XWZ_PRIORITY &priority, + ENUM_X_DIRECTION forDir, + int barIndex = 0, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + priority = X121SMC_XWZ_PRIORITY_NONE; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + result = IsValid() && + HasDirection(forDir); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + XOHCL bar; + result = bar.Init( + symbol, + forPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + if (bar.high < supplyZone.Upper() && + bar.low > supplyZone.Lower()) + { + // + priority = + isBullish + ? X121SMC_XWZ_PRIORITY_NONE + : X121SMC_XWZ_PRIORITY_STRONG_HIGH; + } + else if (bar.high < supplyZone.Lower() && + bar.low > quarter1) + { + // + priority = + isBullish + ? X121SMC_XWZ_PRIORITY_WEAK + : X121SMC_XWZ_PRIORITY_HIGH; + } + else if (bar.high < quarter1 && + bar.low > quarter2) + { + // + priority = + isBullish + ? X121SMC_XWZ_PRIORITY_LOW + : X121SMC_XWZ_PRIORITY_REGULAR; + } + else if (bar.high < quarter2 && + bar.low > quarter3) + { + // + priority = + isBullish + ? X121SMC_XWZ_PRIORITY_REGULAR + : X121SMC_XWZ_PRIORITY_LOW; + } + else if (bar.high < quarter3 && + bar.low > demandZone.Upper()) + { + // + priority = + isBullish + ? X121SMC_XWZ_PRIORITY_HIGH + : X121SMC_XWZ_PRIORITY_WEAK; + } + else if (bar.high < demandZone.Upper() && + bar.low > demandZone.Lower()) + { + // + priority = + isBullish + ? X121SMC_XWZ_PRIORITY_STRONG_HIGH + : X121SMC_XWZ_PRIORITY_NONE; + } + + // + result = priority != X121SMC_XWZ_PRIORITY_NONE && + priority != X121SMC_XWZ_PRIORITY_WEAK; + + // + bar.Clean(); + + // + return result; + } + + // + // + // + + // + void UpdateTo(datetime value = NULL) + { + // + value = NormalizeTime(value); + + // + int count = 0; + bool has = false; + + // + has = HasSupplyZone(); + if (has) + { + supplyZone.To(value); + } + + // + has = HasDemandZone(); + if (has) + { + demandZone.To(value); + } + + // + has = HasSupplyZones(); + if (has) + { + // + count = CountSupplyZones(); + for (int i = 0; i < count; i++) + { + supplyZones[i].To(value); + } + } + + // + has = HasDemandZones(); + if (has) + { + // + count = CountDemandZones(); + for (int i = 0; i < count; i++) + { + demandZones[i].To(value); + } + } + + // + has = HasSupportZones(); + if (has) + { + // + count = CountSupportZones(); + for (int i = 0; i < count; i++) + { + supportZones[i].To(value); + } + } + + // + has = HasResistanceZones(); + if (has) + { + // + count = CountResistanceZones(); + for (int i = 0; i < count; i++) + { + resistanceZones[i].To(value); + } + } + + // + has = HasWaitingZones(); + if (has) + { + // + count = CountWaitingZones(); + for (int i = 0; i < count; i++) + { + waitingZones[i].UpdateTo(value); + } + } + + // + has = HasInsideZones(); + if (has) + { + // + count = CountInsideZones(); + for (int i = 0; i < count; i++) + { + insideZones[i].UpdateTo(value); + } + } + + // + // has = HasBreakedZones(); + // if (has) + // { + // // + // count = CountBreakedZones(); + // for (int i = 0; i < count; i++) + // { + // breakedZones[i].UpdateTo(value); + // } + // } + + // + has = HasInsideBoxes(); + if (has) + { + // + count = CountInsideBoxes(); + for (int i = 0; i < count; i++) + { + insideBoxes[i].to = value; + } + } + + // + // has = HasBreakedBoxes(); + // if (has) + // { + // // + // count = CountBreakedBoxes(); + // for (int i = 0; i < count; i++) + // { + // insideBoxes[i].to = value; + // } + // } + + // + } + + // + void Draw( + XCPOIDrawer *drawer, + bool drawWaitingZones = true, + bool drawInsideZones = false, + bool drawBreakedZones = false, + bool drawSupplyZone = false, + bool drawDemandZone = false, + bool drawSupplyZones = false, + bool drawDemandZones = false, + bool drawSupportZones = false, + bool drawResistanceZones = false // + ) + { + // + if (drawer == NULL) + { + return; + } + + // + int count = 0; + bool has = false; + bool isCreated = false; + + // + ulong chartID = drawer.ChartIdentification(); + int subWindow = drawer.SubWindowIdentification(); + color bullishColor = drawer.BarBullishColor(); + color bearishColor = drawer.BarBearishColor(); + + // + // Supply Zone ... + if (drawSupplyZone) + { + // + has = HasSupplyZone(); + if (has) + { + // + XCSupplyZoneObject *iObj; + isCreated = drawer.CreateSupplyZone( + supplyZone, + iObj // + ); + + // + if (isCreated) + { + mWorkingZoneObjects.Add(iObj); + } + } + } + + // + // Demand Zone ... + if (drawDemandZone) + { + // + has = HasDemandZone(); + if (has) + { + // + XCDemandZoneObject *iObj; + isCreated = drawer.CreateDemandZone( + demandZone, + iObj // + ); + + // + if (isCreated) + { + mWorkingZoneObjects.Add(iObj); + } + } + } + + // + // + // + + // + // Supply Zones ... + if (drawSupplyZones) + { + // + has = HasSupplyZones(); + if (has) + { + // + count = CountSupplyZones(); + for (int i = 0; i < count; i++) + { + // + XCSupplyZoneObject *iObj; + isCreated = drawer.CreateSupplyZone( + supplyZones[i], + iObj // + ); + + // + if (isCreated) + { + mWorkingZoneObjects.Add(iObj); + } + } + } + } + + // + // Demand Zones ... + if (drawDemandZones) + { + // + has = HasDemandZones(); + if (has) + { + // + count = CountDemandZones(); + for (int i = 0; i < count; i++) + { + // + XCDemandZoneObject *iObj; + isCreated = drawer.CreateDemandZone( + demandZones[i], + iObj // + ); + + // + if (isCreated) + { + mWorkingZoneObjects.Add(iObj); + } + } + } + } + + // + // Support Zones ... + if (drawSupportZones) + { + // + has = HasSupportZones(); + if (has) + { + // + count = CountSupportZones(); + for (int i = 0; i < count; i++) + { + // + XCSupportZoneObject *iObj; + isCreated = drawer.CreateSupportZone( + supportZones[i], + iObj // + ); + + // + if (isCreated) + { + mWorkingZoneObjects.Add(iObj); + } + } + } + } + + // + // Resistance Zones ... + if (drawResistanceZones) + { + // + has = HasResistanceZones(); + if (has) + { + // + count = CountResistanceZones(); + for (int i = 0; i < count; i++) + { + // + XCResistanceZoneObject *iObj; + isCreated = drawer.CreateResistanceZone( + resistanceZones[i], + iObj // + ); + + // + if (isCreated) + { + mWorkingZoneObjects.Add(iObj); + } + } + } + } + + // + // + // + + // + // Waiting Zones ... + if (drawWaitingZones) + { + // + has = HasWaitingZones(); + if (has) + { + // + count = CountWaitingZones(); + for (int i = 0; i < count; i++) + { + // + XCBaseObject *objects[]; + int objectsCount = drawer.DrawOBFVG( + waitingZones[i], + objects // + ); + has = IsValidSize(objectsCount); + if (has) + { + // + for (int j = 0; j < objectsCount; j++) + { + mWaitingZoneObjects.Add(objects[j]); + } + } + } + } + } + + // + // Inside Zones ... + if (drawInsideZones) + { + // + // Zones ... + has = HasInsideZones(); + if (has) + { + // + count = CountInsideZones(); + for (int i = 0; i < count; i++) + { + // + XCBaseObject *objects[]; + int objectsCount = drawer.DrawOBFVG( + insideZones[i], + objects // + ); + + // + has = IsValidSize(objectsCount); + if (has) + { + // + for (int i = 0; i < objectsCount; i++) + { + mInsideZoneObjects.Add(objects[i]); + } + } + } + } + + // // + // // Boxes ... + // has = HasInsideBoxes(); + // if (has) + // { + // // + // count = CountInsideBoxes(); + // for (int i = 0; i < count; i++) + // { + // // + // XCBoxObject *object; + // bool isCreated = drawer.DrawBox( + // insideBoxes[i], + // object // + // ); + + // // + // if (isCreated) + // { + // mInsideZoneObjects.Add(object); + // } + // } + // } + } + + // + // Breaked Zones ... + if (drawBreakedZones) + { + // + has = HasBreakedZones(); + if (has) + { + // + count = CountBreakedZones(); + for (int i = 0; i < count; i++) + { + // + XCBaseObject *objects[]; + int objectsCount = drawer.DrawOBFVG( + breakedZones[i], + objects // + ); + + // + has = IsValidSize(objectsCount); + if (has) + { + // + for (int i = 0; i < objectsCount; i++) + { + mBreakedZoneObjects.Add(objects[i]); + } + } + } + } + + // // + // // Boxes ... + // has = HasBreakedBoxes(); + // if (has) + // { + // // + // count = CountBreakedBoxes(); + // for (int i = 0; i < count; i++) + // { + // // + // XCBoxObject *object; + // bool isCreated = drawer.DrawBox( + // breakedBoxes[i], + // object // + // ); + + // // + // if (isCreated) + // { + // mInsideZoneObjects.Add(object); + // } + // } + // } + } + + // + // + // + + // + // Quarters ... + has = IsValid(); + if (has) + { + // + double zoneUpper = supplyZone.Upper(); + double upper = supplyZone.Lower(); + + // + double lower = demandZone.Upper(); + double zoneLower = demandZone.Lower(); + + // + string prefix = "X121WZone_" + symbol + "_" + ToString(period); + + // + // Zone Upper ... + CChartObjectHLine *zoneUpperLine; + zoneUpperLine = new CChartObjectHLine(); + isCreated = zoneUpperLine.Create( + chartID, + prefix + "_ZoneTop", + subWindow, + zoneUpper // + ); + if (isCreated) + { + // + zoneUpperLine.Color(clrRed); + + // + mWaitingZoneObjects.Add(zoneUpperLine); + } + + // + // Zone Lower ... + CChartObjectHLine *zoneLowerLine; + zoneLowerLine = new CChartObjectHLine(); + isCreated = zoneLowerLine.Create( + chartID, + prefix + "_ZoneDown", + subWindow, + zoneLower // + ); + if (isCreated) + { + // + zoneLowerLine.Color(clrRed); + + // + mWaitingZoneObjects.Add(zoneLowerLine); + } + + // + // Upper ... + CChartObjectHLine *upperLine; + upperLine = new CChartObjectHLine(); + isCreated = upperLine.Create( + chartID, + prefix + "_Upper", + subWindow, + upper // + ); + if (isCreated) + { + // + upperLine.Color(clrLime); + + // + mWaitingZoneObjects.Add(upperLine); + } + + // + // Lower ... + CChartObjectHLine *lowerLine; + lowerLine = new CChartObjectHLine(); + isCreated = lowerLine.Create( + chartID, + prefix + "_Lower", + subWindow, + lower // + ); + if (isCreated) + { + // + lowerLine.Color(clrLime); + + // + mWaitingZoneObjects.Add(lowerLine); + } + + // + // Quarters ... + + // + // Quarter 1 ... + CChartObjectHLine *q1Line; + q1Line = new CChartObjectHLine(); + isCreated = q1Line.Create( + chartID, + prefix + "_Q1", + subWindow, + quarter1 // + ); + if (isCreated) + { + // + q1Line.Color(clrYellow); + + // + mWaitingZoneObjects.Add(q1Line); + } + + // + // Quarter 2 ... + CChartObjectHLine *q2Line; + q2Line = new CChartObjectHLine(); + isCreated = q2Line.Create( + chartID, + prefix + "_Q2", + subWindow, + quarter2 // + ); + if (isCreated) + { + // + q2Line.Color(clrYellow); + + // + mWaitingZoneObjects.Add(q2Line); + } + + // + // Quarter 3 ... + CChartObjectHLine *q3Line; + q3Line = new CChartObjectHLine(); + isCreated = q3Line.Create( + chartID, + prefix + "_Q3", + subWindow, + quarter3 // + ); + if (isCreated) + { + // + q3Line.Color(clrYellow); + + // + mWaitingZoneObjects.Add(q3Line); + } + } + } + + // +}; + +// +// Definitions ... +struct X121SMCStrategyXWZSignalConditions +{ + // + // Props ... + + // + string symbol; + ENUM_TIMEFRAMES period; + + // + double sl; + double reward; + double amountPercent; + ENUM_X_DIRECTION dir; + ENUM_X_POSITION_TYPES type; + + // + // Setup Props ... + + // + datetime setupTime; + datetime triggerTime; + + // + double pivot; + double point; + double sls[]; + double targets[]; + + // + XBoxZone signalBox; + + // + ENUM_X121SMC_XWZ_PRIORITY priority; + ENUM_X121SMC_XWZ_PROVIDERS provider; + + // + // Constructor ... + X121SMCStrategyXWZSignalConditions() + { + 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; + + // + ExtensionClean(); + + // + ZeroMemory(this); + } + + /** + * 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 ... + + /** + * Clean Additional Properties ... + */ + void ExtensionClean() + { + // + pivot = 0; + point = 0; + + // + reward = 0; + amountPercent = 0; + + // + Clean(sls); + Clean(targets); + signalBox.Clean(); + + // + provider = X121SMC_XWZ_PROVIDER_NONE; + } + + // + // + // + + // + void UpdateTo(datetime value = NULL) + { + // + value = NormalizeTime(value); + + // + int count = 0; + bool has = false; + } + + // +}; + +// +// Extension Functions ... + +/** + * Check an XOBFVG instance has Required Conditions ... + * + * @param zone: XOBFVG instance ... + * @param state: XPOIState instance ... + * @param conditions: X121Conditions instance ... + * + * @return ( bool ) + */ +bool DetectSelectedZoneConditions( + bool &isReversal, + XOBFVG &zone, + XPOIState &state, + X121Conditions &conditions // +) +{ + // + bool result = false; + + // + isReversal = false; + + // + result = + zone.IsValid() && + state.IsValid() && + state.HasChild(); + if (!result) + { + return result; + } + + // + bool isBullish = zone.IsBullish(); + bool isBearish = zone.IsBearish(); + + // + bool isBullishTrend = conditions.isTrendBullish || + conditions.isTrendSwitchedToBullish; + bool isBearishTrend = conditions.isTrendBearish || + conditions.isTrendSwitchedToBearish; + + // + double bullishScore = 0; + double bearishScore = 0; + double scoreMultiplier = 1.5; + conditions.GenerateScore( + bullishScore, + bearishScore // + ); + + // + bool isBullishScorePassed = bullishScore > 0 && + bearishScore >= 0 && + bullishScore > bearishScore * scoreMultiplier; + + // + bool isBearishScorePassed = bearishScore > 0 && + bullishScore >= 0 && + bearishScore > bullishScore * scoreMultiplier; + + // + // VWap ... + + // + double vwapFast = conditions.vwapFastBuffer[0]; + double vwapMid = conditions.vwapMidBuffer[0]; + double vwapSlow = conditions.vwapSlowBuffer[0]; + + // + bool isVWapInside = + // + vwapFast > zone.ob.Lower() && + vwapFast < zone.ob.Upper() + // + && + vwapMid > zone.ob.Lower() && + vwapMid < zone.ob.Upper() + // + ; + + // + bool isVWapBullish = + // + (conditions.isVWapBullishState && + conditions.isVWapSwitchedToBullishOrdered) + // + || + // + (conditions.isVWapBullishOrdered && + conditions.isVWapSwitchedToBullishState) + // + ; + + // + bool isVWapBearish = + // + (conditions.isVWapBearishState && + conditions.isVWapSwitchedToBearishOrdered) + // + || + // + (conditions.isVWapBearishOrdered && + conditions.isVWapSwitchedToBearishState) + // + ; + + // + // X3Ma ... + + // + double x3maFast = conditions.x3maFastBuffer[0]; + double x3maMid = conditions.x3maMidBuffer[0]; + double x3maSlow = conditions.x3maSlowBuffer[0]; + + // + bool isX3MaInside = + // + x3maFast > zone.ob.Lower() && + x3maFast < zone.ob.Upper() + // + && + x3maMid > zone.ob.Lower() && + x3maMid < zone.ob.Upper() + // + ; + + // + bool isX3MaBullish = + // + (conditions.isX3MaBullishState && + conditions.isX3MaSwitchedToBullishOrdered) + // + || + // + (conditions.isX3MaBullishOrdered && + conditions.isX3MaSwitchedToBullishState) + // + ; + + // + bool isX3MaBearish = + // + (conditions.isX3MaBearishState && + conditions.isX3MaSwitchedToBearishOrdered) + // + || + // + (conditions.isX3MaBearishOrdered && + conditions.isX3MaSwitchedToBearishState) + // + ; + + // + // + // + + // + bool isInside = + // + isVWapInside || + isX3MaInside + // + ; + + // + bool isVWap3MaBullish = + isVWapBullish || + isX3MaBullish; + + // + bool isVWap3MaBearish = + isVWapBearish || + isX3MaBearish; + + // + // + // + + // + bool isDirectionalBullishPassed = + // + isInside && + isBullish && + isBullishTrend && + isVWap3MaBullish && + isBullishScorePassed + // + ; + + // + bool isDirectionalBearishPassed = + // + isInside && + isBearish && + isBearishTrend && + isVWap3MaBearish && + isBearishScorePassed + // + ; + + // + bool isDirectionalPassed = + isDirectionalBullishPassed || + isDirectionalBearishPassed; + + // + bool isReversalBullishPassed = + // + isInside && + isBullish && + isBearishTrend && + isVWap3MaBearish && + isBearishScorePassed + // + ; + + // + bool isReversalBearishPassed = + // + isInside && + isBearish && + isBullishTrend && + isVWap3MaBullish && + isBullishScorePassed + // + ; + + // + bool isReversalPassed = isReversalBullishPassed || + isReversalBearishPassed; + + // + result = isReversalPassed || + isDirectionalPassed; + + // + if (result) + { + isReversal = isReversalPassed; + } + + // + return result; +} + +/** + * Detect Targets Based on Selected Zone for Specified type of Directions ... + * + * @param targets: double Collection ... + * @param selectedZone: XOBFVG instance, selected Zone ... + * @param forDir: ENUM_X_DIRECTION specified Position Direction ... + * @param workingone: X121SMCStrategyXWZWorkingZone instance, Specified Working Zone ... + * @param barIndex: int Specified Bar Index ... + * + * @return ( bool ) + */ +bool DetectSelectedZonesTargets( + double &targets[], + XOBFVG &selectedZone, + ENUM_X_DIRECTION forDir, + ENUM_X121SMC_XWZ_PRIORITY forPriority, + X121SMCStrategyXWZWorkingZone &workingZone, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + Clean(targets); + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (barIndex == 0) + { + barIndex++; + } + + // + result = + // + selectedZone.IsValid() && + HasDirection(forDir) && + workingZone.IsValid() && + forPriority != X121SMC_XWZ_PRIORITY_NONE + // + ; + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + XOHCL cBar; + result = cBar.Init( + workingZone.symbol, + workingZone.period, + barIndex // + ); + if (!result) + { + // + cBar.Clean(); + return result; + } + + // + int idx = -1; + bool has = false; + XOBFVG tmpZones[]; + + // + // Based On Waiting Zones ... + has = workingZone.HasWaitingZones(); + if (has) + { + // + Copy( + workingZone.waitingZones, + tmpZones // + ); + + // + while (HasChild(tmpZones)) + { + // + XOBFVG iOBFVG; + + // + idx = GetYoungest(tmpZones); + if (!IsValidIndex(idx)) + { + // + iOBFVG.Clean(); + break; + } + + // + iOBFVG = tmpZones[idx]; + ArrayRemove( + tmpZones, + idx, + 1 // + ); + + // + double iTarget = + isBullish + ? iOBFVG.ob.Lower() + : iOBFVG.ob.Upper(); + + // + has = + isBullish + ? cBar.high < iTarget + : cBar.low > iTarget; + + // + if (has) + { + // + Add( + iTarget, + targets // + ); + } + + // + iOBFVG.Clean(); + } + + // + Clean(tmpZones); + } + + // + // Based On Breaked Zones ... + has = workingZone.HasBreakedZones(); + if (has) + { + Copy( + workingZone.breakedZones, + tmpZones // + ); + + // + while (HasChild(tmpZones)) + { + // + XOBFVG iOBFVG; + + // + idx = GetYoungest(tmpZones); + if (!IsValidIndex(idx)) + { + // + iOBFVG.Clean(); + break; + } + + // + iOBFVG = tmpZones[idx]; + ArrayRemove( + tmpZones, + idx, + 1 // + ); + + // + double iTarget = + isBullish + ? iOBFVG.ob.Lower() + : iOBFVG.ob.Upper(); + + // + has = + isBullish + ? cBar.high < iTarget + : cBar.low > iTarget; + + // + if (has) + { + // + Add( + iTarget, + targets // + ); + } + + // + iOBFVG.Clean(); + } + + // + Clean(tmpZones); + } + + // + // Based On Priority ... + has = forPriority != X121SMC_XWZ_PRIORITY_NONE; + if (has) + { + // + switch (forPriority) + { + // + case X121SMC_XWZ_PRIORITY_WEAK: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + } + break; + + // + case X121SMC_XWZ_PRIORITY_LOW: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter1, + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter3, + targets // + ); + } + break; + + // + case X121SMC_XWZ_PRIORITY_REGULAR: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter1, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter3, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + } + break; + + // + case X121SMC_XWZ_PRIORITY_HIGH: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter1, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + + // + // High ... + Add( + workingZone.quarter3, + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter3, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + + // + // High ... + Add( + workingZone.quarter1, + targets // + ); + } + break; + + // + case X121SMC_XWZ_PRIORITY_STRONG_HIGH: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter1, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + + // + // High ... + Add( + workingZone.quarter3, + targets // + ); + + // + // Strong High ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter3, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + + // + // High ... + Add( + workingZone.quarter1, + targets // + ); + + // + // Strong High ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + } + break; + } + } + + // + result = HasChild(targets); + + // + // Cleanup ... + cBar.Clean(); + Clean(tmpZones); + + // + return result; +} + +/** + * Detect Targets Based on Selected Zone for Specified type of Directions ... + * + * @param targets: double Collection ... + * @param selectedZone: XBoxZone instance, selected Zone ... + * @param forDir: ENUM_X_DIRECTION specified Position Direction ... + * @param workingone: X121SMCStrategyXWZWorkingZone instance, Specified Working Zone ... + * @param barIndex: int Specified Bar Index ... + * + * @return ( bool ) + */ +bool DetectSelectedZonesTargets( + double &targets[], + XBoxZone &selectedZone, + ENUM_X_DIRECTION forDir, + ENUM_X121SMC_XWZ_PRIORITY forPriority, + X121SMCStrategyXWZWorkingZone &workingZone, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + Clean(targets); + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (barIndex == 0) + { + barIndex++; + } + + // + result = + // + selectedZone.IsValid() && + HasDirection(forDir) && + workingZone.IsValid() && + forPriority != X121SMC_XWZ_PRIORITY_NONE + // + ; + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + XOHCL cBar; + result = cBar.Init( + workingZone.symbol, + workingZone.period, + barIndex // + ); + if (!result) + { + // + cBar.Clean(); + return result; + } + + // + int idx = -1; + bool has = false; + XOBFVG tmpZones[]; + + // + // Based On Waiting Zones ... + has = workingZone.HasWaitingZones(); + if (has) + { + // + Copy( + workingZone.waitingZones, + tmpZones // + ); + + // + while (HasChild(tmpZones)) + { + // + XOBFVG iOBFVG; + + // + idx = GetYoungest(tmpZones); + if (!IsValidIndex(idx)) + { + // + iOBFVG.Clean(); + break; + } + + // + iOBFVG = tmpZones[idx]; + ArrayRemove( + tmpZones, + idx, + 1 // + ); + + // + double iTarget = + isBullish + ? iOBFVG.ob.Lower() + : iOBFVG.ob.Upper(); + + // + has = + isBullish + ? cBar.high < iTarget + : cBar.low > iTarget; + + // + if (has) + { + // + Add( + iTarget, + targets // + ); + } + + // + iOBFVG.Clean(); + } + + // + Clean(tmpZones); + } + + // + // Based On Breaked Zones ... + has = workingZone.HasBreakedZones(); + if (has) + { + Copy( + workingZone.breakedZones, + tmpZones // + ); + + // + while (HasChild(tmpZones)) + { + // + XOBFVG iOBFVG; + + // + idx = GetYoungest(tmpZones); + if (!IsValidIndex(idx)) + { + // + iOBFVG.Clean(); + break; + } + + // + iOBFVG = tmpZones[idx]; + ArrayRemove( + tmpZones, + idx, + 1 // + ); + + // + double iTarget = + isBullish + ? iOBFVG.ob.Lower() + : iOBFVG.ob.Upper(); + + // + has = + isBullish + ? cBar.high < iTarget + : cBar.low > iTarget; + + // + if (has) + { + // + Add( + iTarget, + targets // + ); + } + + // + iOBFVG.Clean(); + } + + // + Clean(tmpZones); + } + + // + // Based On Priority ... + has = forPriority != X121SMC_XWZ_PRIORITY_NONE; + if (has) + { + // + switch (forPriority) + { + // + case X121SMC_XWZ_PRIORITY_WEAK: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + } + break; + + // + case X121SMC_XWZ_PRIORITY_LOW: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter1, + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter3, + targets // + ); + } + break; + + // + case X121SMC_XWZ_PRIORITY_REGULAR: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter1, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter3, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + } + break; + + // + case X121SMC_XWZ_PRIORITY_HIGH: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter1, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + + // + // High ... + Add( + workingZone.quarter3, + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter3, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + + // + // High ... + Add( + workingZone.quarter1, + targets // + ); + } + break; + + // + case X121SMC_XWZ_PRIORITY_STRONG_HIGH: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter1, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + + // + // High ... + Add( + workingZone.quarter3, + targets // + ); + + // + // Strong High ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter3, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + + // + // High ... + Add( + workingZone.quarter1, + targets // + ); + + // + // Strong High ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + } + break; + } + } + + // + result = HasChild(targets); + + // + // Cleanup ... + cBar.Clean(); + Clean(tmpZones); + + // + return result; +} + +/** + * Detect SL Candidates Based on Selected Zone for Specified type of Directions ... + * + * @param sls: double Collection ... + * @param selectedZone: XOBFVG instance, selected Zone ... + * @param forDir: ENUM_X_DIRECTION specified Position Direction ... + * @param workingZone: X121SMCStrategyXWZWorkingZone instance, Specified Working Zone ... + * @param barIndex: int Specified Bar Index ... + * @param maxAllowedSLDistanceInPoint: doube max Allowe SL distance ... + * + * @return ( bool ) + */ +bool DetectSelectedZoneSLCandidates( + double &sls[], + XOBFVG &selectedZone, + ENUM_X_DIRECTION forDir, + X121SMCStrategyXWZWorkingZone &workingZone, + X121Conditions &conditions, + int barIndex = 0, + double maxAllowedSLDistanceInPoint = 300 // +) +{ + // + bool result = false; + + // + Clean(sls); + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (barIndex == 0) + { + barIndex++; + } + + // + result = + // + selectedZone.IsValid() && + HasDirection(forDir) && + workingZone.IsValid() + // + ; + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + double pivot = + isBullish + ? selectedZone.ob.Lower() + : selectedZone.ob.Upper(); + double points = GetPoints(workingZone.symbol); + + // + XOHCL cBar; + result = cBar.Init( + workingZone.symbol, + workingZone.period, + barIndex // + ); + if (!result) + { + // + cBar.Clean(); + return result; + } + + // + int idx = -1; + bool has = false; + + // + double pvSL = isBullish + ? conditions.valesBuffer[0] + : conditions.peaksBuffer[1]; + + // + Add( + pvSL, + sls // + ); + + // + // Based On Passed Bars ... + // XOHCL passedBar; + // bool isPassed = false; + // bool isBodyState = false; + // ENUM_X_DIRECTION passedDir = selectedZone.GetDirection(); + + // // + // // Started Bar ... + // isPassed = selectedZone.ob.IsStarted( + // passedDir, + // passedBar, + // isBodyState // + // ); + // if (isPassed) + // { + // // + // double iSL = + // isBullish + // ? passedBar.low + // : passedBar.high; + // double iSLDiff = MathAbs(iSL - pivot); + // has = + // iSLDiff > 0 && + // iSLDiff <= maxAllowedSLDistanceInPoint * points; + // if (has) + // { + // // + // Add( + // iSL, + // sls // + // ); + // } + // } + + // // + // // Activation Bar ... + // passedBar.Clean(); + // isPassed = selectedZone.ob.IsActivated( + // passedDir, + // passedBar, + // isBodyState // + // ); + // if (isPassed) + // { + // // + // double iSL = + // isBullish + // ? passedBar.low + // : passedBar.high; + // double iSLDiff = MathAbs(iSL - pivot); + // has = + // iSLDiff > 0 && + // iSLDiff <= maxAllowedSLDistanceInPoint * points; + // if (has) + // { + // // + // Add( + // iSL, + // sls // + // ); + // } + // } + + // // + // // Worked Bar ... + // passedBar.Clean(); + // isPassed = selectedZone.ob.IsActivated( + // passedDir, + // passedBar, + // isBodyState // + // ); + // if (isPassed) + // { + // // + // double iSL = + // isBullish + // ? passedBar.low + // : passedBar.high; + // double iSLDiff = MathAbs(iSL - pivot); + // has = + // iSLDiff > 0 && + // iSLDiff <= maxAllowedSLDistanceInPoint * points; + // if (has) + // { + // // + // Add( + // iSL, + // sls // + // ); + // } + // } + + // // + // // Breaked Bar ... + // passedBar.Clean(); + // isPassed = selectedZone.ob.IsActivated( + // passedDir, + // passedBar, + // isBodyState // + // ); + // if (isPassed) + // { + // // + // double iSL = + // isBullish + // ? passedBar.low + // : passedBar.high; + // double iSLDiff = MathAbs(iSL - pivot); + // has = + // iSLDiff > 0 && + // iSLDiff <= maxAllowedSLDistanceInPoint * points; + // if (has) + // { + // // + // Add( + // iSL, + // sls // + // ); + // } + // } + + // + // Based On Consolidation Zones ... + has = workingZone.HasConsolidationZones(); + if (has) + { + // + XConsolidationZone tmpZones[]; + Copy( + workingZone.consolidationZones, + tmpZones // + ); + XConsolidationZone selectedConsolidationZone; + + // + while (HasChild(tmpZones)) + { + // + idx = GetYoungest(tmpZones); + if (!IsValidIndex(idx)) + { + break; + } + + // + XConsolidationZone iZone = tmpZones[idx]; + + // + ArrayRemove( + tmpZones, + idx, + 1 // + ); + + // + has = + !selectedConsolidationZone.IsValid() + ? isBullish + ? cBar.low < iZone.upper + : cBar.high < iZone.lower + : isBullish + ? selectedConsolidationZone.lower < iZone.lower + : selectedConsolidationZone.upper > iZone.upper; + if (has) + { + // + selectedConsolidationZone = iZone; + iZone.Clean(); + break; + } + + // + iZone.Clean(); + } + + // + Clean(tmpZones); + has = selectedConsolidationZone.IsValid(); + if (has) + { + // + double iSL = + isBullish + ? selectedConsolidationZone.lower + : selectedConsolidationZone.upper; + double iSLDiff = MathAbs(iSL - pivot); + has = + iSLDiff > 0 && + iSLDiff <= maxAllowedSLDistanceInPoint * points; + if (has) + { + // + Add( + iSL, + sls // + ); + } + } + } + + // + // Based On Supply and Demand Zones ... + + // + // Demand Zones ... + has = workingZone.HasDemandZones(); + if (has) + { + // + XCDemandZone *tmpZones[]; + Copy( + workingZone.demandZones, + tmpZones // + ); + XCDemandZone *selectedDemand = NULL; + + // + while (HasChild(tmpZones)) + { + // + idx = GetLowest(tmpZones); + has = IsValidIndex(idx); + if (!has) + { + break; + } + + // + XCDemandZone *iZone = tmpZones[idx]; + ArrayRemove( + tmpZones, + idx, + 1 // + ); + + // + // Validate Zone ... + has = + isBullish + ? IsBelowDiff( + iZone, + selectedZone.ob, + true // Ignore Inside ... + ) + : IsAboveDiff( + iZone, + selectedZone.ob, + true // Ignore Inside ... + ); + if (!has) + { + continue; + } + + // + has = + selectedDemand == NULL + ? true + : isBullish + ? selectedDemand.Lower() < iZone.Lower() + : selectedDemand.Upper() > iZone.Upper(); + if (!has) + { + continue; + } + + // + selectedDemand = iZone; + } + + // + has = selectedDemand != NULL; + if (has) + { + // + double iSL = + isBullish + ? selectedDemand.Lower() + : selectedDemand.Upper(); + double iSLDiff = MathAbs(iSL - pivot); + has = + iSLDiff > 0 && + iSLDiff <= maxAllowedSLDistanceInPoint * points; + if (has) + { + // + Add( + iSL, + sls // + ); + } + } + + // + Clean(tmpZones); + ZeroMemory(selectedDemand); + } + + // + // Support Zones ... + // has = workingZone.HasSupportZones(); + // if (has) + // { + // // + // XCSupportZone *tmpZones[]; + // Copy( + // workingZone.supportZones, + // tmpZones // + // ); + // XCSupportZone *selectedSupport = NULL; + + // // + // while (HasChild(tmpZones)) + // { + // // + // idx = GetLowest(tmpZones); + // has = IsValidIndex(idx); + // if (!has) + // { + // break; + // } + + // // + // XCSupportZone *iZone = tmpZones[idx]; + // ArrayRemove( + // tmpZones, + // idx, + // 1 // + // ); + + // // + // // Validate Zone ... + // has = + // isBullish + // ? IsBelowDiff( + // iZone, + // selectedZone.ob, + // true // Ignore Inside ... + // ) + // : IsAboveDiff( + // iZone, + // selectedZone.ob, + // true // Ignore Inside ... + // ); + // if (!has) + // { + // continue; + // } + + // // + // has = + // selectedSupport == NULL + // ? true + // : isBullish + // ? selectedSupport.Lower() < iZone.Lower() + // : selectedSupport.Upper() > iZone.Upper(); + // if (!has) + // { + // continue; + // } + + // // + // selectedSupport = iZone; + + // // + // } + + // // + // has = selectedSupport != NULL; + // if (has) + // { + // // + // double iSL = isBullish + // ? selectedSupport.Lower() + // : selectedSupport.Upper(); + // double iSLDiff = MathAbs(iSL - pivot); + // has = + // iSLDiff > 0 && + // iSLDiff <= maxAllowedSLDistanceInPoint * points; + // if (has) + // { + // // + // Add( + // iSL, + // sls // + // ); + // } + // } + + // // + // Clean(tmpZones); + // ZeroMemory(selectedSupport); + // } + + // + // Supply Zones ... + has = workingZone.HasSupplyZones(); + if (has) + { + // + XCSupplyZone *tmpZones[]; + Copy( + workingZone.supplyZones, + tmpZones // + ); + XCSupplyZone *selectedSupply = NULL; + + // + while (HasChild(tmpZones)) + { + // + idx = GetHighest(tmpZones); + has = IsValidIndex(idx); + if (!has) + { + break; + } + + // + XCSupplyZone *iZone = tmpZones[idx]; + ArrayRemove( + tmpZones, + idx, + 1 // + ); + + // + // Validate Zone ... + has = + !isBullish + ? IsAboveDiff( + iZone, + selectedZone.ob, + true // Ignore Inside ... + ) + : IsBelowDiff( + iZone, + selectedZone.ob, + true // Ignore Inside ... + ); + if (!has) + { + continue; + } + + // + has = + selectedSupply == NULL + ? true + : !isBullish + ? selectedSupply.Upper() > iZone.Upper() + : selectedSupply.Lower() < iZone.Lower(); + if (!has) + { + continue; + } + + // + selectedSupply = iZone; + + // + } + + // + has = selectedSupply != NULL; + if (has) + { + // + double iSL = + !isBullish + ? selectedSupply.Upper() + : selectedSupply.Lower(); + double iSLDiff = MathAbs(iSL - pivot); + has = + iSLDiff > 0 && + iSLDiff <= maxAllowedSLDistanceInPoint * points; + if (has) + { + // + Add( + iSL, + sls // + ); + } + } + + // + Clean(tmpZones); + ZeroMemory(selectedSupply); + } + + // + // Resistance Zones ... + // has = workingZone.HasDemandZones(); + // if (has) + // { + // // + // XCResistanceZone *tmpZones[]; + // Copy( + // workingZone.resistanceZones, + // tmpZones // + // ); + // XCResistanceZone *selectedResistance = NULL; + + // // + // while (HasChild(tmpZones)) + // { + // // + // idx = GetHighest(tmpZones); + // has = IsValidIndex(idx); + // if (!has) + // { + // break; + // } + + // // + // XCResistanceZone *iZone = tmpZones[idx]; + // ArrayRemove( + // tmpZones, + // idx, + // 1 // + // ); + + // // + // // Validate Zone ... + // has = + // !isBullish + // ? IsAboveDiff( + // iZone, + // selectedZone.ob, + // true // Ignore Inside ... + // ) + // : IsBelowDiff( + // iZone, + // selectedZone.ob, + // true // Ignore Inside ... + // ); + // if (!has) + // { + // continue; + // } + + // // + // has = + // selectedResistance == NULL + // ? true + // : !isBullish + // ? selectedResistance.Upper() < iZone.Upper() + // : selectedResistance.Lower() > iZone.Lower(); + // if (!has) + // { + // continue; + // } + + // // + // selectedResistance = iZone; + + // // + // } + + // // + // has = selectedResistance != NULL; + // if (has) + // { + // // + // double iSL = + // !isBullish + // ? selectedResistance.Upper() + // : selectedResistance.Lower(); + // double iSLDiff = MathAbs(iSL - pivot); + // has = + // iSLDiff > 0 && + // iSLDiff <= maxAllowedSLDistanceInPoint * points; + // if (has) + // { + // // + // Add( + // iSL, + // sls // + // ); + // } + // } + + // // + // Clean(tmpZones); + // ZeroMemory(selectedResistance); + // } + + // + // Cleanp Resources ... + + // + cBar.Clean(); + // passedBar.Clean(); + result = HasChild(sls); + + // + return result; +} + + +// \ No newline at end of file diff --git a/BKPS/14031218/Documents/BKP/x-121.smc.xwz.signal.lib.mq5 b/BKPS/14031218/Documents/BKP/x-121.smc.xwz.signal.lib.mq5 new file mode 100644 index 0000000..dd8835d --- /dev/null +++ b/BKPS/14031218/Documents/BKP/x-121.smc.xwz.signal.lib.mq5 @@ -0,0 +1,1582 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 X121 SMC Signal Class +// ------------------------------------------------- +// Name: XWZ +// 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 "../../Libraries/x-trade.lib" +#include "../Classes/x-121.smc.market.cycle.helper.class.mq5" +#include "../Libraries/x-121.smc.guard.lib.mq5" +#include "../Libraries/x-121.smc.lib.mq5" + +// +enum ENUM_X121SMC_XWZ_PROVIDERS +{ + X121SMC_XWZ_PROVIDER_NONE, + X121SMC_XWZ_PROVIDER_ACTIVATED_ZONE, + X121SMC_XWZ_PROVIDER_ACTIVATED_CHOCH, + X121SMC_XWZ_PROVIDER_PRICE_INSIDE_ZONE, +}; + +// +enum ENUM_X121SMC_XWZ_PRIORITY +{ + X121SMC_XWZ_PRIORITY_NONE, + X121SMC_XWZ_PRIORITY_WEAK, + X121SMC_XWZ_PRIORITY_LOW, + X121SMC_XWZ_PRIORITY_REGULAR, + X121SMC_XWZ_PRIORITY_HIGH, + X121SMC_XWZ_PRIORITY_STRONG_HIGH, +}; + +// +struct X121SMCStrategyXWZWorkingZone +{ + // + // Props ... + + // + string symbol; + ENUM_TIMEFRAMES period; + + // + XCSupplyZone *supplyZone; + XCDemandZone *demandZone; + + // + double quarter1; + double quarter2; + double quarter3; + + // + XOBFVG orderFlow[]; + XOBFVGPivot swings[]; + XOBFVG brokenOrderFlow[]; + CChartObjectTrend *orderFlowTrend; + + // + XCSupplyZone *supplyZones[]; + XCDemandZone *demandZones[]; + + // + // Constructor ... + X121SMCStrategyXWZWorkingZone() + { + Clean(); + } + + // + // Tools ... + + // + void Clean() + { + // + quarter1 = 0; + quarter2 = 0; + quarter3 = 0; + + // + symbol = NULL; + period = NULL; + + // + Clean(orderFlow); + Clean(brokenOrderFlow); + + // + Clean(swings); + ZeroMemory(supplyZone); + ZeroMemory(demandZone); + + // + if (orderFlowTrend != NULL) + { + orderFlowTrend.Delete(); + } + ZeroMemory(orderFlowTrend); + + // + ZeroMemory(this); + } + + // + bool IsValid() + { + // + bool result = false; + + // + result = + // + quarter1 > 0 && + quarter2 > 0 && + quarter3 > 0 && + HasSupplyZone() && + HasDemandZone() && + quarter1 > quarter2 && + quarter2 > quarter3 + // + ; + + // + return result; + } + + // + bool HasSupplyZone() + { + return supplyZone != NULL && + supplyZone.IsValid(); + } + + // + bool HasDemandZone() + { + return demandZone != NULL && + demandZone.IsValid(); + } + + // + // + // + + // + bool HasOrderFlow() + { + // + bool result = false; + + // + result = IsValid() && + HasChild(orderFlow); + + // + return result; + } + + // + bool HasOrderFlow( + ENUM_X_DIRECTION &orderFlowDir // + ) + { + // + bool result = false; + + // + result = IsValid() && + HasChild(orderFlow); + if (result) + { + orderFlowDir = orderFlow[0].GetDirection(); + } + + // + return result; + } + + // + int CountOrderFlow() + { + return ArraySize(orderFlow); + } + + // + int GetSwings( + XOBFVGPivot &pivots[] // + ) + { + // + int result = 0; + + // + Clean(pivots); + + // + int count = 0; + bool has = false; + + // + has = HasOrderFlow(); + if (!has) + { + return result; + } + + // + count = CountOrderFlow(); + for (int i = 0; i < count; i++) + { + // + XOBFVGPivot iPivots[]; + int iPivotsCount = orderFlow[i] + .GetSwings(iPivots); + bool hasPivots = IsValidSize(iPivotsCount); + if (hasPivots) + { + // + Copy( + iPivots, + pivots, + false // + ); + } + + // + Clean(iPivots); + } + + // + result = ArraySize(pivots); + + // + return result; + } + + // + double GetOrderFlowTrendLinePrice( + int barIndex = 0, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + double result = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + if (!IsValid() || + !HasOrderFlow() || + orderFlowTrend == NULL) + { + return result; + } + + // + datetime time = iTime( + symbol, + forPeriod, + barIndex // + ); + + // + result = ObjectGetValueByTime( + orderFlowTrend.ChartId(), + orderFlowTrend.Name(), + time // + ); + + // + return result; + } + + // + int DetectOrderFlow( + string forSymbol, + ENUM_TIMEFRAMES forPeriod, + ENUM_X_DIRECTION &orderFlowDir, + XPOIState <fState, + XPOIState &htfState, + XPOIState &mtfState, + XPOIState &stfState // + ) + { + // + int result = 0; + + // + Clean(orderFlow); + orderFlowDir = X_DIRECTION_NONE; + + // + bool isValid = + // + IsValid(forSymbol) && + IsValid(forPeriod) && + ltfState.HasChild() && + htfState.HasChild() && + mtfState.HasChild() && + stfState.HasChild() + // + ; + if (!isValid) + { + return result; + } + + // + // Find Working Zone ... + bool hasWorkingZone = IsValid(); + if (!hasWorkingZone) + { + // + symbol = forSymbol; + period = forPeriod; + + // + int idx = -1; + bool has = false; + + // + has = ltfState.HasSupplyZones(); + if (has) + { + // + idx = GetHighest(ltfState.supplyZones); + if (IsValidIndex(idx)) + { + supplyZone = ltfState.supplyZones[idx]; + } + } + + // + has = ltfState.HasDemandZones(); + if (has) + { + // + idx = GetLowest(ltfState.demandZones); + if (IsValidIndex(idx)) + { + demandZone = ltfState.demandZones[idx]; + } + } + + // + hasWorkingZone = HasSupplyZone() && + HasDemandZone(); + if (hasWorkingZone) + { + // + double upper = supplyZone.Lower(); + double lower = demandZone.Upper(); + + // + double delta = ((upper - lower) / 100) * 25; + + // + quarter1 = upper - (1 * delta); + quarter2 = upper - (2 * delta); + quarter3 = upper - (3 * delta); + + // + hasWorkingZone = IsValid(); + } + } + + // + if (!hasWorkingZone) + { + return result; + } + + // + // Bullish OBFVGs ... + XOBFVG bullOBFVGs[]; + int bullOBFVGsCount = ExtractOBFVGZones( + htfState, + mtfState, + stfState, + bullOBFVGs, + X_DIRECTION_BULLISH, + NULL, // For Period ... + // + // Start ... + XZONE_STATE_PASSED, + true, // Force Body Out ... + // + // Activation ... + XZONE_STATE_PASSED, + true, // Force Body In ... + // + // Breaktion ... + XZONE_STATE_FAILED, + false, // Force Body In ... + // + // Works ... + XZONE_STATE_PASSED, + true, // Force Body Out ... + // + true, // Apply Sort ... + true, // From Filter ... + true, // Place Filter ... + // + true, // Ignore Inside in Place Filter ... + // + true, // Detect Inside OB POI(s) ... + true, // Detect Inside FVG POI(s) ... + true // Apply From Filter to Selected POI(s) ... + ); + bool hasBullOBFVGs = IsValidSize(bullOBFVGsCount); + + // + // Bearish OBFVGs ... + XOBFVG bearOBFVGs[]; + int bearOBFVGsCount = ExtractOBFVGZones( + htfState, + mtfState, + stfState, + bearOBFVGs, + X_DIRECTION_BEARISH, + NULL, // For Period ... + // + // Start ... + XZONE_STATE_PASSED, + true, // Force Body Out ... + // + // Activation ... + XZONE_STATE_PASSED, + true, // Force Body In ... + // + // Breaktion ... + XZONE_STATE_FAILED, + false, // Force Body In ... + // + // Works ... + XZONE_STATE_PASSED, + true, // Force Body Out ... + // + true, // Apply Sort ... + true, // From Filter ... + true, // Place Filter ... + // + true, // Ignore Inside in Place Filter ... + // + true, // Detect Inside OB POI(s) ... + true, // Detect Inside FVG POI(s) ... + true // Apply From Filter to Selected POI(s) ... + ); + bool hasBearOBFVGs = IsValidSize(bearOBFVGsCount); + + // + XOBFVG lastBroken; + bool hasBroken = false; + int idx = GetYoungest(brokenOrderFlow); + if (IsValidIndex(idx)) + { + // + lastBroken = brokenOrderFlow[idx]; + hasBroken = lastBroken.IsValid(); + } + + // + bool hasOrderFlow = hasBearOBFVGs || + hasBullOBFVGs; + if (hasOrderFlow) + { + // + // Vlidate ... + isValid = + // + (hasBullOBFVGs && + !hasBearOBFVGs && + bullOBFVGsCount >= 1) + // + || + // + (hasBearOBFVGs && + !hasBullOBFVGs && + bearOBFVGsCount >= 1) + // + ; + + // + if (isValid) + { + // + if (hasBullOBFVGs) + { + // + Copy( + bullOBFVGs, + orderFlow // + ); + } + else if (hasBearOBFVGs) + { + // + Copy( + bearOBFVGs, + orderFlow // + ); + } + + // + orderFlowDir = + hasBullOBFVGs + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + bool isPlacePassed = true; + if (hasBroken) + { + // + bool isBullish = IsBullish(orderFlowDir); + + // + idx = GetYoungest(orderFlow); + bool hasYounget = IsValidIndex(idx); + + // + isPlacePassed = + ArraySize(orderFlow) > 1 + ? true + : isBullish + ? (IsAbove( + orderFlow[idx].ob, + lastBroken.ob, + true // Ignore Inside ... + )) + : (IsBelow( + orderFlow[idx].ob, + lastBroken.ob, + true // Ignore Inside + )); + + // + Clean(brokenOrderFlow); + AddRef( + orderFlow[idx], + brokenOrderFlow // + ); + } + + // + if (!isPlacePassed) + { + // + Clean(orderFlow); + orderFlowDir = X_DIRECTION_NONE; + } + + // + result = ArraySize(orderFlow); + } + } + + // + Clean(bullOBFVGs); + Clean(bearOBFVGs); + + // + lastBroken.Clean(); + + // + if (IsValidSize(result)) + { + // + int count = GetSwings(swings); + bool has = count >= 2; + bool isBullish = IsBullish(orderFlowDir); + if (has) + { + // + // Get Max / Min ... + double max = 0; + double min = 0; + datetime maxAt = NULL; + datetime minAt = NULL; + for (int i = 0; i < count; i++) + { + // + XOBFVGPivot iPivot = swings[i]; + + // + if (!iPivot.IsValid()) + { + // + iPivot.Clean(); + continue; + } + + // + // Min ... + bool canSetMin = + min == 0 + ? true + : min > iPivot.value; + if (canSetMin) + { + // + minAt = iPivot.at; + min = iPivot.value; + } + + // + // Max ... + bool canSetMax = + max == 0 + ? true + : max < iPivot.value; + if (canSetMax) + { + // + maxAt = iPivot.at; + max = iPivot.value; + } + + // + iPivot.Clean(); + } + + // + double price1 = + isBullish + ? min + : max; + double price2 = + isBullish + ? max + : min; + datetime time1 = + isBullish + ? minAt + : maxAt; + datetime time2 = + isBullish + ? maxAt + : minAt; + + // + color clrTrend = clrNONE; + + // + string trendName = + "XORDFLW" + ToString(orderFlowDir) + "_" + "XTRNDL_" + + ToString(period) + "_" + + ToString(price1) + "_" + + ToString(price2) + "_"; + + // + orderFlowTrend = new CChartObjectTrend(); + has = orderFlowTrend.Create( + 0, + trendName, + 0, + time1, + price1, + time2, + price2 // + ); + + // + if (has) + { + // + orderFlowTrend.Width(1); + orderFlowTrend.Color(clrTrend); + orderFlowTrend.RayRight(true); + } + } + } + + // + return result; + } + + // + void AddOrderFlowItem( + XOBFVG &orderItem // + ) + { + // + ENUM_X_DIRECTION trend; + if (!HasOrderFlow(trend)) + { + return; + } + + // + bool isSameDir = orderItem + .GetDirection() == trend; + if (!isSameDir) + { + return; + } + + // + bool isBullish = IsBullish(trend); + + // + AddRef( + orderItem, + orderFlow // + ); + + // + Sort( + orderFlow, + trend, + true // Ignore Inside ... + ); + } + + // + bool IsDestroyed( + int barIndex = 0, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init( + symbol, + period, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + XOHCL cBar; + result = bar.GetPreviousBar(cBar); + if (!result) + { + // + bar.Clean(); + cBar.Clean(); + + // + return result; + } + + // + bool isSupplyZoneBreaked = + // + bar.low > supplyZone.Upper() && + cBar.low > supplyZone.Upper() + // + ; + + // + bool isDemandZoneBreaked = + // + bar.high < demandZone.Lower() && + cBar.high < demandZone.Lower() + // + ; + + // + bar.Clean(); + cBar.Clean(); + + // + result = isSupplyZoneBreaked || + isDemandZoneBreaked; + + // + return result; + } + + // + bool IsOrderFlowBreaked( + int &breakedIndex, + bool forceOBBreake = false, + bool forceFVGBreake = false, + int barIndex = 0, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + breakedIndex = -1; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + ENUM_X_DIRECTION orderFlowDir; + result = HasOrderFlow(orderFlowDir); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init( + symbol, + forPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + bool isBullish = IsBullish(orderFlowDir); + + // + int idx = + isBullish + ? GetHighest(orderFlow) + : GetLowest(orderFlow); + result = IsValidIndex(idx); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + XOHCL obBreakerBar; + bool isOBBodyOut = false; + bool isOBBreaked = orderFlow[idx].ob.IsBreaked( + orderFlowDir, + obBreakerBar, + isOBBodyOut, + false, // Ignore Start ... + false, // Started Bar Body Out ... + forPeriod // + ); + + // + if (!isOBBreaked) + { + obBreakerBar.Clean(); + } + + // + XOHCL fvgBreakerBar; + bool isFVGBodyOut = false; + bool isFVGBreaked = orderFlow[idx].fvg.IsBreaked( + orderFlowDir, + fvgBreakerBar, + isFVGBodyOut, + false, // Ignore Start ... + true, // Started Bar Body Out ... + forPeriod // + ); + + // + if (!isFVGBreaked) + { + fvgBreakerBar.Clean(); + } + + // + isOBBreaked = + obBreakerBar.IsValid(); + + // + isFVGBreaked = + fvgBreakerBar.IsValid(); + + // + if ((forceOBBreake && forceFVGBreake) || + (!forceOBBreake && !forceFVGBreake)) + { + // + result = isOBBreaked || + isFVGBreaked; + } + else if (forceOBBreake) + { + result = isOBBreaked; + } + else if (forceFVGBreake) + { + result = isFVGBreaked; + } + + // + if (result) + { + breakedIndex = idx; + } + + // + bar.Clean(); + obBreakerBar.Clean(); + fvgBreakerBar.Clean(); + + // + return result; + } + + // + bool DetectPriority( + ENUM_X121SMC_XWZ_PRIORITY &priority, + ENUM_X_DIRECTION forDir, + int barIndex = 0, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + priority = X121SMC_XWZ_PRIORITY_NONE; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + result = IsValid() && + HasDirection(forDir); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + XOHCL bar; + result = bar.Init( + symbol, + forPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + if (bar.high < supplyZone.Upper() && + bar.low > supplyZone.Lower()) + { + // + priority = + isBullish + ? X121SMC_XWZ_PRIORITY_NONE + : X121SMC_XWZ_PRIORITY_STRONG_HIGH; + } + else if (bar.high < supplyZone.Lower() && + bar.low > quarter1) + { + // + priority = + isBullish + ? X121SMC_XWZ_PRIORITY_WEAK + : X121SMC_XWZ_PRIORITY_HIGH; + } + else if (bar.high < quarter1 && + bar.low > quarter2) + { + // + priority = + isBullish + ? X121SMC_XWZ_PRIORITY_LOW + : X121SMC_XWZ_PRIORITY_REGULAR; + } + else if (bar.high < quarter2 && + bar.low > quarter3) + { + // + priority = + isBullish + ? X121SMC_XWZ_PRIORITY_REGULAR + : X121SMC_XWZ_PRIORITY_LOW; + } + else if (bar.high < quarter3 && + bar.low > demandZone.Upper()) + { + // + priority = + isBullish + ? X121SMC_XWZ_PRIORITY_HIGH + : X121SMC_XWZ_PRIORITY_WEAK; + } + else if (bar.high < demandZone.Upper() && + bar.low > demandZone.Lower()) + { + // + priority = + isBullish + ? X121SMC_XWZ_PRIORITY_STRONG_HIGH + : X121SMC_XWZ_PRIORITY_NONE; + } + + // + result = priority != X121SMC_XWZ_PRIORITY_NONE && + priority != X121SMC_XWZ_PRIORITY_WEAK; + + // + bar.Clean(); + + // + return result; + } + + // + // + // + + // + bool HasSupplyZones() + { + return HasChild(supplyZones); + } + + // + int CountSupplyZones() + { + return ArraySize(supplyZones); + } + + // + bool HasDemandZones() + { + return HasChild(demandZones); + } + + // + int CountDemandZones() + { + return ArraySize(demandZones); + } + + // + int DetectSupplyZones( + XPOIState &state // + ) + { + // + int result = CountSupplyZones(); + + bool isValid = state.IsValid() && + state.HasSupplyZones(); + if (!isValid) + { + return result; + } + + // + XCSupplyZone *tmpZones[]; + Copy( + state.supplyZones, + tmpZones // + ); + int count = FilterZones( + // + tmpZones, + // + X_DIRECTION_BULLISH, + state.period, + NULL, + // + // Start ... + XZONE_STATE_IGNORED, + false, + // + // Activation ... + XZONE_STATE_IGNORED, + false, + // + // Breake ... + XZONE_STATE_FAILED, + false, + // + // Work ... + XZONE_STATE_IGNORED, + false, + // + true, // Apply Sore ... + true // Ignore Inside ... + ); + bool has = IsValidSize(count); + if (!has) + { + return result; + } + + // + int idx = -1; + while (HasChild(tmpZones)) + { + // + XCSupplyZone *iZone; + idx = GetHighest(tmpZones); + has = IsValidIndex(idx); + if (!has) + { + // + ZeroMemory(iZone); + continue; + } + + // + iZone = tmpZones[idx]; + + // + ArrayRemove( + tmpZones, + idx, + 1 // + ); + + // + idx = FindIndex( + iZone, + supplyZones // + ); + has = IsValidIndex(idx); + if (has) + { + // + ZeroMemory(iZone); + continue; + } + + // + Add( + iZone, + supplyZones // + ); + } + + // + int after = CountSupplyZones(); + result = after; + + // + return result; + } + + // + int DetectDemandZones( + XPOIState &state // + ) + { + // + int result = CountDemandZones(); + + bool isValid = state.IsValid() && + state.HasDemandZones(); + if (!isValid) + { + return result; + } + + // + XCDemandZone *tmpZones[]; + Copy( + state.demandZones, + tmpZones // + ); + int count = FilterZones( + // + tmpZones, + // + X_DIRECTION_BEARISH, + state.period, + NULL, + // + // Start ... + XZONE_STATE_IGNORED, + false, + // + // Activation ... + XZONE_STATE_IGNORED, + false, + // + // Breake ... + XZONE_STATE_FAILED, + false, + // + // Work ... + XZONE_STATE_IGNORED, + false, + // + true, // Apply Sore ... + true // Ignore Inside ... + ); + bool has = IsValidSize(count); + if (!has) + { + return result; + } + + // + int idx = -1; + while (HasChild(tmpZones)) + { + // + XCDemandZone *iZone; + idx = GetLowest(tmpZones); + has = IsValidIndex(idx); + if (!has) + { + // + ZeroMemory(iZone); + continue; + } + + // + iZone = tmpZones[idx]; + + // + ArrayRemove( + tmpZones, + idx, + 1 // + ); + + // + idx = FindIndex( + iZone, + demandZones // + ); + has = IsValidIndex(idx); + if (has) + { + // + ZeroMemory(iZone); + continue; + } + + // + Add( + iZone, + demandZones // + ); + } + + // + int after = CountDemandZones(); + result = after; + + // + return result; + } + + // + // + // + + // + void UpdateTo(datetime value = NULL) + { + // + value = NormalizeTime(value); + + // + int count = 0; + bool has = false; + + // + has = HasSupplyZone(); + if (has) + { + supplyZone.To(value); + } + + // + has = HasDemandZone(); + if (has) + { + demandZone.To(value); + } + + // + // Order Flow ... + ENUM_X_DIRECTION orderFlowDir; + has = HasOrderFlow(orderFlowDir); + if (has) + { + // + count = CountOrderFlow(); + for (int i = 0; i < count; i++) + { + orderFlow[i].UpdateTo(value); + } + } + + // + has = HasSupplyZones(); + if (has) + { + // + count = CountSupplyZones(); + for (int i = 0; i < count; i++) + { + supplyZones[i].To(value); + } + } + + // + has = HasDemandZones(); + if (has) + { + // + count = CountDemandZones(); + for (int i = 0; i < count; i++) + { + demandZones[i].To(value); + } + } + + // + } +}; + +// +// Definitions ... +struct X121SMCStrategyXWZSignalConditions +{ + // + // Props ... + + // + string symbol; + ENUM_TIMEFRAMES period; + + // + double sl; + double reward; + double amountPercent; + ENUM_X_DIRECTION dir; + ENUM_X_POSITION_TYPES type; + + // + // Setup Props ... + + // + datetime setupTime; + datetime triggerTime; + + // + double pivot; + double point; + double targets[]; + + // + XOBFVG signalZone; + + // + ENUM_X121SMC_XWZ_PRIORITY priority; + ENUM_X121SMC_XWZ_PROVIDERS provider; + + // + // Constructor ... + X121SMCStrategyXWZSignalConditions() + { + 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; + + // + ExtensionClean(); + + // + ZeroMemory(this); + } + + /** + * 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 ... + + /** + * Clean Additional Properties ... + */ + void ExtensionClean() + { + // + pivot = 0; + point = 0; + + // + reward = 0; + amountPercent = 0; + + // + Clean(targets); + signalZone.Clean(); + + // + provider = X121SMC_XWZ_PROVIDER_NONE; + } + + // + // + // + + // + void UpdateTo(datetime value = NULL) + { + // + value = NormalizeTime(value); + + // + int count = 0; + bool has = false; + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14031218/Documents/BKP/x-saherelm.x-poi.class.mq5 b/BKPS/14031218/Documents/BKP/x-saherelm.x-poi.class.mq5 new file mode 100644 index 0000000..be134d9 --- /dev/null +++ b/BKPS/14031218/Documents/BKP/x-saherelm.x-poi.class.mq5 @@ -0,0 +1,4218 @@ +/////////////////////////////////////////////////////// +// +// 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 // + ); + + // + // Create Default Drawer Instance ... + mDrawer = new XCPOIDrawer(); + + // + // 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 iSwingRange = SwingRange(); + if (iSwingRange > 0) + { + // + XOHCL swingBar; + isInited = swingBar.Init( + symbol, + period, + zIndex + iSwingRange // + ); + 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(); + + // + delete mDrawer; + delete mTicksZone; + + // + ZeroMemory(mDrawer); + ZeroMemory(mTicksZone); + } + + // + // 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 // + ); + } + } + + // + 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 // + ); + } + } + + // + 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 // + ); + } + } + + // + 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 // + ); + } + } + + // + 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 // + ); + } + } + + // + 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 // + ); + } + } + + // + 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 // + ); + } + } + + // + 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 // + ); + } + } + + // + 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 // + ); + } + } + + // + 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 // + ); + } + } + + // + 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 // + ); + } + } + + // + 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 // + ); + } + } + + // + 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 // + ); + } + } + + // + 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 // + ); + } + } + + // + 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 iSwingRange = SwingRange(); + if (iSwingRange > 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 = + iSwingRange > 0 + ? swingHighsCount < requiredPOIs + : false; + bool canContinueSwingLows = + iSwingRange > 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; + } + + // + return result; + } + + // + // Liquidity Zones ... + + // + // Sell Side ... + + // + // Buy Side ... + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14031218/Documents/BKP/x-saherelm.x121.xwz.mq5 b/BKPS/14031218/Documents/BKP/x-saherelm.x121.xwz.mq5 new file mode 100644 index 0000000..8828b35 --- /dev/null +++ b/BKPS/14031218/Documents/BKP/x-saherelm.x121.xwz.mq5 @@ -0,0 +1,3438 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XWZ +// Description: XWZ ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121 XWZ Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121_XWZ" + +// +// Includes Common Library ... +#include "../Classes/x-saherelm.x-alert.class.mq5" +#include "../Classes/x-saherelm.x-bar.analyser.class.mq5" +#include "../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" +#include "../Libraries/x-saherelm.x-poi.extensions.lib.mq5" + +// +// Inputs ... + +// +// Market ... +input group "Market"; + +// +input group "Calculation"; +input ENUM_APPLIED_PRICE appliedTo = PRICE_CLOSE; // Detect Price Type + +// +input group "MA Detection"; +input int maLength = 20; // MA Length +input ENUM_MA_METHOD maMethod = MODE_EMA; // MA Method + +// +input group "ATR StopLoss"; +input int atrLength = 14; // ATR Length +input double atrMultiplier = 2; // ATR Multiplier + +// +input group "ADX Detection"; +input int adxLength = 14; // ADX Length +input double adxThreshold = 25; // ADX Threshold for Strong Trends + +// +input group "Alert"; +input bool mXWZEnableAlerts = true; // Enable Alerts +input bool mXWZPushAlerts = false; // Push Alerts +input bool mXWZMailAlerts = false; // Mail Alerts +input bool mXWZTerminalAlerts = false; // Terminal Alerts + +// +// Presentation ... +input group "Presentation"; + +// +input group "Buffer Presentation"; +input bool showMA = true; // Show Moving Average +input bool showPin = true; // Show Pin Bars +input bool showSwing = true; // Show Swing Bars +input bool showTrend = true; // Show Trend +input bool showEngulf = true; // Show Engulf Bars +input bool showLongSL = true; // Show Long SL +input bool showShortSL = true; // Show Short SL +input bool showMomentum = true; // Show Momentum Bars +input bool showRejection = true; // Show Rejection Bars + +// +input group "POI Presentation"; +input bool showPOIs = false; // Show POI(s) +input bool showActivatedPOIs = true; // Show Activated POI(s) +input bool showOrderBlocks = true; // Show Order Blocks +input bool showFairValueGaps = true; // Show Fair Value Gaps +input bool showSupportZones = false; // Show Support Zones +input bool showResistanceZones = false; // Show Resistance Zones + +// +input group "Presentation Config"; +input int startCalculationForLastBars = 1000; // Calculate Last n Bars +input int upTrendArrowCode = 236; // Up Trend Arrow Code +input int downTrendArrowCode = 238; // Down Trend Arrow Code +input int swingLowArrowCode = 108; // Swing Low Arrow Code +input int swingHighArrowCode = 108; // Swing High Arrow Code +input int bullishPinArrowCode = 246; // Bullish Pin Arrow Code +input int bearishPinArrowCode = 248; // Bearish Pin Arrow Code +input int bullishEngulfArrowCode = 200; // Bullish Engulf Arrow Code +input int bearishEngulfArrowCode = 202; // Bearish Engulf Arrow Code +input int bullishMomentumArrowCode = 233; // Bullish Momentum Arrow Code +input int bearishMomentumArrowCode = 234; // Bearish Momentum Arrow Code +input int bullishRejectionArrowCode = 241; // Bullish Rejection Arrow Code +input int bearishRejectionArrowCode = 242; // Bearish Rejection Arrow Code + +// +#property indicator_chart_window + +// +#property indicator_buffers 17 +#property indicator_plots 15 + +// +// Plot Buffers ... + +// +#define maBufferIndex 0 +double maBuffer[]; + +// +#property indicator_label1 "X121-XWZ MA" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrLightSkyBlue +#property indicator_style1 STYLE_SOLID +#property indicator_width1 2 + +// +#define longSLBufferIndex 1 +double longSLBuffer[]; + +// +#property indicator_label2 "X121-XWZ Long SL" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrOrange +#property indicator_style2 STYLE_SOLID +#property indicator_width2 1 + +// +#define shortSLBufferIndex 2 +double shortSLBuffer[]; + +// +#property indicator_label3 "X121-XWZ Short SL" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrOrange +#property indicator_style3 STYLE_SOLID +#property indicator_width3 1 + +// +#define upTrendBufferIndex 3 +double upTrendBuffer[]; + +// +#property indicator_label4 "X121-XWZ Trend Up" +#property indicator_type4 DRAW_ARROW +#property indicator_color4 clrAqua +#property indicator_width4 3 + +// +#define downTrendBufferIndex 4 +double downTrendBuffer[]; + +// +#property indicator_label5 "X121-XWZ Trend Down" +#property indicator_type5 DRAW_ARROW +#property indicator_color5 clrMagenta +#property indicator_width5 3 + +// +#define bullishMomentumBufferIndex 5 +double bullishMomentumBuffer[]; + +// +#property indicator_label6 "X121-XWZ Bull Momentum" +#property indicator_type6 DRAW_ARROW +#property indicator_color6 clrAqua +#property indicator_width6 3 + +// +#define bearishMomentumBufferIndex 6 +double bearishMomentumBuffer[]; + +// +#property indicator_label7 "X121-XWZ Bear Momentum" +#property indicator_type7 DRAW_ARROW +#property indicator_color7 clrMagenta +#property indicator_width7 3 + +// +#define bullishRejectionBufferIndex 7 +double bullishRejectionBuffer[]; + +// +#property indicator_label8 "X121-XWZ Bull Rejection" +#property indicator_type8 DRAW_ARROW +#property indicator_color8 clrAqua +#property indicator_width8 3 + +// +#define bearishRejectionBufferIndex 8 +double bearishRejectionBuffer[]; + +// +#property indicator_label9 "X121-XWZ Bear Rejection" +#property indicator_type9 DRAW_ARROW +#property indicator_color9 clrMagenta +#property indicator_width9 3 + +// +#define bullishPinBufferIndex 9 +double bullishPinBuffer[]; + +// +#property indicator_label10 "X121-XWZ Bull Pin" +#property indicator_type10 DRAW_ARROW +#property indicator_color10 clrAqua +#property indicator_width10 3 + +// +#define bearishPinBufferIndex 10 +double bearishPinBuffer[]; + +// +#property indicator_label11 "X121-XWZ Bear Pin" +#property indicator_type11 DRAW_ARROW +#property indicator_color11 clrMagenta +#property indicator_width11 3 + +// +#define bullishEngulfBufferIndex 11 +double bullishEngulfBuffer[]; + +// +#property indicator_label12 "X121-XWZ Bull Engulf" +#property indicator_type12 DRAW_ARROW +#property indicator_color12 clrAqua +#property indicator_width12 3 + +// +#define bearishEngulfBufferIndex 12 +double bearishEngulfBuffer[]; + +// +#property indicator_label13 "X121-XWZ Bear Engulf" +#property indicator_type13 DRAW_ARROW +#property indicator_color13 clrMagenta +#property indicator_width13 3 + +// +#define swingLowBufferIndex 13 +double swingLowBuffer[]; + +// +#property indicator_label14 "X121-XWZ Swing Low" +#property indicator_type14 DRAW_ARROW +#property indicator_color14 clrAqua +#property indicator_width14 3 + +// +#define swingHighBufferIndex 14 +double swingHighBuffer[]; + +// +#property indicator_label15 "X121-XWZ Swing High" +#property indicator_type15 DRAW_ARROW +#property indicator_color15 clrMagenta +#property indicator_width15 3 + +// +// Data Buffers ... + +// +int mLastBufferIndex = 14; + +// +#define atrBufferIndex mLastBufferIndex + 1 +double atrBuffer[]; + +// +#define adxBufferIndex mLastBufferIndex + 2 +double adxBuffer[]; + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +// MA Handler ... +int maHandler = INVALID_HANDLE; + +// +// ATR Handler ... +int atrHandler = INVALID_HANDLE; + +// +// ADX Handler ... +int adxHandler = INVALID_HANDLE; + +// +XCAlert *mXWZAlert; +CArrayObj mXWZDrawnObjects; +XCPOIDrawer *mXWZPOIDrawer; +XCBarAnalyser *mXWZBarAnalyser; + +// +datetime lastBullishTrend = NULL; +datetime lastBearishTrend = NULL; + +// +datetime lastCrossedOverMA = NULL; +datetime lastCrossedUnderMA = NULL; + +// +// POI(s) ... + +// +bool mXWZDetectOrderBlocks = true; +bool mXWZDetectFairValueGaps = false; +bool mXWZDetectSupportZones = false; +bool mXWZDetectResistanceZones = false; + +// +bool filterPOIsUsingMa = false; // Filter POI(s) Using MA +bool filterPOIsUsingZones = false; // Filter POI(s) Using Zones + +// +XCFVG *lastBullFVG; +XCFVG *lastBearFVG; +XCOrderBlock *lastBullOB; +XCOrderBlock *lastBearOB; +XCSupportZone *lastSupport; +XCResistanceZone *lastResistance; + +// +// Un Activated POI(s) ... +XCFVG *mXWZUnActivatedFVGs[]; +XCOrderBlock *mXWZUnActivatedOBs[]; +XCSupportZone *mXWZUnActivatedSupportZones[]; +XCResistanceZone *mXWZUnActivatedResistanceZones[]; + +// +// Activated POI(s) ... +XCFVG *mXWZActivatedFVGs[]; +XCOrderBlock *mXWZActivatedOBs[]; +XCSupportZone *mXWZActivatedSupportZones[]; +XCResistanceZone *mXWZActivatedResistanceZones[]; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + mXWZDrawnObjects.Clear(); + + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + + // + // MA ... + maHandler = iMA( + _Symbol, + _Period, + maLength, + 0, + maMethod, + appliedTo // + ); + bool isInited = maHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // ATR ... + atrHandler = iATR( + _Symbol, + _Period, + atrLength // + ); + isInited = maHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // ADX ... + adxHandler = iADX( + _Symbol, + _Period, + adxLength // + ); + isInited = maHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + IndicatorSetInteger(INDICATOR_DIGITS, 2); + + // + mXWZPOIDrawer = new XCPOIDrawer(); + ConfigurePOIDrawer(); + + // + mXWZAlert = new XCAlert(); + ConfigureAlert(); + + // + mXWZBarAnalyser = new XCBarAnalyser(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + IndicatorRelease(maHandler); + IndicatorRelease(atrHandler); + IndicatorRelease(adxHandler); + + // + mXWZDrawnObjects.Clear(); + + // + ZeroMemory(mXWZAlert); + ZeroMemory(mXWZPOIDrawer); + ZeroMemory(mXWZBarAnalyser); + + // + Clean(mXWZActivatedOBs); + Clean(mXWZActivatedFVGs); + Clean(mXWZActivatedSupportZones); + Clean(mXWZActivatedResistanceZones); + + // + Clean(mXWZUnActivatedOBs); + Clean(mXWZUnActivatedFVGs); + Clean(mXWZUnActivatedSupportZones); + Clean(mXWZUnActivatedResistanceZones); +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // Validate Calculated Bars ... + + // + // MA ... + int maCalculatedBars = BarsCalculated(maHandler); + + // + // ATR ... + int atrCalculatedBars = BarsCalculated(atrHandler); + + // + // ADX ... + int adxCalculatedBars = BarsCalculated(adxHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // MA ... + maCalculatedBars >= maxLength && + // + // ATR ... + atrCalculatedBars >= maxLength && + // + // ADX ... + adxCalculatedBars >= maxLength + // + ; + if (!isPassedRequiredCalculatedBars) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + + // + // MA ... + int copiedMas = CopyBuffer(maHandler, 0, 0, limit, maBuffer); + + // + // ATR ... + int copiedAtr = CopyBuffer(atrHandler, MAIN_LINE, 0, limit, atrBuffer); + + // + // ADX ... + int copiedAdxs = CopyBuffer(adxHandler, MAIN_LINE, 0, limit, adxBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // MA ... + copiedMas > 0 && + // + // ATR ... + copiedAtr > 0 && + // + // ADX ... + copiedAdxs > 0 + // + ; + if (!isPassedRequiredCopiedItems) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + // + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + result = + // + // MA ... + maLength > 0 && + // + // ATR ... + atrLength > 0 && + atrMultiplier > 0 && + // + // ADX ... + adxLength > 0 && + adxThreshold > 0 + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(maLength, atrLength); + result = MathMax(result, adxLength); + + // + return result; +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + + // + // MA Buffer ... + + // + ENUM_DRAW_TYPE maDrawType = showMA ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(maBuffer, true); + SetIndexBuffer(maBufferIndex, maBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(maBufferIndex, PLOT_SHOW_DATA, showMA); + PlotIndexSetInteger(maBufferIndex, PLOT_DRAW_TYPE, maDrawType); + + // + PlotIndexSetDouble(maBufferIndex, PLOT_EMPTY_VALUE, 0); + + // + // LONG SL Buffer ... + + // + ENUM_DRAW_TYPE longSLDrawType = showLongSL ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(longSLBuffer, true); + SetIndexBuffer(longSLBufferIndex, longSLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(longSLBufferIndex, PLOT_SHOW_DATA, showLongSL); + PlotIndexSetInteger(longSLBufferIndex, PLOT_DRAW_TYPE, longSLDrawType); + + // + PlotIndexSetDouble(longSLBufferIndex, PLOT_EMPTY_VALUE, 0); + + // + // SHORT SL Buffer ... + + // + ENUM_DRAW_TYPE shortSLDrawType = showShortSL ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(shortSLBuffer, true); + SetIndexBuffer(shortSLBufferIndex, shortSLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(shortSLBufferIndex, PLOT_SHOW_DATA, showShortSL); + PlotIndexSetInteger(shortSLBufferIndex, PLOT_DRAW_TYPE, shortSLDrawType); + + // + PlotIndexSetDouble(shortSLBufferIndex, PLOT_EMPTY_VALUE, 0); + + // + // UP Trend ... + + // + ENUM_DRAW_TYPE upTrendDrawType = showTrend ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(upTrendBuffer, true); + SetIndexBuffer(upTrendBufferIndex, upTrendBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(upTrendBufferIndex, PLOT_SHOW_DATA, showTrend); + PlotIndexSetInteger(upTrendBufferIndex, PLOT_DRAW_TYPE, upTrendDrawType); + + // + PlotIndexSetDouble(upTrendBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(upTrendBufferIndex, PLOT_ARROW, upTrendArrowCode); + + // + // DOWN Trend ... + + // + ENUM_DRAW_TYPE downTrendDrawType = showTrend ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(downTrendBuffer, true); + SetIndexBuffer(downTrendBufferIndex, downTrendBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(downTrendBufferIndex, PLOT_SHOW_DATA, showTrend); + PlotIndexSetInteger(downTrendBufferIndex, PLOT_DRAW_TYPE, downTrendDrawType); + + // + PlotIndexSetDouble(downTrendBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(downTrendBufferIndex, PLOT_ARROW, downTrendArrowCode); + + // + // Bullish Momentum ... + + // + ENUM_DRAW_TYPE bullishMomentumDrawType = showMomentum ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(bullishMomentumBuffer, true); + SetIndexBuffer(bullishMomentumBufferIndex, bullishMomentumBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(bullishMomentumBufferIndex, PLOT_SHOW_DATA, showMomentum); + PlotIndexSetInteger(bullishMomentumBufferIndex, PLOT_DRAW_TYPE, bullishMomentumDrawType); + + // + PlotIndexSetDouble(bullishMomentumBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(bullishMomentumBufferIndex, PLOT_ARROW, bullishMomentumArrowCode); + + // + // Bearish Momentum ... + + // + ENUM_DRAW_TYPE bearishMomentumDrawType = showMomentum ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(bearishMomentumBuffer, true); + SetIndexBuffer(bearishMomentumBufferIndex, bearishMomentumBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(bearishMomentumBufferIndex, PLOT_SHOW_DATA, showMomentum); + PlotIndexSetInteger(bearishMomentumBufferIndex, PLOT_DRAW_TYPE, bearishMomentumDrawType); + + // + PlotIndexSetDouble(bearishMomentumBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(bearishMomentumBufferIndex, PLOT_ARROW, bearishMomentumArrowCode); + + // + // Bullish Rejection ... + + // + ENUM_DRAW_TYPE bullishRejectionDrawType = showRejection ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(bullishRejectionBuffer, true); + SetIndexBuffer(bullishRejectionBufferIndex, bullishRejectionBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(bullishRejectionBufferIndex, PLOT_SHOW_DATA, showRejection); + PlotIndexSetInteger(bullishRejectionBufferIndex, PLOT_DRAW_TYPE, bullishRejectionDrawType); + + // + PlotIndexSetDouble(bullishRejectionBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(bullishRejectionBufferIndex, PLOT_ARROW, bullishRejectionArrowCode); + + // + // Bearish Rejection ... + + // + ENUM_DRAW_TYPE bearishRejectionDrawType = showRejection ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(bearishRejectionBuffer, true); + SetIndexBuffer(bearishRejectionBufferIndex, bearishRejectionBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(bearishRejectionBufferIndex, PLOT_SHOW_DATA, showRejection); + PlotIndexSetInteger(bearishRejectionBufferIndex, PLOT_DRAW_TYPE, bearishRejectionDrawType); + + // + PlotIndexSetDouble(bearishRejectionBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(bearishRejectionBufferIndex, PLOT_ARROW, bearishRejectionArrowCode); + + // + // Bullish Pin ... + + // + ENUM_DRAW_TYPE bullishPinDrawType = showPin ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(bullishPinBuffer, true); + SetIndexBuffer(bullishPinBufferIndex, bullishPinBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(bullishPinBufferIndex, PLOT_SHOW_DATA, showPin); + PlotIndexSetInteger(bullishPinBufferIndex, PLOT_DRAW_TYPE, bullishPinDrawType); + + // + PlotIndexSetDouble(bullishPinBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(bullishPinBufferIndex, PLOT_ARROW, bullishPinArrowCode); + + // + // Bearish Pin ... + + // + ENUM_DRAW_TYPE bearishPinDrawType = showPin ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(bearishPinBuffer, true); + SetIndexBuffer(bearishPinBufferIndex, bearishPinBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(bearishPinBufferIndex, PLOT_SHOW_DATA, showPin); + PlotIndexSetInteger(bearishPinBufferIndex, PLOT_DRAW_TYPE, bearishPinDrawType); + + // + PlotIndexSetDouble(bearishPinBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(bearishPinBufferIndex, PLOT_ARROW, bearishPinArrowCode); + + // + // Bullish Engulf ... + + // + ENUM_DRAW_TYPE bullishEngulfDrawType = showEngulf ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(bullishEngulfBuffer, true); + SetIndexBuffer(bullishEngulfBufferIndex, bullishEngulfBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(bullishEngulfBufferIndex, PLOT_SHOW_DATA, showEngulf); + PlotIndexSetInteger(bullishEngulfBufferIndex, PLOT_DRAW_TYPE, bullishEngulfDrawType); + + // + PlotIndexSetDouble(bullishEngulfBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(bullishEngulfBufferIndex, PLOT_ARROW, bullishEngulfArrowCode); + + // + // Bearish Engulf ... + + // + ENUM_DRAW_TYPE bearishEngulfDrawType = showEngulf ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(bearishEngulfBuffer, true); + SetIndexBuffer(bearishEngulfBufferIndex, bearishEngulfBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(bearishEngulfBufferIndex, PLOT_SHOW_DATA, showEngulf); + PlotIndexSetInteger(bearishEngulfBufferIndex, PLOT_DRAW_TYPE, bearishEngulfDrawType); + + // + PlotIndexSetDouble(bearishEngulfBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(bearishEngulfBufferIndex, PLOT_ARROW, bearishEngulfArrowCode); + + // + // Swing Low ... + + // + ENUM_DRAW_TYPE swingLowDrawType = showSwing ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(swingLowBuffer, true); + SetIndexBuffer(swingLowBufferIndex, swingLowBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(swingLowBufferIndex, PLOT_SHOW_DATA, showSwing); + PlotIndexSetInteger(swingLowBufferIndex, PLOT_DRAW_TYPE, swingLowDrawType); + + // + PlotIndexSetDouble(swingLowBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(swingLowBufferIndex, PLOT_ARROW, swingLowArrowCode); + + // + // Swing High ... + + // + ENUM_DRAW_TYPE swingHighDrawType = showSwing ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(swingHighBuffer, true); + SetIndexBuffer(swingHighBufferIndex, swingHighBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(swingHighBufferIndex, PLOT_SHOW_DATA, showSwing); + PlotIndexSetInteger(swingHighBufferIndex, PLOT_DRAW_TYPE, swingHighDrawType); + + // + PlotIndexSetDouble(swingHighBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(swingHighBufferIndex, PLOT_ARROW, swingHighArrowCode); + + // + // DATA Buffers ... + + // + ArraySetAsSeries(atrBuffer, true); + SetIndexBuffer(atrBufferIndex, atrBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(adxBuffer, true); + SetIndexBuffer(adxBufferIndex, adxBuffer, INDICATOR_CALCULATIONS); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateBuffers( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + // + // bool canCalculate = true; + bool canCalculate = + barsLimit == 0 || + bar_index <= barsLimit; + if (canCalculate) + { + // + CalculatedPOIs( + // + bar_index, + prevCalculated, + ratesTotal, + // + open, + high, + close, + low, + tickVolume // + ); + + // + CalculateValues( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + else + { + FillBuffersZero(bar_index); + } +} + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + maBuffer[barIndex] = 0; + atrBuffer[barIndex] = 0; + adxBuffer[barIndex] = 0; + longSLBuffer[barIndex] = 0; + shortSLBuffer[barIndex] = 0; + upTrendBuffer[barIndex] = 0; + swingLowBuffer[barIndex] = 0; + swingHighBuffer[barIndex] = 0; + downTrendBuffer[barIndex] = 0; + bullishPinBuffer[barIndex] = 0; + bearishPinBuffer[barIndex] = 0; + bullishEngulfBuffer[barIndex] = 0; + bearishEngulfBuffer[barIndex] = 0; + bullishMomentumBuffer[barIndex] = 0; + bearishMomentumBuffer[barIndex] = 0; + bullishRejectionBuffer[barIndex] = 0; + bearishRejectionBuffer[barIndex] = 0; +} + +/** + * Calculate Vales ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateValues( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // Prepare Requirements ... + + // + XOHCL iBar; + bool isInited = iBar.Init( + _Symbol, + _Period, + bar_index // + ); + if (!isInited) + { + // + iBar.Clean(); + return; + } + + // + XOHCL pBar; + isInited = iBar.GetPreviousBar(pBar); + if (!isInited) + { + // + iBar.Clean(); + pBar.Clean(); + return; + } + int pIndex = pBar.Index(); + + // + // Calculate Applied Price ... + double iPrice = GetAppliedPrice( + appliedTo, + open, + high, + low, + close, + bar_index // + ); + + // + double iMa = maBuffer[bar_index]; + double iMaPrev = maBuffer[pIndex]; + double iAtr = atrBuffer[bar_index]; + double iAdx = adxBuffer[bar_index]; + double iAppliedAtr = iAtr * atrMultiplier; + + // + double points = GetPoints(_Symbol); + double points10 = 10 * points; + + // + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + + // + bool hasLastBullOB = lastBullOB != NULL && + lastBullOB.IsValid(); + bool hasLastBearOB = lastBearOB != NULL && + lastBearOB.IsValid(); + + // + bool hasLastBullFVG = lastBullFVG != NULL && + lastBullFVG.IsValid(); + bool hasLastBearFVG = lastBearFVG != NULL && + lastBearFVG.IsValid(); + + // + bool hasLastSupport = lastSupport != NULL && + lastSupport.IsValid(); + + // + bool hasLastResistance = lastResistance != NULL && + lastResistance.IsValid(); + + // + // Calculate Crossing Over / Under Ma ... + bool isCrossedOverMA = + // + iBar.low > iMa && + (pBar.low <= iMaPrev && + (pBar.GetUp() <= iMaPrev || + pBar.GetDown() <= iMaPrev)) + // + ; + bool isCrossedUnderMA = + // + iBar.high < iMa && + (pBar.high >= iMaPrev && + (pBar.GetUp() >= iMaPrev || + pBar.GetDown() >= iMaPrev)) + // + ; + lastCrossedOverMA = + isCrossedOverMA + ? iBar.time + : lastCrossedOverMA; + lastCrossedUnderMA = + isCrossedUnderMA + ? iBar.time + : lastCrossedUnderMA; + + // + // SL Buffers ... + + // + double iLongSL = iPrice - iAppliedAtr; + double iShortSL = iPrice + iAppliedAtr; + + // + longSLBuffer[bar_index] = iLongSL; + shortSLBuffer[bar_index] = iShortSL; + + // + // Trend Buffers ... + + // + bool isUpTrend = + // + iPrice > iMa && + iBar.low < iMa && + iAdx > adxThreshold + // + ; + + // + bool isDownTrend = + // + iPrice < iMa && + iBar.high > iMa && + iAdx > adxThreshold + // + ; + + // + double upTrendValue = 0; + double downTrendValue = 0; + if (isUpTrend) + { + // + lastBullishTrend = iBar.time; + upTrendValue = iBar.low; + } + if (isDownTrend) + { + // + lastBearishTrend = iBar.time; + downTrendValue = iBar.high; + } + + // + upTrendBuffer[bar_index] = upTrendValue; + downTrendBuffer[bar_index] = downTrendValue; + + // + // Momentum Buffers ... + + // + bool isMomentum = mXWZBarAnalyser + .IsMomentumBar( + iBar, + iDir, + 1, // Extends ... + 70 // Body Percent ... + ); + bool isBullishMomentum = + isMomentum && + IsBullish(iDir); + bool isBearishMomentum = + isMomentum && + IsBearish(iDir); + if (isMomentum) + { + // + double iBullMomentumValue = 0; + double iBearMomentumValue = 0; + + // + if (isBullishMomentum) + { + // + double selectedValue = iBar.low; + + // + iBullMomentumValue = + !filterPOIsUsingZones + ? selectedValue + : !hasLastBullOB + ? 0 + : IsInside( + selectedValue, + lastBullOB // + ) + ? selectedValue + : 0; + + // + iBullMomentumValue = + !filterPOIsUsingMa + ? iBullMomentumValue + : iBullMomentumValue < iMa + ? iBullMomentumValue + : 0; + } + + // + if (isBearishMomentum) + { + // + double selectedValue = iBar.high; + + // + iBearMomentumValue = + !filterPOIsUsingZones + ? selectedValue + : !hasLastBearOB + ? 0 + : IsInside( + selectedValue, + lastBearOB // + ) + ? selectedValue + : 0; + + // + iBearMomentumValue = + !filterPOIsUsingMa + ? iBearMomentumValue + : iBearMomentumValue > iMa + ? iBearMomentumValue + : 0; + } + + // + bullishMomentumBuffer[bar_index] = iBullMomentumValue; + bearishMomentumBuffer[bar_index] = iBearMomentumValue; + } + + // + // Rejection Buffers ... + + // + bool isRejection = mXWZBarAnalyser + .IsRejectionBar( + iBar, + iDir, + 1, // Extends ... + 70 // Body Percent ... + ); + bool isBullishRejection = + isRejection && + IsBullish(iDir); + bool isBearishRejection = + isRejection && + IsBearish(iDir); + if (isRejection) + { + // + double iBullRejectionValue = 0; + double iBearRejectionValue = 0; + + // + if (isBullishRejection) + { + // + double selectedValue = iBar.low; + + // + iBullRejectionValue = + !filterPOIsUsingZones + ? selectedValue + : !hasLastBullOB + ? 0 + : IsInside( + selectedValue, + lastBullOB // + ) + ? selectedValue + : 0; + + // + iBullRejectionValue = + !filterPOIsUsingMa + ? iBullRejectionValue + : iBullRejectionValue < iMa + ? iBullRejectionValue + : 0; + } + + // + if (isBearishRejection) + { + // + double selectedValue = iBar.high; + + // + iBearRejectionValue = + !filterPOIsUsingZones + ? selectedValue + : !hasLastBearOB + ? 0 + : IsInside( + selectedValue, + lastBearOB // + ) + ? selectedValue + : 0; + + // + iBearRejectionValue = + !filterPOIsUsingMa + ? iBearRejectionValue + : iBearRejectionValue > iMa + ? iBearRejectionValue + : 0; + } + + // + bullishRejectionBuffer[bar_index] = iBullRejectionValue; + bearishRejectionBuffer[bar_index] = iBearRejectionValue; + } + + // + // Pin Buffers ... + + // + bool isPin = mXWZBarAnalyser + .IsPinBar( + iBar, + iDir, + 0, // Extends ... + 50, // Shadow Percent ... + 25 // Body Percent ... + ); + bool isBullishPin = + isPin && + IsBullish(iDir); + bool isBearishPin = + isPin && + IsBearish(iDir); + if (isPin) + { + // + double iBullPinValue = 0; + double iBearPinValue = 0; + + // + if (isBullishPin) + { + // + double selectedValue = iBar.low; + + // + iBullPinValue = + !filterPOIsUsingZones + ? selectedValue + : !hasLastBullOB + ? 0 + : IsInside( + selectedValue, + lastBullOB // + ) + ? selectedValue + : 0; + + // + iBullPinValue = + !filterPOIsUsingMa + ? iBullPinValue + : iBullPinValue < iMa + ? iBullPinValue + : 0; + } + + // + if (isBearishPin) + { + // + double selectedValue = iBar.high; + + // + iBearPinValue = + !filterPOIsUsingZones + ? selectedValue + : !hasLastBearOB + ? 0 + : IsInside( + selectedValue, + lastBearOB // + ) + ? selectedValue + : 0; + + // + iBearPinValue = + !filterPOIsUsingMa + ? iBearPinValue + : iBearPinValue > iMa + ? iBearPinValue + : 0; + } + + // + bullishPinBuffer[bar_index] = iBullPinValue; + bearishPinBuffer[bar_index] = iBearPinValue; + } + + // + // Engulf Buffers ... + + // + bool isEngulf = mXWZBarAnalyser + .IsEngulfBar( + iBar, + iDir, + 1, // Extends ... + 70 // Body Percent ... + ); + bool isBullishEngulf = + isEngulf && + IsBullish(iDir); + bool isBearishEngulf = + isEngulf && + IsBearish(iDir); + if (isEngulf) + { + // + double iBullEngulfValue = 0; + double iBearEngulfValue = 0; + + // + if (isBullishEngulf) + { + // + double selectedValue = iBar.low; + + // + iBullEngulfValue = + !filterPOIsUsingZones + ? selectedValue + : !hasLastBullOB + ? 0 + : IsInside( + selectedValue, + lastBullOB // + ) + ? selectedValue + : 0; + + // + iBullEngulfValue = + !filterPOIsUsingMa + ? iBullEngulfValue + : iBullEngulfValue < iMa + ? iBullEngulfValue + : 0; + } + + // + if (isBearishEngulf) + { + // + double selectedValue = iBar.high; + + // + iBearEngulfValue = + !filterPOIsUsingZones + ? selectedValue + : !hasLastBearOB + ? 0 + : IsInside( + selectedValue, + lastBearOB // + ) + ? selectedValue + : 0; + + // + iBearEngulfValue = + !filterPOIsUsingMa + ? iBearEngulfValue + : iBearEngulfValue > iMa + ? iBearEngulfValue + : 0; + } + + // + bullishEngulfBuffer[bar_index] = iBullEngulfValue; + bearishEngulfBuffer[bar_index] = iBearEngulfValue; + } + + // + // Swing Buffers ... + + // + bool isSwing = mXWZBarAnalyser + .IsSwing( + iBar, + iDir, + 2 // Range ... + ); + bool isSwingLow = + isSwing && + IsBullish(iDir); + bool isSwingHigh = + isSwing && + IsBearish(iDir); + if (isSwing) + { + // + double iSwingLowValue = 0; + double iSwingHighValue = 0; + + // + if (isSwingLow) + { + // + double selectedValue = iBar.low; + + // + iSwingLowValue = + !filterPOIsUsingZones + ? selectedValue + : !hasLastBullOB + ? 0 + : IsBelow( + selectedValue, + lastBullOB // + ) + ? selectedValue + : 0; + + // + iSwingLowValue = + !filterPOIsUsingMa + ? iSwingLowValue + : iSwingLowValue < iMa + ? iSwingLowValue + : 0; + } + + // + if (isSwingHigh) + { + // + double selectedValue = iBar.high; + + // + iSwingHighValue = + !filterPOIsUsingZones + ? selectedValue + : !hasLastBearOB + ? 0 + : IsAbove( + selectedValue, + lastBearOB // + ) + ? selectedValue + : 0; + + // + iSwingHighValue = + !filterPOIsUsingMa + ? iSwingHighValue + : iSwingHighValue > iMa + ? iSwingHighValue + : 0; + } + + // + swingLowBuffer[bar_index] = iSwingLowValue; + swingHighBuffer[bar_index] = iSwingHighValue; + } + + // + // + // + + // + DetectSignals( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // Cleanup Resources ... + + // + iBar.Clean(); + pBar.Clean(); +} + +// +void ConfigureAlert() +{ + // + mXWZAlert.SetPrefix(ShortName); + + // + mXWZAlert.SetPushAlerts(mXWZPushAlerts); + mXWZAlert.SetMailAlerts(mXWZMailAlerts); + mXWZAlert.SetEnableAlerts(mXWZEnableAlerts); + mXWZAlert.SetTerminalAlerts(mXWZTerminalAlerts); +} + +// +void DetectSignals( + int barIndex, + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // Calculate Signals ... + + // + XOHCL bar; + XOHCL pBar; + XOHCL ppBar; + bool isInited = bar.Init( + _Symbol, + _Period, + barIndex // + ); + if (!isInited) + { + return; + } + + // + isInited = bar.GetPreviousBar(pBar); + if (!isInited) + { + return; + } + + // + isInited = pBar.GetPreviousBar(ppBar); + if (!isInited) + { + return; + } + + // + int pIDX = pBar.Index(); + int ppIDX = ppBar.Index(); + + // + // Reading Buffers ... + + // + double ma = maBuffer[barIndex]; + double maPrev = maBuffer[pIDX]; + double maPPrev = maBuffer[ppIDX]; + + // + // Pin Bar ... + bool isBullisPinned = bullishPinBuffer[pIDX] > 0; + bool isBearisPinned = bearishPinBuffer[pIDX] > 0; + + // + // Engulf Bar ... + bool isBullisEngulfed = bullishEngulfBuffer[pIDX] > 0; + bool isBearisEngulfed = bearishEngulfBuffer[pIDX] > 0; + + // + // Rejection Bar ... + bool isBullishRejected = bullishRejectionBuffer[pIDX] > 0; + bool isBearishRejected = bearishRejectionBuffer[pIDX] > 0; + + // + // Momentum Bar ... + bool isBullishMomentum = bullishMomentumBuffer[pIDX] > 0; + bool isBearishMomentum = bearishMomentumBuffer[pIDX] > 0; + + // + // Checking Pullback ... + ENUM_X_DIRECTION pullbackDir; + bool hasPullback = mXWZBarAnalyser.HasPullBack( + pullbackDir, + bar // + ); + bool hasBullishPullback = + hasPullback && + IsBullish(pullbackDir); + bool hasBearishPullback = + hasPullback && + IsBearish(pullbackDir); + + // + // Order Block Parsing ... + + // // + // bool isMACrossedOverBullishOB = + // // + // lastBullOB != NULL && + // lastBullOB.IsValid() && + // // + // IsInside( + // maPPrev, + // lastBullOB // + // ) && + // // + // IsAbove( + // maPrev, + // lastBullOB // + // ) + // // + // ; + + // // + // bool isMACrossedUnderBearishOB = + // // + // lastBearOB != NULL && + // lastBearOB.IsValid() && + // // + // IsInside( + // maPPrev, + // lastBearOB // + // ) && + // // + // IsBelow( + // maPrev, + // lastBearOB // + // ) + // // + // ; + + // + // Bullish ... + // -------------- + // -[] a Bullish Wave Which Crossed Over MA ... + // -[] Trend is Bullish ... + // -[] PullBack to MA ... + // -[] Has a Bllish Rejection ... + bool hasBullishSignal = + // + pBar.IsBullish() && + pBar.low < maPrev && + pBar.GetDown() >= maPrev && + // + bar.open >= ma && + // + hasBearishPullback && + // + false + // + ; + + // + // Bearish ... + // -------------- + // -[] a Bearish Wave Which Crossed Under MA ... + // -[] Trend is Bearish ... + // -[] PullBack to MA ... + // -[] Has a Bearish Rejection ... + bool hasBearishSignal = + // + false + // pBar.IsBearish() && + // pBar.high > maPrev && + // pBar.GetUp() <= maPrev && + // // + // bar.open <= ma && + // // + // true + // + ; + + // + // Draw ... + // + + // + long chartID = mXWZPOIDrawer.ChartIdentification(); + int window = mXWZPOIDrawer.SubWindowIdentification(); + + // // + // if (isMACrossedOverBullishOB) + // { + // // + // string name = + // "Bullish_" + + // ToMD5(ToFormatString(pBar.time)); + + // // + // CChartObjectVLine *iLine; + // iLine = new CChartObjectVLine(); + // bool isCreated = iLine.Create( + // chartID, + // name, + // window, + // pBar.time // + // ); + // if (isCreated) + // { + // // + // iLine.Color(clrAqua); + + // // + // mXWZDrawnObjects.Add(iLine); + // } + // } + + // // + // if (isMACrossedUnderBearishOB) + // { + // // + // string name = + // "Bearish_" + + // ToMD5(ToFormatString(pBar.time)); + + // // + // CChartObjectVLine *iLine; + // iLine = new CChartObjectVLine(); + // bool isCreated = iLine.Create( + // chartID, + // name, + // window, + // pBar.time // + // ); + // if (isCreated) + // { + // // + // iLine.Color(clrMagenta); + + // // + // mXWZDrawnObjects.Add(iLine); + // } + // } + + // + bool hasSignal = + (hasBullishSignal || + hasBearishSignal); + if (hasSignal) + { + // + long chartID = mXWZPOIDrawer.ChartIdentification(); + int window = mXWZPOIDrawer.SubWindowIdentification(); + string name = + (hasBullishSignal + ? "Bullish_" + : "Bearish_") + + "Signal_" + ToMD5(ToFormatString(bar.time)); + color signalColor = + hasBullishSignal + ? clrYellow + : clrOrange; + + // + CChartObjectVLine *iSignal; + iSignal = new CChartObjectVLine(); + bool isCreated = iSignal.Create( + chartID, + name, + window, + bar.time // + ); + if (isCreated) + { + // + iSignal.Color(signalColor); + + // + mXWZDrawnObjects.Add(iSignal); + } + + // + bool drawRR = false; + if (drawRR) + { + // + XRR iSigRR; + ENUM_X_POSITION_TYPES type = + hasBullishSignal + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_SHORT; + double sl = hasBullishSignal + ? longSLBuffer[barIndex] + : shortSLBuffer[barIndex]; + + // + isCreated = iSigRR.Init( + _Symbol, + _Period, + sl, + bar.open, + type, + ShortName // + ); + if (!isCreated) + { + return; + } + + // + iSigRR.time = pBar.NextAt(); + + // + XCRRObject *iObj; + isCreated = mXWZPOIDrawer.CreateRR( + iSigRR, + iObj // + ); + if (isCreated) + { + mXWZDrawnObjects.Add(iObj); + } + + // + iSigRR.Clean(); + } + } + + // + bar.Clean(); + pBar.Clean(); +} + +// +// POIS Functions ... + +// +void ConfigurePOIDrawer() +{ + // + if (mXWZPOIDrawer == NULL) + { + return; + } + + // + mXWZPOIDrawer.Prefix(ShortName); + mXWZPOIDrawer.ChartIdentification(ChartID()); + mXWZPOIDrawer.SubWindowIdentification(0); + + // + mXWZPOIDrawer.BullishFVGWidth(1); + mXWZPOIDrawer.BullishFVGStyle(STYLE_DOT); + mXWZPOIDrawer.BullishFVGColor(clrAqua); + + // + mXWZPOIDrawer.BearishFVGWidth(1); + mXWZPOIDrawer.BearishFVGStyle(STYLE_DOT); + mXWZPOIDrawer.BearishFVGColor(clrMagenta); + + // + mXWZPOIDrawer.SupportZoneWidth(1); + mXWZPOIDrawer.SupportZoneStyle(STYLE_DASHDOTDOT); + mXWZPOIDrawer.SupportZoneColor(clrLime); + + // + mXWZPOIDrawer.ResistanceZoneWidth(1); + mXWZPOIDrawer.ResistanceZoneStyle(STYLE_DASHDOTDOT); + mXWZPOIDrawer.ResistanceZoneColor(clrRed); + + // + mXWZPOIDrawer.BullishOrderBlockWidth(4); + mXWZPOIDrawer.BullishOrderBlockStyle(STYLE_DASH); + mXWZPOIDrawer.BullishOrderBlockColor(clrAqua); + + // + mXWZPOIDrawer.BearishOrderBlockWidth(4); + mXWZPOIDrawer.BearishOrderBlockStyle(STYLE_DASH); + mXWZPOIDrawer.BearishOrderBlockColor(clrMagenta); +} + +// +void CalculatedPOIs( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + XOHCL iBar; + bool isInited = iBar.Init( + _Symbol, + _Period, + bar_index // + ); + if (!isInited) + { + // + iBar.Clean(); + return; + } + + // + XOHCL pBar; + isInited = iBar.GetPreviousBar(pBar); + if (!isInited) + { + // + iBar.Clean(); + pBar.Clean(); + return; + } + + // + // POI ... + DetectPOIs(iBar); + UpdatePOIs(iBar); + DrawPOIs(); + + // + iBar.Clean(); + pBar.Clean(); +} + +// +bool CanDetectPOIs() +{ + // + bool result = false; + + // + result = + // + mXWZDetectOrderBlocks || + mXWZDetectFairValueGaps || + mXWZDetectSupportZones || + mXWZDetectResistanceZones + // + ; + + // + return result; +} + +// +void DetectPOIs( + XOHCL &bar // +) +{ + // + if (!CanDetectPOIs()) + { + return; + } + + // + int idx = -1; + int range = 21; + + // + // Detect Order Block ... + + // + if (mXWZDetectOrderBlocks) + { + // + XOHCL obBar; + XCOrderBlock *ob; + ENUM_X_DIRECTION obDir; + bool hasOB = mXWZBarAnalyser.HasOrderBlock( + bar, + obBar, + obDir // + ); + bool hasBullishOB = + hasOB && + IsBullish(obDir); + bool hasBearishOB = + hasOB && + IsBearish(obDir); + if (hasOB) + { + // + ob = new XCOrderBlock(); + bool isInited = ob.Init(obBar, obDir); + if (isInited) + { + // + ENUM_X_DIRECTION iForDir = ob.GetDirection(); + bool isBullish = IsBullish(iForDir); + + // + // Check OB Not Activated ... + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = ob.IsActivated( + iForDir, + activationBar, + isActivationBarBodyIn, + false, + _Period // + ); + + // + if (!isActivated) + { + // + idx = FindIndex( + ob, + mXWZUnActivatedOBs // + ); + if (!IsValidIndex(idx)) + { + // + if (isBullish) + { + lastBullOB = ob; + } + else + { + lastBearOB = ob; + } + + // + Add( + ob, + mXWZUnActivatedOBs // + ); + } + } + else + { + // + idx = FindIndex( + ob, + mXWZActivatedOBs // + ); + if (!IsValidIndex(idx)) + { + // + ob.To(activationBar.time); + + // + Add( + ob, + mXWZActivatedOBs // + ); + } + } + + // + activationBar.Clean(); + } + } + + // + obBar.Clean(); + } + + // + // Detect Fair Value Gap ... + + // + if (mXWZDetectFairValueGaps) + { + // + XOHCL fvgStartBar; + XOHCL fvgEndBar; + XCFVG *fvg; + ENUM_X_DIRECTION fvgDir; + bool hasFVG = mXWZBarAnalyser.HasFairValueGap( + bar, + fvgStartBar, + fvgEndBar, + fvgDir // + ); + bool hasBullishFVG = + hasFVG && + IsBullish(fvgDir); + bool hasBearishFVG = + hasFVG && + IsBearish(fvgDir); + if (hasFVG) + { + // + fvg = new XCFVG(); + bool isInited = fvg.Init( + fvgStartBar, + fvgEndBar, + fvgDir // + ); + if (isInited) + { + // + ENUM_X_DIRECTION iForDir = fvg.GetDirection(); + bool isBullish = IsBullish(iForDir); + + // + // Check OB Not Activated ... + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = fvg.IsActivated( + iForDir, + activationBar, + isActivationBarBodyIn, + false, + _Period // + ); + + // + if (!isActivated) + { + // + idx = FindIndex( + fvg, + mXWZUnActivatedFVGs // + ); + if (!IsValidIndex(idx)) + { + // + if (isBullish) + { + lastBullFVG = fvg; + } + else + { + lastBearFVG = fvg; + } + + // + Add( + fvg, + mXWZUnActivatedFVGs // + ); + } + } + else + { + // + idx = FindIndex( + fvg, + mXWZActivatedFVGs // + ); + if (!IsValidIndex(idx)) + { + // + fvg.To(activationBar.time); + + // + Add( + fvg, + mXWZActivatedFVGs // + ); + } + } + + // + activationBar.Clean(); + } + } + + // + fvgEndBar.Clean(); + fvgStartBar.Clean(); + } + + // + // Detect Support Zone ... + + // + if (mXWZDetectSupportZones) + { + // + XOHCL supportBar; + XCSupportZone *supportZone; + bool hasSupport = mXWZBarAnalyser + .HasSupport( + bar, + supportBar, + range // + ); + if (hasSupport) + { + // + supportZone = new XCSupportZone(); + hasSupport = supportZone.Init( + supportBar, + range, + true // Use Range As Start ... + ); + + // + if (hasSupport) + { + // + // Check OB Not Activated ... + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = supportZone.IsActivated( + X_DIRECTION_BULLISH, + activationBar, + isActivationBarBodyIn, + false, + _Period // + ); + + // + if (!isActivated) + { + // + idx = FindIndex( + supportZone, + mXWZUnActivatedSupportZones // + ); + hasSupport = !IsValidIndex(idx); + if (hasSupport) + { + // + lastSupport = supportZone; + + // + Add( + supportZone, + mXWZUnActivatedSupportZones // + ); + } + } + else + { + // + idx = FindIndex( + supportZone, + mXWZActivatedSupportZones // + ); + hasSupport = !IsValidIndex(idx); + if (hasSupport) + { + // + supportZone.To(activationBar.time); + + // + Add( + supportZone, + mXWZActivatedSupportZones // + ); + } + } + + // + activationBar.Clean(); + } + } + + // + supportBar.Clean(); + } + + // + // Detect Resistance Zone ... + + // + if (mXWZDetectResistanceZones) + { + // + XOHCL resistaneBar; + XCResistanceZone *resistanceZone; + bool hasResistance = mXWZBarAnalyser + .HasResistance( + bar, + resistaneBar, + range // + ); + if (hasResistance) + { + // + resistanceZone = new XCResistanceZone(); + hasResistance = resistanceZone.Init( + resistaneBar, + range, + true // Use Range As Start ... + ); + + // + if (hasResistance) + { + // + // Check OB Not Activated ... + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = resistanceZone.IsActivated( + X_DIRECTION_BULLISH, + activationBar, + isActivationBarBodyIn, + false, + _Period // + ); + + // + if (!isActivated) + { + // + idx = FindIndex( + resistanceZone, + mXWZUnActivatedResistanceZones // + ); + hasResistance = !IsValidIndex(idx); + if (hasResistance) + { + // + lastResistance = resistanceZone; + + // + Add( + resistanceZone, + mXWZUnActivatedResistanceZones // + ); + } + } + else + { + // + idx = FindIndex( + resistanceZone, + mXWZActivatedResistanceZones // + ); + hasResistance = !IsValidIndex(idx); + if (hasResistance) + { + // + resistanceZone.To(activationBar.time); + + // + Add( + resistanceZone, + mXWZActivatedResistanceZones // + ); + } + } + + // + activationBar.Clean(); + } + } + + // + resistaneBar.Clean(); + } + + // +} + +// +void UpdatePOIs( + XOHCL &bar // +) +{ + // + int count = -1; + bool has = false; + bool resetDraws = false; + + // + if (!bar.IsValid()) + { + return; + } + + // + datetime to = bar.time; + + // + // Order Blocks ... + + // + count = ArraySize(mXWZUnActivatedOBs); + has = IsValidSize(count); + if (has) + { + // + XCOrderBlock *tmps[]; + for (int i = 0; i < count; i++) + { + // + // Update To ... + mXWZUnActivatedOBs[i].To(to); + + // + // Check Activation ... + + // + // Check OB Not Activated ... + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = mXWZUnActivatedOBs[i] + .IsActivated( + mXWZUnActivatedOBs[i].GetDirection(), + activationBar, + isActivationBarBodyIn, + false, + _Period // + ); + + // + activationBar.Clean(); + + // + if (!isActivated) + { + // + Add( + mXWZUnActivatedOBs[i], + tmps // + ); + } + else + { + // + Add( + mXWZUnActivatedOBs[i], + mXWZActivatedOBs // + ); + } + } + + // + Copy( + tmps, + mXWZUnActivatedOBs // + ); + } + + // + count = ArraySize(mXWZActivatedOBs); + has = IsValidSize(count); + if (has) + { + // + // Remove UnWorks / Breaked Zones ... + int removeIDX[]; + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iZone = mXWZActivatedOBs[i]; + + // + XOHCL passedBar; + bool isBodyOut = false; + ENUM_X_DIRECTION iForDir = iZone.GetDirection(); + + // + // Check Works ... + bool isWorked = iZone.IsWorked( + iForDir, + passedBar, + isBodyOut, + true, + false, + false, + _Period // + ); + if (!isWorked) + { + // + Add( + i, + removeIDX // + ); + + // + passedBar.Clean(); + break; + } + + // + passedBar.Clean(); + } + + // + if (HasChild(removeIDX)) + { + // + resetDraws = true; + + // + count = ArraySize(removeIDX); + for (int i = 0; i < count; i++) + { + // + ArrayRemove( + mXWZActivatedOBs, + removeIDX[i], + 1 // + ); + } + } + + // + Clean(removeIDX); + } + + // + // Fair Value Gaps ... + + // + count = ArraySize(mXWZUnActivatedFVGs); + has = IsValidSize(count); + if (has) + { + // + XCFVG *tmps[]; + for (int i = 0; i < count; i++) + { + // + // Update To ... + mXWZUnActivatedFVGs[i].To(to); + + // + // Check Activation ... + + // + // Check OB Not Activated ... + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = mXWZUnActivatedFVGs[i] + .IsActivated( + mXWZUnActivatedFVGs[i].GetDirection(), + activationBar, + isActivationBarBodyIn, + false, + _Period // + ); + + // + activationBar.Clean(); + + // + if (!isActivated) + { + // + Add( + mXWZUnActivatedFVGs[i], + tmps // + ); + } + else + { + // + Add( + mXWZUnActivatedFVGs[i], + mXWZActivatedFVGs // + ); + } + } + + // + Copy( + tmps, + mXWZUnActivatedFVGs // + ); + } + + // + count = ArraySize(mXWZActivatedFVGs); + has = IsValidSize(count); + if (has) + { + // + // Remove UnWorks / Breaked Zones ... + int removeIDX[]; + for (int i = 0; i < count; i++) + { + // + XCFVG *iZone = mXWZActivatedFVGs[i]; + + // + XOHCL passedBar; + bool isBodyOut = false; + ENUM_X_DIRECTION iForDir = iZone.GetDirection(); + + // + // Check Works ... + bool isWorked = iZone.IsWorked( + iForDir, + passedBar, + isBodyOut, + true, + false, + false, + _Period // + ); + if (!isWorked) + { + // + Add( + i, + removeIDX // + ); + + // + passedBar.Clean(); + break; + } + + // + passedBar.Clean(); + } + + // + if (HasChild(removeIDX)) + { + // + resetDraws = true; + + // + count = ArraySize(removeIDX); + for (int i = 0; i < count; i++) + { + // + ArrayRemove( + mXWZActivatedFVGs, + removeIDX[i], + 1 // + ); + } + } + + // + Clean(removeIDX); + } + + // + // Support Zones ... + + // + count = ArraySize(mXWZUnActivatedSupportZones); + has = IsValidSize(count); + if (has) + { + // + XCSupportZone *tmps[]; + for (int i = 0; i < count; i++) + { + // + // Update To ... + mXWZUnActivatedSupportZones[i].To(to); + + // + // Check Activation ... + + // + // Check OB Not Activated ... + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = mXWZUnActivatedSupportZones[i] + .IsActivated( + X_DIRECTION_BULLISH, + activationBar, + isActivationBarBodyIn, + false, + _Period // + ); + + // + if (!isActivated) + { + // + Add( + mXWZUnActivatedSupportZones[i], + tmps // + ); + } + else + { + // + mXWZUnActivatedSupportZones[i].To(activationBar.time); + + // + Add( + mXWZUnActivatedSupportZones[i], + mXWZActivatedSupportZones // + ); + } + + // + activationBar.Clean(); + } + + // + Copy( + tmps, + mXWZUnActivatedSupportZones // + ); + } + + // + count = ArraySize(mXWZActivatedSupportZones); + has = IsValidSize(count); + if (has) + { + // + // Remove UnWorks / Breaked Zones ... + int removeIDX[]; + ENUM_X_DIRECTION iForDir = X_DIRECTION_BULLISH; + for (int i = 0; i < count; i++) + { + // + XCSupportZone *iZone = mXWZActivatedSupportZones[i]; + + // + XOHCL passedBar; + bool isBodyOut = false; + + // + // Check Works ... + bool isWorked = iZone.IsWorked( + iForDir, + passedBar, + isBodyOut, + true, + false, + false, + _Period // + ); + if (!isWorked) + { + // + Add( + i, + removeIDX // + ); + + // + passedBar.Clean(); + break; + } + + // + passedBar.Clean(); + } + + // + if (HasChild(removeIDX)) + { + // + resetDraws = true; + + // + count = ArraySize(removeIDX); + for (int i = 0; i < count; i++) + { + // + ArrayRemove( + mXWZActivatedSupportZones, + removeIDX[i], + 1 // + ); + } + } + + // + Clean(removeIDX); + } + + // + // Resistance Zones ... + + // + count = ArraySize(mXWZUnActivatedResistanceZones); + has = IsValidSize(count); + if (has) + { + // + XCResistanceZone *tmps[]; + for (int i = 0; i < count; i++) + { + // + // Update To ... + mXWZUnActivatedResistanceZones[i].To(to); + + // + // Check Activation ... + + // + // Check OB Not Activated ... + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = mXWZUnActivatedResistanceZones[i] + .IsActivated( + X_DIRECTION_BULLISH, + activationBar, + isActivationBarBodyIn, + false, + _Period // + ); + + // + if (!isActivated) + { + // + Add( + mXWZUnActivatedResistanceZones[i], + tmps // + ); + } + else + { + // + mXWZUnActivatedResistanceZones[i].To(activationBar.time); + + // + Add( + mXWZUnActivatedResistanceZones[i], + mXWZActivatedResistanceZones // + ); + } + + // + activationBar.Clean(); + } + + // + Copy( + tmps, + mXWZUnActivatedResistanceZones // + ); + } + + // + count = ArraySize(mXWZActivatedResistanceZones); + has = IsValidSize(count); + if (has) + { + // + // Remove UnWorks / Breaked Zones ... + int removeIDX[]; + ENUM_X_DIRECTION iForDir = X_DIRECTION_BEARISH; + for (int i = 0; i < count; i++) + { + // + XCResistanceZone *iZone = mXWZActivatedResistanceZones[i]; + + // + XOHCL passedBar; + bool isBodyOut = false; + + // + // Check Breake ... + bool isBreaked = iZone.IsBreaked( + iForDir, + passedBar, + isBodyOut, + true, + false, + _Period // + ); + if (isBreaked) + { + // + Add( + i, + removeIDX // + ); + + // + passedBar.Clean(); + break; + } + + // + // Check Works ... + bool isWorked = iZone.IsWorked( + iForDir, + passedBar, + isBodyOut, + true, + false, + false, + _Period // + ); + if (!isWorked) + { + // + Add( + i, + removeIDX // + ); + + // + passedBar.Clean(); + break; + } + + // + passedBar.Clean(); + } + + // + if (HasChild(removeIDX)) + { + // + resetDraws = true; + + // + count = ArraySize(removeIDX); + for (int i = 0; i < count; i++) + { + // + ArrayRemove( + mXWZActivatedResistanceZones, + removeIDX[i], + 1 // + ); + } + } + + // + Clean(removeIDX); + } + + // + // + // + + // + // Clean Draws if has to ... + if (resetDraws) + { + mXWZDrawnObjects.Clear(); + } + + // +} + +// +void DrawPOIs() +{ + // + int count = 0; + bool has = false; + bool isCreated = false; + + // + if (!showPOIs) + { + return; + } + + // + // Order Blocks ... + if (showOrderBlocks) + { + // + bool showBullishOrderBlocks = true; + bool showBearishOrderBlocks = true; + + // + // UnActivated ... + count = ArraySize(mXWZUnActivatedOBs); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + bool isBullish = mXWZUnActivatedOBs[i].IsBullish(); + + // + if ((isBullish && + showBullishOrderBlocks) || + (!isBullish && + showBearishOrderBlocks)) + { + // + XCBaseObject *iObj; + isCreated = mXWZPOIDrawer + .CreateOrderBlock( + mXWZUnActivatedOBs[i], + iObj // + ); + if (isCreated) + { + mXWZDrawnObjects.Add(iObj); + } + } + } + } + + // + // Activated ... + count = ArraySize(mXWZActivatedOBs); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iOB = mXWZActivatedOBs[i]; + + // + bool isBullish = iOB.IsBullish(); + + // + if (showActivatedPOIs && + ((isBullish && + showBullishOrderBlocks) || + (!isBullish && + showBearishOrderBlocks))) + { + // + XCBaseObject *iObj; + isCreated = mXWZPOIDrawer + .CreateOrderBlock( + iOB, + iObj // + ); + if (isCreated) + { + // + // if (isBullish) + // { + // ((XCBullishOrderBlockObject *)iObj).ZoneFill(true); + // } + // else + // { + // ((XCBearishOrderBlockObject *)iObj).ZoneFill(true); + // } + + // + mXWZDrawnObjects.Add(iObj); + } + } + } + } + } + + // + // Fair Value Gaps ... + if (showFairValueGaps) + { + // + bool showBullishFairValueGaps = true; + bool showBearishFairValueGaps = true; + + // + // UnActivated ... + count = ArraySize(mXWZUnActivatedFVGs); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + bool isBullish = mXWZUnActivatedFVGs[i].IsBullish(); + + // + if ((isBullish && + showBullishFairValueGaps) || + (!isBullish && + showBearishFairValueGaps)) + { + // + XCBaseObject *iObj; + isCreated = mXWZPOIDrawer + .CreateFairValueGap( + mXWZUnActivatedFVGs[i], + iObj // + ); + if (isCreated) + { + mXWZDrawnObjects.Add(iObj); + } + } + } + } + + // + // Activated ... + count = ArraySize(mXWZActivatedFVGs); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + XCFVG *iFVG = mXWZActivatedFVGs[i]; + + // + bool isBullish = iFVG.IsBullish(); + + // + if (showActivatedPOIs && + ((isBullish && + showBullishFairValueGaps) || + (!isBullish && + showBearishFairValueGaps))) + { + XCBaseObject *iObj; + isCreated = mXWZPOIDrawer + .CreateFairValueGap( + iFVG, + iObj // + ); + if (isCreated) + { + // + // if (isBullish) + // { + // ((XCBullishOrderBlockObject *)iObj).ZoneFill(true); + // } + // else + // { + // ((XCBearishOrderBlockObject *)iObj).ZoneFill(true); + // } + + // + mXWZDrawnObjects.Add(iObj); + } + } + } + } + } + + // + // Support Zones ... + if (showSupportZones) + { + // + // UnActivated ... + count = ArraySize(mXWZUnActivatedSupportZones); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + XCSupportZoneObject *iObj; + isCreated = mXWZPOIDrawer + .CreateSupportZone( + mXWZUnActivatedSupportZones[i], + iObj // + ); + if (isCreated) + { + mXWZDrawnObjects.Add(iObj); + } + } + } + + // + // Activated ... + if (showActivatedPOIs) + { + // + count = ArraySize(mXWZActivatedSupportZones); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + XCSupportZoneObject *iObj; + isCreated = mXWZPOIDrawer + .CreateSupportZone( + mXWZActivatedSupportZones[i], + iObj // + ); + if (isCreated) + { + mXWZDrawnObjects.Add(iObj); + } + } + } + } + } + + // + // Resistance Zones ... + if (showResistanceZones) + { + // + // UnActivated ... + count = ArraySize(mXWZUnActivatedResistanceZones); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + XCResistanceZoneObject *iObj; + isCreated = mXWZPOIDrawer + .CreateResistanceZone( + mXWZUnActivatedResistanceZones[i], + iObj // + ); + if (isCreated) + { + mXWZDrawnObjects.Add(iObj); + } + } + } + + // + // Activated ... + if (showActivatedPOIs) + { + // + count = ArraySize(mXWZActivatedResistanceZones); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + XCResistanceZoneObject *iObj; + isCreated = mXWZPOIDrawer + .CreateResistanceZone( + mXWZActivatedResistanceZones[i], + iObj // + ); + if (isCreated) + { + mXWZDrawnObjects.Add(iObj); + } + } + } + } + } + + // +} + +// \ No newline at end of file diff --git a/BKPS/14031218/Documents/BKP/x-saherelm.xobfvg.lib.mq5 b/BKPS/14031218/Documents/BKP/x-saherelm.xobfvg.lib.mq5 new file mode 100644 index 0000000..3939603 --- /dev/null +++ b/BKPS/14031218/Documents/BKP/x-saherelm.xobfvg.lib.mq5 @@ -0,0 +1,1897 @@ +// /////////////////////////////////////////////////////// +// // +// // SaherElm IT Center MQL5 Seriallize Library +// // --------------------------------------- +// // Name: XOBFVGLib +// // Description: All models related to POIs ... +// // +// // +// // Maintainer: +// // ------------ +// // Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// // +// ////////////////////////////////////////////////////// +// // +// // Global Properties ... +// #property library +// #property copyright "Copyright `023, SaherElm IT Center" +// #property link "https://www.saherelm.ir" +// #property version "1.00" +// #property strict + +// // +// // Imports ... +// #include "../Libraries/x-saherelm.x-poi.state.lib.mq5" + +// // +// struct XOBFVGPivot +// { +// // +// // Props ... +// double value; +// datetime at; + +// // +// // Constructor ... +// XOBFVGPivot() +// { +// Clean(); +// } + +// // +// // Tools ... + +// // +// void Clean() +// { +// // +// value = 0; +// at = NULL; + +// // +// ZeroMemory(this); +// } + +// // +// bool IsValid() +// { +// // +// bool result = false; + +// // +// result = +// value > 0 && +// IsValid(at); + +// // +// return result; +// } +// }; + +// // +// struct XOBFVG +// { +// // +// // Props ... +// XCFVG *fvg; +// XCOrderBlock *ob; + +// // +// XCSupplyZone *supplyZones[]; +// XCDemandZone *demandZones[]; + +// // +// XCSupportZone *supportZones[]; +// XCResistanceZone *resistanceZones[]; + +// // +// // Constructor ... +// XOBFVG() +// { +// Clean(); +// } + +// // +// // Tools ... + +// // +// void Clean() +// { +// // +// ZeroMemory(ob); +// ZeroMemory(fvg); + +// // +// Clean(supplyZones); +// Clean(demandZones); +// Clean(supportZones); +// Clean(resistanceZones); + +// // +// ZeroMemory(this); +// } + +// // +// bool IsValid() +// { +// return HasOB() && +// HasFVG(); +// } + +// // +// bool HasOB() +// { +// return ob != NULL && +// ob.IsValid(); +// } + +// // +// bool HasFVG() +// { +// return fvg != NULL && +// fvg.IsValid(); +// } + +// // +// bool HasSupplyZones() +// { +// return HasChild(supplyZones); +// } + +// // +// int CountSupplyZones() +// { +// return ArraySize(supplyZones); +// } + +// // +// bool HasDemandZones() +// { +// return HasChild(demandZones); +// } + +// // +// int CountDemandZones() +// { +// return ArraySize(demandZones); +// } + +// // +// bool HasSupportZones() +// { +// return HasChild(supportZones); +// } + +// // +// int CountSupportZones() +// { +// return ArraySize(supportZones); +// } + +// // +// bool HasResistanceZones() +// { +// return HasChild(resistanceZones); +// } + +// // +// int CountResistanceZones() +// { +// return ArraySize(resistanceZones); +// } + +// // +// ENUM_X_DIRECTION GetDirection() +// { +// // +// ENUM_X_DIRECTION result = X_DIRECTION_NONE; + +// // +// bool isValid = IsValid(); +// if (!isValid) +// { +// return result; +// } + +// // +// result = ob.GetDirection(); + +// // +// return result; +// } + +// // +// bool IsBullish() +// { +// return IsBullish(GetDirection()); +// } + +// // +// bool IsBearish() +// { +// return IsBearish(GetDirection()); +// } + +// // +// int GetSwings( +// XOBFVGPivot &pivots[] // +// ) +// { +// // +// int result = 0; + +// // +// Clean(pivots); + +// // +// if (!IsValid()) +// { +// return result; +// } + +// // +// ENUM_X_DIRECTION forDir = GetDirection(); +// bool isBullish = IsBullish(forDir); + +// // +// XOHCL passedBar; +// XOBFVGPivot iPivot; +// bool isPassed = false; +// double appliedPrice = 0; +// bool isBodyState = false; + +// // +// // Start ... +// isPassed = ob.IsStarted( +// forDir, +// passedBar, +// isBodyState // +// ); +// if (isPassed) +// { +// // +// appliedPrice = +// isBullish +// ? passedBar.low +// : passedBar.high; + +// // +// iPivot.Clean(); +// iPivot.value = appliedPrice; +// iPivot.at = passedBar.time; + +// // +// AddRef( +// iPivot, +// pivots // +// ); + +// // +// iPivot.Clean(); +// } + +// // +// // Activation ... +// isPassed = ob.IsActivated( +// forDir, +// passedBar, +// isBodyState // +// ); +// if (isPassed) +// { +// // +// appliedPrice = +// isBullish +// ? passedBar.low +// : passedBar.high; + +// // +// iPivot.Clean(); +// iPivot.value = appliedPrice; +// iPivot.at = passedBar.time; + +// // +// AddRef( +// iPivot, +// pivots // +// ); + +// // +// iPivot.Clean(); +// } + +// // +// // Worked ... +// isPassed = ob.IsWorked( +// forDir, +// passedBar, +// isBodyState // +// ); +// if (isPassed) +// { +// // +// appliedPrice = +// isBullish +// ? passedBar.low +// : passedBar.high; + +// // +// iPivot.Clean(); +// iPivot.value = appliedPrice; +// iPivot.at = passedBar.time; + +// // +// AddRef( +// iPivot, +// pivots // +// ); + +// // +// iPivot.Clean(); +// } + +// // +// passedBar.Clean(); + +// // +// result = ArraySize(pivots); + +// // +// return result; +// } + +// // +// void UpdateZones( +// XPOIState &state // +// ) +// { +// // +// Clean(supplyZones); +// Clean(demandZones); +// Clean(supportZones); +// Clean(resistanceZones); + +// // +// bool isValid = +// IsValid() && +// state.HasChild(); +// if (!isValid) +// { +// return; +// } + +// // +// int count = 0; +// bool has = false; +// bool isPassed = false; + +// // +// // Supply Zones ... +// has = state.HasSupplyZones(); +// if (has) +// { +// // +// count = state.CountSupplyZones(); +// for (int i = 0; i < count; i++) +// { +// // +// XCSupplyZone *iZone = state.supplyZones[i]; + +// // +// isPassed = iZone.From() > ob.From(); +// if (!isPassed) +// { +// // +// ZeroMemory(iZone); +// continue; +// } + +// // +// isPassed = IsInsideDiff( +// iZone, +// ob // +// ); +// if (!isPassed) +// { +// // +// ZeroMemory(iZone); +// continue; +// } + +// // +// Add( +// iZone, +// supplyZones // +// ); +// } +// } + +// // +// // Demand Zones ... +// has = state.HasDemandZones(); +// if (has) +// { +// // +// count = state.CountDemandZones(); +// for (int i = 0; i < count; i++) +// { +// // +// XCDemandZone *iZone = state.demandZones[i]; + +// // +// isPassed = iZone.From() > ob.From(); +// if (!isPassed) +// { +// // +// ZeroMemory(iZone); +// continue; +// } + +// // +// isPassed = IsInsideDiff( +// iZone, +// ob // +// ); +// if (!isPassed) +// { +// // +// ZeroMemory(iZone); +// continue; +// } + +// // +// Add( +// iZone, +// demandZones // +// ); +// } +// } + +// // +// // Support Zones ... +// has = state.HasSupportZones(); +// if (has) +// { +// // +// count = state.CountSupportZones(); +// for (int i = 0; i < count; i++) +// { +// // +// XCSupportZone *iZone = state.supportZones[i]; + +// // +// isPassed = iZone.From() > ob.From(); +// if (!isPassed) +// { +// // +// ZeroMemory(iZone); +// continue; +// } + +// // +// isPassed = IsInsideDiff( +// iZone, +// ob // +// ); +// if (!isPassed) +// { +// // +// ZeroMemory(iZone); +// continue; +// } + +// // +// Add( +// iZone, +// supportZones // +// ); +// } +// } + +// // +// // Resistance Zones ... +// has = state.HasResistanceZones(); +// if (has) +// { +// // +// count = state.CountResistanceZones(); +// for (int i = 0; i < count; i++) +// { +// // +// XCResistanceZone *iZone = state.resistanceZones[i]; + +// // +// isPassed = iZone.From() > ob.From(); +// if (!isPassed) +// { +// // +// ZeroMemory(iZone); +// continue; +// } + +// // +// isPassed = IsInsideDiff( +// iZone, +// ob // +// ); +// if (!isPassed) +// { +// // +// ZeroMemory(iZone); +// continue; +// } + +// // +// Add( +// iZone, +// resistanceZones // +// ); +// } +// } +// } + +// // +// void UpdateTo(datetime value = NULL) +// { +// // +// value = NormalizeTime(value); + +// // +// int count = 0; +// bool has = false; + +// // +// has = HasOB(); +// if (has) +// { +// ob.To(value); +// } + +// // +// has = HasFVG(); +// if (has) +// { +// fvg.To(value); +// } + +// // +// // Supply Zones ... +// has = HasSupplyZones(); +// if (has) +// { +// // +// count = CountSupplyZones(); +// for (int i = 0; i < count; i++) +// { +// supplyZones[i].To(value); +// } +// } + +// // +// // Demand Zones ... +// has = HasDemandZones(); +// if (has) +// { +// // +// count = CountDemandZones(); +// for (int i = 0; i < count; i++) +// { +// demandZones[i].To(value); +// } +// } + +// // +// // Support Zones ... +// has = HasSupportZones(); +// if (has) +// { +// // +// count = CountSupportZones(); +// for (int i = 0; i < count; i++) +// { +// supportZones[i].To(value); +// } +// } + +// // +// // Resistance Zones ... +// has = HasResistanceZones(); +// if (has) +// { +// // +// count = CountResistanceZones(); +// for (int i = 0; i < count; i++) +// { +// resistanceZones[i].To(value); +// } +// } +// } +// }; + +// // +// // +// // + +// /** +// * Extract XOBFVG Collection of Market ... +// * +// * @param htfState: Higher Time Frame POI State (Used For Detecting Order Blocks) ... +// * @param mtfState: Medium Time Frame POI State (Used For Detecting Fair Value Gaps) ... +// * @param stfState: Short Time Frame POI State (Used For Detecting Other POI(s)) ... +// * @param dest: Result Collection ... +// * @param forDir: Market Direction for Detecting POI(s) ... +// * @param forPeriod: Time Frame which Used for Zones actions (NULL for Default) ... +// * @param startState: Zones Start State ... +// * @param forceStartedBodyOut: Zones Started Bar's Body State ... +// * @param activeState: Zones Activation State ... +// * @param forceActivatedBodyIn: Zones Activated Bar's Body State ... +// * @param breakState: Zones Breaked State ... +// * @param forceBreakedBodyOut: Zone Breaker Bar's Body State ... +// * @param workState: Zones Worked State ... +// * @param forceWorkedBodyOut: Zones Worked Bar's Body State ... +// * @param applySort: Specify Applying Sorting on Collections ... +// * @param applyFromFilter: Filter Sorted Zones based on Occured Date ... +// * @param applyPlaceFilter: Filter Sorted Zones based on Occured Place ... +// * @param ignoreInside: Ignore Inside Sides of POI(s) Zones in Related to Order Block ... +// * @param applyFromFilterForPOIs: Apply From Filter for Other POI(s) ... +// * +// * @return ( int ) +// */ +// int ExtractOBFVGZones( +// XPOIState &htfState, +// XPOIState &mtfState, +// XPOIState &stfState, +// XOBFVG &dest[], +// // +// ENUM_X_DIRECTION forDir, +// ENUM_TIMEFRAMES forPeriod = NULL, +// // +// // Start ... +// ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, +// bool forceStartedBodyOut = false, +// // +// // Activation ... +// ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, +// bool forceActivatedBodyIn = false, +// // +// // Breaktion ... +// ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, +// bool forceBreakedBodyOut = false, +// // +// // Works ... +// ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, +// bool forceWorkedBodyOut = false, +// // +// bool applySort = true, +// bool applyFromFilter = true, +// bool applyPlaceFilter = true, +// // +// bool ignoreInside = true, +// // +// bool detectInsideOBPOIs = true, +// bool detectInsideFVGPOIs = true, +// bool applyFromFilterForPOIs = true +// // +// ) +// { +// // +// int result = 0; + +// // +// Clean(dest); + +// // +// bool isValid = +// // +// htfState.HasChild() && +// mtfState.HasChild() && +// stfState.HasChild() && +// HasDirection(forDir) +// // +// ; +// if (!isValid) +// { +// return result; +// } + +// // +// // Implement Logic ... + +// // +// int idx = -1; +// int count = 0; +// bool has = false; +// XCFVG *tmpFVGs[]; +// XOBFVG tmpOBFVGs[]; +// XCOrderBlock *tmpOBs[]; +// XCOrderBlock *tmpWorkingOBs[]; +// datetime cTime = TimeCurrent(); +// bool isBullish = IsBullish(forDir); + +// // +// if (isBullish) +// { +// // +// has = htfState.HasBullishOrderBlocks(); +// if (has) +// { +// // +// Copy( +// htfState.bullishOrderBlocks, +// tmpOBs // +// ); + +// // +// has = mtfState.HasBullishFairValueGaps(); +// if (has) +// { +// // +// Copy( +// mtfState.bullishFairValueGaps, +// tmpFVGs // +// ); +// } +// } +// } +// else +// { +// // +// has = htfState.HasBearishOrderBlocks(); +// if (has) +// { +// // +// Copy( +// htfState.bearishOrderBlocks, +// tmpOBs // +// ); + +// // +// has = mtfState.HasBearishFairValueGaps(); +// if (has) +// { +// // +// Copy( +// mtfState.bearishFairValueGaps, +// tmpFVGs // +// ); +// } +// } +// } + +// // +// count = ArraySize(tmpOBs); +// has = IsValidSize(count); +// if (has) +// { +// // +// for (int i = 0; i < count; i++) +// { +// // +// XCOrderBlock *iOB = tmpOBs[i]; + +// // +// // Check Started State ... +// if (startState == XZONE_STATE_PASSED || +// startState == XZONE_STATE_FAILED) +// { +// // +// XOHCL passedBar; +// bool isBodyOut = false; +// bool isStarted = iOB.IsStarted( +// forDir, +// passedBar, +// isBodyOut, +// forPeriod // +// ); + +// // +// bool isPassed = +// startState == XZONE_STATE_FAILED +// ? !isStarted +// : !forceStartedBodyOut +// ? isStarted +// : isStarted && +// isBodyOut; + +// // +// passedBar.Clean(); +// if (!isPassed) +// { +// continue; +// } +// } + +// // +// // Check Activation State ... +// if (activeState == XZONE_STATE_PASSED || +// activeState == XZONE_STATE_FAILED) +// { +// // +// XOHCL passedBar; +// bool isBodyIn = false; +// bool isActivated = iOB.IsActivated( +// forDir, +// passedBar, +// isBodyIn, +// forceStartedBodyOut, +// forPeriod // +// ); + +// // +// bool isPassed = +// activeState == XZONE_STATE_FAILED +// ? !isActivated +// : !forceActivatedBodyIn +// ? isActivated +// : isActivated && +// isBodyIn; + +// // +// passedBar.Clean(); +// if (!isPassed) +// { +// continue; +// } +// } + +// // +// // Check Break State ... +// if (breakState == XZONE_STATE_PASSED || +// breakState == XZONE_STATE_FAILED) +// { +// // +// XOHCL passedBar; +// bool isBodyOut = false; +// bool isBreaked = iOB.IsBreaked( +// forDir, +// passedBar, +// isBodyOut, +// forceStartedBodyOut, +// forPeriod // +// ); + +// // +// bool isPassed = +// breakState == XZONE_STATE_FAILED +// ? !isBreaked +// : !forceBreakedBodyOut +// ? isBreaked +// : isBreaked && +// isBodyOut; + +// // +// passedBar.Clean(); +// if (!isPassed) +// { +// continue; +// } +// } + +// // +// // Check Work State ... +// if (workState == XZONE_STATE_PASSED || +// workState == XZONE_STATE_FAILED) +// { +// // +// bool ignoreActivation = activeState != XZONE_STATE_PASSED; + +// // +// XOHCL passedBar; +// bool isBodyOut = false; +// bool isWorked = iOB.IsWorked( +// forDir, +// passedBar, +// isBodyOut, +// ignoreActivation, +// forceStartedBodyOut, +// forceActivatedBodyIn, +// forPeriod // +// ); + +// // +// bool isPassed = +// workState == XZONE_STATE_FAILED +// ? !isWorked +// : !forceWorkedBodyOut +// ? isWorked +// : isWorked && +// isBodyOut; + +// // +// passedBar.Clean(); +// if (!isPassed) +// { +// continue; +// } +// } + +// // +// has = FindIndex( +// idx, +// iOB, +// tmpWorkingOBs // +// ); +// if (has) +// { +// // +// ZeroMemory(iOB); +// continue; +// } + +// // +// Add( +// iOB, +// tmpWorkingOBs // +// ); +// } +// } + +// // +// // Clean ... +// Clean(tmpOBs); +// has = HasChild(tmpWorkingOBs); +// if (has) +// { +// // +// Clean(tmpOBs); +// Copy( +// tmpWorkingOBs, +// tmpOBs // +// ); + +// // +// Clean(tmpWorkingOBs); +// } + +// // +// // Sorting ... +// if (applySort) +// { +// // +// Clean(tmpWorkingOBs); +// has = HasChild(tmpOBs); +// count = ArraySize(tmpOBs); + +// // +// // Sorting Applied Only when there is more than one item ... +// if (has && count > 1) +// { +// // +// bool hasLast = false; +// XCOrderBlock *last = NULL; +// while (HasChild(tmpOBs)) +// { +// // +// // Extract First Last Item ... +// if (!hasLast) +// { +// // +// idx = +// isBullish +// ? GetLowest(tmpOBs) +// : GetHighest(tmpOBs); +// hasLast = IsValidIndex(idx); +// if (hasLast) +// { +// // +// last = tmpOBs[idx]; +// ArrayRemove( +// tmpOBs, +// idx, +// 1 // +// ); + +// // +// Add( +// last, +// tmpWorkingOBs // +// ); +// } +// } + +// // +// has = false; +// XCOrderBlock *iOB = NULL; +// idx = +// isBullish +// ? GetLowest(tmpOBs) +// : GetHighest(tmpOBs); +// has = IsValidIndex(idx); +// if (has) +// { +// // +// iOB = tmpOBs[idx]; +// ArrayRemove( +// tmpOBs, +// idx, +// 1 // +// ); +// } + +// // +// if (!has) +// { +// break; +// } + +// // +// // Apply From Filter ... +// if (applyFromFilter) +// { +// // +// bool isFromPassed = +// hasLast && +// last.From() < iOB.From(); +// if (!isFromPassed) +// { +// continue; +// } +// } + +// // +// // Apply Place Filter ... +// if (applyPlaceFilter) +// { +// // +// bool isAbove = +// hasLast && +// IsAbove( +// iOB, +// last, +// ignoreInside // +// ); + +// // +// bool isBelow = +// hasLast && +// IsBelow( +// iOB, +// last, +// ignoreInside // +// ); + +// // +// bool isPlacePassed = +// isBullish +// ? isAbove +// : isBelow; +// if (!isPlacePassed) +// { +// continue; +// } +// } + +// // +// last = iOB; +// Add( +// iOB, +// tmpWorkingOBs // +// ); +// } + +// // +// if (hasLast && +// !HasChild(tmpWorkingOBs)) +// { +// // +// Add( +// last, +// tmpWorkingOBs // +// ); +// } +// } +// else +// { +// // +// Copy( +// tmpOBs, +// tmpWorkingOBs // +// ); +// } + +// // +// if (HasChild(tmpWorkingOBs)) +// { +// // +// Copy( +// tmpWorkingOBs, +// tmpOBs // +// ); +// } +// // +// } + +// // +// count = ArraySize(tmpOBs); +// has = IsValidSize(count); + +// // +// // Converts to XOBFVG ... +// if (has) +// { +// // +// for (int i = 0; i < count; i++) +// { +// // +// XOBFVG iOBFVG; + +// // +// iOBFVG.ob = tmpOBs[i]; + +// // +// AddRef( +// iOBFVG, +// tmpOBFVGs // +// ); + +// // +// iOBFVG.Clean(); +// } +// } + +// // +// Clean(dest); +// Clean(tmpOBs); +// Clean(tmpWorkingOBs); + +// // +// // Here we Going to Complete XOBFVGs ... +// has = HasChild(tmpOBFVGs); +// if (has && HasChild(tmpFVGs)) +// { +// // +// count = ArraySize(tmpOBFVGs); +// for (int i = 0; i < count; i++) +// { +// // +// XOBFVG iOBFVG = tmpOBFVGs[i]; + +// // +// // Detecting FVG ... +// XCFVG *tmpWorkingFVGs[]; +// for (int j = 0; j < ArraySize(tmpFVGs); j++) +// { +// // +// XCFVG *jFVG = tmpFVGs[j]; + +// // +// // Check Start Date ... +// bool isFromPassed = jFVG.From() > iOBFVG.ob.From(); +// if (!isFromPassed) +// { +// // +// ZeroMemory(jFVG); +// continue; +// } + +// // +// // Check Place ... + +// // +// bool isAbove = IsAboveDiff( +// jFVG, +// iOBFVG.ob, +// ignoreInside // +// ); + +// // +// bool isBelow = IsBelowDiff( +// jFVG, +// iOBFVG.ob, +// ignoreInside // +// ); + +// // +// bool isInside = IsInsideDiff( +// jFVG, +// iOBFVG.ob, +// false // +// ); + +// // +// bool isPlacePassed = +// isInside || +// (isBullish +// ? isAbove +// : isBelow); +// if (!isPlacePassed) +// { +// // +// ZeroMemory(jFVG); +// continue; +// } + +// // +// Add( +// jFVG, +// tmpWorkingFVGs // +// ); +// } + +// // +// int fvgsCount = ArraySize(tmpWorkingFVGs); +// has = IsValidSize(fvgsCount); +// if (has) +// { +// // +// idx = +// isBullish +// ? GetLowest(tmpWorkingFVGs) +// : GetHighest(tmpWorkingFVGs); + +// // +// if (IsValidIndex(idx)) +// { +// // +// XCFVG *selectedFVG = tmpWorkingFVGs[idx]; + +// // +// iOBFVG.fvg = selectedFVG; + +// // +// bool isExists = FindIndex( +// idx, +// selectedFVG, +// tmpFVGs // +// ); +// if (isExists) +// { +// // +// ArrayRemove( +// tmpFVGs, +// idx, +// 1 // +// ); +// } +// } +// } +// Clean(tmpWorkingFVGs); + +// // +// bool isFVGPassed = iOBFVG.HasFVG(); +// if (!isFVGPassed) +// { +// // +// iOBFVG.Clean(); +// continue; +// } + +// // +// // Validate Model ... +// bool isValid = iOBFVG.IsValid(); +// if (!isValid) +// { +// // +// iOBFVG.Clean(); +// continue; +// } + +// // +// iOBFVG.UpdateTo(cTime); + +// // +// AddRef( +// iOBFVG, +// dest // +// ); + +// // +// iOBFVG.Clean(); +// } + +// // +// Clean(tmpOBFVGs); +// } + +// // +// // Detecting Other POI(s) ... +// has = HasChild(dest); +// bool canDetectPOIs = +// detectInsideOBPOIs || +// detectInsideFVGPOIs; +// if (has && +// canDetectPOIs) +// { +// // +// count = ArraySize(dest); +// for (int i = 0; i < count; i++) +// { +// // +// // Supply Zones ... +// has = stfState.HasSupplyZones(); +// if (has) +// { +// // +// for (int j = 0; j < stfState.CountSupplyZones(); j++) +// { +// // +// bool isInsideOB = IsInsideDiff( +// stfState.supplyZones[j], +// dest[i].ob // +// ); + +// // +// bool isInsideFVG = IsInsideDiff( +// stfState.supplyZones[j], +// dest[i].fvg // +// ); + +// // +// bool isInside = isInsideOB || +// isInsideFVG; +// if (isInside) +// { +// // +// bool isPassed = +// detectInsideOBPOIs +// ? isInsideOB +// : detectInsideFVGPOIs +// ? isInsideFVG +// : false; +// if (isPassed) +// { +// // +// isPassed = +// !applyFromFilterForPOIs +// ? isPassed +// : isInsideOB +// ? stfState.supplyZones[j].From() > dest[i].ob.From() +// : isInsideFVG +// ? stfState.supplyZones[j].From() > dest[i].fvg.From() +// : false; +// } + +// // +// if (isPassed) +// { +// // +// Add( +// stfState.supplyZones[j], +// dest[i].supplyZones // +// ); +// } +// } +// } +// } + +// // +// // Demand Zones ... +// has = stfState.HasDemandZones(); +// if (has) +// { +// // +// for (int j = 0; j < stfState.CountDemandZones(); j++) +// { +// // +// bool isInsideOB = IsInsideDiff( +// stfState.demandZones[j], +// dest[i].ob // +// ); + +// // +// bool isInsideFVG = IsInsideDiff( +// stfState.demandZones[j], +// dest[i].fvg // +// ); + +// // +// bool isInside = isInsideOB || +// isInsideFVG; +// if (isInside) +// { +// // +// bool isPassed = +// detectInsideOBPOIs +// ? isInsideOB +// : detectInsideFVGPOIs +// ? isInsideFVG +// : false; +// if (isPassed) +// { +// // +// isPassed = +// !applyFromFilterForPOIs +// ? isPassed +// : isInsideOB +// ? stfState.demandZones[j].From() > dest[i].ob.From() +// : isInsideFVG +// ? stfState.demandZones[j].From() > dest[i].fvg.From() +// : false; +// } + +// // +// if (isPassed) +// { +// // +// Add( +// stfState.demandZones[j], +// dest[i].demandZones // +// ); +// } +// } +// } +// } + +// // +// // Support Zones ... +// has = stfState.HasSupportZones(); +// if (has) +// { +// // +// for (int j = 0; j < stfState.CountSupportZones(); j++) +// { +// // +// bool isInsideOB = IsInsideDiff( +// stfState.supportZones[j], +// dest[i].ob // +// ); + +// // +// bool isInsideFVG = IsInsideDiff( +// stfState.supportZones[j], +// dest[i].fvg // +// ); + +// // +// bool isInside = isInsideOB || +// isInsideFVG; +// if (isInside) +// { +// // +// bool isPassed = +// detectInsideOBPOIs +// ? isInsideOB +// : detectInsideFVGPOIs +// ? isInsideFVG +// : false; +// if (isPassed) +// { +// // +// isPassed = +// !applyFromFilterForPOIs +// ? isPassed +// : isInsideOB +// ? stfState.supportZones[j].From() > dest[i].ob.From() +// : isInsideFVG +// ? stfState.supportZones[j].From() > dest[i].fvg.From() +// : false; +// } + +// // +// if (isPassed) +// { +// // +// Add( +// stfState.supportZones[j], +// dest[i].supportZones // +// ); +// } +// } +// } +// } + +// // +// // Resistance Zones ... +// has = stfState.HasResistanceZones(); +// if (has) +// { +// // +// for (int j = 0; j < stfState.CountResistanceZones(); j++) +// { +// // +// bool isInsideOB = IsInsideDiff( +// stfState.resistanceZones[j], +// dest[i].ob // +// ); + +// // +// bool isInsideFVG = IsInsideDiff( +// stfState.resistanceZones[j], +// dest[i].fvg // +// ); + +// // +// bool isInside = isInsideOB || +// isInsideFVG; +// if (isInside) +// { +// // +// bool isPassed = +// detectInsideOBPOIs +// ? isInsideOB +// : detectInsideFVGPOIs +// ? isInsideFVG +// : false; +// if (isPassed) +// { +// // +// isPassed = +// !applyFromFilterForPOIs +// ? isPassed +// : isInsideOB +// ? stfState.resistanceZones[j].From() > dest[i].ob.From() +// : isInsideFVG +// ? stfState.resistanceZones[j].From() > dest[i].fvg.From() +// : false; +// } + +// // +// if (isPassed) +// { +// // +// Add( +// stfState.resistanceZones[j], +// dest[i].resistanceZones // +// ); +// } +// } +// } +// } +// } +// } + +// // +// Clean(tmpOBs); +// Clean(tmpFVGs); +// Clean(tmpOBFVGs); + +// // +// result = ArraySize(dest); + +// // +// return result; +// } + +// /** +// * Find Highest Order Block of XOBFVG Collection ... +// * +// * @param source: XOBFVG Collection ... +// * +// * @return ( int ) +// */ +// int GetHighest( +// XOBFVG &source[] // +// ) +// { +// // +// int result = -1; + +// // +// int count = ArraySize(source); +// bool has = IsValidSize(count); +// if (!has) +// { +// return result; +// } + +// // +// XOBFVG item; +// for (int i = 0; i < count; i++) +// { +// // +// XOBFVG iOBFVG = source[i]; + +// // +// bool canSet = +// !item.IsValid() +// ? true +// : item.ob.Upper() < iOBFVG.ob.Upper(); +// if (canSet) +// { +// // +// item = iOBFVG; +// result = i; +// } + +// // +// iOBFVG.Clean(); +// } + +// // +// item.Clean(); + +// // +// return result; +// } + +// /** +// * Find Lowest Order Block of XOBFVG Collection ... +// * +// * @param source: XOBFVG Collection ... +// * +// * @return ( int ) +// */ +// int GetLowest( +// XOBFVG &source[] // +// ) +// { +// // +// int result = -1; + +// // +// int count = ArraySize(source); +// bool has = IsValidSize(count); +// if (!has) +// { +// return result; +// } + +// // +// XOBFVG item; +// for (int i = 0; i < count; i++) +// { +// // +// XOBFVG iOBFVG = source[i]; + +// // +// bool canSet = +// !item.IsValid() +// ? true +// : item.ob.Lower() > iOBFVG.ob.Lower(); +// if (canSet) +// { +// // +// item = iOBFVG; +// result = i; +// } + +// // +// iOBFVG.Clean(); +// } + +// // +// item.Clean(); + +// // +// return result; +// } + +// /** +// * Find Youngest Order Block of XOBFVG Collection ... +// * +// * @param source: XOBFVG Collection ... +// * +// * @return ( int ) +// */ +// int GetYoungest( +// XOBFVG &source[] // +// ) +// { +// // +// int result = -1; + +// // +// int count = ArraySize(source); +// bool has = IsValidSize(count); +// if (!has) +// { +// return result; +// } + +// // +// XOBFVG item; +// for (int i = 0; i < count; i++) +// { +// // +// XOBFVG iOBFVG = source[i]; + +// // +// bool canSet = +// !item.IsValid() +// ? true +// : item.ob.From() < iOBFVG.ob.From(); +// if (canSet) +// { +// // +// item = iOBFVG; +// result = i; +// } + +// // +// iOBFVG.Clean(); +// } + +// // +// item.Clean(); + +// // +// return result; +// } + +// /** +// * Find Oldest Order Block of XOBFVG Collection ... +// * +// * @param source: XOBFVG Collection ... +// * +// * @return ( int ) +// */ +// int GetOldest( +// XOBFVG &source[] // +// ) +// { +// // +// int result = -1; + +// // +// int count = ArraySize(source); +// bool has = IsValidSize(count); +// if (!has) +// { +// return result; +// } + +// // +// XOBFVG item; +// for (int i = 0; i < count; i++) +// { +// // +// XOBFVG iOBFVG = source[i]; + +// // +// bool canSet = +// !item.IsValid() +// ? true +// : item.ob.From() > iOBFVG.ob.From(); +// if (canSet) +// { +// // +// item = iOBFVG; +// result = i; +// } + +// // +// iOBFVG.Clean(); +// } + +// // +// item.Clean(); + +// // +// return result; +// } + +// /** +// * Sort XOBFVG Collection based on OB Place ... +// * +// * @param source: XOBFVG instance Collection ... +// * @param forDir: ENUM_X_DIRECTION member ... +// * @param ignoreInside: Specified Ignoring price inside in Sorting ... +// */ +// void Sort( +// XOBFVG &source[], +// ENUM_X_DIRECTION forDir, +// bool ignoreInside = true // +// ) +// { +// // +// int idx = -1; +// int count = 0; +// bool has = false; + +// // +// has = HasDirection(forDir); +// if (!has) +// { +// return; +// } + +// // +// bool isBullish = IsBullish(forDir); + +// // +// count = ArraySize(source); +// has = IsValidSize(count); +// if (!has) +// { +// return; +// } + +// // +// XOBFVG last; +// XOBFVG tmpItems[]; +// bool hasLast = false; +// while (HasChild(source)) +// { +// // +// if (!hasLast) +// { +// // +// idx = GetOldest(source); +// hasLast = IsValidIndex(idx); +// if (hasLast) +// { +// // +// last = source[idx]; +// ArrayRemove( +// source, +// idx, +// 1 // +// ); + +// // +// AddRef( +// last, +// tmpItems // +// ); +// } + +// // +// count = ArraySize(source); +// has = IsValidSize(count); +// if (!has) +// { +// // +// last.Clean(); +// break; +// } +// } +// if (!hasLast) +// { +// // +// last.Clean(); +// break; +// } + +// // +// XOBFVG item; +// idx = GetOldest(source); +// has = IsValidIndex(idx); +// if (!has) +// { +// // +// item.Clean(); +// last.Clean(); +// break; +// } +// item = source[idx]; +// ArrayRemove( +// source, +// idx, +// 1 // +// ); + +// // +// bool isAbove = IsAbove( +// item.ob, +// last.ob, +// ignoreInside // +// ); + +// // +// bool isBelow = IsBelow( +// item.ob, +// last.ob, +// ignoreInside // +// ); + +// // +// has = +// isBullish +// ? isAbove +// : isBelow; +// if (has) +// { +// // +// AddRef( +// item, +// tmpItems // +// ); + +// // +// last = item; +// hasLast = item.IsValid(); +// } +// } + +// // +// Clean(source); +// Copy( +// tmpItems, +// source // +// ); + +// // +// Clean(tmpItems); +// } + +// // diff --git a/BKPS/14031218/Documents/Diagrams/Position Protection.drawio b/BKPS/14031218/Documents/Diagrams/Position Protection.drawio new file mode 100644 index 0000000..d425cb2 --- /dev/null +++ b/BKPS/14031218/Documents/Diagrams/Position Protection.drawio @@ -0,0 +1,279 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/BKPS/14031218/Documents/JsModules/x-color.tools.js b/BKPS/14031218/Documents/JsModules/x-color.tools.js new file mode 100644 index 0000000..c3ac5f9 --- /dev/null +++ b/BKPS/14031218/Documents/JsModules/x-color.tools.js @@ -0,0 +1,506 @@ +/** + * XColor Tools Module ... + * a module for handle colorify text contents in node js ... + * + * Maintainer + * + * Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) + */ + +// +//#region Module Imports ... +const XValueTools = require("./x-value.tools"); +//#endregion + +// +//#region Constants ... +/** + * these are available style which can applied to an string ... + */ +const AVAILABLE_STYLES = { + // + Bold: "\x1b[1m", + Dim: "\x1b[2m", + Underlined: "\x1b[4m", + Blink: "\x1b[5m", + ReverseFandB: "\x1b[7m", + Hidden: "\x1b[8m", + // + // Commonly used for reset all Styles ... + Reset: "\x1b[0m" +}; + +/** + * these are available foreground colors which can applied to an string ... + */ +const AVAILABLE_FOREGROUND_COLORS = { + Default: "\x1b[39m", + Black: "\x1b[30m", + Red: "\x1b[31m", + Green: "\x1b[32m", + Yellow: "\x1b[33m", + Blue: "\x1b[34m", + Magenta: "\x1b[35m", + Cyan: "\x1b[36m", + LightGray: "\x1b[37m", + DarkGray: "\x1b[90m", + LightRed: "\x1b[91m", + LightGreen: "\x1b[92m", + LightYellow: "\x1b[93m", + LightBlue: "\x1b[94m", + LightMagenta: "\x1b[95m", + LightCyan: "\x1b[96m", + White: "\x1b[97m", +}; + +/** + * these are available background colors which can applied to an string ... + */ +const AVAILABLE_BACKGROUND_COLORS = { + Default: "\x1b[49m", + Black: "\x1b[40m", + Red: "\x1b[41m", + Green: "\x1b[42m", + Yellow: "\x1b[43m", + Blue: "\x1b[44m", + Magenta: "\x1b[45m", + Cyan: "\x1b[46m", + LightGray: "\x1b[47m", + DarkGray: "\x1b[100m", + LightRed: "\x1b[101m", + LightGreen: "\x1b[102m", + LightYellow: "\x1b[103m", + LightBlue: "\x1b[104m", + LightMagenta: "\x1b[105m", + LightCyan: "\x1b[106m", + White: "\x1b[107m", +}; + +/** + * these are available style names, which exports from module and + * users can use them ... + */ +const STYLE_NAMES = { + Bold: "Bold", + Dim: "Dim", + Underlined: "Underlined", + Blink: "Blink", + ReverseFandB: "ReverseFandB", + Hidden: "Hidden", + Reset: "Reset", +}; + +/** + * these are available color names, which exports from module and + * users can use them ... + */ +const COLOR_NAMES = { + Default: "Default", + Black: "Black", + Red: "Red", + Green: "Green", + Yellow: "Yellow", + Blue: "Blue", + Magenta: "Magenta", + Cyan: "Cyan", + LightGray: "LightGray", + DarkGray: "DarkGray", + LightRed: "LightRed", + LightGreen: "LightGreen", + LightYellow: "LightYellow", + LightBlue: "LightBlue", + LightMagenta: "LightMagenta", + LightCyan: "LightCyan", + White: "White", +}; +//#endregion + +// +//#region Actions ... +/** + * apply specified style and color on a content ... + * + * @param {string} content specified content for styling ... + * @param {string} color specific color name for using to styling ... + * @param {string} style soecufic style name to use ... + * @param {boolean} toForeground apply specified color as foreground ... + * @param {boolean} toBackground apply specified color as background ... + * @returns {string} styled content ... + */ +function apply( + content, + color, + style, + toForeground = true, + toBackground = false +) { + // + let result = content; + + // + // Validate Arg ... + if (!XValueTools.isValidArg(content)) { + return result; + } + + // + // Detect and Validate Style and Apply it ... + let eStyle = AVAILABLE_STYLES[style]; + if (XValueTools.isValidArg(eStyle)) { + result = `${eStyle}${result}${AVAILABLE_STYLES.Reset}`; + } + + // + // Detect and Validate Foreground Color and Apply it ... + let eFColor = AVAILABLE_FOREGROUND_COLORS[color]; + if ( + !!toForeground + && XValueTools.isValidArg(eFColor) + ) { + result = `${eFColor}${result}${AVAILABLE_STYLES.Reset}`; + } + + // + // Detect and Validate Background Color and Apply it ... + let eBColor = AVAILABLE_BACKGROUND_COLORS[color]; + if ( + !!toBackground + && XValueTools.isValidArg(eBColor) + ) { + result = `${eBColor}${result}${AVAILABLE_STYLES.Reset}`; + } + +} + +/** + * apply specific style on a content ... + * + * @param {string} content specific content which going to styled ... + * @param {string} style a member of STYLE_NAMES which specified that which style going to applied to content ... + * @returns {string} styled content ... + */ +function applyStyle(content, style) { + // + // Validate Arg ... + if (!XValueTools.isValidArg(content)) { + return content; + } + + // + let eStyle = AVAILABLE_STYLES[style]; + if (eStyle === undefined) { + return content; + } + + // + return `${eStyle}${content}${AVAILABLE_STYLES.Reset}`; +} + +/** + * apply specific foreground color on a content ... + * + * @param {string} content specific content which going to colorified ... + * @param {string} color a member of COLOR_NAMES which specified that which color going to applied to content ... + * @returns {string} colorified content ... + */ +function applyForegroundColor(content, color) { + // + // Validate Arg ... + if (!XValueTools.isValidArg(content)) { + return content; + } + + // + let eColor = AVAILABLE_FOREGROUND_COLORS[color]; + if (eColor === undefined) { + return content; + } + + // + return `${eColor}${content}${AVAILABLE_STYLES.Reset}`; +} + +/** + * apply specific background color on a content ... + * + * @param {string} content specific content which going to colorified ... + * @param {string} color a member of COLOR_NAMES which specified that which color going to applied to content ... + * @returns {string} colorified content ... + */ +function applyBackgroundColor(content, color) { + // + // Validate Arg ... + if (!XValueTools.isValidArg(content)) { + return content; + } + + // + let eColor = AVAILABLE_BACKGROUND_COLORS[color]; + if (eColor === undefined) { + return content; + } + + // + return `${eColor}${content}${AVAILABLE_STYLES.Reset}`; +} + +/** + * generate style and color applier expression ... + * + * @param {string} color specific color name for using to styling ... + * @param {string} style soecufic style name to use ... + * @param {boolean} reset close applier string by reset styles ... + * @param {boolean} toForeground apply specified color as foreground ... + * @param {boolean} toBackground apply specified color as background ... + * @returns {string} style and color applier string ... + */ +function getApplier( + style = "", + color = "", + reset = false, + toForeground = true, + toBackground = false +) { + // + let result = ""; + + // + // Detect and Validate Style and Apply it ... + let eStyle = AVAILABLE_STYLES[style]; + if (XValueTools.isValidArg(eStyle)) { + result = `${eStyle}`; + } + + // + // Detect and Validate Foreground Color and Apply it ... + let eFColor = AVAILABLE_FOREGROUND_COLORS[color]; + if ( + !!toForeground + && XValueTools.isValidArg(eFColor) + ) { + result = `${eFColor}`; + } + + // + // Detect and Validate Background Color and Apply it ... + let eBColor = AVAILABLE_BACKGROUND_COLORS[color]; + if ( + !!toBackground + && XValueTools.isValidArg(eBColor) + ) { + result = `${eBColor}`; + } + + // + if ( + !!reset && + result.length > 0 + ) { + result = `${result}${AVAILABLE_STYLES.Reset}`; + } + + // + return result; +} + +/** + * generate style applier expression ... + * + * @param {string} style soecufic style name to use ... + * @param {boolean} reset close applier string by reset styles ... + * @returns {string} style applier string ... + */ +function getStyleApplier( + style = "", + reset = false +) { + // + let result = ""; + + // + // Detect and Validate Style and Apply it ... + let eStyle = AVAILABLE_STYLES[style]; + if (XValueTools.isValidArg(eStyle)) { + result = `${eStyle}`; + } + + // + if ( + !!reset && + result.length > 0 + ) { + result = `${result}${AVAILABLE_STYLES.Reset}`; + } + + // + return result; +} + +/** + * generate color applier expression ... + * + * @param {string} color specific color name for using to styling ... + * @param {boolean} reset close applier string by reset styles ... + * @param {boolean} toForeground apply specified color as foreground ... + * @param {boolean} toBackground apply specified color as background ... + * @returns {string} color applier string ... + */ +function getColorApplier( + color = "", + reset = false, + toForeground = true, + toBackground = false +) { + // + let result = ""; + + // + // Detect and Validate Foreground Color and Apply it ... + let eFColor = AVAILABLE_FOREGROUND_COLORS[color]; + if ( + !!toForeground + && XValueTools.isValidArg(eFColor) + ) { + result = `${eFColor}`; + } + + // + // Detect and Validate Background Color and Apply it ... + let eBColor = AVAILABLE_BACKGROUND_COLORS[color]; + if ( + !!toBackground + && XValueTools.isValidArg(eBColor) + ) { + result = `${eBColor}`; + } + + // + if ( + !!reset && + result.length > 0 + ) { + result = `${result}${AVAILABLE_STYLES.Reset}`; + } + + // + return result; +} + +/** + * colorified specific content ... + * + * @param {string} content specified content for styling ... + * @param {string} color specific color name for using to styling ... + * @param {boolean} toForeground apply specified color as foreground ... + * @param {boolean} toBackground apply specified color as background ... + * @returns {string} + */ +function colorifyContent( + content = "", + color = "", + toForeground = true, + toBackground = false +) { + // + let result = content; + + // + if (!XValueTools.isValidArg(content)) { + return result; + } + + // + // Finde Colors ... + + // + // Detect and Validate Foreground Color and Apply it ... + let eFColor = AVAILABLE_FOREGROUND_COLORS[color]; + if ( + !!toForeground + && XValueTools.isValidArg(eFColor) + ) { + result = `${eFColor}${result}`; + } + + // + // Detect and Validate Background Color and Apply it ... + let eBColor = AVAILABLE_BACKGROUND_COLORS[color]; + if ( + !!toBackground + && XValueTools.isValidArg(eBColor) + ) { + result = `${eBColor}${result}`; + } + + // + if ( + result.length > 0 + && ( + XValueTools.isValidArg(eFColor) || + XValueTools.isValidArg(eBColor) + ) + ) { + result = `${result}${AVAILABLE_STYLES.Reset}`; + } + + // + return result; +} + +/** + * apply style on specific content ... + * + * @param {string} content specified content for styling ... + * @param {string} style soecufic style name to use ... + * @returns {string} + */ +function stylifiyContent( + content = "", + style = "", +) { + // + let result = content; + + // + if (!XValueTools.isValidArg(content)) { + return result; + } + + // + // Detect and Validate Style and Apply it ... + let eStyle = AVAILABLE_STYLES[style]; + if (XValueTools.isValidArg(eStyle)) { + result = `${eStyle}${result}`; + } + + // + if ( + result.length > 0 + && XValueTools.isValidArg(eStyle) + ) { + result = `${result}${AVAILABLE_STYLES.Reset}`; + } + + // + return result; +} +//#endregion + +// +//#region Module Exports ... +module.exports = { + // + STYLE_NAMES, + COLOR_NAMES, + // + apply, + applyStyle, + getApplier, + getColorApplier, + getStyleApplier, + colorifyContent, + stylifiyContent, + applyForegroundColor, + applyBackgroundColor, +} +//#endregion \ No newline at end of file diff --git a/BKPS/14031218/Documents/JsModules/x-file.tools.js b/BKPS/14031218/Documents/JsModules/x-file.tools.js new file mode 100644 index 0000000..2a3535d --- /dev/null +++ b/BKPS/14031218/Documents/JsModules/x-file.tools.js @@ -0,0 +1,887 @@ +/** + * XFile Tools Module ... + * a module for handle all file/folder manipulating task in node js ... + * + * Maintainer + * + * Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) + */ + +// +//#region Module Imports ... +const fs = require('fs'); +const os = require('os'); +const Path = require('path'); +const http = require('http'); +const https = require('https'); +const XValueTools = require('./x-value.tools'); +//#endregion + +// +//#region Constants ... +/** + * current os path separators ... + */ +const PathSeparator = Path.sep; + +/** + * current directory ... + */ +const CurrentDir = __dirname; +//#endregion + +// +//#region Actions ... +// +//#region Global ... +/** + * retrieve a path status ... + * + * @param {string} path a path value to check ... + * @returns an stat object ... + */ +function getStatus(path = '') { + // + if (!XValueTools.isValidArg(path)) { + return undefined; + } + + // + return fs.statSync(path); +} + +/** + * retrieve user's Home path ... + * + * @returns {string} a path ... + */ +function getHomePath() { + return os.homedir(); +} +//#endregion + +// +//#region Path ... +/** + * retrieve the base name of specific address path ... + * + * @param {string} path address of file or folder ... + * @returns string ... + */ +function basename(path = '') { + // + if (!XValueTools.isValidArg(path)) { + return ''; + } + + // + const result = Path.basename(path); + return result; +} + +/** + * join several path segments together ... + * + * @param {...string} path path params ... + * @returns a joined paths ... + */ +function joinPath(...path) { + return Path.join(...path); +} + +/** + * resolve a relative path to absolute ... + * + * @param {string[]} path a path value to check ... + * @returns {string} + */ +function resolvePath(...path) { + return Path.resolve(...path); +} +//#endregion + +// +//#region File ... +/** + * determines a path destination is a file or not ... + * + * @param {string} path a path value to check ... + * @returns a boolean value ... + */ +function isFileExists(path = '') { + // + if (!XValueTools.isValidArg(path)) { + return false; + } + + // + try { + const stat = getStatus(path); + if (!stat) { + return false; + } + + // + return stat.isFile(); + } catch { + return false; + } +} + +/** + * remove a file ... + * + * @param {string} path a file path ... + * @returns {Promise} action done or not ... + */ +function removeFile(path = '') { + return new Promise((resolve) => { + // + if (!isFileExists(path)) { + resolve(false); + } + + // + fs.unlink(path, (err) => { + // + if (err) { + resolve(false); + return; + } + + // + resolve(true); + }); + }); +} + +/** + * copy a file to destination path ... + * + * @param {string} source source file path ... + * @param {string} dest dest folder path ... + * @returns {Promise} action done or not ... + */ +function copyFile( + source = '', + dest = '' +) { + return new Promise((resolve) => { + // + if ( + !isFileExists(source) || + !isDirectoryExists(dest) + ) { + resolve(false); + return; + } + + // + const destFilePath = Path.join(dest, Path.basename(source)); + fs.copyFile(source, destFilePath, (err) => { + // + if (err) { + resolve(false); + return; + } + + // + resolve(true); + }); + }); +} + +/** + * reading specified file content ... + * + * @param {string} path a file path ... + * @returns {Promise} file content ... + */ +function readFile(path = '') { + return new Promise((resolve) => { + // + if (!isFileExists(path)) { + resolve(''); + return; + } + + // + fs.readFile(path, 'utf8', (err, content) => { + // + if (err) { + resolve(undefined); + return; + } + + // + resolve(content); + }); + }); +} + +/** + * write content to a file ... + * + * @param {string} path a file path ... + * @param {string} content the content which going to write to the file ... + * @param {bool} overwrite determines file overwrite if exists ... + * @returns {Promise} action done or not ... + */ +function writeFile( + path = '', + content = '', + overwrite = true +) { + return new Promise((resolve) => { + // + if (isFileExists(path) && !overwrite) { + // + resolve(false); + return; + } + + // + // Normalize Content ... + content = XValueTools.isValidArg(content) ? + content : + ''; + + // + fs.writeFile(path, content, (err) => { + // + if (err) { + // + resolve(false); + return; + } + + // + resolve(true); + }); + }); +} + +/** + * create a file ... + * + * @param {string} path file path ... + * @param {string} fileName file name ... + * @returns {Promise} action done or not ... + */ +function createFile( + path = '', + fileName = '' +) { + return new Promise((resolve) => { + // + const filePath = Path.join(path, fileName); + if ( + isFileExists(filePath) || + !XValueTools.isValidArg(path) || + !XValueTools.isValidArg(fileName) + ) { + // + resolve(false); + return; + } + + // + fs.writeFile(filePath, '', (err) => { + // + if (err) { + // + resolve(false); + return; + } + + // + resolve(true); + }); + }); +} + +/** + * remove a file name extension ... + * + * @param {string} name + * @returns {string} name without extension ... + */ +function removeFileExtension(name = '') { + return name.substring(0, name.lastIndexOf('.')) || name; +} + +/** + * retrieve a file extension ... + * + * @param {string} path a path which locate a file ... + * @returns {string} + */ +function getFileExtension(path = '') { + // + let result = ""; + + // + // Validate Arg ... + if ( + !XValueTools.isValidArg(path) + || !isFileExists(path) + ) { + return result; + } + + // + // Retrieve just file name ... + const fileName = basename(path); + result = fileName.replace( + removeFileExtension(fileName), + "" + ); + + // + return result; +} + +/** + * retrieve all files list recursively from specific path ... + * + * @param {string} path a source folder path ... + * @param {string[]} extensions which file extensions need to be listed, live empty for all files ... + * @returns {Promise} + */ +async function getRecursiveFilesList( + path = "", + extensions = [] +) { + // + let result = []; + + // + // Validate Args ... + if ( + !XValueTools.isValidArg(path) + || !isDirectoryExists(path) + ) { + return result; + } + + // + const contents = await getDirectoryContents(path); + for (const item of contents) { + // + const itemPath = joinPath( + path, + item + ); + + // + const isItemFile = isFileExists(itemPath); + if (isItemFile) { + // + const itemFileExtension = getFileExtension(itemPath); + const isFileInSupportedExtensions = + extensions === undefined || extensions.length === 0 + ? true + : extensions.includes(itemFileExtension) + ; + if (isFileInSupportedExtensions) { + result.push(itemPath); + } + } else if (isDirectoryExists(itemPath)) { + // + const itemPathFiles = await getRecursiveFilesList(itemPath, extensions); + result.push(...itemPathFiles); + } + } + + // + return result; +} + +/** + * Extract Specific files from a folder and it's content ... + * + * @param {string} path Folder Path ... + * @returns + */ +async function extractFiles(path = "", ext = [], excludeWorkspaceFolders = []) { + // + const result = []; + + // + if (!ext || ext.length == 0) { + return result; + } + + // + const pathContent = await getDirectoryContents(path); + if (!pathContent || pathContent.length == 0) { + return result; + } + + // + // Loop through Content ... + for (const c of pathContent) { + // + // Prepare full path ... + const cPath = joinPath(path, c); + + // + // check content path is file or not ... + const isCFile = isFileExists(cPath); + const isCDirectory = isDirectoryExists(cPath); + if (isCFile) { + // + // Check it is MQL file or not ... + const cExt = getFileExtension(cPath); + if (ext.includes(cExt)) { + result.push(cPath); + } + } else if (isCDirectory) { + // + const destFolderName = basename(cPath); + const isExcluded = excludeWorkspaceFolders.includes(destFolderName); + if (isExcluded) { + continue; + } + + // + const cFiles = await extractFiles(cPath, ext); + if (cFiles && cFiles.length > 0) { + result.push(...cFiles); + } + } + } + + // + return result; +} +//#endregion + +// +//#region Directory ... +/** + * create a directory ... + * + * @param {string} path destination path including dir name ... + * @param {boolean} recursive create directories recursively ... + * @returns action done or not ... + */ +function createDirectory( + path = '', + recursive = true +) { + // + let result = false; + + // + if ( + isDirectoryExists(path) || + !XValueTools.isValidArg(path) + ) { + return false; + } + + // + try { + // + fs.mkdirSync(path, { recursive: recursive }); + result = true; + return result; + } catch { + return false; + } +} + +/** + * remove a directory ... + * + * @param {string} path destination path including dir name ... + * @param {boolean} recursive removes directories recursively ... + * @returns {Promise} action done or not ... + */ +function removeDirectory( + path = '', + recursive = false +) { + return new Promise((resolve) => { + // + if (!isDirectoryExists(path)) { + resolve(false); + return; + } + + // + fs.rm(path, { + recursive + }, (err) => { + // + if (err) { + resolve(false); + return; + } + + // + resolve(true); + }); + }); +} + +/** + * determines a path destination is a directory or not ... + * + * @param {string} path a folder path ... + * @returns represent destnation path is Directory or not ... + */ +function isDirectoryExists(path = '') { + // + if (!XValueTools.isValidArg(path)) { + return false; + } + + // + try { + // + const isExists = fs.existsSync(path); + if (!isExists) { + return false; + } + + // + const stat = getStatus(path); + if (!stat) { + return false; + } + + // + const result = stat.isDirectory(); + return result; + } catch { + return false; + } +} + +/** + * retrieve a directory content ... + * + * @param {string} path a folder path ... + * @returns {Promise} a collection of folder files ... + */ +function getDirectoryContents(path = '') { + return new Promise((resolve) => { + // + if (!isDirectoryExists(path)) { + resolve([]); + return; + } + + // + fs.readdir(path, (err, content) => { + // + if (err) { + resolve([]); + return; + } + + // + resolve(content); + }); + }); +} + +/** + * retrieve a directory files ... + * + * @param {string} path a folder path ... + * @returns {Promise} a collection of folder files ... + */ +function getDirectoryFiles( + path = '', + containsHiddenFiles = false +) { + return new Promise((resolve) => { + // + if (!isDirectoryExists(path)) { + resolve([]); + return; + } + + // + fs.readdir(path, (err, content) => { + // + if (err) { + resolve([]); + return; + } + + // + if (!containsHiddenFiles) { + content = content.filter(c => !c.startsWith('.')); + } + + // + const result = []; + content + .forEach(c => { + // + const cPath = Path.join(path, c); + if (isFileExists(cPath)) { + result.push(c); + } + }); + + // + resolve(result); + }); + }); +} + +/** + * retrieve a directory folders ... + * + * @param {string} path a folder path ... + * @returns {Promise} a collection of folder names ... + */ +function getDirectoryFolders(path = '') { + return new Promise((resolve) => { + // + if (!isDirectoryExists(path)) { + resolve([]); + return; + } + + // + fs.readdir(path, (err, content) => { + // + if (err) { + resolve([]); + return; + } + + // + const result = []; + content.forEach(c => { + // + const cPath = Path.join(path, c); + if (isDirectoryExists(cPath)) { + result.push(c); + } + }); + + // + resolve(result); + }); + }); +} + +/** + * copy a folder with all of it's content to dest ... + * + * @param {string} source source folder path ... + * @param {string} dest dest folder path ... + * @returns {Promise} action done or not ... + */ +async function copyFolder( + source = '', + dest = '' +) { + // + if ( + !isDirectoryExists(source) || + !XValueTools.isValidArg(dest) || + !XValueTools.isValidArg(source) + ) { + return false; + } + + // + const folderName = Path.basename(source); + const destPath = Path.join(dest, folderName); + + // + // Create Dest Path folder if not exists ... + if (!isDirectoryExists(destPath)) { + // + let result = createDirectory(destPath, true); + if (!result) { + return false; + } + } + + // + // Files ... + const files = await getDirectoryFiles(source); + if (files && files.constructor === Array && files.length > 0) { + // + const filesPromises = files.map(file => copyFile(Path.join(source, file), destPath)); + const filesResult = (await Promise.all(filesPromises)).every(r => !!r); + if (!filesResult) { + return false; + } + } + + // + // Folders ... + const folders = await getDirectoryFolders(source); + if (folders && folders.constructor === Array && folders.length > 0) { + // + const folderPromises = folders.map(folder => copyFolder(Path.join(source, folder), destPath)); + const filesResult = (await Promise.all(folderPromises)).every(r => !!r); + if (!filesResult) { + return false; + } + } + + // + return true; +} +//#endregion + +// +//#region Downloader ... +/** + * download a file from specific url and store it ... + * + * @param {string} filepath the file name and path which required to put download file on it ... + * @param {string} url the web url for downloading ... + */ +function download(filepath, url) { + // + // Validate Args ... + if ( + !XValueTools.isValidArg(url) + || !XValueTools.isValidURL(url) + || !XValueTools.isValidArg(filepath) + ) { + return; + } + + // + var file = fs.createWriteStream(filepath); + + // + if (url.startsWith('https:')) { + https.get(url, function (response) { + response.pipe(file); + }); + } else if (url.startsWith('http:')) { + http.get(url, function (response) { + response.pipe(file); + }); + } +} +//#endregion + +// +//#region JSON ... +/** + * read and parse a JSON content from a file ... + * + * @param {string} path source file path ... + * @returns {any} + */ +function readJSON(path = "") { + // + // Validate Args ... + if (!isFileExists(path)) { + return undefined; + } + + // + let result = undefined; + try { + result = require(path); + } catch { + result = undefined; + } + + // + return result; +} + +/** + * write a JSON Object content into a file ... + * + * @param {string} path dest file path ... + * @param {any} content an object which required to write to file ... + * @returns {Promise} + */ +async function writeJSON( + path = "", + content = undefined +) { + // + let result = false; + + // + // Validate Args ... + if (!XValueTools.isValidArg(path)) { + return result; + } + + // + // Normallize Content ... + if (content === undefined) { + content = {}; + } + + // + const contentString = XValueTools.beautifyJSON(content); + + // + result = await writeFile( + path, + contentString, + true + ); + + // + return result; +} +//#endregion +//#endregion + +// +//#region Module Exports ... +module.exports = { + // + CurrentDir, + PathSeparator, + + // + getStatus, + getHomePath, + + // + basename, + joinPath, + resolvePath, + + // + download, + + // + readJSON, + writeJSON, + + // + copyFile, + readFile, + writeFile, + createFile, + removeFile, + isFileExists, + getFileExtension, + removeFileExtension, + getRecursiveFilesList, + extractFiles, + + // + copyFolder, + createDirectory, + removeDirectory, + isDirectoryExists, + getDirectoryFiles, + getDirectoryFolders, + getDirectoryContents, +}; +//#endregion \ No newline at end of file diff --git a/BKPS/14031218/Documents/JsModules/x-shell.tools.js b/BKPS/14031218/Documents/JsModules/x-shell.tools.js new file mode 100644 index 0000000..0ee13de --- /dev/null +++ b/BKPS/14031218/Documents/JsModules/x-shell.tools.js @@ -0,0 +1,219 @@ +/** + * XShell Tools Module ... + * a module for handling shell actions and retrieve OS Info in node js ... + * + * Maintainer + * + * Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) + */ + +// +//#region Imports ... +const os = require('os'); +const process = require('process'); +const { exec } = require("child_process"); +const XFileTools = require('./x-file.tools'); +//#endregion + +// +//#region Constants ... +// +const OS = { + Aix: 'aix', + Darwin: 'darwin', + FreeBSD: 'freebsd', + Linux: 'linux', + OpenBSD: 'openbsd', + SnOS: 'sunos', + Windows: 'win32' +}; + +// +const isWindows = process.platform === OS.Windows; +//#endregion + +// +//#region Actions ... +// +//#region Pure shell commands ... +/** + * execute a command using NodeJS on shell ... + * + * @param {string} cmd command to execute ... + * @param {string} cwd working directory ... + * + * @returns Promise instance ... + */ +function execute(cmd, cwd) { + return new Promise((resolve, reject) => { + // + if (!cmd || cmd.toString().length === 0 || (cwd && !XFileTools.isDirectoryExists(cwd))) { + reject('invalid args ...'); + return; + } + + // + exec(cmd, { cwd }, (err, result, stdError) => { + // + if (err) { + reject(err); + return; + } + + // + if (stdError) { + // + // reject(stdError); + // return; + } + + // + resolve(result); + }); + }); +}; + +/** + * determines a command exists on host or not ... + * + * @param {string} name specific command name ... + * + * @returns boolean Promise ... + */ +function checkCommandExists(name) { + return new Promise(resolve => { + // + if (!name) { + resolve(false); + return; + } + + // + const cmd = isWindows ? `${name} >nul 2>&1` : `type ${name} >/dev/null 2>&1`; + execute(cmd).then(result => { + resolve(true); + }) + .catch(err => { + resolve(false); + }); + }); +} +//#endregion + +// +//#region required commands state ... +/** + * check al required commands exists or not ... + * + * @returns + */ +async function isRequiredCommandsExists() { + // + let result = false; + + // + // const isTarExists = await isTarCommandExists(); + // const isCatExists = await isCatCommandExists(); + // const isGrepExists = await isGrepCommandExists(); + // const isSedExists = await isSedCommandExists(); + const isNpmExists = await isNpmCommandExists(); + const isNgExists = await isNgCommandExists(); + const isIonicExists = await isIonicCommandExists(); + const isCordovaExists = await isCordovaCommandExists(); + + // + result = isNpmExists + && isNgExists + && isIonicExists + && isCordovaExists + ; + + // + return result; +} + +/** + * retrieve required commands state object ... + * + * @returns + */ +async function getRequiredCommandsStates() { + // + const result = {}; + + // + // const isTarExists = await isTarCommandExists(); + // const isCatExists = await isCatCommandExists(); + // const isGrepExists = await isGrepCommandExists(); + // const isSedExists = await isSedCommandExists(); + const isNpmExists = await isNpmCommandExists(); + const isNgExists = await isNgCommandExists(); + const isIonicExists = await isIonicCommandExists(); + const isCordovaExists = await isCordovaCommandExists(); + + // + result['npm'] = isNpmExists; + result['ng'] = isNgExists; + result['ionic'] = isIonicExists; + result['cordova'] = isCordovaExists; + + // + return result; +} +//#endregion + +// +//#region Commonly used Command Checkers ... +/** + * determines npm command exists or not ... + * + * @returns + */ +function isNpmCommandExists() { + return checkCommandExists('npm'); +} + +/** + * determines ng command exists or not ... + * + * @returns + */ +function isNgCommandExists() { + return checkCommandExists('ng'); +} + +/** + * determines ionic command exists or not ... + * + * @returns + */ +function isIonicCommandExists() { + return checkCommandExists('ionic'); +} + +/** + * determines cordova command exists or not ... + * + * @returns + */ +function isCordovaCommandExists() { + return checkCommandExists('cordova'); +} +//#endregion +//#endregion + +// +//#region Module Exports ... +module.exports = { + // + execute, + checkCommandExists, + isRequiredCommandsExists, + getRequiredCommandsStates, + + // + isNgCommandExists, + isIonicCommandExists, + isCordovaCommandExists, +} +//#endregion \ No newline at end of file diff --git a/BKPS/14031218/Documents/JsModules/x-type-detector.tools.js b/BKPS/14031218/Documents/JsModules/x-type-detector.tools.js new file mode 100644 index 0000000..86ed3d8 --- /dev/null +++ b/BKPS/14031218/Documents/JsModules/x-type-detector.tools.js @@ -0,0 +1,268 @@ +/** + * DataType Tools Module ... + * a module for manipulate and detect supported data types in node js ... + * + * Maintainer + * + * Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) + */ + +// +//#region Constants ... +/** + * all supported data types ... + */ +const DataTypes = { + Null: 'null', + Date: 'date', + Array: 'array', + Object: 'object', + String: 'string', + Number: 'number', + Unknown: 'unknown', + Boolean: 'boolean', + Function: 'function', + Undefined: 'undefined', +}; +//#endregion + +// +//#region Actions ... +/** + * detect type of a content ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function getType(value) { + // + const type = typeof value; + + // + let result = DataTypes.Unknown; + let dateIdentifier = '[object Date]'; + let constructor = value && value.constructor ? + value.constructor.toString() : + ''; + + // + switch (type) { + // + case 'undefined': + result = DataTypes.Undefined; + break; + + // + case 'boolean': + result = DataTypes.Boolean; + break; + + // + case 'string': + result = DataTypes.String; + break; + + // + case 'number': + result = DataTypes.Number; + break; + + // + case 'function': + result = DataTypes.Function; + break; + + // + case 'object': + // + // Null ... + if (value === null) { + result = DataTypes.Null; + } else + // + // Array ... + if (Array.isArray(value)) { + result = DataTypes.Array; + } else + // + // Data ... + if ( + value instanceof Date || + isFunction(value.getMonth) || + constructor.includes(dateIdentifier) || + Object.prototype.toString.call(value) === dateIdentifier + ) { + result = DataTypes.Date; + } else + // + // Object ... + { + result = DataTypes.Object; + } + break; + + // + default: + result = DataTypes.Unknown; + break; + } + + // + return result; +} + +/** + * retrieve an object constructor ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function getConstructor(value) { + // + const result = value && value.constructor ? + value.constructor.toString() : + ''; + + // + return result; +} + +/** + * retrieve an object prototype ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function getPrototype(value) { + // + const result = value ? + Object.prototype.toString.call(value) : + ''; + + // + return result; +} + +/** + * check an object is null or not ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function isNull(value) { + return getType(value) === DataTypes.Null; +} + +/** + * check an object is undefined or not ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function isUndefined(value) { + return getType(value) === DataTypes.Undefined; +} + +/** + * check an object is null or undefined or not ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function isNullOrUndefined(value) { + return isNull(value) || isUndefined(value); +} + +/** + * check an object is a date or not ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function isDate(value) { + return getType(value) === DataTypes.Date; +} + +/** + * check an object is number or not ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function isNumber(value) { + return getType(value) === DataTypes.Number; +} + +/** + * check an object is string or not ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function isString(value) { + return getType(value) === DataTypes.String; +} + +/** + * check an object is boolean or not ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function isBoolean(value) { + return getType(value) === DataTypes.Boolean; +} + +/** + * check an object is an Array or not ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function isArray(value) { + return getType(value) === DataTypes.Array; +} + +/** + * check an object is and Object or not ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function isObject(value) { + return getType(value) === DataTypes.Object; +} + +/** + * check an object is a Function or not ... + * + * @param {any} value the content which going to check ... + * @returns + */ +function isFunction(value) { + return getType(value) === DataTypes.Function; +} +//#endregion + +// +//#region Module Exports ... +module.exports = { + // + DataTypes, + + // + getType, + getConstructor, + getPrototype, + isNull, + isUndefined, + isNullOrUndefined, + isDate, + isNumber, + isString, + isBoolean, + isArray, + isObject, + isFunction, +} +//#endregion \ No newline at end of file diff --git a/BKPS/14031218/Documents/JsModules/x-value.tools.js b/BKPS/14031218/Documents/JsModules/x-value.tools.js new file mode 100644 index 0000000..81cfcc4 --- /dev/null +++ b/BKPS/14031218/Documents/JsModules/x-value.tools.js @@ -0,0 +1,1528 @@ +/** + * Value Tools Module ... + * a module for Validate args and values ... + * + * Maintainer + * + * Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) + */ + +// +//#region Imports ... +const XTypeTools = require('./x-type-detector.tools'); +//#endregion + +// +//#region Actions ... +/** +* validate a value as an argument ... +* +* @param {string} value the value which going to validate ... +* @returns +*/ +function isValidArg(value) { + // + let result = false; + + // + result = value && + value.length > 0; + + // + return result; +} + +/** + * validate a collection of valuea as an arguments ... + * + * @param {string|string[]} values the value collection which going to checked ... + * @returns + */ +function isValidArgs(values) { + // + // Normalize Values ... + const normalValues = toNormalArray(values); + if (!hasChildArray(normalValues)) { + return false; + } + + // + let result = normalValues.every(nv => isValidArg(nv)); + return result; +} + +/** + * converts content to an array object ... + * + * @param {string|string[]} content the content which required to normalized ... + * @returns {string[]} array object ... + */ +function toNormalArray(content = '') { + // + // Validate Args ... + if (!isValidArg(content)) { + return []; + } + + // + const result = Array.isArray(content) ? + [...content] : + content.includes(',') && + content !== ',' ? + [...content.split(',')] : + [content]; + + // + return result; +} + +/** + * determines value is array and has atleast one child ... + * + * @param {any} value the value which going to checked ... + * @returns {boolean} result of checking ... + */ +function hasChildArray(value) { + // + let result = false; + result = value && + Array.isArray(value) && + value.length > 0; + + // + return result; +} + +/** + * check an string is ends with specified symbol ... + * + * @param {string} symbol specified search symbol ... + * @param {string} value specified search content ... + * @param {boolean} ignoreCase specified search case sensitive or not ... + * @returns + */ +function endsWidth( + symbol = '', + value = '', + ignoreCase = true +) { + // + if (!isValidArg(value)) { + return false; + } + + // + if (!isValidArg(symbol)) { + return true; + } + + // + // TODO: uncomment it if necessary ... + // symbol = symbol.trim(); + + // + let result = false; + const subtractedContent = value.substring(value.length - symbol.length); + result = !!ignoreCase ? + subtractedContent + .toLowerCase() === symbol + .toLowerCase() : + subtractedContent === symbol; + + // + return result; +} + +/** + * surround specified content by provided symbol ... + * + * @param {string} symbol surround string ... + * @param {string} content used content to surrounded by symbol ... + * @returns surrounded content ... + */ +function surroundBy( + symbol = '', + content = '' +) { + // + // Validate Args ... + if (!isValidArg(content)) { + content = ''; + } + + // + if (!isValidArg(symbol)) { + symbol = ''; + } + + // + if (isSurrounded(symbol, content)) { + return content; + } + + // + const result = `${symbol}${content}${symbol}`; + return result; +} + +/** + * convert a parsed sign to clear string ... + * + * @param {string} value a parsed content ... + * @returns clear parsed signs ... + */ +function toStringExpression(value) { + // + let result = ''; + result = value; + + // + if ( + !value || + !isValidArg(value) || + !isSurroundedString(value) + ) { + return result; + } + + // + const startSymbol = value.charAt(0); + const endSymbol = value.charAt(value.length - 1); + + // + if (startSymbol !== endSymbol) { + return result; + } + + // + if ( + startSymbol === "\"" || + startSymbol === "\'" + ) { + result = clearSurround(startSymbol, value); + } + + // + return result; +} + + + +/** + * find and cleare proposed candidates from specified content ... + * + * @param {string|string[]} candidates the proposed string(s) whic going to cleared from content ... + * @param {string} content the destination content which used to find and replace candidates on it ... + * @returns cleared content ... + */ +function clearContent( + candidates, + content +) { + // + // Validate Args ... + if ( + !candidates || + !isValidArg(content) + ) { + return ''; + } + + // + // Normalize candidates ... + const normalCandidates = toNormalArray(candidates) + .filter(c => isValidArg(c)); + if (!hasChildArray(normalCandidates)) { + return content; + } + + // + // define regexp for content ... + const regExpExpression = normalCandidates.join('|'); + const regExp = new RegExp( + regExpExpression, + 'gi' + ); + + // + let result = ''; + result = content.replace(regExp, ''); + + // + return result; +} + +/** + * clear surrounded symbol from content ... + * + * @param {string} symbol specified search symbol ... + * @param {string} content specified content to clear ... + * @returns + */ +function clearSurround( + symbol = '', + content = '' +) { + // + // Validate Args ... + if ( + !isValidArg(content) || + (isValidArg(symbol) && + symbol.length >= content.length - 1) + ) { + return ''; + } + + // + // Validate Surround ... + if (!isSurrounded(symbol, content)) { + return content; + } + + // + if (!isValidArg(symbol)) { + return content; + } + + // + let result = content.substring(symbol.length, content.length - symbol.length); + return result; +} + +/** + * clear object sign ... + * + * @param {string} content + * @returns cleared content ... + */ +function clearObjectSurround(content = '') { + // + // Validate Args ... + if ( + !isValidArg(content) || + !isSurroundedObject(content) + ) { + return content; + } + + // + const endIndex = content.length - ( + endsWidth('}', content) ? + 1 : + endsWidth('},', content) || + endsWidth('};', content) || + endsWidth('}\n', content) ? + 2 : + 0 + ); + + // + const result = content.substring(1, endIndex); + return result; +} + +/** + * clear array sign ... + * + * @param {string} content + * @returns cleared content ... + */ +function clearArraySurround(content = '') { + // + // Validate Args ... + if ( + !isValidArg(content) || + !isSurroundedArray(content) + ) { + return content; + } + + // + const endIndex = content.length - ( + endsWidth(']', content) ? + 1 : + endsWidth('],', content) || + endsWidth('];', content) || + endsWidth(']\n', content) ? + 2 : + 0 + ); + + // + const result = content.substring(1, endIndex); + return result; +} + +/** + * slice a content to individual parts ... + * + * @param {number|number[]} indexes which indexes used to slice ... + * @param {strng} content the content which going to sliced ... + * @returns sliced parts of content ... + */ +function sliceContent(indexes, content) { + // + // Validate Args ... + if ( + !isValidArg(indexes) || + !isValidArg(content) + ) { + return []; + } + + // + // Normalize indexes ... + const normalIndexes = toNormalArray(indexes) + .filter(index => index > -1 && index < content.length); + if (!hasChildArray(normalIndexes)) { + return []; + } + + // + let result = ['']; + result.pop(); + + // + let lastIndex = 0; + for (const index of normalIndexes) { + // + const part = content.substring(lastIndex, index); + if (isValidArg(part)) { + result.push(part.trim()); + } + + // + lastIndex = index + 1; + } + + // + // check remained parts ... + if (lastIndex < content.length) { + // + const part = content.substring(lastIndex); + if (isValidArg(part)) { + result.push(part.trim()); + } + } + + // + return result; +} + + + +/** + * check an string is starts and ends with specified symbol ... + * + * @param {string} symbol specified search symbol ... + * @param {string} content specified search content ... + * @param {boolean} ignoreCase specified search case sensitive or not ... + * @returns + */ +function isSurrounded( + symbol = '', + content = '', + ignoreCase = true +) { + // + // Validate Args ... + if (!isValidArg(content)) { + return false; + } + + // + if (!isValidArg(symbol)) { + return true; + } + + // + symbol = symbol.trim(); + + // + let result = false; + result = (!!ignoreCase ? + content + .toLowerCase() + .startsWith(symbol.toLowerCase()) : + content.startsWith(symbol) + ) && + endsWidth(symbol, content, ignoreCase); + + // + return result; +} + +/** + * determines a content is an string surrounded value or not ... + * + * @param {string} content a content which going to check ... + * @returns + */ +function isSurroundedString(content = '') { + // + // Validate Args ... + if (!isValidArg(content)) { + return false; + } + + // + let result = false; + result = ( + content.startsWith('\'') && + ( + endsWidth('\'', content) || + endsWidth('\',', content) || + endsWidth('\';', content) || + endsWidth('\'\n', content) + ) || + content.startsWith('\"') && + ( + endsWidth('\"', content) || + endsWidth('\",', content) || + endsWidth('\";', content) || + endsWidth('\"\n', content) + ) || + content.startsWith('`') && + ( + endsWidth('\`', content) || + endsWidth('\`,', content) || + endsWidth('\`;', content) || + endsWidth('\`\n', content) + ) + ); + return result; +} + +/** + * check a content is an array content or not ... + * + * @param {string} content + * @returns + */ +function isSurroundedArray(content = '') { + // + // Validate Args ... + if (!isValidArg(content)) { + return false; + } + + // + let result = false; + result = content.startsWith('[') && + ( + endsWidth(']', content) || + endsWidth('],', content) || + endsWidth('];', content) || + endsWidth(']\n', content) + ); + return result; +} + +/** + * check a content is an object content or not ... + * + * @param {string} content + * @returns + */ +function isSurroundedObject(content = '') { + // + // Validate Args ... + if (!isValidArg(content)) { + return false; + } + + // + let result = false; + result = content.startsWith('{') && + ( + endsWidth('}', content) || + endsWidth('},', content) || + endsWidth('};', content) || + endsWidth('}\n', content) + ); + return result; +} + +/** + * check an index model is contains inside anothers or not ... + * + * @param {{ start: number, end: number}} source the source index model to check ... + * @param {...{ start: number, end: number}} dest the collection of index models which going to check ... + * @returns + */ +function isIndexInside(source, ...dest) { + // + let result = false; + + // + // Validate Args ... + if (!source || !dest) { + return result; + } + + // + // Check idx is standard ... + if ( + !source || + !source.end || + !source.start || + source.start > source.end + ) { + return false; + } + + // + // Check types of destinations ... + for (let index of dest) { + // + // Check idx is standard ... + if ( + !index || + !index.end || + !index.start || + index.start > index.end + ) { + return false; + } + } + + // + if (dest.includes(source)) { + dest = dest.filter(d => d !== source); + } + + // + const insideContentIndex = dest.find(dIndex => { + // + const result = source.start >= dIndex.start && + source.start <= dIndex.end && + source.end >= dIndex.start && + source.end <= dIndex.end; + return result; + }); + + // + result = insideContentIndex; + return result; +} + +/** + * check a number exists in + * @param {number} idx the number which going to check ... + * @param {{ start: number, end: number}} index the index model + * @returns + */ +function isInsideIndex(idx = -1, index) { + // + let result = false; + + // + // Validate Args ... + if ( + !index || + !index.hasOwnProperty('end') || + !index.hasOwnProperty('start') + ) { + return result; + } + + // + result = idx > index.start && idx < index.end; + return result; +} + +/** + * determines an object is key/value and type ... + * + * @param {any} content the object which we are going to check ... + * @returns + */ +function isKeyValueType(content) { + // + const result = content && + content.hasOwnProperty('key') && + content.hasOwnProperty('type') && + content.hasOwnProperty('value'); + + // + return result; +} + + + +/** + * find all indexes of token(s) in content ... + * + * @param {string|string[]} tokens the tokens which require to search ... + * @param {string} content the content which using to search ... + * @returns {number[]} all occured indexes ... + */ +function findAllIndexes( + tokens, + content +) { + // + // Validate Args ... + if ( + !isValidArg(tokens) || + !isValidArg(content) + ) { + return []; + } + + // + // normalize tokens ... + const normalTokens = toNormalArray(tokens); + if (!hasChildArray(normalTokens)) { + return []; + } + + // + // Parse contents ... + let match; + const result = []; + const regExp = new RegExp( + normalTokens.join('|'), + 'g' + ); + while ((match = regExp.exec(content)) !== null) { + result.push(match.index); + } + if (!hasChildArray(result)) { + return []; + } + + // + return result; +} + +/** + * find nearest symbol in a content from specified index ... + * + * @param {string|string[]} candidates specifies which symbols to find ... + * @param {string} content te content for seasrch ... + * @param {number} startFromIndex the index of start position ... + * @returns + */ +function findNearest( + candidates, + content = '', + startFromIndex = 0 +) { + // + // Validate Args ... + if ( + !isValidArg(content) || + !isValidArg(candidates) || + !isValidArg(content.trim()) + ) { + return ''; + } + + // + // Normalize Content ... + content = content.trim(); + + // + // Normalize Starts From ... + startFromIndex = startFromIndex < 0 || startFromIndex > content.length - 1 ? 0 : startFromIndex; + + // + // Normalize Symbols ... + const normalCandidates = toNormalArray(candidates); + if (!hasChildArray(normalCandidates)) { + return ''; + } + + // + let nearestIndex = findNearestIndex( + normalCandidates, + content, + startFromIndex + ); + if (nearestIndex < 0) { + return ''; + } + + // + let result = content.substring( + nearestIndex, + nearestIndex + Math.max(...normalCandidates.map(nc => nc.length)) + ).trim(); + return result; +} + +/** + * search candidates in content and find nearest one and return it ... + * + * @param {string|string[]} candidates which candidates required to check ... + * @param {string} content the content which required to search candidates ... + * @param {number} startFromIndex the proposed index to start searching content from on ... + * @returns + */ +function findNearestIndex( + candidates = [''], + content = '', + startFromIndex = 0, + ignoreClosedItems = false +) { + // + // Validate Args ... + if ( + !isValidArg(content) || + !isValidArg(candidates) + ) { + return -1; + } + + // + // Mormalize startFromIndex value ... + startFromIndex = startFromIndex < 0 ? + 0 : + startFromIndex > content.length - 1 ? + content.length - 1 : + startFromIndex; + + // + // Normalize candidates ... + let normalCandidates = toNormalArray(candidates); + + // + if (!!ignoreClosedItems) { + normalCandidates = normalCandidates + .map(c => content.indexOf( + c, + startFromIndex + ) + ).map(c => +c) + .filter(c => +c > -1); + } else { + normalCandidates = findAllIndexesOutOfCloseds(normalCandidates, content) + .filter(c => c >= startFromIndex); + } + if (!hasChildArray(normalCandidates)) { + return -1; + } + + // + let result = -1; + result = Math.min(...normalCandidates); + + // + return result; +} + +/** + * find close index of specific sign in destination content ... + * + * @param {string} openSymbol open of area sign ... + * @param {string} closeSymbol close of area sign ... + * @param {string} content the destination content for parsing ... + * @param {number} startsFrom an start index of content for start parsing ... + * @returns + */ +function findCloseIndex( + openSymbol = '', + closeSymbol = '', + content = '', + startsFrom = -1 +) { + // + // Validate Args ... + if ( + startsFrom < 0 || + !isValidArg(content) || + !isValidArg(openSymbol) || + !isValidArg(closeSymbol) || + openSymbol === closeSymbol || + !content.includes(openSymbol) || + !content.includes(closeSymbol) || + startsFrom > content.length - 1 + ) { + return -1; + } + + // + let result = -1; + + // + let index = startsFrom; + const openSignStack = []; + while (index < content.length) { + // + const openCandidate = content.substring(index, index + openSymbol.length); + const closeCandidate = content.substring(index, index + closeSymbol.length); + + // + if (openCandidate === openSymbol) { + openSignStack.push(index); + } else if (closeCandidate === closeSymbol) { + // + if (openSignStack.length > 0) { + openSignStack.pop(); + } + + // + if (openSignStack.length === 0) { + result = index; + break; + } + } + + // + index++; + } + + // + return result; +} + +/** + * find closed contents of specific sign in destination content ... + * + * @param {string} openSymbol open of area sign ... + * @param {string} closeSymbol close of area sign ... + * @param {string} content the destination content for parsing ... + * @param {number} startsFrom an start index of content for start parsing ... + * @returns + */ +function findClosedContent( + openSymbol = '', + closeSymbol = '', + content = '', + startsFrom = 0, +) { + // + let result = [{ + start: -1, + end: -1, + content: '' + }]; + result.pop(); + + // + // Validate Args ... + if ( + !isValidArg(content) || + !isValidArg(openSymbol) || + !isValidArg(closeSymbol) || + !content.includes(openSymbol) || + !content.includes(closeSymbol) || + openSymbol.length >= content.length || + closeSymbol.length >= content.length + ) { + return result; + } + + // + // Normalize Start From ... + startsFrom = startsFrom < 0 || startsFrom >= content.length ? 0 : startsFrom; + + // + let canContinue = true; + while (!!canContinue) { + // + let openSymbolIndex = content.indexOf(openSymbol, startsFrom); + if (openSymbolIndex < 0) { + // + canContinue = false; + continue; + } + + // + let closeSymbolIndex = findCloseIndex( + openSymbol, + closeSymbol, + content, + openSymbolIndex + ); + if (closeSymbolIndex < 0) { + // + canContinue = false; + continue; + } + if (content.charAt(closeSymbolIndex) !== closeSymbol) { + closeSymbolIndex++; + } + + // + // Prevent ${} string interpolations ... + if ( + openSymbol === '{' && + openSymbolIndex - 1 >= 0 + ) { + // + const prevChar = content.charAt(openSymbolIndex - 1); + if (prevChar === '$') { + continue; + } + } + + // + const item = content + .substring(openSymbolIndex, closeSymbolIndex + 1) + .trim(); + startsFrom = closeSymbolIndex + 1; + result.push({ + start: openSymbolIndex, + end: closeSymbolIndex, + content: item + }); + } + + // + if (!hasChildArray(result)) { + return result; + } + + // + return result; +} + +/** + * extract a collection of closed contents exists in a content ... + * + * @param symbols a collection of open and close contents ... + * @param {string} content a content for searching inside it ... + * @returns a collection of closed content ... + */ +function findClosedContents( + symbols = [ + { + openSymbol: '', + closeSymbol: '' + } + ], + content = '' +) { + // + let result = [{ + start: -1, + end: -1, + content: '' + }]; + result.pop(); + + // + if ( + !isValidArg(content) || + !hasChildArray(symbols) + ) { + return []; + } + + // + symbols.forEach(symbol => { + // + const closedContent = findClosedContent( + symbol.openSymbol, + symbol.closeSymbol, + content + ); + + // + if (hasChildArray(closedContent)) { + result.push( + ...closedContent + ); + } + }); + + // + return result; +} + +/** + * find all string content closed items ... + * + * @param {string} content a content which going to search ... + * @returns a collection of index descriptors ... + */ +function findClosedStrings(content = '') { + // + // Validate Args ... + if (!isValidArg(content)) { + return []; + } + + // + // there are 3 types of strings ... + // ' " and ` + + // + const token1 = '\''; + const token1Stack = [0]; + token1Stack.pop(); + + // + const token2 = '"'; + const token2Stack = [0]; + token2Stack.pop(); + + // + const token3 = '`'; + const token3Stack = [0]; + token3Stack.pop(); + + // + const result = [ + { + start: -1, + end: -1, + content: '' + } + ]; + result.pop(); + + // + for (let i = 0; i < content.length; i++) { + // + const currentChart = content.charAt(i); + + // + //#region Token 1 ... + if (currentChart === token1) { + // + if (!hasChildArray(token1Stack)) { + token1Stack.push(i); + } else { + // + const start = token1Stack.pop(); + const end = i + 1; + const pContent = content.substring(start, end); + result.push({ + start, + end, + content: pContent + }); + } + } + //#endregion + + // + //#region Token 2 ... + if (currentChart === token2) { + // + if (!hasChildArray(token2Stack)) { + token2Stack.push(i); + } else { + // + const start = token2Stack.pop(); + const end = i + 1; + const pContent = content.substring(start, end); + result.push({ + start, + end, + content: pContent + }); + } + } + //#endregion + + // + //#region Token 3 ... + if (currentChart === token3) { + // + if (!hasChildArray(token3Stack)) { + token3Stack.push(i); + } else { + // + const start = token3Stack.pop(); + const end = i + 1; + const pContent = content.substring(start, end); + result.push({ + start, + end, + content: pContent + }); + } + } + //#endregion + } + + // + return result; +} + +/** + * find container indexes from within indexes ... + * + * @param {...{start: number, end: number}} index the collection of indexes to find beiggers inside ... + * @returns + */ +function findContainerIndexes(...index) { + // + let result = [ + { + start: -1, + end: -1, + content: '' + } + ]; + result.pop(); + + // + let concatedIndexes = []; + for (let idx of index) { + // + // Index Childs ... + for (let iix of idx) { + // + // Check idx is standard ... + if ( + !iix || + !iix.end || + !iix.start || + iix.start > iix.end + ) { + continue; + } + + // + // Check index inside another index ... + concatedIndexes.push(iix); + } + } + + // + if (!hasChildArray(concatedIndexes)) { + return result; + } + + // + for (let ccIdx of concatedIndexes) { + // + const isInside = isIndexInside(ccIdx, ...concatedIndexes); + if (isInside) { + continue; + } + + // + if (hasChildArray(result)) { + // + const isInsideResult = isIndexInside(ccIdx, ...result); + if (isInsideResult) { + continue; + } + } + + // + result.push(ccIdx); + } + + // + return result; +} + +/** + * find all tokens indexes inside a content which they are not inside closed items ... + * + * @param {string|string[]} tokens the tokens which require to search ... + * @param {string} content the content which using to search ... + * @returns + */ +function findAllIndexesOutOfCloseds1( + tokens, + content, +) { + // + // Validate Args ... + if (!isValidArg(content)) { + return []; + } + + // + // Extract token Indexes ... + const tokensIndexes = findAllIndexes(tokens, content); + if (!hasChildArray(tokensIndexes)) { + return []; + } + + // + // Extract Closed Objects Indexes ... + const closedArrays = findClosedContent('[', ']', content); + const closedObjects = findClosedContent('{', '}', content); + const closedStrings = findClosedStrings(content); + if ( + !hasChildArray(closedObjects) && + !hasChildArray(closedArrays) && + !hasChildArray(closedStrings) + ) { + return tokensIndexes; + } + + // + // find bigger sloded ... + let containerClosedItems = findContainerIndexes( + closedArrays, + closedObjects, + closedStrings + ).filter(i => !isSurroundedString(i.content)); + + // + let result = [-1]; + result.pop(); + + // + for (let tIdx of tokensIndexes) { + // + let canAdd = true; + for (let ccIndex of containerClosedItems) { + // + canAdd = isInsideIndex(tIdx, ccIndex); + if (canAdd) { + break; + } + } + + // + if (!canAdd) { + result.push(tIdx); + } + } + + // + return result; +} + +/** + * find all tokens indexes inside a content which they are not inside closed items ... + * + * @param {string|string[]} tokens the tokens which require to search ... + * @param {string} content the content which using to search ... + * @returns + */ +function findAllIndexesOutOfCloseds( + tokens, + content, +) { + // + // Define Result ... + let result = [-1]; + result.pop(); + + // + // Validate Args ... + if (!isValidArg(content)) { + return []; + } + + // + // Normalize Tokens ... + const normalizeTokens = toNormalArray(tokens); + if (!hasChildArray(normalizeTokens)) { + return result; + } + + // + // Extract Closed Objects Indexes ... + let openSymbols = [ + '{', + '[', + '\'', + '"', + '`' + ]; + let closeSymbols = [ + '}', + ']', + '\'', + '"', + '`' + ]; + let openStack = []; + let lastOpenSymbol = ''; + let lastClosedIndex = -1; + for (let i = 0; i < content.length; i++) { + // + const prevChar = content.charAt(i - 1) || ''; + const char = content.charAt(i); + const nextChar = content.charAt(i + 1) || ''; + + // + const isToken = normalizeTokens.includes(char); + const isOpenSymbol = openSymbols.includes(char); + const isCloseSymbol = closeSymbols.includes(char); + + // + if (isOpenSymbol && lastOpenSymbol !== char) { + openStack.push(i); + lastOpenSymbol = char === '\'' || char === '"' || char === '`' ? char : lastOpenSymbol; + } else if (isCloseSymbol) { + // + lastOpenSymbol = char === '\'' || char === '"' || char === '`' ? '' : lastOpenSymbol; + let lastPop = openStack.pop(); + if (openStack.length === 0) { + lastClosedIndex = lastPop; + } + } else if (isToken) { + if ( + i > lastClosedIndex && + openStack.length === 0 + ) { + result.push(i); + } + } + } + + // + return result; +} +//#endregion + +// +//#region Validator Actions ... +/** + * check specified value is Valid URL Address or not ... + * + * @param {string} value specified string which required to check + * @returns {boolean} + */ +function isValidURL(value = "") { + // + if (!isValidArg(value)) { + return false; + } + + const pattern = new RegExp( + '^([a-zA-Z]+:\\/\\/)?' + // protocol + '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name + '((\\d{1,3}\\.){3}\\d{1,3}))' + // OR IP (v4) address + '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path + '(\\?[;&a-z\\d%_.~+=-]*)?' + // query string + '(\\#[-a-z\\d_]*)?$', // fragment locator + 'i' + ); + + // + const result = pattern.test(value); + return result; +} + +/** + * check specified value is Valid URL Address or not ... + * + * @param {string} value specified string which required to check + */ +function isValidEmail(value = "") { + // + if (!isValidArg(value)) { + return false; + } + + // + const pattern = /[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}/gim; + + // + const result = pattern.test(value); + return result; +} +//#endregion + +// +//#region Normallizers ... +/** + * normallize an string ... + * + * @param {string} value specified value ... + * @returns {string} + */ +function toNormalString(value = "") { + // + if (!XTypeTools.isString(value)) { + value = ""; + } + + // + const result = value + .trim() + .toLowerCase(); + + // + return result; +} +//#endregion + +// +//#region Beautifiers ... +/** + * converts an object to string based on json and beautify result ... + * + * @param {any} object + * @returns {string} + */ +function beautifyJSON(object = undefined) { + // + // TODO: Complete this ... + let result = ""; + + // + // validate object ... + if (object === undefined) { + return result; + } + + // + // Convert result ... + result = JSON.stringify( + object, + null, + 4 + ); + + // + return result; +} +//#endregion + +// +//#region Module Exports ... +module.exports = { + // + endsWidth, + surroundBy, + isValidArg, + isValidArgs, + toNormalArray, + hasChildArray, + toStringExpression, + + // + sliceContent, + clearContent, + clearSurround, + clearArraySurround, + clearObjectSurround, + + // + isSurrounded, + isIndexInside, + isInsideIndex, + isKeyValueType, + isSurroundedArray, + isSurroundedString, + isSurroundedObject, + + // + findNearest, + findAllIndexes, + findCloseIndex, + findNearestIndex, + findClosedContent, + findClosedStrings, + findClosedContents, + findAllIndexesOutOfCloseds, + + // + // Validator Actions ... + isValidURL, + isValidEmail, + + // + // Normallizers ... + toNormalString, + + // + beautifyJSON, +} +//#endregion \ No newline at end of file diff --git a/BKPS/14031218/Documents/Temlates/x-saherelm.x-ea.template.ea.mq5 b/BKPS/14031218/Documents/Temlates/x-saherelm.x-ea.template.ea.mq5 new file mode 100644 index 0000000..ec3e257 --- /dev/null +++ b/BKPS/14031218/Documents/Temlates/x-saherelm.x-ea.template.ea.mq5 @@ -0,0 +1,542 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center XTest MQL5 Expert Advisor +// ------------------------------------------------- +// Name: XEATemplate +// Description: a Template For Exper Advisors +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +//////////////////////////////////////////////////////x +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XEATemplate" +#property strict + +// +#define ShortName "XEATemplate" + +// +// Imports ... +#include "../Classes/x-saherelm.xalert.class.mq5" +#include "../Classes/x-saherelm.xtrade.class.mq5" +#include "../Helpers/x-saherelm.xcc.helper.mq5" +#include "../Helpers/x-saherelm.xct.helper.mq5" + +// +// Inputs ... + +// +// Common ... +input group "Common"; +input long eaMagicNumber = 78692110; // Magic Number +input int eaSlippage = 10; // Slippgae +input string eaLogSuffix = ""; // Log Suffix + +// +// Alert ... +// Here we Provider All Requirements for +// Configuring Alert Provider ... +input group "Alert"; +input bool eAEnableAlerts = true; // Enable Alerts +input bool eALogAlerts = true; // Log Alerts +input bool eAMailAlerts = false; // Mail Alerts +input bool eAPushAlerts = false; // Push Alerts +input bool eATerminalAlerts = false; // Terminal Alerts + +// +// Time Report ... +input group "Reports"; +input bool eaReportNewMonths = false; // Report New Month +input bool eaReportNewWeeks = false; // Report New Weeks +input bool eaReportNewDays = false; // Report New Days +input bool eaReportNewHours = false; // Report New Hours + +// +// Define Local Variables ... + +// +string eaLogTag; // EA Log Prefix ... +XSCAlert *eaAlert; // Alert Provider for Expert Adviser ... +XSCTrade *eaTrader; // Trader of Expert Adviser ... +XTimeTracker eaTimeTracker; // Time Tracker for Providing Reports ... +XSCXCTHelper *eaCHelper; // Bar Timer Indicator Helper class ... +XSCXCCHelper *eaCCHelper; // Chart Styler Indicator Helper Class ... + +// +// Event Handlers ... + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs and Required Parameters + // for EA to Works fine ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Timer ... + if (!InitTimer()) { + return INIT_FAILED; + } + + // + // Initialize all Requirements ... + if (!InitEA()) + { + return INIT_FAILED; + } + + // + // Initialize all GUI Objects and Classes ... + if (!InitGUI()) + { + return INIT_FAILED; + } + + // + // Alert Initialization ... + string msg = "Initialized Successfully ..."; + eaAlert.Alert(msg); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Destroy Timer ... + DestroyTimer(); + + // + // Destroy all GUI Requirements ... + DestroyGUI(); + + // + // Alert De Initialization Succeeded ... + string msg = "De Initialized Successfully ..."; + eaAlert.Alert(msg); + + // + // Destroy all EA Requirements ... + DestroyEA(); +} + +// +// On Tick Handler ... +void OnTick() +{ + // + UpdateGUI(); + HandleReportTime(); + UpdatePositionsState(); + + // + // TODO: Implemetn Tick Processors Algorithm ... +} + +// +// Handle On Trade Event ... +void OnTrade() +{ + eaTrader.HandleOnTrade(); +} + +// +// On Timer ... +void OnTimer() +{ + // + // TODO: Implement Time Based Functionalities ... +} + +// +// Chart Event Handler ... +void OnChartEvent( + const int id, + const long &lparam, + const double &dparam, + const string &sparam // +) +{ + // + // Handle OnClick Event ... + if (id == CHARTEVENT_OBJECT_CLICK) + { + HandleOnClickEvent(sparam); + } +} + +// +// Custom Event Handlers ... + +/** + * Handle StopLoss Triggered Positions ... + * + * @param deal: XDeal ... + */ +void OnStopLossTriggered(const XDeal &deal) +{ + // + HandleReportBalance(); +} + +/** + * Handle Take Profit Triggered Positions ... + * + * @param deal: XDeal ... + */ +void OnTakeProfitTriggered(const XDeal &deal) +{ + // + HandleReportBalance(); +} + +/** + * Handle Force Close a Position ... + * + * @param ticket: Position Ticket ... + * @param position: XPosition ... + * @param comment: Closing Comment ... + */ +void OnPositionForceClosed( + const ulong ticket, + const XPosition &position, + const string comment // +) +{ + // + HandleReportBalance(); +} + +// +// Custom Functions ... + +/** + * Validate all Inputs of Expert Adviser ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + string errMessage = ""; + + // + bool isCommonValid = ( + // + eaSlippage > 0 && + eaMagicNumber > 0 + // + ); + if (!isCommonValid) + { + // + errMessage += "common configurations error;" + "\n"; + } + + // + result = + // + // Common ... + isCommonValid && + // + // Otere ... + true + // + ; + + // + if (!result) + { + // + // Since here Logger not Initiallized, we Use Raw Print Command ... + Print(ShortName + " Errors: \n", errMessage); + } + + // + return result; +} + +/** + * Initialize Timer ... + * + * @return ( bool ) + */ +bool InitTimer() { + // + bool result = false; + + // + // TODO: Initialize Timer if necessary ... + // result = EventSetTimer(1); + // result = EventSetMillisecondTimer(100); + result = true; + + // + return result; +} + +/** + * Destroy Timer ... + */ +void DestroyTimer() { + // + // TODO: Use This ... + // EventKillTimer(); +} + +/** + * Initialize all Requirements for Working Fine ... + * + * @return ( bool ) + */ +bool InitEA() +{ + // + bool result = false; + + // + // Locally Apply Changes on Prefix ... + eaLogTag = ShortName + ">" + eaLogSuffix; + + // + // Bar Timer ... + XCTInputs ctInputs; + ctInputs.Default(); // Default Configurations ... + eaCHelper = new XSCXCTHelper(); + result = eaCHelper.Init( + _Symbol, + _Period, + ctInputs // + ); + if (!result) + { + return result; + } + + // + // Bar Styles ... + XCCInputs ccInputs; + ccInputs.Default(); // Default Configurations ... + eaCCHelper = new XSCXCCHelper(); + result = eaCCHelper.Init( + _Symbol, + _Period, + ccInputs // + ); + if (!result) + { + return result; + } + + // + // Create Instance of Alert Class and Configure it ... + eaAlert = new XSCAlert(); + eaAlert.SetPrefix(eaLogTag); + eaAlert.SetLogAlerts(eALogAlerts); + eaAlert.SetMailAlerts(eAMailAlerts); + eaAlert.SetPushAlerts(eAPushAlerts); + eaAlert.SetEnableAlerts(eAEnableAlerts); + eaAlert.SetTerminalAlerts(eATerminalAlerts); + + // + // Create Trader Instance and Configure it ... + eaTrader = new XSCTrade( + eaSlippage, + eaMagicNumber // + ); + eaTrader.AddOnStopLossEventHandler(OnStopLossTriggered); + eaTrader.AddOnTakeProfitEventHandler(OnTakeProfitTriggered); + eaTrader.AddOnForceClosePositionEventHandler(OnPositionForceClosed); + + // + return result; +} + +/** + * Destroy all Initialized EA Requirements ... + */ +void DestroyEA() +{ + // + delete eaCHelper; + delete eaCCHelper; + + // + delete eaAlert; +} + +/** + * Initialize all GUI Requirements for EA ... + * + * @return ( bool ) + */ +bool InitGUI() +{ + // + bool result = false; + + // + // TODO: Fix This ... + result = true; + + // + return result; +} + +/** + * Update GUI based on Each Ticks ... + */ +void UpdateGUI() +{ + // + // TODO: Implement this ... +} + +/** + * Destroy all Initialized GUi Requirements ... + */ +void DestroyGUI() +{ + // + // TODO: Complete this ... +} + +// +// Others ... + +/** + * Update Positions States ... + */ +void UpdatePositionsState() +{ + // + // TODO: Implement this ... +} + +/** + * Handle On Click Event for GUI Components ... + * + * @param name: Object Name ... + */ +void HandleOnClickEvent(string name) +{ + // + if (!IsValid(name)) + { + return; + } + + // + bool isClicked = false; + + // + // TODO: Implement Chart Objects On Click ... + + // + if (isClicked) + { + UpdateGUI(); + } +} + +/** + * Report Account Balance ... + */ +void HandleReportBalance() +{ + // + if (!IsRunningOnTestMode()) + { + return; + } + + // + string msg = "Balance: " + ToString(eaTrader.mAccount.GetBalance()); + eaAlert.Log(msg); +} + +/** + * Time Reporting based on Inputs ... + */ +void HandleReportTime() +{ + // + // Monthly Report .... + if (eaReportNewMonths && + eaTimeTracker.IsNewMonth()) + { + // + string msg = "New Month ..."; + + // + eaAlert.Alert(msg); + } + + // + // Weekly Report .... + if (eaReportNewWeeks && + eaTimeTracker.IsNewWeek()) + { + // + string msg = "New Week ..."; + + // + eaAlert.Alert(msg); + } + + // + // Daily Report .... + if (eaReportNewDays && + eaTimeTracker.IsNewDay()) + { + // + string msg = "New Day ..."; + + // + eaAlert.Alert(msg); + } + + // + // Hourly Report .... + if (eaReportNewHours && + eaTimeTracker.IsNewHour()) + { + // + string msg = "New Hour ..."; + + // + eaAlert.Alert(msg); + } +} + +// diff --git a/BKPS/14031218/Documents/Temlates/x-saherelm.x-panel.ea.mq5 b/BKPS/14031218/Documents/Temlates/x-saherelm.x-panel.ea.mq5 new file mode 100644 index 0000000..c04228d --- /dev/null +++ b/BKPS/14031218/Documents/Temlates/x-saherelm.x-panel.ea.mq5 @@ -0,0 +1,575 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center XTest MQL5 Expert Advisor +// ------------------------------------------------- +// Name: XPanelEA +// Description: an Exper Advisor which used Panels +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +//////////////////////////////////////////////////////x +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XPanelEA" +#property strict + +// +#define ShortName "XPANELEA" + +// +// Imports ... +#include "../Classes/x-saherelm.x-app-dialog.class.mq5" +#include "../Classes/x-saherelm.xalert.class.mq5" +#include "../Classes/x-saherelm.xtrade.class.mq5" +#include "../Helpers/x-saherelm.xcc.helper.mq5" +#include "../Helpers/x-saherelm.xct.helper.mq5" + +// +// Inputs ... + +// +// Common ... +input group "Common"; +input long eaMagicNumber = 78692110; // Magic Number +input int eaSlippage = 10; // Slippgae +input string eaLogSuffix = ""; // Log Suffix + +// +// Alert ... +// Here we Provider All Requirements for +// Configuring Alert Provider ... +input group "Alert"; +input bool eAEnableAlerts = true; // Enable Alerts +input bool eALogAlerts = true; // Log Alerts +input bool eAMailAlerts = false; // Mail Alerts +input bool eAPushAlerts = false; // Push Alerts +input bool eATerminalAlerts = false; // Terminal Alerts + +// +// Time Report ... +input group "Reports"; +input bool eaReportNewMonths = false; // Report New Month +input bool eaReportNewWeeks = false; // Report New Weeks +input bool eaReportNewDays = false; // Report New Days +input bool eaReportNewHours = false; // Report New Hours + +// +// Define Local Variables ... + +// +string eaLogTag; // EA Log Prefix ... +XSCAlert *eaAlert; // Alert Provider for Expert Adviser ... +XSCTrade *eaTrader; // Trader of Expert Adviser ... +XTimeTracker eaTimeTracker; // Time Tracker for Providing Reports ... +XSCXCTHelper *eaCTHelper; // Bar Timer Indicator Helper class ... +XSCXCCHelper *eaCCHelper; // Chart Styler Indicator Helper Class ... + +// +XCAppDialog eaMainWindow; // EA Main Dialog ... + +// +// Event Handlers ... + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs and Required Parameters + // for EA to Works fine ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Timer ... + if (!InitTimer()) + { + return INIT_FAILED; + } + + // + // Initialize all Requirements ... + if (!InitEA()) + { + return INIT_FAILED; + } + + // + // Initialize all GUI Objects and Classes ... + if (!InitGUI()) + { + return INIT_FAILED; + } + + // + // Alert Initialization ... + string msg = "Initialized Successfully ..."; + eaAlert.Alert(msg); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Destroy Timer ... + DestroyTimer(); + + // + // Destroy all GUI Requirements ... + DestroyGUI(); + + // + // Alert De Initialization Succeeded ... + string msg = "De Initialized Successfully ..."; + eaAlert.Alert(msg); + + // + // Destroy all EA Requirements ... + DestroyEA(); +} + +// +// On Tick Handler ... +void OnTick() +{ + // + UpdateGUI(); + HandleReportTime(); + UpdatePositionsState(); + + // + // TODO: Implemetn Tick Processors Algorithm ... +} + +// +// Handle On Trade Event ... +void OnTrade() +{ + eaTrader.HandleOnTrade(); +} + +// +// On Timer ... +void OnTimer() +{ + // + // TODO: Implement Time Based Functionalities ... +} + +// +// Chart Event Handler ... +void OnChartEvent( + const int id, + const long &lparam, + const double &dparam, + const string &sparam // +) +{ + // + // Apply Chart Event on Main Window ... + eaMainWindow.ChartEvent(id, lparam, dparam, sparam); + + // + // Handle OnClick Event ... + if (id == CHARTEVENT_OBJECT_CLICK) + { + HandleOnClickEvent(sparam); + } +} + +// +// Custom Event Handlers ... + +/** + * Handle StopLoss Triggered Positions ... + * + * @param deal: XDeal ... + */ +void OnStopLossTriggered(const XDeal &deal) +{ + // + HandleReportBalance(); +} + +/** + * Handle Take Profit Triggered Positions ... + * + * @param deal: XDeal ... + */ +void OnTakeProfitTriggered(const XDeal &deal) +{ + // + HandleReportBalance(); +} + +/** + * Handle Force Close a Position ... + * + * @param ticket: Position Ticket ... + * @param position: XPosition ... + * @param comment: Closing Comment ... + */ +void OnPositionForceClosed( + const ulong ticket, + const XPosition &position, + const string comment // +) +{ + // + HandleReportBalance(); +} + +// +// Custom Functions ... + +/** + * Validate all Inputs of Expert Adviser ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + string errMessage = ""; + + // + bool isCommonValid = ( + // + eaSlippage > 0 && + eaMagicNumber > 0 + // + ); + if (!isCommonValid) + { + // + errMessage += "common configurations error;" + "\n"; + } + + // + result = + // + // Common ... + isCommonValid && + // + // Otere ... + true + // + ; + + // + if (!result) + { + // + // Since here Logger not Initiallized, we Use Raw Print Command ... + Print(ShortName + " Errors: \n", errMessage); + } + + // + return result; +} + +/** + * Initialize Timer ... + * + * @return ( bool ) + */ +bool InitTimer() +{ + // + bool result = false; + + // + // TODO: Initialize Timer if necessary ... + // result = EventSetTimer(1); + // result = EventSetMillisecondTimer(100); + result = true; + + // + return result; +} + +/** + * Destroy Timer ... + */ +void DestroyTimer() +{ + // + // TODO: Use This ... + // EventKillTimer(); +} + +/** + * Initialize all Requirements for Working Fine ... + * + * @return ( bool ) + */ +bool InitEA() +{ + // + bool result = false; + + // + // Locally Apply Changes on Prefix ... + eaLogTag = ShortName + ">" + eaLogSuffix; + + // + // Bar Timer ... + XCTInputs ctInputs; + ctInputs.Default(); // Default Configurations ... + eaCTHelper = new XSCXCTHelper(); + result = eaCTHelper.Init( + _Symbol, + _Period, + ctInputs // + ); + if (!result) + { + return result; + } + + // + // Bar Styles ... + XCCInputs ccInputs; + ccInputs.Default(); // Default Configurations ... + eaCCHelper = new XSCXCCHelper(); + result = eaCCHelper.Init( + _Symbol, + _Period, + ccInputs // + ); + if (!result) + { + return result; + } + + // + // Create Instance of Alert Class and Configure it ... + eaAlert = new XSCAlert(); + eaAlert.SetPrefix(eaLogTag); + eaAlert.SetLogAlerts(eALogAlerts); + eaAlert.SetMailAlerts(eAMailAlerts); + eaAlert.SetPushAlerts(eAPushAlerts); + eaAlert.SetEnableAlerts(eAEnableAlerts); + eaAlert.SetTerminalAlerts(eATerminalAlerts); + + // + // Create Trader Instance and Configure it ... + eaTrader = new XSCTrade( + eaSlippage, + eaMagicNumber // + ); + eaTrader.AddOnStopLossEventHandler(OnStopLossTriggered); + eaTrader.AddOnTakeProfitEventHandler(OnTakeProfitTriggered); + eaTrader.AddOnForceClosePositionEventHandler(OnPositionForceClosed); + + // + return result; +} + +/** + * Destroy all Initialized EA Requirements ... + */ +void DestroyEA() +{ + // + delete eaCTHelper; + delete eaCCHelper; + + // + delete eaAlert; +} + +/** + * Initialize all GUI Requirements for EA ... + * + * @return ( bool ) + */ +bool InitGUI() +{ + // + bool result = false; + + // + // Initialize Application Main Window ... + result = eaMainWindow.Create( + ChartID(), + ShortName, // Dialog Name ... + 0, // SubWindow ... + 10, // X1 ... + 35, // Y1 ... + 300, // X2 ... + 200 // Y2 ... + ); + + // + // Configuring Dialog ... + // eaMainWindow.MinimizeButton(false); // Hide Minimize Button ... + // eaMainWindow.CloseButton(false); // Hide Close Button ... + eaMainWindow.BackgroundColor(clrBlack); + // result = true; + + // + // Try To Run Main Window ... + if (result) + { + eaMainWindow.Run(); + } + + // + return result; +} + +/** + * Update GUI based on Each Ticks ... + */ +void UpdateGUI() +{ + // + // TODO: Implement this ... +} + +/** + * Destroy all Initialized GUi Requirements ... + */ +void DestroyGUI() +{ + // + eaMainWindow.Destroy(); +} + +// +// Others ... + +/** + * Update Positions States ... + */ +void UpdatePositionsState() +{ + // + // TODO: Implement this ... +} + +/** + * Handle On Click Event for GUI Components ... + * + * @param name: Object Name ... + */ +void HandleOnClickEvent(string name) +{ + // + if (!IsValid(name)) + { + return; + } + + // + bool isClicked = false; + + // + // TODO: Implement Chart Objects On Click ... + + // + if (isClicked) + { + UpdateGUI(); + } +} + +/** + * Report Account Balance ... + */ +void HandleReportBalance() +{ + // + if (!IsRunningOnTestMode()) + { + return; + } + + // + string msg = "Balance: " + ToString(eaTrader.mAccount.GetBalance()); + eaAlert.Log(msg); +} + +/** + * Time Reporting based on Inputs ... + */ +void HandleReportTime() +{ + // + // Monthly Report .... + if (eaReportNewMonths && + eaTimeTracker.IsNewMonth()) + { + // + string msg = "New Month ..."; + + // + eaAlert.Alert(msg); + } + + // + // Weekly Report .... + if (eaReportNewWeeks && + eaTimeTracker.IsNewWeek()) + { + // + string msg = "New Week ..."; + + // + eaAlert.Alert(msg); + } + + // + // Daily Report .... + if (eaReportNewDays && + eaTimeTracker.IsNewDay()) + { + // + string msg = "New Day ..."; + + // + eaAlert.Alert(msg); + } + + // + // Hourly Report .... + if (eaReportNewHours && + eaTimeTracker.IsNewHour()) + { + // + string msg = "New Hour ..."; + + // + eaAlert.Alert(msg); + } +} + +// diff --git a/BKPS/14031218/Experts/Advisors/ExpertMACD.mq5 b/BKPS/14031218/Experts/Advisors/ExpertMACD.mq5 new file mode 100644 index 0000000..0e4c57c --- /dev/null +++ b/BKPS/14031218/Experts/Advisors/ExpertMACD.mq5 @@ -0,0 +1,168 @@ +//+------------------------------------------------------------------+ +//| ExpertMACD.mq5 | +//| Copyright 2000-2025, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2000-2025, MetaQuotes Ltd." +#property link "https://www.mql5.com" +#property version "1.00" +//+------------------------------------------------------------------+ +//| Include | +//+------------------------------------------------------------------+ +#include +#include +#include +#include +//+------------------------------------------------------------------+ +//| Inputs | +//+------------------------------------------------------------------+ +//--- inputs for expert +input string Inp_Expert_Title ="ExpertMACD"; +int Expert_MagicNumber =10981; +bool Expert_EveryTick =false; +//--- inputs for signal +input int Inp_Signal_MACD_PeriodFast =12; +input int Inp_Signal_MACD_PeriodSlow =24; +input int Inp_Signal_MACD_PeriodSignal=9; +input int Inp_Signal_MACD_TakeProfit =50; +input int Inp_Signal_MACD_StopLoss =20; +//+------------------------------------------------------------------+ +//| Global expert object | +//+------------------------------------------------------------------+ +CExpert ExtExpert; +//+------------------------------------------------------------------+ +//| Initialization function of the expert | +//+------------------------------------------------------------------+ +int OnInit(void) + { +//--- Initializing expert + if(!ExtExpert.Init(Symbol(),Period(),Expert_EveryTick,Expert_MagicNumber)) + { + //--- failed + printf(__FUNCTION__+": error initializing expert"); + ExtExpert.Deinit(); + return(-1); + } +//--- Creation of signal object + CSignalMACD *signal=new CSignalMACD; + if(signal==NULL) + { + //--- failed + printf(__FUNCTION__+": error creating signal"); + ExtExpert.Deinit(); + return(-2); + } +//--- Add signal to expert (will be deleted automatically)) + if(!ExtExpert.InitSignal(signal)) + { + //--- failed + printf(__FUNCTION__+": error initializing signal"); + ExtExpert.Deinit(); + return(-3); + } +//--- Set signal parameters + signal.PeriodFast(Inp_Signal_MACD_PeriodFast); + signal.PeriodSlow(Inp_Signal_MACD_PeriodSlow); + signal.PeriodSignal(Inp_Signal_MACD_PeriodSignal); + signal.TakeLevel(Inp_Signal_MACD_TakeProfit); + signal.StopLevel(Inp_Signal_MACD_StopLoss); +//--- Check signal parameters + if(!signal.ValidationSettings()) + { + //--- failed + printf(__FUNCTION__+": error signal parameters"); + ExtExpert.Deinit(); + return(-4); + } +//--- Creation of trailing object + CTrailingNone *trailing=new CTrailingNone; + if(trailing==NULL) + { + //--- failed + printf(__FUNCTION__+": error creating trailing"); + ExtExpert.Deinit(); + return(-5); + } +//--- Add trailing to expert (will be deleted automatically)) + if(!ExtExpert.InitTrailing(trailing)) + { + //--- failed + printf(__FUNCTION__+": error initializing trailing"); + ExtExpert.Deinit(); + return(-6); + } +//--- Set trailing parameters +//--- Check trailing parameters + if(!trailing.ValidationSettings()) + { + //--- failed + printf(__FUNCTION__+": error trailing parameters"); + ExtExpert.Deinit(); + return(-7); + } +//--- Creation of money object + CMoneyNone *money=new CMoneyNone; + if(money==NULL) + { + //--- failed + printf(__FUNCTION__+": error creating money"); + ExtExpert.Deinit(); + return(-8); + } +//--- Add money to expert (will be deleted automatically)) + if(!ExtExpert.InitMoney(money)) + { + //--- failed + printf(__FUNCTION__+": error initializing money"); + ExtExpert.Deinit(); + return(-9); + } +//--- Set money parameters +//--- Check money parameters + if(!money.ValidationSettings()) + { + //--- failed + printf(__FUNCTION__+": error money parameters"); + ExtExpert.Deinit(); + return(-10); + } +//--- Tuning of all necessary indicators + if(!ExtExpert.InitIndicators()) + { + //--- failed + printf(__FUNCTION__+": error initializing indicators"); + ExtExpert.Deinit(); + return(-11); + } +//--- succeed + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| Deinitialization function of the expert | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { + ExtExpert.Deinit(); + } +//+------------------------------------------------------------------+ +//| Function-event handler "tick" | +//+------------------------------------------------------------------+ +void OnTick(void) + { + ExtExpert.OnTick(); + } +//+------------------------------------------------------------------+ +//| Function-event handler "trade" | +//+------------------------------------------------------------------+ +void OnTrade(void) + { + ExtExpert.OnTrade(); + } +//+------------------------------------------------------------------+ +//| Function-event handler "timer" | +//+------------------------------------------------------------------+ +void OnTimer(void) + { + ExtExpert.OnTimer(); + } +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Experts/Advisors/ExpertMAMA.mq5 b/BKPS/14031218/Experts/Advisors/ExpertMAMA.mq5 new file mode 100644 index 0000000..68e8bb8 --- /dev/null +++ b/BKPS/14031218/Experts/Advisors/ExpertMAMA.mq5 @@ -0,0 +1,175 @@ +//+------------------------------------------------------------------+ +//| ExpertMAMA.mq5 | +//| Copyright 2000-2025, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2000-2025, MetaQuotes Ltd." +#property link "https://www.mql5.com" +#property version "1.00" +//+------------------------------------------------------------------+ +//| Include | +//+------------------------------------------------------------------+ +#include +#include +#include +#include +//+------------------------------------------------------------------+ +//| Inputs | +//+------------------------------------------------------------------+ +//--- inputs for expert +input string Inp_Expert_Title ="ExpertMAMA"; +int Expert_MagicNumber =12003; +bool Expert_EveryTick =false; +//--- inputs for signal +input int Inp_Signal_MA_Period =12; +input int Inp_Signal_MA_Shift =6; +input ENUM_MA_METHOD Inp_Signal_MA_Method =MODE_SMA; +input ENUM_APPLIED_PRICE Inp_Signal_MA_Applied =PRICE_CLOSE; +//--- inputs for trailing +input int Inp_Trailing_MA_Period =12; +input int Inp_Trailing_MA_Shift =0; +input ENUM_MA_METHOD Inp_Trailing_MA_Method =MODE_SMA; +input ENUM_APPLIED_PRICE Inp_Trailing_MA_Applied=PRICE_CLOSE; +//+------------------------------------------------------------------+ +//| Global expert object | +//+------------------------------------------------------------------+ +CExpert ExtExpert; +//+------------------------------------------------------------------+ +//| Initialization function of the expert | +//+------------------------------------------------------------------+ +int OnInit(void) + { +//--- Initializing expert + if(!ExtExpert.Init(Symbol(),Period(),Expert_EveryTick,Expert_MagicNumber)) + { + //--- failed + printf(__FUNCTION__+": error initializing expert"); + ExtExpert.Deinit(); + return(-1); + } +//--- Creation of signal object + CSignalMA *signal=new CSignalMA; + if(signal==NULL) + { + //--- failed + printf(__FUNCTION__+": error creating signal"); + ExtExpert.Deinit(); + return(-2); + } +//--- Add signal to expert (will be deleted automatically)) + if(!ExtExpert.InitSignal(signal)) + { + //--- failed + printf(__FUNCTION__+": error initializing signal"); + ExtExpert.Deinit(); + return(-3); + } +//--- Set signal parameters + signal.PeriodMA(Inp_Signal_MA_Period); + signal.Shift(Inp_Signal_MA_Shift); + signal.Method(Inp_Signal_MA_Method); + signal.Applied(Inp_Signal_MA_Applied); +//--- Check signal parameters + if(!signal.ValidationSettings()) + { + //--- failed + printf(__FUNCTION__+": error signal parameters"); + ExtExpert.Deinit(); + return(-4); + } +//--- Creation of trailing object + CTrailingMA *trailing=new CTrailingMA; + if(trailing==NULL) + { + //--- failed + printf(__FUNCTION__+": error creating trailing"); + ExtExpert.Deinit(); + return(-5); + } +//--- Add trailing to expert (will be deleted automatically)) + if(!ExtExpert.InitTrailing(trailing)) + { + //--- failed + printf(__FUNCTION__+": error initializing trailing"); + ExtExpert.Deinit(); + return(-6); + } +//--- Set trailing parameters + trailing.Period(Inp_Trailing_MA_Period); + trailing.Shift(Inp_Trailing_MA_Shift); + trailing.Method(Inp_Trailing_MA_Method); + trailing.Applied(Inp_Trailing_MA_Applied); +//--- Check trailing parameters + if(!trailing.ValidationSettings()) + { + //--- failed + printf(__FUNCTION__+": error trailing parameters"); + ExtExpert.Deinit(); + return(-7); + } +//--- Creation of money object + CMoneyNone *money=new CMoneyNone; + if(money==NULL) + { + //--- failed + printf(__FUNCTION__+": error creating money"); + ExtExpert.Deinit(); + return(-8); + } +//--- Add money to expert (will be deleted automatically)) + if(!ExtExpert.InitMoney(money)) + { + //--- failed + printf(__FUNCTION__+": error initializing money"); + ExtExpert.Deinit(); + return(-9); + } +//--- Set money parameters +//--- Check money parameters + if(!money.ValidationSettings()) + { + //--- failed + printf(__FUNCTION__+": error money parameters"); + ExtExpert.Deinit(); + return(-10); + } +//--- Tuning of all necessary indicators + if(!ExtExpert.InitIndicators()) + { + //--- failed + printf(__FUNCTION__+": error initializing indicators"); + ExtExpert.Deinit(); + return(-11); + } +//--- succeed + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| Deinitialization function of the expert | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { + ExtExpert.Deinit(); + } +//+------------------------------------------------------------------+ +//| Function-event handler "tick" | +//+------------------------------------------------------------------+ +void OnTick(void) + { + ExtExpert.OnTick(); + } +//+------------------------------------------------------------------+ +//| Function-event handler "trade" | +//+------------------------------------------------------------------+ +void OnTrade(void) + { + ExtExpert.OnTrade(); + } +//+------------------------------------------------------------------+ +//| Function-event handler "timer" | +//+------------------------------------------------------------------+ +void OnTimer(void) + { + ExtExpert.OnTimer(); + } +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Experts/Advisors/ExpertMAPSAR.mq5 b/BKPS/14031218/Experts/Advisors/ExpertMAPSAR.mq5 new file mode 100644 index 0000000..1eae701 --- /dev/null +++ b/BKPS/14031218/Experts/Advisors/ExpertMAPSAR.mq5 @@ -0,0 +1,171 @@ +//+------------------------------------------------------------------+ +//| ExpertMAPSAR.mq5 | +//| Copyright 2000-2025, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2000-2025, MetaQuotes Ltd." +#property link "https://www.mql5.com" +#property version "1.00" +//+------------------------------------------------------------------+ +//| Include | +//+------------------------------------------------------------------+ +#include +#include +#include +#include +//+------------------------------------------------------------------+ +//| Inputs | +//+------------------------------------------------------------------+ +//--- inputs for expert +input string Inp_Expert_Title ="ExpertMAPSAR"; +int Expert_MagicNumber =14598; +bool Expert_EveryTick =false; +//--- inputs for signal +input int Inp_Signal_MA_Period =12; +input int Inp_Signal_MA_Shift =6; +input ENUM_MA_METHOD Inp_Signal_MA_Method =MODE_SMA; +input ENUM_APPLIED_PRICE Inp_Signal_MA_Applied =PRICE_CLOSE; +//--- inputs for trailing +input double Inp_Trailing_ParabolicSAR_Step =0.02; +input double Inp_Trailing_ParabolicSAR_Maximum=0.2; +//+------------------------------------------------------------------+ +//| Global expert object | +//+------------------------------------------------------------------+ +CExpert ExtExpert; +//+------------------------------------------------------------------+ +//| Initialization function of the expert | +//+------------------------------------------------------------------+ +int OnInit(void) + { +//--- Initializing expert + if(!ExtExpert.Init(Symbol(),Period(),Expert_EveryTick,Expert_MagicNumber)) + { + //--- failed + printf(__FUNCTION__+": error initializing expert"); + ExtExpert.Deinit(); + return(-1); + } +//--- Creation of signal object + CSignalMA *signal=new CSignalMA; + if(signal==NULL) + { + //--- failed + printf(__FUNCTION__+": error creating signal"); + ExtExpert.Deinit(); + return(-2); + } +//--- Add signal to expert (will be deleted automatically)) + if(!ExtExpert.InitSignal(signal)) + { + //--- failed + printf(__FUNCTION__+": error initializing signal"); + ExtExpert.Deinit(); + return(-3); + } +//--- Set signal parameters + signal.PeriodMA(Inp_Signal_MA_Period); + signal.Shift(Inp_Signal_MA_Shift); + signal.Method(Inp_Signal_MA_Method); + signal.Applied(Inp_Signal_MA_Applied); +//--- Check signal parameters + if(!signal.ValidationSettings()) + { + //--- failed + printf(__FUNCTION__+": error signal parameters"); + ExtExpert.Deinit(); + return(-4); + } +//--- Creation of trailing object + CTrailingPSAR *trailing=new CTrailingPSAR; + if(trailing==NULL) + { + //--- failed + printf(__FUNCTION__+": error creating trailing"); + ExtExpert.Deinit(); + return(-5); + } +//--- Add trailing to expert (will be deleted automatically)) + if(!ExtExpert.InitTrailing(trailing)) + { + //--- failed + printf(__FUNCTION__+": error initializing trailing"); + ExtExpert.Deinit(); + return(-6); + } +//--- Set trailing parameters + trailing.Step(Inp_Trailing_ParabolicSAR_Step); + trailing.Maximum(Inp_Trailing_ParabolicSAR_Maximum); +//--- Check trailing parameters + if(!trailing.ValidationSettings()) + { + //--- failed + printf(__FUNCTION__+": error trailing parameters"); + ExtExpert.Deinit(); + return(-7); + } +//--- Creation of money object + CMoneyNone *money=new CMoneyNone; + if(money==NULL) + { + //--- failed + printf(__FUNCTION__+": error creating money"); + ExtExpert.Deinit(); + return(-8); + } +//--- Add money to expert (will be deleted automatically)) + if(!ExtExpert.InitMoney(money)) + { + //--- failed + printf(__FUNCTION__+": error initializing money"); + ExtExpert.Deinit(); + return(-9); + } +//--- Set money parameters +//--- Check money parameters + if(!money.ValidationSettings()) + { + //--- failed + printf(__FUNCTION__+": error money parameters"); + ExtExpert.Deinit(); + return(-10); + } +//--- Tuning of all necessary indicators + if(!ExtExpert.InitIndicators()) + { + //--- failed + printf(__FUNCTION__+": error initializing indicators"); + ExtExpert.Deinit(); + return(-11); + } +//--- succeed + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| Deinitialization function of the expert | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { + ExtExpert.Deinit(); + } +//+------------------------------------------------------------------+ +//| Function-event handler "tick" | +//+------------------------------------------------------------------+ +void OnTick(void) + { + ExtExpert.OnTick(); + } +//+------------------------------------------------------------------+ +//| Function-event handler "trade" | +//+------------------------------------------------------------------+ +void OnTrade(void) + { + ExtExpert.OnTrade(); + } +//+------------------------------------------------------------------+ +//| Function-event handler "timer" | +//+------------------------------------------------------------------+ +void OnTimer(void) + { + ExtExpert.OnTimer(); + } +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Experts/Advisors/ExpertMAPSARSizeOptimized.mq5 b/BKPS/14031218/Experts/Advisors/ExpertMAPSARSizeOptimized.mq5 new file mode 100644 index 0000000..e7da4e7 --- /dev/null +++ b/BKPS/14031218/Experts/Advisors/ExpertMAPSARSizeOptimized.mq5 @@ -0,0 +1,176 @@ +//+------------------------------------------------------------------+ +//| ExpertMAPSARSizeOptimized.mq5 | +//| Copyright 2000-2025, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2000-2025, MetaQuotes Ltd." +#property link "https://www.mql5.com" +#property version "1.00" +//+------------------------------------------------------------------+ +//| Include | +//+------------------------------------------------------------------+ +#include +#include +#include +#include +//+------------------------------------------------------------------+ +//| Inputs | +//+------------------------------------------------------------------+ +//--- inputs for expert +input string Inp_Expert_Title ="ExpertMAPSARSizeOptimized"; +int Expert_MagicNumber =27893; +bool Expert_EveryTick =false; +//--- inputs for signal +input int Inp_Signal_MA_Period =12; +input int Inp_Signal_MA_Shift =6; +input ENUM_MA_METHOD Inp_Signal_MA_Method =MODE_SMA; +input ENUM_APPLIED_PRICE Inp_Signal_MA_Applied =PRICE_CLOSE; +//--- inputs for trailing +input double Inp_Trailing_ParabolicSAR_Step =0.02; +input double Inp_Trailing_ParabolicSAR_Maximum =0.2; +//--- inputs for money +input double Inp_Money_SizeOptimized_DecreaseFactor=3.0; +input double Inp_Money_SizeOptimized_Percent =10.0; +//+------------------------------------------------------------------+ +//| Global expert object | +//+------------------------------------------------------------------+ +CExpert ExtExpert; +//+------------------------------------------------------------------+ +//| Initialization function of the expert | +//+------------------------------------------------------------------+ +int OnInit(void) + { +//--- Initializing expert + if(!ExtExpert.Init(Symbol(),Period(),Expert_EveryTick,Expert_MagicNumber)) + { + //--- failed + printf(__FUNCTION__+": error initializing expert"); + ExtExpert.Deinit(); + return(-1); + } +//--- Creation of signal object + CSignalMA *signal=new CSignalMA; + if(signal==NULL) + { + //--- failed + printf(__FUNCTION__+": error creating signal"); + ExtExpert.Deinit(); + return(-2); + } +//--- Add signal to expert (will be deleted automatically)) + if(!ExtExpert.InitSignal(signal)) + { + //--- failed + printf(__FUNCTION__+": error initializing signal"); + ExtExpert.Deinit(); + return(-3); + } +//--- Set signal parameters + signal.PeriodMA(Inp_Signal_MA_Period); + signal.Shift(Inp_Signal_MA_Shift); + signal.Method(Inp_Signal_MA_Method); + signal.Applied(Inp_Signal_MA_Applied); +//--- Check signal parameters + if(!signal.ValidationSettings()) + { + //--- failed + printf(__FUNCTION__+": error signal parameters"); + ExtExpert.Deinit(); + return(-4); + } +//--- Creation of trailing object + CTrailingPSAR *trailing=new CTrailingPSAR; + if(trailing==NULL) + { + //--- failed + printf(__FUNCTION__+": error creating trailing"); + ExtExpert.Deinit(); + return(-5); + } +//--- Add trailing to expert (will be deleted automatically)) + if(!ExtExpert.InitTrailing(trailing)) + { + //--- failed + printf(__FUNCTION__+": error initializing trailing"); + ExtExpert.Deinit(); + return(-6); + } +//--- Set trailing parameters + trailing.Step(Inp_Trailing_ParabolicSAR_Step); + trailing.Maximum(Inp_Trailing_ParabolicSAR_Maximum); +//--- Check trailing parameters + if(!trailing.ValidationSettings()) + { + //--- failed + printf(__FUNCTION__+": error trailing parameters"); + ExtExpert.Deinit(); + return(-7); + } +//--- Creation of money object + CMoneySizeOptimized *money=new CMoneySizeOptimized; + if(money==NULL) + { + //--- failed + printf(__FUNCTION__+": error creating money"); + ExtExpert.Deinit(); + return(-8); + } +//--- Add money to expert (will be deleted automatically)) + if(!ExtExpert.InitMoney(money)) + { + //--- failed + printf(__FUNCTION__+": error initializing money"); + ExtExpert.Deinit(); + return(-9); + } +//--- Set money parameters + money.DecreaseFactor(Inp_Money_SizeOptimized_DecreaseFactor); + money.Percent(Inp_Money_SizeOptimized_Percent); +//--- Check money parameters + if(!money.ValidationSettings()) + { + //--- failed + printf(__FUNCTION__+": error money parameters"); + ExtExpert.Deinit(); + return(-10); + } +//--- Tuning of all necessary indicators + if(!ExtExpert.InitIndicators()) + { + //--- failed + printf(__FUNCTION__+": error initializing indicators"); + ExtExpert.Deinit(); + return(-11); + } +//--- succeed + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| Deinitialization function of the expert | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { + ExtExpert.Deinit(); + } +//+------------------------------------------------------------------+ +//| Function-event handler "tick" | +//+------------------------------------------------------------------+ +void OnTick(void) + { + ExtExpert.OnTick(); + } +//+------------------------------------------------------------------+ +//| Function-event handler "trade" | +//+------------------------------------------------------------------+ +void OnTrade(void) + { + ExtExpert.OnTrade(); + } +//+------------------------------------------------------------------+ +//| Function-event handler "timer" | +//+------------------------------------------------------------------+ +void OnTimer(void) + { + ExtExpert.OnTimer(); + } +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Experts/Examples/ChartInChart/ChartInChart.mq5 b/BKPS/14031218/Experts/Examples/ChartInChart/ChartInChart.mq5 new file mode 100644 index 0000000..3ae1082 Binary files /dev/null and b/BKPS/14031218/Experts/Examples/ChartInChart/ChartInChart.mq5 differ diff --git a/BKPS/14031218/Experts/Examples/Controls/Controls.mq5 b/BKPS/14031218/Experts/Examples/Controls/Controls.mq5 new file mode 100644 index 0000000..b10deb2 --- /dev/null +++ b/BKPS/14031218/Experts/Examples/Controls/Controls.mq5 @@ -0,0 +1,45 @@ +//+------------------------------------------------------------------+ +//| Controls.mq5 | +//| Copyright 2000-2025, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2000-2025, MetaQuotes Ltd." +#property link "https://www.mql5.com" +#property version "1.00" +#include "ControlsDialog.mqh" +//+------------------------------------------------------------------+ +//| Global Variables | +//+------------------------------------------------------------------+ +CControlsDialog ExtDialog; +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { +//--- create application dialog + if(!ExtDialog.Create(0,"Controls",0,20,20,360,324)) + return(INIT_FAILED); +//--- run application + ExtDialog.Run(); +//--- succeed + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { +//--- destroy dialog + ExtDialog.Destroy(reason); + } +//+------------------------------------------------------------------+ +//| Expert chart event function | +//+------------------------------------------------------------------+ +void OnChartEvent(const int id, // event ID + const long& lparam, // event parameter of the long type + const double& dparam, // event parameter of the double type + const string& sparam) // event parameter of the string type + { + ExtDialog.ChartEvent(id,lparam,dparam,sparam); + } +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Experts/Examples/Controls/ControlsDialog.mqh b/BKPS/14031218/Experts/Examples/Controls/ControlsDialog.mqh new file mode 100644 index 0000000..4ed57d7 --- /dev/null +++ b/BKPS/14031218/Experts/Examples/Controls/ControlsDialog.mqh @@ -0,0 +1,427 @@ +//+------------------------------------------------------------------+ +//| ControlsDialog.mqh | +//| Copyright 2000-2025, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#include +#include +#include +#include +#include +#include +#include +#include +#include +//+------------------------------------------------------------------+ +//| defines | +//+------------------------------------------------------------------+ +//--- indents and gaps +#define INDENT_LEFT (11) // indent from left (with allowance for border width) +#define INDENT_TOP (11) // indent from top (with allowance for border width) +#define INDENT_RIGHT (11) // indent from right (with allowance for border width) +#define INDENT_BOTTOM (11) // indent from bottom (with allowance for border width) +#define CONTROLS_GAP_X (5) // gap by X coordinate +#define CONTROLS_GAP_Y (5) // gap by Y coordinate +//--- for buttons +#define BUTTON_WIDTH (100) // size by X coordinate +#define BUTTON_HEIGHT (20) // size by Y coordinate +//--- for the indication area +#define EDIT_HEIGHT (20) // size by Y coordinate +//--- for group controls +#define GROUP_WIDTH (150) // size by X coordinate +#define LIST_HEIGHT (179) // size by Y coordinate +#define RADIO_HEIGHT (56) // size by Y coordinate +#define CHECK_HEIGHT (93) // size by Y coordinate +//+------------------------------------------------------------------+ +//| Class CControlsDialog | +//| Usage: main dialog of the Controls application | +//+------------------------------------------------------------------+ +class CControlsDialog : public CAppDialog + { +private: + CEdit m_edit; // the display field object + CButton m_button1; // the button object + CButton m_button2; // the button object + CButton m_button3; // the fixed button object + CSpinEdit m_spin_edit; // the up-down object + CDatePicker m_date; // the datepicker object + CListView m_list_view; // the list object + CComboBox m_combo_box; // the dropdown list object + CRadioGroup m_radio_group; // the radio buttons group object + CCheckGroup m_check_group; // the check box group object + +public: + CControlsDialog(void); + ~CControlsDialog(void); + //--- create + virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2); + //--- chart event handler + virtual bool OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam); + +protected: + //--- create dependent controls + bool CreateEdit(void); + bool CreateButton1(void); + bool CreateButton2(void); + bool CreateButton3(void); + bool CreateSpinEdit(void); + bool CreateDate(void); + bool CreateListView(void); + bool CreateComboBox(void); + bool CreateRadioGroup(void); + bool CreateCheckGroup(void); + //--- handlers of the dependent controls events + void OnClickButton1(void); + void OnClickButton2(void); + void OnClickButton3(void); + void OnChangeSpinEdit(void); + void OnChangeDate(void); + void OnChangeListView(void); + void OnChangeComboBox(void); + void OnChangeRadioGroup(void); + void OnChangeCheckGroup(void); + }; +//+------------------------------------------------------------------+ +//| Event Handling | +//+------------------------------------------------------------------+ +EVENT_MAP_BEGIN(CControlsDialog) + ON_EVENT(ON_CLICK,m_button1,OnClickButton1) + ON_EVENT(ON_CLICK,m_button2,OnClickButton2) + ON_EVENT(ON_CLICK,m_button3,OnClickButton3) + ON_EVENT(ON_CHANGE,m_spin_edit,OnChangeSpinEdit) + ON_EVENT(ON_CHANGE,m_date,OnChangeDate) + ON_EVENT(ON_CHANGE,m_list_view,OnChangeListView) + ON_EVENT(ON_CHANGE,m_combo_box,OnChangeComboBox) + ON_EVENT(ON_CHANGE,m_radio_group,OnChangeRadioGroup) + ON_EVENT(ON_CHANGE,m_check_group,OnChangeCheckGroup) +EVENT_MAP_END(CAppDialog) +//+------------------------------------------------------------------+ +//| Constructor | +//+------------------------------------------------------------------+ +CControlsDialog::CControlsDialog(void) + { + } +//+------------------------------------------------------------------+ +//| Destructor | +//+------------------------------------------------------------------+ +CControlsDialog::~CControlsDialog(void) + { + } +//+------------------------------------------------------------------+ +//| Create | +//+------------------------------------------------------------------+ +bool CControlsDialog::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2) + { + if(!CAppDialog::Create(chart,name,subwin,x1,y1,x2,y2)) + return(false); +//--- create dependent controls + if(!CreateEdit()) + return(false); + if(!CreateButton1()) + return(false); + if(!CreateButton2()) + return(false); + if(!CreateButton3()) + return(false); + if(!CreateSpinEdit()) + return(false); + if(!CreateListView()) + return(false); + if(!CreateDate()) + return(false); + if(!CreateRadioGroup()) + return(false); + if(!CreateCheckGroup()) + return(false); + if(!CreateComboBox()) + return(false); +//--- succeed + return(true); + } +//+------------------------------------------------------------------+ +//| Create the display field | +//+------------------------------------------------------------------+ +bool CControlsDialog::CreateEdit(void) + { +//--- coordinates + int x1=INDENT_LEFT; + int y1=INDENT_TOP; + int x2=ClientAreaWidth()-INDENT_RIGHT; + int y2=y1+EDIT_HEIGHT; +//--- create + if(!m_edit.Create(m_chart_id,m_name+"Edit",m_subwin,x1,y1,x2,y2)) + return(false); + if(!m_edit.ReadOnly(true)) + return(false); + if(!Add(m_edit)) + return(false); +//--- succeed + return(true); + } +//+------------------------------------------------------------------+ +//| Create the "Button1" button | +//+------------------------------------------------------------------+ +bool CControlsDialog::CreateButton1(void) + { +//--- coordinates + int x1=INDENT_LEFT; + int y1=INDENT_TOP+(EDIT_HEIGHT+CONTROLS_GAP_Y); + int x2=x1+BUTTON_WIDTH; + int y2=y1+BUTTON_HEIGHT; +//--- create + if(!m_button1.Create(m_chart_id,m_name+"Button1",m_subwin,x1,y1,x2,y2)) + return(false); + if(!m_button1.Text("Button1")) + return(false); + if(!Add(m_button1)) + return(false); +//--- succeed + return(true); + } +//+------------------------------------------------------------------+ +//| Create the "Button2" button | +//+------------------------------------------------------------------+ +bool CControlsDialog::CreateButton2(void) + { +//--- coordinates + int x1=INDENT_LEFT+(BUTTON_WIDTH+CONTROLS_GAP_X); + int y1=INDENT_TOP+(EDIT_HEIGHT+CONTROLS_GAP_Y); + int x2=x1+BUTTON_WIDTH; + int y2=y1+BUTTON_HEIGHT; +//--- create + if(!m_button2.Create(m_chart_id,m_name+"Button2",m_subwin,x1,y1,x2,y2)) + return(false); + if(!m_button2.Text("Button2")) + return(false); + if(!Add(m_button2)) + return(false); +//--- succeed + return(true); + } +//+------------------------------------------------------------------+ +//| Create the "Button3" fixed button | +//+------------------------------------------------------------------+ +bool CControlsDialog::CreateButton3(void) + { +//--- coordinates + int x1=INDENT_LEFT+2*(BUTTON_WIDTH+CONTROLS_GAP_X); + int y1=INDENT_TOP+(EDIT_HEIGHT+CONTROLS_GAP_Y); + int x2=x1+BUTTON_WIDTH; + int y2=y1+BUTTON_HEIGHT; +//--- create + if(!m_button3.Create(m_chart_id,m_name+"Button3",m_subwin,x1,y1,x2,y2)) + return(false); + if(!m_button3.Text("Locked")) + return(false); + if(!Add(m_button3)) + return(false); + m_button3.Locking(true); +//--- succeed + return(true); + } +//+------------------------------------------------------------------+ +//| Create the "SpinEdit" element | +//+------------------------------------------------------------------+ +bool CControlsDialog::CreateSpinEdit(void) + { +//--- coordinates + int x1=INDENT_LEFT; + int y1=INDENT_TOP+(EDIT_HEIGHT+CONTROLS_GAP_Y)+(BUTTON_HEIGHT+CONTROLS_GAP_Y); + int x2=x1+GROUP_WIDTH; + int y2=y1+EDIT_HEIGHT; +//--- create + if(!m_spin_edit.Create(m_chart_id,m_name+"SpinEdit",m_subwin,x1,y1,x2,y2)) + return(false); + if(!Add(m_spin_edit)) + return(false); + m_spin_edit.MinValue(10); + m_spin_edit.MaxValue(1000); + m_spin_edit.Value(100); +//--- succeed + return(true); + } +//+------------------------------------------------------------------+ +//| Create the "DatePicker" element | +//+------------------------------------------------------------------+ +bool CControlsDialog::CreateDate(void) + { +//--- coordinates + int x1=INDENT_LEFT+GROUP_WIDTH+2*CONTROLS_GAP_X; + int y1=INDENT_TOP+(EDIT_HEIGHT+CONTROLS_GAP_Y)+(BUTTON_HEIGHT+CONTROLS_GAP_Y); + int x2=x1+GROUP_WIDTH; + int y2=y1+EDIT_HEIGHT; +//--- create + if(!m_date.Create(m_chart_id,m_name+"Date",m_subwin,x1,y1,x2,y2)) + return(false); + if(!Add(m_date)) + return(false); + m_date.Value(TimeCurrent()); +//--- succeed + return(true); + } +//+------------------------------------------------------------------+ +//| Create the "ListView" element | +//+------------------------------------------------------------------+ +bool CControlsDialog::CreateListView(void) + { +//--- coordinates + int x1=INDENT_LEFT+GROUP_WIDTH+2*CONTROLS_GAP_X; + int y1=INDENT_TOP+(EDIT_HEIGHT+CONTROLS_GAP_Y)+ + (BUTTON_HEIGHT+CONTROLS_GAP_Y)+ + (EDIT_HEIGHT+2*CONTROLS_GAP_Y); + int x2=x1+GROUP_WIDTH; + int y2=y1+LIST_HEIGHT-CONTROLS_GAP_Y; +//--- create + if(!m_list_view.Create(m_chart_id,m_name+"ListView",m_subwin,x1,y1,x2,y2)) + return(false); + if(!Add(m_list_view)) + return(false); +//--- fill out with strings + for(int i=0;i<16;i++) + if(!m_list_view.AddItem("Item "+IntegerToString(i))) + return(false); +//--- succeed + return(true); + } +//+------------------------------------------------------------------+ +//| Create the "ComboBox" element | +//+------------------------------------------------------------------+ +bool CControlsDialog::CreateComboBox(void) + { +//--- coordinates + int x1=INDENT_LEFT; + int y1=INDENT_TOP+(EDIT_HEIGHT+CONTROLS_GAP_Y)+ + (BUTTON_HEIGHT+CONTROLS_GAP_Y)+ + (EDIT_HEIGHT+CONTROLS_GAP_Y); + int x2=x1+GROUP_WIDTH; + int y2=y1+EDIT_HEIGHT; +//--- create + if(!m_combo_box.Create(m_chart_id,m_name+"ComboBox",m_subwin,x1,y1,x2,y2)) + return(false); + if(!Add(m_combo_box)) + return(false); +//--- fill out with strings + for(int i=0;i<16;i++) + if(!m_combo_box.ItemAdd("Item "+IntegerToString(i))) + return(false); +//--- succeed + return(true); + } +//+------------------------------------------------------------------+ +//| Create the "RadioGroup" element | +//+------------------------------------------------------------------+ +bool CControlsDialog::CreateRadioGroup(void) + { +//--- coordinates + int x1=INDENT_LEFT; + int y1=INDENT_TOP+(EDIT_HEIGHT+CONTROLS_GAP_Y)+ + (BUTTON_HEIGHT+CONTROLS_GAP_Y)+ + (EDIT_HEIGHT+CONTROLS_GAP_Y)+ + (EDIT_HEIGHT+CONTROLS_GAP_Y); + int x2=x1+GROUP_WIDTH; + int y2=y1+RADIO_HEIGHT; +//--- create + if(!m_radio_group.Create(m_chart_id,m_name+"RadioGroup",m_subwin,x1,y1,x2,y2)) + return(false); + if(!Add(m_radio_group)) + return(false); +//--- fill out with strings + for(int i=0;i<3;i++) + if(!m_radio_group.AddItem("Item "+IntegerToString(i),1< +#include +#include +#include +//--- +input double InpLots =0.1; // Lots +input int InpTakeProfit =50; // Take Profit (in pips) +input int InpTrailingStop =30; // Trailing Stop Level (in pips) +input int InpMACDOpenLevel =3; // MACD open level (in pips) +input int InpMACDCloseLevel=2; // MACD close level (in pips) +input int InpMATrendPeriod =26; // MA trend period +//--- +int ExtTimeOut=10; // time out in seconds between trade operations +//+------------------------------------------------------------------+ +//| MACD Sample expert class | +//+------------------------------------------------------------------+ +class CSampleExpert + { +protected: + double m_adjusted_point; // point value adjusted for 3 or 5 points + CTrade m_trade; // trading object + CSymbolInfo m_symbol; // symbol info object + CPositionInfo m_position; // trade position object + CAccountInfo m_account; // account info wrapper + //--- indicators + int m_handle_macd; // MACD indicator handle + int m_handle_ema; // moving average indicator handle + //--- indicator buffers + double m_buff_MACD_main[]; // MACD indicator main buffer + double m_buff_MACD_signal[]; // MACD indicator signal buffer + double m_buff_EMA[]; // EMA indicator buffer + //--- indicator data for processing + double m_macd_current; + double m_macd_previous; + double m_signal_current; + double m_signal_previous; + double m_ema_current; + double m_ema_previous; + //--- + double m_macd_open_level; + double m_macd_close_level; + double m_traling_stop; + double m_take_profit; + +public: + CSampleExpert(void); + ~CSampleExpert(void); + bool Init(void); + void Deinit(void); + bool Processing(void); + +protected: + bool InitCheckParameters(const int digits_adjust); + bool InitIndicators(void); + bool LongClosed(void); + bool ShortClosed(void); + bool LongModified(void); + bool ShortModified(void); + bool LongOpened(void); + bool ShortOpened(void); + }; +//--- global expert +CSampleExpert ExtExpert; +//+------------------------------------------------------------------+ +//| Constructor | +//+------------------------------------------------------------------+ +CSampleExpert::CSampleExpert(void) : m_adjusted_point(0), + m_handle_macd(INVALID_HANDLE), + m_handle_ema(INVALID_HANDLE), + m_macd_current(0), + m_macd_previous(0), + m_signal_current(0), + m_signal_previous(0), + m_ema_current(0), + m_ema_previous(0), + m_macd_open_level(0), + m_macd_close_level(0), + m_traling_stop(0), + m_take_profit(0) + { + ArraySetAsSeries(m_buff_MACD_main,true); + ArraySetAsSeries(m_buff_MACD_signal,true); + ArraySetAsSeries(m_buff_EMA,true); + } +//+------------------------------------------------------------------+ +//| Destructor | +//+------------------------------------------------------------------+ +CSampleExpert::~CSampleExpert(void) + { + } +//+------------------------------------------------------------------+ +//| Initialization and checking for input parameters | +//+------------------------------------------------------------------+ +bool CSampleExpert::Init(void) + { +//--- initialize common information + m_symbol.Name(Symbol()); // symbol + m_trade.SetExpertMagicNumber(MACD_MAGIC); // magic + m_trade.SetMarginMode(); + m_trade.SetTypeFillingBySymbol(Symbol()); +//--- tuning for 3 or 5 digits + int digits_adjust=1; + if(m_symbol.Digits()==3 || m_symbol.Digits()==5) + digits_adjust=10; + m_adjusted_point=m_symbol.Point()*digits_adjust; +//--- set default deviation for trading in adjusted points + m_macd_open_level =InpMACDOpenLevel*m_adjusted_point; + m_macd_close_level=InpMACDCloseLevel*m_adjusted_point; + m_traling_stop =InpTrailingStop*m_adjusted_point; + m_take_profit =InpTakeProfit*m_adjusted_point; +//--- set default deviation for trading in adjusted points + m_trade.SetDeviationInPoints(3*digits_adjust); +//--- + if(!InitCheckParameters(digits_adjust)) + return(false); + if(!InitIndicators()) + return(false); +//--- succeed + return(true); + } +//+------------------------------------------------------------------+ +//| Checking for input parameters | +//+------------------------------------------------------------------+ +bool CSampleExpert::InitCheckParameters(const int digits_adjust) + { +//--- initial data checks + if(InpTakeProfit*digits_adjustm_symbol.LotsMax()) + { + printf("Lots amount must be in the range from %f to %f",m_symbol.LotsMin(),m_symbol.LotsMax()); + return(false); + } + if(MathAbs(InpLots/m_symbol.LotsStep()-MathRound(InpLots/m_symbol.LotsStep()))>1.0E-10) + { + printf("Lots amount is not corresponding with lot step %f",m_symbol.LotsStep()); + return(false); + } +//--- warning + if(InpTakeProfit<=InpTrailingStop) + printf("Warning: Trailing Stop must be less than Take Profit"); +//--- succeed + return(true); + } +//+------------------------------------------------------------------+ +//| Initialization of the indicators | +//+------------------------------------------------------------------+ +bool CSampleExpert::InitIndicators(void) + { +//--- create MACD indicator + if(m_handle_macd==INVALID_HANDLE) + if((m_handle_macd=iMACD(NULL,0,12,26,9,PRICE_CLOSE))==INVALID_HANDLE) + { + printf("Error creating MACD indicator"); + return(false); + } +//--- create EMA indicator and add it to collection + if(m_handle_ema==INVALID_HANDLE) + if((m_handle_ema=iMA(NULL,0,InpMATrendPeriod,0,MODE_EMA,PRICE_CLOSE))==INVALID_HANDLE) + { + printf("Error creating EMA indicator"); + return(false); + } +//--- succeed + return(true); + } +//+------------------------------------------------------------------+ +//| Check for long position closing | +//+------------------------------------------------------------------+ +bool CSampleExpert::LongClosed(void) + { + bool res=false; +//--- should it be closed? + if(m_macd_current>0) + if(m_macd_currentm_signal_previous) + if(m_macd_current>m_macd_close_level) + { + //--- close position + if(m_trade.PositionClose(Symbol())) + printf("Long position by %s to be closed",Symbol()); + else + printf("Error closing position by %s : '%s'",Symbol(),m_trade.ResultComment()); + //--- processed and cannot be modified + res=true; + } +//--- result + return(res); + } +//+------------------------------------------------------------------+ +//| Check for short position closing | +//+------------------------------------------------------------------+ +bool CSampleExpert::ShortClosed(void) + { + bool res=false; +//--- should it be closed? + if(m_macd_current<0) + if(m_macd_current>m_signal_current && m_macd_previousm_macd_close_level) + { + //--- close position + if(m_trade.PositionClose(Symbol())) + printf("Short position by %s to be closed",Symbol()); + else + printf("Error closing position by %s : '%s'",Symbol(),m_trade.ResultComment()); + //--- processed and cannot be modified + res=true; + } +//--- result + return(res); + } +//+------------------------------------------------------------------+ +//| Check for long position modifying | +//+------------------------------------------------------------------+ +bool CSampleExpert::LongModified(void) + { + bool res=false; +//--- check for trailing stop + if(InpTrailingStop>0) + { + if(m_symbol.Bid()-m_position.PriceOpen()>m_adjusted_point*InpTrailingStop) + { + double sl=NormalizeDouble(m_symbol.Bid()-m_traling_stop,m_symbol.Digits()); + double tp=m_position.TakeProfit(); + if(m_position.StopLoss()0) + { + if((m_position.PriceOpen()-m_symbol.Ask())>(m_adjusted_point*InpTrailingStop)) + { + double sl=NormalizeDouble(m_symbol.Ask()+m_traling_stop,m_symbol.Digits()); + double tp=m_position.TakeProfit(); + if(m_position.StopLoss()>sl || m_position.StopLoss()==0.0) + { + //--- modify position + if(m_trade.PositionModify(Symbol(),sl,tp)) + printf("Short position by %s to be modified",Symbol()); + else + { + printf("Error modifying position by %s : '%s'",Symbol(),m_trade.ResultComment()); + printf("Modify parameters : SL=%f,TP=%f",sl,tp); + } + //--- modified and must exit from expert + res=true; + } + } + } +//--- result + return(res); + } +//+------------------------------------------------------------------+ +//| Check for long position opening | +//+------------------------------------------------------------------+ +bool CSampleExpert::LongOpened(void) + { + bool res=false; +//--- check for long position (BUY) possibility + if(m_macd_current<0) + if(m_macd_current>m_signal_current && m_macd_previous(m_macd_open_level) && m_ema_current>m_ema_previous) + { + double price=m_symbol.Ask(); + double tp =m_symbol.Bid()+m_take_profit; + //--- check for free money + if(m_account.FreeMarginCheck(Symbol(),ORDER_TYPE_BUY,InpLots,price)<0.0) + printf("We have no money. Free Margin = %f",m_account.FreeMargin()); + else + { + //--- open position + if(m_trade.PositionOpen(Symbol(),ORDER_TYPE_BUY,InpLots,price,0.0,tp)) + printf("Position by %s to be opened",Symbol()); + else + { + printf("Error opening BUY position by %s : '%s'",Symbol(),m_trade.ResultComment()); + printf("Open parameters : price=%f,TP=%f",price,tp); + } + } + //--- in any case we must exit from expert + res=true; + } +//--- result + return(res); + } +//+------------------------------------------------------------------+ +//| Check for short position opening | +//+------------------------------------------------------------------+ +bool CSampleExpert::ShortOpened(void) + { + bool res=false; +//--- check for short position (SELL) possibility + if(m_macd_current>0) + if(m_macd_currentm_signal_previous) + if(m_macd_current>(m_macd_open_level) && m_ema_current=limit_time) + { + //--- check for data + if(Bars(Symbol(),Period())>2*InpMATrendPeriod) + { + //--- change limit time by timeout in seconds if processed + if(ExtExpert.Processing()) + limit_time=TimeCurrent()+ExtTimeOut; + } + } + } +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Experts/Examples/Math 3D Morpher/Functions.mqh b/BKPS/14031218/Experts/Examples/Math 3D Morpher/Functions.mqh new file mode 100644 index 0000000..1f27019 --- /dev/null +++ b/BKPS/14031218/Experts/Examples/Math 3D Morpher/Functions.mqh @@ -0,0 +1,372 @@ +//+------------------------------------------------------------------+ +//| Functions.mqh | +//| Copyright 2000-2025, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ + +//--- custom function y=f(x,y) +typedef double(*MathFunction)(double,double); + +//+------------------------------------------------------------------+ +//| math functions | +//+------------------------------------------------------------------+ +enum EnMathFunction + { + Peaks=0, + Chomolungma=1, + ClimberDream=2, + Granite=3, + Hedgehog=4, + Hill=5, + Josephine=6, + Screw=7, + DoubleScrew=8, + MultiExtremalScrew=9, + Sink=10, + Skin=11, + Trapfall=12, + }; +//+------------------------------------------------------------------+ +//| Names of the math functions | +//+------------------------------------------------------------------+ +const string ExtFunctionsNames[]= + { + "Peaks", + "Chomolungma", + "Climber Dream", + "Granite", + "Hedgehog", + "Hill", + "Josephine", + "Screw", + "Double Screw", + "Multi Extremal Screw", + "Sinc", + "Skin", + "Trapfall" + }; +//+------------------------------------------------------------------+ +//| Function Peaks | +//+------------------------------------------------------------------+ +double PeaksFunction(double x,double y) + { + double res = 3*MathPow((1-x),2)*MathExp(-x*x-(y+1)*(y+1))-10*(0.2*x-MathPow(x,3)-MathPow(y,5))*MathExp(-x*x-y*y)-1/3*MathExp(-(x+1)*(x+1)-y*y); +//--- + return(res); + } +//+------------------------------------------------------------------+ +//| Function Chomolungma | +//+------------------------------------------------------------------+ +double ChomolungmaFunction(double x,double y) + { + double a= MathCos(x*x)+MathCos(y*y); + double b= MathPow(MathCos(5*x*y),5); + double c=1.0/MathPow(2,b); +//--- calculate result + double res=a-c; +//--- + return(res); + } +//+------------------------------------------------------------------+ +//| Function ClimberDream | +//+------------------------------------------------------------------+ +double ClimberDreamFunction(double x,double y) + { + double a= MathSin(MathSqrt(MathAbs(x - 1.3) + MathAbs(y))); + double b= MathCos(MathSqrt(MathAbs(MathSin(x))) + MathSqrt(MathAbs(MathSin(y)))); + double f=a+b; +//--- calculate result + double res=MathPow(f,4); +//--- + return(res); + } +//+------------------------------------------------------------------+ +//| Function Granite | +//+------------------------------------------------------------------+ +double GraniteFunction(double x,double y) + { + double a= MathPow(MathSin(MathSqrt(MathAbs(x)+MathAbs(y))),2); + double b= MathPow(MathCos(MathSqrt(MathAbs(x)+MathAbs(y))),2); +//--- calculate result + double res=a*b; +//--- + return(res); + } +//+------------------------------------------------------------------+ +//| Function Hedgehog | +//+------------------------------------------------------------------+ +double HedgehogFunction(double x,double y) + { + double a1=MathSin(MathSqrt(MathAbs(x-2)+MathAbs(y))); + double a2=MathCos(MathSqrt(MathAbs(MathSin(x)))+MathSqrt(MathAbs(MathSin(y)))); +//--- calculate result + double res=a1+a2; +//--- + return(res); + } +//+------------------------------------------------------------------+ +//| Function Hill | +//+------------------------------------------------------------------+ +double HillFunction(double x,double y) + { +//--- calculate result + double res=MathExp(-x*x-y*y); +//--- + return(res); + } +//+------------------------------------------------------------------+ +//| Function Josephine | +//+------------------------------------------------------------------+ +double JosephineFunction(double x,double y) + { + double a= MathSin(MathPow(MathAbs(x)+MathAbs(y),0.5)); + double b= MathCos(MathPow(MathAbs(x),0.5)+MathPow(MathAbs(y),0.5)); +//--- calculate function + double res=a+b; +//--- + return(res); + } +//+------------------------------------------------------------------+ +//| Function Screw | +//+------------------------------------------------------------------+ +double ScrewFunction(double x,double y) + { + double a=(y==0)?0:((x*y<0)?MathArctan(x/y):MathArctan(x/y)+M_PI); + double b=x*x+y*y; + double f=MathSin(b+a); +//--- calculate result + double res=(f*f); +//--- + return(res); + } +//+------------------------------------------------------------------+ +//| Function DoubleScrew | +//+------------------------------------------------------------------+ +double DoubleScrewFunction(double x,double y) + { + double a=(y==0)?0:((x*y<0)?MathArctan(x/y):MathArctan(x/y)+M_PI); + double b=x*x+y*y; + double res1=MathCos(b/2+a*3); + res1=((res1*res1)/sqrt(b+1)-0.2); + double res2=MathCos(b/2-a*3); + res2=((res2*res2)/sqrt(b+1)-0.2); + double f=fmax(res1,res2); +//--- calculate result + double res=(f>0)?f:0; +//--- + return(res); + } +//+------------------------------------------------------------------+ +//| Function MultiExtremalScrew | +//+------------------------------------------------------------------+ +double MultiExtremalScrewFunction(double x,double y) + { + double a=(y==0)?0:((x*y<0)?MathArctan(x/y):MathArctan(x/y)+M_PI); + double b=x*x+y*y; + double res1=MathCos(b/2+a*3); + res1=((res1*res1)/sqrt(b+1)-0.2); + double res2=MathCos(b/2-a*3); + res2=((res2*res2)/sqrt(b+1)-0.2); +//--- calculate function + double res=fmin(res1,res2); +//--- + return(res); + } +//+------------------------------------------------------------------+ +//| Function Sink | +//+------------------------------------------------------------------+ +double SinkFunction(double x,double y) + { + static double k=5.0; + static double p=6.0; +//--- calculate result + double res=MathSin(x*x+y*y)+k*MathExp(-p*x*x-p*y*y); +//--- + return(res); + } +//+------------------------------------------------------------------+ +//| Function Skin | +//+------------------------------------------------------------------+ +double SkinFunction(double x,double y) + { + double a1=2*x*x; + double a2=2*y*y; + double b1=MathCos(a1)-1.1; + b1=b1*b1; + double c1=MathSin(0.5*x)-1.2; + c1=c1*c1; + double d1=MathCos(a2)-1.1; + d1=d1*d1; + double e1=MathSin(0.5*y)-1.2; + e1=e1*e1; +//--- calculate result + double res=b1+c1-d1+e1; +//--- + return(res); + } +//+------------------------------------------------------------------+ +//| Function Trapfall | +//+------------------------------------------------------------------+ +double TrapfallFunction(double x,double y) + { + double a1=MathSqrt(MathAbs(MathSin(x-1.0))); + double b1=MathSqrt(MathAbs(MathSin(y+2.0))); +//--- calculate result + double res=-MathSqrt(MathAbs(MathSin(MathSin(a1+b1)))); +//--- + return(res); + } +//+------------------------------------------------------------------+ +//| GenerateFunctionData | +//+------------------------------------------------------------------+ +void GenerateFunctionData(double &data[],int &x_size,int &y_size,double x_min,double x_max,double y_min,double y_max,MathFunction function) + { + double dx = 0.1; + double dy = 0.1; +//--- + x_size = (int)((x_max - x_min)/dx) + 1; + y_size = (int)((y_max - y_min)/dy) + 1; + ArrayResize(data,x_size*y_size); +//--- + for(int j = 0; j < y_size; j++) + { + for(int i = 0; i < x_size; i++) + { + double x = x_min + i*dx; + double y = y_min + j*dy; + data[j*x_size + i] = function(x,y); + } + } + } +//+------------------------------------------------------------------+ +//| GenerateData | +//+------------------------------------------------------------------+ +void GenerateData(EnMathFunction function_id,double &data[],int &x_size,int &y_size) + { +//--- + switch(function_id) + { + case Peaks: + GenerateFunctionData(data,x_size,y_size,-3.0,+3.0,-3.0,+3.0,PeaksFunction); + break; + case Chomolungma: + GenerateFunctionData(data,x_size,y_size,-2.0,+2.0,-2.0,+2.0,ChomolungmaFunction); + break; + case ClimberDream: + GenerateFunctionData(data,x_size,y_size,-10.0,+10.0,-10.0,+10.0,ClimberDreamFunction); + break; + case Granite: + GenerateFunctionData(data,x_size,y_size,-4.0,+4.0,-4.0,+4.0,GraniteFunction); + break; + case Hedgehog: + GenerateFunctionData(data,x_size,y_size,-10.0,+10.0,-10.0,+10.0,HedgehogFunction); + break; + case Hill: + GenerateFunctionData(data,x_size,y_size,-1.5,+1.5,-1.5,+1.5,HillFunction); + break; + case Josephine: + GenerateFunctionData(data,x_size,y_size,-200.0,+200.0,-200.0,+200.0,JosephineFunction); + break; + case Screw: + GenerateFunctionData(data,x_size,y_size,-3.0,+3.0,-3.0,+3.0,ScrewFunction); + break; + case DoubleScrew: + GenerateFunctionData(data,x_size,y_size,-3.0,+3.0,-3.0,+3.0,DoubleScrewFunction); + break; + case MultiExtremalScrew: + GenerateFunctionData(data,x_size,y_size,-3.0,+3.0,-3.0,+3.0,MultiExtremalScrewFunction); + break; + case Sink: + GenerateFunctionData(data,x_size,y_size,-3.0,+3.0,-3.0,+3.0,SinkFunction); + break; + case Skin: + GenerateFunctionData(data,x_size,y_size,-5.0,+5.0,-5.0,+5.0,SkinFunction); + break; + case Trapfall: + GenerateFunctionData(data,x_size,y_size,-5.0,+5.0,-5.0,+5.0,TrapfallFunction); + break; + } + } +//+------------------------------------------------------------------+ +//| GenerateFunctionDataFixedSize | +//+------------------------------------------------------------------+ +bool GenerateFunctionDataFixedSize(int x_size,int y_size,double &data[],double x_min,double x_max,double y_min,double y_max,MathFunction function) + { + if(x_size<2 || y_size<2) + { + PrintFormat("Error in data sizes: x_size=%d,y_size=%d",x_size,y_size); + return(false); + } + double dx = (x_max - x_min)/(x_size-1); + double dy = (y_max - y_min)/(y_size-1); + ArrayResize(data,x_size*y_size); +//--- + for(int j = 0; j < y_size; j++) + { + for(int i = 0; i < x_size; i++) + { + double x = x_min + i*dx; + double y = y_min + j*dy; + data[j*x_size + i] = function(x,y); + } + } + return(true); + } +//+------------------------------------------------------------------+ +//| GenerateDataFixedSize | +//+------------------------------------------------------------------+ +bool GenerateDataFixedSize(int x_size,int y_size,EnMathFunction function_id,double &data[]) + { + if(x_size<2 || y_size<2) + { + PrintFormat("Error in data sizes: x_size=%d,y_size=%d",x_size,y_size); + return(false); + } + bool result=false; +//--- + switch(function_id) + { + case Peaks: + result=GenerateFunctionDataFixedSize(x_size,y_size,data,-3.0,+3.0,-3.0,+3.0,PeaksFunction); + break; + case Chomolungma: + result=GenerateFunctionDataFixedSize(x_size,y_size,data,-2.0,+2.0,-2.0,+2.0,ChomolungmaFunction); + break; + case ClimberDream: + result=GenerateFunctionDataFixedSize(x_size,y_size,data,-10.0,+10.0,-10.0,+10.0,ClimberDreamFunction); + break; + case Granite: + result=GenerateFunctionDataFixedSize(x_size,y_size,data,-4.0,+4.0,-4.0,+4.0,GraniteFunction); + break; + case Hedgehog: + result=GenerateFunctionDataFixedSize(x_size,y_size,data,-10.0,+10.0,-10.0,+10.0,HedgehogFunction); + break; + case Hill: + result=GenerateFunctionDataFixedSize(x_size,y_size,data,-1.5,+1.5,-1.5,+1.5,HillFunction); + break; + case Josephine: + result=GenerateFunctionDataFixedSize(x_size,y_size,data,-200.0,+200.0,-200.0,+200.0,JosephineFunction); + break; + case Screw: + result=GenerateFunctionDataFixedSize(x_size,y_size,data,-3.0,+3.0,-3.0,+3.0,ScrewFunction); + break; + case DoubleScrew: + result=GenerateFunctionDataFixedSize(x_size,y_size,data,-3.0,+3.0,-3.0,+3.0,DoubleScrewFunction); + break; + case MultiExtremalScrew: + result=GenerateFunctionDataFixedSize(x_size,y_size,data,-3.0,+3.0,-3.0,+3.0,MultiExtremalScrewFunction); + break; + case Sink: + result=GenerateFunctionDataFixedSize(x_size,y_size,data,-3.0,+3.0,-3.0,+3.0,SinkFunction); + break; + case Skin: + result=GenerateFunctionDataFixedSize(x_size,y_size,data,-5.0,+5.0,-5.0,+5.0,SkinFunction); + break; + case Trapfall: + result=GenerateFunctionDataFixedSize(x_size,y_size,data,-5.0,+5.0,-5.0,+5.0,TrapfallFunction); + break; + } +//--- + return(result); + } +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Experts/Examples/Math 3D Morpher/Math 3D Morpher.mq5 b/BKPS/14031218/Experts/Examples/Math 3D Morpher/Math 3D Morpher.mq5 new file mode 100644 index 0000000..2ecc8cb Binary files /dev/null and b/BKPS/14031218/Experts/Examples/Math 3D Morpher/Math 3D Morpher.mq5 differ diff --git a/BKPS/14031218/Experts/Examples/Math 3D Morpher/Math 3D Morpher.mqproj b/BKPS/14031218/Experts/Examples/Math 3D Morpher/Math 3D Morpher.mqproj new file mode 100644 index 0000000..99ae59f Binary files /dev/null and b/BKPS/14031218/Experts/Examples/Math 3D Morpher/Math 3D Morpher.mqproj differ diff --git a/BKPS/14031218/Experts/Examples/Math 3D Morpher/Textures/checker.bmp b/BKPS/14031218/Experts/Examples/Math 3D Morpher/Textures/checker.bmp new file mode 100644 index 0000000..0d65c53 Binary files /dev/null and b/BKPS/14031218/Experts/Examples/Math 3D Morpher/Textures/checker.bmp differ diff --git a/BKPS/14031218/Experts/Examples/Math 3D/Functions.mqh b/BKPS/14031218/Experts/Examples/Math 3D/Functions.mqh new file mode 100644 index 0000000..40aed1c Binary files /dev/null and b/BKPS/14031218/Experts/Examples/Math 3D/Functions.mqh differ diff --git a/BKPS/14031218/Experts/Examples/Math 3D/Math 3D.ico b/BKPS/14031218/Experts/Examples/Math 3D/Math 3D.ico new file mode 100644 index 0000000..0d881c4 Binary files /dev/null and b/BKPS/14031218/Experts/Examples/Math 3D/Math 3D.ico differ diff --git a/BKPS/14031218/Experts/Examples/Math 3D/Math 3D.mq5 b/BKPS/14031218/Experts/Examples/Math 3D/Math 3D.mq5 new file mode 100644 index 0000000..f95451d Binary files /dev/null and b/BKPS/14031218/Experts/Examples/Math 3D/Math 3D.mq5 differ diff --git a/BKPS/14031218/Experts/Examples/Math 3D/Math 3D.mqproj b/BKPS/14031218/Experts/Examples/Math 3D/Math 3D.mqproj new file mode 100644 index 0000000..771b9da Binary files /dev/null and b/BKPS/14031218/Experts/Examples/Math 3D/Math 3D.mqproj differ diff --git a/BKPS/14031218/Experts/Examples/Math 3D/Sets/Chomolungma.set b/BKPS/14031218/Experts/Examples/Math 3D/Sets/Chomolungma.set new file mode 100644 index 0000000..09a4599 Binary files /dev/null and b/BKPS/14031218/Experts/Examples/Math 3D/Sets/Chomolungma.set differ diff --git a/BKPS/14031218/Experts/Examples/Math 3D/Sets/ClimberDream.set b/BKPS/14031218/Experts/Examples/Math 3D/Sets/ClimberDream.set new file mode 100644 index 0000000..3536542 Binary files /dev/null and b/BKPS/14031218/Experts/Examples/Math 3D/Sets/ClimberDream.set differ diff --git a/BKPS/14031218/Experts/Examples/Math 3D/Sets/DoubleScrew.set b/BKPS/14031218/Experts/Examples/Math 3D/Sets/DoubleScrew.set new file mode 100644 index 0000000..61c3cbc Binary files /dev/null and b/BKPS/14031218/Experts/Examples/Math 3D/Sets/DoubleScrew.set differ diff --git a/BKPS/14031218/Experts/Examples/Math 3D/Sets/Granite.set b/BKPS/14031218/Experts/Examples/Math 3D/Sets/Granite.set new file mode 100644 index 0000000..3356136 Binary files /dev/null and b/BKPS/14031218/Experts/Examples/Math 3D/Sets/Granite.set differ diff --git a/BKPS/14031218/Experts/Examples/Math 3D/Sets/Hedgehog.set b/BKPS/14031218/Experts/Examples/Math 3D/Sets/Hedgehog.set new file mode 100644 index 0000000..c543a3f Binary files /dev/null and b/BKPS/14031218/Experts/Examples/Math 3D/Sets/Hedgehog.set differ diff --git a/BKPS/14031218/Experts/Examples/Math 3D/Sets/Hill.set b/BKPS/14031218/Experts/Examples/Math 3D/Sets/Hill.set new file mode 100644 index 0000000..e3935ad Binary files /dev/null and b/BKPS/14031218/Experts/Examples/Math 3D/Sets/Hill.set differ diff --git a/BKPS/14031218/Experts/Examples/Math 3D/Sets/Josephine.set b/BKPS/14031218/Experts/Examples/Math 3D/Sets/Josephine.set new file mode 100644 index 0000000..8d82f2c Binary files /dev/null and b/BKPS/14031218/Experts/Examples/Math 3D/Sets/Josephine.set differ diff --git a/BKPS/14031218/Experts/Examples/Math 3D/Sets/MultyExtremalScrew.set b/BKPS/14031218/Experts/Examples/Math 3D/Sets/MultyExtremalScrew.set new file mode 100644 index 0000000..b8af71e Binary files /dev/null and b/BKPS/14031218/Experts/Examples/Math 3D/Sets/MultyExtremalScrew.set differ diff --git a/BKPS/14031218/Experts/Examples/Math 3D/Sets/Screw.set b/BKPS/14031218/Experts/Examples/Math 3D/Sets/Screw.set new file mode 100644 index 0000000..af37238 Binary files /dev/null and b/BKPS/14031218/Experts/Examples/Math 3D/Sets/Screw.set differ diff --git a/BKPS/14031218/Experts/Examples/Math 3D/Sets/Sink.set b/BKPS/14031218/Experts/Examples/Math 3D/Sets/Sink.set new file mode 100644 index 0000000..4da1d77 Binary files /dev/null and b/BKPS/14031218/Experts/Examples/Math 3D/Sets/Sink.set differ diff --git a/BKPS/14031218/Experts/Examples/Math 3D/Sets/Skin.set b/BKPS/14031218/Experts/Examples/Math 3D/Sets/Skin.set new file mode 100644 index 0000000..4d2bf73 Binary files /dev/null and b/BKPS/14031218/Experts/Examples/Math 3D/Sets/Skin.set differ diff --git a/BKPS/14031218/Experts/Examples/Math 3D/Sets/Trapfall.set b/BKPS/14031218/Experts/Examples/Math 3D/Sets/Trapfall.set new file mode 100644 index 0000000..1ad0320 Binary files /dev/null and b/BKPS/14031218/Experts/Examples/Math 3D/Sets/Trapfall.set differ diff --git a/BKPS/14031218/Experts/Examples/Moving Average/Moving Average.mq5 b/BKPS/14031218/Experts/Examples/Moving Average/Moving Average.mq5 new file mode 100644 index 0000000..04fb643 --- /dev/null +++ b/BKPS/14031218/Experts/Examples/Moving Average/Moving Average.mq5 @@ -0,0 +1,233 @@ +//+------------------------------------------------------------------+ +//| Moving Averages.mq5 | +//| Copyright 2000-2025, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2000-2025, MetaQuotes Ltd." +#property link "https://www.mql5.com" +#property version "1.00" + +#include + +input double MaximumRisk = 0.02; // Maximum Risk in percentage +input double DecreaseFactor = 3; // Descrease factor +input int MovingPeriod = 12; // Moving Average period +input int MovingShift = 6; // Moving Average shift +//--- +int ExtHandle=0; +bool ExtHedging=false; +CTrade ExtTrade; + +#define MA_MAGIC 1234501 +//+------------------------------------------------------------------+ +//| Calculate optimal lot size | +//+------------------------------------------------------------------+ +double TradeSizeOptimized(void) + { + double price=0.0; + double margin=0.0; +//--- select lot size + if(!SymbolInfoDouble(_Symbol,SYMBOL_ASK,price)) + return(0.0); + if(!OrderCalcMargin(ORDER_TYPE_BUY,_Symbol,1.0,price,margin)) + return(0.0); + if(margin<=0.0) + return(0.0); + + double lot=NormalizeDouble(AccountInfoDouble(ACCOUNT_MARGIN_FREE)*MaximumRisk/margin,2); +//--- calculate number of losses orders without a break + if(DecreaseFactor>0) + { + //--- select history for access + HistorySelect(0,TimeCurrent()); + //--- + int orders=HistoryDealsTotal(); // total history deals + int losses=0; // number of losses orders without a break + + for(int i=orders-1;i>=0;i--) + { + ulong ticket=HistoryDealGetTicket(i); + if(ticket==0) + { + Print("HistoryDealGetTicket failed, no trade history"); + break; + } + //--- check symbol + if(HistoryDealGetString(ticket,DEAL_SYMBOL)!=_Symbol) + continue; + //--- check Expert Magic number + if(HistoryDealGetInteger(ticket,DEAL_MAGIC)!=MA_MAGIC) + continue; + //--- check profit + double profit=HistoryDealGetDouble(ticket,DEAL_PROFIT); + if(profit>0.0) + break; + if(profit<0.0) + losses++; + } + //--- + if(losses>1) + lot=NormalizeDouble(lot-lot*losses/DecreaseFactor,1); + } +//--- normalize and check limits + double stepvol=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP); + lot=stepvol*NormalizeDouble(lot/stepvol,0); + + double minvol=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN); + if(lotmaxvol) + lot=maxvol; +//--- return trading volume + return(lot); + } +//+------------------------------------------------------------------+ +//| Check for open position conditions | +//+------------------------------------------------------------------+ +void CheckForOpen(void) + { + MqlRates rt[2]; +//--- go trading only for first ticks of new bar + if(CopyRates(_Symbol,_Period,0,2,rt)!=2) + { + Print("CopyRates of ",_Symbol," failed, no history"); + return; + } + if(rt[1].tick_volume>1) + return; +//--- get current Moving Average + double ma[1]; + if(CopyBuffer(ExtHandle,0,0,1,ma)!=1) + { + Print("CopyBuffer from iMA failed, no data"); + return; + } +//--- check signals + ENUM_ORDER_TYPE signal=WRONG_VALUE; + + if(rt[0].open>ma[0] && rt[0].closema[0]) + signal=ORDER_TYPE_BUY; // buy conditions + } +//--- additional checking + if(signal!=WRONG_VALUE) + { + if(TerminalInfoInteger(TERMINAL_TRADE_ALLOWED) && Bars(_Symbol,_Period)>100) + ExtTrade.PositionOpen(_Symbol,signal,TradeSizeOptimized(), + SymbolInfoDouble(_Symbol,signal==ORDER_TYPE_SELL ? SYMBOL_BID:SYMBOL_ASK), + 0,0); + } +//--- + } +//+------------------------------------------------------------------+ +//| Check for close position conditions | +//+------------------------------------------------------------------+ +void CheckForClose(void) + { + MqlRates rt[2]; +//--- go trading only for first ticks of new bar + if(CopyRates(_Symbol,_Period,0,2,rt)!=2) + { + Print("CopyRates of ",_Symbol," failed, no history"); + return; + } + if(rt[1].tick_volume>1) + return; +//--- get current Moving Average + double ma[1]; + if(CopyBuffer(ExtHandle,0,0,1,ma)!=1) + { + Print("CopyBuffer from iMA failed, no data"); + return; + } +//--- positions already selected before + bool signal=false; + long type=PositionGetInteger(POSITION_TYPE); + + if(type==(long)POSITION_TYPE_BUY && rt[0].open>ma[0] && rt[0].closema[0]) + signal=true; +//--- additional checking + if(signal) + { + if(TerminalInfoInteger(TERMINAL_TRADE_ALLOWED) && Bars(_Symbol,_Period)>100) + ExtTrade.PositionClose(_Symbol,3); + } +//--- + } +//+------------------------------------------------------------------+ +//| Position select depending on netting or hedging | +//+------------------------------------------------------------------+ +bool SelectPosition() + { + bool res=false; +//--- check position in Hedging mode + if(ExtHedging) + { + uint total=PositionsTotal(); + for(uint i=0; i +#include + +#define SIGNAL_BUY 1 // Buy signal +#define SIGNAL_NOT 0 // no trading signal +#define SIGNAL_SELL -1 // Sell signal + +#define CLOSE_LONG 2 // signal to close Long +#define CLOSE_SHORT -2 // signal to close Short + +//--- Input parameters +input int InpAverBodyPeriod=12; // period for calculating average candlestick size +input int InpPeriodCCI =37; // CCI period +input ENUM_APPLIED_PRICE InpPrice=PRICE_CLOSE; // price type + +//--- trade parameters +input uint InpDuration=10; // position holding time in bars +input uint InpSL =200; // Stop Loss in points +input uint InpTP =200; // Take Profit in points +input uint InpSlippage=10; // slippage in points +//--- money management parameters +input double InpLot =0.1; // lot +//--- Expert ID +input long InpMagicNumber=120100; // Magic Number + +//--- global variables +int ExtAvgBodyPeriod; // average candlestick calculation period +int ExtSignalOpen =0; // Buy/Sell signal +int ExtSignalClose =0; // signal to close a position +string ExtPatternInfo =""; // current pattern information +string ExtDirection =""; // position opening direction +bool ExtPatternDetected=false; // pattern detected +bool ExtConfirmed =false; // pattern confirmed +bool ExtCloseByTime =true; // requires closing by time +bool ExtCheckPassed =true; // status checking error + +//--- indicator handle +int ExtIndicatorHandle=INVALID_HANDLE; + +//--- service objects +CTrade ExtTrade; +CSymbolInfo ExtSymbolInfo; +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { + Print("InpSL=", InpSL); + Print("InpTP=", InpTP); +//--- set parameters for trading operations + ExtTrade.SetDeviationInPoints(InpSlippage); // slippage + ExtTrade.SetExpertMagicNumber(InpMagicNumber); // Expert Advisor ID + ExtTrade.LogLevel(LOG_LEVEL_ERRORS); // logging level + + ExtAvgBodyPeriod=InpAverBodyPeriod; +//--- indicator initialization + ExtIndicatorHandle=iCCI(_Symbol, _Period, InpPeriodCCI, InpPrice); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating CCI indicator"); + return(INIT_FAILED); + } +//--- OK + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { +//--- release indicator handle + IndicatorRelease(ExtIndicatorHandle); + } +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() + { +//--- save the next bar start time; all checks at bar opening only + static datetime next_bar_open=0; + +//--- Phase 1 - check the emergence of a new bar and update the status + if(TimeCurrent()>=next_bar_open) + { + //--- get the current state of environment on the new bar + // namely, set the values of global variables: + // ExtPatternDetected - pattern detection + // ExtConfirmed - pattern confirmation + // ExtSignalOpen - signal to open + // ExtSignalClose - signal to close + // ExtPatternInfo - current pattern information + if(CheckState()) + { + //--- set the new bar opening time + next_bar_open=TimeCurrent(); + next_bar_open-=next_bar_open%PeriodSeconds(_Period); + next_bar_open+=PeriodSeconds(_Period); + + //--- report the emergence of a new bar only once within a bar + if(ExtPatternDetected && ExtConfirmed) + Print(ExtPatternInfo); + } + else + { + //--- error getting the status, retry on the next tick + return; + } + } + +//--- Phase 2 - if there is a signal and no position in this direction + if(ExtSignalOpen && !PositionExist(ExtSignalOpen)) + { + Print("\r\nSignal to open position ", ExtDirection); + PositionOpen(); + if(PositionExist(ExtSignalOpen)) + ExtSignalOpen=SIGNAL_NOT; + } + +//--- Phase 3 - close if there is a signal to close + if(ExtSignalClose && PositionExist(ExtSignalClose)) + { + Print("\r\nSignal to close position ", ExtDirection); + CloseBySignal(ExtSignalClose); + if(!PositionExist(ExtSignalClose)) + ExtSignalClose=SIGNAL_NOT; + } + +//--- Phase 4 - close upon expiration + if(ExtCloseByTime && PositionExpiredByTimeExist()) + { + CloseByTime(); + ExtCloseByTime=PositionExpiredByTimeExist(); + } + } +//+------------------------------------------------------------------+ +//| Get the current environment and check for a pattern | +//+------------------------------------------------------------------+ +bool CheckState() + { +//--- check if there is a pattern + if(!CheckPattern()) + { + Print("Error, failed to check pattern"); + return(false); + } + +//--- check for confirmation + if(!CheckConfirmation()) + { + Print("Error, failed to check pattern confirmation"); + return(false); + } +//--- if there is no confirmation, cancel the signal + if(!ExtConfirmed) + ExtSignalOpen=SIGNAL_NOT; + +//--- check if there is a signal to close a position + if(!CheckCloseSignal()) + { + Print("Error, failed to check the closing signal"); + return(false); + } + +//--- if positions are to be closed after certain holding time in bars + if(InpDuration) + ExtCloseByTime=true; // set flag to close upon expiration + +//--- all checks done + return(true); + } +//+------------------------------------------------------------------+ +//| Open a position in the direction of the signal | +//+------------------------------------------------------------------+ +bool PositionOpen() + { + ExtSymbolInfo.Refresh(); + ExtSymbolInfo.RefreshRates(); + + double price=0; +//--- Stop Loss and Take Profit are not set by default + double stoploss=0.0; + double takeprofit=0.0; + + int digits=ExtSymbolInfo.Digits(); + double point=ExtSymbolInfo.Point(); + double spread=ExtSymbolInfo.Ask()-ExtSymbolInfo.Bid(); + +//--- uptrend + if(ExtSignalOpen==SIGNAL_BUY) + { + price=NormalizeDouble(ExtSymbolInfo.Ask(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price-spread, digits); + } + else + stoploss = NormalizeDouble(price-InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price+spread, digits); + } + else + takeprofit = NormalizeDouble(price+InpTP*point, digits); + } + + if(!ExtTrade.Buy(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s buy %G at %G (sl=%G tp=%G) failed. Ask=%G error=%d", + Symbol(), InpLot, price, stoploss, takeprofit, ExtSymbolInfo.Ask(), GetLastError()); + return(false); + } + } + +//--- downtrend + if(ExtSignalOpen==SIGNAL_SELL) + { + price=NormalizeDouble(ExtSymbolInfo.Bid(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price+spread, digits); + } + else + stoploss = NormalizeDouble(price+InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price-spread, digits); + } + else + takeprofit = NormalizeDouble(price-InpTP*point, digits); + } + + if(!ExtTrade.Sell(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s sell at %G (sl=%G tp=%G) failed. Bid=%G error=%d", + Symbol(), price, stoploss, takeprofit, ExtSymbolInfo.Bid(), GetLastError()); + ExtTrade.PrintResult(); + Print(" "); + return(false); + } + } + + return(true); + } +//+------------------------------------------------------------------+ +//| Close a position based on the specified signal | +//+------------------------------------------------------------------+ +void CloseBySignal(int type_close) + { +//--- if there is no signal to close, return successful completion + if(type_close==SIGNAL_NOT) + return; +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalClose)==0) + return; + +//--- closing direction + long type; + switch(type_close) + { + case CLOSE_SHORT: + type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + type=POSITION_TYPE_BUY; + break; + default: + Print("Error! Signal to close not detected"); + return; + } + +//--- check all positions and close ours based on the signal + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + if(PositionGetInteger(POSITION_TYPE)==type) + { + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Close positions upon holding time expiration in bars | +//+------------------------------------------------------------------+ +void CloseByTime() + { +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalOpen)==0) + return; + +//--- check all positions and close ours based on the holding time in bars + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + //--- position opening time + datetime open_time=(datetime)PositionGetInteger(POSITION_TIME); + //--- check position holding time in bars + if(BarsHold(open_time)>=(int)InpDuration) + { + Print("\r\nTime to close position #", ticket); + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Returns true if there are open positions | +//+------------------------------------------------------------------+ +bool PositionExist(int signal_direction) + { + bool check_type=(signal_direction!=SIGNAL_NOT); + +//--- what positions to search + ENUM_POSITION_TYPE search_type=WRONG_VALUE; + if(check_type) + switch(signal_direction) + { + case SIGNAL_BUY: + search_type=POSITION_TYPE_BUY; + break; + case SIGNAL_SELL: + search_type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + search_type=POSITION_TYPE_BUY; + break; + case CLOSE_SHORT: + search_type=POSITION_TYPE_SELL; + break; + default: + //--- entry direction is not specified; nothing to search + return(false); + } + +//--- go through the list of all positions + int positions=PositionsTotal(); + for(int i=0; i=(int)InpDuration)) + return(true); + } + } + } + +//--- open position not found + return(false); + } +//+------------------------------------------------------------------+ +//| Checks position closing time in bars | +//+------------------------------------------------------------------+ +int BarsHold(datetime open_time) + { +//--- first run a basic simple check + if(TimeCurrent()-open_timeAvgBody(1)) && // long black + (Open(2)-Close(2)>AvgBody(1)) && + (Open(1)-Close(1)>AvgBody(1)) && + (MidPoint(2)AvgBody(1)) && // long white + (Close(2)-Open(2)>AvgBody(1)) && + (Close(1)-Open(1)>AvgBody(1)) && + (MidPoint(2)>MidPoint(3)) && // higher midpoints + (MidPoint(1)>MidPoint(2))) + { + ExtPatternDetected=true; + ExtSignalOpen=SIGNAL_BUY; + ExtPatternInfo="\r\n3 White Soldiers detected"; + ExtDirection="Buy"; + return(true); + } + +//--- result of checking + return(ExtCheckPassed); + } +//+------------------------------------------------------------------+ +//| Returns true in case of successful confirmation check | +//+------------------------------------------------------------------+ +bool CheckConfirmation() + { + ExtConfirmed=false; +//--- if there is no pattern, do not search for confirmation + if(!ExtPatternDetected) + return(true); + +//--- get the value of the stochastic indicator to confirm the signal + double signal=CCI(1); + if(signal==EMPTY_VALUE) + { + //--- failed to get indicator value, check failed + return(false); + } + +//--- check the Buy signal + if(ExtSignalOpen==SIGNAL_BUY && (signal<-50)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: CCI<-50"; + } + +//--- check the Sell signal + if(ExtSignalOpen==SIGNAL_SELL && (signal>50)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: CCI>50"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| Check if there is a signal to close | +//+------------------------------------------------------------------+ +bool CheckCloseSignal() + { + ExtSignalClose=false; +//--- if there is a signal to enter the market, do not check the signal to close + if(ExtSignalOpen!=SIGNAL_NOT) + return(true); + +//--- check if there is a signal to close a long position + if(((CCI(1)<80) && (CCI(2)>80)) || ((CCI(1)<-80) && (CCI(2)>-80))) + { + //--- there is a signal to close a long position + ExtSignalClose=CLOSE_LONG; + ExtDirection="Long"; + } + +//--- check if there is a signal to close a short position + if(((CCI(1)>-80) && (CCI(2)<-80)) || ((CCI(1)>80) && (CCI(2)<80))) + { + //--- there is a signal to close a short position + ExtSignalClose=CLOSE_SHORT; + ExtDirection="Short"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| CCI indicator value at the specified bar | +//+------------------------------------------------------------------+ +double CCI(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtIndicatorHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the CCI indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Experts/Free Robots/BlackCrows WhiteSoldiers MFI.mq5 b/BKPS/14031218/Experts/Free Robots/BlackCrows WhiteSoldiers MFI.mq5 new file mode 100644 index 0000000..e9bb791 --- /dev/null +++ b/BKPS/14031218/Experts/Free Robots/BlackCrows WhiteSoldiers MFI.mq5 @@ -0,0 +1,657 @@ +//+------------------------------------------------------------------+ +//| BlackCrows WhiteSoldiers MFI.mq5 | +//| Copyright 2024, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2024, MetaQuotes Ltd." +#property link "https://www.mql5.com" +#property version "1.00" + +#include +#include + +#define SIGNAL_BUY 1 // Buy signal +#define SIGNAL_NOT 0 // no trading signal +#define SIGNAL_SELL -1 // Sell signal + +#define CLOSE_LONG 2 // signal to close Long +#define CLOSE_SHORT -2 // signal to close Short + +//--- Input parameters +input int InpAverBodyPeriod=12; // period for calculating average candlestick size +input int InpPeriodMFI =37; // MFI period +input ENUM_APPLIED_VOLUME InpVolume=VOLUME_TICK; // volume type + +//--- trade parameters +input uint InpDuration=10; // position holding time in bars +input uint InpSL =200; // Stop Loss in points +input uint InpTP =200; // Take Profit in points +input uint InpSlippage=10; // slippage in points +//--- money management parameters +input double InpLot =0.1; // lot +//--- Expert ID +input long InpMagicNumber=120200; // Magic Number + +//--- global variables +int ExtAvgBodyPeriod; // average candlestick calculation period +int ExtSignalOpen =0; // Buy/Sell signal +int ExtSignalClose =0; // signal to close a position +string ExtPatternInfo =""; // current pattern information +string ExtDirection =""; // position opening direction +bool ExtPatternDetected=false; // pattern detected +bool ExtConfirmed =false; // pattern confirmed +bool ExtCloseByTime =true; // requires closing by time +bool ExtCheckPassed =true; // status checking error + +//--- indicator handle +int ExtIndicatorHandle=INVALID_HANDLE; + +//--- service objects +CTrade ExtTrade; +CSymbolInfo ExtSymbolInfo; +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { + Print("InpSL=", InpSL); + Print("InpTP=", InpTP); +//--- set parameters for trading operations + ExtTrade.SetDeviationInPoints(InpSlippage); // slippage + ExtTrade.SetExpertMagicNumber(InpMagicNumber); // Expert Advisor ID + ExtTrade.LogLevel(LOG_LEVEL_ERRORS); // logging level + + ExtAvgBodyPeriod=InpAverBodyPeriod; +//--- indicator initialization + ExtIndicatorHandle=iMFI(_Symbol, _Period, InpPeriodMFI, InpVolume); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating MFI indicator"); + return(INIT_FAILED); + } +//--- OK + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { +//--- release indicator handle + IndicatorRelease(ExtIndicatorHandle); + } +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() + { +//--- save the next bar start time; all checks at bar opening only + static datetime next_bar_open=0; + +//--- Phase 1 - check the emergence of a new bar and update the status + if(TimeCurrent()>=next_bar_open) + { + //--- get the current state of environment on the new bar + // namely, set the values of global variables: + // ExtPatternDetected - pattern detection + // ExtConfirmed - pattern confirmation + // ExtSignalOpen - signal to open + // ExtSignalClose - signal to close + // ExtPatternInfo - current pattern information + if(CheckState()) + { + //--- set the new bar opening time + next_bar_open=TimeCurrent(); + next_bar_open-=next_bar_open%PeriodSeconds(_Period); + next_bar_open+=PeriodSeconds(_Period); + + //--- report the emergence of a new bar only once within a bar + if(ExtPatternDetected && ExtConfirmed) + Print(ExtPatternInfo); + } + else + { + //--- error getting the status, retry on the next tick + return; + } + } + +//--- Phase 2 - if there is a signal and no position in this direction + if(ExtSignalOpen && !PositionExist(ExtSignalOpen)) + { + Print("\r\nSignal to open position ", ExtDirection); + PositionOpen(); + if(PositionExist(ExtSignalOpen)) + ExtSignalOpen=SIGNAL_NOT; + } + +//--- Phase 3 - close if there is a signal to close + if(ExtSignalClose && PositionExist(ExtSignalClose)) + { + Print("\r\nSignal to close position ", ExtDirection); + CloseBySignal(ExtSignalClose); + if(!PositionExist(ExtSignalClose)) + ExtSignalClose=SIGNAL_NOT; + } + +//--- Phase 4 - close upon expiration + if(ExtCloseByTime && PositionExpiredByTimeExist()) + { + CloseByTime(); + ExtCloseByTime=PositionExpiredByTimeExist(); + } + } +//+------------------------------------------------------------------+ +//| Get the current environment and check for a pattern | +//+------------------------------------------------------------------+ +bool CheckState() + { +//--- check if there is a pattern + if(!CheckPattern()) + { + Print("Error, failed to check pattern"); + return(false); + } + +//--- check for confirmation + if(!CheckConfirmation()) + { + Print("Error, failed to check pattern confirmation"); + return(false); + } +//--- if there is no confirmation, cancel the signal + if(!ExtConfirmed) + ExtSignalOpen=SIGNAL_NOT; + +//--- check if there is a signal to close a position + if(!CheckCloseSignal()) + { + Print("Error, failed to check the closing signal"); + return(false); + } + +//--- if positions are to be closed after certain holding time in bars + if(InpDuration) + ExtCloseByTime=true; // set flag to close upon expiration + +//--- all checks done + return(true); + } +//+------------------------------------------------------------------+ +//| Open a position in the direction of the signal | +//+------------------------------------------------------------------+ +bool PositionOpen() + { + ExtSymbolInfo.Refresh(); + ExtSymbolInfo.RefreshRates(); + + double price=0; +//--- Stop Loss and Take Profit are not set by default + double stoploss=0.0; + double takeprofit=0.0; + + int digits=ExtSymbolInfo.Digits(); + double point=ExtSymbolInfo.Point(); + double spread=ExtSymbolInfo.Ask()-ExtSymbolInfo.Bid(); + +//--- uptrend + if(ExtSignalOpen==SIGNAL_BUY) + { + price=NormalizeDouble(ExtSymbolInfo.Ask(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price-spread, digits); + } + else + stoploss = NormalizeDouble(price-InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price+spread, digits); + } + else + takeprofit = NormalizeDouble(price+InpTP*point, digits); + } + + if(!ExtTrade.Buy(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s buy %G at %G (sl=%G tp=%G) failed. Ask=%G error=%d", + Symbol(), InpLot, price, stoploss, takeprofit, ExtSymbolInfo.Ask(), GetLastError()); + return(false); + } + } + +//--- downtrend + if(ExtSignalOpen==SIGNAL_SELL) + { + price=NormalizeDouble(ExtSymbolInfo.Bid(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price+spread, digits); + } + else + stoploss = NormalizeDouble(price+InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price-spread, digits); + } + else + takeprofit = NormalizeDouble(price-InpTP*point, digits); + } + + if(!ExtTrade.Sell(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s sell at %G (sl=%G tp=%G) failed. Bid=%G error=%d", + Symbol(), price, stoploss, takeprofit, ExtSymbolInfo.Bid(), GetLastError()); + ExtTrade.PrintResult(); + Print(" "); + return(false); + } + } + + return(true); + } +//+------------------------------------------------------------------+ +//| Close a position based on the specified signal | +//+------------------------------------------------------------------+ +void CloseBySignal(int type_close) + { +//--- if there is no signal to close, return successful completion + if(type_close==SIGNAL_NOT) + return; +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalClose)==0) + return; + +//--- closing direction + long type; + switch(type_close) + { + case CLOSE_SHORT: + type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + type=POSITION_TYPE_BUY; + break; + default: + Print("Error! Signal to close not detected"); + return; + } + +//--- check all positions and close ours based on the signal + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + if(PositionGetInteger(POSITION_TYPE)==type) + { + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Close positions upon holding time expiration in bars | +//+------------------------------------------------------------------+ +void CloseByTime() + { +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalOpen)==0) + return; + +//--- check all positions and close ours based on the holding time in bars + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + //--- position opening time + datetime open_time=(datetime)PositionGetInteger(POSITION_TIME); + //--- check position holding time in bars + if(BarsHold(open_time)>=(int)InpDuration) + { + Print("\r\nTime to close position #", ticket); + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Returns true if there are open positions | +//+------------------------------------------------------------------+ +bool PositionExist(int signal_direction) + { + bool check_type=(signal_direction!=SIGNAL_NOT); + +//--- what positions to search + ENUM_POSITION_TYPE search_type=WRONG_VALUE; + if(check_type) + switch(signal_direction) + { + case SIGNAL_BUY: + search_type=POSITION_TYPE_BUY; + break; + case SIGNAL_SELL: + search_type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + search_type=POSITION_TYPE_BUY; + break; + case CLOSE_SHORT: + search_type=POSITION_TYPE_SELL; + break; + default: + //--- entry direction is not specified; nothing to search + return(false); + } + +//--- go through the list of all positions + int positions=PositionsTotal(); + for(int i=0; i=(int)InpDuration)) + return(true); + } + } + } + +//--- open position not found + return(false); + } +//+------------------------------------------------------------------+ +//| Checks position closing time in bars | +//+------------------------------------------------------------------+ +int BarsHold(datetime open_time) + { +//--- first run a basic simple check + if(TimeCurrent()-open_timeAvgBody(1)) && // long black + (Open(2)-Close(2)>AvgBody(1)) && + (Open(1)-Close(1)>AvgBody(1)) && + (MidPoint(2)AvgBody(1)) && // long white + (Close(2)-Open(2)>AvgBody(1)) && + (Close(1)-Open(1)>AvgBody(1)) && + (MidPoint(2)>MidPoint(3)) && // higher midpoints + (MidPoint(1)>MidPoint(2))) + { + ExtPatternDetected=true; + ExtSignalOpen=SIGNAL_BUY; + ExtPatternInfo="\r\n3 White Soldiers detected"; + ExtDirection="Buy"; + return(true); + } + +//--- result of checking + return(ExtCheckPassed); + } +//+------------------------------------------------------------------+ +//| Returns true in case of successful confirmation check | +//+------------------------------------------------------------------+ +bool CheckConfirmation() + { + ExtConfirmed=false; +//--- if there is no pattern, do not search for confirmation + if(!ExtPatternDetected) + return(true); + +//--- get the value of the stochastic indicator to confirm the signal + double signal=MFI(1); + if(signal==EMPTY_VALUE) + { + //--- failed to get indicator value, check failed + return(false); + } + +//--- check the Buy signal + if(ExtSignalOpen==SIGNAL_BUY && (signal<40)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: MFI<40"; + } + +//--- check the Sell signal + if(ExtSignalOpen==SIGNAL_SELL && (signal>60)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: MFI>60"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| Check if there is a signal to close | +//+------------------------------------------------------------------+ +bool CheckCloseSignal() + { + ExtSignalClose=false; +//--- if there is a signal to enter the market, do not check the signal to close + if(ExtSignalOpen!=SIGNAL_NOT) + return(true); + +//--- check if there is a signal to close a long position + if(((MFI(1)<70) && (MFI(2)>70)) || ((MFI(1)<30) && (MFI(2)>30))) + { + //--- there is a signal to close a long position + ExtSignalClose=CLOSE_LONG; + ExtDirection="Long"; + } + +//--- check if there is a signal to close a short position + if(((MFI(1)>30) && (MFI(2)<30)) || ((MFI(1)>70) && (MFI(2)<70))) + { + //--- there is a signal to close a short position + ExtSignalClose=CLOSE_SHORT; + ExtDirection="Short"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| MFI indicator value at the specified bar | +//+------------------------------------------------------------------+ +double MFI(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtIndicatorHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the MFI indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Experts/Free Robots/BlackCrows WhiteSoldiers RSI.mq5 b/BKPS/14031218/Experts/Free Robots/BlackCrows WhiteSoldiers RSI.mq5 new file mode 100644 index 0000000..c79c357 --- /dev/null +++ b/BKPS/14031218/Experts/Free Robots/BlackCrows WhiteSoldiers RSI.mq5 @@ -0,0 +1,657 @@ +//+------------------------------------------------------------------+ +//| BlackCrows WhiteSoldiers RSI.mq5 | +//| Copyright 2024, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2024, MetaQuotes Ltd." +#property link "https://www.mql5.com" +#property version "1.00" + +#include +#include + +#define SIGNAL_BUY 1 // Buy signal +#define SIGNAL_NOT 0 // no trading signal +#define SIGNAL_SELL -1 // Sell signal + +#define CLOSE_LONG 2 // signal to close Long +#define CLOSE_SHORT -2 // signal to close Short + +//--- Input parameters +input int InpAverBodyPeriod=12; // period for calculating average candlestick size +input int InpPeriodRSI =37; // RSI period +input ENUM_APPLIED_PRICE InpPrice=PRICE_CLOSE; // price type + +//--- trade parameters +input uint InpDuration=10; // position holding time in bars +input uint InpSL =200; // Stop Loss in points +input uint InpTP =200; // Take Profit in points +input uint InpSlippage=10; // slippage in points +//--- money management parameters +input double InpLot =0.1; // lot +//--- Expert ID +input long InpMagicNumber=120300; // Magic Number + +//--- global variables +int ExtAvgBodyPeriod; // average candlestick calculation period +int ExtSignalOpen =0; // Buy/Sell signal +int ExtSignalClose =0; // signal to close a position +string ExtPatternInfo =""; // current pattern information +string ExtDirection =""; // position opening direction +bool ExtPatternDetected=false; // pattern detected +bool ExtConfirmed =false; // pattern confirmed +bool ExtCloseByTime =true; // requires closing by time +bool ExtCheckPassed =true; // status checking error + +//--- indicator handle +int ExtIndicatorHandle=INVALID_HANDLE; + +//--- service objects +CTrade ExtTrade; +CSymbolInfo ExtSymbolInfo; +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { + Print("InpSL=", InpSL); + Print("InpTP=", InpTP); +//--- set parameters for trading operations + ExtTrade.SetDeviationInPoints(InpSlippage); // slippage + ExtTrade.SetExpertMagicNumber(InpMagicNumber); // Expert Advisor ID + ExtTrade.LogLevel(LOG_LEVEL_ERRORS); // logging level + + ExtAvgBodyPeriod=InpAverBodyPeriod; +//--- indicator initialization + ExtIndicatorHandle=iRSI(_Symbol, _Period, InpPeriodRSI, InpPrice); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating CCI indicator"); + return(INIT_FAILED); + } +//--- OK + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { +//--- release indicator handle + IndicatorRelease(ExtIndicatorHandle); + } +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() + { +//--- save the next bar start time; all checks at bar opening only + static datetime next_bar_open=0; + +//--- Phase 1 - check the emergence of a new bar and update the status + if(TimeCurrent()>=next_bar_open) + { + //--- get the current state of environment on the new bar + // namely, set the values of global variables: + // ExtPatternDetected - pattern detection + // ExtConfirmed - pattern confirmation + // ExtSignalOpen - signal to open + // ExtSignalClose - signal to close + // ExtPatternInfo - current pattern information + if(CheckState()) + { + //--- set the new bar opening time + next_bar_open=TimeCurrent(); + next_bar_open-=next_bar_open%PeriodSeconds(_Period); + next_bar_open+=PeriodSeconds(_Period); + + //--- report the emergence of a new bar only once within a bar + if(ExtPatternDetected && ExtConfirmed) + Print(ExtPatternInfo); + } + else + { + //--- error getting the status, retry on the next tick + return; + } + } + +//--- Phase 2 - if there is a signal and no position in this direction + if(ExtSignalOpen && !PositionExist(ExtSignalOpen)) + { + Print("\r\nSignal to open position ", ExtDirection); + PositionOpen(); + if(PositionExist(ExtSignalOpen)) + ExtSignalOpen=SIGNAL_NOT; + } + +//--- Phase 3 - close if there is a signal to close + if(ExtSignalClose && PositionExist(ExtSignalClose)) + { + Print("\r\nSignal to close position ", ExtDirection); + CloseBySignal(ExtSignalClose); + if(!PositionExist(ExtSignalClose)) + ExtSignalClose=SIGNAL_NOT; + } + +//--- Phase 4 - close upon expiration + if(ExtCloseByTime && PositionExpiredByTimeExist()) + { + CloseByTime(); + ExtCloseByTime=PositionExpiredByTimeExist(); + } + } +//+------------------------------------------------------------------+ +//| Get the current environment and check for a pattern | +//+------------------------------------------------------------------+ +bool CheckState() + { +//--- check if there is a pattern + if(!CheckPattern()) + { + Print("Error, failed to check pattern"); + return(false); + } + +//--- check for confirmation + if(!CheckConfirmation()) + { + Print("Error, failed to check pattern confirmation"); + return(false); + } +//--- if there is no confirmation, cancel the signal + if(!ExtConfirmed) + ExtSignalOpen=SIGNAL_NOT; + +//--- check if there is a signal to close a position + if(!CheckCloseSignal()) + { + Print("Error, failed to check the closing signal"); + return(false); + } + +//--- if positions are to be closed after certain holding time in bars + if(InpDuration) + ExtCloseByTime=true; // set flag to close upon expiration + +//--- all checks done + return(true); + } +//+------------------------------------------------------------------+ +//| Open a position in the direction of the signal | +//+------------------------------------------------------------------+ +bool PositionOpen() + { + ExtSymbolInfo.Refresh(); + ExtSymbolInfo.RefreshRates(); + + double price=0; +//--- Stop Loss and Take Profit are not set by default + double stoploss=0.0; + double takeprofit=0.0; + + int digits=ExtSymbolInfo.Digits(); + double point=ExtSymbolInfo.Point(); + double spread=ExtSymbolInfo.Ask()-ExtSymbolInfo.Bid(); + +//--- uptrend + if(ExtSignalOpen==SIGNAL_BUY) + { + price=NormalizeDouble(ExtSymbolInfo.Ask(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price-spread, digits); + } + else + stoploss = NormalizeDouble(price-InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price+spread, digits); + } + else + takeprofit = NormalizeDouble(price+InpTP*point, digits); + } + + if(!ExtTrade.Buy(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s buy %G at %G (sl=%G tp=%G) failed. Ask=%G error=%d", + Symbol(), InpLot, price, stoploss, takeprofit, ExtSymbolInfo.Ask(), GetLastError()); + return(false); + } + } + +//--- downtrend + if(ExtSignalOpen==SIGNAL_SELL) + { + price=NormalizeDouble(ExtSymbolInfo.Bid(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price+spread, digits); + } + else + stoploss = NormalizeDouble(price+InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price-spread, digits); + } + else + takeprofit = NormalizeDouble(price-InpTP*point, digits); + } + + if(!ExtTrade.Sell(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s sell at %G (sl=%G tp=%G) failed. Bid=%G error=%d", + Symbol(), price, stoploss, takeprofit, ExtSymbolInfo.Bid(), GetLastError()); + ExtTrade.PrintResult(); + Print(" "); + return(false); + } + } + + return(true); + } +//+------------------------------------------------------------------+ +//| Close a position based on the specified signal | +//+------------------------------------------------------------------+ +void CloseBySignal(int type_close) + { +//--- if there is no signal to close, return successful completion + if(type_close==SIGNAL_NOT) + return; +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalClose)==0) + return; + +//--- closing direction + long type; + switch(type_close) + { + case CLOSE_SHORT: + type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + type=POSITION_TYPE_BUY; + break; + default: + Print("Error! Signal to close not detected"); + return; + } + +//--- check all positions and close ours based on the signal + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + if(PositionGetInteger(POSITION_TYPE)==type) + { + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Close positions upon holding time expiration in bars | +//+------------------------------------------------------------------+ +void CloseByTime() + { +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalOpen)==0) + return; + +//--- check all positions and close ours based on the holding time in bars + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + //--- position opening time + datetime open_time=(datetime)PositionGetInteger(POSITION_TIME); + //--- check position holding time in bars + if(BarsHold(open_time)>=(int)InpDuration) + { + Print("\r\nTime to close position #", ticket); + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Returns true if there are open positions | +//+------------------------------------------------------------------+ +bool PositionExist(int signal_direction) + { + bool check_type=(signal_direction!=SIGNAL_NOT); + +//--- what positions to search + ENUM_POSITION_TYPE search_type=WRONG_VALUE; + if(check_type) + switch(signal_direction) + { + case SIGNAL_BUY: + search_type=POSITION_TYPE_BUY; + break; + case SIGNAL_SELL: + search_type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + search_type=POSITION_TYPE_BUY; + break; + case CLOSE_SHORT: + search_type=POSITION_TYPE_SELL; + break; + default: + //--- entry direction is not specified; nothing to search + return(false); + } + +//--- go through the list of all positions + int positions=PositionsTotal(); + for(int i=0; i=(int)InpDuration)) + return(true); + } + } + } + +//--- open position not found + return(false); + } +//+------------------------------------------------------------------+ +//| Checks position closing time in bars | +//+------------------------------------------------------------------+ +int BarsHold(datetime open_time) + { +//--- first run a basic simple check + if(TimeCurrent()-open_timeAvgBody(1)) && // long black + (Open(2)-Close(2)>AvgBody(1)) && + (Open(1)-Close(1)>AvgBody(1)) && + (MidPoint(2)AvgBody(1)) && // long white + (Close(2)-Open(2)>AvgBody(1)) && + (Close(1)-Open(1)>AvgBody(1)) && + (MidPoint(2)>MidPoint(3)) && // higher midpoints + (MidPoint(1)>MidPoint(2))) + { + ExtPatternDetected=true; + ExtSignalOpen=SIGNAL_BUY; + ExtPatternInfo="\r\n3 White Soldiers detected"; + ExtDirection="Buy"; + return(true); + } + +//--- result of checking + return(ExtCheckPassed); + } +//+------------------------------------------------------------------+ +//| Returns true in case of successful confirmation check | +//+------------------------------------------------------------------+ +bool CheckConfirmation() + { + ExtConfirmed=false; +//--- if there is no pattern, do not search for confirmation + if(!ExtPatternDetected) + return(true); + +//--- get the value of the stochastic indicator to confirm the signal + double signal=RSI(1); + if(signal==EMPTY_VALUE) + { + //--- failed to get indicator value, check failed + return(false); + } + +//--- check the Buy signal + if(ExtSignalOpen==SIGNAL_BUY && (signal<40)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: RSI<40"; + } + +//--- check the Sell signal + if(ExtSignalOpen==SIGNAL_SELL && (signal>60)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: RSI>60"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| Check if there is a signal to close | +//+------------------------------------------------------------------+ +bool CheckCloseSignal() + { + ExtSignalClose=false; +//--- if there is a signal to enter the market, do not check the signal to close + if(ExtSignalOpen!=SIGNAL_NOT) + return(true); + +//--- check if there is a signal to close a long position + if(((RSI(1)<70) && (RSI(2)>70)) || ((RSI(1)<30) && (RSI(2)>30))) + { + //--- there is a signal to close a long position + ExtSignalClose=CLOSE_LONG; + ExtDirection="Long"; + } + +//--- check if there is a signal to close a short position + if(((RSI(1)>30) && (RSI(2)<30)) || ((RSI(1)>70) && (RSI(2)<70))) + { + //--- there is a signal to close a short position + ExtSignalClose=CLOSE_SHORT; + ExtDirection="Short"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| RSI indicator value at the specified bar | +//+------------------------------------------------------------------+ +double RSI(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtIndicatorHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the RSI indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Experts/Free Robots/BlackCrows WhiteSoldiers Stoch.mq5 b/BKPS/14031218/Experts/Free Robots/BlackCrows WhiteSoldiers Stoch.mq5 new file mode 100644 index 0000000..81ed611 --- /dev/null +++ b/BKPS/14031218/Experts/Free Robots/BlackCrows WhiteSoldiers Stoch.mq5 @@ -0,0 +1,661 @@ +//+------------------------------------------------------------------+ +//| BlackCrows WhiteSoldiers Stoch.mq5 | +//| Copyright 2024, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2024, MetaQuotes Ltd." +#property link "https://www.mql5.com" +#property version "1.00" + +#include +#include + +#define SIGNAL_BUY 1 // Buy signal +#define SIGNAL_NOT 0 // no trading signal +#define SIGNAL_SELL -1 // Sell signal + +#define CLOSE_LONG 2 // signal to close Long +#define CLOSE_SHORT -2 // signal to close Short + +//--- Input parameters +input int InpAverBodyPeriod=12; // period for calculating average candlestick size +input int InpStochK =47; // period %K +input int InpStochD =9; // period %D +input int InpStochSlow =13; // smoothing period %K +input ENUM_STO_PRICE InpStochApplied =STO_LOWHIGH; // calculation type +input ENUM_MA_METHOD InpStochMA =MODE_SMA; // smoothing type + +//--- trade parameters +input uint InpDuration=10; // position holding time in bars +input uint InpSL =200; // Stop Loss in points +input uint InpTP =200; // Take Profit in points +input uint InpSlippage=10; // slippage in points +//--- money management parameters +input double InpLot =0.1; // lot +//--- Expert ID +input long InpMagicNumber=120400; // Magic Number + +//--- global variables +int ExtAvgBodyPeriod; // average candlestick calculation period +int ExtSignalOpen =0; // Buy/Sell signal +int ExtSignalClose =0; // signal to close a position +string ExtPatternInfo =""; // current pattern information +string ExtDirection =""; // position opening direction +bool ExtPatternDetected=false; // pattern detected +bool ExtConfirmed =false; // pattern confirmed +bool ExtCloseByTime =true; // requires closing by time +bool ExtCheckPassed =true; // status checking error +//--- indicator handle +int ExtIndicatorHandle=INVALID_HANDLE; + +//--- service objects +CTrade ExtTrade; +CSymbolInfo ExtSymbolInfo; +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { + Print("InpSL=", InpSL); + Print("InpTP=", InpTP); +//--- set parameters for trading operations + ExtTrade.SetDeviationInPoints(InpSlippage); // slippage + ExtTrade.SetExpertMagicNumber(InpMagicNumber); // Expert Advisor ID + ExtTrade.LogLevel(LOG_LEVEL_ERRORS); // logging level + + ExtAvgBodyPeriod=InpAverBodyPeriod; +//--- indicator initialization + ExtIndicatorHandle=iStochastic(_Symbol, _Period, InpStochK, InpStochD, InpStochSlow, InpStochMA, InpStochApplied); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating iStochastic indicator"); + return(INIT_FAILED); + } +//--- OK + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { +//--- release indicator handle + IndicatorRelease(ExtIndicatorHandle); + } +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() + { +//--- save the next bar start time; all checks at bar opening only + static datetime next_bar_open=0; + +//--- Phase 1 - check the emergence of a new bar and update the status + if(TimeCurrent()>=next_bar_open) + { + //--- get the current state of environment on the new bar + // namely, set the values of global variables: + // ExtPatternDetected - pattern detection + // ExtConfirmed - pattern confirmation + // ExtSignalOpen - signal to open + // ExtSignalClose - signal to close + // ExtPatternInfo - current pattern information + if(CheckState()) + { + //--- set the new bar opening time + next_bar_open=TimeCurrent(); + next_bar_open-=next_bar_open%PeriodSeconds(_Period); + next_bar_open+=PeriodSeconds(_Period); + + //--- report the emergence of a new bar only once within a bar + if(ExtPatternDetected && ExtConfirmed) + Print(ExtPatternInfo); + } + else + { + //--- error getting the status, retry on the next tick + return; + } + } + +//--- Phase 2 - if there is a signal and no position in this direction + if(ExtSignalOpen && !PositionExist(ExtSignalOpen)) + { + Print("\r\nSignal to open position ", ExtDirection); + PositionOpen(); + if(PositionExist(ExtSignalOpen)) + ExtSignalOpen=SIGNAL_NOT; + } + +//--- Phase 3 - close if there is a signal to close + if(ExtSignalClose && PositionExist(ExtSignalClose)) + { + Print("\r\nSignal to close position ", ExtDirection); + CloseBySignal(ExtSignalClose); + if(!PositionExist(ExtSignalClose)) + ExtSignalClose=SIGNAL_NOT; + } + +//--- Phase 4 - close upon expiration + if(ExtCloseByTime && PositionExpiredByTimeExist()) + { + CloseByTime(); + ExtCloseByTime=PositionExpiredByTimeExist(); + } + } +//+------------------------------------------------------------------+ +//| Get the current environment and check for a pattern | +//+------------------------------------------------------------------+ +bool CheckState() + { +//--- check if there is a pattern + if(!CheckPattern()) + { + Print("Error, failed to check pattern"); + return(false); + } + +//--- check for confirmation + if(!CheckConfirmation()) + { + Print("Error, failed to check pattern confirmation"); + return(false); + } +//--- if there is no confirmation, cancel the signal + if(!ExtConfirmed) + ExtSignalOpen=SIGNAL_NOT; + +//--- check if there is a signal to close a position + if(!CheckCloseSignal()) + { + Print("Error, failed to check the closing signal"); + return(false); + } + +//--- if positions are to be closed after certain holding time in bars + if(InpDuration) + ExtCloseByTime=true; // set flag to close upon expiration + +//--- all checks done + return(true); + } +//+------------------------------------------------------------------+ +//| Open a position in the direction of the signal | +//+------------------------------------------------------------------+ +bool PositionOpen() + { + ExtSymbolInfo.Refresh(); + ExtSymbolInfo.RefreshRates(); + + double price=0; +//--- Stop Loss and Take Profit are not set by default + double stoploss=0.0; + double takeprofit=0.0; + + int digits=ExtSymbolInfo.Digits(); + double point=ExtSymbolInfo.Point(); + double spread=ExtSymbolInfo.Ask()-ExtSymbolInfo.Bid(); + +//--- uptrend + if(ExtSignalOpen==SIGNAL_BUY) + { + price=NormalizeDouble(ExtSymbolInfo.Ask(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price-spread, digits); + } + else + stoploss = NormalizeDouble(price-InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price+spread, digits); + } + else + takeprofit = NormalizeDouble(price+InpTP*point, digits); + } + + if(!ExtTrade.Buy(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s buy %G at %G (sl=%G tp=%G) failed. Ask=%G error=%d", + Symbol(), InpLot, price, stoploss, takeprofit, ExtSymbolInfo.Ask(), GetLastError()); + return(false); + } + } + +//--- downtrend + if(ExtSignalOpen==SIGNAL_SELL) + { + price=NormalizeDouble(ExtSymbolInfo.Bid(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price+spread, digits); + } + else + stoploss = NormalizeDouble(price+InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price-spread, digits); + } + else + takeprofit = NormalizeDouble(price-InpTP*point, digits); + } + + if(!ExtTrade.Sell(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s sell at %G (sl=%G tp=%G) failed. Bid=%G error=%d", + Symbol(), price, stoploss, takeprofit, ExtSymbolInfo.Bid(), GetLastError()); + ExtTrade.PrintResult(); + Print(" "); + return(false); + } + } + + return(true); + } +//+------------------------------------------------------------------+ +//| Close a position based on the specified signal | +//+------------------------------------------------------------------+ +void CloseBySignal(int type_close) + { +//--- if there is no signal to close, return successful completion + if(type_close==SIGNAL_NOT) + return; +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalClose)==0) + return; + +//--- closing direction + long type; + switch(type_close) + { + case CLOSE_SHORT: + type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + type=POSITION_TYPE_BUY; + break; + default: + Print("Error! Signal to close not detected"); + return; + } + +//--- check all positions and close ours based on the signal + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + if(PositionGetInteger(POSITION_TYPE)==type) + { + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Close positions upon holding time expiration in bars | +//+------------------------------------------------------------------+ +void CloseByTime() + { +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalOpen)==0) + return; + +//--- check all positions and close ours based on the holding time in bars + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + //--- position opening time + datetime open_time=(datetime)PositionGetInteger(POSITION_TIME); + //--- check position holding time in bars + if(BarsHold(open_time)>=(int)InpDuration) + { + Print("\r\nTime to close position #", ticket); + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Returns true if there are open positions | +//+------------------------------------------------------------------+ +bool PositionExist(int signal_direction) + { + bool check_type=(signal_direction!=SIGNAL_NOT); + +//--- what positions to search + ENUM_POSITION_TYPE search_type=WRONG_VALUE; + if(check_type) + switch(signal_direction) + { + case SIGNAL_BUY: + search_type=POSITION_TYPE_BUY; + break; + case SIGNAL_SELL: + search_type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + search_type=POSITION_TYPE_BUY; + break; + case CLOSE_SHORT: + search_type=POSITION_TYPE_SELL; + break; + default: + //--- entry direction is not specified; nothing to search + return(false); + } + +//--- go through the list of all positions + int positions=PositionsTotal(); + for(int i=0; i=(int)InpDuration)) + return(true); + } + } + } + +//--- open position not found + return(false); + } +//+------------------------------------------------------------------+ +//| Checks position closing time in bars | +//+------------------------------------------------------------------+ +int BarsHold(datetime open_time) + { +//--- first run a basic simple check + if(TimeCurrent()-open_timeAvgBody(1)) && // long black + (Open(2)-Close(2)>AvgBody(1)) && + (Open(1)-Close(1)>AvgBody(1)) && + (MidPoint(2)AvgBody(1)) && // long white + (Close(2)-Open(2)>AvgBody(1)) && + (Close(1)-Open(1)>AvgBody(1)) && + (MidPoint(2)>MidPoint(3)) && // higher midpoints + (MidPoint(1)>MidPoint(2))) + { + ExtPatternDetected=true; + ExtSignalOpen=SIGNAL_BUY; + ExtPatternInfo="\r\n3 White Soldiers detected"; + ExtDirection="Buy"; + return(true); + } + +//--- result of checking + return(ExtCheckPassed); + } +//+------------------------------------------------------------------+ +//| Returns true in case of successful confirmation check | +//+------------------------------------------------------------------+ +bool CheckConfirmation() + { + ExtConfirmed=false; +//--- if there is no pattern, do not search for confirmation + if(!ExtPatternDetected) + return(true); + +//--- get the value of the stochastic indicator to confirm the signal + double signal=StochSignal(1); + if(signal==EMPTY_VALUE) + { + //--- failed to get indicator value, check failed + return(false); + } + +//--- check the Buy signal + if(ExtSignalOpen==SIGNAL_BUY && (signal<30)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: StochSignal<30"; + } + +//--- check the Sell signal + if(ExtSignalOpen==SIGNAL_SELL && (signal>70)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: StochSignal>70"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| Check if there is a signal to close | +//+------------------------------------------------------------------+ +bool CheckCloseSignal() + { + ExtSignalClose=false; +//--- if there is a signal to enter the market, do not check the signal to close + if(ExtSignalOpen!=SIGNAL_NOT) + return(true); + +//--- check if there is a signal to close a long position + if(((StochSignal(1)<80) && (StochSignal(2)>80))|| // 80 crossed downwards + ((StochSignal(1)<20) && (StochSignal(2)>20))) // 20 crossed downwards + { + //--- there is a signal to close a long position + ExtSignalClose=CLOSE_LONG; + ExtDirection="Long"; + } + +//--- check if there is a signal to close a short position + if((((StochSignal(1)>20) && (StochSignal(2)<20)) || // 20 crossed upwards + ((StochSignal(1)>80) && (StochSignal(2)<80)))) // 80 crossed upwards + { + //--- there is a signal to close a short position + ExtSignalClose=CLOSE_SHORT; + ExtDirection="Short"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| Stochastic indicator value at the specified bar | +//+------------------------------------------------------------------+ +double StochSignal(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtIndicatorHandle, SIGNAL_LINE, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the iStochastic indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Experts/Free Robots/BullishBearish Engulfing CCI.mq5 b/BKPS/14031218/Experts/Free Robots/BullishBearish Engulfing CCI.mq5 new file mode 100644 index 0000000..b8347bc --- /dev/null +++ b/BKPS/14031218/Experts/Free Robots/BullishBearish Engulfing CCI.mq5 @@ -0,0 +1,682 @@ +//+------------------------------------------------------------------+ +//| BullishBearish Engulfing CCI.mq5 | +//| Copyright 2024, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2024, MetaQuotes Ltd." +#property link "https://www.mql5.com" +#property version "1.00" + +#include +#include + +#define SIGNAL_BUY 1 // Buy signal +#define SIGNAL_NOT 0 // no trading signal +#define SIGNAL_SELL -1 // Sell signal + +#define CLOSE_LONG 2 // signal to close Long +#define CLOSE_SHORT -2 // signal to close Short + +//--- Input parameters +input int InpAverBodyPeriod=12; // period for calculating average candlestick size +input int InpMAPeriod =5; // Trend MA period +input int InpPeriodCCI =37; // CCI period +input ENUM_APPLIED_PRICE InpPrice=PRICE_CLOSE; // price type + +//--- trade parameters +input uint InpDuration=10; // position holding time in bars +input uint InpSL =200; // Stop Loss in points +input uint InpTP =200; // Take Profit in points +input uint InpSlippage=10; // slippage in points +//--- money management parameters +input double InpLot =0.1; // lot +//--- Expert ID +input long InpMagicNumber=121100; // Magic Number + +//--- global variables +int ExtAvgBodyPeriod; // average candlestick calculation period +int ExtSignalOpen =0; // Buy/Sell signal +int ExtSignalClose =0; // signal to close a position +string ExtPatternInfo =""; // current pattern information +string ExtDirection =""; // position opening direction +bool ExtPatternDetected=false; // pattern detected +bool ExtConfirmed =false; // pattern confirmed +bool ExtCloseByTime =true; // requires closing by time +bool ExtCheckPassed =true; // status checking error + +//--- indicator handles +int ExtIndicatorHandle=INVALID_HANDLE; +int ExtTrendMAHandle =INVALID_HANDLE; + +//--- service objects +CTrade ExtTrade; +CSymbolInfo ExtSymbolInfo; +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { + Print("InpSL=", InpSL); + Print("InpTP=", InpTP); +//--- set parameters for trading operations + ExtTrade.SetDeviationInPoints(InpSlippage); // slippage + ExtTrade.SetExpertMagicNumber(InpMagicNumber); // Expert Advisor ID + ExtTrade.LogLevel(LOG_LEVEL_ERRORS); // logging level + + ExtAvgBodyPeriod=InpAverBodyPeriod; +//--- indicator initialization + ExtIndicatorHandle=iCCI(_Symbol, _Period, InpPeriodCCI, InpPrice); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating CCI indicator"); + return(INIT_FAILED); + } + +//--- trend moving average + ExtTrendMAHandle=iMA(_Symbol, _Period, InpMAPeriod, 0, MODE_SMA, PRICE_CLOSE); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating Moving Average indicator"); + return(INIT_FAILED); + } + +//--- OK + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { +//--- release indicator handle + IndicatorRelease(ExtIndicatorHandle); + } +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() + { +//--- save the next bar start time; all checks at bar opening only + static datetime next_bar_open=0; + +//--- Phase 1 - check the emergence of a new bar and update the status + if(TimeCurrent()>=next_bar_open) + { + //--- get the current state of environment on the new bar + // namely, set the values of global variables: + // ExtPatternDetected - pattern detection + // ExtConfirmed - pattern confirmation + // ExtSignalOpen - signal to open + // ExtSignalClose - signal to close + // ExtPatternInfo - current pattern information + if(CheckState()) + { + //--- set the new bar opening time + next_bar_open=TimeCurrent(); + next_bar_open-=next_bar_open%PeriodSeconds(_Period); + next_bar_open+=PeriodSeconds(_Period); + + //--- report the emergence of a new bar only once within a bar + if(ExtPatternDetected && ExtConfirmed) + Print(ExtPatternInfo); + } + else + { + //--- error getting the status, retry on the next tick + return; + } + } + +//--- Phase 2 - if there is a signal and no position in this direction + if(ExtSignalOpen && !PositionExist(ExtSignalOpen)) + { + Print("\r\nSignal to open position ", ExtDirection); + PositionOpen(); + if(PositionExist(ExtSignalOpen)) + ExtSignalOpen=SIGNAL_NOT; + } + +//--- Phase 3 - close if there is a signal to close + if(ExtSignalClose && PositionExist(ExtSignalClose)) + { + Print("\r\nSignal to close position ", ExtDirection); + CloseBySignal(ExtSignalClose); + if(!PositionExist(ExtSignalClose)) + ExtSignalClose=SIGNAL_NOT; + } + +//--- Phase 4 - close upon expiration + if(ExtCloseByTime && PositionExpiredByTimeExist()) + { + CloseByTime(); + ExtCloseByTime=PositionExpiredByTimeExist(); + } + } +//+------------------------------------------------------------------+ +//| Get the current environment and check for a pattern | +//+------------------------------------------------------------------+ +bool CheckState() + { +//--- check if there is a pattern + if(!CheckPattern()) + { + Print("Error, failed to check pattern"); + return(false); + } + +//--- check for confirmation + if(!CheckConfirmation()) + { + Print("Error, failed to check pattern confirmation"); + return(false); + } +//--- if there is no confirmation, cancel the signal + if(!ExtConfirmed) + ExtSignalOpen=SIGNAL_NOT; + +//--- check if there is a signal to close a position + if(!CheckCloseSignal()) + { + Print("Error, failed to check the closing signal"); + return(false); + } + +//--- if positions are to be closed after certain holding time in bars + if(InpDuration) + ExtCloseByTime=true; // set flag to close upon expiration + +//--- all checks done + return(true); + } +//+------------------------------------------------------------------+ +//| Open a position in the direction of the signal | +//+------------------------------------------------------------------+ +bool PositionOpen() + { + ExtSymbolInfo.Refresh(); + ExtSymbolInfo.RefreshRates(); + + double price=0; +//--- Stop Loss and Take Profit are not set by default + double stoploss=0.0; + double takeprofit=0.0; + + int digits=ExtSymbolInfo.Digits(); + double point=ExtSymbolInfo.Point(); + double spread=ExtSymbolInfo.Ask()-ExtSymbolInfo.Bid(); + +//--- uptrend + if(ExtSignalOpen==SIGNAL_BUY) + { + price=NormalizeDouble(ExtSymbolInfo.Ask(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price-spread, digits); + } + else + stoploss = NormalizeDouble(price-InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price+spread, digits); + } + else + takeprofit = NormalizeDouble(price+InpTP*point, digits); + } + + if(!ExtTrade.Buy(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s buy %G at %G (sl=%G tp=%G) failed. Ask=%G error=%d", + Symbol(), InpLot, price, stoploss, takeprofit, ExtSymbolInfo.Ask(), GetLastError()); + return(false); + } + } + +//--- downtrend + if(ExtSignalOpen==SIGNAL_SELL) + { + price=NormalizeDouble(ExtSymbolInfo.Bid(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price+spread, digits); + } + else + stoploss = NormalizeDouble(price+InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price-spread, digits); + } + else + takeprofit = NormalizeDouble(price-InpTP*point, digits); + } + + if(!ExtTrade.Sell(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s sell at %G (sl=%G tp=%G) failed. Bid=%G error=%d", + Symbol(), price, stoploss, takeprofit, ExtSymbolInfo.Bid(), GetLastError()); + ExtTrade.PrintResult(); + Print(" "); + return(false); + } + } + + return(true); + } +//+------------------------------------------------------------------+ +//| Close a position based on the specified signal | +//+------------------------------------------------------------------+ +void CloseBySignal(int type_close) + { +//--- if there is no signal to close, return successful completion + if(type_close==SIGNAL_NOT) + return; +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalClose)==0) + return; + +//--- closing direction + long type; + switch(type_close) + { + case CLOSE_SHORT: + type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + type=POSITION_TYPE_BUY; + break; + default: + Print("Error! Signal to close not detected"); + return; + } + +//--- check all positions and close ours based on the signal + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + if(PositionGetInteger(POSITION_TYPE)==type) + { + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Close positions upon holding time expiration in bars | +//+------------------------------------------------------------------+ +void CloseByTime() + { +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalOpen)==0) + return; + +//--- check all positions and close ours based on the holding time in bars + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + //--- position opening time + datetime open_time=(datetime)PositionGetInteger(POSITION_TIME); + //--- check position holding time in bars + if(BarsHold(open_time)>=(int)InpDuration) + { + Print("\r\nTime to close position #", ticket); + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Returns true if there are open positions | +//+------------------------------------------------------------------+ +bool PositionExist(int signal_direction) + { + bool check_type=(signal_direction!=SIGNAL_NOT); + +//--- what positions to search + ENUM_POSITION_TYPE search_type=WRONG_VALUE; + if(check_type) + switch(signal_direction) + { + case SIGNAL_BUY: + search_type=POSITION_TYPE_BUY; + break; + case SIGNAL_SELL: + search_type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + search_type=POSITION_TYPE_BUY; + break; + case CLOSE_SHORT: + search_type=POSITION_TYPE_SELL; + break; + default: + //--- entry direction is not specified; nothing to search + return(false); + } + +//--- go through the list of all positions + int positions=PositionsTotal(); + for(int i=0; i=(int)InpDuration)) + return(true); + } + } + } + +//--- open position not found + return(false); + } +//+------------------------------------------------------------------+ +//| Checks position closing time in bars | +//+------------------------------------------------------------------+ +int BarsHold(datetime open_time) + { +//--- first run a basic simple check + if(TimeCurrent()-open_timeAvgBody(1)) && // body of the candle is higher than average value of the body + (Close(1)CloseAvg(2)) && // uptrend + (Open(1)>Close(2))) // Open price of the bearish candle is higher than close price of the bullish candle + { + ExtPatternDetected=true; + ExtSignalOpen=SIGNAL_SELL; + ExtPatternInfo="\r\nBearish Engulfing detected"; + ExtDirection="Sell"; + return(true); + } + +//--- check Bullish Engulfing + if((Open(2)>Close(2)) && // previous candle is bearish + (Close(1)-Open(1)>AvgBody(1)) && // body of the bullish candle is higher than average value of the body + (Close(1)>Open(2)) && // close price of the bullish candle is higher than open price of the bearish candle + (MidOpenClose(2)50)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: CCI>50"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| Check if there is a signal to close | +//+------------------------------------------------------------------+ +bool CheckCloseSignal() + { + ExtSignalClose=false; +//--- if there is a signal to enter the market, do not check the signal to close + if(ExtSignalOpen!=SIGNAL_NOT) + return(true); + +//--- check if there is a signal to close a long position + if(((CCI(1)<80) && (CCI(2)>80)) || ((CCI(1)<-80) && (CCI(2)>-80))) + { + //--- there is a signal to close a long position + ExtSignalClose=CLOSE_LONG; + ExtDirection="Long"; + } + +//--- check if there is a signal to close a short position + if(((CCI(1)>-80) && (CCI(2)<-80)) || ((CCI(1)>80) && (CCI(2)<80))) + { + //--- there is a signal to close a short position + ExtSignalClose=CLOSE_SHORT; + ExtDirection="Short"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| CCI indicator value at the specified bar | +//+------------------------------------------------------------------+ +double CCI(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtIndicatorHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the CCI indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ +//| SMA value at the specified bar | +//+------------------------------------------------------------------+ +double CloseAvg(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtTrendMAHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the Simple Moving Average indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Experts/Free Robots/BullishBearish Engulfing MFI.mq5 b/BKPS/14031218/Experts/Free Robots/BullishBearish Engulfing MFI.mq5 new file mode 100644 index 0000000..ef447bb --- /dev/null +++ b/BKPS/14031218/Experts/Free Robots/BullishBearish Engulfing MFI.mq5 @@ -0,0 +1,682 @@ +//+------------------------------------------------------------------+ +//| BullishBearish Engulfing MFI.mq5 | +//| Copyright 2024, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2024, MetaQuotes Ltd." +#property link "https://www.mql5.com" +#property version "1.00" + +#include +#include + +#define SIGNAL_BUY 1 // Buy signal +#define SIGNAL_NOT 0 // no trading signal +#define SIGNAL_SELL -1 // Sell signal + +#define CLOSE_LONG 2 // signal to close Long +#define CLOSE_SHORT -2 // signal to close Short + +//--- Input parameters +input int InpAverBodyPeriod=12; // period for calculating average candlestick size +input int InpMAPeriod =5; // Trend MA period +input int InpPeriodMFI =37; // MFI period +input ENUM_APPLIED_VOLUME InpVolume=VOLUME_TICK; // volume type + +//--- trade parameters +input uint InpDuration=10; // position holding time in bars +input uint InpSL =200; // Stop Loss in points +input uint InpTP =200; // Take Profit in points +input uint InpSlippage=10; // slippage in points +//--- money management parameters +input double InpLot =0.1; // lot +//--- Expert ID +input long InpMagicNumber=120600; // Magic Number + +//--- global variables +int ExtAvgBodyPeriod; // average candlestick calculation period +int ExtSignalOpen =0; // Buy/Sell signal +int ExtSignalClose =0; // signal to close a position +string ExtPatternInfo =""; // current pattern information +string ExtDirection =""; // position opening direction +bool ExtPatternDetected=false; // pattern detected +bool ExtConfirmed =false; // pattern confirmed +bool ExtCloseByTime =true; // requires closing by time +bool ExtCheckPassed =true; // status checking error + +//--- indicator handles +int ExtIndicatorHandle=INVALID_HANDLE; +int ExtTrendMAHandle =INVALID_HANDLE; + +//--- service objects +CTrade ExtTrade; +CSymbolInfo ExtSymbolInfo; +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { + Print("InpSL=", InpSL); + Print("InpTP=", InpTP); +//--- set parameters for trading operations + ExtTrade.SetDeviationInPoints(InpSlippage); // slippage + ExtTrade.SetExpertMagicNumber(InpMagicNumber); // Expert Advisor ID + ExtTrade.LogLevel(LOG_LEVEL_ERRORS); // logging level + + ExtAvgBodyPeriod=InpAverBodyPeriod; +//--- indicator initialization + ExtIndicatorHandle=iMFI(_Symbol, _Period, InpPeriodMFI, InpVolume); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating MFI indicator"); + return(INIT_FAILED); + } + +//--- trend moving average + ExtTrendMAHandle=iMA(_Symbol, _Period, InpMAPeriod, 0, MODE_SMA, PRICE_CLOSE); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating Moving Average indicator"); + return(INIT_FAILED); + } + +//--- OK + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { +//--- release indicator handle + IndicatorRelease(ExtIndicatorHandle); + } +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() + { +//--- save the next bar start time; all checks at bar opening only + static datetime next_bar_open=0; + +//--- Phase 1 - check the emergence of a new bar and update the status + if(TimeCurrent()>=next_bar_open) + { + //--- get the current state of environment on the new bar + // namely, set the values of global variables: + // ExtPatternDetected - pattern detection + // ExtConfirmed - pattern confirmation + // ExtSignalOpen - signal to open + // ExtSignalClose - signal to close + // ExtPatternInfo - current pattern information + if(CheckState()) + { + //--- set the new bar opening time + next_bar_open=TimeCurrent(); + next_bar_open-=next_bar_open%PeriodSeconds(_Period); + next_bar_open+=PeriodSeconds(_Period); + + //--- report the emergence of a new bar only once within a bar + if(ExtPatternDetected && ExtConfirmed) + Print(ExtPatternInfo); + } + else + { + //--- error getting the status, retry on the next tick + return; + } + } + +//--- Phase 2 - if there is a signal and no position in this direction + if(ExtSignalOpen && !PositionExist(ExtSignalOpen)) + { + Print("\r\nSignal to open position ", ExtDirection); + PositionOpen(); + if(PositionExist(ExtSignalOpen)) + ExtSignalOpen=SIGNAL_NOT; + } + +//--- Phase 3 - close if there is a signal to close + if(ExtSignalClose && PositionExist(ExtSignalClose)) + { + Print("\r\nSignal to close position ", ExtDirection); + CloseBySignal(ExtSignalClose); + if(!PositionExist(ExtSignalClose)) + ExtSignalClose=SIGNAL_NOT; + } + +//--- Phase 4 - close upon expiration + if(ExtCloseByTime && PositionExpiredByTimeExist()) + { + CloseByTime(); + ExtCloseByTime=PositionExpiredByTimeExist(); + } + } +//+------------------------------------------------------------------+ +//| Get the current environment and check for a pattern | +//+------------------------------------------------------------------+ +bool CheckState() + { +//--- check if there is a pattern + if(!CheckPattern()) + { + Print("Error, failed to check pattern"); + return(false); + } + +//--- check for confirmation + if(!CheckConfirmation()) + { + Print("Error, failed to check pattern confirmation"); + return(false); + } +//--- if there is no confirmation, cancel the signal + if(!ExtConfirmed) + ExtSignalOpen=SIGNAL_NOT; + +//--- check if there is a signal to close a position + if(!CheckCloseSignal()) + { + Print("Error, failed to check the closing signal"); + return(false); + } + +//--- if positions are to be closed after certain holding time in bars + if(InpDuration) + ExtCloseByTime=true; // set flag to close upon expiration + +//--- all checks done + return(true); + } +//+------------------------------------------------------------------+ +//| Open a position in the direction of the signal | +//+------------------------------------------------------------------+ +bool PositionOpen() + { + ExtSymbolInfo.Refresh(); + ExtSymbolInfo.RefreshRates(); + + double price=0; +//--- Stop Loss and Take Profit are not set by default + double stoploss=0.0; + double takeprofit=0.0; + + int digits=ExtSymbolInfo.Digits(); + double point=ExtSymbolInfo.Point(); + double spread=ExtSymbolInfo.Ask()-ExtSymbolInfo.Bid(); + +//--- uptrend + if(ExtSignalOpen==SIGNAL_BUY) + { + price=NormalizeDouble(ExtSymbolInfo.Ask(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price-spread, digits); + } + else + stoploss = NormalizeDouble(price-InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price+spread, digits); + } + else + takeprofit = NormalizeDouble(price+InpTP*point, digits); + } + + if(!ExtTrade.Buy(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s buy %G at %G (sl=%G tp=%G) failed. Ask=%G error=%d", + Symbol(), InpLot, price, stoploss, takeprofit, ExtSymbolInfo.Ask(), GetLastError()); + return(false); + } + } + +//--- downtrend + if(ExtSignalOpen==SIGNAL_SELL) + { + price=NormalizeDouble(ExtSymbolInfo.Bid(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price+spread, digits); + } + else + stoploss = NormalizeDouble(price+InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price-spread, digits); + } + else + takeprofit = NormalizeDouble(price-InpTP*point, digits); + } + + if(!ExtTrade.Sell(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s sell at %G (sl=%G tp=%G) failed. Bid=%G error=%d", + Symbol(), price, stoploss, takeprofit, ExtSymbolInfo.Bid(), GetLastError()); + ExtTrade.PrintResult(); + Print(" "); + return(false); + } + } + + return(true); + } +//+------------------------------------------------------------------+ +//| Close a position based on the specified signal | +//+------------------------------------------------------------------+ +void CloseBySignal(int type_close) + { +//--- if there is no signal to close, return successful completion + if(type_close==SIGNAL_NOT) + return; +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalClose)==0) + return; + +//--- closing direction + long type; + switch(type_close) + { + case CLOSE_SHORT: + type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + type=POSITION_TYPE_BUY; + break; + default: + Print("Error! Signal to close not detected"); + return; + } + +//--- check all positions and close ours based on the signal + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + if(PositionGetInteger(POSITION_TYPE)==type) + { + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Close positions upon holding time expiration in bars | +//+------------------------------------------------------------------+ +void CloseByTime() + { +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalOpen)==0) + return; + +//--- check all positions and close ours based on the holding time in bars + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + //--- position opening time + datetime open_time=(datetime)PositionGetInteger(POSITION_TIME); + //--- check position holding time in bars + if(BarsHold(open_time)>=(int)InpDuration) + { + Print("\r\nTime to close position #", ticket); + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Returns true if there are open positions | +//+------------------------------------------------------------------+ +bool PositionExist(int signal_direction) + { + bool check_type=(signal_direction!=SIGNAL_NOT); + +//--- what positions to search + ENUM_POSITION_TYPE search_type=WRONG_VALUE; + if(check_type) + switch(signal_direction) + { + case SIGNAL_BUY: + search_type=POSITION_TYPE_BUY; + break; + case SIGNAL_SELL: + search_type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + search_type=POSITION_TYPE_BUY; + break; + case CLOSE_SHORT: + search_type=POSITION_TYPE_SELL; + break; + default: + //--- entry direction is not specified; nothing to search + return(false); + } + +//--- go through the list of all positions + int positions=PositionsTotal(); + for(int i=0; i=(int)InpDuration)) + return(true); + } + } + } + +//--- open position not found + return(false); + } +//+------------------------------------------------------------------+ +//| Checks position closing time in bars | +//+------------------------------------------------------------------+ +int BarsHold(datetime open_time) + { +//--- first run a basic simple check + if(TimeCurrent()-open_timeAvgBody(1)) && // body of the candle is higher than average value of the body + (Close(1)CloseAvg(2)) && // uptrend + (Open(1)>Close(2))) // Open price of the bearish candle is higher than close price of the bullish candle + { + ExtPatternDetected=true; + ExtSignalOpen=SIGNAL_SELL; + ExtPatternInfo="\r\nBearish Engulfing detected"; + ExtDirection="Sell"; + return(true); + } + +//--- check Bullish Engulfing + if((Open(2)>Close(2)) && // previous candle is bearish + (Close(1)-Open(1)>AvgBody(1)) && // body of the bullish candle is higher than average value of the body + (Close(1)>Open(2)) && // close price of the bullish candle is higher than open price of the bearish candle + (MidOpenClose(2)60)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: MFI>60"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| Check if there is a signal to close | +//+------------------------------------------------------------------+ +bool CheckCloseSignal() + { + ExtSignalClose=false; +//--- if there is a signal to enter the market, do not check the signal to close + if(ExtSignalOpen!=SIGNAL_NOT) + return(true); + +//--- check if there is a signal to close a long position + if(((MFI(1)<70) && (MFI(2)>70)) || ((MFI(1)<30) && (MFI(2)>30))) + { + //--- there is a signal to close a long position + ExtSignalClose=CLOSE_LONG; + ExtDirection="Long"; + } + +//--- check if there is a signal to close a short position + if(((MFI(1)>30) && (MFI(2)<30)) || ((MFI(1)>70) && (MFI(2)<70))) + { + //--- there is a signal to close a short position + ExtSignalClose=CLOSE_SHORT; + ExtDirection="Short"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| MFI indicator value at the specified bar | +//+------------------------------------------------------------------+ +double MFI(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtIndicatorHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the MFI indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ +//| SMA value at the specified bar | +//+------------------------------------------------------------------+ +double CloseAvg(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtTrendMAHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the Simple Moving Average indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Experts/Free Robots/BullishBearish Engulfing RSI.mq5 b/BKPS/14031218/Experts/Free Robots/BullishBearish Engulfing RSI.mq5 new file mode 100644 index 0000000..7524628 --- /dev/null +++ b/BKPS/14031218/Experts/Free Robots/BullishBearish Engulfing RSI.mq5 @@ -0,0 +1,682 @@ +//+------------------------------------------------------------------+ +//| BullishBearish Engulfing RSI.mq5 | +//| Copyright 2024, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2024, MetaQuotes Ltd." +#property link "https://www.mql5.com" +#property version "1.00" + +#include +#include + +#define SIGNAL_BUY 1 // Buy signal +#define SIGNAL_NOT 0 // no trading signal +#define SIGNAL_SELL -1 // Sell signal + +#define CLOSE_LONG 2 // signal to close Long +#define CLOSE_SHORT -2 // signal to close Short + +//--- Input parameters +input int InpAverBodyPeriod=12; // period for calculating average candlestick size +input int InpMAPeriod =5; // Trend MA period +input int InpPeriodRSI =37; // RSI period +input ENUM_APPLIED_PRICE InpPrice=PRICE_CLOSE; // price type + +//--- trade parameters +input uint InpDuration=10; // position holding time in bars +input uint InpSL =200; // Stop Loss in points +input uint InpTP =200; // Take Profit in points +input uint InpSlippage=10; // slippage in points +//--- money management parameters +input double InpLot =0.1; // lot +//--- Expert ID +input long InpMagicNumber=121300; // Magic Number + +//--- global variables +int ExtAvgBodyPeriod; // average candlestick calculation period +int ExtSignalOpen =0; // Buy/Sell signal +int ExtSignalClose =0; // signal to close a position +string ExtPatternInfo =""; // current pattern information +string ExtDirection =""; // position opening direction +bool ExtPatternDetected=false; // pattern detected +bool ExtConfirmed =false; // pattern confirmed +bool ExtCloseByTime =true; // requires closing by time +bool ExtCheckPassed =true; // status checking error + +//--- indicator handles +int ExtIndicatorHandle=INVALID_HANDLE; +int ExtTrendMAHandle =INVALID_HANDLE; + +//--- service objects +CTrade ExtTrade; +CSymbolInfo ExtSymbolInfo; +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { + Print("InpSL=", InpSL); + Print("InpTP=", InpTP); +//--- set parameters for trading operations + ExtTrade.SetDeviationInPoints(InpSlippage); // slippage + ExtTrade.SetExpertMagicNumber(InpMagicNumber); // Expert Advisor ID + ExtTrade.LogLevel(LOG_LEVEL_ERRORS); // logging level + + ExtAvgBodyPeriod=InpAverBodyPeriod; +//--- indicator initialization + ExtIndicatorHandle=iRSI(_Symbol, _Period, InpPeriodRSI, InpPrice); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating CCI indicator"); + return(INIT_FAILED); + } + +//--- trend moving average + ExtTrendMAHandle=iMA(_Symbol, _Period, InpMAPeriod, 0, MODE_SMA, PRICE_CLOSE); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating Moving Average indicator"); + return(INIT_FAILED); + } + +//--- OK + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { +//--- release indicator handle + IndicatorRelease(ExtIndicatorHandle); + } +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() + { +//--- save the next bar start time; all checks at bar opening only + static datetime next_bar_open=0; + +//--- Phase 1 - check the emergence of a new bar and update the status + if(TimeCurrent()>=next_bar_open) + { + //--- get the current state of environment on the new bar + // namely, set the values of global variables: + // ExtPatternDetected - pattern detection + // ExtConfirmed - pattern confirmation + // ExtSignalOpen - signal to open + // ExtSignalClose - signal to close + // ExtPatternInfo - current pattern information + if(CheckState()) + { + //--- set the new bar opening time + next_bar_open=TimeCurrent(); + next_bar_open-=next_bar_open%PeriodSeconds(_Period); + next_bar_open+=PeriodSeconds(_Period); + + //--- report the emergence of a new bar only once within a bar + if(ExtPatternDetected && ExtConfirmed) + Print(ExtPatternInfo); + } + else + { + //--- error getting the status, retry on the next tick + return; + } + } + +//--- Phase 2 - if there is a signal and no position in this direction + if(ExtSignalOpen && !PositionExist(ExtSignalOpen)) + { + Print("\r\nSignal to open position ", ExtDirection); + PositionOpen(); + if(PositionExist(ExtSignalOpen)) + ExtSignalOpen=SIGNAL_NOT; + } + +//--- Phase 3 - close if there is a signal to close + if(ExtSignalClose && PositionExist(ExtSignalClose)) + { + Print("\r\nSignal to close position ", ExtDirection); + CloseBySignal(ExtSignalClose); + if(!PositionExist(ExtSignalClose)) + ExtSignalClose=SIGNAL_NOT; + } + +//--- Phase 4 - close upon expiration + if(ExtCloseByTime && PositionExpiredByTimeExist()) + { + CloseByTime(); + ExtCloseByTime=PositionExpiredByTimeExist(); + } + } +//+------------------------------------------------------------------+ +//| Get the current environment and check for a pattern | +//+------------------------------------------------------------------+ +bool CheckState() + { +//--- check if there is a pattern + if(!CheckPattern()) + { + Print("Error, failed to check pattern"); + return(false); + } + +//--- check for confirmation + if(!CheckConfirmation()) + { + Print("Error, failed to check pattern confirmation"); + return(false); + } +//--- if there is no confirmation, cancel the signal + if(!ExtConfirmed) + ExtSignalOpen=SIGNAL_NOT; + +//--- check if there is a signal to close a position + if(!CheckCloseSignal()) + { + Print("Error, failed to check the closing signal"); + return(false); + } + +//--- if positions are to be closed after certain holding time in bars + if(InpDuration) + ExtCloseByTime=true; // set flag to close upon expiration + +//--- all checks done + return(true); + } +//+------------------------------------------------------------------+ +//| Open a position in the direction of the signal | +//+------------------------------------------------------------------+ +bool PositionOpen() + { + ExtSymbolInfo.Refresh(); + ExtSymbolInfo.RefreshRates(); + + double price=0; +//--- Stop Loss and Take Profit are not set by default + double stoploss=0.0; + double takeprofit=0.0; + + int digits=ExtSymbolInfo.Digits(); + double point=ExtSymbolInfo.Point(); + double spread=ExtSymbolInfo.Ask()-ExtSymbolInfo.Bid(); + +//--- uptrend + if(ExtSignalOpen==SIGNAL_BUY) + { + price=NormalizeDouble(ExtSymbolInfo.Ask(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price-spread, digits); + } + else + stoploss = NormalizeDouble(price-InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price+spread, digits); + } + else + takeprofit = NormalizeDouble(price+InpTP*point, digits); + } + + if(!ExtTrade.Buy(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s buy %G at %G (sl=%G tp=%G) failed. Ask=%G error=%d", + Symbol(), InpLot, price, stoploss, takeprofit, ExtSymbolInfo.Ask(), GetLastError()); + return(false); + } + } + +//--- downtrend + if(ExtSignalOpen==SIGNAL_SELL) + { + price=NormalizeDouble(ExtSymbolInfo.Bid(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price+spread, digits); + } + else + stoploss = NormalizeDouble(price+InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price-spread, digits); + } + else + takeprofit = NormalizeDouble(price-InpTP*point, digits); + } + + if(!ExtTrade.Sell(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s sell at %G (sl=%G tp=%G) failed. Bid=%G error=%d", + Symbol(), price, stoploss, takeprofit, ExtSymbolInfo.Bid(), GetLastError()); + ExtTrade.PrintResult(); + Print(" "); + return(false); + } + } + + return(true); + } +//+------------------------------------------------------------------+ +//| Close a position based on the specified signal | +//+------------------------------------------------------------------+ +void CloseBySignal(int type_close) + { +//--- if there is no signal to close, return successful completion + if(type_close==SIGNAL_NOT) + return; +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalClose)==0) + return; + +//--- closing direction + long type; + switch(type_close) + { + case CLOSE_SHORT: + type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + type=POSITION_TYPE_BUY; + break; + default: + Print("Error! Signal to close not detected"); + return; + } + +//--- check all positions and close ours based on the signal + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + if(PositionGetInteger(POSITION_TYPE)==type) + { + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Close positions upon holding time expiration in bars | +//+------------------------------------------------------------------+ +void CloseByTime() + { +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalOpen)==0) + return; + +//--- check all positions and close ours based on the holding time in bars + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + //--- position opening time + datetime open_time=(datetime)PositionGetInteger(POSITION_TIME); + //--- check position holding time in bars + if(BarsHold(open_time)>=(int)InpDuration) + { + Print("\r\nTime to close position #", ticket); + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Returns true if there are open positions | +//+------------------------------------------------------------------+ +bool PositionExist(int signal_direction) + { + bool check_type=(signal_direction!=SIGNAL_NOT); + +//--- what positions to search + ENUM_POSITION_TYPE search_type=WRONG_VALUE; + if(check_type) + switch(signal_direction) + { + case SIGNAL_BUY: + search_type=POSITION_TYPE_BUY; + break; + case SIGNAL_SELL: + search_type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + search_type=POSITION_TYPE_BUY; + break; + case CLOSE_SHORT: + search_type=POSITION_TYPE_SELL; + break; + default: + //--- entry direction is not specified; nothing to search + return(false); + } + +//--- go through the list of all positions + int positions=PositionsTotal(); + for(int i=0; i=(int)InpDuration)) + return(true); + } + } + } + +//--- open position not found + return(false); + } +//+------------------------------------------------------------------+ +//| Checks position closing time in bars | +//+------------------------------------------------------------------+ +int BarsHold(datetime open_time) + { +//--- first run a basic simple check + if(TimeCurrent()-open_timeAvgBody(1)) && // body of the candle is higher than average value of the body + (Close(1)CloseAvg(2)) && // uptrend + (Open(1)>Close(2))) // Open price of the bearish candle is higher than close price of the bullish candle + { + ExtPatternDetected=true; + ExtSignalOpen=SIGNAL_SELL; + ExtPatternInfo="\r\nBearish Engulfing detected"; + ExtDirection="Sell"; + return(true); + } + +//--- check Bullish Engulfing + if((Open(2)>Close(2)) && // previous candle is bearish + (Close(1)-Open(1)>AvgBody(1)) && // body of the bullish candle is higher than average value of the body + (Close(1)>Open(2)) && // close price of the bullish candle is higher than open price of the bearish candle + (MidOpenClose(2)60)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: RSI>60"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| Check if there is a signal to close | +//+------------------------------------------------------------------+ +bool CheckCloseSignal() + { + ExtSignalClose=false; +//--- if there is a signal to enter the market, do not check the signal to close + if(ExtSignalOpen!=SIGNAL_NOT) + return(true); + +//--- check if there is a signal to close a long position + if(((RSI(1)<70) && (RSI(2)>70)) || ((RSI(1)<30) && (RSI(2)>30))) + { + //--- there is a signal to close a long position + ExtSignalClose=CLOSE_LONG; + ExtDirection="Long"; + } + +//--- check if there is a signal to close a short position + if(((RSI(1)>30) && (RSI(2)<30)) || ((RSI(1)>70) && (RSI(2)<70))) + { + //--- there is a signal to close a short position + ExtSignalClose=CLOSE_SHORT; + ExtDirection="Short"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| RSI indicator value at the specified bar | +//+------------------------------------------------------------------+ +double RSI(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtIndicatorHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the RSI indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ +//| SMA value at the specified bar | +//+------------------------------------------------------------------+ +double CloseAvg(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtTrendMAHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the Simple Moving Average indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Experts/Free Robots/BullishBearish Engulfing Stoch.mq5 b/BKPS/14031218/Experts/Free Robots/BullishBearish Engulfing Stoch.mq5 new file mode 100644 index 0000000..7437be3 --- /dev/null +++ b/BKPS/14031218/Experts/Free Robots/BullishBearish Engulfing Stoch.mq5 @@ -0,0 +1,688 @@ +//+------------------------------------------------------------------+ +//| BullishBearish Engulfing Stoch.mq5 | +//| Copyright 2024, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2024, MetaQuotes Ltd." +#property link "https://www.mql5.com" +#property version "1.00" + +#include +#include + +#define SIGNAL_BUY 1 // Buy signal +#define SIGNAL_NOT 0 // no trading signal +#define SIGNAL_SELL -1 // Sell signal + +#define CLOSE_LONG 2 // signal to close Long +#define CLOSE_SHORT -2 // signal to close Short + +//--- Input parameters +input int InpAverBodyPeriod=12; // period for calculating average candlestick size +input int InpMAPeriod =5; // Trend MA period +input int InpStochK =47; // period %K +input int InpStochD =9; // period %D +input int InpStochSlow=13; // smoothing period %K +input ENUM_STO_PRICE InpStochApplied =STO_LOWHIGH; // calculation type +input ENUM_MA_METHOD InpStochMA =MODE_SMA; // smoothing type + +//--- trade parameters +input uint InpDuration=10; // position holding time in bars +input uint InpSL =200; // Stop Loss in points +input uint InpTP =200; // Take Profit in points +input uint InpSlippage=10; // slippage in points +//--- money management parameters +input double InpLot =0.1; // lot +//--- Expert ID +input long InpMagicNumber=121400; // Magic Number + +//--- global variables +int ExtAvgBodyPeriod; // average candlestick calculation period +int ExtSignalOpen =0; // Buy/Sell signal +int ExtSignalClose =0; // signal to close a position +string ExtPatternInfo =""; // current pattern information +string ExtDirection =""; // position opening direction +bool ExtPatternDetected=false; // pattern detected +bool ExtConfirmed =false; // pattern confirmed +bool ExtCloseByTime =true; // requires closing by time +bool ExtCheckPassed =true; // status checking error + +//--- indicator handles +int ExtIndicatorHandle=INVALID_HANDLE; +int ExtTrendMAHandle =INVALID_HANDLE; + +//--- service objects +CTrade ExtTrade; +CSymbolInfo ExtSymbolInfo; +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { + Print("InpSL=", InpSL); + Print("InpTP=", InpTP); +//--- set parameters for trading operations + ExtTrade.SetDeviationInPoints(InpSlippage); // slippage + ExtTrade.SetExpertMagicNumber(InpMagicNumber); // Expert Advisor ID + ExtTrade.LogLevel(LOG_LEVEL_ERRORS); // logging level + + ExtAvgBodyPeriod=InpAverBodyPeriod; +//--- indicator initialization + ExtIndicatorHandle=iStochastic(_Symbol, _Period, InpStochK, InpStochD, InpStochSlow, InpStochMA, InpStochApplied); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating iStochastic indicator"); + return(INIT_FAILED); + } + +//--- trend moving average + ExtTrendMAHandle=iMA(_Symbol, _Period, InpMAPeriod,0, MODE_SMA,PRICE_CLOSE); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating Moving Average indicator"); + return(INIT_FAILED); + } + +//--- OK + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { +//--- release indicator handle + IndicatorRelease(ExtIndicatorHandle); + } +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() + { +//--- save the next bar start time; all checks at bar opening only + static datetime next_bar_open=0; + +//--- Phase 1 - check the emergence of a new bar and update the status + if(TimeCurrent()>=next_bar_open) + { + //--- get the current state of environment on the new bar + // namely, set the values of global variables: + // ExtPatternDetected - pattern detection + // ExtConfirmed - pattern confirmation + // ExtSignalOpen - signal to open + // ExtSignalClose - signal to close + // ExtPatternInfo - current pattern information + if(CheckState()) + { + //--- set the new bar opening time + next_bar_open=TimeCurrent(); + next_bar_open-=next_bar_open%PeriodSeconds(_Period); + next_bar_open+=PeriodSeconds(_Period); + + //--- report the emergence of a new bar only once within a bar + if(ExtPatternDetected && ExtConfirmed) + Print(ExtPatternInfo); + } + else + { + //--- error getting the status, retry on the next tick + return; + } + } + +//--- Phase 2 - if there is a signal and no position in this direction + if(ExtSignalOpen && !PositionExist(ExtSignalOpen)) + { + Print("\r\nSignal to open position ", ExtDirection); + PositionOpen(); + if(PositionExist(ExtSignalOpen)) + ExtSignalOpen=SIGNAL_NOT; + } + +//--- Phase 3 - close if there is a signal to close + if(ExtSignalClose && PositionExist(ExtSignalClose)) + { + Print("\r\nSignal to close position ", ExtDirection); + CloseBySignal(ExtSignalClose); + if(!PositionExist(ExtSignalClose)) + ExtSignalClose=SIGNAL_NOT; + } + +//--- Phase 4 - close upon expiration + if(ExtCloseByTime && PositionExpiredByTimeExist()) + { + CloseByTime(); + ExtCloseByTime=PositionExpiredByTimeExist(); + } + } +//+------------------------------------------------------------------+ +//| Get the current environment and check for a pattern | +//+------------------------------------------------------------------+ +bool CheckState() + { +//--- check if there is a pattern + if(!CheckPattern()) + { + Print("Error, failed to check pattern"); + return(false); + } + +//--- check for confirmation + if(!CheckConfirmation()) + { + Print("Error, failed to check pattern confirmation"); + return(false); + } +//--- if there is no confirmation, cancel the signal + if(!ExtConfirmed) + ExtSignalOpen=SIGNAL_NOT; + +//--- check if there is a signal to close a position + if(!CheckCloseSignal()) + { + Print("Error, failed to check the closing signal"); + return(false); + } + +//--- if positions are to be closed after certain holding time in bars + if(InpDuration) + ExtCloseByTime=true; // set flag to close upon expiration + +//--- all checks done + return(true); + } +//+------------------------------------------------------------------+ +//| Open a position in the direction of the signal | +//+------------------------------------------------------------------+ +bool PositionOpen() + { + ExtSymbolInfo.Refresh(); + ExtSymbolInfo.RefreshRates(); + + double price=0; +//--- Stop Loss and Take Profit are not set by default + double stoploss=0.0; + double takeprofit=0.0; + + int digits=ExtSymbolInfo.Digits(); + double point=ExtSymbolInfo.Point(); + double spread=ExtSymbolInfo.Ask()-ExtSymbolInfo.Bid(); + +//--- uptrend + if(ExtSignalOpen==SIGNAL_BUY) + { + price=NormalizeDouble(ExtSymbolInfo.Ask(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price-spread, digits); + } + else + stoploss = NormalizeDouble(price-InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price+spread, digits); + } + else + takeprofit = NormalizeDouble(price+InpTP*point, digits); + } + + if(!ExtTrade.Buy(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s buy %G at %G (sl=%G tp=%G) failed. Ask=%G error=%d", + Symbol(), InpLot, price, stoploss, takeprofit, ExtSymbolInfo.Ask(), GetLastError()); + return(false); + } + } + +//--- downtrend + if(ExtSignalOpen==SIGNAL_SELL) + { + price=NormalizeDouble(ExtSymbolInfo.Bid(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price+spread, digits); + } + else + stoploss = NormalizeDouble(price+InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price-spread, digits); + } + else + takeprofit = NormalizeDouble(price-InpTP*point, digits); + } + + if(!ExtTrade.Sell(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s sell at %G (sl=%G tp=%G) failed. Bid=%G error=%d", + Symbol(), price, stoploss, takeprofit, ExtSymbolInfo.Bid(), GetLastError()); + ExtTrade.PrintResult(); + Print(" "); + return(false); + } + } +//--- + return(true); + } +//+------------------------------------------------------------------+ +//| Close a position based on the specified signal | +//+------------------------------------------------------------------+ +void CloseBySignal(int type_close) + { +//--- if there is no signal to close, return successful completion + if(type_close==SIGNAL_NOT) + return; +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalClose)==0) + return; + +//--- closing direction + long type; + switch(type_close) + { + case CLOSE_SHORT: + type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + type=POSITION_TYPE_BUY; + break; + default: + Print("Error! Signal to close not detected"); + return; + } + +//--- check all positions and close ours based on the signal + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + if(PositionGetInteger(POSITION_TYPE)==type) + { + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Close positions upon holding time expiration in bars | +//+------------------------------------------------------------------+ +void CloseByTime() + { +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalOpen)==0) + return; + +//--- check all positions and close ours based on the holding time in bars + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + //--- position opening time + datetime open_time=(datetime)PositionGetInteger(POSITION_TIME); + //--- check position holding time in bars + if(BarsHold(open_time)>=(int)InpDuration) + { + Print("\r\nTime to close position #", ticket); + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Returns true if there are open positions | +//+------------------------------------------------------------------+ +bool PositionExist(int signal_direction) + { + bool check_type=(signal_direction!=SIGNAL_NOT); + +//--- what positions to search + ENUM_POSITION_TYPE search_type=WRONG_VALUE; + if(check_type) + switch(signal_direction) + { + case SIGNAL_BUY: + search_type=POSITION_TYPE_BUY; + break; + case SIGNAL_SELL: + search_type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + search_type=POSITION_TYPE_BUY; + break; + case CLOSE_SHORT: + search_type=POSITION_TYPE_SELL; + break; + default: + //--- entry direction is not specified; nothing to search + return(false); + } + +//--- go through the list of all positions + int positions=PositionsTotal(); + for(int i=0; i=(int)InpDuration)) + return(true); + } + } + } + +//--- open position not found + return(false); + } + +//+------------------------------------------------------------------+ +//| Checks position closing time in bars | +//+------------------------------------------------------------------+ +int BarsHold(datetime open_time) + { +//--- first run a basic simple check + if(TimeCurrent()-open_timeAvgBody(1)) && // body of the candle is higher than average value of the body + (Close(1)CloseAvg(2)) && // uptrend + (Open(1)>Close(2))) // Open price of the bearish candle is higher than close price of the bullish candle + { + ExtPatternDetected=true; + ExtSignalOpen=SIGNAL_SELL; + ExtPatternInfo="\r\nBearish Engulfing detected"; + ExtDirection="Sell"; + return(true); + } + +//--- check Bullish Engulfing + if((Open(2)>Close(2)) && // previous candle is bearish + (Close(1)-Open(1)>AvgBody(1)) && // body of the bullish candle is higher than average value of the body + (Close(1)>Open(2)) && // close price of the bullish candle is higher than open price of the bearish candle + (MidOpenClose(2)70)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: StochSignal>70"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| Check if there is a signal to close | +//+------------------------------------------------------------------+ +bool CheckCloseSignal() + { + ExtSignalClose=false; +//--- if there is a signal to enter the market, do not check the signal to close + if(ExtSignalOpen!=SIGNAL_NOT) + return(true); + +//--- check if there is a signal to close a long position + if(((StochSignal(1)<80) && (StochSignal(2)>80))|| // 80 crossed downwards + ((StochSignal(1)<20) && (StochSignal(2)>20))) // 20 crossed downwards + { + //--- there is a signal to close a long position + ExtSignalClose=CLOSE_LONG; + ExtDirection="Long"; + } + +//--- check if there is a signal to close a short position + if((((StochSignal(1)>20) && (StochSignal(2)<20)) || // 20 crossed upwards + ((StochSignal(1)>80) && (StochSignal(2)<80)))) // 80 crossed upwards + { + //--- there is a signal to close a short position + ExtSignalClose=CLOSE_SHORT; + ExtDirection="Short"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| Stochastic indicator value at the specified bar | +//+------------------------------------------------------------------+ +double StochSignal(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtIndicatorHandle, SIGNAL_LINE, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the iStochastic indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ +//| SMA value at the specified bar | +//+------------------------------------------------------------------+ +double CloseAvg(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtTrendMAHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the Simple Moving Average indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Experts/Free Robots/BullishBearish Harami CCI.mq5 b/BKPS/14031218/Experts/Free Robots/BullishBearish Harami CCI.mq5 new file mode 100644 index 0000000..b61b438 --- /dev/null +++ b/BKPS/14031218/Experts/Free Robots/BullishBearish Harami CCI.mq5 @@ -0,0 +1,682 @@ +//+------------------------------------------------------------------+ +//| BullishBearish Harami CCI.mq5 | +//| Copyright 2024, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2024, MetaQuotes Ltd." +#property link "https://www.mql5.com" +#property version "1.00" + +#include +#include + +#define SIGNAL_BUY 1 // Buy signal +#define SIGNAL_NOT 0 // no trading signal +#define SIGNAL_SELL -1 // Sell signal + +#define CLOSE_LONG 2 // signal to close Long +#define CLOSE_SHORT -2 // signal to close Short + +//--- Input parameters +input int InpAverBodyPeriod=12; // period for calculating average candlestick size +input int InpMAPeriod =5; // Trend MA period +input int InpPeriodCCI =37; // CCI period +input ENUM_APPLIED_PRICE InpPrice=PRICE_CLOSE; // price type + +//--- trade parameters +input uint InpDuration=10; // position holding time in bars +input uint InpSL =200; // Stop Loss in points +input uint InpTP =200; // Take Profit in points +input uint InpSlippage=10; // slippage in points +//--- money management parameters +input double InpLot =0.1; // lot +//--- Expert ID +input long InpMagicNumber=122100; // Magic Number + +//--- global variables +int ExtAvgBodyPeriod; // average candlestick calculation period +int ExtSignalOpen =0; // Buy/Sell signal +int ExtSignalClose =0; // signal to close a position +string ExtPatternInfo =""; // current pattern information +string ExtDirection =""; // position opening direction +bool ExtPatternDetected=false; // pattern detected +bool ExtConfirmed =false; // pattern confirmed +bool ExtCloseByTime =true; // requires closing by time +bool ExtCheckPassed =true; // status checking error + +//--- indicator handles +int ExtIndicatorHandle=INVALID_HANDLE; +int ExtTrendMAHandle =INVALID_HANDLE; + +//--- service objects +CTrade ExtTrade; +CSymbolInfo ExtSymbolInfo; +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { + Print("InpSL=", InpSL); + Print("InpTP=", InpTP); +//--- set parameters for trading operations + ExtTrade.SetDeviationInPoints(InpSlippage); // slippage + ExtTrade.SetExpertMagicNumber(InpMagicNumber); // Expert Advisor ID + ExtTrade.LogLevel(LOG_LEVEL_ERRORS); // logging level + + ExtAvgBodyPeriod=InpAverBodyPeriod; +//--- indicator initialization + ExtIndicatorHandle=iCCI(_Symbol, _Period, InpPeriodCCI, InpPrice); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating CCI indicator"); + return(INIT_FAILED); + } + +//--- trend moving average + ExtTrendMAHandle=iMA(_Symbol, _Period, InpMAPeriod, 0, MODE_SMA, PRICE_CLOSE); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating Moving Average indicator"); + return(INIT_FAILED); + } + +//--- OK + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { +//--- release indicator handle + IndicatorRelease(ExtIndicatorHandle); + } +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() + { +//--- save the next bar start time; all checks at bar opening only + static datetime next_bar_open=0; + +//--- Phase 1 - check the emergence of a new bar and update the status + if(TimeCurrent()>=next_bar_open) + { + //--- get the current state of environment on the new bar + // namely, set the values of global variables: + // ExtPatternDetected - pattern detection + // ExtConfirmed - pattern confirmation + // ExtSignalOpen - signal to open + // ExtSignalClose - signal to close + // ExtPatternInfo - current pattern information + if(CheckState()) + { + //--- set the new bar opening time + next_bar_open=TimeCurrent(); + next_bar_open-=next_bar_open%PeriodSeconds(_Period); + next_bar_open+=PeriodSeconds(_Period); + + //--- report the emergence of a new bar only once within a bar + if(ExtPatternDetected && ExtConfirmed) + Print(ExtPatternInfo); + } + else + { + //--- error getting the status, retry on the next tick + return; + } + } + +//--- Phase 2 - if there is a signal and no position in this direction + if(ExtSignalOpen && !PositionExist(ExtSignalOpen)) + { + Print("\r\nSignal to open position ", ExtDirection); + PositionOpen(); + if(PositionExist(ExtSignalOpen)) + ExtSignalOpen=SIGNAL_NOT; + } + +//--- Phase 3 - close if there is a signal to close + if(ExtSignalClose && PositionExist(ExtSignalClose)) + { + Print("\r\nSignal to close position ", ExtDirection); + CloseBySignal(ExtSignalClose); + if(!PositionExist(ExtSignalClose)) + ExtSignalClose=SIGNAL_NOT; + } + +//--- Phase 4 - close upon expiration + if(ExtCloseByTime && PositionExpiredByTimeExist()) + { + CloseByTime(); + ExtCloseByTime=PositionExpiredByTimeExist(); + } + } +//+------------------------------------------------------------------+ +//| Get the current environment and check for a pattern | +//+------------------------------------------------------------------+ +bool CheckState() + { +//--- check if there is a pattern + if(!CheckPattern()) + { + Print("Error, failed to check pattern"); + return(false); + } + +//--- check for confirmation + if(!CheckConfirmation()) + { + Print("Error, failed to check pattern confirmation"); + return(false); + } +//--- if there is no confirmation, cancel the signal + if(!ExtConfirmed) + ExtSignalOpen=SIGNAL_NOT; + +//--- check if there is a signal to close a position + if(!CheckCloseSignal()) + { + Print("Error, failed to check the closing signal"); + return(false); + } + +//--- if positions are to be closed after certain holding time in bars + if(InpDuration) + ExtCloseByTime=true; // set flag to close upon expiration + +//--- all checks done + return(true); + } +//+------------------------------------------------------------------+ +//| Open a position in the direction of the signal | +//+------------------------------------------------------------------+ +bool PositionOpen() + { + ExtSymbolInfo.Refresh(); + ExtSymbolInfo.RefreshRates(); + + double price=0; +//--- Stop Loss and Take Profit are not set by default + double stoploss=0.0; + double takeprofit=0.0; + + int digits=ExtSymbolInfo.Digits(); + double point=ExtSymbolInfo.Point(); + double spread=ExtSymbolInfo.Ask()-ExtSymbolInfo.Bid(); + +//--- uptrend + if(ExtSignalOpen==SIGNAL_BUY) + { + price=NormalizeDouble(ExtSymbolInfo.Ask(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price-spread, digits); + } + else + stoploss = NormalizeDouble(price-InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price+spread, digits); + } + else + takeprofit = NormalizeDouble(price+InpTP*point, digits); + } + + if(!ExtTrade.Buy(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s buy %G at %G (sl=%G tp=%G) failed. Ask=%G error=%d", + Symbol(), InpLot, price, stoploss, takeprofit, ExtSymbolInfo.Ask(), GetLastError()); + return(false); + } + } + +//--- downtrend + if(ExtSignalOpen==SIGNAL_SELL) + { + price=NormalizeDouble(ExtSymbolInfo.Bid(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price+spread, digits); + } + else + stoploss = NormalizeDouble(price+InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price-spread, digits); + } + else + takeprofit = NormalizeDouble(price-InpTP*point, digits); + } + + if(!ExtTrade.Sell(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s sell at %G (sl=%G tp=%G) failed. Bid=%G error=%d", + Symbol(), price, stoploss, takeprofit, ExtSymbolInfo.Bid(), GetLastError()); + ExtTrade.PrintResult(); + Print(" "); + return(false); + } + } + + return(true); + } +//+------------------------------------------------------------------+ +//| Close a position based on the specified signal | +//+------------------------------------------------------------------+ +void CloseBySignal(int type_close) + { +//--- if there is no signal to close, return successful completion + if(type_close==SIGNAL_NOT) + return; +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalClose)==0) + return; + +//--- closing direction + long type; + switch(type_close) + { + case CLOSE_SHORT: + type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + type=POSITION_TYPE_BUY; + break; + default: + Print("Error! Signal to close not detected"); + return; + } + +//--- check all positions and close ours based on the signal + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + if(PositionGetInteger(POSITION_TYPE)==type) + { + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Close positions upon holding time expiration in bars | +//+------------------------------------------------------------------+ +void CloseByTime() + { +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalOpen)==0) + return; + +//--- check all positions and close ours based on the holding time in bars + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + //--- position opening time + datetime open_time=(datetime)PositionGetInteger(POSITION_TIME); + //--- check position holding time in bars + if(BarsHold(open_time)>=(int)InpDuration) + { + Print("\r\nTime to close position #", ticket); + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Returns true if there are open positions | +//+------------------------------------------------------------------+ +bool PositionExist(int signal_direction) + { + bool check_type=(signal_direction!=SIGNAL_NOT); + +//--- what positions to search + ENUM_POSITION_TYPE search_type=WRONG_VALUE; + if(check_type) + switch(signal_direction) + { + case SIGNAL_BUY: + search_type=POSITION_TYPE_BUY; + break; + case SIGNAL_SELL: + search_type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + search_type=POSITION_TYPE_BUY; + break; + case CLOSE_SHORT: + search_type=POSITION_TYPE_SELL; + break; + default: + //--- entry direction is not specified; nothing to search + return(false); + } + +//--- go through the list of all positions + int positions=PositionsTotal(); + for(int i=0; i=(int)InpDuration)) + return(true); + } + } + } + +//--- open position not found + return(false); + } +//+------------------------------------------------------------------+ +//| Checks position closing time in bars | +//+------------------------------------------------------------------+ +int BarsHold(datetime open_time) + { +//--- first run a basic simple check + if(TimeCurrent()-open_timeAvgBody(1)) && // the previous candle is bullish, its body is greater than average (long white) + (Close(1)>Open(2)) && // close price of the bearish candle is higher than open price of the bullish candle + (Open(1)CloseAvg(2))) // up trend + { + ExtPatternDetected=true; + ExtSignalOpen=SIGNAL_SELL; + ExtPatternInfo="\r\nBearish Harami detected"; + ExtDirection="Sell"; + return(true); + } + +//--- check Bullish Harami + if((Close(1)>Open(1)) && // the last completed bar is bullish (white day) + ((Open(2)-Close(2))>AvgBody(1)) && // the previous candle is bearish, its body is greater than average (long black) + (Close(1)Close(2)) && // open price of the bullish candle is higher than close price of the bearish candle + (MidPoint(2)50)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: CCI>50"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| Check if there is a signal to close | +//+------------------------------------------------------------------+ +bool CheckCloseSignal() + { + ExtSignalClose=false; +//--- if there is a signal to enter the market, do not check the signal to close + if(ExtSignalOpen!=SIGNAL_NOT) + return(true); + +//--- check if there is a signal to close a long position + if(((CCI(1)<80) && (CCI(2)>80)) || ((CCI(1)<-80) && (CCI(2)>-80))) + { + //--- there is a signal to close a long position + ExtSignalClose=CLOSE_LONG; + ExtDirection="Long"; + } + +//--- check if there is a signal to close a short position + if(((CCI(1)>-80) && (CCI(2)<-80)) || ((CCI(1)>80) && (CCI(2)<80))) + { + //--- there is a signal to close a short position + ExtSignalClose=CLOSE_SHORT; + ExtDirection="Short"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| CCI indicator value at the specified bar | +//+------------------------------------------------------------------+ +double CCI(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtIndicatorHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the CCI indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ +//| SMA value at the specified bar | +//+------------------------------------------------------------------+ +double CloseAvg(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtTrendMAHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the Simple Moving Average indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Experts/Free Robots/BullishBearish Harami MFI.mq5 b/BKPS/14031218/Experts/Free Robots/BullishBearish Harami MFI.mq5 new file mode 100644 index 0000000..ff639f8 --- /dev/null +++ b/BKPS/14031218/Experts/Free Robots/BullishBearish Harami MFI.mq5 @@ -0,0 +1,682 @@ +//+------------------------------------------------------------------+ +//| BullishBearish Harami MFI.mq5 | +//| Copyright 2024, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2024, MetaQuotes Ltd." +#property link "https://www.mql5.com" +#property version "1.00" + +#include +#include + +#define SIGNAL_BUY 1 // Buy signal +#define SIGNAL_NOT 0 // no trading signal +#define SIGNAL_SELL -1 // Sell signal + +#define CLOSE_LONG 2 // signal to close Long +#define CLOSE_SHORT -2 // signal to close Short + +//--- Input parameters +input int InpAverBodyPeriod=12; // period for calculating average candlestick size +input int InpMAPeriod =5; // Trend MA period +input int InpPeriodMFI =37; // MFI period +input ENUM_APPLIED_VOLUME InpVolume=VOLUME_TICK; // volume type + +//--- trade parameters +input uint InpDuration=10; // position holding time in bars +input uint InpSL =200; // Stop Loss in points +input uint InpTP =200; // Take Profit in points +input uint InpSlippage=10; // slippage in points +//--- money management parameters +input double InpLot =0.1; // lot +//--- Expert ID +input long InpMagicNumber=121600; // Magic Number + +//--- global variables +int ExtAvgBodyPeriod; // average candlestick calculation period +int ExtSignalOpen =0; // Buy/Sell signal +int ExtSignalClose =0; // signal to close a position +string ExtPatternInfo =""; // current pattern information +string ExtDirection =""; // position opening direction +bool ExtPatternDetected=false; // pattern detected +bool ExtConfirmed =false; // pattern confirmed +bool ExtCloseByTime =true; // requires closing by time +bool ExtCheckPassed =true; // status checking error + +//--- indicator handles +int ExtIndicatorHandle=INVALID_HANDLE; +int ExtTrendMAHandle =INVALID_HANDLE; + +//--- service objects +CTrade ExtTrade; +CSymbolInfo ExtSymbolInfo; +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { + Print("InpSL=", InpSL); + Print("InpTP=", InpTP); +//--- set parameters for trading operations + ExtTrade.SetDeviationInPoints(InpSlippage); // slippage + ExtTrade.SetExpertMagicNumber(InpMagicNumber); // Expert Advisor ID + ExtTrade.LogLevel(LOG_LEVEL_ERRORS); // logging level + + ExtAvgBodyPeriod=InpAverBodyPeriod; +//--- indicator initialization + ExtIndicatorHandle=iMFI(_Symbol, _Period, InpPeriodMFI, InpVolume); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating MFI indicator"); + return(INIT_FAILED); + } + +//--- trend moving average + ExtTrendMAHandle=iMA(_Symbol, _Period, InpMAPeriod, 0, MODE_SMA, PRICE_CLOSE); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating Moving Average indicator"); + return(INIT_FAILED); + } + +//--- OK + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { +//--- release indicator handle + IndicatorRelease(ExtIndicatorHandle); + } +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() + { +//--- save the next bar start time; all checks at bar opening only + static datetime next_bar_open=0; + +//--- Phase 1 - check the emergence of a new bar and update the status + if(TimeCurrent()>=next_bar_open) + { + //--- get the current state of environment on the new bar + // namely, set the values of global variables: + // ExtPatternDetected - pattern detection + // ExtConfirmed - pattern confirmation + // ExtSignalOpen - signal to open + // ExtSignalClose - signal to close + // ExtPatternInfo - current pattern information + if(CheckState()) + { + //--- set the new bar opening time + next_bar_open=TimeCurrent(); + next_bar_open-=next_bar_open%PeriodSeconds(_Period); + next_bar_open+=PeriodSeconds(_Period); + + //--- report the emergence of a new bar only once within a bar + if(ExtPatternDetected && ExtConfirmed) + Print(ExtPatternInfo); + } + else + { + //--- error getting the status, retry on the next tick + return; + } + } + +//--- Phase 2 - if there is a signal and no position in this direction + if(ExtSignalOpen && !PositionExist(ExtSignalOpen)) + { + Print("\r\nSignal to open position ", ExtDirection); + PositionOpen(); + if(PositionExist(ExtSignalOpen)) + ExtSignalOpen=SIGNAL_NOT; + } + +//--- Phase 3 - close if there is a signal to close + if(ExtSignalClose && PositionExist(ExtSignalClose)) + { + Print("\r\nSignal to close position ", ExtDirection); + CloseBySignal(ExtSignalClose); + if(!PositionExist(ExtSignalClose)) + ExtSignalClose=SIGNAL_NOT; + } + +//--- Phase 4 - close upon expiration + if(ExtCloseByTime && PositionExpiredByTimeExist()) + { + CloseByTime(); + ExtCloseByTime=PositionExpiredByTimeExist(); + } + } +//+------------------------------------------------------------------+ +//| Get the current environment and check for a pattern | +//+------------------------------------------------------------------+ +bool CheckState() + { +//--- check if there is a pattern + if(!CheckPattern()) + { + Print("Error, failed to check pattern"); + return(false); + } + +//--- check for confirmation + if(!CheckConfirmation()) + { + Print("Error, failed to check pattern confirmation"); + return(false); + } +//--- if there is no confirmation, cancel the signal + if(!ExtConfirmed) + ExtSignalOpen=SIGNAL_NOT; + +//--- check if there is a signal to close a position + if(!CheckCloseSignal()) + { + Print("Error, failed to check the closing signal"); + return(false); + } + +//--- if positions are to be closed after certain holding time in bars + if(InpDuration) + ExtCloseByTime=true; // set flag to close upon expiration + +//--- all checks done + return(true); + } +//+------------------------------------------------------------------+ +//| Open a position in the direction of the signal | +//+------------------------------------------------------------------+ +bool PositionOpen() + { + ExtSymbolInfo.Refresh(); + ExtSymbolInfo.RefreshRates(); + + double price=0; +//--- Stop Loss and Take Profit are not set by default + double stoploss=0.0; + double takeprofit=0.0; + + int digits=ExtSymbolInfo.Digits(); + double point=ExtSymbolInfo.Point(); + double spread=ExtSymbolInfo.Ask()-ExtSymbolInfo.Bid(); + +//--- uptrend + if(ExtSignalOpen==SIGNAL_BUY) + { + price=NormalizeDouble(ExtSymbolInfo.Ask(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price-spread, digits); + } + else + stoploss = NormalizeDouble(price-InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price+spread, digits); + } + else + takeprofit = NormalizeDouble(price+InpTP*point, digits); + } + + if(!ExtTrade.Buy(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s buy %G at %G (sl=%G tp=%G) failed. Ask=%G error=%d", + Symbol(), InpLot, price, stoploss, takeprofit, ExtSymbolInfo.Ask(), GetLastError()); + return(false); + } + } + +//--- downtrend + if(ExtSignalOpen==SIGNAL_SELL) + { + price=NormalizeDouble(ExtSymbolInfo.Bid(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price+spread, digits); + } + else + stoploss = NormalizeDouble(price+InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price-spread, digits); + } + else + takeprofit = NormalizeDouble(price-InpTP*point, digits); + } + + if(!ExtTrade.Sell(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s sell at %G (sl=%G tp=%G) failed. Bid=%G error=%d", + Symbol(), price, stoploss, takeprofit, ExtSymbolInfo.Bid(), GetLastError()); + ExtTrade.PrintResult(); + Print(" "); + return(false); + } + } + + return(true); + } +//+------------------------------------------------------------------+ +//| Close a position based on the specified signal | +//+------------------------------------------------------------------+ +void CloseBySignal(int type_close) + { +//--- if there is no signal to close, return successful completion + if(type_close==SIGNAL_NOT) + return; +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalClose)==0) + return; + +//--- closing direction + long type; + switch(type_close) + { + case CLOSE_SHORT: + type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + type=POSITION_TYPE_BUY; + break; + default: + Print("Error! Signal to close not detected"); + return; + } + +//--- check all positions and close ours based on the signal + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + if(PositionGetInteger(POSITION_TYPE)==type) + { + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Close positions upon holding time expiration in bars | +//+------------------------------------------------------------------+ +void CloseByTime() + { +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalOpen)==0) + return; + +//--- check all positions and close ours based on the holding time in bars + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + //--- position opening time + datetime open_time=(datetime)PositionGetInteger(POSITION_TIME); + //--- check position holding time in bars + if(BarsHold(open_time)>=(int)InpDuration) + { + Print("\r\nTime to close position #", ticket); + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Returns true if there are open positions | +//+------------------------------------------------------------------+ +bool PositionExist(int signal_direction) + { + bool check_type=(signal_direction!=SIGNAL_NOT); + +//--- what positions to search + ENUM_POSITION_TYPE search_type=WRONG_VALUE; + if(check_type) + switch(signal_direction) + { + case SIGNAL_BUY: + search_type=POSITION_TYPE_BUY; + break; + case SIGNAL_SELL: + search_type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + search_type=POSITION_TYPE_BUY; + break; + case CLOSE_SHORT: + search_type=POSITION_TYPE_SELL; + break; + default: + //--- entry direction is not specified; nothing to search + return(false); + } + +//--- go through the list of all positions + int positions=PositionsTotal(); + for(int i=0; i=(int)InpDuration)) + return(true); + } + } + } + +//--- open position not found + return(false); + } +//+------------------------------------------------------------------+ +//| Checks position closing time in bars | +//+------------------------------------------------------------------+ +int BarsHold(datetime open_time) + { +//--- first run a basic simple check + if(TimeCurrent()-open_timeAvgBody(1)) && // the previous candle is bullish, its body is greater than average (long white) + (Close(1)>Open(2)) && // close price of the bearish candle is higher than open price of the bullish candle + (Open(1)CloseAvg(2))) // up trend + { + ExtPatternDetected=true; + ExtSignalOpen=SIGNAL_SELL; + ExtPatternInfo="\r\nBearish Harami detected"; + ExtDirection="Sell"; + return(true); + } + +//--- check Bullish Harami + if((Close(1)>Open(1)) && // the last completed bar is bullish (white day) + ((Open(2)-Close(2))>AvgBody(1)) && // the previous candle is bearish, its body is greater than average (long black) + (Close(1)Close(2)) && // open price of the bullish candle is higher than close price of the bearish candle + (MidPoint(2)60)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: MFI>60"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| Check if there is a signal to close | +//+------------------------------------------------------------------+ +bool CheckCloseSignal() + { + ExtSignalClose=false; +//--- if there is a signal to enter the market, do not check the signal to close + if(ExtSignalOpen!=SIGNAL_NOT) + return(true); + +//--- check if there is a signal to close a long position + if(((MFI(1)<70) && (MFI(2)>70)) || ((MFI(1)<30) && (MFI(2)>30))) + { + //--- there is a signal to close a long position + ExtSignalClose=CLOSE_LONG; + ExtDirection="Long"; + } + +//--- check if there is a signal to close a short position + if(((MFI(1)>30) && (MFI(2)<30)) || ((MFI(1)>70) && (MFI(2)<70))) + { + //--- there is a signal to close a short position + ExtSignalClose=CLOSE_SHORT; + ExtDirection="Short"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| MFI indicator value at the specified bar | +//+------------------------------------------------------------------+ +double MFI(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtIndicatorHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the MFI indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ +//| SMA value at the specified bar | +//+------------------------------------------------------------------+ +double CloseAvg(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtTrendMAHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the Simple Moving Average indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Experts/Free Robots/BullishBearish Harami RSI.mq5 b/BKPS/14031218/Experts/Free Robots/BullishBearish Harami RSI.mq5 new file mode 100644 index 0000000..cf4082a --- /dev/null +++ b/BKPS/14031218/Experts/Free Robots/BullishBearish Harami RSI.mq5 @@ -0,0 +1,682 @@ +//+------------------------------------------------------------------+ +//| BullishBearish Harami RSI.mq5 | +//| Copyright 2024, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2024, MetaQuotes Ltd." +#property link "https://www.mql5.com" +#property version "1.00" + +#include +#include + +#define SIGNAL_BUY 1 // Buy signal +#define SIGNAL_NOT 0 // no trading signal +#define SIGNAL_SELL -1 // Sell signal + +#define CLOSE_LONG 2 // signal to close Long +#define CLOSE_SHORT -2 // signal to close Short + +//--- Input parameters +input int InpAverBodyPeriod=12; // period for calculating average candlestick size +input int InpMAPeriod =5; // Trend MA period +input int InpPeriodRSI =37; // RSI period +input ENUM_APPLIED_PRICE InpPrice=PRICE_CLOSE; // price type + +//--- trade parameters +input uint InpDuration=10; // position holding time in bars +input uint InpSL =200; // Stop Loss in points +input uint InpTP =200; // Take Profit in points +input uint InpSlippage=10; // slippage in points +//--- money management parameters +input double InpLot =0.1; // lot +//--- Expert ID +input long InpMagicNumber=121300; // Magic Number + +//--- global variables +int ExtAvgBodyPeriod; // average candlestick calculation period +int ExtSignalOpen =0; // Buy/Sell signal +int ExtSignalClose =0; // signal to close a position +string ExtPatternInfo =""; // current pattern information +string ExtDirection =""; // position opening direction +bool ExtPatternDetected=false; // pattern detected +bool ExtConfirmed =false; // pattern confirmed +bool ExtCloseByTime =true; // requires closing by time +bool ExtCheckPassed =true; // status checking error + +//--- indicator handles +int ExtIndicatorHandle=INVALID_HANDLE; +int ExtTrendMAHandle =INVALID_HANDLE; + +//--- service objects +CTrade ExtTrade; +CSymbolInfo ExtSymbolInfo; +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { + Print("InpSL=", InpSL); + Print("InpTP=", InpTP); +//--- set parameters for trading operations + ExtTrade.SetDeviationInPoints(InpSlippage); // slippage + ExtTrade.SetExpertMagicNumber(InpMagicNumber); // Expert Advisor ID + ExtTrade.LogLevel(LOG_LEVEL_ERRORS); // logging level + + ExtAvgBodyPeriod=InpAverBodyPeriod; +//--- indicator initialization + ExtIndicatorHandle=iRSI(_Symbol, _Period, InpPeriodRSI, InpPrice); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating CCI indicator"); + return(INIT_FAILED); + } + +//--- trend moving average + ExtTrendMAHandle=iMA(_Symbol, _Period, InpMAPeriod, 0, MODE_SMA, PRICE_CLOSE); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating Moving Average indicator"); + return(INIT_FAILED); + } + +//--- OK + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { +//--- release indicator handle + IndicatorRelease(ExtIndicatorHandle); + } +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() + { +//--- save the next bar start time; all checks at bar opening only + static datetime next_bar_open=0; + +//--- Phase 1 - check the emergence of a new bar and update the status + if(TimeCurrent()>=next_bar_open) + { + //--- get the current state of environment on the new bar + // namely, set the values of global variables: + // ExtPatternDetected - pattern detection + // ExtConfirmed - pattern confirmation + // ExtSignalOpen - signal to open + // ExtSignalClose - signal to close + // ExtPatternInfo - current pattern information + if(CheckState()) + { + //--- set the new bar opening time + next_bar_open=TimeCurrent(); + next_bar_open-=next_bar_open%PeriodSeconds(_Period); + next_bar_open+=PeriodSeconds(_Period); + + //--- report the emergence of a new bar only once within a bar + if(ExtPatternDetected && ExtConfirmed) + Print(ExtPatternInfo); + } + else + { + //--- error getting the status, retry on the next tick + return; + } + } + +//--- Phase 2 - if there is a signal and no position in this direction + if(ExtSignalOpen && !PositionExist(ExtSignalOpen)) + { + Print("\r\nSignal to open position ", ExtDirection); + PositionOpen(); + if(PositionExist(ExtSignalOpen)) + ExtSignalOpen=SIGNAL_NOT; + } + +//--- Phase 3 - close if there is a signal to close + if(ExtSignalClose && PositionExist(ExtSignalClose)) + { + Print("\r\nSignal to close position ", ExtDirection); + CloseBySignal(ExtSignalClose); + if(!PositionExist(ExtSignalClose)) + ExtSignalClose=SIGNAL_NOT; + } + +//--- Phase 4 - close upon expiration + if(ExtCloseByTime && PositionExpiredByTimeExist()) + { + CloseByTime(); + ExtCloseByTime=PositionExpiredByTimeExist(); + } + } +//+------------------------------------------------------------------+ +//| Get the current environment and check for a pattern | +//+------------------------------------------------------------------+ +bool CheckState() + { +//--- check if there is a pattern + if(!CheckPattern()) + { + Print("Error, failed to check pattern"); + return(false); + } + +//--- check for confirmation + if(!CheckConfirmation()) + { + Print("Error, failed to check pattern confirmation"); + return(false); + } +//--- if there is no confirmation, cancel the signal + if(!ExtConfirmed) + ExtSignalOpen=SIGNAL_NOT; + +//--- check if there is a signal to close a position + if(!CheckCloseSignal()) + { + Print("Error, failed to check the closing signal"); + return(false); + } + +//--- if positions are to be closed after certain holding time in bars + if(InpDuration) + ExtCloseByTime=true; // set flag to close upon expiration + +//--- all checks done + return(true); + } +//+------------------------------------------------------------------+ +//| Open a position in the direction of the signal | +//+------------------------------------------------------------------+ +bool PositionOpen() + { + ExtSymbolInfo.Refresh(); + ExtSymbolInfo.RefreshRates(); + + double price=0; +//--- Stop Loss and Take Profit are not set by default + double stoploss=0.0; + double takeprofit=0.0; + + int digits=ExtSymbolInfo.Digits(); + double point=ExtSymbolInfo.Point(); + double spread=ExtSymbolInfo.Ask()-ExtSymbolInfo.Bid(); + +//--- uptrend + if(ExtSignalOpen==SIGNAL_BUY) + { + price=NormalizeDouble(ExtSymbolInfo.Ask(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price-spread, digits); + } + else + stoploss = NormalizeDouble(price-InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price+spread, digits); + } + else + takeprofit = NormalizeDouble(price+InpTP*point, digits); + } + + if(!ExtTrade.Buy(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s buy %G at %G (sl=%G tp=%G) failed. Ask=%G error=%d", + Symbol(), InpLot, price, stoploss, takeprofit, ExtSymbolInfo.Ask(), GetLastError()); + return(false); + } + } + +//--- downtrend + if(ExtSignalOpen==SIGNAL_SELL) + { + price=NormalizeDouble(ExtSymbolInfo.Bid(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price+spread, digits); + } + else + stoploss = NormalizeDouble(price+InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price-spread, digits); + } + else + takeprofit = NormalizeDouble(price-InpTP*point, digits); + } + + if(!ExtTrade.Sell(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s sell at %G (sl=%G tp=%G) failed. Bid=%G error=%d", + Symbol(), price, stoploss, takeprofit, ExtSymbolInfo.Bid(), GetLastError()); + ExtTrade.PrintResult(); + Print(" "); + return(false); + } + } + + return(true); + } +//+------------------------------------------------------------------+ +//| Close a position based on the specified signal | +//+------------------------------------------------------------------+ +void CloseBySignal(int type_close) + { +//--- if there is no signal to close, return successful completion + if(type_close==SIGNAL_NOT) + return; +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalClose)==0) + return; + +//--- closing direction + long type; + switch(type_close) + { + case CLOSE_SHORT: + type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + type=POSITION_TYPE_BUY; + break; + default: + Print("Error! Signal to close not detected"); + return; + } + +//--- check all positions and close ours based on the signal + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + if(PositionGetInteger(POSITION_TYPE)==type) + { + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Close positions upon holding time expiration in bars | +//+------------------------------------------------------------------+ +void CloseByTime() + { +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalOpen)==0) + return; + +//--- check all positions and close ours based on the holding time in bars + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + //--- position opening time + datetime open_time=(datetime)PositionGetInteger(POSITION_TIME); + //--- check position holding time in bars + if(BarsHold(open_time)>=(int)InpDuration) + { + Print("\r\nTime to close position #", ticket); + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Returns true if there are open positions | +//+------------------------------------------------------------------+ +bool PositionExist(int signal_direction) + { + bool check_type=(signal_direction!=SIGNAL_NOT); + +//--- what positions to search + ENUM_POSITION_TYPE search_type=WRONG_VALUE; + if(check_type) + switch(signal_direction) + { + case SIGNAL_BUY: + search_type=POSITION_TYPE_BUY; + break; + case SIGNAL_SELL: + search_type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + search_type=POSITION_TYPE_BUY; + break; + case CLOSE_SHORT: + search_type=POSITION_TYPE_SELL; + break; + default: + //--- entry direction is not specified; nothing to search + return(false); + } + +//--- go through the list of all positions + int positions=PositionsTotal(); + for(int i=0; i=(int)InpDuration)) + return(true); + } + } + } + +//--- open position not found + return(false); + } +//+------------------------------------------------------------------+ +//| Checks position closing time in bars | +//+------------------------------------------------------------------+ +int BarsHold(datetime open_time) + { +//--- first run a basic simple check + if(TimeCurrent()-open_timeAvgBody(1)) && // the previous candle is bullish, its body is greater than average (long white) + (Close(1)>Open(2)) && // close price of the bearish candle is higher than open price of the bullish candle + (Open(1)CloseAvg(2))) // up trend + { + ExtPatternDetected=true; + ExtSignalOpen=SIGNAL_SELL; + ExtPatternInfo="\r\nBearish Harami detected"; + ExtDirection="Sell"; + return(true); + } + +//--- check Bullish Harami + if((Close(1)>Open(1)) && // the last completed bar is bullish (white day) + ((Open(2)-Close(2))>AvgBody(1)) && // the previous candle is bearish, its body is greater than average (long black) + (Close(1)Close(2)) && // open price of the bullish candle is higher than close price of the bearish candle + (MidPoint(2)60)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: RSI>60"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| Check if there is a signal to close | +//+------------------------------------------------------------------+ +bool CheckCloseSignal() + { + ExtSignalClose=false; +//--- if there is a signal to enter the market, do not check the signal to close + if(ExtSignalOpen!=SIGNAL_NOT) + return(true); + +//--- check if there is a signal to close a long position + if(((RSI(1)<70) && (RSI(2)>70)) || ((RSI(1)<30) && (RSI(2)>30))) + { + //--- there is a signal to close a long position + ExtSignalClose=CLOSE_LONG; + ExtDirection="Long"; + } + +//--- check if there is a signal to close a short position + if(((RSI(1)>30) && (RSI(2)<30)) || ((RSI(1)>70) && (RSI(2)<70))) + { + //--- there is a signal to close a short position + ExtSignalClose=CLOSE_SHORT; + ExtDirection="Short"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| RSI indicator value at the specified bar | +//+------------------------------------------------------------------+ +double RSI(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtIndicatorHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the RSI indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ +//| SMA value at the specified bar | +//+------------------------------------------------------------------+ +double CloseAvg(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtTrendMAHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the Simple Moving Average indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Experts/Free Robots/BullishBearish Harami Stoch.mq5 b/BKPS/14031218/Experts/Free Robots/BullishBearish Harami Stoch.mq5 new file mode 100644 index 0000000..10c4b8a --- /dev/null +++ b/BKPS/14031218/Experts/Free Robots/BullishBearish Harami Stoch.mq5 @@ -0,0 +1,685 @@ +//+------------------------------------------------------------------+ +//| BullishBearish Harami Stoch.mq5 | +//| Copyright 2024, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2024, MetaQuotes Ltd." +#property link "https://www.mql5.com" +#property version "1.00" + +#include +#include + +#define SIGNAL_BUY 1 // Buy signal +#define SIGNAL_NOT 0 // no trading signal +#define SIGNAL_SELL -1 // Sell signal + +#define CLOSE_LONG 2 // signal to close Long +#define CLOSE_SHORT -2 // signal to close Short + +//--- Input parameters +input int InpAverBodyPeriod=12; // period for calculating average candlestick size +input int InpMAPeriod =5; // Trend MA period +input int InpStochK =47; // period %K +input int InpStochD =9; // period %D +input int InpStochSlow =13; // smoothing period %K +input ENUM_STO_PRICE InpStochApplied=STO_LOWHIGH; // calculation type +input ENUM_MA_METHOD InpStochMA =MODE_SMA; // smoothing type + +//--- trade parameters +input uint InpDuration=10; // position holding time in bars +input uint InpSL =200; // Stop Loss in points +input uint InpTP =200; // Take Profit in points +input uint InpSlippage=10; // slippage in points +//--- money management parameters +input double InpLot =0.1; // lot +//--- Expert ID +input long InpMagicNumber=122400; // Magic Number + +//--- global variables +int ExtAvgBodyPeriod; // average candlestick calculation period +int ExtSignalOpen =0; // Buy/Sell signal +int ExtSignalClose =0; // signal to close a position +string ExtPatternInfo =""; // current pattern information +string ExtDirection =""; // position opening direction +bool ExtPatternDetected=false; // pattern detected +bool ExtConfirmed =false; // pattern confirmed +bool ExtCloseByTime =true; // requires closing by time +bool ExtCheckPassed =true; // status checking error + +//--- indicator handles +int ExtIndicatorHandle=INVALID_HANDLE; +int ExtTrendMAHandle =INVALID_HANDLE; + +//--- service objects +CTrade ExtTrade; +CSymbolInfo ExtSymbolInfo; +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { + Print("InpSL=", InpSL); + Print("InpTP=", InpTP); +//--- set parameters for trading operations + ExtTrade.SetDeviationInPoints(InpSlippage); // slippage + ExtTrade.SetExpertMagicNumber(InpMagicNumber); // Expert Advisor ID + ExtTrade.LogLevel(LOG_LEVEL_ERRORS); // logging level + + ExtAvgBodyPeriod=InpAverBodyPeriod; +//--- indicator initialization + ExtIndicatorHandle=iStochastic(_Symbol, _Period, InpStochK, InpStochD, InpStochSlow, InpStochMA, InpStochApplied); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating iStochastic indicator"); + return(INIT_FAILED); + } + +//--- trend moving average + ExtTrendMAHandle=iMA(_Symbol, _Period, InpMAPeriod, 0, MODE_SMA, PRICE_CLOSE); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating Moving Average indicator"); + return(INIT_FAILED); + } + +//--- OK + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { +//--- release indicator handle + IndicatorRelease(ExtIndicatorHandle); + } +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() + { +//--- save the next bar start time; all checks at bar opening only + static datetime next_bar_open=0; + +//--- Phase 1 - check the emergence of a new bar and update the status + if(TimeCurrent()>=next_bar_open) + { + //--- get the current state of environment on the new bar + // namely, set the values of global variables: + // ExtPatternDetected - pattern detection + // ExtConfirmed - pattern confirmation + // ExtSignalOpen - signal to open + // ExtSignalClose - signal to close + // ExtPatternInfo - current pattern information + if(CheckState()) + { + //--- set the new bar opening time + next_bar_open=TimeCurrent(); + next_bar_open-=next_bar_open%PeriodSeconds(_Period); + next_bar_open+=PeriodSeconds(_Period); + + //--- report the emergence of a new bar only once within a bar + if(ExtPatternDetected && ExtConfirmed) + Print(ExtPatternInfo); + } + else + { + //--- error getting the status, retry on the next tick + return; + } + } + +//--- Phase 2 - if there is a signal and no position in this direction + if(ExtSignalOpen && !PositionExist(ExtSignalOpen)) + { + Print("\r\nSignal to open position ", ExtDirection); + PositionOpen(); + if(PositionExist(ExtSignalOpen)) + ExtSignalOpen=SIGNAL_NOT; + } + +//--- Phase 3 - close if there is a signal to close + if(ExtSignalClose && PositionExist(ExtSignalClose)) + { + Print("\r\nSignal to close position ", ExtDirection); + CloseBySignal(ExtSignalClose); + if(!PositionExist(ExtSignalClose)) + ExtSignalClose=SIGNAL_NOT; + } + +//--- Phase 4 - close upon expiration + if(ExtCloseByTime && PositionExpiredByTimeExist()) + { + CloseByTime(); + ExtCloseByTime=PositionExpiredByTimeExist(); + } + } +//+------------------------------------------------------------------+ +//| Get the current environment and check for a pattern | +//+------------------------------------------------------------------+ +bool CheckState() + { +//--- check if there is a pattern + if(!CheckPattern()) + { + Print("Error, failed to check pattern"); + return(false); + } + +//--- check for confirmation + if(!CheckConfirmation()) + { + Print("Error, failed to check pattern confirmation"); + return(false); + } +//--- if there is no confirmation, cancel the signal + if(!ExtConfirmed) + ExtSignalOpen=SIGNAL_NOT; + +//--- check if there is a signal to close a position + if(!CheckCloseSignal()) + { + Print("Error, failed to check the closing signal"); + return(false); + } + +//--- if positions are to be closed after certain holding time in bars + if(InpDuration) + ExtCloseByTime=true; // set flag to close upon expiration + +//--- all checks done + return(true); + } +//+------------------------------------------------------------------+ +//| Open a position in the direction of the signal | +//+------------------------------------------------------------------+ +bool PositionOpen() + { + ExtSymbolInfo.Refresh(); + ExtSymbolInfo.RefreshRates(); + + double price=0; +//--- Stop Loss and Take Profit are not set by default + double stoploss=0.0; + double takeprofit=0.0; + + int digits=ExtSymbolInfo.Digits(); + double point=ExtSymbolInfo.Point(); + double spread=ExtSymbolInfo.Ask()-ExtSymbolInfo.Bid(); + +//--- uptrend + if(ExtSignalOpen==SIGNAL_BUY) + { + price=NormalizeDouble(ExtSymbolInfo.Ask(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price-spread, digits); + } + else + stoploss = NormalizeDouble(price-InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price+spread, digits); + } + else + takeprofit = NormalizeDouble(price+InpTP*point, digits); + } + + if(!ExtTrade.Buy(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s buy %G at %G (sl=%G tp=%G) failed. Ask=%G error=%d", + Symbol(), InpLot, price, stoploss, takeprofit, ExtSymbolInfo.Ask(), GetLastError()); + return(false); + } + } +//--- downtrend + if(ExtSignalOpen==SIGNAL_SELL) + { + price=NormalizeDouble(ExtSymbolInfo.Bid(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price+spread, digits); + } + else + stoploss = NormalizeDouble(price+InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price-spread, digits); + } + else + takeprofit = NormalizeDouble(price-InpTP*point, digits); + } + + if(!ExtTrade.Sell(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s sell at %G (sl=%G tp=%G) failed. Bid=%G error=%d", + Symbol(), price, stoploss, takeprofit, ExtSymbolInfo.Bid(), GetLastError()); + ExtTrade.PrintResult(); + Print(" "); + return(false); + } + } + + return(true); + } +//+------------------------------------------------------------------+ +//| Close a position based on the specified signal | +//+------------------------------------------------------------------+ +void CloseBySignal(int type_close) + { +//--- if there is no signal to close, return successful completion + if(type_close==SIGNAL_NOT) + return; +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalClose)==0) + return; + +//--- closing direction + long type; + switch(type_close) + { + case CLOSE_SHORT: + type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + type=POSITION_TYPE_BUY; + break; + default: + Print("Error! Signal to close not detected"); + return; + } + +//--- check all positions and close ours based on the signal + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + if(PositionGetInteger(POSITION_TYPE)==type) + { + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Close positions upon holding time expiration in bars | +//+------------------------------------------------------------------+ +void CloseByTime() + { +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalOpen)==0) + return; + +//--- check all positions and close ours based on the holding time in bars + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + //--- position opening time + datetime open_time=(datetime)PositionGetInteger(POSITION_TIME); + //--- check position holding time in bars + if(BarsHold(open_time)>=(int)InpDuration) + { + Print("\r\nTime to close position #", ticket); + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Returns true if there are open positions | +//+------------------------------------------------------------------+ +bool PositionExist(int signal_direction) + { + bool check_type=(signal_direction!=SIGNAL_NOT); + +//--- what positions to search + ENUM_POSITION_TYPE search_type=WRONG_VALUE; + if(check_type) + switch(signal_direction) + { + case SIGNAL_BUY: + search_type=POSITION_TYPE_BUY; + break; + case SIGNAL_SELL: + search_type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + search_type=POSITION_TYPE_BUY; + break; + case CLOSE_SHORT: + search_type=POSITION_TYPE_SELL; + break; + default: + //--- entry direction is not specified; nothing to search + return(false); + } + +//--- go through the list of all positions + int positions=PositionsTotal(); + for(int i=0; i=(int)InpDuration)) + return(true); + } + } + } +//--- open position not found + return(false); + } + +//+------------------------------------------------------------------+ +//| Checks position closing time in bars | +//+------------------------------------------------------------------+ +int BarsHold(datetime open_time) + { +//--- first run a basic simple check + if(TimeCurrent()-open_timeAvgBody(1)) && // the previous candle is bullish, its body is greater than average (long white) + (Close(1)>Open(2)) && // close price of the bearish candle is higher than open price of the bullish candle + (Open(1)CloseAvg(2))) // up trend + { + ExtPatternDetected=true; + ExtSignalOpen=SIGNAL_SELL; + ExtPatternInfo="\r\nBearish Harami detected"; + ExtDirection="Sell"; + return(true); + } + +//--- check Bullish Harami + if((Close(1)>Open(1)) && // the last completed bar is bullish (white day) + ((Open(2)-Close(2))>AvgBody(1)) && // the previous candle is bearish, its body is greater than average (long black) + (Close(1)Close(2)) && // open price of the bullish candle is higher than close price of the bearish candle + (MidPoint(2)70)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: StochSignal>70"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| Check if there is a signal to close | +//+------------------------------------------------------------------+ +bool CheckCloseSignal() + { + ExtSignalClose=false; +//--- if there is a signal to enter the market, do not check the signal to close + if(ExtSignalOpen!=SIGNAL_NOT) + return(true); + +//--- check if there is a signal to close a long position + if(((StochSignal(1)<80) && (StochSignal(2)>80))|| // 80 crossed downwards + ((StochSignal(1)<20) && (StochSignal(2)>20))) // 20 crossed downwards + { + //--- there is a signal to close a long position + ExtSignalClose=CLOSE_LONG; + ExtDirection="Long"; + } + +//--- check if there is a signal to close a short position + if((((StochSignal(1)>20) && (StochSignal(2)<20)) || // 20 crossed upwards + ((StochSignal(1)>80) && (StochSignal(2)<80)))) // 80 crossed upwards + { + //--- there is a signal to close a short position + ExtSignalClose=CLOSE_SHORT; + ExtDirection="Short"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| Stochastic indicator value at the specified bar | +//+------------------------------------------------------------------+ +double StochSignal(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtIndicatorHandle, SIGNAL_LINE, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the iStochastic indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ +//| SMA value at the specified bar | +//+------------------------------------------------------------------+ +double CloseAvg(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtTrendMAHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the Simple Moving Average indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Experts/Free Robots/BullishBearish MeetingLines CCI.mq5 b/BKPS/14031218/Experts/Free Robots/BullishBearish MeetingLines CCI.mq5 new file mode 100644 index 0000000..761f926 --- /dev/null +++ b/BKPS/14031218/Experts/Free Robots/BullishBearish MeetingLines CCI.mq5 @@ -0,0 +1,654 @@ +//+------------------------------------------------------------------+ +//| BullishBearish MeetingLines CCI.mq5 | +//| Copyright 2024, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2024, MetaQuotes Ltd." +#property link "https://www.mql5.com" +#property version "1.00" + +#include +#include + +#define SIGNAL_BUY 1 // Buy signal +#define SIGNAL_NOT 0 // no trading signal +#define SIGNAL_SELL -1 // Sell signal + +#define CLOSE_LONG 2 // signal to close Long +#define CLOSE_SHORT -2 // signal to close Short + +//--- Input parameters +input int InpAverBodyPeriod=12; // period for calculating average candlestick size +input int InpPeriodCCI =37; // CCI period +input ENUM_APPLIED_PRICE InpPrice=PRICE_CLOSE; // price type + +//--- trade parameters +input uint InpDuration=10; // position holding time in bars +input uint InpSL =200; // Stop Loss in points +input uint InpTP =200; // Take Profit in points +input uint InpSlippage=10; // slippage in points +//--- money management parameters +input double InpLot =0.1; // lot +//--- Expert ID +input long InpMagicNumber=123100; // Magic Number + +//--- global variables +int ExtAvgBodyPeriod; // average candlestick calculation period +int ExtSignalOpen =0; // Buy/Sell signal +int ExtSignalClose =0; // signal to close a position +string ExtPatternInfo =""; // current pattern information +string ExtDirection =""; // position opening direction +bool ExtPatternDetected=false; // pattern detected +bool ExtConfirmed =false; // pattern confirmed +bool ExtCloseByTime =true; // requires closing by time +bool ExtCheckPassed =true; // status checking error + +//--- indicator handle +int ExtIndicatorHandle=INVALID_HANDLE; + +//--- service objects +CTrade ExtTrade; +CSymbolInfo ExtSymbolInfo; +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { + Print("InpSL=", InpSL); + Print("InpTP=", InpTP); +//--- set parameters for trading operations + ExtTrade.SetDeviationInPoints(InpSlippage); // slippage + ExtTrade.SetExpertMagicNumber(InpMagicNumber); // Expert Advisor ID + ExtTrade.LogLevel(LOG_LEVEL_ERRORS); // logging level + + ExtAvgBodyPeriod=InpAverBodyPeriod; +//--- indicator initialization + ExtIndicatorHandle=iCCI(_Symbol, _Period, InpPeriodCCI, InpPrice); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating CCI indicator"); + return(INIT_FAILED); + } +//--- OK + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { +//--- release indicator handle + IndicatorRelease(ExtIndicatorHandle); + } +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() + { +//--- save the next bar start time; all checks at bar opening only + static datetime next_bar_open=0; + +//--- Phase 1 - check the emergence of a new bar and update the status + if(TimeCurrent()>=next_bar_open) + { + //--- get the current state of environment on the new bar + // namely, set the values of global variables: + // ExtPatternDetected - pattern detection + // ExtConfirmed - pattern confirmation + // ExtSignalOpen - signal to open + // ExtSignalClose - signal to close + // ExtPatternInfo - current pattern information + if(CheckState()) + { + //--- set the new bar opening time + next_bar_open=TimeCurrent(); + next_bar_open-=next_bar_open%PeriodSeconds(_Period); + next_bar_open+=PeriodSeconds(_Period); + + //--- report the emergence of a new bar only once within a bar + if(ExtPatternDetected && ExtConfirmed) + Print(ExtPatternInfo); + } + else + { + //--- error getting the status, retry on the next tick + return; + } + } + +//--- Phase 2 - if there is a signal and no position in this direction + if(ExtSignalOpen && !PositionExist(ExtSignalOpen)) + { + Print("\r\nSignal to open position ", ExtDirection); + PositionOpen(); + if(PositionExist(ExtSignalOpen)) + ExtSignalOpen=SIGNAL_NOT; + } + +//--- Phase 3 - close if there is a signal to close + if(ExtSignalClose && PositionExist(ExtSignalClose)) + { + Print("\r\nSignal to close position ", ExtDirection); + CloseBySignal(ExtSignalClose); + if(!PositionExist(ExtSignalClose)) + ExtSignalClose=SIGNAL_NOT; + } + +//--- Phase 4 - close upon expiration + if(ExtCloseByTime && PositionExpiredByTimeExist()) + { + CloseByTime(); + ExtCloseByTime=PositionExpiredByTimeExist(); + } + } +//+------------------------------------------------------------------+ +//| Get the current environment and check for a pattern | +//+------------------------------------------------------------------+ +bool CheckState() + { +//--- check if there is a pattern + if(!CheckPattern()) + { + Print("Error, failed to check pattern"); + return(false); + } + +//--- check for confirmation + if(!CheckConfirmation()) + { + Print("Error, failed to check pattern confirmation"); + return(false); + } +//--- if there is no confirmation, cancel the signal + if(!ExtConfirmed) + ExtSignalOpen=SIGNAL_NOT; + +//--- check if there is a signal to close a position + if(!CheckCloseSignal()) + { + Print("Error, failed to check the closing signal"); + return(false); + } + +//--- if positions are to be closed after certain holding time in bars + if(InpDuration) + ExtCloseByTime=true; // set flag to close upon expiration + +//--- all checks done + return(true); + } +//+------------------------------------------------------------------+ +//| Open a position in the direction of the signal | +//+------------------------------------------------------------------+ +bool PositionOpen() + { + ExtSymbolInfo.Refresh(); + ExtSymbolInfo.RefreshRates(); + + double price=0; +//--- Stop Loss and Take Profit are not set by default + double stoploss=0.0; + double takeprofit=0.0; + + int digits=ExtSymbolInfo.Digits(); + double point=ExtSymbolInfo.Point(); + double spread=ExtSymbolInfo.Ask()-ExtSymbolInfo.Bid(); + +//--- uptrend + if(ExtSignalOpen==SIGNAL_BUY) + { + price=NormalizeDouble(ExtSymbolInfo.Ask(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price-spread, digits); + } + else + stoploss = NormalizeDouble(price-InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price+spread, digits); + } + else + takeprofit = NormalizeDouble(price+InpTP*point, digits); + } + + if(!ExtTrade.Buy(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s buy %G at %G (sl=%G tp=%G) failed. Ask=%G error=%d", + Symbol(), InpLot, price, stoploss, takeprofit, ExtSymbolInfo.Ask(), GetLastError()); + return(false); + } + } + +//--- downtrend + if(ExtSignalOpen==SIGNAL_SELL) + { + price=NormalizeDouble(ExtSymbolInfo.Bid(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price+spread, digits); + } + else + stoploss = NormalizeDouble(price+InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price-spread, digits); + } + else + takeprofit = NormalizeDouble(price-InpTP*point, digits); + } + + if(!ExtTrade.Sell(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s sell at %G (sl=%G tp=%G) failed. Bid=%G error=%d", + Symbol(), price, stoploss, takeprofit, ExtSymbolInfo.Bid(), GetLastError()); + ExtTrade.PrintResult(); + Print(" "); + return(false); + } + } + + return(true); + } +//+------------------------------------------------------------------+ +//| Close a position based on the specified signal | +//+------------------------------------------------------------------+ +void CloseBySignal(int type_close) + { +//--- if there is no signal to close, return successful completion + if(type_close==SIGNAL_NOT) + return; +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalClose)==0) + return; + +//--- closing direction + long type; + switch(type_close) + { + case CLOSE_SHORT: + type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + type=POSITION_TYPE_BUY; + break; + default: + Print("Error! Signal to close not detected"); + return; + } + +//--- check all positions and close ours based on the signal + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + if(PositionGetInteger(POSITION_TYPE)==type) + { + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Close positions upon holding time expiration in bars | +//+------------------------------------------------------------------+ +void CloseByTime() + { +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalOpen)==0) + return; + +//--- check all positions and close ours based on the holding time in bars + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + //--- position opening time + datetime open_time=(datetime)PositionGetInteger(POSITION_TIME); + //--- check position holding time in bars + if(BarsHold(open_time)>=(int)InpDuration) + { + Print("\r\nTime to close position #", ticket); + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Returns true if there are open positions | +//+------------------------------------------------------------------+ +bool PositionExist(int signal_direction) + { + bool check_type=(signal_direction!=SIGNAL_NOT); + +//--- what positions to search + ENUM_POSITION_TYPE search_type=WRONG_VALUE; + if(check_type) + switch(signal_direction) + { + case SIGNAL_BUY: + search_type=POSITION_TYPE_BUY; + break; + case SIGNAL_SELL: + search_type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + search_type=POSITION_TYPE_BUY; + break; + case CLOSE_SHORT: + search_type=POSITION_TYPE_SELL; + break; + default: + //--- entry direction is not specified; nothing to search + return(false); + } + +//--- go through the list of all positions + int positions=PositionsTotal(); + for(int i=0; i=(int)InpDuration)) + return(true); + } + } + } + +//--- open position not found + return(false); + } +//+------------------------------------------------------------------+ +//| Checks position closing time in bars | +//+------------------------------------------------------------------+ +int BarsHold(datetime open_time) + { +//--- first run a basic simple check + if(TimeCurrent()-open_timeAvgBody(1)) && // long white candle + ((Open(1)-Close(1))>AvgBody(1)) && // long black candle + (MathAbs(Close(1)-Close(2))<0.1*AvgBody(1))) // doji close + { + ExtPatternDetected=true; + ExtSignalOpen=SIGNAL_SELL; + ExtPatternInfo="\r\nBearish MeetingLines detected"; + ExtDirection="Sell"; + return(true); + } + +//--- check Bullish MeetingLines + if((Open(2)-Close(2)>AvgBody(1)) && // long black candle + ((Close(1)-Open(1))>AvgBody(1)) && // long white candle + (MathAbs(Close(1)-Close(2))<0.1*AvgBody(1))) // doji close + { + ExtPatternDetected=true; + ExtSignalOpen=SIGNAL_BUY; + ExtPatternInfo="\r\nBullish MeetingLines detected"; + ExtDirection="Buy"; + return(true); + } + +//--- result of checking + return(ExtCheckPassed); + } + +//+------------------------------------------------------------------+ +//| Returns true in case of successful confirmation check | +//+------------------------------------------------------------------+ +bool CheckConfirmation() + { + ExtConfirmed=false; +//--- if there is no pattern, do not search for confirmation + if(!ExtPatternDetected) + return(true); + +//--- get the value of the stochastic indicator to confirm the signal + double signal=CCI(1); + if(signal==EMPTY_VALUE) + { + //--- failed to get indicator value, check failed + return(false); + } + +//--- check the Buy signal + if(ExtSignalOpen==SIGNAL_BUY && (signal<-50)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: CCI<-50"; + } + +//--- check the Sell signal + if(ExtSignalOpen==SIGNAL_SELL && (signal>50)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: CCI>50"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| Check if there is a signal to close | +//+------------------------------------------------------------------+ +bool CheckCloseSignal() + { + ExtSignalClose=false; +//--- if there is a signal to enter the market, do not check the signal to close + if(ExtSignalOpen!=SIGNAL_NOT) + return(true); + +//--- check if there is a signal to close a long position + if(((CCI(1)<80) && (CCI(2)>80)) || ((CCI(1)<-80) && (CCI(2)>-80))) + { + //--- there is a signal to close a long position + ExtSignalClose=CLOSE_LONG; + ExtDirection="Long"; + } + +//--- check if there is a signal to close a short position + if(((CCI(1)>-80) && (CCI(2)<-80)) || ((CCI(1)>80) && (CCI(2)<80))) + { + //--- there is a signal to close a short position + ExtSignalClose=CLOSE_SHORT; + ExtDirection="Short"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| CCI indicator value at the specified bar | +//+------------------------------------------------------------------+ +double CCI(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtIndicatorHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the CCI indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Experts/Free Robots/BullishBearish MeetingLines MFI.mq5 b/BKPS/14031218/Experts/Free Robots/BullishBearish MeetingLines MFI.mq5 new file mode 100644 index 0000000..375c13d --- /dev/null +++ b/BKPS/14031218/Experts/Free Robots/BullishBearish MeetingLines MFI.mq5 @@ -0,0 +1,652 @@ +//+------------------------------------------------------------------+ +//| BullishBearish MeetingLines MFI.mq5 | +//| Copyright 2024, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2024, MetaQuotes Ltd." +#property link "https://www.mql5.com" +#property version "1.00" + +#include +#include + +#define SIGNAL_BUY 1 // Buy signal +#define SIGNAL_NOT 0 // no trading signal +#define SIGNAL_SELL -1 // Sell signal + +#define CLOSE_LONG 2 // signal to close Long +#define CLOSE_SHORT -2 // signal to close Short + +//--- Input parameters +input int InpAverBodyPeriod=12; // period for calculating average candlestick size +input int InpPeriodMFI =37; // MFI period +input ENUM_APPLIED_VOLUME InpVolume=VOLUME_TICK; // volume type + +//--- trade parameters +input uint InpDuration=10; // position holding time in bars +input uint InpSL =200; // Stop Loss in points +input uint InpTP =200; // Take Profit in points +input uint InpSlippage=10; // slippage in points +//--- money management parameters +input double InpLot=0.1; // lot +//--- Expert ID +input long InpMagicNumber=121200; // Magic Number + +//--- global variables +int ExtAvgBodyPeriod; // average candlestick calculation period +int ExtSignalOpen =0; // Buy/Sell signal +int ExtSignalClose =0; // signal to close a position +string ExtPatternInfo =""; // current pattern information +string ExtDirection =""; // position opening direction +bool ExtPatternDetected=false; // pattern detected +bool ExtConfirmed =false; // pattern confirmed +bool ExtCloseByTime =true; // requires closing by time +bool ExtCheckPassed =true; // status checking error +//--- indicator handle +int ExtIndicatorHandle=INVALID_HANDLE; + +//--- service objects +CTrade ExtTrade; +CSymbolInfo ExtSymbolInfo; +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { + Print("InpSL=", InpSL); + Print("InpTP=", InpTP); +//--- set parameters for trading operations + ExtTrade.SetDeviationInPoints(InpSlippage); // slippage + ExtTrade.SetExpertMagicNumber(InpMagicNumber); // Expert Advisor ID + ExtTrade.LogLevel(LOG_LEVEL_ERRORS); // logging level + + ExtAvgBodyPeriod=InpAverBodyPeriod; +//--- indicator initialization + ExtIndicatorHandle=iMFI(_Symbol, _Period, InpPeriodMFI, InpVolume); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating MFI indicator"); + return(INIT_FAILED); + } +//--- OK + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { +//--- release indicator handle + IndicatorRelease(ExtIndicatorHandle); + } +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() + { +//--- save the next bar start time; all checks at bar opening only + static datetime next_bar_open=0; + +//--- Phase 1 - check the emergence of a new bar and update the status + if(TimeCurrent()>=next_bar_open) + { + //--- get the current state of environment on the new bar + // namely, set the values of global variables: + // ExtPatternDetected - pattern detection + // ExtConfirmed - pattern confirmation + // ExtSignalOpen - signal to open + // ExtSignalClose - signal to close + // ExtPatternInfo - current pattern information + if(CheckState()) + { + //--- set the new bar opening time + next_bar_open=TimeCurrent(); + next_bar_open-=next_bar_open%PeriodSeconds(_Period); + next_bar_open+=PeriodSeconds(_Period); + + //--- report the emergence of a new bar only once within a bar + if(ExtPatternDetected && ExtConfirmed) + Print(ExtPatternInfo); + } + else + { + //--- error getting the status, retry on the next tick + return; + } + } + +//--- Phase 2 - if there is a signal and no position in this direction + if(ExtSignalOpen && !PositionExist(ExtSignalOpen)) + { + Print("\r\nSignal to open position ", ExtDirection); + PositionOpen(); + if(PositionExist(ExtSignalOpen)) + ExtSignalOpen=SIGNAL_NOT; + } + +//--- Phase 3 - close if there is a signal to close + if(ExtSignalClose && PositionExist(ExtSignalClose)) + { + Print("\r\nSignal to close position ", ExtDirection); + CloseBySignal(ExtSignalClose); + if(!PositionExist(ExtSignalClose)) + ExtSignalClose=SIGNAL_NOT; + } + +//--- Phase 4 - close upon expiration + if(ExtCloseByTime && PositionExpiredByTimeExist()) + { + CloseByTime(); + ExtCloseByTime=PositionExpiredByTimeExist(); + } + } +//+------------------------------------------------------------------+ +//| Get the current environment and check for a pattern | +//+------------------------------------------------------------------+ +bool CheckState() + { +//--- check if there is a pattern + if(!CheckPattern()) + { + Print("Error, failed to check pattern"); + return(false); + } + +//--- check for confirmation + if(!CheckConfirmation()) + { + Print("Error, failed to check pattern confirmation"); + return(false); + } +//--- if there is no confirmation, cancel the signal + if(!ExtConfirmed) + ExtSignalOpen=SIGNAL_NOT; + +//--- check if there is a signal to close a position + if(!CheckCloseSignal()) + { + Print("Error, failed to check the closing signal"); + return(false); + } + +//--- if positions are to be closed after certain holding time in bars + if(InpDuration) + ExtCloseByTime=true; // set flag to close upon expiration + +//--- all checks done + return(true); + } +//+------------------------------------------------------------------+ +//| Open a position in the direction of the signal | +//+------------------------------------------------------------------+ +bool PositionOpen() + { + ExtSymbolInfo.Refresh(); + ExtSymbolInfo.RefreshRates(); + + double price=0; +//--- Stop Loss and Take Profit are not set by default + double stoploss=0.0; + double takeprofit=0.0; + + int digits=ExtSymbolInfo.Digits(); + double point=ExtSymbolInfo.Point(); + double spread=ExtSymbolInfo.Ask()-ExtSymbolInfo.Bid(); + +//--- uptrend + if(ExtSignalOpen==SIGNAL_BUY) + { + price=NormalizeDouble(ExtSymbolInfo.Ask(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price-spread, digits); + } + else + stoploss = NormalizeDouble(price-InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price+spread, digits); + } + else + takeprofit = NormalizeDouble(price+InpTP*point, digits); + } + + if(!ExtTrade.Buy(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s buy %G at %G (sl=%G tp=%G) failed. Ask=%G error=%d", + Symbol(), InpLot, price, stoploss, takeprofit, ExtSymbolInfo.Ask(), GetLastError()); + return(false); + } + } + +//--- downtrend + if(ExtSignalOpen==SIGNAL_SELL) + { + price=NormalizeDouble(ExtSymbolInfo.Bid(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price+spread, digits); + } + else + stoploss = NormalizeDouble(price+InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price-spread, digits); + } + else + takeprofit = NormalizeDouble(price-InpTP*point, digits); + } + + if(!ExtTrade.Sell(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s sell at %G (sl=%G tp=%G) failed. Bid=%G error=%d", + Symbol(), price, stoploss, takeprofit, ExtSymbolInfo.Bid(), GetLastError()); + ExtTrade.PrintResult(); + Print(" "); + return(false); + } + } + + return(true); + } +//+------------------------------------------------------------------+ +//| Close a position based on the specified signal | +//+------------------------------------------------------------------+ +void CloseBySignal(int type_close) + { +//--- if there is no signal to close, return successful completion + if(type_close==SIGNAL_NOT) + return; +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalClose)==0) + return; + +//--- closing direction + long type; + switch(type_close) + { + case CLOSE_SHORT: + type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + type=POSITION_TYPE_BUY; + break; + default: + Print("Error! Signal to close not detected"); + return; + } + +//--- check all positions and close ours based on the signal + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + if(PositionGetInteger(POSITION_TYPE)==type) + { + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Close positions upon holding time expiration in bars | +//+------------------------------------------------------------------+ +void CloseByTime() + { +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalOpen)==0) + return; + +//--- check all positions and close ours based on the holding time in bars + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + //--- position opening time + datetime open_time=(datetime)PositionGetInteger(POSITION_TIME); + //--- check position holding time in bars + if(BarsHold(open_time)>=(int)InpDuration) + { + Print("\r\nTime to close position #", ticket); + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Returns true if there are open positions | +//+------------------------------------------------------------------+ +bool PositionExist(int signal_direction) + { + bool check_type=(signal_direction!=SIGNAL_NOT); + +//--- what positions to search + ENUM_POSITION_TYPE search_type=WRONG_VALUE; + if(check_type) + switch(signal_direction) + { + case SIGNAL_BUY: + search_type=POSITION_TYPE_BUY; + break; + case SIGNAL_SELL: + search_type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + search_type=POSITION_TYPE_BUY; + break; + case CLOSE_SHORT: + search_type=POSITION_TYPE_SELL; + break; + default: + //--- entry direction is not specified; nothing to search + return(false); + } + +//--- go through the list of all positions + int positions=PositionsTotal(); + for(int i=0; i=(int)InpDuration)) + return(true); + } + } + } + +//--- open position not found + return(false); + } +//+------------------------------------------------------------------+ +//| Checks position closing time in bars | +//+------------------------------------------------------------------+ +int BarsHold(datetime open_time) + { +//--- first run a basic simple check + if(TimeCurrent()-open_timeAvgBody(1)) && // long white candle + ((Open(1)-Close(1))>AvgBody(1)) && // long black candle + (MathAbs(Close(1)-Close(2))<0.1*AvgBody(1))) // doji close + { + ExtPatternDetected=true; + ExtSignalOpen=SIGNAL_SELL; + ExtPatternInfo="\r\nBearish MeetingLines detected"; + ExtDirection="Sell"; + return(true); + } + +//--- check Bullish MeetingLines + if((Open(2)-Close(2)>AvgBody(1)) && // long black candle + ((Close(1)-Open(1))>AvgBody(1)) && // long white candle + (MathAbs(Close(1)-Close(2))<0.1*AvgBody(1))) // doji close + { + ExtPatternDetected=true; + ExtSignalOpen=SIGNAL_BUY; + ExtPatternInfo="\r\nBullish MeetingLines detected"; + ExtDirection="Buy"; + return(true); + } + +//--- result of checking + return(ExtCheckPassed); + } +//+------------------------------------------------------------------+ +//| Returns true in case of successful confirmation check | +//+------------------------------------------------------------------+ +bool CheckConfirmation() + { + ExtConfirmed=false; +//--- if there is no pattern, do not search for confirmation + if(!ExtPatternDetected) + return(true); + +//--- get the value of the stochastic indicator to confirm the signal + double signal=MFI(1); + if(signal==EMPTY_VALUE) + { + //--- failed to get indicator value, check failed + return(false); + } + +//--- check the Buy signal + if(ExtSignalOpen==SIGNAL_BUY && (signal<40)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: MFI<40"; + } + +//--- check the Sell signal + if(ExtSignalOpen==SIGNAL_SELL && (signal>60)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: MFI>60"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| Check if there is a signal to close | +//+------------------------------------------------------------------+ +bool CheckCloseSignal() + { + ExtSignalClose=false; +//--- if there is a signal to enter the market, do not check the signal to close + if(ExtSignalOpen!=SIGNAL_NOT) + return(true); + +//--- check if there is a signal to close a long position + if(((MFI(1)<70) && (MFI(2)>70)) || ((MFI(1)<30) && (MFI(2)>30))) + { + //--- there is a signal to close a long position + ExtSignalClose=CLOSE_LONG; + ExtDirection="Long"; + } + +//--- check if there is a signal to close a short position + if(((MFI(1)>30) && (MFI(2)<30)) || ((MFI(1)>70) && (MFI(2)<70))) + { + //--- there is a signal to close a short position + ExtSignalClose=CLOSE_SHORT; + ExtDirection="Short"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| MFI indicator value at the specified bar | +//+------------------------------------------------------------------+ +double MFI(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtIndicatorHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the MFI indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Experts/Free Robots/BullishBearish MeetingLines RSI.mq5 b/BKPS/14031218/Experts/Free Robots/BullishBearish MeetingLines RSI.mq5 new file mode 100644 index 0000000..76a9be9 --- /dev/null +++ b/BKPS/14031218/Experts/Free Robots/BullishBearish MeetingLines RSI.mq5 @@ -0,0 +1,653 @@ +//+------------------------------------------------------------------+ +//| BullishBearish MeetingLines RSI.mq5 | +//| Copyright 2024, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2024, MetaQuotes Ltd." +#property link "https://www.mql5.com" +#property version "1.00" + +#include +#include + +#define SIGNAL_BUY 1 // Buy signal +#define SIGNAL_NOT 0 // no trading signal +#define SIGNAL_SELL -1 // Sell signal + +#define CLOSE_LONG 2 // signal to close Long +#define CLOSE_SHORT -2 // signal to close Short + +//--- Input parameters +input int InpAverBodyPeriod=12; // period for calculating average candlestick size +input int InpPeriodRSI =37; // RSI period +input ENUM_APPLIED_PRICE InpPrice=PRICE_CLOSE; // price type + +//--- trade parameters +input uint InpDuration=10; // position holding time in bars +input uint InpSL =200; // Stop Loss in points +input uint InpTP =200; // Take Profit in points +input uint InpSlippage=10; // slippage in points +//--- money management parameters +input double InpLot =0.1; // lot +//--- Expert ID +input long InpMagicNumber=122300; // Magic Number + +//--- global variables +int ExtAvgBodyPeriod; // average candlestick calculation period +int ExtSignalOpen =0; // Buy/Sell signal +int ExtSignalClose =0; // signal to close a position +string ExtPatternInfo =""; // current pattern information +string ExtDirection =""; // position opening direction +bool ExtPatternDetected=false; // pattern detected +bool ExtConfirmed =false; // pattern confirmed +bool ExtCloseByTime =true; // requires closing by time +bool ExtCheckPassed =true; // status checking error +//--- indicator handle +int ExtIndicatorHandle=INVALID_HANDLE; + +//--- service objects +CTrade ExtTrade; +CSymbolInfo ExtSymbolInfo; +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { + Print("InpSL=", InpSL); + Print("InpTP=", InpTP); +//--- set parameters for trading operations + ExtTrade.SetDeviationInPoints(InpSlippage); // slippage + ExtTrade.SetExpertMagicNumber(InpMagicNumber); // Expert Advisor ID + ExtTrade.LogLevel(LOG_LEVEL_ERRORS); // logging level + + ExtAvgBodyPeriod=InpAverBodyPeriod; +//--- indicator initialization + ExtIndicatorHandle=iRSI(_Symbol, _Period, InpPeriodRSI, InpPrice); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating CCI indicator"); + return(INIT_FAILED); + } +//--- OK + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { +//--- release indicator handle + IndicatorRelease(ExtIndicatorHandle); + } +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() + { +//--- save the next bar start time; all checks at bar opening only + static datetime next_bar_open=0; + +//--- Phase 1 - check the emergence of a new bar and update the status + if(TimeCurrent()>=next_bar_open) + { + //--- get the current state of environment on the new bar + // namely, set the values of global variables: + // ExtPatternDetected - pattern detection + // ExtConfirmed - pattern confirmation + // ExtSignalOpen - signal to open + // ExtSignalClose - signal to close + // ExtPatternInfo - current pattern information + if(CheckState()) + { + //--- set the new bar opening time + next_bar_open=TimeCurrent(); + next_bar_open-=next_bar_open%PeriodSeconds(_Period); + next_bar_open+=PeriodSeconds(_Period); + + //--- report the emergence of a new bar only once within a bar + if(ExtPatternDetected && ExtConfirmed) + Print(ExtPatternInfo); + } + else + { + //--- error getting the status, retry on the next tick + return; + } + } + +//--- Phase 2 - if there is a signal and no position in this direction + if(ExtSignalOpen && !PositionExist(ExtSignalOpen)) + { + Print("\r\nSignal to open position ", ExtDirection); + PositionOpen(); + if(PositionExist(ExtSignalOpen)) + ExtSignalOpen=SIGNAL_NOT; + } + +//--- Phase 3 - close if there is a signal to close + if(ExtSignalClose && PositionExist(ExtSignalClose)) + { + Print("\r\nSignal to close position ", ExtDirection); + CloseBySignal(ExtSignalClose); + if(!PositionExist(ExtSignalClose)) + ExtSignalClose=SIGNAL_NOT; + } + +//--- Phase 4 - close upon expiration + if(ExtCloseByTime && PositionExpiredByTimeExist()) + { + CloseByTime(); + ExtCloseByTime=PositionExpiredByTimeExist(); + } + } +//+------------------------------------------------------------------+ +//| Get the current environment and check for a pattern | +//+------------------------------------------------------------------+ +bool CheckState() + { +//--- check if there is a pattern + if(!CheckPattern()) + { + Print("Error, failed to check pattern"); + return(false); + } + +//--- check for confirmation + if(!CheckConfirmation()) + { + Print("Error, failed to check pattern confirmation"); + return(false); + } +//--- if there is no confirmation, cancel the signal + if(!ExtConfirmed) + ExtSignalOpen=SIGNAL_NOT; + +//--- check if there is a signal to close a position + if(!CheckCloseSignal()) + { + Print("Error, failed to check the closing signal"); + return(false); + } + +//--- if positions are to be closed after certain holding time in bars + if(InpDuration) + ExtCloseByTime=true; // set flag to close upon expiration + +//--- all checks done + return(true); + } +//+------------------------------------------------------------------+ +//| Open a position in the direction of the signal | +//+------------------------------------------------------------------+ +bool PositionOpen() + { + ExtSymbolInfo.Refresh(); + ExtSymbolInfo.RefreshRates(); + + double price=0; +//--- Stop Loss and Take Profit are not set by default + double stoploss=0.0; + double takeprofit=0.0; + + int digits=ExtSymbolInfo.Digits(); + double point=ExtSymbolInfo.Point(); + double spread=ExtSymbolInfo.Ask()-ExtSymbolInfo.Bid(); + +//--- uptrend + if(ExtSignalOpen==SIGNAL_BUY) + { + price=NormalizeDouble(ExtSymbolInfo.Ask(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price-spread, digits); + } + else + stoploss = NormalizeDouble(price-InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price+spread, digits); + } + else + takeprofit = NormalizeDouble(price+InpTP*point, digits); + } + + if(!ExtTrade.Buy(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s buy %G at %G (sl=%G tp=%G) failed. Ask=%G error=%d", + Symbol(), InpLot, price, stoploss, takeprofit, ExtSymbolInfo.Ask(), GetLastError()); + return(false); + } + } + +//--- downtrend + if(ExtSignalOpen==SIGNAL_SELL) + { + price=NormalizeDouble(ExtSymbolInfo.Bid(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price+spread, digits); + } + else + stoploss = NormalizeDouble(price+InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price-spread, digits); + } + else + takeprofit = NormalizeDouble(price-InpTP*point, digits); + } + + if(!ExtTrade.Sell(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s sell at %G (sl=%G tp=%G) failed. Bid=%G error=%d", + Symbol(), price, stoploss, takeprofit, ExtSymbolInfo.Bid(), GetLastError()); + ExtTrade.PrintResult(); + Print(" "); + return(false); + } + } + + return(true); + } +//+------------------------------------------------------------------+ +//| Close a position based on the specified signal | +//+------------------------------------------------------------------+ +void CloseBySignal(int type_close) + { +//--- if there is no signal to close, return successful completion + if(type_close==SIGNAL_NOT) + return; +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalClose)==0) + return; + +//--- closing direction + long type; + switch(type_close) + { + case CLOSE_SHORT: + type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + type=POSITION_TYPE_BUY; + break; + default: + Print("Error! Signal to close not detected"); + return; + } + +//--- check all positions and close ours based on the signal + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + if(PositionGetInteger(POSITION_TYPE)==type) + { + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Close positions upon holding time expiration in bars | +//+------------------------------------------------------------------+ +void CloseByTime() + { +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalOpen)==0) + return; + +//--- check all positions and close ours based on the holding time in bars + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + //--- position opening time + datetime open_time=(datetime)PositionGetInteger(POSITION_TIME); + //--- check position holding time in bars + if(BarsHold(open_time)>=(int)InpDuration) + { + Print("\r\nTime to close position #", ticket); + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Returns true if there are open positions | +//+------------------------------------------------------------------+ +bool PositionExist(int signal_direction) + { + bool check_type=(signal_direction!=SIGNAL_NOT); + +//--- what positions to search + ENUM_POSITION_TYPE search_type=WRONG_VALUE; + if(check_type) + switch(signal_direction) + { + case SIGNAL_BUY: + search_type=POSITION_TYPE_BUY; + break; + case SIGNAL_SELL: + search_type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + search_type=POSITION_TYPE_BUY; + break; + case CLOSE_SHORT: + search_type=POSITION_TYPE_SELL; + break; + default: + //--- entry direction is not specified; nothing to search + return(false); + } + +//--- go through the list of all positions + int positions=PositionsTotal(); + for(int i=0; i=(int)InpDuration)) + return(true); + } + } + } + +//--- open position not found + return(false); + } + +//+------------------------------------------------------------------+ +//| Checks position closing time in bars | +//+------------------------------------------------------------------+ +int BarsHold(datetime open_time) + { +//--- first run a basic simple check + if(TimeCurrent()-open_timeAvgBody(1)) && // long white candle + ((Open(1)-Close(1))>AvgBody(1)) && // long black candle + (MathAbs(Close(1)-Close(2))<0.1*AvgBody(1))) // doji close + { + ExtPatternDetected=true; + ExtSignalOpen=SIGNAL_SELL; + ExtPatternInfo="\r\nBearish MeetingLines detected"; + ExtDirection="Sell"; + return(true); + } + +//--- check Bullish MeetingLines + if((Open(2)-Close(2)>AvgBody(1)) && // long black candle + ((Close(1)-Open(1))>AvgBody(1)) && // long white candle + (MathAbs(Close(1)-Close(2))<0.1*AvgBody(1))) // doji close + { + ExtPatternDetected=true; + ExtSignalOpen=SIGNAL_BUY; + ExtPatternInfo="\r\nBullish MeetingLines detected"; + ExtDirection="Buy"; + return(true); + } + +//--- result of checking + return(ExtCheckPassed); + } +//+------------------------------------------------------------------+ +//| Returns true in case of successful confirmation check | +//+------------------------------------------------------------------+ +bool CheckConfirmation() + { + ExtConfirmed=false; +//--- if there is no pattern, do not search for confirmation + if(!ExtPatternDetected) + return(true); + +//--- get the value of the stochastic indicator to confirm the signal + double signal=RSI(1); + if(signal==EMPTY_VALUE) + { + //--- failed to get indicator value, check failed + return(false); + } + +//--- check the Buy signal + if(ExtSignalOpen==SIGNAL_BUY && (signal<40)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: RSI<40"; + } + +//--- check the Sell signal + if(ExtSignalOpen==SIGNAL_SELL && (signal>60)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: RSI>60"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| Check if there is a signal to close | +//+------------------------------------------------------------------+ +bool CheckCloseSignal() + { + ExtSignalClose=false; +//--- if there is a signal to enter the market, do not check the signal to close + if(ExtSignalOpen!=SIGNAL_NOT) + return(true); + +//--- check if there is a signal to close a long position + if(((RSI(1)<70) && (RSI(2)>70)) || ((RSI(1)<30) && (RSI(2)>30))) + { + //--- there is a signal to close a long position + ExtSignalClose=CLOSE_LONG; + ExtDirection="Long"; + } + +//--- check if there is a signal to close a short position + if(((RSI(1)>30) && (RSI(2)<30)) || ((RSI(1)>70) && (RSI(2)<70))) + { + //--- there is a signal to close a short position + ExtSignalClose=CLOSE_SHORT; + ExtDirection="Short"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| RSI indicator value at the specified bar | +//+------------------------------------------------------------------+ +double RSI(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtIndicatorHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the RSI indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Experts/Free Robots/BullishBearish MeetingLines Stoch.mq5 b/BKPS/14031218/Experts/Free Robots/BullishBearish MeetingLines Stoch.mq5 new file mode 100644 index 0000000..de4acc7 --- /dev/null +++ b/BKPS/14031218/Experts/Free Robots/BullishBearish MeetingLines Stoch.mq5 @@ -0,0 +1,662 @@ +//+------------------------------------------------------------------+ +//| BullishBearish MeetingLines Stoch.mq5 | +//| Copyright 2024, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2024, MetaQuotes Ltd." +#property link "https://www.mql5.com" +#property version "1.00" + +#include +#include + +#define SIGNAL_BUY 1 // Buy signal +#define SIGNAL_NOT 0 // no trading signal +#define SIGNAL_SELL -1 // Sell signal + +#define CLOSE_LONG 2 // signal to close Long +#define CLOSE_SHORT -2 // signal to close Short + +//--- Input parameters +input int InpAverBodyPeriod=12; // period for calculating average candlestick size +input int InpStochK =47; // period %K +input int InpStochD =9; // period %D +input int InpStochSlow =13; // smoothing period %K +input ENUM_STO_PRICE InpStochApplied=STO_LOWHIGH; // calculation type +input ENUM_MA_METHOD InpStochMA =MODE_SMA; // smoothing type + +//--- trade parameters +input uint InpDuration=10; // position holding time in bars +input uint InpSL =200; // Stop Loss in points +input uint InpTP =200; // Take Profit in points +input uint InpSlippage=10; // slippage in points +//--- money management parameters +input double InpLot=0.1; // lot +//--- Expert ID +input long InpMagicNumber=123400; // Magic Number + +//--- global variables +int ExtAvgBodyPeriod; // average candlestick calculation period +int ExtSignalOpen=0; // Buy/Sell signal +int ExtSignalClose=0; // signal to close a position +string ExtPatternInfo=""; // current pattern information +string ExtDirection=""; // position opening direction +bool ExtPatternDetected=false; // pattern detected +bool ExtConfirmed=false; // pattern confirmed +bool ExtCloseByTime=true; // requires closing by time +bool ExtCheckPassed=true; // status checking error +//--- indicator handle +int ExtIndicatorHandle=INVALID_HANDLE; + +//--- service objects +CTrade ExtTrade; +CSymbolInfo ExtSymbolInfo; +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { + Print("InpSL=", InpSL); + Print("InpTP=", InpTP); +//--- set parameters for trading operations + ExtTrade.SetDeviationInPoints(InpSlippage); // slippage + ExtTrade.SetExpertMagicNumber(InpMagicNumber); // Expert Advisor ID + ExtTrade.LogLevel(LOG_LEVEL_ERRORS); // logging level + + ExtAvgBodyPeriod=InpAverBodyPeriod; +//--- indicator initialization + ExtIndicatorHandle=iStochastic(_Symbol, _Period, InpStochK, InpStochD, InpStochSlow, InpStochMA, InpStochApplied); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating iStochastic indicator"); + return(INIT_FAILED); + } +//--- OK + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { +//--- release indicator handle + IndicatorRelease(ExtIndicatorHandle); + } +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() + { +//--- save the next bar start time; all checks at bar opening only + static datetime next_bar_open=0; + +//--- Phase 1 - check the emergence of a new bar and update the status + if(TimeCurrent()>=next_bar_open) + { + //--- get the current state of environment on the new bar + // namely, set the values of global variables: + // ExtPatternDetected - pattern detection + // ExtConfirmed - pattern confirmation + // ExtSignalOpen - signal to open + // ExtSignalClose - signal to close + // ExtPatternInfo - current pattern information + if(CheckState()) + { + //--- set the new bar opening time + next_bar_open=TimeCurrent(); + next_bar_open-=next_bar_open%PeriodSeconds(_Period); + next_bar_open+=PeriodSeconds(_Period); + + //--- report the emergence of a new bar only once within a bar + if(ExtPatternDetected && ExtConfirmed) + Print(ExtPatternInfo); + } + else + { + //--- error getting the status, retry on the next tick + return; + } + } + +//--- Phase 2 - if there is a signal and no position in this direction + if(ExtSignalOpen && !PositionExist(ExtSignalOpen)) + { + Print("\r\nSignal to open position ", ExtDirection); + PositionOpen(); + if(PositionExist(ExtSignalOpen)) + ExtSignalOpen=SIGNAL_NOT; + } + +//--- Phase 3 - close if there is a signal to close + if(ExtSignalClose && PositionExist(ExtSignalClose)) + { + Print("\r\nSignal to close position ", ExtDirection); + CloseBySignal(ExtSignalClose); + if(!PositionExist(ExtSignalClose)) + ExtSignalClose=SIGNAL_NOT; + } + +//--- Phase 4 - close upon expiration + if(ExtCloseByTime && PositionExpiredByTimeExist()) + { + CloseByTime(); + ExtCloseByTime=PositionExpiredByTimeExist(); + } + } +//+------------------------------------------------------------------+ +//| Get the current environment and check for a pattern | +//+------------------------------------------------------------------+ +bool CheckState() + { +//--- check if there is a pattern + if(!CheckPattern()) + { + Print("Error, failed to check pattern"); + return(false); + } + +//--- check for confirmation + if(!CheckConfirmation()) + { + Print("Error, failed to check pattern confirmation"); + return(false); + } +//--- if there is no confirmation, cancel the signal + if(!ExtConfirmed) + ExtSignalOpen=SIGNAL_NOT; + +//--- check if there is a signal to close a position + if(!CheckCloseSignal()) + { + Print("Error, failed to check the closing signal"); + return(false); + } + +//--- if positions are to be closed after certain holding time in bars + if(InpDuration) + ExtCloseByTime=true; // set flag to close upon expiration + +//--- all checks done + return(true); + } +//+------------------------------------------------------------------+ +//| Open a position in the direction of the signal | +//+------------------------------------------------------------------+ +bool PositionOpen() + { + ExtSymbolInfo.Refresh(); + ExtSymbolInfo.RefreshRates(); + + double price=0; +//--- Stop Loss and Take Profit are not set by default + double stoploss=0.0; + double takeprofit=0.0; + + int digits=ExtSymbolInfo.Digits(); + double point=ExtSymbolInfo.Point(); + double spread=ExtSymbolInfo.Ask()-ExtSymbolInfo.Bid(); + +//--- uptrend + if(ExtSignalOpen==SIGNAL_BUY) + { + price=NormalizeDouble(ExtSymbolInfo.Ask(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price-spread, digits); + } + else + stoploss = NormalizeDouble(price-InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price+spread, digits); + } + else + takeprofit = NormalizeDouble(price+InpTP*point, digits); + } + + if(!ExtTrade.Buy(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s buy %G at %G (sl=%G tp=%G) failed. Ask=%G error=%d", + Symbol(), InpLot, price, stoploss, takeprofit, ExtSymbolInfo.Ask(), GetLastError()); + return(false); + } + } + +//--- downtrend + if(ExtSignalOpen==SIGNAL_SELL) + { + price=NormalizeDouble(ExtSymbolInfo.Bid(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price+spread, digits); + } + else + stoploss = NormalizeDouble(price+InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price-spread, digits); + } + else + takeprofit = NormalizeDouble(price-InpTP*point, digits); + } + + if(!ExtTrade.Sell(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s sell at %G (sl=%G tp=%G) failed. Bid=%G error=%d", + Symbol(), price, stoploss, takeprofit, ExtSymbolInfo.Bid(), GetLastError()); + ExtTrade.PrintResult(); + Print(" "); + return(false); + } + } + + return(true); + } +//+------------------------------------------------------------------+ +//| Close a position based on the specified signal | +//+------------------------------------------------------------------+ +void CloseBySignal(int type_close) + { +//--- if there is no signal to close, return successful completion + if(type_close==SIGNAL_NOT) + return; +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalClose)==0) + return; + +//--- closing direction + long type; + switch(type_close) + { + case CLOSE_SHORT: + type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + type=POSITION_TYPE_BUY; + break; + default: + Print("Error! Signal to close not detected"); + return; + } + +//--- check all positions and close ours based on the signal + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + if(PositionGetInteger(POSITION_TYPE)==type) + { + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Close positions upon holding time expiration in bars | +//+------------------------------------------------------------------+ +void CloseByTime() + { +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalOpen)==0) + return; + +//--- check all positions and close ours based on the holding time in bars + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + //--- position opening time + datetime open_time=(datetime)PositionGetInteger(POSITION_TIME); + //--- check position holding time in bars + if(BarsHold(open_time)>=(int)InpDuration) + { + Print("\r\nTime to close position #", ticket); + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Returns true if there are open positions | +//+------------------------------------------------------------------+ +bool PositionExist(int signal_direction) + { + bool check_type=(signal_direction!=SIGNAL_NOT); + +//--- what positions to search + ENUM_POSITION_TYPE search_type=WRONG_VALUE; + if(check_type) + switch(signal_direction) + { + case SIGNAL_BUY: + search_type=POSITION_TYPE_BUY; + break; + case SIGNAL_SELL: + search_type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + search_type=POSITION_TYPE_BUY; + break; + case CLOSE_SHORT: + search_type=POSITION_TYPE_SELL; + break; + default: + //--- entry direction is not specified; nothing to search + return(false); + } + +//--- go through the list of all positions + int positions=PositionsTotal(); + for(int i=0; i=(int)InpDuration)) + return(true); + } + } + } + +//--- open position not found + return(false); + } + +//+------------------------------------------------------------------+ +//| Checks position closing time in bars | +//+------------------------------------------------------------------+ +int BarsHold(datetime open_time) + { +//--- first run a basic simple check + if(TimeCurrent()-open_timeAvgBody(1)) && // long black + (Open(2)-Close(2)>AvgBody(1)) && + (Open(1)-Close(1)>AvgBody(1)) && + (MidPoint(2)AvgBody(1)) && // long white + (Close(2)-Open(2)>AvgBody(1)) && + (Close(1)-Open(1)>AvgBody(1)) && + (MidPoint(2)>MidPoint(3)) && // higher midpoints + (MidPoint(1)>MidPoint(2))) + { + ExtPatternDetected=true; + ExtSignalOpen=SIGNAL_BUY; + ExtPatternInfo="\r\n3 White Soldiers detected"; + ExtDirection="Buy"; + return(true); + } + +//--- result of checking + return(ExtCheckPassed); + } +//+------------------------------------------------------------------+ +//| Returns true in case of successful confirmation check | +//+------------------------------------------------------------------+ +bool CheckConfirmation() + { + ExtConfirmed=false; +//--- if there is no pattern, do not search for confirmation + if(!ExtPatternDetected) + return(true); + +//--- get the value of the stochastic indicator to confirm the signal + double signal=StochSignal(1); + if(signal==EMPTY_VALUE) + { + //--- failed to get indicator value, check failed + return(false); + } + +//--- check the Buy signal + if(ExtSignalOpen==SIGNAL_BUY && (signal<30)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: StochSignal<30"; + } + +//--- check the Sell signal + if(ExtSignalOpen==SIGNAL_SELL && (signal>70)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: StochSignal>70"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| Check if there is a signal to close | +//+------------------------------------------------------------------+ +bool CheckCloseSignal() + { + ExtSignalClose=false; +//--- if there is a signal to enter the market, do not check the signal to close + if(ExtSignalOpen!=SIGNAL_NOT) + return(true); + +//--- check if there is a signal to close a long position + if(((StochSignal(1)<80) && (StochSignal(2)>80))|| // 80 crossed downwards + ((StochSignal(1)<20) && (StochSignal(2)>20))) // 20 crossed downwards + { + //--- there is a signal to close a long position + ExtSignalClose=CLOSE_LONG; + ExtDirection="Long"; + } + +//--- check if there is a signal to close a short position + if((((StochSignal(1)>20) && (StochSignal(2)<20)) || // 20 crossed upwards + ((StochSignal(1)>80) && (StochSignal(2)<80)))) // 80 crossed upwards + { + //--- there is a signal to close a short position + ExtSignalClose=CLOSE_SHORT; + ExtDirection="Short"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| Stochastic indicator value at the specified bar | +//+------------------------------------------------------------------+ +double StochSignal(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtIndicatorHandle, SIGNAL_LINE, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the iStochastic indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Experts/Free Robots/DarkCloud PiercingLine CCI.mq5 b/BKPS/14031218/Experts/Free Robots/DarkCloud PiercingLine CCI.mq5 new file mode 100644 index 0000000..4f87e86 --- /dev/null +++ b/BKPS/14031218/Experts/Free Robots/DarkCloud PiercingLine CCI.mq5 @@ -0,0 +1,682 @@ +//+------------------------------------------------------------------+ +//| DarkCloud PiercingLine CCI.mq5 | +//| Copyright 2024, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2024, MetaQuotes Ltd." +#property link "https://www.mql5.com" +#property version "1.00" + +#include +#include + +#define SIGNAL_BUY 1 // Buy signal +#define SIGNAL_NOT 0 // no trading signal +#define SIGNAL_SELL -1 // Sell signal + +#define CLOSE_LONG 2 // signal to close Long +#define CLOSE_SHORT -2 // signal to close Short + +//--- Input parameters +input int InpAverBodyPeriod=12; // period for calculating average candlestick size +input int InpMAPeriod =5; // Trend MA period +input int InpPeriodCCI =37; // CCI period +input ENUM_APPLIED_PRICE InpPrice=PRICE_CLOSE; // price type + +//--- trade parameters +input uint InpDuration=10; // position holding time in bars +input uint InpSL =200; // Stop Loss in points +input uint InpTP =200; // Take Profit in points +input uint InpSlippage=10; // slippage in points +//--- money management parameters +input double InpLot=0.1; // lot +//--- Expert ID +input long InpMagicNumber=120500; // Magic Number + +//--- global variables +int ExtAvgBodyPeriod; // average candlestick calculation period +int ExtSignalOpen =0; // Buy/Sell signal +int ExtSignalClose =0; // signal to close a position +string ExtPatternInfo =""; // current pattern information +string ExtDirection =""; // position opening direction +bool ExtPatternDetected=false; // pattern detected +bool ExtConfirmed =false; // pattern confirmed +bool ExtCloseByTime =true; // requires closing by time +bool ExtCheckPassed =true; // status checking error +//--- indicator handles +int ExtIndicatorHandle=INVALID_HANDLE; +int ExtTrendMAHandle=INVALID_HANDLE; + +//--- service objects +CTrade ExtTrade; +CSymbolInfo ExtSymbolInfo; +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { + Print("InpSL=", InpSL); + Print("InpTP=", InpTP); +//--- set parameters for trading operations + ExtTrade.SetDeviationInPoints(InpSlippage); // slippage + ExtTrade.SetExpertMagicNumber(InpMagicNumber); // Expert Advisor ID + ExtTrade.LogLevel(LOG_LEVEL_ERRORS); // logging level + + ExtAvgBodyPeriod=InpAverBodyPeriod; +//--- indicator initialization + ExtIndicatorHandle=iCCI(_Symbol, _Period, InpPeriodCCI, InpPrice); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating CCI indicator"); + return(INIT_FAILED); + } + +//--- trend moving average + ExtTrendMAHandle=iMA(_Symbol, _Period, InpMAPeriod,0, MODE_SMA,PRICE_CLOSE); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating Moving Average indicator"); + return(INIT_FAILED); + } + +//--- OK + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { +//--- release indicator handle + IndicatorRelease(ExtIndicatorHandle); + } +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() + { +//--- save the next bar start time; all checks at bar opening only + static datetime next_bar_open=0; + +//--- Phase 1 - check the emergence of a new bar and update the status + if(TimeCurrent()>=next_bar_open) + { + //--- get the current state of environment on the new bar + // namely, set the values of global variables: + // ExtPatternDetected - pattern detection + // ExtConfirmed - pattern confirmation + // ExtSignalOpen - signal to open + // ExtSignalClose - signal to close + // ExtPatternInfo - current pattern information + if(CheckState()) + { + //--- set the new bar opening time + next_bar_open=TimeCurrent(); + next_bar_open-=next_bar_open%PeriodSeconds(_Period); + next_bar_open+=PeriodSeconds(_Period); + + //--- report the emergence of a new bar only once within a bar + if(ExtPatternDetected && ExtConfirmed) + Print(ExtPatternInfo); + } + else + { + //--- error getting the status, retry on the next tick + return; + } + } + +//--- Phase 2 - if there is a signal and no position in this direction + if(ExtSignalOpen && !PositionExist(ExtSignalOpen)) + { + Print("\r\nSignal to open position ", ExtDirection); + PositionOpen(); + if(PositionExist(ExtSignalOpen)) + ExtSignalOpen=SIGNAL_NOT; + } + +//--- Phase 3 - close if there is a signal to close + if(ExtSignalClose && PositionExist(ExtSignalClose)) + { + Print("\r\nSignal to close position ", ExtDirection); + CloseBySignal(ExtSignalClose); + if(!PositionExist(ExtSignalClose)) + ExtSignalClose=SIGNAL_NOT; + } + +//--- Phase 4 - close upon expiration + if(ExtCloseByTime && PositionExpiredByTimeExist()) + { + CloseByTime(); + ExtCloseByTime=PositionExpiredByTimeExist(); + } + } +//+------------------------------------------------------------------+ +//| Get the current environment and check for a pattern | +//+------------------------------------------------------------------+ +bool CheckState() + { +//--- check if there is a pattern + if(!CheckPattern()) + { + Print("Error, failed to check pattern"); + return(false); + } + +//--- check for confirmation + if(!CheckConfirmation()) + { + Print("Error, failed to check pattern confirmation"); + return(false); + } +//--- if there is no confirmation, cancel the signal + if(!ExtConfirmed) + ExtSignalOpen=SIGNAL_NOT; + +//--- check if there is a signal to close a position + if(!CheckCloseSignal()) + { + Print("Error, failed to check the closing signal"); + return(false); + } + +//--- if positions are to be closed after certain holding time in bars + if(InpDuration) + ExtCloseByTime=true; // set flag to close upon expiration + +//--- all checks done + return(true); + } +//+------------------------------------------------------------------+ +//| Open a position in the direction of the signal | +//+------------------------------------------------------------------+ +bool PositionOpen() + { + ExtSymbolInfo.Refresh(); + ExtSymbolInfo.RefreshRates(); + + double price=0; +//--- Stop Loss and Take Profit are not set by default + double stoploss=0.0; + double takeprofit=0.0; + + int digits=ExtSymbolInfo.Digits(); + double point=ExtSymbolInfo.Point(); + double spread=ExtSymbolInfo.Ask()-ExtSymbolInfo.Bid(); + +//--- uptrend + if(ExtSignalOpen==SIGNAL_BUY) + { + price=NormalizeDouble(ExtSymbolInfo.Ask(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price-spread, digits); + } + else + stoploss = NormalizeDouble(price-InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price+spread, digits); + } + else + takeprofit = NormalizeDouble(price+InpTP*point, digits); + } + + if(!ExtTrade.Buy(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s buy %G at %G (sl=%G tp=%G) failed. Ask=%G error=%d", + Symbol(), InpLot, price, stoploss, takeprofit, ExtSymbolInfo.Ask(), GetLastError()); + return(false); + } + } + +//--- downtrend + if(ExtSignalOpen==SIGNAL_SELL) + { + price=NormalizeDouble(ExtSymbolInfo.Bid(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price+spread, digits); + } + else + stoploss = NormalizeDouble(price+InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price-spread, digits); + } + else + takeprofit = NormalizeDouble(price-InpTP*point, digits); + } + + if(!ExtTrade.Sell(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s sell at %G (sl=%G tp=%G) failed. Bid=%G error=%d", + Symbol(), price, stoploss, takeprofit, ExtSymbolInfo.Bid(), GetLastError()); + ExtTrade.PrintResult(); + Print(" "); + return(false); + } + } + + return(true); + } +//+------------------------------------------------------------------+ +//| Close a position based on the specified signal | +//+------------------------------------------------------------------+ +void CloseBySignal(int type_close) + { +//--- if there is no signal to close, return successful completion + if(type_close==SIGNAL_NOT) + return; +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalClose)==0) + return; + +//--- closing direction + long type; + switch(type_close) + { + case CLOSE_SHORT: + type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + type=POSITION_TYPE_BUY; + break; + default: + Print("Error! Signal to close not detected"); + return; + } + +//--- check all positions and close ours based on the signal + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + if(PositionGetInteger(POSITION_TYPE)==type) + { + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Close positions upon holding time expiration in bars | +//+------------------------------------------------------------------+ +void CloseByTime() + { +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalOpen)==0) + return; + +//--- check all positions and close ours based on the holding time in bars + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + //--- position opening time + datetime open_time=(datetime)PositionGetInteger(POSITION_TIME); + //--- check position holding time in bars + if(BarsHold(open_time)>=(int)InpDuration) + { + Print("\r\nTime to close position #", ticket); + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Returns true if there are open positions | +//+------------------------------------------------------------------+ +bool PositionExist(int signal_direction) + { + bool check_type=(signal_direction!=SIGNAL_NOT); + +//--- what positions to search + ENUM_POSITION_TYPE search_type=WRONG_VALUE; + if(check_type) + switch(signal_direction) + { + case SIGNAL_BUY: + search_type=POSITION_TYPE_BUY; + break; + case SIGNAL_SELL: + search_type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + search_type=POSITION_TYPE_BUY; + break; + case CLOSE_SHORT: + search_type=POSITION_TYPE_SELL; + break; + default: + //--- entry direction is not specified; nothing to search + return(false); + } + +//--- go through the list of all positions + int positions=PositionsTotal(); + for(int i=0; i=(int)InpDuration)) + return(true); + } + } + } +//--- open position not found + return(false); + } +//+------------------------------------------------------------------+ +//| Checks position closing time in bars | +//+------------------------------------------------------------------+ +int BarsHold(datetime open_time) + { +//--- first run a basic simple check + if(TimeCurrent()-open_timeAvgBody(1)) && // long body of the white candlestick (long white) + (Close(1)Open(2)) && // close within the previous candlestick body (white) + (MidOpenClose(2)>CloseAvg(2)) && // uptrend + (Open(1)>High(2))) // open above the previous day's High price (open at new high) + { + ExtPatternDetected=true; + ExtSignalOpen=SIGNAL_SELL; + ExtPatternInfo="\r\nDark Cloud Cover detected"; + ExtDirection="Sell"; + return(true); + } + +//--- check Piercing Line + if((Close(1)-Open(1)>AvgBody(1)) && // long body of the white candlestick (long white) + (Open(2)-Close(2)>AvgBody(1)) && // long body of the previous black candlestick (long black) + (Close(1)>Close(2)) && // close within the body + (Close(1)50)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: CCI>50"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| Check if there is a signal to close | +//+------------------------------------------------------------------+ +bool CheckCloseSignal() + { + ExtSignalClose=false; +//--- if there is a signal to enter the market, do not check the signal to close + if(ExtSignalOpen!=SIGNAL_NOT) + return(true); + +//--- check if there is a signal to close a long position + if(((CCI(1)<80) && (CCI(2)>80)) || ((CCI(1)<-80) && (CCI(2)>-80))) + { + //--- there is a signal to close a long position + ExtSignalClose=CLOSE_LONG; + ExtDirection="Long"; + } + +//--- check if there is a signal to close a short position + if(((CCI(1)>-80) && (CCI(2)<-80)) || ((CCI(1)>80) && (CCI(2)<80))) + { + //--- there is a signal to close a short position + ExtSignalClose=CLOSE_SHORT; + ExtDirection="Short"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| CCI indicator value at the specified bar | +//+------------------------------------------------------------------+ +double CCI(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtIndicatorHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the CCI indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ +//| SMA value at the specified bar | +//+------------------------------------------------------------------+ +double CloseAvg(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtTrendMAHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the Simple Moving Average indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Experts/Free Robots/DarkCloud PiercingLine MFI.mq5 b/BKPS/14031218/Experts/Free Robots/DarkCloud PiercingLine MFI.mq5 new file mode 100644 index 0000000..b739422 --- /dev/null +++ b/BKPS/14031218/Experts/Free Robots/DarkCloud PiercingLine MFI.mq5 @@ -0,0 +1,681 @@ +//+------------------------------------------------------------------+ +//| DarkCloud PiercingLine MFI.mq5 | +//| Copyright 2024, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2024, MetaQuotes Ltd." +#property link "https://www.mql5.com" +#property version "1.00" + +#include +#include + +#define SIGNAL_BUY 1 // Buy signal +#define SIGNAL_NOT 0 // no trading signal +#define SIGNAL_SELL -1 // Sell signal + +#define CLOSE_LONG 2 // signal to close Long +#define CLOSE_SHORT -2 // signal to close Short + +//--- Input parameters +input int InpAverBodyPeriod=12; // period for calculating average candlestick size +input int InpMAPeriod =5; // Trend MA period +input int InpPeriodMFI =37; // MFI period +input ENUM_APPLIED_VOLUME InpVolume=VOLUME_TICK; // volume type + +//--- trade parameters +input uint InpDuration=10; // position holding time in bars +input uint InpSL =200; // Stop Loss in points +input uint InpTP =200; // Take Profit in points +input uint InpSlippage=10; // slippage in points +//--- money management parameters +input double InpLot=0.1; // lot +//--- Expert ID +input long InpMagicNumber=122600; // Magic Number + +//--- global variables +int ExtAvgBodyPeriod; // average candlestick calculation period +int ExtSignalOpen =0; // Buy/Sell signal +int ExtSignalClose =0; // signal to close a position +string ExtPatternInfo =""; // current pattern information +string ExtDirection =""; // position opening direction +bool ExtPatternDetected=false; // pattern detected +bool ExtConfirmed =false; // pattern confirmed +bool ExtCloseByTime =true; // requires closing by time +bool ExtCheckPassed =true; // status checking error +//--- indicator handles +int ExtIndicatorHandle=INVALID_HANDLE; +int ExtTrendMAHandle=INVALID_HANDLE; + +//--- service objects +CTrade ExtTrade; +CSymbolInfo ExtSymbolInfo; +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { + Print("InpSL=", InpSL); + Print("InpTP=", InpTP); +//--- set parameters for trading operations + ExtTrade.SetDeviationInPoints(InpSlippage); // slippage + ExtTrade.SetExpertMagicNumber(InpMagicNumber); // Expert Advisor ID + ExtTrade.LogLevel(LOG_LEVEL_ERRORS); // logging level + + ExtAvgBodyPeriod=InpAverBodyPeriod; +//--- indicator initialization + ExtIndicatorHandle=iMFI(_Symbol, _Period, InpPeriodMFI, InpVolume); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating MFI indicator"); + return(INIT_FAILED); + } + +//--- trend moving average + ExtTrendMAHandle=iMA(_Symbol, _Period, InpMAPeriod,0, MODE_SMA,PRICE_CLOSE); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating Moving Average indicator"); + return(INIT_FAILED); + } + +//--- OK + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { +//--- release indicator handle + IndicatorRelease(ExtIndicatorHandle); + } +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() + { +//--- save the next bar start time; all checks at bar opening only + static datetime next_bar_open=0; + +//--- Phase 1 - check the emergence of a new bar and update the status + if(TimeCurrent()>=next_bar_open) + { + //--- get the current state of environment on the new bar + // namely, set the values of global variables: + // ExtPatternDetected - pattern detection + // ExtConfirmed - pattern confirmation + // ExtSignalOpen - signal to open + // ExtSignalClose - signal to close + // ExtPatternInfo - current pattern information + if(CheckState()) + { + //--- set the new bar opening time + next_bar_open=TimeCurrent(); + next_bar_open-=next_bar_open%PeriodSeconds(_Period); + next_bar_open+=PeriodSeconds(_Period); + + //--- report the emergence of a new bar only once within a bar + if(ExtPatternDetected && ExtConfirmed) + Print(ExtPatternInfo); + } + else + { + //--- error getting the status, retry on the next tick + return; + } + } + +//--- Phase 2 - if there is a signal and no position in this direction + if(ExtSignalOpen && !PositionExist(ExtSignalOpen)) + { + Print("\r\nSignal to open position ", ExtDirection); + PositionOpen(); + if(PositionExist(ExtSignalOpen)) + ExtSignalOpen=SIGNAL_NOT; + } + +//--- Phase 3 - close if there is a signal to close + if(ExtSignalClose && PositionExist(ExtSignalClose)) + { + Print("\r\nSignal to close position ", ExtDirection); + CloseBySignal(ExtSignalClose); + if(!PositionExist(ExtSignalClose)) + ExtSignalClose=SIGNAL_NOT; + } + +//--- Phase 4 - close upon expiration + if(ExtCloseByTime && PositionExpiredByTimeExist()) + { + CloseByTime(); + ExtCloseByTime=PositionExpiredByTimeExist(); + } + } +//+------------------------------------------------------------------+ +//| Get the current environment and check for a pattern | +//+------------------------------------------------------------------+ +bool CheckState() + { +//--- check if there is a pattern + if(!CheckPattern()) + { + Print("Error, failed to check pattern"); + return(false); + } + +//--- check for confirmation + if(!CheckConfirmation()) + { + Print("Error, failed to check pattern confirmation"); + return(false); + } +//--- if there is no confirmation, cancel the signal + if(!ExtConfirmed) + ExtSignalOpen=SIGNAL_NOT; + +//--- check if there is a signal to close a position + if(!CheckCloseSignal()) + { + Print("Error, failed to check the closing signal"); + return(false); + } + +//--- if positions are to be closed after certain holding time in bars + if(InpDuration) + ExtCloseByTime=true; // set flag to close upon expiration + +//--- all checks done + return(true); + } +//+------------------------------------------------------------------+ +//| Open a position in the direction of the signal | +//+------------------------------------------------------------------+ +bool PositionOpen() + { + ExtSymbolInfo.Refresh(); + ExtSymbolInfo.RefreshRates(); + + double price=0; +//--- Stop Loss and Take Profit are not set by default + double stoploss=0.0; + double takeprofit=0.0; + + int digits=ExtSymbolInfo.Digits(); + double point=ExtSymbolInfo.Point(); + double spread=ExtSymbolInfo.Ask()-ExtSymbolInfo.Bid(); + +//--- uptrend + if(ExtSignalOpen==SIGNAL_BUY) + { + price=NormalizeDouble(ExtSymbolInfo.Ask(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price-spread, digits); + } + else + stoploss = NormalizeDouble(price-InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price+spread, digits); + } + else + takeprofit = NormalizeDouble(price+InpTP*point, digits); + } + + if(!ExtTrade.Buy(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s buy %G at %G (sl=%G tp=%G) failed. Ask=%G error=%d", + Symbol(), InpLot, price, stoploss, takeprofit, ExtSymbolInfo.Ask(), GetLastError()); + return(false); + } + } + +//--- downtrend + if(ExtSignalOpen==SIGNAL_SELL) + { + price=NormalizeDouble(ExtSymbolInfo.Bid(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price+spread, digits); + } + else + stoploss = NormalizeDouble(price+InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price-spread, digits); + } + else + takeprofit = NormalizeDouble(price-InpTP*point, digits); + } + + if(!ExtTrade.Sell(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s sell at %G (sl=%G tp=%G) failed. Bid=%G error=%d", + Symbol(), price, stoploss, takeprofit, ExtSymbolInfo.Bid(), GetLastError()); + ExtTrade.PrintResult(); + Print(" "); + return(false); + } + } + + return(true); + } +//+------------------------------------------------------------------+ +//| Close a position based on the specified signal | +//+------------------------------------------------------------------+ +void CloseBySignal(int type_close) + { +//--- if there is no signal to close, return successful completion + if(type_close==SIGNAL_NOT) + return; +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalClose)==0) + return; + +//--- closing direction + long type; + switch(type_close) + { + case CLOSE_SHORT: + type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + type=POSITION_TYPE_BUY; + break; + default: + Print("Error! Signal to close not detected"); + return; + } +//--- check all positions and close ours based on the signal + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + if(PositionGetInteger(POSITION_TYPE)==type) + { + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Close positions upon holding time expiration in bars | +//+------------------------------------------------------------------+ +void CloseByTime() + { +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalOpen)==0) + return; + +//--- check all positions and close ours based on the holding time in bars + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + //--- position opening time + datetime open_time=(datetime)PositionGetInteger(POSITION_TIME); + //--- check position holding time in bars + if(BarsHold(open_time)>=(int)InpDuration) + { + Print("\r\nTime to close position #", ticket); + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Returns true if there are open positions | +//+------------------------------------------------------------------+ +bool PositionExist(int signal_direction) + { + bool check_type=(signal_direction!=SIGNAL_NOT); + +//--- what positions to search + ENUM_POSITION_TYPE search_type=WRONG_VALUE; + if(check_type) + switch(signal_direction) + { + case SIGNAL_BUY: + search_type=POSITION_TYPE_BUY; + break; + case SIGNAL_SELL: + search_type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + search_type=POSITION_TYPE_BUY; + break; + case CLOSE_SHORT: + search_type=POSITION_TYPE_SELL; + break; + default: + //--- entry direction is not specified; nothing to search + return(false); + } + +//--- go through the list of all positions + int positions=PositionsTotal(); + for(int i=0; i=(int)InpDuration)) + return(true); + } + } + } +//--- open position not found + return(false); + } +//+------------------------------------------------------------------+ +//| Checks position closing time in bars | +//+------------------------------------------------------------------+ +int BarsHold(datetime open_time) + { +//--- first run a basic simple check + if(TimeCurrent()-open_timeAvgBody(1)) && // long body of the white candlestick (long white) + (Close(1)Open(2)) && // close within the previous candlestick body (white) + (MidOpenClose(2)>CloseAvg(2)) && // uptrend + (Open(1)>High(2))) // open above the previous day's High price (open at new high) + { + ExtPatternDetected=true; + ExtSignalOpen=SIGNAL_SELL; + ExtPatternInfo="\r\nDark Cloud Cover detected"; + ExtDirection="Sell"; + return(true); + } + +//--- check Piercing Line + if((Close(1)-Open(1)>AvgBody(1)) && // long body of the white candlestick (long white) + (Open(2)-Close(2)>AvgBody(1)) && // long body of the previous black candlestick (long black) + (Close(1)>Close(2)) && // close within the body + (Close(1)60)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: MFI>60"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| Check if there is a signal to close | +//+------------------------------------------------------------------+ +bool CheckCloseSignal() + { + ExtSignalClose=false; +//--- if there is a signal to enter the market, do not check the signal to close + if(ExtSignalOpen!=SIGNAL_NOT) + return(true); + +//--- check if there is a signal to close a long position + if(((MFI(1)<70) && (MFI(2)>70)) || ((MFI(1)<30) && (MFI(2)>30))) + { + //--- there is a signal to close a long position + ExtSignalClose=CLOSE_LONG; + ExtDirection="Long"; + } + +//--- check if there is a signal to close a short position + if(((MFI(1)>30) && (MFI(2)<30)) || ((MFI(1)>70) && (MFI(2)<70))) + { + //--- there is a signal to close a short position + ExtSignalClose=CLOSE_SHORT; + ExtDirection="Short"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| MFI indicator value at the specified bar | +//+------------------------------------------------------------------+ +double MFI(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtIndicatorHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the MFI indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ +//| SMA value at the specified bar | +//+------------------------------------------------------------------+ +double CloseAvg(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtTrendMAHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the Simple Moving Average indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Experts/Free Robots/DarkCloud PiercingLine RSI.mq5 b/BKPS/14031218/Experts/Free Robots/DarkCloud PiercingLine RSI.mq5 new file mode 100644 index 0000000..4a83bb3 --- /dev/null +++ b/BKPS/14031218/Experts/Free Robots/DarkCloud PiercingLine RSI.mq5 @@ -0,0 +1,683 @@ +//+------------------------------------------------------------------+ +//| DarkCloud PiercingLine RSI.mq5 | +//| Copyright 2024, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2024, MetaQuotes Ltd." +#property link "https://www.mql5.com" +#property version "1.00" + +#include +#include + +#define SIGNAL_BUY 1 // Buy signal +#define SIGNAL_NOT 0 // no trading signal +#define SIGNAL_SELL -1 // Sell signal + +#define CLOSE_LONG 2 // signal to close Long +#define CLOSE_SHORT -2 // signal to close Short + +//--- Input parameters +input int InpAverBodyPeriod=12; // period for calculating average candlestick size +input int InpMAPeriod =5; // Trend MA period +input int InpPeriodRSI =37; // RSI period +input ENUM_APPLIED_PRICE InpPrice=PRICE_CLOSE; // price type + +//--- trade parameters +input uint InpDuration=10; // position holding time in bars +input uint InpSL =200; // Stop Loss in points +input uint InpTP =200; // Take Profit in points +input uint InpSlippage=10; // slippage in points +//--- money management parameters +input double InpLot=0.1; // lot +//--- Expert ID +input long InpMagicNumber=120700; // Magic Number + +//--- global variables +int ExtAvgBodyPeriod; // average candlestick calculation period +int ExtSignalOpen =0; // Buy/Sell signal +int ExtSignalClose =0; // signal to close a position +string ExtPatternInfo =""; // current pattern information +string ExtDirection =""; // position opening direction +bool ExtPatternDetected=false; // pattern detected +bool ExtConfirmed =false; // pattern confirmed +bool ExtCloseByTime =true; // requires closing by time +bool ExtCheckPassed =true; // status checking error +//--- indicator handles +int ExtIndicatorHandle=INVALID_HANDLE; +int ExtTrendMAHandle=INVALID_HANDLE; + +//--- service objects +CTrade ExtTrade; +CSymbolInfo ExtSymbolInfo; +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { + Print("InpSL=", InpSL); + Print("InpTP=", InpTP); +//--- set parameters for trading operations + ExtTrade.SetDeviationInPoints(InpSlippage); // slippage + ExtTrade.SetExpertMagicNumber(InpMagicNumber); // Expert Advisor ID + ExtTrade.LogLevel(LOG_LEVEL_ERRORS); // logging level + + ExtAvgBodyPeriod=InpAverBodyPeriod; +//--- indicator initialization + ExtIndicatorHandle=iRSI(_Symbol, _Period, InpPeriodRSI, InpPrice); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating CCI indicator"); + return(INIT_FAILED); + } + +//--- trend moving average + ExtTrendMAHandle=iMA(_Symbol, _Period, InpMAPeriod,0, MODE_SMA,PRICE_CLOSE); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating Moving Average indicator"); + return(INIT_FAILED); + } + +//--- OK + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { +//--- release indicator handle + IndicatorRelease(ExtIndicatorHandle); + } +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() + { +//--- save the next bar start time; all checks at bar opening only + static datetime next_bar_open=0; + +//--- Phase 1 - check the emergence of a new bar and update the status + if(TimeCurrent()>=next_bar_open) + { + //--- get the current state of environment on the new bar + // namely, set the values of global variables: + // ExtPatternDetected - pattern detection + // ExtConfirmed - pattern confirmation + // ExtSignalOpen - signal to open + // ExtSignalClose - signal to close + // ExtPatternInfo - current pattern information + if(CheckState()) + { + //--- set the new bar opening time + next_bar_open=TimeCurrent(); + next_bar_open-=next_bar_open%PeriodSeconds(_Period); + next_bar_open+=PeriodSeconds(_Period); + + //--- report the emergence of a new bar only once within a bar + if(ExtPatternDetected && ExtConfirmed) + Print(ExtPatternInfo); + } + else + { + //--- error getting the status, retry on the next tick + return; + } + } + +//--- Phase 2 - if there is a signal and no position in this direction + if(ExtSignalOpen && !PositionExist(ExtSignalOpen)) + { + Print("\r\nSignal to open position ", ExtDirection); + PositionOpen(); + if(PositionExist(ExtSignalOpen)) + ExtSignalOpen=SIGNAL_NOT; + } + +//--- Phase 3 - close if there is a signal to close + if(ExtSignalClose && PositionExist(ExtSignalClose)) + { + Print("\r\nSignal to close position ", ExtDirection); + CloseBySignal(ExtSignalClose); + if(!PositionExist(ExtSignalClose)) + ExtSignalClose=SIGNAL_NOT; + } + +//--- Phase 4 - close upon expiration + if(ExtCloseByTime && PositionExpiredByTimeExist()) + { + CloseByTime(); + ExtCloseByTime=PositionExpiredByTimeExist(); + } + } +//+------------------------------------------------------------------+ +//| Get the current environment and check for a pattern | +//+------------------------------------------------------------------+ +bool CheckState() + { +//--- check if there is a pattern + if(!CheckPattern()) + { + Print("Error, failed to check pattern"); + return(false); + } + +//--- check for confirmation + if(!CheckConfirmation()) + { + Print("Error, failed to check pattern confirmation"); + return(false); + } +//--- if there is no confirmation, cancel the signal + if(!ExtConfirmed) + ExtSignalOpen=SIGNAL_NOT; + +//--- check if there is a signal to close a position + if(!CheckCloseSignal()) + { + Print("Error, failed to check the closing signal"); + return(false); + } + +//--- if positions are to be closed after certain holding time in bars + if(InpDuration) + ExtCloseByTime=true; // set flag to close upon expiration + +//--- all checks done + return(true); + } +//+------------------------------------------------------------------+ +//| Open a position in the direction of the signal | +//+------------------------------------------------------------------+ +bool PositionOpen() + { + ExtSymbolInfo.Refresh(); + ExtSymbolInfo.RefreshRates(); + + double price=0; +//--- Stop Loss and Take Profit are not set by default + double stoploss=0.0; + double takeprofit=0.0; + + int digits=ExtSymbolInfo.Digits(); + double point=ExtSymbolInfo.Point(); + double spread=ExtSymbolInfo.Ask()-ExtSymbolInfo.Bid(); + +//--- uptrend + if(ExtSignalOpen==SIGNAL_BUY) + { + price=NormalizeDouble(ExtSymbolInfo.Ask(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price-spread, digits); + } + else + stoploss = NormalizeDouble(price-InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price+spread, digits); + } + else + takeprofit = NormalizeDouble(price+InpTP*point, digits); + } + + if(!ExtTrade.Buy(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s buy %G at %G (sl=%G tp=%G) failed. Ask=%G error=%d", + Symbol(), InpLot, price, stoploss, takeprofit, ExtSymbolInfo.Ask(), GetLastError()); + return(false); + } + } + +//--- downtrend + if(ExtSignalOpen==SIGNAL_SELL) + { + price=NormalizeDouble(ExtSymbolInfo.Bid(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price+spread, digits); + } + else + stoploss = NormalizeDouble(price+InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price-spread, digits); + } + else + takeprofit = NormalizeDouble(price-InpTP*point, digits); + } + + if(!ExtTrade.Sell(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s sell at %G (sl=%G tp=%G) failed. Bid=%G error=%d", + Symbol(), price, stoploss, takeprofit, ExtSymbolInfo.Bid(), GetLastError()); + ExtTrade.PrintResult(); + Print(" "); + return(false); + } + } + + return(true); + } +//+------------------------------------------------------------------+ +//| Close a position based on the specified signal | +//+------------------------------------------------------------------+ +void CloseBySignal(int type_close) + { +//--- if there is no signal to close, return successful completion + if(type_close==SIGNAL_NOT) + return; +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalClose)==0) + return; + +//--- closing direction + long type; + switch(type_close) + { + case CLOSE_SHORT: + type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + type=POSITION_TYPE_BUY; + break; + default: + Print("Error! Signal to close not detected"); + return; + } + +//--- check all positions and close ours based on the signal + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + if(PositionGetInteger(POSITION_TYPE)==type) + { + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Close positions upon holding time expiration in bars | +//+------------------------------------------------------------------+ +void CloseByTime() + { +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalOpen)==0) + return; + +//--- check all positions and close ours based on the holding time in bars + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + //--- position opening time + datetime open_time=(datetime)PositionGetInteger(POSITION_TIME); + //--- check position holding time in bars + if(BarsHold(open_time)>=(int)InpDuration) + { + Print("\r\nTime to close position #", ticket); + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Returns true if there are open positions | +//+------------------------------------------------------------------+ +bool PositionExist(int signal_direction) + { + bool check_type=(signal_direction!=SIGNAL_NOT); + +//--- what positions to search + ENUM_POSITION_TYPE search_type=WRONG_VALUE; + if(check_type) + switch(signal_direction) + { + case SIGNAL_BUY: + search_type=POSITION_TYPE_BUY; + break; + case SIGNAL_SELL: + search_type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + search_type=POSITION_TYPE_BUY; + break; + case CLOSE_SHORT: + search_type=POSITION_TYPE_SELL; + break; + default: + //--- entry direction is not specified; nothing to search + return(false); + } + +//--- go through the list of all positions + int positions=PositionsTotal(); + for(int i=0; i=(int)InpDuration)) + return(true); + } + } + } + +//--- open position not found + return(false); + } +//+------------------------------------------------------------------+ +//| Checks position closing time in bars | +//+------------------------------------------------------------------+ +int BarsHold(datetime open_time) + { +//--- first run a basic simple check + if(TimeCurrent()-open_timeAvgBody(1)) && // long body of the white candlestick (long white) + (Close(1)Open(2)) && // close within the previous candlestick body (white) + (MidOpenClose(2)>CloseAvg(2)) && // uptrend + (Open(1)>High(2))) // open above the previous day's High price (open at new high) + { + ExtPatternDetected=true; + ExtSignalOpen=SIGNAL_SELL; + ExtPatternInfo="\r\nDark Cloud Cover detected"; + ExtDirection="Sell"; + return(true); + } + +//--- check Piercing Line + if((Close(1)-Open(1)>AvgBody(1)) && // long body of the white candlestick (long white) + (Open(2)-Close(2)>AvgBody(1)) && // long body of the previous black candlestick (long black) + (Close(1)>Close(2)) && // close within the body + (Close(1)60)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: RSI>60"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| Check if there is a signal to close | +//+------------------------------------------------------------------+ +bool CheckCloseSignal() + { + ExtSignalClose=false; +//--- if there is a signal to enter the market, do not check the signal to close + if(ExtSignalOpen!=SIGNAL_NOT) + return(true); + +//--- check if there is a signal to close a long position + if(((RSI(1)<70) && (RSI(2)>70)) || ((RSI(1)<30) && (RSI(2)>30))) + { + //--- there is a signal to close a long position + ExtSignalClose=CLOSE_LONG; + ExtDirection="Long"; + } + +//--- check if there is a signal to close a short position + if(((RSI(1)>30) && (RSI(2)<30)) || ((RSI(1)>70) && (RSI(2)<70))) + { + //--- there is a signal to close a short position + ExtSignalClose=CLOSE_SHORT; + ExtDirection="Short"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| RSI indicator value at the specified bar | +//+------------------------------------------------------------------+ +double RSI(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtIndicatorHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the RSI indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ +//| SMA value at the specified bar | +//+------------------------------------------------------------------+ +double CloseAvg(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtTrendMAHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the Simple Moving Average indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Experts/Free Robots/DarkCloud PiercingLine Stoch.mq5 b/BKPS/14031218/Experts/Free Robots/DarkCloud PiercingLine Stoch.mq5 new file mode 100644 index 0000000..4eb1a89 --- /dev/null +++ b/BKPS/14031218/Experts/Free Robots/DarkCloud PiercingLine Stoch.mq5 @@ -0,0 +1,687 @@ +//+------------------------------------------------------------------+ +//| DarkCloud PiercingLine Stoch.mq5 | +//| Copyright 2024, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2024, MetaQuotes Ltd." +#property link "https://www.mql5.com" +#property version "1.00" + +#include +#include + +#define SIGNAL_BUY 1 // Buy signal +#define SIGNAL_NOT 0 // no trading signal +#define SIGNAL_SELL -1 // Sell signal + +#define CLOSE_LONG 2 // signal to close Long +#define CLOSE_SHORT -2 // signal to close Short + +//--- Input parameters +input int InpAverBodyPeriod=12; // period for calculating average candlestick size +input int InpMAPeriod =5; // Trend MA period +input int InpStochK =47; // period %K +input int InpStochD =9; // period %D +input int InpStochSlow =13; // smoothing period %K +input ENUM_STO_PRICE InpStochApplied=STO_LOWHIGH; // calculation type +input ENUM_MA_METHOD InpStochMA =MODE_SMA; // smoothing type + +//--- trade parameters +input uint InpDuration=10; // position holding time in bars +input uint InpSL =200; // Stop Loss in points +input uint InpTP =200; // Take Profit in points +input uint InpSlippage=10; // slippage in points +//--- money management parameters +input double InpLot=0.1; // lot +//--- Expert ID +input long InpMagicNumber=120800; // Magic Number + +//--- global variables +int ExtAvgBodyPeriod; // average candlestick calculation period +int ExtSignalOpen =0; // Buy/Sell signal +int ExtSignalClose =0; // signal to close a position +string ExtPatternInfo =""; // current pattern information +string ExtDirection =""; // position opening direction +bool ExtPatternDetected=false; // pattern detected +bool ExtConfirmed =false; // pattern confirmed +bool ExtCloseByTime =true; // requires closing by time +bool ExtCheckPassed =true; // status checking error +//--- indicator handles +int ExtIndicatorHandle=INVALID_HANDLE; +int ExtTrendMAHandle=INVALID_HANDLE; + +//--- service objects +CTrade ExtTrade; +CSymbolInfo ExtSymbolInfo; +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { + Print("InpSL=", InpSL); + Print("InpTP=", InpTP); +//--- set parameters for trading operations + ExtTrade.SetDeviationInPoints(InpSlippage); // slippage + ExtTrade.SetExpertMagicNumber(InpMagicNumber); // Expert Advisor ID + ExtTrade.LogLevel(LOG_LEVEL_ERRORS); // logging level + + ExtAvgBodyPeriod=InpAverBodyPeriod; +//--- indicator initialization + ExtIndicatorHandle=iStochastic(_Symbol, _Period, InpStochK, InpStochD, InpStochSlow, InpStochMA, InpStochApplied); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating iStochastic indicator"); + return(INIT_FAILED); + } + +//--- trend moving average + ExtTrendMAHandle=iMA(_Symbol, _Period, InpMAPeriod,0, MODE_SMA,PRICE_CLOSE); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating Moving Average indicator"); + return(INIT_FAILED); + } + +//--- OK + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { +//--- release indicator handle + IndicatorRelease(ExtIndicatorHandle); + } +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() + { +//--- save the next bar start time; all checks at bar opening only + static datetime next_bar_open=0; + +//--- Phase 1 - check the emergence of a new bar and update the status + if(TimeCurrent()>=next_bar_open) + { + //--- get the current state of environment on the new bar + // namely, set the values of global variables: + // ExtPatternDetected - pattern detection + // ExtConfirmed - pattern confirmation + // ExtSignalOpen - signal to open + // ExtSignalClose - signal to close + // ExtPatternInfo - current pattern information + if(CheckState()) + { + //--- set the new bar opening time + next_bar_open=TimeCurrent(); + next_bar_open-=next_bar_open%PeriodSeconds(_Period); + next_bar_open+=PeriodSeconds(_Period); + + //--- report the emergence of a new bar only once within a bar + if(ExtPatternDetected && ExtConfirmed) + Print(ExtPatternInfo); + } + else + { + //--- error getting the status, retry on the next tick + return; + } + } + +//--- Phase 2 - if there is a signal and no position in this direction + if(ExtSignalOpen && !PositionExist(ExtSignalOpen)) + { + Print("\r\nSignal to open position ", ExtDirection); + PositionOpen(); + if(PositionExist(ExtSignalOpen)) + ExtSignalOpen=SIGNAL_NOT; + } + +//--- Phase 3 - close if there is a signal to close + if(ExtSignalClose && PositionExist(ExtSignalClose)) + { + Print("\r\nSignal to close position ", ExtDirection); + CloseBySignal(ExtSignalClose); + if(!PositionExist(ExtSignalClose)) + ExtSignalClose=SIGNAL_NOT; + } + +//--- Phase 4 - close upon expiration + if(ExtCloseByTime && PositionExpiredByTimeExist()) + { + CloseByTime(); + ExtCloseByTime=PositionExpiredByTimeExist(); + } + } +//+------------------------------------------------------------------+ +//| Get the current environment and check for a pattern | +//+------------------------------------------------------------------+ +bool CheckState() + { +//--- check if there is a pattern + if(!CheckPattern()) + { + Print("Error, failed to check pattern"); + return(false); + } + +//--- check for confirmation + if(!CheckConfirmation()) + { + Print("Error, failed to check pattern confirmation"); + return(false); + } +//--- if there is no confirmation, cancel the signal + if(!ExtConfirmed) + ExtSignalOpen=SIGNAL_NOT; + +//--- check if there is a signal to close a position + if(!CheckCloseSignal()) + { + Print("Error, failed to check the closing signal"); + return(false); + } + +//--- if positions are to be closed after certain holding time in bars + if(InpDuration) + ExtCloseByTime=true; // set flag to close upon expiration + +//--- all checks done + return(true); + } +//+------------------------------------------------------------------+ +//| Open a position in the direction of the signal | +//+------------------------------------------------------------------+ +bool PositionOpen() + { + ExtSymbolInfo.Refresh(); + ExtSymbolInfo.RefreshRates(); + + double price=0; +//--- Stop Loss and Take Profit are not set by default + double stoploss=0.0; + double takeprofit=0.0; + + int digits=ExtSymbolInfo.Digits(); + double point=ExtSymbolInfo.Point(); + double spread=ExtSymbolInfo.Ask()-ExtSymbolInfo.Bid(); + +//--- uptrend + if(ExtSignalOpen==SIGNAL_BUY) + { + price=NormalizeDouble(ExtSymbolInfo.Ask(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price-spread, digits); + } + else + stoploss = NormalizeDouble(price-InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price+spread, digits); + } + else + takeprofit = NormalizeDouble(price+InpTP*point, digits); + } + + if(!ExtTrade.Buy(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s buy %G at %G (sl=%G tp=%G) failed. Ask=%G error=%d", + Symbol(), InpLot, price, stoploss, takeprofit, ExtSymbolInfo.Ask(), GetLastError()); + return(false); + } + } + +//--- downtrend + if(ExtSignalOpen==SIGNAL_SELL) + { + price=NormalizeDouble(ExtSymbolInfo.Bid(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price+spread, digits); + } + else + stoploss = NormalizeDouble(price+InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price-spread, digits); + } + else + takeprofit = NormalizeDouble(price-InpTP*point, digits); + } + + if(!ExtTrade.Sell(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s sell at %G (sl=%G tp=%G) failed. Bid=%G error=%d", + Symbol(), price, stoploss, takeprofit, ExtSymbolInfo.Bid(), GetLastError()); + ExtTrade.PrintResult(); + Print(" "); + return(false); + } + } + + return(true); + } +//+------------------------------------------------------------------+ +//| Close a position based on the specified signal | +//+------------------------------------------------------------------+ +void CloseBySignal(int type_close) + { +//--- if there is no signal to close, return successful completion + if(type_close==SIGNAL_NOT) + return; +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalClose)==0) + return; + +//--- closing direction + long type; + switch(type_close) + { + case CLOSE_SHORT: + type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + type=POSITION_TYPE_BUY; + break; + default: + Print("Error! Signal to close not detected"); + return; + } + +//--- check all positions and close ours based on the signal + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + if(PositionGetInteger(POSITION_TYPE)==type) + { + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Close positions upon holding time expiration in bars | +//+------------------------------------------------------------------+ +void CloseByTime() + { +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalOpen)==0) + return; + +//--- check all positions and close ours based on the holding time in bars + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + //--- position opening time + datetime open_time=(datetime)PositionGetInteger(POSITION_TIME); + //--- check position holding time in bars + if(BarsHold(open_time)>=(int)InpDuration) + { + Print("\r\nTime to close position #", ticket); + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Returns true if there are open positions | +//+------------------------------------------------------------------+ +bool PositionExist(int signal_direction) + { + bool check_type=(signal_direction!=SIGNAL_NOT); + +//--- what positions to search + ENUM_POSITION_TYPE search_type=WRONG_VALUE; + if(check_type) + switch(signal_direction) + { + case SIGNAL_BUY: + search_type=POSITION_TYPE_BUY; + break; + case SIGNAL_SELL: + search_type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + search_type=POSITION_TYPE_BUY; + break; + case CLOSE_SHORT: + search_type=POSITION_TYPE_SELL; + break; + default: + //--- entry direction is not specified; nothing to search + return(false); + } + +//--- go through the list of all positions + int positions=PositionsTotal(); + for(int i=0; i=(int)InpDuration)) + return(true); + } + } + } +//--- open position not found + return(false); + } +//+------------------------------------------------------------------+ +//| Checks position closing time in bars | +//+------------------------------------------------------------------+ +int BarsHold(datetime open_time) + { +//--- first run a basic simple check + if(TimeCurrent()-open_timeAvgBody(1)) && // long body of the white candlestick (long white) + (Close(1)Open(2)) && // close within the previous candlestick body (white) + (MidOpenClose(2)>CloseAvg(2)) && // uptrend + (Open(1)>High(2))) // open above the previous day's High price (open at new high) + { + ExtPatternDetected=true; + ExtSignalOpen=SIGNAL_SELL; + ExtPatternInfo="\r\nDark Cloud Cover detected"; + ExtDirection="Sell"; + return(true); + } + +//--- check Piercing Line + if((Close(1)-Open(1)>AvgBody(1)) && // long body of the white candlestick (long white) + (Open(2)-Close(2)>AvgBody(1)) && // long body of the previous black candlestick (long black) + (Close(1)>Close(2)) && // close within the body + (Close(1)70)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: StochSignal>70"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| Check if there is a signal to close | +//+------------------------------------------------------------------+ +bool CheckCloseSignal() + { + ExtSignalClose=false; +//--- if there is a signal to enter the market, do not check the signal to close + if(ExtSignalOpen!=SIGNAL_NOT) + return(true); + +//--- check if there is a signal to close a long position + if(((StochSignal(1)<80) && (StochSignal(2)>80))|| // 80 crossed downwards + ((StochSignal(1)<20) && (StochSignal(2)>20))) // 20 crossed downwards + { + //--- there is a signal to close a long position + ExtSignalClose=CLOSE_LONG; + ExtDirection="Long"; + } + +//--- check if there is a signal to close a short position + if((((StochSignal(1)>20) && (StochSignal(2)<20)) || // 20 crossed upwards + ((StochSignal(1)>80) && (StochSignal(2)<80)))) // 80 crossed upwards + { + //--- there is a signal to close a short position + ExtSignalClose=CLOSE_SHORT; + ExtDirection="Short"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| Stochastic indicator value at the specified bar | +//+------------------------------------------------------------------+ +double StochSignal(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtIndicatorHandle, SIGNAL_LINE, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the iStochastic indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ +//| SMA value at the specified bar | +//+------------------------------------------------------------------+ +double CloseAvg(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtTrendMAHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the Simple Moving Average indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Experts/Free Robots/HangingMan Hammer CCI.mq5 b/BKPS/14031218/Experts/Free Robots/HangingMan Hammer CCI.mq5 new file mode 100644 index 0000000..d137f14 --- /dev/null +++ b/BKPS/14031218/Experts/Free Robots/HangingMan Hammer CCI.mq5 @@ -0,0 +1,679 @@ +//+------------------------------------------------------------------+ +//| HangingMan Hammer CCI.mq5 | +//| Copyright 2024, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2024, MetaQuotes Ltd." +#property link "https://www.mql5.com" +#property version "1.00" + +#include +#include + +#define SIGNAL_BUY 1 // Buy signal +#define SIGNAL_NOT 0 // no trading signal +#define SIGNAL_SELL -1 // Sell signal + +#define CLOSE_LONG 2 // signal to close Long +#define CLOSE_SHORT -2 // signal to close Short + +//--- Input parameters +input int InpAverBodyPeriod=12; // period for calculating average candlestick size +input int InpMAPeriod =5; // Trend MA period +input int InpPeriodCCI =37; // CCI period +input ENUM_APPLIED_PRICE InpPrice=PRICE_CLOSE; // price type + +//--- trade parameters +input uint InpDuration=10; // position holding time in bars +input uint InpSL =200; // Stop Loss in points +input uint InpTP =200; // Take Profit in points +input uint InpSlippage=10; // slippage in points +//--- money management parameters +input double InpLot=0.1; // lot +//--- Expert ID +input long InpMagicNumber=124100; // Magic Number + +//--- global variables +int ExtAvgBodyPeriod; // average candlestick calculation period +int ExtSignalOpen =0; // Buy/Sell signal +int ExtSignalClose =0; // signal to close a position +string ExtPatternInfo =""; // current pattern information +string ExtDirection =""; // position opening direction +bool ExtPatternDetected=false; // pattern detected +bool ExtConfirmed =false; // pattern confirmed +bool ExtCloseByTime =true; // requires closing by time +bool ExtCheckPassed =true; // status checking error +//--- indicator handles +int ExtIndicatorHandle=INVALID_HANDLE; +int ExtTrendMAHandle=INVALID_HANDLE; + +//--- service objects +CTrade ExtTrade; +CSymbolInfo ExtSymbolInfo; +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { + Print("InpSL=", InpSL); + Print("InpTP=", InpTP); +//--- set parameters for trading operations + ExtTrade.SetDeviationInPoints(InpSlippage); // slippage + ExtTrade.SetExpertMagicNumber(InpMagicNumber); // Expert Advisor ID + ExtTrade.LogLevel(LOG_LEVEL_ERRORS); // logging level + + ExtAvgBodyPeriod=InpAverBodyPeriod; +//--- indicator initialization + ExtIndicatorHandle=iCCI(_Symbol, _Period, InpPeriodCCI, InpPrice); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating CCI indicator"); + return(INIT_FAILED); + } + +//--- trend moving average + ExtTrendMAHandle=iMA(_Symbol, _Period, InpMAPeriod, 0, MODE_SMA, PRICE_CLOSE); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating Moving Average indicator"); + return(INIT_FAILED); + } + +//--- OK + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { +//--- release indicator handle + IndicatorRelease(ExtIndicatorHandle); + } +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() + { +//--- save the next bar start time; all checks at bar opening only + static datetime next_bar_open=0; + +//--- Phase 1 - check the emergence of a new bar and update the status + if(TimeCurrent()>=next_bar_open) + { + //--- get the current state of environment on the new bar + // namely, set the values of global variables: + // ExtPatternDetected - pattern detection + // ExtConfirmed - pattern confirmation + // ExtSignalOpen - signal to open + // ExtSignalClose - signal to close + // ExtPatternInfo - current pattern information + if(CheckState()) + { + //--- set the new bar opening time + next_bar_open=TimeCurrent(); + next_bar_open-=next_bar_open%PeriodSeconds(_Period); + next_bar_open+=PeriodSeconds(_Period); + + //--- report the emergence of a new bar only once within a bar + if(ExtPatternDetected && ExtConfirmed) + Print(ExtPatternInfo); + } + else + { + //--- error getting the status, retry on the next tick + return; + } + } + +//--- Phase 2 - if there is a signal and no position in this direction + if(ExtSignalOpen && !PositionExist(ExtSignalOpen)) + { + Print("\r\nSignal to open position ", ExtDirection); + PositionOpen(); + if(PositionExist(ExtSignalOpen)) + ExtSignalOpen=SIGNAL_NOT; + } + +//--- Phase 3 - close if there is a signal to close + if(ExtSignalClose && PositionExist(ExtSignalClose)) + { + Print("\r\nSignal to close position ", ExtDirection); + CloseBySignal(ExtSignalClose); + if(!PositionExist(ExtSignalClose)) + ExtSignalClose=SIGNAL_NOT; + } + +//--- Phase 4 - close upon expiration + if(ExtCloseByTime && PositionExpiredByTimeExist()) + { + CloseByTime(); + ExtCloseByTime=PositionExpiredByTimeExist(); + } + } +//+------------------------------------------------------------------+ +//| Get the current environment and check for a pattern | +//+------------------------------------------------------------------+ +bool CheckState() + { +//--- check if there is a pattern + if(!CheckPattern()) + { + Print("Error, failed to check pattern"); + return(false); + } + +//--- check for confirmation + if(!CheckConfirmation()) + { + Print("Error, failed to check pattern confirmation"); + return(false); + } +//--- if there is no confirmation, cancel the signal + if(!ExtConfirmed) + ExtSignalOpen=SIGNAL_NOT; + +//--- check if there is a signal to close a position + if(!CheckCloseSignal()) + { + Print("Error, failed to check the closing signal"); + return(false); + } + +//--- if positions are to be closed after certain holding time in bars + if(InpDuration) + ExtCloseByTime=true; // set flag to close upon expiration + +//--- all checks done + return(true); + } +//+------------------------------------------------------------------+ +//| Open a position in the direction of the signal | +//+------------------------------------------------------------------+ +bool PositionOpen() + { + ExtSymbolInfo.Refresh(); + ExtSymbolInfo.RefreshRates(); + + double price=0; +//--- Stop Loss and Take Profit are not set by default + double stoploss=0.0; + double takeprofit=0.0; + + int digits=ExtSymbolInfo.Digits(); + double point=ExtSymbolInfo.Point(); + double spread=ExtSymbolInfo.Ask()-ExtSymbolInfo.Bid(); + +//--- uptrend + if(ExtSignalOpen==SIGNAL_BUY) + { + price=NormalizeDouble(ExtSymbolInfo.Ask(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price-spread, digits); + } + else + stoploss = NormalizeDouble(price-InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price+spread, digits); + } + else + takeprofit = NormalizeDouble(price+InpTP*point, digits); + } + + if(!ExtTrade.Buy(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s buy %G at %G (sl=%G tp=%G) failed. Ask=%G error=%d", + Symbol(), InpLot, price, stoploss, takeprofit, ExtSymbolInfo.Ask(), GetLastError()); + return(false); + } + } + +//--- downtrend + if(ExtSignalOpen==SIGNAL_SELL) + { + price=NormalizeDouble(ExtSymbolInfo.Bid(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price+spread, digits); + } + else + stoploss = NormalizeDouble(price+InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price-spread, digits); + } + else + takeprofit = NormalizeDouble(price-InpTP*point, digits); + } + + if(!ExtTrade.Sell(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s sell at %G (sl=%G tp=%G) failed. Bid=%G error=%d", + Symbol(), price, stoploss, takeprofit, ExtSymbolInfo.Bid(), GetLastError()); + ExtTrade.PrintResult(); + Print(" "); + return(false); + } + } + + return(true); + } +//+------------------------------------------------------------------+ +//| Close a position based on the specified signal | +//+------------------------------------------------------------------+ +void CloseBySignal(int type_close) + { +//--- if there is no signal to close, return successful completion + if(type_close==SIGNAL_NOT) + return; +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalClose)==0) + return; + +//--- closing direction + long type; + switch(type_close) + { + case CLOSE_SHORT: + type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + type=POSITION_TYPE_BUY; + break; + default: + Print("Error! Signal to close not detected"); + return; + } + +//--- check all positions and close ours based on the signal + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + if(PositionGetInteger(POSITION_TYPE)==type) + { + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Close positions upon holding time expiration in bars | +//+------------------------------------------------------------------+ +void CloseByTime() + { +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalOpen)==0) + return; + +//--- check all positions and close ours based on the holding time in bars + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + //--- position opening time + datetime open_time=(datetime)PositionGetInteger(POSITION_TIME); + //--- check position holding time in bars + if(BarsHold(open_time)>=(int)InpDuration) + { + Print("\r\nTime to close position #", ticket); + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Returns true if there are open positions | +//+------------------------------------------------------------------+ +bool PositionExist(int signal_direction) + { + bool check_type=(signal_direction!=SIGNAL_NOT); + +//--- what positions to search + ENUM_POSITION_TYPE search_type=WRONG_VALUE; + if(check_type) + switch(signal_direction) + { + case SIGNAL_BUY: + search_type=POSITION_TYPE_BUY; + break; + case SIGNAL_SELL: + search_type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + search_type=POSITION_TYPE_BUY; + break; + case CLOSE_SHORT: + search_type=POSITION_TYPE_SELL; + break; + default: + //--- entry direction is not specified; nothing to search + return(false); + } + +//--- go through the list of all positions + int positions=PositionsTotal(); + for(int i=0; i=(int)InpDuration)) + return(true); + } + } + } + +//--- open position not found + return(false); + } +//+------------------------------------------------------------------+ +//| Checks position closing time in bars | +//+------------------------------------------------------------------+ +int BarsHold(datetime open_time) + { +//--- first run a basic simple check + if(TimeCurrent()-open_timeCloseAvg(2)) && // up trend + (MathMin(Open(1), Close(1))> (High(1)-(High(1)-Low(1))/3.0)) && // body in upper 1/3 + (Close(1)>Close(2)) && (Open(1)>Open(2))) // body gap + { + ExtPatternDetected=true; + ExtSignalOpen=SIGNAL_SELL; + ExtPatternInfo="\r\nHanging Man detected"; + ExtDirection="Sell"; + return(true); + } + + +//--- check Hammer + if((MidPoint(1)(High(1)-(High(1)-Low(1))/3.0)) && // body in upper 1/3 + (Close(1)50)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: CCI>50"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| Check if there is a signal to close | +//+------------------------------------------------------------------+ +bool CheckCloseSignal() + { + ExtSignalClose=false; +//--- if there is a signal to enter the market, do not check the signal to close + if(ExtSignalOpen!=SIGNAL_NOT) + return(true); + +//--- check if there is a signal to close a long position + if(((CCI(1)<80) && (CCI(2)>80)) || ((CCI(1)<-80) && (CCI(2)>-80))) + { + //--- there is a signal to close a long position + ExtSignalClose=CLOSE_LONG; + ExtDirection="Long"; + } + +//--- check if there is a signal to close a short position + if(((CCI(1)>-80) && (CCI(2)<-80)) || ((CCI(1)>80) && (CCI(2)<80))) + { + //--- there is a signal to close a short position + ExtSignalClose=CLOSE_SHORT; + ExtDirection="Short"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| CCI indicator value at the specified bar | +//+------------------------------------------------------------------+ +double CCI(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtIndicatorHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the CCI indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ +//| SMA value at the specified bar | +//+------------------------------------------------------------------+ +double CloseAvg(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtTrendMAHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the Simple Moving Average indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Experts/Free Robots/HangingMan Hammer MFI.mq5 b/BKPS/14031218/Experts/Free Robots/HangingMan Hammer MFI.mq5 new file mode 100644 index 0000000..94428f1 --- /dev/null +++ b/BKPS/14031218/Experts/Free Robots/HangingMan Hammer MFI.mq5 @@ -0,0 +1,679 @@ +//+------------------------------------------------------------------+ +//| HangingMan Hammer MFI.mq5 | +//| Copyright 2024, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2024, MetaQuotes Ltd." +#property link "https://www.mql5.com" +#property version "1.00" + +#include +#include + +#define SIGNAL_BUY 1 // Buy signal +#define SIGNAL_NOT 0 // no trading signal +#define SIGNAL_SELL -1 // Sell signal + +#define CLOSE_LONG 2 // signal to close Long +#define CLOSE_SHORT -2 // signal to close Short + +//--- Input parameters +input int InpAverBodyPeriod=12; // period for calculating average candlestick size +input int InpMAPeriod =5; // Trend MA period +input int InpPeriodMFI =37; // MFI period +input ENUM_APPLIED_VOLUME InpVolume=VOLUME_TICK; // volume type + +//--- trade parameters +input uint InpDuration=10; // position holding time in bars +input uint InpSL =200; // Stop Loss in points +input uint InpTP =200; // Take Profit in points +input uint InpSlippage=10; // slippage in points +//--- money management parameters +input double InpLot=0.1; // lot +//--- Expert ID +input long InpMagicNumber=123600; // Magic Number + +//--- global variables +int ExtAvgBodyPeriod; // average candlestick calculation period +int ExtSignalOpen =0; // Buy/Sell signal +int ExtSignalClose =0; // signal to close a position +string ExtPatternInfo =""; // current pattern information +string ExtDirection =""; // position opening direction +bool ExtPatternDetected=false; // pattern detected +bool ExtConfirmed =false; // pattern confirmed +bool ExtCloseByTime =true; // requires closing by time +bool ExtCheckPassed =true; // status checking error +//--- indicator handles +int ExtIndicatorHandle=INVALID_HANDLE; +int ExtTrendMAHandle=INVALID_HANDLE; + +//--- service objects +CTrade ExtTrade; +CSymbolInfo ExtSymbolInfo; +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { + Print("InpSL=", InpSL); + Print("InpTP=", InpTP); +//--- set parameters for trading operations + ExtTrade.SetDeviationInPoints(InpSlippage); // slippage + ExtTrade.SetExpertMagicNumber(InpMagicNumber); // Expert Advisor ID + ExtTrade.LogLevel(LOG_LEVEL_ERRORS); // logging level + + ExtAvgBodyPeriod=InpAverBodyPeriod; +//--- indicator initialization + ExtIndicatorHandle=iMFI(_Symbol, _Period, InpPeriodMFI, InpVolume); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating MFI indicator"); + return(INIT_FAILED); + } + +//--- trend moving average + ExtTrendMAHandle=iMA(_Symbol, _Period, InpMAPeriod, 0, MODE_SMA, PRICE_CLOSE); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating Moving Average indicator"); + return(INIT_FAILED); + } + +//--- OK + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { +//--- release indicator handle + IndicatorRelease(ExtIndicatorHandle); + } +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() + { +//--- save the next bar start time; all checks at bar opening only + static datetime next_bar_open=0; + +//--- Phase 1 - check the emergence of a new bar and update the status + if(TimeCurrent()>=next_bar_open) + { + //--- get the current state of environment on the new bar + // namely, set the values of global variables: + // ExtPatternDetected - pattern detection + // ExtConfirmed - pattern confirmation + // ExtSignalOpen - signal to open + // ExtSignalClose - signal to close + // ExtPatternInfo - current pattern information + if(CheckState()) + { + //--- set the new bar opening time + next_bar_open=TimeCurrent(); + next_bar_open-=next_bar_open%PeriodSeconds(_Period); + next_bar_open+=PeriodSeconds(_Period); + + //--- report the emergence of a new bar only once within a bar + if(ExtPatternDetected && ExtConfirmed) + Print(ExtPatternInfo); + } + else + { + //--- error getting the status, retry on the next tick + return; + } + } + +//--- Phase 2 - if there is a signal and no position in this direction + if(ExtSignalOpen && !PositionExist(ExtSignalOpen)) + { + Print("\r\nSignal to open position ", ExtDirection); + PositionOpen(); + if(PositionExist(ExtSignalOpen)) + ExtSignalOpen=SIGNAL_NOT; + } + +//--- Phase 3 - close if there is a signal to close + if(ExtSignalClose && PositionExist(ExtSignalClose)) + { + Print("\r\nSignal to close position ", ExtDirection); + CloseBySignal(ExtSignalClose); + if(!PositionExist(ExtSignalClose)) + ExtSignalClose=SIGNAL_NOT; + } + +//--- Phase 4 - close upon expiration + if(ExtCloseByTime && PositionExpiredByTimeExist()) + { + CloseByTime(); + ExtCloseByTime=PositionExpiredByTimeExist(); + } + } +//+------------------------------------------------------------------+ +//| Get the current environment and check for a pattern | +//+------------------------------------------------------------------+ +bool CheckState() + { +//--- check if there is a pattern + if(!CheckPattern()) + { + Print("Error, failed to check pattern"); + return(false); + } + +//--- check for confirmation + if(!CheckConfirmation()) + { + Print("Error, failed to check pattern confirmation"); + return(false); + } +//--- if there is no confirmation, cancel the signal + if(!ExtConfirmed) + ExtSignalOpen=SIGNAL_NOT; + +//--- check if there is a signal to close a position + if(!CheckCloseSignal()) + { + Print("Error, failed to check the closing signal"); + return(false); + } + +//--- if positions are to be closed after certain holding time in bars + if(InpDuration) + ExtCloseByTime=true; // set flag to close upon expiration + +//--- all checks done + return(true); + } +//+------------------------------------------------------------------+ +//| Open a position in the direction of the signal | +//+------------------------------------------------------------------+ +bool PositionOpen() + { + ExtSymbolInfo.Refresh(); + ExtSymbolInfo.RefreshRates(); + + double price=0; +//--- Stop Loss and Take Profit are not set by default + double stoploss=0.0; + double takeprofit=0.0; + + int digits=ExtSymbolInfo.Digits(); + double point=ExtSymbolInfo.Point(); + double spread=ExtSymbolInfo.Ask()-ExtSymbolInfo.Bid(); + +//--- uptrend + if(ExtSignalOpen==SIGNAL_BUY) + { + price=NormalizeDouble(ExtSymbolInfo.Ask(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price-spread, digits); + } + else + stoploss = NormalizeDouble(price-InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price+spread, digits); + } + else + takeprofit = NormalizeDouble(price+InpTP*point, digits); + } + + if(!ExtTrade.Buy(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s buy %G at %G (sl=%G tp=%G) failed. Ask=%G error=%d", + Symbol(), InpLot, price, stoploss, takeprofit, ExtSymbolInfo.Ask(), GetLastError()); + return(false); + } + } + +//--- downtrend + if(ExtSignalOpen==SIGNAL_SELL) + { + price=NormalizeDouble(ExtSymbolInfo.Bid(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price+spread, digits); + } + else + stoploss = NormalizeDouble(price+InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price-spread, digits); + } + else + takeprofit = NormalizeDouble(price-InpTP*point, digits); + } + + if(!ExtTrade.Sell(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s sell at %G (sl=%G tp=%G) failed. Bid=%G error=%d", + Symbol(), price, stoploss, takeprofit, ExtSymbolInfo.Bid(), GetLastError()); + ExtTrade.PrintResult(); + Print(" "); + return(false); + } + } + + return(true); + } +//+------------------------------------------------------------------+ +//| Close a position based on the specified signal | +//+------------------------------------------------------------------+ +void CloseBySignal(int type_close) + { +//--- if there is no signal to close, return successful completion + if(type_close==SIGNAL_NOT) + return; +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalClose)==0) + return; + +//--- closing direction + long type; + switch(type_close) + { + case CLOSE_SHORT: + type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + type=POSITION_TYPE_BUY; + break; + default: + Print("Error! Signal to close not detected"); + return; + } + +//--- check all positions and close ours based on the signal + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + if(PositionGetInteger(POSITION_TYPE)==type) + { + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Close positions upon holding time expiration in bars | +//+------------------------------------------------------------------+ +void CloseByTime() + { +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalOpen)==0) + return; + +//--- check all positions and close ours based on the holding time in bars + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + //--- position opening time + datetime open_time=(datetime)PositionGetInteger(POSITION_TIME); + //--- check position holding time in bars + if(BarsHold(open_time)>=(int)InpDuration) + { + Print("\r\nTime to close position #", ticket); + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Returns true if there are open positions | +//+------------------------------------------------------------------+ +bool PositionExist(int signal_direction) + { + bool check_type=(signal_direction!=SIGNAL_NOT); + +//--- what positions to search + ENUM_POSITION_TYPE search_type=WRONG_VALUE; + if(check_type) + switch(signal_direction) + { + case SIGNAL_BUY: + search_type=POSITION_TYPE_BUY; + break; + case SIGNAL_SELL: + search_type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + search_type=POSITION_TYPE_BUY; + break; + case CLOSE_SHORT: + search_type=POSITION_TYPE_SELL; + break; + default: + //--- entry direction is not specified; nothing to search + return(false); + } + +//--- go through the list of all positions + int positions=PositionsTotal(); + for(int i=0; i=(int)InpDuration)) + return(true); + } + } + } + +//--- open position not found + return(false); + } + +//+------------------------------------------------------------------+ +//| Checks position closing time in bars | +//+------------------------------------------------------------------+ +int BarsHold(datetime open_time) + { +//--- first run a basic simple check + if(TimeCurrent()-open_timeCloseAvg(2)) && // up trend + (MathMin(Open(1), Close(1))> (High(1)-(High(1)-Low(1))/3.0)) && // body in upper 1/3 + (Close(1)>Close(2)) && (Open(1)>Open(2))) // body gap + { + ExtPatternDetected=true; + ExtSignalOpen=SIGNAL_SELL; + ExtPatternInfo="\r\nHanging Man detected"; + ExtDirection="Sell"; + return(true); + } + + +//--- check Hammer + if((MidPoint(1)(High(1)-(High(1)-Low(1))/3.0)) && // body in upper 1/3 + (Close(1)60)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: MFI>60"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| Check if there is a signal to close | +//+------------------------------------------------------------------+ +bool CheckCloseSignal() + { + ExtSignalClose=false; +//--- if there is a signal to enter the market, do not check the signal to close + if(ExtSignalOpen!=SIGNAL_NOT) + return(true); + +//--- check if there is a signal to close a long position + if(((MFI(1)<70) && (MFI(2)>70)) || ((MFI(1)<30) && (MFI(2)>30))) + { + //--- there is a signal to close a long position + ExtSignalClose=CLOSE_LONG; + ExtDirection="Long"; + } + +//--- check if there is a signal to close a short position + if(((MFI(1)>30) && (MFI(2)<30)) || ((MFI(1)>70) && (MFI(2)<70))) + { + //--- there is a signal to close a short position + ExtSignalClose=CLOSE_SHORT; + ExtDirection="Short"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| MFI indicator value at the specified bar | +//+------------------------------------------------------------------+ +double MFI(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtIndicatorHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the MFI indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ +//| SMA value at the specified bar | +//+------------------------------------------------------------------+ +double CloseAvg(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtTrendMAHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the Simple Moving Average indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Experts/Free Robots/HangingMan Hammer RSI.mq5 b/BKPS/14031218/Experts/Free Robots/HangingMan Hammer RSI.mq5 new file mode 100644 index 0000000..3ee08ba --- /dev/null +++ b/BKPS/14031218/Experts/Free Robots/HangingMan Hammer RSI.mq5 @@ -0,0 +1,677 @@ +//+------------------------------------------------------------------+ +//| HangingMan Hammer RSI.mq5 | +//| Copyright 2024, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2024, MetaQuotes Ltd." +#property link "https://www.mql5.com" +#property version "1.00" + +#include +#include + +#define SIGNAL_BUY 1 // Buy signal +#define SIGNAL_NOT 0 // no trading signal +#define SIGNAL_SELL -1 // Sell signal + +#define CLOSE_LONG 2 // signal to close Long +#define CLOSE_SHORT -2 // signal to close Short + +//--- Input parameters +input int InpAverBodyPeriod=12; // period for calculating average candlestick size +input int InpMAPeriod =5; // Trend MA period +input int InpPeriodRSI =37; // RSI period +input ENUM_APPLIED_PRICE InpPrice=PRICE_CLOSE; // price type + +//--- trade parameters +input uint InpDuration=10; // position holding time in bars +input uint InpSL =200; // Stop Loss in points +input uint InpTP =200; // Take Profit in points +input uint InpSlippage=10; // slippage in points +//--- money management parameters +input double InpLot=0.1; // lot +//--- Expert ID +input long InpMagicNumber=123300; // Magic Number + +//--- global variables +int ExtAvgBodyPeriod; // average candlestick calculation period +int ExtSignalOpen =0; // Buy/Sell signal +int ExtSignalClose =0; // signal to close a position +string ExtPatternInfo =""; // current pattern information +string ExtDirection =""; // position opening direction +bool ExtPatternDetected=false; // pattern detected +bool ExtConfirmed =false; // pattern confirmed +bool ExtCloseByTime =true; // requires closing by time +bool ExtCheckPassed =true; // status checking error +//--- indicator handles +int ExtIndicatorHandle=INVALID_HANDLE; +int ExtTrendMAHandle=INVALID_HANDLE; + +//--- service objects +CTrade ExtTrade; +CSymbolInfo ExtSymbolInfo; +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { + Print("InpSL=", InpSL); + Print("InpTP=", InpTP); +//--- set parameters for trading operations + ExtTrade.SetDeviationInPoints(InpSlippage); // slippage + ExtTrade.SetExpertMagicNumber(InpMagicNumber); // Expert Advisor ID + ExtTrade.LogLevel(LOG_LEVEL_ERRORS); // logging level + + ExtAvgBodyPeriod=InpAverBodyPeriod; +//--- indicator initialization + ExtIndicatorHandle=iRSI(_Symbol, _Period, InpPeriodRSI, InpPrice); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating CCI indicator"); + return(INIT_FAILED); + } + +//--- trend moving average + ExtTrendMAHandle=iMA(_Symbol, _Period, InpMAPeriod, 0, MODE_SMA, PRICE_CLOSE); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating Moving Average indicator"); + return(INIT_FAILED); + } + +//--- OK + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { +//--- release indicator handle + IndicatorRelease(ExtIndicatorHandle); + } +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() + { +//--- save the next bar start time; all checks at bar opening only + static datetime next_bar_open=0; + +//--- Phase 1 - check the emergence of a new bar and update the status + if(TimeCurrent()>=next_bar_open) + { + //--- get the current state of environment on the new bar + // namely, set the values of global variables: + // ExtPatternDetected - pattern detection + // ExtConfirmed - pattern confirmation + // ExtSignalOpen - signal to open + // ExtSignalClose - signal to close + // ExtPatternInfo - current pattern information + if(CheckState()) + { + //--- set the new bar opening time + next_bar_open=TimeCurrent(); + next_bar_open-=next_bar_open%PeriodSeconds(_Period); + next_bar_open+=PeriodSeconds(_Period); + + //--- report the emergence of a new bar only once within a bar + if(ExtPatternDetected && ExtConfirmed) + Print(ExtPatternInfo); + } + else + { + //--- error getting the status, retry on the next tick + return; + } + } + +//--- Phase 2 - if there is a signal and no position in this direction + if(ExtSignalOpen && !PositionExist(ExtSignalOpen)) + { + Print("\r\nSignal to open position ", ExtDirection); + PositionOpen(); + if(PositionExist(ExtSignalOpen)) + ExtSignalOpen=SIGNAL_NOT; + } + +//--- Phase 3 - close if there is a signal to close + if(ExtSignalClose && PositionExist(ExtSignalClose)) + { + Print("\r\nSignal to close position ", ExtDirection); + CloseBySignal(ExtSignalClose); + if(!PositionExist(ExtSignalClose)) + ExtSignalClose=SIGNAL_NOT; + } + +//--- Phase 4 - close upon expiration + if(ExtCloseByTime && PositionExpiredByTimeExist()) + { + CloseByTime(); + ExtCloseByTime=PositionExpiredByTimeExist(); + } + } +//+------------------------------------------------------------------+ +//| Get the current environment and check for a pattern | +//+------------------------------------------------------------------+ +bool CheckState() + { +//--- check if there is a pattern + if(!CheckPattern()) + { + Print("Error, failed to check pattern"); + return(false); + } + +//--- check for confirmation + if(!CheckConfirmation()) + { + Print("Error, failed to check pattern confirmation"); + return(false); + } +//--- if there is no confirmation, cancel the signal + if(!ExtConfirmed) + ExtSignalOpen=SIGNAL_NOT; + +//--- check if there is a signal to close a position + if(!CheckCloseSignal()) + { + Print("Error, failed to check the closing signal"); + return(false); + } + +//--- if positions are to be closed after certain holding time in bars + if(InpDuration) + ExtCloseByTime=true; // set flag to close upon expiration + +//--- all checks done + return(true); + } +//+------------------------------------------------------------------+ +//| Open a position in the direction of the signal | +//+------------------------------------------------------------------+ +bool PositionOpen() + { + ExtSymbolInfo.Refresh(); + ExtSymbolInfo.RefreshRates(); + + double price=0; +//--- Stop Loss and Take Profit are not set by default + double stoploss=0.0; + double takeprofit=0.0; + + int digits=ExtSymbolInfo.Digits(); + double point=ExtSymbolInfo.Point(); + double spread=ExtSymbolInfo.Ask()-ExtSymbolInfo.Bid(); + +//--- uptrend + if(ExtSignalOpen==SIGNAL_BUY) + { + price=NormalizeDouble(ExtSymbolInfo.Ask(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price-spread, digits); + } + else + stoploss = NormalizeDouble(price-InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price+spread, digits); + } + else + takeprofit = NormalizeDouble(price+InpTP*point, digits); + } + + if(!ExtTrade.Buy(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s buy %G at %G (sl=%G tp=%G) failed. Ask=%G error=%d", + Symbol(), InpLot, price, stoploss, takeprofit, ExtSymbolInfo.Ask(), GetLastError()); + return(false); + } + } + +//--- downtrend + if(ExtSignalOpen==SIGNAL_SELL) + { + price=NormalizeDouble(ExtSymbolInfo.Bid(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price+spread, digits); + } + else + stoploss = NormalizeDouble(price+InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price-spread, digits); + } + else + takeprofit = NormalizeDouble(price-InpTP*point, digits); + } + + if(!ExtTrade.Sell(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s sell at %G (sl=%G tp=%G) failed. Bid=%G error=%d", + Symbol(), price, stoploss, takeprofit, ExtSymbolInfo.Bid(), GetLastError()); + ExtTrade.PrintResult(); + Print(" "); + return(false); + } + } + + return(true); + } +//+------------------------------------------------------------------+ +//| Close a position based on the specified signal | +//+------------------------------------------------------------------+ +void CloseBySignal(int type_close) + { +//--- if there is no signal to close, return successful completion + if(type_close==SIGNAL_NOT) + return; +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalClose)==0) + return; + +//--- closing direction + long type; + switch(type_close) + { + case CLOSE_SHORT: + type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + type=POSITION_TYPE_BUY; + break; + default: + Print("Error! Signal to close not detected"); + return; + } + +//--- check all positions and close ours based on the signal + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + if(PositionGetInteger(POSITION_TYPE)==type) + { + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Close positions upon holding time expiration in bars | +//+------------------------------------------------------------------+ +void CloseByTime() + { +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalOpen)==0) + return; + +//--- check all positions and close ours based on the holding time in bars + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + //--- position opening time + datetime open_time=(datetime)PositionGetInteger(POSITION_TIME); + //--- check position holding time in bars + if(BarsHold(open_time)>=(int)InpDuration) + { + Print("\r\nTime to close position #", ticket); + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Returns true if there are open positions | +//+------------------------------------------------------------------+ +bool PositionExist(int signal_direction) + { + bool check_type=(signal_direction!=SIGNAL_NOT); + +//--- what positions to search + ENUM_POSITION_TYPE search_type=WRONG_VALUE; + if(check_type) + switch(signal_direction) + { + case SIGNAL_BUY: + search_type=POSITION_TYPE_BUY; + break; + case SIGNAL_SELL: + search_type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + search_type=POSITION_TYPE_BUY; + break; + case CLOSE_SHORT: + search_type=POSITION_TYPE_SELL; + break; + default: + //--- entry direction is not specified; nothing to search + return(false); + } + +//--- go through the list of all positions + int positions=PositionsTotal(); + for(int i=0; i=(int)InpDuration)) + return(true); + } + } + } + +//--- open position not found + return(false); + } +//+------------------------------------------------------------------+ +//| Checks position closing time in bars | +//+------------------------------------------------------------------+ +int BarsHold(datetime open_time) + { +//--- first run a basic simple check + if(TimeCurrent()-open_timeCloseAvg(2)) && // up trend + (MathMin(Open(1), Close(1))> (High(1)-(High(1)-Low(1))/3.0)) && // body in upper 1/3 + (Close(1)>Close(2)) && (Open(1)>Open(2))) // body gap + { + ExtPatternDetected=true; + ExtSignalOpen=SIGNAL_SELL; + ExtPatternInfo="\r\nHanging Man detected"; + ExtDirection="Sell"; + return(true); + } + +//--- check Hammer + if((MidPoint(1)(High(1)-(High(1)-Low(1))/3.0)) && // body in upper 1/3 + (Close(1)60)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: RSI>60"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| Check if there is a signal to close | +//+------------------------------------------------------------------+ +bool CheckCloseSignal() + { + ExtSignalClose=false; +//--- if there is a signal to enter the market, do not check the signal to close + if(ExtSignalOpen!=SIGNAL_NOT) + return(true); + +//--- check if there is a signal to close a long position + if(((RSI(1)<70) && (RSI(2)>70)) || ((RSI(1)<30) && (RSI(2)>30))) + { + //--- there is a signal to close a long position + ExtSignalClose=CLOSE_LONG; + ExtDirection="Long"; + } + +//--- check if there is a signal to close a short position + if(((RSI(1)>30) && (RSI(2)<30)) || ((RSI(1)>70) && (RSI(2)<70))) + { + //--- there is a signal to close a short position + ExtSignalClose=CLOSE_SHORT; + ExtDirection="Short"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| RSI indicator value at the specified bar | +//+------------------------------------------------------------------+ +double RSI(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtIndicatorHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the RSI indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ +//| SMA value at the specified bar | +//+------------------------------------------------------------------+ +double CloseAvg(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtTrendMAHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the Simple Moving Average indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Experts/Free Robots/HangingMan Hammer Stoch.mq5 b/BKPS/14031218/Experts/Free Robots/HangingMan Hammer Stoch.mq5 new file mode 100644 index 0000000..d64b8e0 --- /dev/null +++ b/BKPS/14031218/Experts/Free Robots/HangingMan Hammer Stoch.mq5 @@ -0,0 +1,683 @@ +//+------------------------------------------------------------------+ +//| HangingMan Hammer Stoch.mq5 | +//| Copyright 2024, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2024, MetaQuotes Ltd." +#property link "https://www.mql5.com" +#property version "1.00" + +#include +#include + +#define SIGNAL_BUY 1 // Buy signal +#define SIGNAL_NOT 0 // no trading signal +#define SIGNAL_SELL -1 // Sell signal + +#define CLOSE_LONG 2 // signal to close Long +#define CLOSE_SHORT -2 // signal to close Short + +//--- Input parameters +input int InpAverBodyPeriod=12; // period for calculating average candlestick size +input int InpMAPeriod =5; // Trend MA period +input int InpStochK =47; // period %K +input int InpStochD =9; // period %D +input int InpStochSlow =13; // smoothing period %K +input ENUM_STO_PRICE InpStochApplied=STO_LOWHIGH; // calculation type +input ENUM_MA_METHOD InpStochMA =MODE_SMA; // smoothing type + +//--- trade parameters +input uint InpDuration=10; // position holding time in bars +input uint InpSL =200; // Stop Loss in points +input uint InpTP =200; // Take Profit in points +input uint InpSlippage=10; // slippage in points +//--- money management parameters +input double InpLot=0.1; // lot +//--- Expert ID +input long InpMagicNumber=124400; // Magic Number + +//--- global variables +int ExtAvgBodyPeriod; // average candlestick calculation period +int ExtSignalOpen =0; // Buy/Sell signal +int ExtSignalClose =0; // signal to close a position +string ExtPatternInfo =""; // current pattern information +string ExtDirection =""; // position opening direction +bool ExtPatternDetected=false; // pattern detected +bool ExtConfirmed =false; // pattern confirmed +bool ExtCloseByTime =true; // requires closing by time +bool ExtCheckPassed =true; // status checking error +//--- indicator handles +int ExtIndicatorHandle=INVALID_HANDLE; +int ExtTrendMAHandle=INVALID_HANDLE; + +//--- service objects +CTrade ExtTrade; +CSymbolInfo ExtSymbolInfo; +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { + Print("InpSL=", InpSL); + Print("InpTP=", InpTP); +//--- set parameters for trading operations + ExtTrade.SetDeviationInPoints(InpSlippage); // slippage + ExtTrade.SetExpertMagicNumber(InpMagicNumber); // Expert Advisor ID + ExtTrade.LogLevel(LOG_LEVEL_ERRORS); // logging level + + ExtAvgBodyPeriod=InpAverBodyPeriod; +//--- indicator initialization + ExtIndicatorHandle=iStochastic(_Symbol, _Period, InpStochK, InpStochD, InpStochSlow, InpStochMA, InpStochApplied); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating iStochastic indicator"); + return(INIT_FAILED); + } + +//--- trend moving average + ExtTrendMAHandle=iMA(_Symbol, _Period, InpMAPeriod,0, MODE_SMA,PRICE_CLOSE); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating Moving Average indicator"); + return(INIT_FAILED); + } + +//--- OK + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { +//--- release indicator handle + IndicatorRelease(ExtIndicatorHandle); + } +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() + { +//--- save the next bar start time; all checks at bar opening only + static datetime next_bar_open=0; + +//--- Phase 1 - check the emergence of a new bar and update the status + if(TimeCurrent()>=next_bar_open) + { + //--- get the current state of environment on the new bar + // namely, set the values of global variables: + // ExtPatternDetected - pattern detection + // ExtConfirmed - pattern confirmation + // ExtSignalOpen - signal to open + // ExtSignalClose - signal to close + // ExtPatternInfo - current pattern information + if(CheckState()) + { + //--- set the new bar opening time + next_bar_open=TimeCurrent(); + next_bar_open-=next_bar_open%PeriodSeconds(_Period); + next_bar_open+=PeriodSeconds(_Period); + + //--- report the emergence of a new bar only once within a bar + if(ExtPatternDetected && ExtConfirmed) + Print(ExtPatternInfo); + } + else + { + //--- error getting the status, retry on the next tick + return; + } + } + +//--- Phase 2 - if there is a signal and no position in this direction + if(ExtSignalOpen && !PositionExist(ExtSignalOpen)) + { + Print("\r\nSignal to open position ", ExtDirection); + PositionOpen(); + if(PositionExist(ExtSignalOpen)) + ExtSignalOpen=SIGNAL_NOT; + } + +//--- Phase 3 - close if there is a signal to close + if(ExtSignalClose && PositionExist(ExtSignalClose)) + { + Print("\r\nSignal to close position ", ExtDirection); + CloseBySignal(ExtSignalClose); + if(!PositionExist(ExtSignalClose)) + ExtSignalClose=SIGNAL_NOT; + } + +//--- Phase 4 - close upon expiration + if(ExtCloseByTime && PositionExpiredByTimeExist()) + { + CloseByTime(); + ExtCloseByTime=PositionExpiredByTimeExist(); + } + } +//+------------------------------------------------------------------+ +//| Get the current environment and check for a pattern | +//+------------------------------------------------------------------+ +bool CheckState() + { +//--- check if there is a pattern + if(!CheckPattern()) + { + Print("Error, failed to check pattern"); + return(false); + } + +//--- check for confirmation + if(!CheckConfirmation()) + { + Print("Error, failed to check pattern confirmation"); + return(false); + } +//--- if there is no confirmation, cancel the signal + if(!ExtConfirmed) + ExtSignalOpen=SIGNAL_NOT; + +//--- check if there is a signal to close a position + if(!CheckCloseSignal()) + { + Print("Error, failed to check the closing signal"); + return(false); + } + +//--- if positions are to be closed after certain holding time in bars + if(InpDuration) + ExtCloseByTime=true; // set flag to close upon expiration + +//--- all checks done + return(true); + } +//+------------------------------------------------------------------+ +//| Open a position in the direction of the signal | +//+------------------------------------------------------------------+ +bool PositionOpen() + { + ExtSymbolInfo.Refresh(); + ExtSymbolInfo.RefreshRates(); + + double price=0; +//--- Stop Loss and Take Profit are not set by default + double stoploss=0.0; + double takeprofit=0.0; + + int digits=ExtSymbolInfo.Digits(); + double point=ExtSymbolInfo.Point(); + double spread=ExtSymbolInfo.Ask()-ExtSymbolInfo.Bid(); + +//--- uptrend + if(ExtSignalOpen==SIGNAL_BUY) + { + price=NormalizeDouble(ExtSymbolInfo.Ask(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price-spread, digits); + } + else + stoploss = NormalizeDouble(price-InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price+spread, digits); + } + else + takeprofit = NormalizeDouble(price+InpTP*point, digits); + } + + if(!ExtTrade.Buy(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s buy %G at %G (sl=%G tp=%G) failed. Ask=%G error=%d", + Symbol(), InpLot, price, stoploss, takeprofit, ExtSymbolInfo.Ask(), GetLastError()); + return(false); + } + } + +//--- downtrend + if(ExtSignalOpen==SIGNAL_SELL) + { + price=NormalizeDouble(ExtSymbolInfo.Bid(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price+spread, digits); + } + else + stoploss = NormalizeDouble(price+InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price-spread, digits); + } + else + takeprofit = NormalizeDouble(price-InpTP*point, digits); + } + + if(!ExtTrade.Sell(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s sell at %G (sl=%G tp=%G) failed. Bid=%G error=%d", + Symbol(), price, stoploss, takeprofit, ExtSymbolInfo.Bid(), GetLastError()); + ExtTrade.PrintResult(); + Print(" "); + return(false); + } + } +//--- + return(true); + } +//+------------------------------------------------------------------+ +//| Close a position based on the specified signal | +//+------------------------------------------------------------------+ +void CloseBySignal(int type_close) + { +//--- if there is no signal to close, return successful completion + if(type_close==SIGNAL_NOT) + return; +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalClose)==0) + return; + +//--- closing direction + long type; + switch(type_close) + { + case CLOSE_SHORT: + type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + type=POSITION_TYPE_BUY; + break; + default: + Print("Error! Signal to close not detected"); + return; + } + +//--- check all positions and close ours based on the signal + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + if(PositionGetInteger(POSITION_TYPE)==type) + { + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Close positions upon holding time expiration in bars | +//+------------------------------------------------------------------+ +void CloseByTime() + { +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalOpen)==0) + return; + +//--- check all positions and close ours based on the holding time in bars + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + //--- position opening time + datetime open_time=(datetime)PositionGetInteger(POSITION_TIME); + //--- check position holding time in bars + if(BarsHold(open_time)>=(int)InpDuration) + { + Print("\r\nTime to close position #", ticket); + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Returns true if there are open positions | +//+------------------------------------------------------------------+ +bool PositionExist(int signal_direction) + { + bool check_type=(signal_direction!=SIGNAL_NOT); + +//--- what positions to search + ENUM_POSITION_TYPE search_type=WRONG_VALUE; + if(check_type) + switch(signal_direction) + { + case SIGNAL_BUY: + search_type=POSITION_TYPE_BUY; + break; + case SIGNAL_SELL: + search_type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + search_type=POSITION_TYPE_BUY; + break; + case CLOSE_SHORT: + search_type=POSITION_TYPE_SELL; + break; + default: + //--- entry direction is not specified; nothing to search + return(false); + } + +//--- go through the list of all positions + int positions=PositionsTotal(); + for(int i=0; i=(int)InpDuration)) + return(true); + } + } + } + +//--- open position not found + return(false); + } +//+------------------------------------------------------------------+ +//| Checks position closing time in bars | +//+------------------------------------------------------------------+ +int BarsHold(datetime open_time) + { +//--- first run a basic simple check + if(TimeCurrent()-open_timeCloseAvg(2)) && // up trend + (MathMin(Open(1), Close(1))> (High(1)-(High(1)-Low(1))/3.0)) && // body in upper 1/3 + (Close(1)>Close(2)) && (Open(1)>Open(2))) // body gap + { + ExtPatternDetected=true; + ExtSignalOpen=SIGNAL_SELL; + ExtPatternInfo="\r\nHanging Man detected"; + ExtDirection="Sell"; + return(true); + } + + +//--- check Hammer + if((MidPoint(1)(High(1)-(High(1)-Low(1))/3.0)) && // body in upper 1/3 + (Close(1)70)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: StochSignal>70"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| Check if there is a signal to close | +//+------------------------------------------------------------------+ +bool CheckCloseSignal() + { + ExtSignalClose=false; +//--- if there is a signal to enter the market, do not check the signal to close + if(ExtSignalOpen!=SIGNAL_NOT) + return(true); + +//--- check if there is a signal to close a long position + if(((StochSignal(1)<80) && (StochSignal(2)>80))|| // 80 crossed downwards + ((StochSignal(1)<20) && (StochSignal(2)>20))) // 20 crossed downwards + { + //--- there is a signal to close a long position + ExtSignalClose=CLOSE_LONG; + ExtDirection="Long"; + } + +//--- check if there is a signal to close a short position + if((((StochSignal(1)>20) && (StochSignal(2)<20)) || // 20 crossed upwards + ((StochSignal(1)>80) && (StochSignal(2)<80)))) // 80 crossed upwards + { + //--- there is a signal to close a short position + ExtSignalClose=CLOSE_SHORT; + ExtDirection="Short"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| Stochastic indicator value at the specified bar | +//+------------------------------------------------------------------+ +double StochSignal(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtIndicatorHandle, SIGNAL_LINE, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the iStochastic indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ +//| SMA value at the specified bar | +//+------------------------------------------------------------------+ +double CloseAvg(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtTrendMAHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the Simple Moving Average indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Experts/Free Robots/MorningEvening StarDoji CCI.mq5 b/BKPS/14031218/Experts/Free Robots/MorningEvening StarDoji CCI.mq5 new file mode 100644 index 0000000..c6338a1 --- /dev/null +++ b/BKPS/14031218/Experts/Free Robots/MorningEvening StarDoji CCI.mq5 @@ -0,0 +1,685 @@ +//+------------------------------------------------------------------+ +//| MorningEvening StarDoji CCI.mq5 | +//| Copyright 2024, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2024, MetaQuotes Ltd." +#property link "https://www.mql5.com" +#property version "1.00" + +#include +#include + +#define SIGNAL_BUY 1 // Buy signal +#define SIGNAL_NOT 0 // no trading signal +#define SIGNAL_SELL -1 // Sell signal + +#define CLOSE_LONG 2 // signal to close Long +#define CLOSE_SHORT -2 // signal to close Short + +//--- Input parameters +input int InpAverBodyPeriod=12; // period for calculating average candlestick size +input int InpPeriodCCI =37; // CCI period +input ENUM_APPLIED_PRICE InpPrice=PRICE_CLOSE; // price type + +//--- trade parameters +input uint InpDuration =10; // position holding time in bars +input uint InpSL =200; // Stop Loss in points +input uint InpTP =200; // Take Profit in points +input uint InpSlippage =10; // slippage in points +//--- money management parameters +input double InpLot=0.1; // lot +//--- Expert ID +input long InpMagicNumber=130100; // Magic Number + +//--- global variables +int ExtAvgBodyPeriod; // average candlestick calculation period +int ExtSignalOpen =0; // Buy/Sell signal +int ExtSignalClose =0; // signal to close a position +string ExtPatternInfo =""; // current pattern information +string ExtDirection =""; // position opening direction +bool ExtPatternDetected=false; // pattern detected +bool ExtConfirmed =false; // pattern confirmed +bool ExtCloseByTime =true; // requires closing by time +bool ExtCheckPassed =true; // status checking error +//--- indicator handle +int ExtIndicatorHandle=INVALID_HANDLE; + +//--- service objects +CTrade ExtTrade; +CSymbolInfo ExtSymbolInfo; +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { + Print("InpSL=", InpSL); + Print("InpTP=", InpTP); +//--- set parameters for trading operations + ExtTrade.SetDeviationInPoints(InpSlippage); // slippage + ExtTrade.SetExpertMagicNumber(InpMagicNumber); // Expert Advisor ID + ExtTrade.LogLevel(LOG_LEVEL_ERRORS); // logging level + + ExtAvgBodyPeriod=InpAverBodyPeriod; +//--- indicator initialization + ExtIndicatorHandle=iCCI(_Symbol, _Period, InpPeriodCCI, InpPrice); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating CCI indicator"); + return(INIT_FAILED); + } +//--- OK + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { +//--- release indicator handle + IndicatorRelease(ExtIndicatorHandle); + } +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() + { +//--- save the next bar start time; all checks at bar opening only + static datetime next_bar_open=0; + +//--- Phase 1 - check the emergence of a new bar and update the status + if(TimeCurrent()>=next_bar_open) + { + //--- get the current state of environment on the new bar + // namely, set the values of global variables: + // ExtPatternDetected - pattern detection + // ExtConfirmed - pattern confirmation + // ExtSignalOpen - signal to open + // ExtSignalClose - signal to close + // ExtPatternInfo - current pattern information + if(CheckState()) + { + //--- set the new bar opening time + next_bar_open=TimeCurrent(); + next_bar_open-=next_bar_open%PeriodSeconds(_Period); + next_bar_open+=PeriodSeconds(_Period); + + //--- report the emergence of a new bar only once within a bar + if(ExtPatternDetected && ExtConfirmed) + Print(ExtPatternInfo); + } + else + { + //--- error getting the status, retry on the next tick + return; + } + } + +//--- Phase 2 - if there is a signal and no position in this direction + if(ExtSignalOpen && !PositionExist(ExtSignalOpen)) + { + Print("\r\nSignal to open position ", ExtDirection); + PositionOpen(); + if(PositionExist(ExtSignalOpen)) + ExtSignalOpen=SIGNAL_NOT; + } + +//--- Phase 3 - close if there is a signal to close + if(ExtSignalClose && PositionExist(ExtSignalClose)) + { + Print("\r\nSignal to close position ", ExtDirection); + CloseBySignal(ExtSignalClose); + if(!PositionExist(ExtSignalClose)) + ExtSignalClose=SIGNAL_NOT; + } + +//--- Phase 4 - close upon expiration + if(ExtCloseByTime && PositionExpiredByTimeExist()) + { + CloseByTime(); + ExtCloseByTime=PositionExpiredByTimeExist(); + } + } +//+------------------------------------------------------------------+ +//| Get the current environment and check for a pattern | +//+------------------------------------------------------------------+ +bool CheckState() + { +//--- check if there is a pattern + if(!CheckPattern()) + { + Print("Error, failed to check pattern"); + return(false); + } + +//--- check for confirmation + if(!CheckConfirmation()) + { + Print("Error, failed to check pattern confirmation"); + return(false); + } +//--- if there is no confirmation, cancel the signal + if(!ExtConfirmed) + ExtSignalOpen=SIGNAL_NOT; + +//--- check if there is a signal to close a position + if(!CheckCloseSignal()) + { + Print("Error, failed to check the closing signal"); + return(false); + } + +//--- if positions are to be closed after certain holding time in bars + if(InpDuration) + ExtCloseByTime=true; // set flag to close upon expiration + +//--- all checks done + return(true); + } +//+------------------------------------------------------------------+ +//| Open a position in the direction of the signal | +//+------------------------------------------------------------------+ +bool PositionOpen() + { + ExtSymbolInfo.Refresh(); + ExtSymbolInfo.RefreshRates(); + + double price=0; +//--- Stop Loss and Take Profit are not set by default + double stoploss=0.0; + double takeprofit=0.0; + + int digits=ExtSymbolInfo.Digits(); + double point=ExtSymbolInfo.Point(); + double spread=ExtSymbolInfo.Ask()-ExtSymbolInfo.Bid(); + +//--- uptrend + if(ExtSignalOpen==SIGNAL_BUY) + { + price=NormalizeDouble(ExtSymbolInfo.Ask(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price-spread, digits); + } + else + stoploss = NormalizeDouble(price-InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price+spread, digits); + } + else + takeprofit = NormalizeDouble(price+InpTP*point, digits); + } + + if(!ExtTrade.Buy(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s buy %G at %G (sl=%G tp=%G) failed. Ask=%G error=%d", + Symbol(), InpLot, price, stoploss, takeprofit, ExtSymbolInfo.Ask(), GetLastError()); + return(false); + } + } + +//--- downtrend + if(ExtSignalOpen==SIGNAL_SELL) + { + price=NormalizeDouble(ExtSymbolInfo.Bid(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price+spread, digits); + } + else + stoploss = NormalizeDouble(price+InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price-spread, digits); + } + else + takeprofit = NormalizeDouble(price-InpTP*point, digits); + } + + if(!ExtTrade.Sell(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s sell at %G (sl=%G tp=%G) failed. Bid=%G error=%d", + Symbol(), price, stoploss, takeprofit, ExtSymbolInfo.Bid(), GetLastError()); + ExtTrade.PrintResult(); + Print(" "); + return(false); + } + } + + return(true); + } +//+------------------------------------------------------------------+ +//| Close a position based on the specified signal | +//+------------------------------------------------------------------+ +void CloseBySignal(int type_close) + { +//--- if there is no signal to close, return successful completion + if(type_close==SIGNAL_NOT) + return; +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalClose)==0) + return; + +//--- closing direction + long type; + switch(type_close) + { + case CLOSE_SHORT: + type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + type=POSITION_TYPE_BUY; + break; + default: + Print("Error! Signal to close not detected"); + return; + } + +//--- check all positions and close ours based on the signal + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + if(PositionGetInteger(POSITION_TYPE)==type) + { + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Close positions upon holding time expiration in bars | +//+------------------------------------------------------------------+ +void CloseByTime() + { +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalOpen)==0) + return; + +//--- check all positions and close ours based on the holding time in bars + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + //--- position opening time + datetime open_time=(datetime)PositionGetInteger(POSITION_TIME); + //--- check position holding time in bars + if(BarsHold(open_time)>=(int)InpDuration) + { + Print("\r\nTime to close position #", ticket); + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Returns true if there are open positions | +//+------------------------------------------------------------------+ +bool PositionExist(int signal_direction) + { + bool check_type=(signal_direction!=SIGNAL_NOT); + +//--- what positions to search + ENUM_POSITION_TYPE search_type=WRONG_VALUE; + if(check_type) + switch(signal_direction) + { + case SIGNAL_BUY: + search_type=POSITION_TYPE_BUY; + break; + case SIGNAL_SELL: + search_type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + search_type=POSITION_TYPE_BUY; + break; + case CLOSE_SHORT: + search_type=POSITION_TYPE_SELL; + break; + default: + //--- entry direction is not specified; nothing to search + return(false); + } + +//--- go through the list of all positions + int positions=PositionsTotal(); + for(int i=0; i=(int)InpDuration)) + return(true); + } + } + } +//--- open position not found + return(false); + } +//+------------------------------------------------------------------+ +//| Checks position closing time in bars | +//+------------------------------------------------------------------+ +int BarsHold(datetime open_time) + { +//--- first run a basic simple check + if(TimeCurrent()-open_timeAvgBody(1)) && // bullish candlestick, its body is larger than average + (MathAbs(Close(2)-Open(2))Close(3)) && // second candlestick close is higher than first candlestick close + (Open(2)>Open(3)) && // second candlestick open is higher than first candlestick open + (Open(1)AvgBody(1)) && // bullish candlestick, its body is larger than average + (MathAbs(Close(2)-Open(2))Close(3)) && // second candlestick close is higher than first candlestick close + (Open(2)>Open(3)) && // second candlestick open is higher than first candlestick open + (Close(1)AvgBody(1)) && // bearish candlestick, its body is larger than average + (MathAbs(Close(2)-Open(2))Close(2)) && // upward price gap on the last candlestick + (Close(1)>Close(2))) // last candlestick close higher than second candlestick close + { + ExtPatternDetected=true; + ExtSignalOpen=SIGNAL_BUY; + ExtPatternInfo="\r\nMorning Doji detected"; + ExtDirection="Buy"; + return(true); + } + +//--- check Morning Star + if((Open(3)-Close(3)>AvgBody(1)) && // bearish candlestick, its body is larger than average + (MathAbs(Close(2)-Open(2))MidOpenClose(3))) // last candlestick close is lower than the middle of the first (bearish) one + { + ExtPatternDetected=true; + ExtSignalOpen=SIGNAL_BUY; + ExtPatternInfo="\r\nMorning Star detected"; + ExtDirection="Buy"; + return(true); + } + +//--- result of checking + return(ExtCheckPassed); + } +//+------------------------------------------------------------------+ +//| Returns true in case of successful confirmation check | +//+------------------------------------------------------------------+ +bool CheckConfirmation() + { + ExtConfirmed=false; +//--- if there is no pattern, do not search for confirmation + if(!ExtPatternDetected) + return(true); + +//--- get the value of the stochastic indicator to confirm the signal + double signal=CCI(1); + if(signal==EMPTY_VALUE) + { + //--- failed to get indicator value, check failed + return(false); + } + +//--- check the Buy signal + if(ExtSignalOpen==SIGNAL_BUY && (signal<-50)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: CCI<-50"; + } + +//--- check the Sell signal + if(ExtSignalOpen==SIGNAL_SELL && (signal>50)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: CCI>50"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| Check if there is a signal to close | +//+------------------------------------------------------------------+ +bool CheckCloseSignal() + { + ExtSignalClose=false; +//--- if there is a signal to enter the market, do not check the signal to close + if(ExtSignalOpen!=SIGNAL_NOT) + return(true); + +//--- check if there is a signal to close a long position + if(((CCI(1)<80) && (CCI(2)>80)) || ((CCI(1)<-80) && (CCI(2)>-80))) + { + //--- there is a signal to close a long position + ExtSignalClose=CLOSE_LONG; + ExtDirection="Long"; + } + +//--- check if there is a signal to close a short position + if(((CCI(1)>-80) && (CCI(2)<-80)) || ((CCI(1)>80) && (CCI(2)<80))) + { + //--- there is a signal to close a short position + ExtSignalClose=CLOSE_SHORT; + ExtDirection="Short"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| CCI indicator value at the specified bar | +//+------------------------------------------------------------------+ +double CCI(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtIndicatorHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the CCI indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Experts/Free Robots/MorningEvening StarDoji MFI.mq5 b/BKPS/14031218/Experts/Free Robots/MorningEvening StarDoji MFI.mq5 new file mode 100644 index 0000000..0771bc5 --- /dev/null +++ b/BKPS/14031218/Experts/Free Robots/MorningEvening StarDoji MFI.mq5 @@ -0,0 +1,686 @@ +//+------------------------------------------------------------------+ +//| MorningEvening StarDoji MFI.mq5 | +//| Copyright 2024, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2024, MetaQuotes Ltd." +#property link "https://www.mql5.com" +#property version "1.00" + +#include +#include + +#define SIGNAL_BUY 1 // Buy signal +#define SIGNAL_NOT 0 // no trading signal +#define SIGNAL_SELL -1 // Sell signal + +#define CLOSE_LONG 2 // signal to close Long +#define CLOSE_SHORT -2 // signal to close Short + +//--- Input parameters +input int InpAverBodyPeriod=12; // period for calculating average candlestick size +input int InpPeriodMFI =37; // MFI period +input ENUM_APPLIED_VOLUME InpVolume=VOLUME_TICK; // volume type + +//--- trade parameters +input uint InpDuration=10; // position holding time in bars +input uint InpSL =200; // Stop Loss in points +input uint InpTP =200; // Take Profit in points +input uint InpSlippage=10; // slippage in points +//--- money management parameters +input double InpLot=0.1; // lot +//--- Expert ID +input long InpMagicNumber=130200; // Magic Number + +//--- global variables +int ExtAvgBodyPeriod; // average candlestick calculation period +int ExtSignalOpen =0; // Buy/Sell signal +int ExtSignalClose =0; // signal to close a position +string ExtPatternInfo =""; // current pattern information +string ExtDirection =""; // position opening direction +bool ExtPatternDetected=false; // pattern detected +bool ExtConfirmed =false; // pattern confirmed +bool ExtCloseByTime =true; // requires closing by time +bool ExtCheckPassed =true; // status checking error +//--- indicator handle +int ExtIndicatorHandle=INVALID_HANDLE; + +//--- service objects +CTrade ExtTrade; +CSymbolInfo ExtSymbolInfo; +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { + Print("InpSL=", InpSL); + Print("InpTP=", InpTP); +//--- set parameters for trading operations + ExtTrade.SetDeviationInPoints(InpSlippage); // slippage + ExtTrade.SetExpertMagicNumber(InpMagicNumber); // Expert Advisor ID + ExtTrade.LogLevel(LOG_LEVEL_ERRORS); // logging level + + ExtAvgBodyPeriod=InpAverBodyPeriod; +//--- indicator initialization + ExtIndicatorHandle=iMFI(_Symbol, _Period, InpPeriodMFI, InpVolume); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating MFI indicator"); + return(INIT_FAILED); + } +//--- OK + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { +//--- release indicator handle + IndicatorRelease(ExtIndicatorHandle); + } +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() + { +//--- save the next bar start time; all checks at bar opening only + static datetime next_bar_open=0; + +//--- Phase 1 - check the emergence of a new bar and update the status + if(TimeCurrent()>=next_bar_open) + { + //--- get the current state of environment on the new bar + // namely, set the values of global variables: + // ExtPatternDetected - pattern detection + // ExtConfirmed - pattern confirmation + // ExtSignalOpen - signal to open + // ExtSignalClose - signal to close + // ExtPatternInfo - current pattern information + if(CheckState()) + { + //--- set the new bar opening time + next_bar_open=TimeCurrent(); + next_bar_open-=next_bar_open%PeriodSeconds(_Period); + next_bar_open+=PeriodSeconds(_Period); + + //--- report the emergence of a new bar only once within a bar + if(ExtPatternDetected && ExtConfirmed) + Print(ExtPatternInfo); + } + else + { + //--- error getting the status, retry on the next tick + return; + } + } + +//--- Phase 2 - if there is a signal and no position in this direction + if(ExtSignalOpen && !PositionExist(ExtSignalOpen)) + { + Print("\r\nSignal to open position ", ExtDirection); + PositionOpen(); + if(PositionExist(ExtSignalOpen)) + ExtSignalOpen=SIGNAL_NOT; + } + +//--- Phase 3 - close if there is a signal to close + if(ExtSignalClose && PositionExist(ExtSignalClose)) + { + Print("\r\nSignal to close position ", ExtDirection); + CloseBySignal(ExtSignalClose); + if(!PositionExist(ExtSignalClose)) + ExtSignalClose=SIGNAL_NOT; + } + +//--- Phase 4 - close upon expiration + if(ExtCloseByTime && PositionExpiredByTimeExist()) + { + CloseByTime(); + ExtCloseByTime=PositionExpiredByTimeExist(); + } + } +//+------------------------------------------------------------------+ +//| Get the current environment and check for a pattern | +//+------------------------------------------------------------------+ +bool CheckState() + { +//--- check if there is a pattern + if(!CheckPattern()) + { + Print("Error, failed to check pattern"); + return(false); + } + +//--- check for confirmation + if(!CheckConfirmation()) + { + Print("Error, failed to check pattern confirmation"); + return(false); + } +//--- if there is no confirmation, cancel the signal + if(!ExtConfirmed) + ExtSignalOpen=SIGNAL_NOT; + +//--- check if there is a signal to close a position + if(!CheckCloseSignal()) + { + Print("Error, failed to check the closing signal"); + return(false); + } + +//--- if positions are to be closed after certain holding time in bars + if(InpDuration) + ExtCloseByTime=true; // set flag to close upon expiration + +//--- all checks done + return(true); + } +//+------------------------------------------------------------------+ +//| Open a position in the direction of the signal | +//+------------------------------------------------------------------+ +bool PositionOpen() + { + ExtSymbolInfo.Refresh(); + ExtSymbolInfo.RefreshRates(); + + double price=0; +//--- Stop Loss and Take Profit are not set by default + double stoploss=0.0; + double takeprofit=0.0; + + int digits=ExtSymbolInfo.Digits(); + double point=ExtSymbolInfo.Point(); + double spread=ExtSymbolInfo.Ask()-ExtSymbolInfo.Bid(); + +//--- uptrend + if(ExtSignalOpen==SIGNAL_BUY) + { + price=NormalizeDouble(ExtSymbolInfo.Ask(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price-spread, digits); + } + else + stoploss = NormalizeDouble(price-InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price+spread, digits); + } + else + takeprofit = NormalizeDouble(price+InpTP*point, digits); + } + + if(!ExtTrade.Buy(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s buy %G at %G (sl=%G tp=%G) failed. Ask=%G error=%d", + Symbol(), InpLot, price, stoploss, takeprofit, ExtSymbolInfo.Ask(), GetLastError()); + return(false); + } + } + +//--- downtrend + if(ExtSignalOpen==SIGNAL_SELL) + { + price=NormalizeDouble(ExtSymbolInfo.Bid(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price+spread, digits); + } + else + stoploss = NormalizeDouble(price+InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price-spread, digits); + } + else + takeprofit = NormalizeDouble(price-InpTP*point, digits); + } + + if(!ExtTrade.Sell(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s sell at %G (sl=%G tp=%G) failed. Bid=%G error=%d", + Symbol(), price, stoploss, takeprofit, ExtSymbolInfo.Bid(), GetLastError()); + ExtTrade.PrintResult(); + Print(" "); + return(false); + } + } + + return(true); + } +//+------------------------------------------------------------------+ +//| Close a position based on the specified signal | +//+------------------------------------------------------------------+ +void CloseBySignal(int type_close) + { +//--- if there is no signal to close, return successful completion + if(type_close==SIGNAL_NOT) + return; +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalClose)==0) + return; + +//--- closing direction + long type; + switch(type_close) + { + case CLOSE_SHORT: + type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + type=POSITION_TYPE_BUY; + break; + default: + Print("Error! Signal to close not detected"); + return; + } + +//--- check all positions and close ours based on the signal + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + if(PositionGetInteger(POSITION_TYPE)==type) + { + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Close positions upon holding time expiration in bars | +//+------------------------------------------------------------------+ +void CloseByTime() + { +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalOpen)==0) + return; + +//--- check all positions and close ours based on the holding time in bars + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + //--- position opening time + datetime open_time=(datetime)PositionGetInteger(POSITION_TIME); + //--- check position holding time in bars + if(BarsHold(open_time)>=(int)InpDuration) + { + Print("\r\nTime to close position #", ticket); + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Returns true if there are open positions | +//+------------------------------------------------------------------+ +bool PositionExist(int signal_direction) + { + bool check_type=(signal_direction!=SIGNAL_NOT); + +//--- what positions to search + ENUM_POSITION_TYPE search_type=WRONG_VALUE; + if(check_type) + switch(signal_direction) + { + case SIGNAL_BUY: + search_type=POSITION_TYPE_BUY; + break; + case SIGNAL_SELL: + search_type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + search_type=POSITION_TYPE_BUY; + break; + case CLOSE_SHORT: + search_type=POSITION_TYPE_SELL; + break; + default: + //--- entry direction is not specified; nothing to search + return(false); + } + +//--- go through the list of all positions + int positions=PositionsTotal(); + for(int i=0; i=(int)InpDuration)) + return(true); + } + } + } + +//--- open position not found + return(false); + } +//+------------------------------------------------------------------+ +//| Checks position closing time in bars | +//+------------------------------------------------------------------+ +int BarsHold(datetime open_time) + { +//--- first run a basic simple check + if(TimeCurrent()-open_timeAvgBody(1)) && // bullish candlestick, its body is larger than average + (MathAbs(Close(2)-Open(2))Close(3)) && // second candlestick close is higher than first candlestick close + (Open(2)>Open(3)) && // second candlestick open is higher than first candlestick open + (Open(1)AvgBody(1)) && // bullish candlestick, its body is larger than average + (MathAbs(Close(2)-Open(2))Close(3)) && // second candlestick close is higher than first candlestick close + (Open(2)>Open(3)) && // second candlestick open is higher than first candlestick open + (Close(1)AvgBody(1)) && // bearish candlestick, its body is larger than average + (MathAbs(Close(2)-Open(2))Close(2)) && // upward price gap on the last candlestick + (Close(1)>Close(2))) // last candlestick close higher than second candlestick close + { + ExtPatternDetected=true; + ExtSignalOpen=SIGNAL_BUY; + ExtPatternInfo="\r\nMorning Doji detected"; + ExtDirection="Buy"; + return(true); + } + +//--- check Morning Star + if((Open(3)-Close(3)>AvgBody(1)) && // bearish candlestick, its body is larger than average + (MathAbs(Close(2)-Open(2))MidOpenClose(3))) // last candlestick close is lower than the middle of the first (bearish) one + { + ExtPatternDetected=true; + ExtSignalOpen=SIGNAL_BUY; + ExtPatternInfo="\r\nMorning Star detected"; + ExtDirection="Buy"; + return(true); + } + +//--- result of checking + return(ExtCheckPassed); + } +//+------------------------------------------------------------------+ +//| Returns true in case of successful confirmation check | +//+------------------------------------------------------------------+ +bool CheckConfirmation() + { + ExtConfirmed=false; +//--- if there is no pattern, do not search for confirmation + if(!ExtPatternDetected) + return(true); + +//--- get the value of the stochastic indicator to confirm the signal + double signal=MFI(1); + if(signal==EMPTY_VALUE) + { + //--- failed to get indicator value, check failed + return(false); + } + +//--- check the Buy signal + if(ExtSignalOpen==SIGNAL_BUY && (signal<40)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: MFI<40"; + } + +//--- check the Sell signal + if(ExtSignalOpen==SIGNAL_SELL && (signal>60)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: MFI>60"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| Check if there is a signal to close | +//+------------------------------------------------------------------+ +bool CheckCloseSignal() + { + ExtSignalClose=false; +//--- if there is a signal to enter the market, do not check the signal to close + if(ExtSignalOpen!=SIGNAL_NOT) + return(true); + +//--- check if there is a signal to close a long position + if(((MFI(1)<70) && (MFI(2)>70)) || ((MFI(1)<30) && (MFI(2)>30))) + { + //--- there is a signal to close a long position + ExtSignalClose=CLOSE_LONG; + ExtDirection="Long"; + } + +//--- check if there is a signal to close a short position + if(((MFI(1)>30) && (MFI(2)<30)) || ((MFI(1)>70) && (MFI(2)<70))) + { + //--- there is a signal to close a short position + ExtSignalClose=CLOSE_SHORT; + ExtDirection="Short"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| MFI indicator value at the specified bar | +//+------------------------------------------------------------------+ +double MFI(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtIndicatorHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the MFI indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Experts/Free Robots/MorningEvening StarDoji RSI.mq5 b/BKPS/14031218/Experts/Free Robots/MorningEvening StarDoji RSI.mq5 new file mode 100644 index 0000000..293d897 --- /dev/null +++ b/BKPS/14031218/Experts/Free Robots/MorningEvening StarDoji RSI.mq5 @@ -0,0 +1,686 @@ +//+------------------------------------------------------------------+ +//| MorningEvening StarDoji RSI.mq5 | +//| Copyright 2024, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2024, MetaQuotes Ltd." +#property link "https://www.mql5.com" +#property version "1.00" + +#include +#include + +#define SIGNAL_BUY 1 // Buy signal +#define SIGNAL_NOT 0 // no trading signal +#define SIGNAL_SELL -1 // Sell signal + +#define CLOSE_LONG 2 // signal to close Long +#define CLOSE_SHORT -2 // signal to close Short + +//--- Input parameters +input int InpAverBodyPeriod=12; // period for calculating average candlestick size +input int InpPeriodRSI =37; // RSI period +input ENUM_APPLIED_PRICE InpPrice=PRICE_CLOSE; // price type + +//--- trade parameters +input uint InpDuration=10; // position holding time in bars +input uint InpSL =200; // Stop Loss in points +input uint InpTP =200; // Take Profit in points +input uint InpSlippage=10; // slippage in points +//--- money management parameters +input double InpLot=0.1; // lot +//--- Expert ID +input long InpMagicNumber=130300; // Magic Number + +//--- global variables +int ExtAvgBodyPeriod; // average candlestick calculation period +int ExtSignalOpen =0; // Buy/Sell signal +int ExtSignalClose =0; // signal to close a position +string ExtPatternInfo =""; // current pattern information +string ExtDirection =""; // position opening direction +bool ExtPatternDetected=false; // pattern detected +bool ExtConfirmed =false; // pattern confirmed +bool ExtCloseByTime =true; // requires closing by time +bool ExtCheckPassed =true; // status checking error +//--- indicator handle +int ExtIndicatorHandle=INVALID_HANDLE; + +//--- service objects +CTrade ExtTrade; +CSymbolInfo ExtSymbolInfo; +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { + Print("InpSL=", InpSL); + Print("InpTP=", InpTP); +//--- set parameters for trading operations + ExtTrade.SetDeviationInPoints(InpSlippage); // slippage + ExtTrade.SetExpertMagicNumber(InpMagicNumber); // Expert Advisor ID + ExtTrade.LogLevel(LOG_LEVEL_ERRORS); // logging level + + ExtAvgBodyPeriod=InpAverBodyPeriod; +//--- indicator initialization + ExtIndicatorHandle=iRSI(_Symbol, _Period, InpPeriodRSI, InpPrice); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating CCI indicator"); + return(INIT_FAILED); + } +//--- OK + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { +//--- release indicator handle + IndicatorRelease(ExtIndicatorHandle); + } +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() + { +//--- save the next bar start time; all checks at bar opening only + static datetime next_bar_open=0; + +//--- Phase 1 - check the emergence of a new bar and update the status + if(TimeCurrent()>=next_bar_open) + { + //--- get the current state of environment on the new bar + // namely, set the values of global variables: + // ExtPatternDetected - pattern detection + // ExtConfirmed - pattern confirmation + // ExtSignalOpen - signal to open + // ExtSignalClose - signal to close + // ExtPatternInfo - current pattern information + if(CheckState()) + { + //--- set the new bar opening time + next_bar_open=TimeCurrent(); + next_bar_open-=next_bar_open%PeriodSeconds(_Period); + next_bar_open+=PeriodSeconds(_Period); + + //--- report the emergence of a new bar only once within a bar + if(ExtPatternDetected && ExtConfirmed) + Print(ExtPatternInfo); + } + else + { + //--- error getting the status, retry on the next tick + return; + } + } + +//--- Phase 2 - if there is a signal and no position in this direction + if(ExtSignalOpen && !PositionExist(ExtSignalOpen)) + { + Print("\r\nSignal to open position ", ExtDirection); + PositionOpen(); + if(PositionExist(ExtSignalOpen)) + ExtSignalOpen=SIGNAL_NOT; + } + +//--- Phase 3 - close if there is a signal to close + if(ExtSignalClose && PositionExist(ExtSignalClose)) + { + Print("\r\nSignal to close position ", ExtDirection); + CloseBySignal(ExtSignalClose); + if(!PositionExist(ExtSignalClose)) + ExtSignalClose=SIGNAL_NOT; + } + +//--- Phase 4 - close upon expiration + if(ExtCloseByTime && PositionExpiredByTimeExist()) + { + CloseByTime(); + ExtCloseByTime=PositionExpiredByTimeExist(); + } + } +//+------------------------------------------------------------------+ +//| Get the current environment and check for a pattern | +//+------------------------------------------------------------------+ +bool CheckState() + { +//--- check if there is a pattern + if(!CheckPattern()) + { + Print("Error, failed to check pattern"); + return(false); + } + +//--- check for confirmation + if(!CheckConfirmation()) + { + Print("Error, failed to check pattern confirmation"); + return(false); + } +//--- if there is no confirmation, cancel the signal + if(!ExtConfirmed) + ExtSignalOpen=SIGNAL_NOT; + +//--- check if there is a signal to close a position + if(!CheckCloseSignal()) + { + Print("Error, failed to check the closing signal"); + return(false); + } + +//--- if positions are to be closed after certain holding time in bars + if(InpDuration) + ExtCloseByTime=true; // set flag to close upon expiration + +//--- all checks done + return(true); + } +//+------------------------------------------------------------------+ +//| Open a position in the direction of the signal | +//+------------------------------------------------------------------+ +bool PositionOpen() + { + ExtSymbolInfo.Refresh(); + ExtSymbolInfo.RefreshRates(); + + double price=0; +//--- Stop Loss and Take Profit are not set by default + double stoploss=0.0; + double takeprofit=0.0; + + int digits=ExtSymbolInfo.Digits(); + double point=ExtSymbolInfo.Point(); + double spread=ExtSymbolInfo.Ask()-ExtSymbolInfo.Bid(); + +//--- uptrend + if(ExtSignalOpen==SIGNAL_BUY) + { + price=NormalizeDouble(ExtSymbolInfo.Ask(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price-spread, digits); + } + else + stoploss = NormalizeDouble(price-InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price+spread, digits); + } + else + takeprofit = NormalizeDouble(price+InpTP*point, digits); + } + + if(!ExtTrade.Buy(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s buy %G at %G (sl=%G tp=%G) failed. Ask=%G error=%d", + Symbol(), InpLot, price, stoploss, takeprofit, ExtSymbolInfo.Ask(), GetLastError()); + return(false); + } + } + +//--- downtrend + if(ExtSignalOpen==SIGNAL_SELL) + { + price=NormalizeDouble(ExtSymbolInfo.Bid(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price+spread, digits); + } + else + stoploss = NormalizeDouble(price+InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price-spread, digits); + } + else + takeprofit = NormalizeDouble(price-InpTP*point, digits); + } + + if(!ExtTrade.Sell(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s sell at %G (sl=%G tp=%G) failed. Bid=%G error=%d", + Symbol(), price, stoploss, takeprofit, ExtSymbolInfo.Bid(), GetLastError()); + ExtTrade.PrintResult(); + Print(" "); + return(false); + } + } + + return(true); + } +//+------------------------------------------------------------------+ +//| Close a position based on the specified signal | +//+------------------------------------------------------------------+ +void CloseBySignal(int type_close) + { +//--- if there is no signal to close, return successful completion + if(type_close==SIGNAL_NOT) + return; +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalClose)==0) + return; + +//--- closing direction + long type; + switch(type_close) + { + case CLOSE_SHORT: + type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + type=POSITION_TYPE_BUY; + break; + default: + Print("Error! Signal to close not detected"); + return; + } + +//--- check all positions and close ours based on the signal + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + if(PositionGetInteger(POSITION_TYPE)==type) + { + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Close positions upon holding time expiration in bars | +//+------------------------------------------------------------------+ +void CloseByTime() + { +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalOpen)==0) + return; + +//--- check all positions and close ours based on the holding time in bars + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + //--- position opening time + datetime open_time=(datetime)PositionGetInteger(POSITION_TIME); + //--- check position holding time in bars + if(BarsHold(open_time)>=(int)InpDuration) + { + Print("\r\nTime to close position #", ticket); + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Returns true if there are open positions | +//+------------------------------------------------------------------+ +bool PositionExist(int signal_direction) + { + bool check_type=(signal_direction!=SIGNAL_NOT); + +//--- what positions to search + ENUM_POSITION_TYPE search_type=WRONG_VALUE; + if(check_type) + switch(signal_direction) + { + case SIGNAL_BUY: + search_type=POSITION_TYPE_BUY; + break; + case SIGNAL_SELL: + search_type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + search_type=POSITION_TYPE_BUY; + break; + case CLOSE_SHORT: + search_type=POSITION_TYPE_SELL; + break; + default: + //--- entry direction is not specified; nothing to search + return(false); + } + +//--- go through the list of all positions + int positions=PositionsTotal(); + for(int i=0; i=(int)InpDuration)) + return(true); + } + } + } + +//--- open position not found + return(false); + } +//+------------------------------------------------------------------+ +//| Checks position closing time in bars | +//+------------------------------------------------------------------+ +int BarsHold(datetime open_time) + { +//--- first run a basic simple check + if(TimeCurrent()-open_timeAvgBody(1)) && // bullish candlestick, its body is larger than average + (MathAbs(Close(2)-Open(2))Close(3)) && // second candlestick close is higher than first candlestick close + (Open(2)>Open(3)) && // second candlestick open is higher than first candlestick open + (Open(1)AvgBody(1)) && // bullish candlestick, its body is larger than average + (MathAbs(Close(2)-Open(2))Close(3)) && // second candlestick close is higher than first candlestick close + (Open(2)>Open(3)) && // second candlestick open is higher than first candlestick open + (Close(1)AvgBody(1)) && // bearish candlestick, its body is larger than average + (MathAbs(Close(2)-Open(2))Close(2)) && // upward price gap on the last candlestick + (Close(1)>Close(2))) // last candlestick close higher than second candlestick close + { + ExtPatternDetected=true; + ExtSignalOpen=SIGNAL_BUY; + ExtPatternInfo="\r\nMorning Doji detected"; + ExtDirection="Buy"; + return(true); + } + +//--- check Morning Star + if((Open(3)-Close(3)>AvgBody(1)) && // bearish candlestick, its body is larger than average + (MathAbs(Close(2)-Open(2))MidOpenClose(3))) // last candlestick close is lower than the middle of the first (bearish) one + { + ExtPatternDetected=true; + ExtSignalOpen=SIGNAL_BUY; + ExtPatternInfo="\r\nMorning Star detected"; + ExtDirection="Buy"; + return(true); + } + +//--- result of checking + return(ExtCheckPassed); + } +//+------------------------------------------------------------------+ +//| Returns true in case of successful confirmation check | +//+------------------------------------------------------------------+ +bool CheckConfirmation() + { + ExtConfirmed=false; +//--- if there is no pattern, do not search for confirmation + if(!ExtPatternDetected) + return(true); + +//--- get the value of the stochastic indicator to confirm the signal + double signal=RSI(1); + if(signal==EMPTY_VALUE) + { + //--- failed to get indicator value, check failed + return(false); + } + +//--- check the Buy signal + if(ExtSignalOpen==SIGNAL_BUY && (signal<40)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: RSI<40"; + } + +//--- check the Sell signal + if(ExtSignalOpen==SIGNAL_SELL && (signal>60)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: RSI>60"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| Check if there is a signal to close | +//+------------------------------------------------------------------+ +bool CheckCloseSignal() + { + ExtSignalClose=false; +//--- if there is a signal to enter the market, do not check the signal to close + if(ExtSignalOpen!=SIGNAL_NOT) + return(true); + +//--- check if there is a signal to close a long position + if(((RSI(1)<70) && (RSI(2)>70)) || ((RSI(1)<30) && (RSI(2)>30))) + { + //--- there is a signal to close a long position + ExtSignalClose=CLOSE_LONG; + ExtDirection="Long"; + } + +//--- check if there is a signal to close a short position + if(((RSI(1)>30) && (RSI(2)<30)) || ((RSI(1)>70) && (RSI(2)<70))) + { + //--- there is a signal to close a short position + ExtSignalClose=CLOSE_SHORT; + ExtDirection="Short"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| RSI indicator value at the specified bar | +//+------------------------------------------------------------------+ +double RSI(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtIndicatorHandle, 0, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the RSI indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Experts/Free Robots/MorningEvening StarDoji Stoch.mq5 b/BKPS/14031218/Experts/Free Robots/MorningEvening StarDoji Stoch.mq5 new file mode 100644 index 0000000..8a58965 --- /dev/null +++ b/BKPS/14031218/Experts/Free Robots/MorningEvening StarDoji Stoch.mq5 @@ -0,0 +1,691 @@ +//+------------------------------------------------------------------+ +//| MorningEvening StarDoji Stoch.mq5 | +//| Copyright 2024, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2024, MetaQuotes Ltd." +#property link "https://www.mql5.com" +#property version "1.00" + +#include +#include + +#define SIGNAL_BUY 1 // Buy signal +#define SIGNAL_NOT 0 // no trading signal +#define SIGNAL_SELL -1 // Sell signal + +#define CLOSE_LONG 2 // signal to close Long +#define CLOSE_SHORT -2 // signal to close Short + +//--- Input parameters +input int InpAverBodyPeriod=12; // period for calculating average candlestick size +input int InpStochK =47; // period %K +input int InpStochD =9; // period %D +input int InpStochSlow =13; // smoothing period %K +input ENUM_STO_PRICE InpStochApplied =STO_LOWHIGH; // calculation type +input ENUM_MA_METHOD InpStochMA =MODE_SMA; // smoothing type + +//--- trade parameters +input uint InpDuration=10; // position holding time in bars +input uint InpSL =200; // Stop Loss in points +input uint InpTP =200; // Take Profit in points +input uint InpSlippage=10; // slippage in points +//--- money management parameters +input double InpLot=0.1; // lot +//--- Expert ID +input long InpMagicNumber=130400; // Magic Number + +//--- global variables +int ExtAvgBodyPeriod; // average candlestick calculation period +int ExtSignalOpen =0; // Buy/Sell signal +int ExtSignalClose =0; // signal to close a position +string ExtPatternInfo =""; // current pattern information +string ExtDirection =""; // position opening direction +bool ExtPatternDetected=false; // pattern detected +bool ExtConfirmed =false; // pattern confirmed +bool ExtCloseByTime =true; // requires closing by time +bool ExtCheckPassed =true; // status checking error +//--- indicator handle +int ExtIndicatorHandle=INVALID_HANDLE; + +//--- service objects +CTrade ExtTrade; +CSymbolInfo ExtSymbolInfo; +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { + Print("InpSL=", InpSL); + Print("InpTP=", InpTP); +//--- set parameters for trading operations + ExtTrade.SetDeviationInPoints(InpSlippage); // slippage + ExtTrade.SetExpertMagicNumber(InpMagicNumber); // Expert Advisor ID + ExtTrade.LogLevel(LOG_LEVEL_ERRORS); // logging level + + ExtAvgBodyPeriod=InpAverBodyPeriod; +//--- indicator initialization + ExtIndicatorHandle=iStochastic(_Symbol, _Period, InpStochK, InpStochD, InpStochSlow, InpStochMA, InpStochApplied); + if(ExtIndicatorHandle==INVALID_HANDLE) + { + Print("Error creating iStochastic indicator"); + return(INIT_FAILED); + } +//--- OK + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { +//--- release indicator handle + IndicatorRelease(ExtIndicatorHandle); + } +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() + { +//--- save the next bar start time; all checks at bar opening only + static datetime next_bar_open=0; + +//--- Phase 1 - check the emergence of a new bar and update the status + if(TimeCurrent()>=next_bar_open) + { + //--- get the current state of environment on the new bar + // namely, set the values of global variables: + // ExtPatternDetected - pattern detection + // ExtConfirmed - pattern confirmation + // ExtSignalOpen - signal to open + // ExtSignalClose - signal to close + // ExtPatternInfo - current pattern information + if(CheckState()) + { + //--- set the new bar opening time + next_bar_open=TimeCurrent(); + next_bar_open-=next_bar_open%PeriodSeconds(_Period); + next_bar_open+=PeriodSeconds(_Period); + + //--- report the emergence of a new bar only once within a bar + if(ExtPatternDetected && ExtConfirmed) + Print(ExtPatternInfo); + } + else + { + //--- error getting the status, retry on the next tick + return; + } + } + +//--- Phase 2 - if there is a signal and no position in this direction + if(ExtSignalOpen && !PositionExist(ExtSignalOpen)) + { + Print("\r\nSignal to open position ", ExtDirection); + PositionOpen(); + if(PositionExist(ExtSignalOpen)) + ExtSignalOpen=SIGNAL_NOT; + } + +//--- Phase 3 - close if there is a signal to close + if(ExtSignalClose && PositionExist(ExtSignalClose)) + { + Print("\r\nSignal to close position ", ExtDirection); + CloseBySignal(ExtSignalClose); + if(!PositionExist(ExtSignalClose)) + ExtSignalClose=SIGNAL_NOT; + } + +//--- Phase 4 - close upon expiration + if(ExtCloseByTime && PositionExpiredByTimeExist()) + { + CloseByTime(); + ExtCloseByTime=PositionExpiredByTimeExist(); + } + } +//+------------------------------------------------------------------+ +//| Get the current environment and check for a pattern | +//+------------------------------------------------------------------+ +bool CheckState() + { +//--- check if there is a pattern + if(!CheckPattern()) + { + Print("Error, failed to check pattern"); + return(false); + } + +//--- check for confirmation + if(!CheckConfirmation()) + { + Print("Error, failed to check pattern confirmation"); + return(false); + } +//--- if there is no confirmation, cancel the signal + if(!ExtConfirmed) + ExtSignalOpen=SIGNAL_NOT; + +//--- check if there is a signal to close a position + if(!CheckCloseSignal()) + { + Print("Error, failed to check the closing signal"); + return(false); + } + +//--- if positions are to be closed after certain holding time in bars + if(InpDuration) + ExtCloseByTime=true; // set flag to close upon expiration + +//--- all checks done + return(true); + } +//+------------------------------------------------------------------+ +//| Open a position in the direction of the signal | +//+------------------------------------------------------------------+ +bool PositionOpen() + { + ExtSymbolInfo.Refresh(); + ExtSymbolInfo.RefreshRates(); + + double price=0; +//--- Stop Loss and Take Profit are not set by default + double stoploss=0.0; + double takeprofit=0.0; + + int digits=ExtSymbolInfo.Digits(); + double point=ExtSymbolInfo.Point(); + double spread=ExtSymbolInfo.Ask()-ExtSymbolInfo.Bid(); + +//--- uptrend + if(ExtSignalOpen==SIGNAL_BUY) + { + price=NormalizeDouble(ExtSymbolInfo.Ask(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price-spread, digits); + } + else + stoploss = NormalizeDouble(price-InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price+spread, digits); + } + else + takeprofit = NormalizeDouble(price+InpTP*point, digits); + } + + if(!ExtTrade.Buy(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s buy %G at %G (sl=%G tp=%G) failed. Ask=%G error=%d", + Symbol(), InpLot, price, stoploss, takeprofit, ExtSymbolInfo.Ask(), GetLastError()); + return(false); + } + } + +//--- downtrend + if(ExtSignalOpen==SIGNAL_SELL) + { + price=NormalizeDouble(ExtSymbolInfo.Bid(), digits); + //--- if Stop Loss is set + if(InpSL>0) + { + if(spread>=InpSL*point) + { + PrintFormat("StopLoss (%d points) <= current spread = %.0f points. Spread value will be used", InpSL, spread/point); + stoploss = NormalizeDouble(price+spread, digits); + } + else + stoploss = NormalizeDouble(price+InpSL*point, digits); + } + //--- if Take Profit is set + if(InpTP>0) + { + if(spread>=InpTP*point) + { + PrintFormat("TakeProfit (%d points) < current spread = %.0f points. Spread value will be used", InpTP, spread/point); + takeprofit = NormalizeDouble(price-spread, digits); + } + else + takeprofit = NormalizeDouble(price-InpTP*point, digits); + } + + if(!ExtTrade.Sell(InpLot, Symbol(), price, stoploss, takeprofit)) + { + PrintFormat("Failed %s sell at %G (sl=%G tp=%G) failed. Bid=%G error=%d", + Symbol(), price, stoploss, takeprofit, ExtSymbolInfo.Bid(), GetLastError()); + ExtTrade.PrintResult(); + Print(" "); + return(false); + } + } + + return(true); + } +//+------------------------------------------------------------------+ +//| Close a position based on the specified signal | +//+------------------------------------------------------------------+ +void CloseBySignal(int type_close) + { +//--- if there is no signal to close, return successful completion + if(type_close==SIGNAL_NOT) + return; +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalClose)==0) + return; + +//--- closing direction + long type; + switch(type_close) + { + case CLOSE_SHORT: + type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + type=POSITION_TYPE_BUY; + break; + default: + Print("Error! Signal to close not detected"); + return; + } + +//--- check all positions and close ours based on the signal + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + if(PositionGetInteger(POSITION_TYPE)==type) + { + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Close positions upon holding time expiration in bars | +//+------------------------------------------------------------------+ +void CloseByTime() + { +//--- if there are no positions opened by our EA + if(PositionExist(ExtSignalOpen)==0) + return; + +//--- check all positions and close ours based on the holding time in bars + int positions=PositionsTotal(); + for(int i=positions-1; i>=0; i--) + { + ulong ticket=PositionGetTicket(i); + if(ticket!=0) + { + //--- get the name of the symbol and the position id (magic) + string symbol=PositionGetString(POSITION_SYMBOL); + long magic =PositionGetInteger(POSITION_MAGIC); + //--- if they correspond to our values + if(symbol==Symbol() && magic==InpMagicNumber) + { + //--- position opening time + datetime open_time=(datetime)PositionGetInteger(POSITION_TIME); + //--- check position holding time in bars + if(BarsHold(open_time)>=(int)InpDuration) + { + Print("\r\nTime to close position #", ticket); + ExtTrade.PositionClose(ticket, InpSlippage); + ExtTrade.PrintResult(); + Print(" "); + } + } + } + } + } +//+------------------------------------------------------------------+ +//| Returns true if there are open positions | +//+------------------------------------------------------------------+ +bool PositionExist(int signal_direction) + { + bool check_type=(signal_direction!=SIGNAL_NOT); + +//--- what positions to search + ENUM_POSITION_TYPE search_type=WRONG_VALUE; + if(check_type) + switch(signal_direction) + { + case SIGNAL_BUY: + search_type=POSITION_TYPE_BUY; + break; + case SIGNAL_SELL: + search_type=POSITION_TYPE_SELL; + break; + case CLOSE_LONG: + search_type=POSITION_TYPE_BUY; + break; + case CLOSE_SHORT: + search_type=POSITION_TYPE_SELL; + break; + default: + //--- entry direction is not specified; nothing to search + return(false); + } + +//--- go through the list of all positions + int positions=PositionsTotal(); + for(int i=0; i=(int)InpDuration)) + return(true); + } + } + } + +//--- open position not found + return(false); + } +//+------------------------------------------------------------------+ +//| Checks position closing time in bars | +//+------------------------------------------------------------------+ +int BarsHold(datetime open_time) + { +//--- first run a basic simple check + if(TimeCurrent()-open_timeAvgBody(1)) && // bullish candlestick, its body is larger than average + (MathAbs(Close(2)-Open(2))Close(3)) && // second candlestick close is higher than first candlestick close + (Open(2)>Open(3)) && // second candlestick open is higher than first candlestick open + (Open(1)AvgBody(1)) && // bullish candlestick, its body is larger than average + (MathAbs(Close(2)-Open(2))Close(3)) && // second candlestick close is higher than first candlestick close + (Open(2)>Open(3)) && // second candlestick open is higher than first candlestick open + (Close(1)AvgBody(1)) && // bearish candlestick, its body is larger than average + (MathAbs(Close(2)-Open(2))Close(2)) && // upward price gap on the last candlestick + (Close(1)>Close(2))) // last candlestick close higher than second candlestick close + { + ExtPatternDetected=true; + ExtSignalOpen=SIGNAL_BUY; + ExtPatternInfo="\r\nMorning Doji detected"; + ExtDirection="Buy"; + return(true); + } + +//--- check Morning Star + if((Open(3)-Close(3)>AvgBody(1)) && // bearish candlestick, its body is larger than average + (MathAbs(Close(2)-Open(2))MidOpenClose(3))) // last candlestick close is lower than the middle of the first (bearish) one + { + ExtPatternDetected=true; + ExtSignalOpen=SIGNAL_BUY; + ExtPatternInfo="\r\nMorning Star detected"; + ExtDirection="Buy"; + return(true); + } + +//--- result of checking + return(ExtCheckPassed); + } +//+------------------------------------------------------------------+ +//| Returns true in case of successful confirmation check | +//+------------------------------------------------------------------+ +bool CheckConfirmation() + { + ExtConfirmed=false; +//--- if there is no pattern, do not search for confirmation + if(!ExtPatternDetected) + return(true); + +//--- get the value of the stochastic indicator to confirm the signal + double signal=StochSignal(1); + if(signal==EMPTY_VALUE) + { + //--- failed to get indicator value, check failed + return(false); + } + +//--- check the Buy signal + if(ExtSignalOpen==SIGNAL_BUY && (signal<30)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: StochSignal<30"; + } + +//--- check the Sell signal + if(ExtSignalOpen==SIGNAL_SELL && (signal>70)) + { + ExtConfirmed=true; + ExtPatternInfo+="\r\n Confirmed: StochSignal>70"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| Check if there is a signal to close | +//+------------------------------------------------------------------+ +bool CheckCloseSignal() + { + ExtSignalClose=false; +//--- if there is a signal to enter the market, do not check the signal to close + if(ExtSignalOpen!=SIGNAL_NOT) + return(true); + +//--- check if there is a signal to close a long position + if(((StochSignal(1)<80) && (StochSignal(2)>80))|| // 80 crossed downwards + ((StochSignal(1)<20) && (StochSignal(2)>20))) // 20 crossed downwards + { + //--- there is a signal to close a long position + ExtSignalClose=CLOSE_LONG; + ExtDirection="Long"; + } + +//--- check if there is a signal to close a short position + if((((StochSignal(1)>20) && (StochSignal(2)<20)) || // 20 crossed upwards + ((StochSignal(1)>80) && (StochSignal(2)<80)))) // 80 crossed upwards + { + //--- there is a signal to close a short position + ExtSignalClose=CLOSE_SHORT; + ExtDirection="Short"; + } + +//--- successful completion of the check + return(true); + } +//+------------------------------------------------------------------+ +//| Stochastic indicator value at the specified bar | +//+------------------------------------------------------------------+ +double StochSignal(int index) + { + double indicator_values[]; + if(CopyBuffer(ExtIndicatorHandle, SIGNAL_LINE, index, 1, indicator_values)<0) + { + //--- if the copying fails, report the error code + PrintFormat("Failed to copy data from the iStochastic indicator, error code %d", GetLastError()); + return(EMPTY_VALUE); + } + return(indicator_values[0]); + } +//+------------------------------------------------------------------+ diff --git a/BKPS/14031218/Experts/x-saherelm.x-121.smc.ea.ex5 b/BKPS/14031218/Experts/x-saherelm.x-121.smc.ea.ex5 new file mode 100644 index 0000000..63c7a4c Binary files /dev/null and b/BKPS/14031218/Experts/x-saherelm.x-121.smc.ea.ex5 differ diff --git a/BKPS/14031218/Experts/x-saherelm.x-121.smc.ea.mq5 b/BKPS/14031218/Experts/x-saherelm.x-121.smc.ea.mq5 new file mode 100644 index 0000000..8cc6f1f --- /dev/null +++ b/BKPS/14031218/Experts/x-saherelm.x-121.smc.ea.mq5 @@ -0,0 +1,464 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center XTest MQL5 Expert Advisor +// ------------------------------------------------- +// Name: X121SMCEA +// Description: an Exper Advisor which used Panels +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121SMCEA" +#property strict + +// +#define ShortName "X121SMCEA" + +// +// Imports ... +#include "../X121SMCEA/Experts/x-121.smc.expert.class.mq5" + +// +// Inputs ... + +// +// Common ... +input group "Common"; +input long eaMagicNumber = 78692110; // Magic Number +input int eaSlippage = 10; // Slippgae +input string eaLogSuffix = ""; // Log Suffix + +// +// Symbols ... +input group "Symbols"; +input bool eaMultiSymbol = false; // Use Multi Symbol +input string eaSymbols = "EURUSDb,GBPUSDb,USDCHFb,USDJPYb"; // Trading Symbols + +// +// Signalling ... +input group "Signalling"; +input bool eaAllowLong = true; // Allow Long Signals +input bool eaAllowShort = true; // Allow Short Signals +input int eaMaxAllowedLongs = 5; // Max Allowed Long Signals +input int eaMaxAllowedShorts = 5; // Max Allowed Short Signals +input bool eaUseMaxAllowedSignalsPerSymbol = true; // Use Max Allowed Signal Types Per Symbol +input double eaLastPositionProfitForAcceptNextInPoint = 30; // Last Position Profit In Points for Accept new Signal +input int eaDelaysBetweenTwoSignalsInBar = 12; // Delay between two Signals in Bars +input double eaMaxAllowedSpread = 25; // Max Allowed Spread for Signalling +input int eaMinRequiredVerificationForSpreadPass = 20; // Minimum Spread Verification for Signalling + +// +// Trade ... +input group "Trade"; +input bool eaAllowTrade = true; // Allow Open Trade On Signals +input string eaStartTradeAt = "02:30"; // Enable Trade on Signals on Time +input string eaStopTradeAt = "23:30"; // Enable Trade on Signals on Time +input string eaCloseAllTradesAt = ""; // Enable Close All Trades on Signals on Time + +// +// Risk Management ... +input group "Risk Management"; +input double eaR2R = 6; // Signallers Risk to Reward Ratio +input double eaVolume = 0; // Static Volume +input double eaStaticBalance = 1000; // Static Balance +input double eaBalancePerTrade = 10; // Balance Used in Each Trade +input double eaRiskPercentPerBalance = 0; // Risk Percent Per Balance in Each Trade +input bool eaDynamicRiskManagement = false; // Dynamic Risk Management +input bool eaUseDynamicVolume = false; // Use Dynamic Volume +input double eaDynamicVolumeStep = 0.01; // Increase Volume Step +input double eaDynamicVolumeBalanceFactor = 200; // Balance Factor for Generate Dynamic Volume +input double eaMaxAllowedDrawdownToOpenTrades = 3; // Max Allowed Drawdown for Open Trades +input int eaMaxAllowedSLToPauseSignallingPerSymbol = 2; // Max Allowed SL for Pause Signalling Per Symbol +input int eaPauseSignallingAfterReachesMaxAllowedSLInSecconds = 10800; // Pause Signalling Per Symbol afte Max Allowed SL Reached In Seconds + +// +// Protection ... +input group "Protection"; +input bool eaAllowHedging = true; // Allow Hedge Positions +input int eaMinOpenTradesFroHedging = 2; // Minimum Open Positions for Hedging +input double eaHedgingMinVolumeStep = 0.01; // Minimum Volume Step for Hedging +input double eaHedgeingMinRequiredProfitPerVolumeStep = 1.0; // Minimum Required Profit Per Volume Step for Hedging + +// +// Alert ... +// Here we Provider All Requirements for +// Configuring Alert Provider ... +input group "Alert"; +input bool eaEnableAlerts = true; // Enable Alerts +input bool eaLogAlerts = true; // Log Alerts +input bool eaMailAlerts = false; // Mail Alerts +input bool eaPushAlerts = false; // Push Alerts +input bool eaTerminalAlerts = false; // Terminal Alerts + +// +// Time Report ... +input group "Reports"; +input bool eaReportNewMonths = false; // Report New Month +input bool eaReportNewWeeks = false; // Report New Weeks +input bool eaReportNewDays = true; // Report New Days +input bool eaReportNewHours = false; // Report New Hours + +// +// Define Local Variables ... + +XC121SMCExpert *eaExpert; + +// +// Event Handlers ... + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs and Required Parameters + // for EA to Works fine ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Timer ... + if (!InitTimer()) + { + return INIT_FAILED; + } + + // + // Configure EA Expert Class ... + eaExpert = new XC121SMCExpert(); + + // + // Event Handlers ... + eaExpert.OnSignalEventListener = OnSignalRecieved; + eaExpert.OnDealsChangedEventListener = OnDealsChanged; + eaExpert.OnOrdersChangedEventListener = OnOrdersChanged; + eaExpert.OnPositionSLEventListener = OnStopLossTriggered; + eaExpert.OnPositionTPEventListener = OnTakeProfitTriggered; + eaExpert.OnPositionsChangedEventListener = OnPositionsChanged; + eaExpert.OnPositionForceCloseEventListener = OnPositionForceClosed; + + // + // Common ... + eaExpert.MagicNumber(eaMagicNumber); + eaExpert.Slippage(eaSlippage); + eaExpert.TagPrefix(eaLogSuffix); + + // + // Symbol ... + eaExpert.SetSymbol(_Symbol); + eaExpert.SetPeriod(_Period); + eaExpert.Symbols(eaSymbols); + eaExpert.MultiSymbol(eaMultiSymbol); + + // + // Signalling ... + eaExpert.AllowLong(eaAllowLong); + eaExpert.AllowShort(eaAllowShort); + eaExpert.MaxAllowedLongs(eaMaxAllowedLongs); + eaExpert.MaxAllowedShorts(eaMaxAllowedShorts); + eaExpert.UseMaxAllowedSignalsPerSymbol(eaUseMaxAllowedSignalsPerSymbol); + eaExpert.LastPositionProfitForAcceptNextInPoint(eaLastPositionProfitForAcceptNextInPoint); + eaExpert.DelaysBetweenTwoSignalsInBar(eaDelaysBetweenTwoSignalsInBar); + eaExpert.MaxAllowedSpread(eaMaxAllowedSpread); + eaExpert.MinRequiredVerificationForSpreadPass(eaMinRequiredVerificationForSpreadPass); + + // + // Trade ... + eaExpert.AllowTrade(eaAllowTrade); + eaExpert.StartTradeAt(eaStartTradeAt); + eaExpert.StopTradeAt(eaStopTradeAt); + eaExpert.CloseAllTradesAt(eaCloseAllTradesAt); + + // + // Risk Management ... + eaExpert.R2R(eaR2R); + eaExpert.Volume(eaVolume); + eaExpert.StaticBalance(eaStaticBalance); + eaExpert.BalancePerTrade(eaBalancePerTrade); + eaExpert.RiskPercentPerBalance(eaRiskPercentPerBalance); + eaExpert.DynamicRiskManagement(eaDynamicRiskManagement); + eaExpert.UseDynamicVolume(eaUseDynamicVolume); + eaExpert.DynamicVolumeStep(eaDynamicVolumeStep); + eaExpert.DynamicVolumeBalanceFactor(eaDynamicVolumeBalanceFactor); + eaExpert.MaxAllowedDrawdownToOpenTrades(eaMaxAllowedDrawdownToOpenTrades); + eaExpert.MaxAllowedSLToPauseSignallingPerSymbol(eaMaxAllowedSLToPauseSignallingPerSymbol); + eaExpert.PauseSignallingAfterReachesMaxAllowedSLInSecconds(eaPauseSignallingAfterReachesMaxAllowedSLInSecconds); + + // + // Protection ... + eaExpert.AllowHedging(eaAllowHedging); + eaExpert.MinOpenTradesFroHedging(eaMinOpenTradesFroHedging); + eaExpert.HedgingMinVolumeStep(eaHedgingMinVolumeStep); + eaExpert.HedgeingMinRequiredProfitPerVolumeStep(eaHedgeingMinRequiredProfitPerVolumeStep); + + // + // Alert ... + eaExpert.SetAlertEnableAlerts(eaEnableAlerts); + eaExpert.SetAlertLogAlerts(eaLogAlerts); + eaExpert.SetAlertMailAlerts(eaMailAlerts); + eaExpert.SetAlertPushAlerts(eaPushAlerts); + eaExpert.SetAlertTerminalAlerts(eaTerminalAlerts); + + // + // Reports ... + eaExpert.ReportNewMonths(eaReportNewMonths); + eaExpert.ReportNewWeeks(eaReportNewWeeks); + eaExpert.ReportNewDays(eaReportNewDays); + eaExpert.ReportNewHours(eaReportNewHours); + + // + bool isInited = eaExpert.HandleOnInit(); + if (!isInited) + { + return INIT_FAILED; + } + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Destroy Timer ... + eaExpert.HandleOnDeInit(); + + // + delete eaExpert; + + // + ZeroMemory(eaExpert); +} + +// +// On Tick Handler ... +void OnTick() +{ + eaExpert.HandleOnTick(); +} + +// +// Handle On Trade Event ... +void OnTrade() +{ + eaExpert.HandleOnTrade(); +} + +// +// On Timer ... +void OnTimer() +{ + eaExpert.HandleOnTimer(); +} + +// +// Chart Event Handler ... +void OnChartEvent( + const int id, + const long &lparam, + const double &dparam, + const string &sparam // +) +{ + eaExpert.HandleOnChartEvent(id, lparam, dparam, sparam); +} + +// +// Event Listeners ... + +/** + * Do What we Want by Specific Signal ... + * + * @param signal: XSignal instance ... + * @param conditions: XStrategyConditions instance ... + */ +void OnSignalRecieved( + XSignal &signal, + X121SMCStrategyConditions &conditions // +) +{ + // + eaExpert.HandleOnSignalRecieved( + signal, + conditions // + ); +} + +/** + * Handle StopLoss Triggered Positions ... + * + * @param deal: XDeal instance ... + */ +void OnStopLossTriggered(const XDeal &deal) +{ + eaExpert.HandleOnStopLossTriggered(deal); +} + +/** + * Handle Take Profit Triggered Positions ... + * + * @param deal: XDeal instance ... + */ +void OnTakeProfitTriggered(const XDeal &deal) +{ + eaExpert.HandleOnTakeProfitTriggered(deal); +} + +/** + * Handle Force Close a Position ... + * + * @param ticket: ULONG ... + * @param position: XPosition instance ... + * @param comment: String ... + */ +void OnPositionForceClosed( + const ulong ticket, + const XPosition &position, + const string comment // +) +{ + // + eaExpert.HandleOnPositionForceClosed( + ticket, + position, + comment // + ); +} + +/** + * Handle Deals Changes ... + * + * @param count: Integer, Number of Changes ... + */ +void OnDealsChanged(int count) +{ + eaExpert.HandleOnDealsChanged(count); +} + +/** + * Handle Orders Changes ... + * + * @param count: Integer, Number of Changes ... + */ +void OnOrdersChanged(int count) +{ + eaExpert.HandleOnOrdersChanged(count); +} + +/** + * Handle Positions Changes ... + * + * @param count: Integer, Number of Changes ... + */ +void OnPositionsChanged(int count) +{ + eaExpert.HandleOnPositionsChanged(count); +} + +// +// Custom Functions ... + +/** + * Validate all Inputs of Expert Adviser ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + string errMessage = ""; + + // + bool isCommonValid = ( + // + eaSlippage > 0 && + eaMagicNumber > 0 + // + ); + if (!isCommonValid) + { + // + errMessage += "common configurations error;" + "\n"; + } + + // + result = + // + // Common ... + isCommonValid && + // + // Otere ... + true + // + ; + + // + if (!result) + { + // + // Since here Logger not Initiallized, we Use Raw Print Command ... + Print(ShortName + " Errors: \n", errMessage); + } + + // + return result; +} + +/** + * Initialize Timer ... + * + * @return ( bool ) + */ +bool InitTimer() +{ + // + bool result = false; + + // + // TODO: Initialize Timer if necessary ... + // result = EventSetTimer(1); + // result = EventSetMillisecondTimer(100); + result = true; + + // + return result; +} + +/** + * Destroy Timer ... + */ +void DestroyTimer() +{ + // + // TODO: Use This ... + // EventKillTimer(); +} + +// diff --git a/BKPS/14031218/Helpers/x-saherelm.x121.helper.mq5 b/BKPS/14031218/Helpers/x-saherelm.x121.helper.mq5 new file mode 100644 index 0000000..f97ba86 --- /dev/null +++ b/BKPS/14031218/Helpers/x-saherelm.x121.helper.mq5 @@ -0,0 +1,4464 @@ +/////////////////////////////////////////////////////// +// +// 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 "../Helpers/x-saherelm.x121.x3ma.helper.mq5" +#include "../Helpers/x-saherelm.x121.xatr.helper.mq5" +#include "../Helpers/x-saherelm.x121.xche.helper.mq5" +#include "../Helpers/x-saherelm.x121.xdon.helper.mq5" +#include "../Helpers/x-saherelm.x121.xhk.helper.mq5" +#include "../Helpers/x-saherelm.x121.xpv.helper.mq5" +#include "../Helpers/x-saherelm.x121.xstr.helper.mq5" +#include "../Helpers/x-saherelm.x121.xtrend.helper.mq5" +#include "../Helpers/x-saherelm.x121.xvwap.helper.mq5" + +// +// Inputs ... +struct X121Inputs +{ + // + // Props ... + bool showRSI; + X121XPVInputs xpvInputs; + X121XHKInputs xhkInputs; + X121XATRInputs xatrInputs; + X121XSTRInputs xstrInputs; + X121XCHEInputs xcheInputs; + X121XDONInputs xdonInputs; + X121X3MAInputs x3maInputs; + X121XVWAPInputs xvwapInputs; + X121XTRENDInputs xtrendInputs; + + // + // Constructor ... + X121Inputs() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + xpvInputs.Clean(); + xhkInputs.Clean(); + xatrInputs.Clean(); + xstrInputs.Clean(); + xcheInputs.Clean(); + xdonInputs.Clean(); + xvwapInputs.Clean(); + xtrendInputs.Clean(); + + // + ZeroMemory(this); + } + + /** + * Set Default Values ... + */ + void Default() + { + // + xpvInputs.Default(); + xhkInputs.Default(); + xatrInputs.Default(); + xstrInputs.Default(); + xcheInputs.Default(); + xdonInputs.Default(); + x3maInputs.Default(); + xvwapInputs.Default(); + xtrendInputs.Default(); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + // + xpvInputs.IsValid() && + xhkInputs.IsValid() && + xatrInputs.IsValid() && + xstrInputs.IsValid() && + xcheInputs.IsValid() && + xdonInputs.IsValid() && + xvwapInputs.IsValid() && + xtrendInputs.IsValid() + // + ; + + // + return result; + } + + /** + * Extract Max Input Length ... + * + * @return ( int ) + */ + int Max() + { + // + int result = 0; + + // + int xpvMax = xpvInputs.Max(); + int xhkMax = xpvInputs.Max(); + int xatrMax = xatrInputs.Max(); + int xstrMax = xstrInputs.Max(); + int xcheMax = xcheInputs.Max(); + int xdonMax = xdonInputs.Max(); + int xvwapMax = xvwapInputs.Max(); + int xtrendMax = xtrendInputs.Max(); + + // + result = MathMax(xpvMax, xhkMax); + result = MathMax(result, xatrMax); + result = MathMax(result, xstrMax); + result = MathMax(result, xcheMax); + result = MathMax(result, xdonMax); + result = MathMax(result, xvwapMax); + result = MathMax(result, xtrendMax); + + // + return result; + } +}; + +// +// Conditions ... +struct X121Conditions +{ + // + // Common ... + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + // Buffers ... + double maBuffer[]; + double rsiBuffer[]; + double atrBuffer[]; + double strBuffer[]; + double le1Buffer[]; + double se1Buffer[]; + double le2Buffer[]; + double se2Buffer[]; + double sarBuffer[]; + double cHHBuffer[]; + double cLLBuffer[]; + double sHHBuffer[]; + double sLLBuffer[]; + double mHHBuffer[]; + double mLLBuffer[]; + double lHHBuffer[]; + double lLLBuffer[]; + double hHHBuffer[]; + double hLLBuffer[]; + double upTBuffer[]; + double adxBuffer[]; + double adxPBuffer[]; + double adxMBuffer[]; + long volumeBuffer[]; + double peaksBuffer[]; + double valesBuffer[]; + double strUpBuffer[]; + double downTBuffer[]; + double strDownBuffer[]; + double vwapMidBuffer[]; + double upTrendBuffer[]; + double x3maMidBuffer[]; + double le1StartBuffer[]; + double se1StartBuffer[]; + double le2StartBuffer[]; + double se2StartBuffer[]; + double strPriceBuffer[]; + double atrUpperBuffer[]; + double atrLowerBuffer[]; + double strStateBuffer[]; + double vwapFastBuffer[]; + double vwapSlowBuffer[]; + double xhkSMLowBuffer[]; + double x3maFastBuffer[]; + double x3maSlowBuffer[]; + double downTrendBuffer[]; + double vwapPriceBuffer[]; + double xhkRawLowBuffer[]; + double xhkSMOpenBuffer[]; + double xhkSMHighBuffer[]; + double xhkRawOpenBuffer[]; + double xhkRawHighBuffer[]; + double xhkSMCloseBuffer[]; + double vwapVolumeBuffer[]; + double xhkRawCloseBuffer[]; + double atrUpperRawBuffer[]; + double atrLowerRawBuffer[]; + double donLowUpperBuffer[]; + double donLowLowerBuffer[]; + double vwapMidStateBuffer[]; + double donOpenUpperBuffer[]; + double donOpenLowerBuffer[]; + double donHighUpperBuffer[]; + double donHighLowerBuffer[]; + double x3maMidStateBuffer[]; + double vwapFastStateBuffer[]; + double vwapSlowStateBuffer[]; + double donCloseUpperBuffer[]; + double donCloseLowerBuffer[]; + double x3maFastStateBuffer[]; + double x3maSlowStateBuffer[]; + + // + double rsiSlope; + double strSlope; + double atrUpperSlope; + double atrLowerSlope; + double vwapFastSlope; + double vwapMidSlope; + double vwapSlowSlope; + + // + // Conditions ... + + // + // XTrend ... + + // + bool isTrendBullish; + bool isTrendBearish; + bool isTrendSwitchedToBullish; + bool isTrendSwitchedToBearish; + + // + bool isRsiSlopeBullish; + bool isStrSlopeBullish; + bool isAtrUpperSlopeBullish; + bool isAtrLowerSlopeBullish; + bool isVwapFastSlopeBullish; + bool isVwapMidSlopeBullish; + bool isVwapSlowSlopeBullish; + + // + bool isRsiSlopeBearish; + bool isStrSlopeBearish; + bool isAtrUpperSlopeBearish; + bool isAtrLowerSlopeBearish; + bool isVwapFastSlopeBearish; + bool isVwapMidSlopeBearish; + bool isVwapSlowSlopeBearish; + + // + bool isRsiOverSold; + bool isRsiOverBought; + bool isRsiCrossedOverOverSold; + bool isRsiCrossedUnderOverSold; + bool isRsiCrossedOverOverBought; + bool isRsiCrossedUnderOverBought; + + // + bool isClosedOverAtrUpper; + bool isClosedOverAtrLower; + bool isClosedUnderAtrUpper; + bool isClosedUnderAtrLower; + + // + bool isRejectedUpAtrUpper; + bool isRejectedDownAtrUpper; + + // + bool isRejectedUpAtrLower; + bool isRejectedDownAtrLower; + + // + bool isBreakedUpAtrUpper; + bool isBreakedDownAtrUpper; + + // + bool isBreakedUpAtrLower; + bool isBreakedDownAtrLower; + + // + bool isRejectedDonOpenUpper; + bool isRejectedDonHighUpper; + bool isRejectedDonLowUpper; + bool isRejectedDonCloseUpper; + + // + bool isRejectedDonOpenLower; + bool isRejectedDonHighLower; + bool isRejectedDonLowLower; + bool isRejectedDonCloseLower; + + // + bool isBreakedDonOpenUpper; + bool isBreakedDonHighUpper; + bool isBreakedDonLowUpper; + bool isBreakedDonCloseUpper; + + // + bool isBreakedDonOpenLower; + bool isBreakedDonHighLower; + bool isBreakedDonLowLower; + bool isBreakedDonCloseLower; + + // + bool isSarBullish; + bool isSarBearish; + bool isSarSwitchedToBullish; + bool isSarSwitchedToBearish; + + // + bool isNewPeak; + bool isNewPeakOverLast; + bool isNewPeakUnderLast; + bool isRejectedPrevPeak; + bool isBreakedUpPrevPeak; + + // + bool isNewVale; + bool isNewValeOverLast; + bool isNewValeUnderLast; + bool isRejectedPrevVale; + bool isBreakedDownPrevVale; + + // + bool isStrBullish; + bool isStrBearish; + bool isStrSwitchedToBullish; + bool isStrSwitchedToBearish; + + // + bool isChe1Bullish; + bool isChe1Bearish; + bool isChe1SwitchedToBullish; + bool isChe1SwitchedToBearish; + + // + bool isChe2Bullish; + bool isChe2Bearish; + bool isChe2SwitchedToBullish; + bool isChe2SwitchedToBearish; + + // + bool isCheBullish; + bool isCheBearish; + bool isCheSwitchedToBullish; + bool isCheSwitchedToBearish; + + // + bool isVWapMidBullish; + bool isVWapMidBearish; + bool isVWapFastBullish; + bool isVWapFastBearish; + bool isVWapMidNeutural; + bool isVWapSlowBullish; + bool isVWapSlowBearish; + bool isVWapFastOverMid; + bool isVWapMidOverSlow; + bool isVWapFastNeutural; + bool isVWapSlowNeutural; + bool isVWapFastUnderMid; + bool isVWapMidUnderSlow; + bool isVWapBullishState; + bool isVWapBearishState; + bool isVWapNeuturalState; + bool isVWapBullishOrdered; + bool isVWapBearishOrdered; + bool isVWapSwitchedToBullishState; + bool isVWapSwitchedToBearishState; + bool isVWapSwitchedToNeuturalState; + bool isVWapSwitchedToBullishOrdered; + bool isVWapSwitchedToBearishOrdered; + + // + bool isX3MaMidBullish; + bool isX3MaMidBearish; + bool isX3MaFastBullish; + bool isX3MaFastBearish; + bool isX3MaMidNeutural; + bool isX3MaSlowBullish; + bool isX3MaSlowBearish; + bool isX3MaFastOverMid; + bool isX3MaMidOverSlow; + bool isX3MaFastNeutural; + bool isX3MaSlowNeutural; + bool isX3MaFastUnderMid; + bool isX3MaMidUnderSlow; + bool isX3MaBullishState; + bool isX3MaBearishState; + bool isX3MaNeuturalState; + bool isX3MaBullishOrdered; + bool isX3MaBearishOrdered; + bool isX3MaSwitchedToBullishState; + bool isX3MaSwitchedToBearishState; + bool isX3MaSwitchedToNeuturalState; + bool isX3MaSwitchedToBullishOrdered; + bool isX3MaSwitchedToBearishOrdered; + + // + bool isSMHKBullish; + bool isRawHKBullish; + bool isSMHKBearish; + bool isRawHKBearish; + bool isBreakedUpSMHK; + bool isBreakedUpRawHK; + bool isRejectedUpSMHK; + bool isClosedOverSMHK; + bool isRejectedUpRawHK; + bool isBreakedDownSMHK; + bool isClosedUnderSMHK; + bool isClosedOverRawHK; + bool isClosedUnderRawHK; + bool isBreakedDownRawHK; + bool isRejectedDownSMHK; + bool isRejectedDownRawHK; + bool isRawHKBreakedUpSMHK; + bool isRawHKClosedOverSMHK; + bool isRawHKClosedUnderSMHK; + bool isRawHKBreakedDownSMHK; + bool isSMHKSwitchedToBullish; + bool isSMHKSwitchedToBearish; + bool isRawHKSwitchedToBearish; + bool isRawHKSwitchedToBullish; + + // + // Complex Conditions ... + + // + double cheMin; + double cheMax; + double x3maMin; + double x3maMax; + double vwapMin; + double vwapMax; + + // + bool isSarIncreased; + bool isSarDecreased; + bool isX3MaFatsOverMid; + bool isSarEqualsToPeak; + bool isSarEqualsToVale; + bool isStrEqualsToPeak; + bool isStrEqualsToVale; + bool isX3MaMinBreakedUp; + bool isX3MaMaxBreakedUp; + bool isX3MaFatsUnderMid; + bool isX3MaFatsOverSlow; + bool isAtrUpperOverPeak; + bool isPeakOverAtrUpper; + bool isStrUpperOverPeak; + bool isStrLowerOverVale; + bool isBreakedUpPrevSar; + bool isBreakedUpPrevStr; + bool isVWapMinBreakedUp; + bool isVWapMaxBreakedUp; + bool isClosedOverCheMin; + bool isClosedOverCheMax; + bool isX3MaFatsUnderSlow; + bool isAtrLowerUnderVale; + bool isClosedOverX3MaMin; + bool isClosedOverX3MaMax; + bool isValeUnderAtrLower; + bool isStrUpperUnderPeak; + bool isStrLowerUnderVale; + bool isClosedUnderCheMin; + bool isClosedUnderCheMax; + bool isClosedOverVWapMin; + bool isClosedOverVWapMax; + bool isX3MaMinBreakedDown; + bool isX3MaMaxBreakedDown; + bool isClosedUnderX3MaMin; + bool isClosedUnderX3MaMax; + bool isBreakedDownPrevSar; + bool isBreakedDownPrevStr; + bool isStrCrossedOverVale; + bool isSarCrossedOverVale; + bool isClosedUnderVWapMin; + bool isClosedUnderVWapMax; + bool isVWapMinBreakedDown; + bool isVWapMaxBreakedDown; + bool isX3MaFatsOverMidPrev; + bool isSarCrossedUnderPeak; + bool isStrCrossedUnderPeak; + bool isNewPeakOverAtrUpper; + bool isBreakedUpPrevCheMin; + bool isBreakedUpPrevCheMax; + bool isBreakedUpPrevCheLE1; + bool isBreakedUpPrevCheLE2; + bool isBreakedUpPrevCheSE1; + bool isBreakedUpPrevCheSE2; + bool isX3MaFatsUnderMidPrev; + bool isX3MaFatsOverSlowPrev; + bool isAtrUpperEqualsToPeak; + bool isAtrLowerEqualsToVale; + bool isStrUpperOverAtrUpper; + bool isStrLowerOverAtrLower; + bool isNewValeUnderAtrLower; + bool isAtrUpperCrossedUpPeak; + bool isAtrLowerCrossedUpVale; + bool isStrUpperUnderAtrUpper; + bool isStrLowerUnderAtrLower; + bool isX3MaFatsUnderSlowPrev; + bool isBreakedUpPrevAtrUpper; + bool isBreakedUpPrevAtrLower; + bool isBreakedDownPrevCheMin; + bool isBreakedDownPrevCheMax; + bool isBreakedDownPrevCheLE1; + bool isBreakedDownPrevCheLE2; + bool isBreakedDownPrevCheSE1; + bool isBreakedDownPrevCheSE2; + bool isX3MaFastCrossedOverMid; + bool isRejectedUpPrevAtrUpper; + bool isRejectedUpPrevAtrLower; + bool isVWapFastCrossedOverMid; + bool isX3MaFastCrossedUnderMid; + bool isX3MaFastCrossedOverSlow; + bool isAtrUpperCrossedDownPeak; + bool isAtrLowerCrossedDownVale; + bool isStrLowerOverDonLowLower; + bool isVWapFastCrossedUnderMid; + bool isBreakedDownPrevAtrUpper; + bool isBreakedDownPrevAtrLower; + bool isStrUpperCrossedOverPeak; + bool isStrLowerCrossedOverVale; + bool isDonLowLowerEqualsToVale; + bool isVWapFastCrossedOverSlow; + bool isX3MaFastCrossedUnderSlow; + bool isStrUpperOverDonHighUpper; + bool isStrLowerUnderDonLowLower; + bool isVWapFastCrossedUnderSlow; + bool isStrUpperCrossedUnderPeak; + bool isStrLowerCrossedUnderVale; + bool isDonHighUpperEqualsToPeak; + bool isRejectedDownPrevAtrUpper; + bool isRejectedDownPrevAtrLower; + bool isStrUpperUnderDonHighUpper; + bool isStrUpperCrossedOverAtrUpper; + bool isStrLowerCrossedOverAtrLower; + bool isStrUpperCrossedUnderAtrUpper; + bool isStrLowerCrossedUnderAtrLower; + bool isStrLowerCrossedOverDonLowLower; + bool isStrUpperCrossedOverDonHighUpper; + bool isStrLowerCrossedUnderDonLowLower; + bool isStrUpperCrossedUnderDonHighUpper; + + // + // Constructor ... + X121Conditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + // Commons ... + symbol = NULL; + period = NULL; + time = NULL; + + // + // Buffers ... + + // + Clean(maBuffer); + Clean(rsiBuffer); + Clean(atrBuffer); + Clean(strBuffer); + Clean(le1Buffer); + Clean(se1Buffer); + Clean(le2Buffer); + Clean(se2Buffer); + Clean(sarBuffer); + Clean(cHHBuffer); + Clean(cLLBuffer); + Clean(sHHBuffer); + Clean(sLLBuffer); + Clean(mHHBuffer); + Clean(mLLBuffer); + Clean(lHHBuffer); + Clean(lLLBuffer); + Clean(hHHBuffer); + Clean(hLLBuffer); + Clean(upTBuffer); + Clean(adxBuffer); + Clean(adxPBuffer); + Clean(adxMBuffer); + Clean(volumeBuffer); + Clean(peaksBuffer); + Clean(valesBuffer); + Clean(strUpBuffer); + Clean(downTBuffer); + Clean(strDownBuffer); + Clean(vwapMidBuffer); + Clean(upTrendBuffer); + Clean(x3maMidBuffer); + Clean(le1StartBuffer); + Clean(se1StartBuffer); + Clean(le2StartBuffer); + Clean(se2StartBuffer); + Clean(strPriceBuffer); + Clean(atrUpperBuffer); + Clean(atrLowerBuffer); + Clean(strStateBuffer); + Clean(vwapFastBuffer); + Clean(vwapSlowBuffer); + Clean(xhkSMLowBuffer); + Clean(x3maFastBuffer); + Clean(x3maSlowBuffer); + Clean(downTrendBuffer); + Clean(vwapPriceBuffer); + Clean(xhkRawLowBuffer); + Clean(xhkSMOpenBuffer); + Clean(xhkSMHighBuffer); + Clean(xhkRawOpenBuffer); + Clean(xhkRawHighBuffer); + Clean(xhkSMCloseBuffer); + Clean(vwapVolumeBuffer); + Clean(xhkRawCloseBuffer); + Clean(atrUpperRawBuffer); + Clean(atrLowerRawBuffer); + Clean(donLowUpperBuffer); + Clean(donLowLowerBuffer); + Clean(vwapMidStateBuffer); + Clean(donOpenUpperBuffer); + Clean(donOpenLowerBuffer); + Clean(donHighUpperBuffer); + Clean(donHighLowerBuffer); + Clean(x3maMidStateBuffer); + Clean(vwapFastStateBuffer); + Clean(vwapSlowStateBuffer); + Clean(donCloseUpperBuffer); + Clean(donCloseLowerBuffer); + Clean(x3maFastStateBuffer); + Clean(x3maSlowStateBuffer); + + // + ArraySetAsSeries(maBuffer, true); + ArraySetAsSeries(rsiBuffer, true); + ArraySetAsSeries(atrBuffer, true); + ArraySetAsSeries(strBuffer, true); + ArraySetAsSeries(le1Buffer, true); + ArraySetAsSeries(se1Buffer, true); + ArraySetAsSeries(le2Buffer, true); + ArraySetAsSeries(se2Buffer, true); + ArraySetAsSeries(sarBuffer, 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(upTBuffer, true); + ArraySetAsSeries(adxBuffer, true); + ArraySetAsSeries(adxPBuffer, true); + ArraySetAsSeries(adxMBuffer, true); + ArraySetAsSeries(volumeBuffer, true); + ArraySetAsSeries(peaksBuffer, true); + ArraySetAsSeries(valesBuffer, true); + ArraySetAsSeries(strUpBuffer, true); + ArraySetAsSeries(downTBuffer, true); + ArraySetAsSeries(strDownBuffer, true); + ArraySetAsSeries(vwapMidBuffer, true); + ArraySetAsSeries(upTrendBuffer, true); + ArraySetAsSeries(x3maMidBuffer, true); + ArraySetAsSeries(le1StartBuffer, true); + ArraySetAsSeries(se1StartBuffer, true); + ArraySetAsSeries(le2StartBuffer, true); + ArraySetAsSeries(se2StartBuffer, true); + ArraySetAsSeries(strPriceBuffer, true); + ArraySetAsSeries(atrUpperBuffer, true); + ArraySetAsSeries(atrLowerBuffer, true); + ArraySetAsSeries(strStateBuffer, true); + ArraySetAsSeries(vwapFastBuffer, true); + ArraySetAsSeries(vwapSlowBuffer, true); + ArraySetAsSeries(xhkSMLowBuffer, true); + ArraySetAsSeries(x3maFastBuffer, true); + ArraySetAsSeries(x3maSlowBuffer, true); + ArraySetAsSeries(downTrendBuffer, true); + ArraySetAsSeries(vwapPriceBuffer, true); + ArraySetAsSeries(xhkRawLowBuffer, true); + ArraySetAsSeries(xhkSMOpenBuffer, true); + ArraySetAsSeries(xhkSMHighBuffer, true); + ArraySetAsSeries(xhkRawOpenBuffer, true); + ArraySetAsSeries(xhkRawHighBuffer, true); + ArraySetAsSeries(xhkSMCloseBuffer, true); + ArraySetAsSeries(vwapVolumeBuffer, true); + ArraySetAsSeries(xhkRawCloseBuffer, true); + ArraySetAsSeries(atrUpperRawBuffer, true); + ArraySetAsSeries(atrLowerRawBuffer, true); + ArraySetAsSeries(donLowUpperBuffer, true); + ArraySetAsSeries(donLowLowerBuffer, true); + ArraySetAsSeries(vwapMidStateBuffer, true); + ArraySetAsSeries(donOpenUpperBuffer, true); + ArraySetAsSeries(donOpenLowerBuffer, true); + ArraySetAsSeries(donHighUpperBuffer, true); + ArraySetAsSeries(donHighLowerBuffer, true); + ArraySetAsSeries(x3maMidStateBuffer, true); + ArraySetAsSeries(vwapFastStateBuffer, true); + ArraySetAsSeries(vwapSlowStateBuffer, true); + ArraySetAsSeries(donCloseUpperBuffer, true); + ArraySetAsSeries(donCloseLowerBuffer, true); + ArraySetAsSeries(x3maFastStateBuffer, true); + ArraySetAsSeries(x3maSlowStateBuffer, true); + + // + cheMin = 0; + cheMax = 0; + vwapMin = 0; + vwapMax = 0; + x3maMin = 0; + x3maMax = 0; + + // + // Slopes ... + + rsiSlope = 0; + strSlope = 0; + atrUpperSlope = 0; + atrLowerSlope = 0; + vwapFastSlope = 0; + vwapMidSlope = 0; + vwapSlowSlope = 0; + + // + // Conditions ... + + // + isRsiSlopeBullish = false; + isStrSlopeBullish = false; + isAtrUpperSlopeBullish = false; + isAtrLowerSlopeBullish = false; + isVwapFastSlopeBullish = false; + isVwapMidSlopeBullish = false; + isVwapSlowSlopeBullish = false; + + // + isRsiSlopeBearish = false; + isStrSlopeBearish = false; + isAtrUpperSlopeBearish = false; + isAtrLowerSlopeBearish = false; + isVwapFastSlopeBearish = false; + isVwapMidSlopeBearish = false; + isVwapSlowSlopeBearish = false; + + // + // RSI ... + + // + isRsiOverBought = false; + isRsiCrossedOverOverBought = false; + isRsiCrossedUnderOverBought = false; + + // + isRsiOverSold = false; + isRsiCrossedUnderOverSold = false; + isRsiCrossedOverOverSold = false; + + // + // ATR ... + + // + isBreakedUpAtrUpper = false; + isBreakedUpAtrLower = false; + isClosedOverAtrUpper = false; + isClosedOverAtrLower = false; + isRejectedUpAtrUpper = false; + isRejectedUpAtrLower = false; + isClosedUnderAtrUpper = false; + isClosedUnderAtrLower = false; + isBreakedDownAtrUpper = false; + isBreakedDownAtrLower = false; + isRejectedDownAtrUpper = false; + isRejectedDownAtrLower = false; + + // + // DON ... + + // + isRejectedDonOpenUpper = false; + isRejectedDonHighUpper = false; + isRejectedDonLowUpper = false; + isRejectedDonCloseUpper = false; + isRejectedDonOpenLower = false; + isRejectedDonHighLower = false; + isRejectedDonLowLower = false; + isRejectedDonCloseLower = false; + isBreakedDonOpenUpper = false; + isBreakedDonHighUpper = false; + isBreakedDonLowUpper = false; + isBreakedDonCloseUpper = false; + isBreakedDonOpenLower = false; + isBreakedDonHighLower = false; + isBreakedDonLowLower = false; + isBreakedDonCloseLower = false; + + // + // SAR ... + + // + isSarBullish = false; + isSarBearish = false; + isSarSwitchedToBullish = false; + isSarSwitchedToBearish = false; + + // + // PV ... + + // + isNewPeak = false; + isNewPeakOverLast = false; + isNewPeakUnderLast = false; + isRejectedPrevPeak = false; + isBreakedUpPrevPeak = false; + + // + isNewVale = false; + isNewValeOverLast = false; + isNewValeUnderLast = false; + isRejectedPrevVale = false; + isBreakedDownPrevVale = false; + + // + // STR ... + + // + isStrBullish = false; + isStrBearish = false; + isStrSwitchedToBullish = false; + isStrSwitchedToBearish = false; + + // + // VWAP ... + isVWapMidBullish = false; + isVWapMidBearish = false; + isVWapMidNeutural = false; + isVWapSlowBullish = false; + isVWapSlowBearish = false; + isVWapFastBullish = false; + isVWapFastBearish = false; + isVWapFastOverMid = false; + isVWapMidOverSlow = false; + isVWapFastNeutural = false; + isVWapSlowNeutural = false; + isVWapFastUnderMid = false; + isVWapMidUnderSlow = false; + isVWapBullishState = false; + isVWapBearishState = false; + isVWapNeuturalState = false; + isVWapBullishOrdered = false; + isVWapBearishOrdered = false; + isVWapSwitchedToBullishState = false; + isVWapSwitchedToBearishState = false; + isVWapSwitchedToNeuturalState = false; + isVWapSwitchedToBullishOrdered = false; + isVWapSwitchedToBearishOrdered = false; + + // + // X3MA ... + isX3MaMidBullish = false; + isX3MaMidBearish = false; + isX3MaFastBullish = false; + isX3MaFastBearish = false; + isX3MaMidNeutural = false; + isX3MaSlowBullish = false; + isX3MaSlowBearish = false; + isX3MaFastOverMid = false; + isX3MaMidOverSlow = false; + isX3MaFastNeutural = false; + isX3MaSlowNeutural = false; + isX3MaFastUnderMid = false; + isX3MaMidUnderSlow = false; + isX3MaBullishState = false; + isX3MaBearishState = false; + isX3MaNeuturalState = false; + isX3MaBullishOrdered = false; + isX3MaBearishOrdered = false; + isX3MaSwitchedToBullishState = false; + isX3MaSwitchedToBearishState = false; + isX3MaSwitchedToNeuturalState = false; + isX3MaSwitchedToBullishOrdered = false; + isX3MaSwitchedToBearishOrdered = false; + + // + // CHE ... + + // + isCheBullish = false; + isCheBearish = false; + isChe1Bullish = false; + isChe1Bearish = false; + isChe2Bullish = false; + isChe2Bearish = false; + isClosedOverCheMin = false; + isClosedOverCheMax = false; + isClosedUnderCheMin = false; + isClosedUnderCheMax = false; + isCheSwitchedToBullish = false; + isCheSwitchedToBearish = false; + isChe1SwitchedToBullish = false; + isChe1SwitchedToBearish = false; + isChe2SwitchedToBullish = false; + isChe2SwitchedToBearish = false; + + // + // XHK ... + isSMHKBullish = false; + isRawHKBullish = false; + isSMHKBearish = false; + isRawHKBearish = false; + isBreakedUpSMHK = false; + isBreakedUpRawHK = false; + isRejectedUpSMHK = false; + isClosedOverSMHK = false; + isRejectedUpRawHK = false; + isBreakedDownSMHK = false; + isClosedUnderSMHK = false; + isClosedOverRawHK = false; + isClosedUnderRawHK = false; + isBreakedDownRawHK = false; + isRejectedDownSMHK = false; + isRejectedDownRawHK = false; + isRawHKBreakedUpSMHK = false; + isRawHKClosedOverSMHK = false; + isSMHKSwitchedToBearish = false; + isRawHKSwitchedToBearish = false; + isRawHKClosedUnderSMHK = false; + isRawHKBreakedDownSMHK = false; + isSMHKSwitchedToBullish = false; + isRawHKSwitchedToBullish = false; + + // + // Complex Conditions ... + + // + isSarIncreased = false; + isSarDecreased = false; + isX3MaFatsOverMid = false; + isSarEqualsToPeak = false; + isSarEqualsToVale = false; + isStrEqualsToPeak = false; + isStrEqualsToVale = false; + isX3MaMinBreakedUp = false; + isX3MaMaxBreakedUp = false; + isX3MaFatsUnderMid = false; + isX3MaFatsOverSlow = false; + isAtrUpperOverPeak = false; + isPeakOverAtrUpper = false; + isStrUpperOverPeak = false; + isStrLowerOverVale = false; + isBreakedUpPrevSar = false; + isBreakedUpPrevStr = false; + isVWapMinBreakedUp = false; + isVWapMaxBreakedUp = false; + isClosedOverCheMin = false; + isClosedOverCheMax = false; + isX3MaFatsUnderSlow = false; + isAtrLowerUnderVale = false; + isClosedOverX3MaMin = false; + isClosedOverX3MaMax = false; + isValeUnderAtrLower = false; + isStrUpperUnderPeak = false; + isStrLowerUnderVale = false; + isClosedUnderCheMin = false; + isClosedUnderCheMax = false; + isClosedOverVWapMin = false; + isClosedOverVWapMax = false; + isX3MaMinBreakedDown = false; + isX3MaMaxBreakedDown = false; + isClosedUnderX3MaMin = false; + isClosedUnderX3MaMax = false; + isBreakedDownPrevSar = false; + isBreakedDownPrevStr = false; + isStrCrossedOverVale = false; + isSarCrossedOverVale = false; + isClosedUnderVWapMin = false; + isClosedUnderVWapMax = false; + isVWapMinBreakedDown = false; + isVWapMaxBreakedDown = false; + isX3MaFatsOverMidPrev = false; + isSarCrossedUnderPeak = false; + isStrCrossedUnderPeak = false; + isNewPeakOverAtrUpper = false; + isBreakedUpPrevCheMin = false; + isBreakedUpPrevCheMax = false; + isBreakedUpPrevCheLE1 = false; + isBreakedUpPrevCheLE2 = false; + isBreakedUpPrevCheSE1 = false; + isBreakedUpPrevCheSE2 = false; + isX3MaFatsUnderMidPrev = false; + isX3MaFatsOverSlowPrev = false; + isAtrUpperEqualsToPeak = false; + isAtrLowerEqualsToVale = false; + isStrUpperOverAtrUpper = false; + isStrLowerOverAtrLower = false; + isNewValeUnderAtrLower = false; + isAtrUpperCrossedUpPeak = false; + isAtrLowerCrossedUpVale = false; + isStrUpperUnderAtrUpper = false; + isStrLowerUnderAtrLower = false; + isX3MaFatsUnderSlowPrev = false; + isBreakedUpPrevAtrUpper = false; + isBreakedUpPrevAtrLower = false; + isBreakedDownPrevCheMin = false; + isBreakedDownPrevCheMax = false; + isBreakedDownPrevCheLE1 = false; + isBreakedDownPrevCheLE2 = false; + isBreakedDownPrevCheSE1 = false; + isBreakedDownPrevCheSE2 = false; + isX3MaFastCrossedOverMid = false; + isRejectedUpPrevAtrUpper = false; + isRejectedUpPrevAtrLower = false; + isVWapFastCrossedOverMid = false; + isX3MaFastCrossedUnderMid = false; + isX3MaFastCrossedOverSlow = false; + isAtrUpperCrossedDownPeak = false; + isAtrLowerCrossedDownVale = false; + isStrLowerOverDonLowLower = false; + isVWapFastCrossedUnderMid = false; + isBreakedDownPrevAtrUpper = false; + isBreakedDownPrevAtrLower = false; + isStrUpperCrossedOverPeak = false; + isStrLowerCrossedOverVale = false; + isDonLowLowerEqualsToVale = false; + isVWapFastCrossedOverSlow = false; + isX3MaFastCrossedUnderSlow = false; + isStrUpperOverDonHighUpper = false; + isStrLowerUnderDonLowLower = false; + isVWapFastCrossedUnderSlow = false; + isStrUpperCrossedUnderPeak = false; + isStrLowerCrossedUnderVale = false; + isDonHighUpperEqualsToPeak = false; + isRejectedDownPrevAtrUpper = false; + isRejectedDownPrevAtrLower = false; + isStrUpperUnderDonHighUpper = false; + isStrUpperCrossedOverAtrUpper = false; + isStrLowerCrossedOverAtrLower = false; + isStrUpperCrossedUnderAtrUpper = false; + isStrLowerCrossedUnderAtrLower = false; + isStrLowerCrossedOverDonLowLower = false; + isStrUpperCrossedOverDonHighUpper = false; + isStrLowerCrossedUnderDonLowLower = false; + isStrUpperCrossedUnderDonHighUpper = false; + + // + ZeroMemory(this); + } + + /** + * Generate Conditions Scores ... + * + * @param bullishScore: Double, Directional Scores Reference ... + * @param bearishScore: Double, Directional Scores Reference ... + */ + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + // + bullishScore = 0; + bearishScore = 0; + + // + double score = 1; + double minScore = 0.5; + double highScore = 1.5; + + // + // SLOPES ... + + // + if (isRsiSlopeBullish) + { + bullishScore += minScore; + } + if (isStrSlopeBullish) + { + bullishScore += minScore; + } + if (isAtrUpperSlopeBullish) + { + bullishScore += minScore; + } + if (isAtrLowerSlopeBullish) + { + bullishScore += minScore; + } + if (isVwapFastSlopeBullish) + { + bullishScore += minScore; + } + if (isVwapMidSlopeBullish) + { + bullishScore += minScore; + } + if (isVwapSlowSlopeBullish) + { + bullishScore += minScore; + } + + // + if (isRsiSlopeBearish) + { + bearishScore += minScore; + } + if (isStrSlopeBearish) + { + bearishScore += minScore; + } + if (isAtrUpperSlopeBearish) + { + bearishScore += minScore; + } + if (isAtrLowerSlopeBearish) + { + bearishScore += minScore; + } + if (isVwapFastSlopeBearish) + { + bearishScore += minScore; + } + if (isVwapMidSlopeBearish) + { + bearishScore += minScore; + } + if (isVwapSlowSlopeBearish) + { + bearishScore += minScore; + } + + // + // COMPLEX ... + + // + if (isRsiOverSold) + { + bullishScore += score; + } + if (isRsiCrossedUnderOverSold) + { + bullishScore += highScore; + } + + // + if (isRsiOverBought) + { + bearishScore += score; + } + if (isRsiCrossedOverOverBought) + { + bearishScore += highScore; + } + + // + // XTREND ... + + // + if (isTrendBullish) + { + bullishScore += minScore; + } + if (isTrendSwitchedToBullish) + { + bullishScore += score; + } + + // + if (isTrendBearish) + { + bearishScore += minScore; + } + if (isTrendSwitchedToBearish) + { + bearishScore += score; + } + + // + // XSAR ... + + // + if (isSarBullish) + { + bullishScore += minScore; + } + if (isSarSwitchedToBullish) + { + bullishScore += score; + } + + // + if (isSarBearish) + { + bearishScore += minScore; + } + if (isSarSwitchedToBearish) + { + bearishScore += score; + } + + // + // XSTR ... + + // + if (isStrBullish) + { + bullishScore += minScore; + } + if (isStrSwitchedToBullish) + { + bullishScore += score; + } + + // + if (isStrBearish) + { + bearishScore += minScore; + } + if (isStrSwitchedToBearish) + { + bearishScore += score; + } + + // + // XCHE ... + + // + if (isCheBullish) + { + bullishScore += score; + } + if (isCheSwitchedToBullish) + { + bullishScore += highScore; + } + if (isChe1Bullish && + !isCheBullish && + !isCheSwitchedToBullish) + { + bullishScore += minScore; + } + if (isChe1SwitchedToBullish && + !isCheBullish && + !isCheSwitchedToBullish) + { + bullishScore += minScore; + } + + // + if (isCheBearish) + { + bearishScore += score; + } + if (isCheSwitchedToBearish) + { + bearishScore += highScore; + } + if (isChe1Bearish && + !isCheBearish && + !isCheSwitchedToBearish) + { + bearishScore += minScore; + } + if (isChe1SwitchedToBearish && + !isCheBearish && + !isCheSwitchedToBearish) + { + bearishScore += minScore; + } + + // + // XVWAP ... + + // + if (isVWapBullishState) + { + bullishScore += score; + } + if (isVWapBullishOrdered) + { + bullishScore += score; + } + if (isVWapSwitchedToBullishState) + { + bullishScore += highScore; + } + if (isVWapSwitchedToBullishOrdered) + { + bullishScore += highScore; + } + if (!isVWapBullishState && + !isVWapSwitchedToBullishState) + { + // + if (isVWapFastBullish) + { + bullishScore += minScore; + } + if (isVWapSlowBullish) + { + bullishScore += minScore; + } + } + if (!isVWapBullishOrdered && + !isVWapSwitchedToBullishOrdered) + { + // + if (isVWapFastOverMid) + { + bullishScore += minScore; + } + if (isVWapMidOverSlow) + { + bullishScore += minScore; + } + } + + // + if (isVWapBearishState) + { + bearishScore += score; + } + if (isVWapBearishOrdered) + { + bearishScore += score; + } + if (isVWapSwitchedToBearishState) + { + bearishScore += highScore; + } + if (isVWapSwitchedToBearishOrdered) + { + bearishScore += highScore; + } + if (!isVWapBearishState && + !isVWapSwitchedToBearishState) + { + // + if (isVWapFastBearish) + { + bearishScore += minScore; + } + if (isVWapSlowBearish) + { + bearishScore += minScore; + } + } + if (!isVWapBearishOrdered && + !isVWapSwitchedToBearishOrdered) + { + // + if (isVWapFastUnderMid) + { + bearishScore += minScore; + } + if (isVWapMidUnderSlow) + { + bearishScore += minScore; + } + } + + // + // X3MA ... + + // + if (isX3MaBullishState) + { + bullishScore += score; + } + if (isX3MaBullishOrdered) + { + bullishScore += score; + } + if (isX3MaSwitchedToBullishState) + { + bullishScore += highScore; + } + if (isX3MaSwitchedToBullishOrdered) + { + bullishScore += highScore; + } + if (!isX3MaBullishState && + !isX3MaSwitchedToBullishState) + { + // + if (isX3MaFastBullish) + { + bullishScore += minScore; + } + if (isX3MaSlowBullish) + { + bullishScore += minScore; + } + } + if (!isX3MaBullishOrdered && + !isX3MaSwitchedToBullishOrdered) + { + // + if (isX3MaFastOverMid) + { + bullishScore += minScore; + } + if (isX3MaMidOverSlow) + { + bullishScore += minScore; + } + } + + // + if (isX3MaBearishState) + { + bearishScore += score; + } + if (isX3MaBearishOrdered) + { + bearishScore += score; + } + if (isX3MaSwitchedToBearishState) + { + bearishScore += highScore; + } + if (isX3MaSwitchedToBearishOrdered) + { + bearishScore += highScore; + } + if (!isX3MaBearishState && + !isX3MaSwitchedToBearishState) + { + // + if (isX3MaFastBearish) + { + bearishScore += minScore; + } + if (isX3MaSlowBearish) + { + bearishScore += minScore; + } + } + if (!isX3MaBearishOrdered && + !isX3MaSwitchedToBearishOrdered) + { + // + if (isX3MaFastUnderMid) + { + bearishScore += minScore; + } + if (isX3MaMidUnderSlow) + { + bearishScore += minScore; + } + } + + // + // XSMHK ... + + // + if (isSMHKBullish) + { + bullishScore += minScore; + } + if (isRawHKBullish) + { + bullishScore += minScore; + } + if (isClosedOverSMHK) + { + bullishScore += minScore; + } + if (isClosedOverRawHK) + { + bullishScore += minScore; + } + if (isRawHKClosedOverSMHK) + { + bullishScore += minScore; + } + if (isSMHKSwitchedToBullish) + { + bullishScore += highScore; + } + if (isRawHKSwitchedToBullish) + { + bullishScore += highScore; + } + + // + if (isSMHKBearish) + { + bearishScore += minScore; + } + if (isRawHKBearish) + { + bearishScore += minScore; + } + if (isClosedUnderSMHK) + { + bearishScore += minScore; + } + if (isClosedUnderRawHK) + { + bearishScore += minScore; + } + if (isRawHKClosedUnderSMHK) + { + bearishScore += minScore; + } + if (isSMHKSwitchedToBearish) + { + bearishScore += highScore; + } + if (isRawHKSwitchedToBullish) + { + bearishScore += highScore; + } + + // + // Complex Conditions ... + + // + if (isSarIncreased) + { + bullishScore += minScore; + } + if (isSarEqualsToVale) + { + bullishScore += minScore; + } + if (isBreakedUpPrevSar) + { + bullishScore += minScore; + } + if (isSarCrossedOverVale) + { + bullishScore += score; + } + + // + if (isAtrLowerUnderVale) + { + bullishScore += minScore; + } + if (isValeUnderAtrLower) + { + bullishScore += minScore; + } + if (isNewValeUnderAtrLower) + { + bullishScore += minScore; + } + if (isAtrLowerEqualsToVale) + { + bullishScore += minScore; + } + if (isStrLowerOverAtrLower) + { + bullishScore += minScore; + } + if (isStrUpperOverAtrUpper) + { + bullishScore += minScore; + } + if (isAtrLowerCrossedUpVale) + { + bullishScore += score; + } + if (isAtrUpperCrossedUpPeak) + { + bullishScore += score; + } + if (isBreakedUpPrevAtrLower) + { + bullishScore += minScore; + } + if (isBreakedUpPrevAtrUpper) + { + bullishScore += minScore; + } + if (isRejectedUpPrevAtrUpper) + { + bullishScore += minScore; + } + if (isRejectedUpPrevAtrLower) + { + bullishScore += minScore; + } + if (isStrLowerCrossedOverAtrLower) + { + bullishScore += score; + } + if (isStrUpperCrossedOverAtrUpper) + { + bullishScore += score; + } + + // + if (isBreakedUpPrevStr) + { + bullishScore += minScore; + } + if (isStrEqualsToVale) + { + bullishScore += minScore; + } + if (isStrLowerOverVale) + { + bullishScore += minScore; + } + if (isStrLowerUnderVale) + { + bullishScore += minScore; + } + if (isStrCrossedOverVale) + { + bullishScore += score; + } + if (isStrUpperCrossedOverPeak) + { + bullishScore += score; + } + if (isStrLowerCrossedOverVale) + { + bullishScore += score; + } + if (isStrLowerUnderDonLowLower) + { + bullishScore += minScore; + } + if (isStrLowerCrossedOverDonLowLower) + { + bullishScore += score; + } + if (isStrUpperCrossedOverDonHighUpper) + { + bullishScore += score; + } + + // + if (isVWapMinBreakedUp) + { + bullishScore += minScore; + } + if (isVWapMaxBreakedUp) + { + bullishScore += minScore; + } + if (isClosedOverVWapMin) + { + bullishScore += minScore; + } + if (isClosedOverVWapMax) + { + bullishScore += minScore; + } + if (isVWapFastCrossedOverMid) + { + bullishScore += score; + } + if (isVWapFastCrossedOverSlow) + { + bullishScore += score; + } + + // + if (isX3MaMinBreakedUp) + { + bullishScore += minScore; + } + if (isX3MaMaxBreakedUp) + { + bullishScore += minScore; + } + if (isClosedOverX3MaMin) + { + bullishScore += minScore; + } + if (isClosedOverX3MaMax) + { + bullishScore += minScore; + } + if (isX3MaFastCrossedOverMid) + { + bullishScore += score; + } + if (isX3MaFastCrossedOverSlow) + { + bullishScore += score; + } + + // + if (isClosedOverCheMin) + { + bullishScore += minScore; + } + if (isClosedOverCheMax) + { + bullishScore += minScore; + } + if (isBreakedUpPrevCheMin) + { + bullishScore += minScore; + } + if (isBreakedUpPrevCheMax) + { + bullishScore += minScore; + } + if (isBreakedUpPrevCheLE1) + { + bullishScore += minScore; + } + if (isBreakedUpPrevCheLE2) + { + bullishScore += minScore; + } + if (isBreakedUpPrevCheSE1) + { + bullishScore += minScore; + } + if (isBreakedUpPrevCheSE2) + { + bullishScore += minScore; + } + if (isDonLowLowerEqualsToVale) + { + bullishScore += minScore; + } + + // + // + // + + // + if (isSarDecreased) + { + bearishScore += minScore; + } + if (isSarEqualsToPeak) + { + bearishScore += minScore; + } + if (isBreakedDownPrevSar) + { + bearishScore += minScore; + } + if (isSarCrossedUnderPeak) + { + bearishScore += score; + } + + // + if (isAtrUpperOverPeak) + { + bearishScore += minScore; + } + if (isPeakOverAtrUpper) + { + bearishScore += minScore; + } + if (isNewPeakOverAtrUpper) + { + bearishScore += minScore; + } + if (isAtrUpperEqualsToPeak) + { + bearishScore += minScore; + } + if (isStrLowerUnderAtrLower) + { + bearishScore += minScore; + } + if (isStrUpperUnderAtrUpper) + { + bearishScore += minScore; + } + if (isAtrLowerCrossedDownVale) + { + bearishScore += score; + } + if (isAtrUpperCrossedDownPeak) + { + bearishScore += score; + } + if (isBreakedDownPrevAtrUpper) + { + bearishScore += minScore; + } + if (isBreakedDownPrevAtrLower) + { + bearishScore += minScore; + } + if (isRejectedDownPrevAtrUpper) + { + bearishScore += minScore; + } + if (isRejectedDownPrevAtrLower) + { + bearishScore += minScore; + } + if (isStrLowerCrossedUnderAtrLower) + { + bearishScore += score; + } + if (isStrUpperCrossedUnderAtrUpper) + { + bearishScore += score; + } + + // + if (isStrEqualsToPeak) + { + bearishScore += minScore; + } + if (isStrUpperOverPeak) + { + bearishScore += minScore; + } + if (isStrUpperUnderPeak) + { + bearishScore += minScore; + } + if (isBreakedDownPrevStr) + { + bearishScore += minScore; + } + if (isStrCrossedUnderPeak) + { + bearishScore += score; + } + if (isStrLowerOverDonLowLower) + { + bearishScore += minScore; + } + if (isStrUpperOverDonHighUpper) + { + bearishScore += minScore; + } + if (isStrUpperCrossedUnderPeak) + { + bearishScore += score; + } + if (isStrLowerCrossedUnderVale) + { + bearishScore += score; + } + if (isStrUpperUnderDonHighUpper) + { + bearishScore += minScore; + } + if (isStrLowerCrossedUnderDonLowLower) + { + bearishScore += score; + } + if (isStrUpperCrossedUnderDonHighUpper) + { + bearishScore += score; + } + + // + if (isClosedUnderVWapMin) + { + bearishScore += minScore; + } + if (isClosedUnderVWapMax) + { + bearishScore += minScore; + } + if (isVWapMinBreakedDown) + { + bearishScore += minScore; + } + if (isVWapMaxBreakedDown) + { + bearishScore += minScore; + } + if (isVWapFastCrossedUnderMid) + { + bearishScore += score; + } + if (isVWapFastCrossedUnderSlow) + { + bearishScore += score; + } + + // + if (isX3MaMinBreakedDown) + { + bearishScore += minScore; + } + if (isX3MaMaxBreakedDown) + { + bearishScore += minScore; + } + if (isClosedUnderX3MaMin) + { + bearishScore += minScore; + } + if (isClosedUnderX3MaMax) + { + bearishScore += minScore; + } + if (isX3MaFastCrossedUnderMid) + { + bearishScore += score; + } + if (isX3MaFastCrossedUnderSlow) + { + bearishScore += score; + } + + // + if (isClosedUnderCheMin) + { + bearishScore += minScore; + } + if (isClosedUnderCheMax) + { + bearishScore += minScore; + } + if (isBreakedDownPrevCheMin) + { + bearishScore += minScore; + } + if (isBreakedDownPrevCheMax) + { + bearishScore += minScore; + } + if (isBreakedDownPrevCheLE1) + { + bearishScore += minScore; + } + if (isBreakedDownPrevCheLE2) + { + bearishScore += minScore; + } + if (isBreakedDownPrevCheSE1) + { + bearishScore += minScore; + } + if (isBreakedDownPrevCheSE2) + { + bearishScore += minScore; + } + if (isDonHighUpperEqualsToPeak) + { + bearishScore += minScore; + } + + // + // + // + } + + /** + * Generate Summary String for Represent Conditions State ... + * + * @param onlyCommons: Boolean, Just Generate Only Commons Conditions ... + * @param onlyConditions: Boolean, Just Generate Only Conditions ... + * @param includeScores: Boolean, Attach Scores Representations on Result ... + * @param ignoreFalseConditions: Boolean, Ignore False Conditions on Result ... + * @param separator: String, Separate Lines ... + * + * @return ( string ) + */ + string GenerateSummary( + bool onlyCommons = false, + bool onlyConditions = false, + bool includeScores = true, + bool ignoreFalseConditions = true, + string separator = "\n" // + ) + { + // + string result = NULL; + + // + double bullishScore = 0; + double bearishScore = 0; + GenerateScore( + bullishScore, + bearishScore // + ); + + // + string scoresStr = + // + "Scores: " + separator + + "---------------" + separator + + "Bullish: " + ToString(bullishScore) + separator + + "Bearish: " + ToString(bearishScore) + separator + + "" + // + ; + + // + string commonStr = GenerateSpecifiedCommonSummary( + this, + separator, + includeScores // + ); + + // + string conditionsStr = + // + "-----------------------" + separator + + "SAR ..." + separator + + "-----------------------" + separator + + ToString("isSarBullish", isSarBullish, ignoreFalseConditions, separator) + + ToString("isSarBearish", isSarBearish, ignoreFalseConditions, separator) + + ToString("isSarSwitchedToBullish", isSarSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isSarSwitchedToBearish", isSarSwitchedToBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "Trend ..." + separator + + "-----------------------" + separator + + ToString("isTrendBullish", isTrendBullish, ignoreFalseConditions, separator) + + ToString("isTrendBearish", isTrendBearish, ignoreFalseConditions, separator) + + ToString("isTrendSwitchedToBullish", isTrendSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isTrendSwitchedToBearish", isTrendSwitchedToBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "STR ..." + separator + + "-----------------------" + separator + + ToString("isStrBullish", isStrBullish, ignoreFalseConditions, separator) + + ToString("isStrBearish", isStrBearish, ignoreFalseConditions, separator) + + ToString("isStrSwitchedToBullish", isStrSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isStrSwitchedToBearish", isStrSwitchedToBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "PV ..." + separator + + "-----------------------" + separator + + ToString("isNewPeak", isNewPeak, ignoreFalseConditions, separator) + + ToString("isNewPeakOverLast", isNewPeakOverLast, ignoreFalseConditions, separator) + + ToString("isNewPeakUnderLast", isNewPeakUnderLast, ignoreFalseConditions, separator) + + ToString("isRejectedPrevPeak", isRejectedPrevPeak, ignoreFalseConditions, separator) + + ToString("isBreakedUpPrevPeak", isBreakedUpPrevPeak, ignoreFalseConditions, separator) + + ToString("isNewVale", isNewVale, ignoreFalseConditions, separator) + + ToString("isNewValeOverLast", isNewValeOverLast, ignoreFalseConditions, separator) + + ToString("isNewValeUnderLast", isNewValeUnderLast, ignoreFalseConditions, separator) + + ToString("isRejectedPrevVale", isRejectedPrevVale, ignoreFalseConditions, separator) + + ToString("isBreakedDownPrevVale", isBreakedDownPrevVale, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "> RSI ..." + separator + + "-----------------------" + separator + + ToString("isRsiOverBought", isRsiOverBought, ignoreFalseConditions, separator) + + ToString("isRsiCrossedOverOverBought", isRsiCrossedOverOverBought, ignoreFalseConditions, separator) + + ToString("isRsiCrossedUnderOverBought", isRsiCrossedUnderOverBought, ignoreFalseConditions, separator) + + ToString("isRsiOverSold", isRsiOverSold, ignoreFalseConditions, separator) + + ToString("isRsiCrossedUnderOverSold", isRsiCrossedUnderOverSold, ignoreFalseConditions, separator) + + ToString("isRsiCrossedOverOverSold", isRsiCrossedOverOverSold, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "ATR ..." + separator + + "-----------------------" + separator + + ToString("isClosedOverAtrUpper", isClosedOverAtrUpper, ignoreFalseConditions, separator) + + ToString("isClosedOverAtrLower", isClosedOverAtrLower, ignoreFalseConditions, separator) + + ToString("isClosedUnderAtrUpper", isClosedUnderAtrUpper, ignoreFalseConditions, separator) + + ToString("isClosedUnderAtrLower", isClosedUnderAtrLower, ignoreFalseConditions, separator) + + ToString("isRejectedUpAtrUpper", isRejectedUpAtrUpper, ignoreFalseConditions, separator) + + ToString("isRejectedDownAtrUpper", isRejectedDownAtrUpper, ignoreFalseConditions, separator) + + ToString("isRejectedUpAtrLower", isRejectedUpAtrLower, ignoreFalseConditions, separator) + + ToString("isRejectedDownAtrLower", isRejectedDownAtrLower, ignoreFalseConditions, separator) + + ToString("isBreakedUpAtrUpper", isBreakedUpAtrUpper, ignoreFalseConditions, separator) + + ToString("isBreakedDownAtrUpper", isBreakedDownAtrUpper, ignoreFalseConditions, separator) + + ToString("isBreakedUpAtrLower", isBreakedUpAtrLower, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "DON ..." + separator + + "-----------------------" + separator + + ToString("isBreakedDownAtrLower", isBreakedDownAtrLower, ignoreFalseConditions, separator) + + ToString("isRejectedDonOpenUpper", isRejectedDonOpenUpper, ignoreFalseConditions, separator) + + ToString("isRejectedDonHighUpper", isRejectedDonHighUpper, ignoreFalseConditions, separator) + + ToString("isRejectedDonLowUpper", isRejectedDonLowUpper, ignoreFalseConditions, separator) + + ToString("isRejectedDonCloseUpper", isRejectedDonCloseUpper, ignoreFalseConditions, separator) + + ToString("isRejectedDonOpenLower", isRejectedDonOpenLower, ignoreFalseConditions, separator) + + ToString("isRejectedDonHighLower", isRejectedDonHighLower, ignoreFalseConditions, separator) + + ToString("isRejectedDonLowLower", isRejectedDonLowLower, ignoreFalseConditions, separator) + + ToString("isRejectedDonCloseLower", isRejectedDonCloseLower, ignoreFalseConditions, separator) + + ToString("isBreakedDonOpenUpper", isBreakedDonOpenUpper, ignoreFalseConditions, separator) + + ToString("isBreakedDonHighUpper", isBreakedDonHighUpper, ignoreFalseConditions, separator) + + ToString("isBreakedDonLowUpper", isBreakedDonLowUpper, ignoreFalseConditions, separator) + + ToString("isBreakedDonCloseUpper", isBreakedDonCloseUpper, ignoreFalseConditions, separator) + + ToString("isBreakedDonOpenLower", isBreakedDonOpenLower, ignoreFalseConditions, separator) + + ToString("isBreakedDonHighLower", isBreakedDonHighLower, ignoreFalseConditions, separator) + + ToString("isBreakedDonLowLower", isBreakedDonLowLower, ignoreFalseConditions, separator) + + ToString("isBreakedDonCloseLower", isBreakedDonCloseLower, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "VWAP ..." + separator + + "-----------------------" + separator + + 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) + + // + "-----------------------" + separator + + "X3MA ..." + separator + + "-----------------------" + separator + + ToString("isX3MaMidBullish", isX3MaMidBullish, ignoreFalseConditions, separator) + + ToString("isX3MaMidBearish", isX3MaMidBearish, ignoreFalseConditions, separator) + + ToString("isX3MaFastBullish", isX3MaFastBullish, ignoreFalseConditions, separator) + + ToString("isX3MaFastBearish", isX3MaFastBearish, ignoreFalseConditions, separator) + + ToString("isX3MaMidNeutural", isX3MaMidNeutural, ignoreFalseConditions, separator) + + ToString("isX3MaSlowBullish", isX3MaSlowBullish, ignoreFalseConditions, separator) + + ToString("isX3MaSlowBearish", isX3MaSlowBearish, ignoreFalseConditions, separator) + + ToString("isX3MaFastOverMid", isX3MaFastOverMid, ignoreFalseConditions, separator) + + ToString("isX3MaMidOverSlow", isX3MaMidOverSlow, ignoreFalseConditions, separator) + + ToString("isX3MaFastNeutural", isX3MaFastNeutural, ignoreFalseConditions, separator) + + ToString("isX3MaSlowNeutural", isX3MaSlowNeutural, ignoreFalseConditions, separator) + + ToString("isX3MaFastUnderMid", isX3MaFastUnderMid, ignoreFalseConditions, separator) + + ToString("isX3MaMidUnderSlow", isX3MaMidUnderSlow, ignoreFalseConditions, separator) + + ToString("isX3MaBullishState", isX3MaBullishState, ignoreFalseConditions, separator) + + ToString("isX3MaBearishState", isX3MaBearishState, ignoreFalseConditions, separator) + + ToString("isX3MaNeuturalState", isX3MaNeuturalState, ignoreFalseConditions, separator) + + ToString("isX3MaBullishOrdered", isX3MaBullishOrdered, ignoreFalseConditions, separator) + + ToString("isX3MaBearishOrdered", isX3MaBearishOrdered, ignoreFalseConditions, separator) + + ToString("isX3MaSwitchedToBullishState", isX3MaSwitchedToBullishState, ignoreFalseConditions, separator) + + ToString("isX3MaSwitchedToBearishState", isX3MaSwitchedToBearishState, ignoreFalseConditions, separator) + + ToString("isX3MaSwitchedToNeuturalState", isX3MaSwitchedToNeuturalState, ignoreFalseConditions, separator) + + ToString("isX3MaSwitchedToBullishOrdered", isX3MaSwitchedToBullishOrdered, ignoreFalseConditions, separator) + + ToString("isX3MaSwitchedToBearishOrdered", isX3MaSwitchedToBearishOrdered, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "CHE ..." + separator + + "-----------------------" + separator + + ToString("isChe1Bullish", isChe1Bullish, ignoreFalseConditions, separator) + + ToString("isChe1Bearish", isChe1Bearish, ignoreFalseConditions, separator) + + ToString("isChe1SwitchedToBullish", isChe1SwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isChe1SwitchedToBearish", isChe1SwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isChe2Bullish", isChe2Bullish, ignoreFalseConditions, separator) + + ToString("isChe2Bearish", isChe2Bearish, ignoreFalseConditions, separator) + + ToString("isChe2SwitchedToBullish", isChe2SwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isChe2SwitchedToBearish", isChe2SwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isCheBullish", isCheBullish, ignoreFalseConditions, separator) + + ToString("isCheBearish", isCheBearish, ignoreFalseConditions, separator) + + ToString("isCheSwitchedToBullish", isCheSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isCheSwitchedToBearish", isCheSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isClosedOverCheMin", isClosedOverCheMin, ignoreFalseConditions, separator) + + ToString("isClosedOverCheMax", isClosedOverCheMax, ignoreFalseConditions, separator) + + ToString("isClosedUnderCheMin", isClosedUnderCheMin, ignoreFalseConditions, separator) + + ToString("isClosedUnderCheMax", isClosedUnderCheMax, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "HK ..." + separator + + "-----------------------" + separator + + ToString("isSMHKBullish", isSMHKBullish, ignoreFalseConditions, separator) + + ToString("isRawHKBullish", isRawHKBullish, ignoreFalseConditions, separator) + + ToString("isSMHKBearish", isSMHKBearish, ignoreFalseConditions, separator) + + ToString("isRawHKBearish", isRawHKBearish, ignoreFalseConditions, separator) + + ToString("isBreakedUpSMHK", isBreakedUpSMHK, ignoreFalseConditions, separator) + + ToString("isBreakedUpRawHK", isBreakedUpRawHK, ignoreFalseConditions, separator) + + ToString("isRejectedUpSMHK", isRejectedUpSMHK, ignoreFalseConditions, separator) + + ToString("isClosedOverSMHK", isClosedOverSMHK, ignoreFalseConditions, separator) + + ToString("isRejectedUpRawHK", isRejectedUpRawHK, ignoreFalseConditions, separator) + + ToString("isBreakedDownSMHK", isBreakedDownSMHK, ignoreFalseConditions, separator) + + ToString("isClosedUnderSMHK", isClosedUnderSMHK, ignoreFalseConditions, separator) + + ToString("isClosedOverRawHK", isClosedOverRawHK, ignoreFalseConditions, separator) + + ToString("isClosedUnderRawHK", isClosedUnderRawHK, ignoreFalseConditions, separator) + + ToString("isBreakedDownRawHK", isBreakedDownRawHK, ignoreFalseConditions, separator) + + ToString("isRejectedDownSMHK", isRejectedDownSMHK, ignoreFalseConditions, separator) + + ToString("isRejectedDownRawHK", isRejectedDownRawHK, ignoreFalseConditions, separator) + + ToString("isRawHKBreakedUpSMHK", isRawHKBreakedUpSMHK, ignoreFalseConditions, separator) + + ToString("isRawHKClosedOverSMHK", isRawHKClosedOverSMHK, ignoreFalseConditions, separator) + + ToString("isSMHKSwitchedToBearish", isSMHKSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isRawHKSwitchedToBearish", isRawHKSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isRawHKClosedUnderSMHK", isRawHKClosedUnderSMHK, ignoreFalseConditions, separator) + + ToString("isRawHKBreakedDownSMHK", isRawHKBreakedDownSMHK, ignoreFalseConditions, separator) + + ToString("isSMHKSwitchedToBullish", isSMHKSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isRawHKSwitchedToBullish", isRawHKSwitchedToBullish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "Slopes ..." + separator + + "-----------------------" + separator + + ToString("isRsiSlopeBullish", isRsiSlopeBullish, ignoreFalseConditions, separator) + + ToString("isStrSlopeBullish", isStrSlopeBullish, ignoreFalseConditions, separator) + + ToString("isAtrUpperSlopeBullish", isAtrUpperSlopeBullish, ignoreFalseConditions, separator) + + ToString("isAtrLowerSlopeBullish", isAtrLowerSlopeBullish, ignoreFalseConditions, separator) + + ToString("isVwapFastSlopeBullish", isVwapFastSlopeBullish, ignoreFalseConditions, separator) + + ToString("isVwapMidSlopeBullish", isVwapMidSlopeBullish, ignoreFalseConditions, separator) + + ToString("isVwapSlowSlopeBullish", isVwapSlowSlopeBullish, ignoreFalseConditions, separator) + + ToString("isRsiSlopeBearish", isRsiSlopeBearish, ignoreFalseConditions, separator) + + ToString("isStrSlopeBearish", isStrSlopeBearish, ignoreFalseConditions, separator) + + ToString("isAtrUpperSlopeBearish", isAtrUpperSlopeBearish, ignoreFalseConditions, separator) + + ToString("isAtrLowerSlopeBearish", isAtrLowerSlopeBearish, ignoreFalseConditions, separator) + + ToString("isVwapFastSlopeBearish", isVwapFastSlopeBearish, ignoreFalseConditions, separator) + + ToString("isVwapMidSlopeBearish", isVwapMidSlopeBearish, ignoreFalseConditions, separator) + + ToString("isVwapSlowSlopeBearish", isVwapSlowSlopeBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "Coplex ..." + separator + + "-----------------------" + separator + + ToString("isSarIncreased", isSarIncreased, ignoreFalseConditions, separator) + + ToString("isSarDecreased", isSarDecreased, ignoreFalseConditions, separator) + + ToString("isSarEqualsToPeak", isSarEqualsToPeak, ignoreFalseConditions, separator) + + + ToString("isStrEqualsToPeak", isStrEqualsToPeak, ignoreFalseConditions, separator) + + ToString("isStrEqualsToVale", isStrEqualsToVale, ignoreFalseConditions, separator) + + ToString("isPeakOverAtrUpper", isPeakOverAtrUpper, ignoreFalseConditions, separator) + + ToString("isBreakedUpPrevSar", isBreakedUpPrevSar, ignoreFalseConditions, separator) + + ToString("isBreakedUpPrevStr", isBreakedUpPrevStr, ignoreFalseConditions, separator) + + ToString("isVWapMinBreakedUp", isVWapMinBreakedUp, ignoreFalseConditions, separator) + + ToString("isVWapMaxBreakedUp", isVWapMaxBreakedUp, ignoreFalseConditions, separator) + + ToString("isStrUpperOverPeak", isStrUpperOverPeak, ignoreFalseConditions, separator) + + ToString("isStrLowerOverVale", isStrLowerOverVale, ignoreFalseConditions, separator) + + ToString("isAtrUpperOverPeak", isAtrUpperOverPeak, ignoreFalseConditions, separator) + + ToString("isAtrLowerUnderVale", isAtrLowerUnderVale, ignoreFalseConditions, separator) + + ToString("isClosedOverVWapMin", isClosedOverVWapMin, ignoreFalseConditions, separator) + + ToString("isClosedOverVWapMax", isClosedOverVWapMax, ignoreFalseConditions, separator) + + ToString("isStrUpperUnderPeak", isStrUpperUnderPeak, ignoreFalseConditions, separator) + + ToString("isValeUnderAtrLower", isValeUnderAtrLower, ignoreFalseConditions, separator) + + ToString("isStrLowerUnderVale", isStrLowerUnderVale, ignoreFalseConditions, separator) + + ToString("isVWapMinBreakedDown", isVWapMinBreakedDown, ignoreFalseConditions, separator) + + ToString("isVWapMaxBreakedDown", isVWapMaxBreakedDown, ignoreFalseConditions, separator) + + ToString("isClosedUnderVWapMin", isClosedUnderVWapMin, ignoreFalseConditions, separator) + + ToString("isClosedUnderVWapMax", isClosedUnderVWapMax, ignoreFalseConditions, separator) + + ToString("isBreakedDownPrevSar", isBreakedDownPrevSar, ignoreFalseConditions, separator) + + ToString("isBreakedDownPrevStr", isBreakedDownPrevStr, ignoreFalseConditions, separator) + + ToString("isSarCrossedOverVale", isSarCrossedOverVale, ignoreFalseConditions, separator) + + ToString("isStrCrossedOverVale", isStrCrossedOverVale, ignoreFalseConditions, separator) + + ToString("isBreakedUpPrevCheLE1", isBreakedUpPrevCheLE1, ignoreFalseConditions, separator) + + ToString("isBreakedUpPrevCheLE2", isBreakedUpPrevCheLE2, ignoreFalseConditions, separator) + + ToString("isBreakedUpPrevCheSE1", isBreakedUpPrevCheSE1, ignoreFalseConditions, separator) + + ToString("isBreakedUpPrevCheSE2", isBreakedUpPrevCheSE2, ignoreFalseConditions, separator) + + ToString("isSarCrossedUnderPeak", isSarCrossedUnderPeak, ignoreFalseConditions, separator) + + ToString("isStrCrossedUnderPeak", isStrCrossedUnderPeak, ignoreFalseConditions, separator) + + ToString("isNewPeakOverAtrUpper", isNewPeakOverAtrUpper, ignoreFalseConditions, separator) + + ToString("isBreakedUpPrevCheMin", isBreakedUpPrevCheMin, ignoreFalseConditions, separator) + + ToString("isBreakedUpPrevCheMax", isBreakedUpPrevCheMax, ignoreFalseConditions, separator) + + ToString("isNewValeUnderAtrLower", isNewValeUnderAtrLower, ignoreFalseConditions, separator) + + ToString("isStrUpperOverAtrUpper", isStrUpperOverAtrUpper, ignoreFalseConditions, separator) + + ToString("isStrLowerOverAtrLower", isStrLowerOverAtrLower, ignoreFalseConditions, separator) + + ToString("isAtrUpperEqualsToPeak", isAtrUpperEqualsToPeak, ignoreFalseConditions, separator) + + ToString("isAtrLowerEqualsToVale", isAtrLowerEqualsToVale, ignoreFalseConditions, separator) + + ToString("isBreakedDownPrevCheMin", isBreakedDownPrevCheMin, ignoreFalseConditions, separator) + + ToString("isBreakedDownPrevCheMax", isBreakedDownPrevCheMax, ignoreFalseConditions, separator) + + ToString("isBreakedDownPrevCheLE1", isBreakedDownPrevCheLE1, ignoreFalseConditions, separator) + + ToString("isBreakedDownPrevCheLE2", isBreakedDownPrevCheLE2, ignoreFalseConditions, separator) + + ToString("isBreakedDownPrevCheSE1", isBreakedDownPrevCheSE1, ignoreFalseConditions, separator) + + ToString("isBreakedDownPrevCheSE2", isBreakedDownPrevCheSE2, ignoreFalseConditions, separator) + + ToString("isAtrUpperCrossedUpPeak", isAtrUpperCrossedUpPeak, ignoreFalseConditions, separator) + + ToString("isAtrLowerCrossedUpVale", isAtrLowerCrossedUpVale, ignoreFalseConditions, separator) + + ToString("isStrUpperUnderAtrUpper", isStrUpperUnderAtrUpper, ignoreFalseConditions, separator) + + ToString("isStrLowerUnderAtrLower", isStrLowerUnderAtrLower, ignoreFalseConditions, separator) + + ToString("isBreakedUpPrevAtrUpper", isBreakedUpPrevAtrUpper, ignoreFalseConditions, separator) + + ToString("isBreakedUpPrevAtrLower", isBreakedUpPrevAtrLower, ignoreFalseConditions, separator) + + ToString("isVWapFastCrossedOverMid", isVWapFastCrossedOverMid, ignoreFalseConditions, separator) + + ToString("isRejectedUpPrevAtrUpper", isRejectedUpPrevAtrUpper, ignoreFalseConditions, separator) + + ToString("isRejectedUpPrevAtrLower", isRejectedUpPrevAtrLower, ignoreFalseConditions, separator) + + ToString("isAtrUpperCrossedDownPeak", isAtrUpperCrossedDownPeak, ignoreFalseConditions, separator) + + ToString("isAtrLowerCrossedDownVale", isAtrLowerCrossedDownVale, ignoreFalseConditions, separator) + + ToString("isBreakedDownPrevAtrUpper", isBreakedDownPrevAtrUpper, ignoreFalseConditions, separator) + + ToString("isBreakedDownPrevAtrLower", isBreakedDownPrevAtrLower, ignoreFalseConditions, separator) + + ToString("isVWapFastCrossedUnderMid", isVWapFastCrossedUnderMid, ignoreFalseConditions, separator) + + ToString("isVWapFastCrossedOverSlow", isVWapFastCrossedOverSlow, ignoreFalseConditions, separator) + + ToString("isStrUpperCrossedOverPeak", isStrUpperCrossedOverPeak, ignoreFalseConditions, separator) + + ToString("isStrLowerOverDonLowLower", isStrLowerOverDonLowLower, ignoreFalseConditions, separator) + + ToString("isStrLowerCrossedOverVale", isStrLowerCrossedOverVale, ignoreFalseConditions, separator) + + ToString("isDonLowLowerEqualsToVale", isDonLowLowerEqualsToVale, ignoreFalseConditions, separator) + + ToString("isRejectedDownPrevAtrUpper", isRejectedDownPrevAtrUpper, ignoreFalseConditions, separator) + + ToString("isRejectedDownPrevAtrLower", isRejectedDownPrevAtrLower, ignoreFalseConditions, separator) + + ToString("isVWapFastCrossedUnderSlow", isVWapFastCrossedUnderSlow, ignoreFalseConditions, separator) + + ToString("isStrUpperCrossedUnderPeak", isStrUpperCrossedUnderPeak, ignoreFalseConditions, separator) + + ToString("isStrLowerCrossedUnderVale", isStrLowerCrossedUnderVale, ignoreFalseConditions, separator) + + ToString("isDonHighUpperEqualsToPeak", isDonHighUpperEqualsToPeak, ignoreFalseConditions, separator) + + ToString("isStrUpperOverDonHighUpper", isStrUpperOverDonHighUpper, ignoreFalseConditions, separator) + + ToString("isStrLowerUnderDonLowLower", isStrLowerUnderDonLowLower, ignoreFalseConditions, separator) + + ToString("isStrUpperUnderDonHighUpper", isStrUpperUnderDonHighUpper, ignoreFalseConditions, separator) + + ToString("isStrUpperCrossedOverAtrUpper", isStrUpperCrossedOverAtrUpper, ignoreFalseConditions, separator) + + ToString("isStrLowerCrossedOverAtrLower", isStrLowerCrossedOverAtrLower, ignoreFalseConditions, separator) + + ToString("isStrUpperCrossedUnderAtrUpper", isStrUpperCrossedUnderAtrUpper, ignoreFalseConditions, separator) + + ToString("isStrLowerCrossedUnderAtrLower", isStrLowerCrossedUnderAtrLower, ignoreFalseConditions, separator) + + ToString("isStrLowerCrossedOverDonLowLower", isStrLowerCrossedOverDonLowLower, ignoreFalseConditions, separator) + + ToString("isStrUpperCrossedOverDonHighUpper", isStrUpperCrossedOverDonHighUpper, ignoreFalseConditions, separator) + + ToString("isStrLowerCrossedUnderDonLowLower", isStrLowerCrossedUnderDonLowLower, ignoreFalseConditions, separator) + + ToString("isStrUpperCrossedUnderDonHighUpper", isStrUpperCrossedUnderDonHighUpper, 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 XCBase +{ + // + public: + // + + // + // Helpers ... + XCX121XPVHelper *xpvHelper; + XCX121XHKHelper *xhkHelper; + XCX121XATRHelper *xatrHelper; + XCX121XSTRHelper *xstrHelper; + XCX121XCHEHelper *xcheHelper; + XCX121XDONHelper *xdonHelper; + XCX121X3MAHelper *x3maHelper; + XCX121XVWAPHelper *xvwapHelper; + XCX121XTRENDHelper *xtrendHelper; + + // + // Constructors ... + XCX121Helper() + { + } + + // + // Deconstructor ... + ~XCX121Helper() + { + // + mInputs.Clean(); + xpvInputs.Clean(); + xhkInputs.Clean(); + xatrInputs.Clean(); + xdonInputs.Clean(); + xstrInputs.Clean(); + xcheInputs.Clean(); + x3maInputs.Clean(); + xvwapInputs.Clean(); + xtrendInputs.Clean(); + + // + delete xpvHelper; + delete xhkHelper; + delete xatrHelper; + delete xstrHelper; + delete xcheHelper; + delete xdonHelper; + delete x3maHelper; + delete xvwapHelper; + delete xtrendHelper; + + // + ZeroMemory(xpvHelper); + ZeroMemory(xhkHelper); + ZeroMemory(xatrHelper); + ZeroMemory(xstrHelper); + ZeroMemory(xcheHelper); + ZeroMemory(xdonHelper); + ZeroMemory(x3maHelper); + ZeroMemory(xvwapHelper); + ZeroMemory(xtrendHelper); + } + + // + string GetSymbol() + { + return mSymbol; + } + + // + ENUM_TIMEFRAMES GetPeriod() + { + return mPeriod; + } + + // + // Tools ... + + /** + * Initialize Indicator Helper ... + * + * @param symbol: String, Symbol ... + * @param period: ENUM_TIMEFRAMES member, Period ... + * @param inputs: X121Inputs instance, Indicator Inputs ... + * + * @return ( bool ) + */ + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + X121Inputs &inputs // Inputs + ) + { + // + bool result = false; + + // + result = + IsValid(symbol) && + IsValid(period) && + inputs.IsValid(); + if (!result) + { + return result; + } + + // + mSymbol = symbol; + mPeriod = period; + + // + // Setting Inputs ... + + // + mInputs = inputs; + xpvInputs = inputs.xpvInputs; + xhkInputs = inputs.xhkInputs; + xatrInputs = inputs.xatrInputs; + xstrInputs = inputs.xstrInputs; + xcheInputs = inputs.xcheInputs; + xdonInputs = inputs.xdonInputs; + x3maInputs = inputs.x3maInputs; + xvwapInputs = inputs.xvwapInputs; + xtrendInputs = inputs.xtrendInputs; + + // + // Initial Helpers ... + + // + // XPV ... + xpvHelper = new XCX121XPVHelper(); + result = xpvHelper.Init( + symbol, + period, + xpvInputs // + ); + if (!result) + { + return result; + } + + // + // XHK ... + xhkHelper = new XCX121XHKHelper(); + result = xhkHelper.Init( + symbol, + period, + xhkInputs // + ); + if (!result) + { + return result; + } + + // + // XATR ... + xatrHelper = new XCX121XATRHelper(); + result = xatrHelper.Init( + symbol, + period, + xatrInputs // + ); + if (!result) + { + return result; + } + + // + // XSTR ... + xstrHelper = new XCX121XSTRHelper(); + result = xstrHelper.Init( + symbol, + period, + xstrInputs // + ); + if (!result) + { + return result; + } + + // + // XCHE ... + xcheHelper = new XCX121XCHEHelper(); + result = xcheHelper.Init( + symbol, + period, + xcheInputs // + ); + if (!result) + { + return result; + } + + // + // XDON ... + xdonHelper = new XCX121XDONHelper(); + result = xdonHelper.Init( + symbol, + period, + xdonInputs // + ); + if (!result) + { + return result; + } + + // + // X3MA ... + x3maHelper = new XCX121X3MAHelper(); + result = x3maHelper.Init( + symbol, + period, + x3maInputs // + ); + if (!result) + { + return result; + } + + // + // XVWAP ... + xvwapHelper = new XCX121XVWAPHelper(); + result = xvwapHelper.Init( + symbol, + period, + xvwapInputs // + ); + if (!result) + { + return result; + } + + // + // XTREND ... + xtrendHelper = new XCX121XTRENDHelper(); + result = xtrendHelper.Init( + symbol, + period, + xtrendInputs // + ); + if (!result) + { + return result; + } + + // + if (inputs.showRSI) + { + // + mRSIHandler = iRSI( + symbol, + period, + xatrInputs.rsiLength, + xatrInputs.rsiAppliedTo // + ); + + // + result = mRSIHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + } + + // + return result; + } + + // + // Conditions Readers ... + + // + // XPV ... + bool GetPVConditions( + X121XPVConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = false; + + // + result = xpvHelper.GetConditions( + conditions, + barIndex, + loopback // + ); + + // + return result; + } + + // + // XHK ... + bool GetHKConditions( + X121XHKConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = false; + + // + result = xhkHelper.GetConditions( + conditions, + barIndex, + loopback // + ); + + // + return result; + } + + // + // XATR ... + bool GetATRConditions( + X121XATRConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = false; + + // + result = xatrHelper.GetConditions( + conditions, + barIndex, + loopback // + ); + + // + return result; + } + + // + // XSTR ... + bool GetSTRConditions( + X121XSTRConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = false; + + // + result = xstrHelper.GetConditions( + conditions, + barIndex, + loopback // + ); + + // + return result; + } + + // + // XCHE ... + bool GetCHEConditions( + X121XCHEConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = false; + + // + result = xcheHelper.GetConditions( + conditions, + barIndex, + loopback // + ); + + // + return result; + } + + // + // XDON ... + bool GetDONConditions( + X121XDONConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = false; + + // + result = xdonHelper.GetConditions( + conditions, + barIndex, + loopback // + ); + + // + return result; + } + + // + // X3MA ... + bool Get3MAConditions( + X121X3MAConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = false; + + // + result = x3maHelper.GetConditions( + conditions, + barIndex, + loopback // + ); + + // + return result; + } + + // + // XVWAP ... + bool GetVWAPConditions( + X121XVWAPConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = false; + + // + result = xvwapHelper.GetConditions( + conditions, + barIndex, + loopback // + ); + + // + return result; + } + + // + // XTREND ... + bool GetTrendConditions( + X121XTRENDConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = false; + + // + result = xtrendHelper.GetConditions( + conditions, + barIndex, + loopback // + ); + + // + return result; + } + + // + void Free() + { + // + xpvHelper.Free(); + xhkHelper.Free(); + xatrHelper.Free(); + xstrHelper.Free(); + xcheHelper.Free(); + xdonHelper.Free(); + xvwapHelper.Free(); + xtrendHelper.Free(); + } + + // + 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; + } + + // + // XPV ... + X121XPVConditions xpvConditions; + result = GetPVConditions( + xpvConditions, + barIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // XHK ... + X121XHKConditions xhkConditions; + result = GetHKConditions( + xhkConditions, + barIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // XATR ... + X121XATRConditions xatrConditions; + result = GetATRConditions( + xatrConditions, + barIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // XSTR ... + X121XSTRConditions xstrConditions; + result = GetSTRConditions( + xstrConditions, + barIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // XCHE ... + X121XCHEConditions xcheConditions; + result = GetCHEConditions( + xcheConditions, + barIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // XDON ... + X121XDONConditions xdonConditions; + result = GetDONConditions( + xdonConditions, + barIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // X3MA ... + X121X3MAConditions x3maConditions; + result = Get3MAConditions( + x3maConditions, + barIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // XVWAP ... + X121XVWAPConditions xvwapConditions; + result = GetVWAPConditions( + xvwapConditions, + barIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // XTREND ... + X121XTRENDConditions xtrendConditions; + result = GetTrendConditions( + xtrendConditions, + barIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // Fill Volume Buffer ... + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + // Reading Bar Valuem ... + long iVol = iVolume( + mSymbol, + mPeriod, + i // + ); + + // + Add( + iVol, + conditions.volumeBuffer // + ); + } + + // + // Fill X121 Conditions Reference by Using + // Retrieved Conditions ... + + // + int cIDX = 1; + int pIDX = cIDX + 1; + + // + // XPV ... + + // + // Buffers ... + + // + Copy( + xpvConditions.peaksBuffer, + conditions.peaksBuffer // + ); + + // + Copy( + xpvConditions.valesBuffer, + conditions.valesBuffer // + ); + + // + Copy( + xpvConditions.sarBuffer, + conditions.sarBuffer // + ); + + // + Copy( + xpvConditions.cHHBuffer, + conditions.cHHBuffer // + ); + + // + Copy( + xpvConditions.cLLBuffer, + conditions.cLLBuffer // + ); + + // + Copy( + xpvConditions.sHHBuffer, + conditions.sHHBuffer // + ); + + // + Copy( + xpvConditions.sLLBuffer, + conditions.sLLBuffer // + ); + + // + Copy( + xpvConditions.mHHBuffer, + conditions.mHHBuffer // + ); + + // + Copy( + xpvConditions.mLLBuffer, + conditions.mLLBuffer // + ); + + // + Copy( + xpvConditions.lHHBuffer, + conditions.lHHBuffer // + ); + + // + Copy( + xpvConditions.lLLBuffer, + conditions.lLLBuffer // + ); + + // + Copy( + xpvConditions.hHHBuffer, + conditions.hHHBuffer // + ); + + // + Copy( + xpvConditions.hLLBuffer, + conditions.hLLBuffer // + ); + + // + // Conditions ... + + // + conditions.isNewPeak = xpvConditions.isNewPeak; + conditions.isNewVale = xpvConditions.isNewVale; + conditions.isSarBullish = xpvConditions.isSarBullish; + conditions.isSarBearish = xpvConditions.isSarBearish; + conditions.isNewPeakOverLast = xpvConditions.isNewPeakOverLast; + conditions.isNewValeOverLast = xpvConditions.isNewValeOverLast; + conditions.isNewPeakUnderLast = xpvConditions.isNewPeakUnderLast; + conditions.isNewValeUnderLast = xpvConditions.isNewValeUnderLast; + conditions.isRejectedPrevVale = xpvConditions.isRejectedPrevVale; + conditions.isRejectedPrevPeak = xpvConditions.isRejectedPrevPeak; + conditions.isBreakedUpPrevPeak = xpvConditions.isBreakedUpPrevPeak; + conditions.isBreakedDownPrevVale = xpvConditions.isBreakedDownPrevVale; + conditions.isSarSwitchedToBullish = xpvConditions.isSarSwitchedToBullish; + conditions.isSarSwitchedToBearish = xpvConditions.isSarSwitchedToBearish; + + // + // XHK ... + + // + // Buffers ... + + // + Copy( + xhkConditions.xhkRawOpenBuffer, + conditions.xhkRawOpenBuffer // + ); + + // + Copy( + xhkConditions.xhkRawHighBuffer, + conditions.xhkRawHighBuffer // + ); + + // + Copy( + xhkConditions.xhkRawLowBuffer, + conditions.xhkRawLowBuffer // + ); + + // + Copy( + xhkConditions.xhkRawCloseBuffer, + conditions.xhkRawCloseBuffer // + ); + + // + Copy( + xhkConditions.xhkSMOpenBuffer, + conditions.xhkSMOpenBuffer // + ); + + // + Copy( + xhkConditions.xhkSMHighBuffer, + conditions.xhkSMHighBuffer // + ); + + // + Copy( + xhkConditions.xhkSMLowBuffer, + conditions.xhkSMLowBuffer // + ); + + // + Copy( + xhkConditions.xhkSMCloseBuffer, + conditions.xhkSMCloseBuffer // + ); + + // + // Conditions ... + conditions.isSMHKBullish = xhkConditions.isSMHKBullish; + conditions.isRawHKBullish = xhkConditions.isRawHKBullish; + conditions.isSMHKBearish = xhkConditions.isSMHKBearish; + conditions.isRawHKBearish = xhkConditions.isRawHKBearish; + conditions.isBreakedUpSMHK = xhkConditions.isBreakedUpSMHK; + conditions.isBreakedUpRawHK = xhkConditions.isBreakedUpRawHK; + conditions.isRejectedUpSMHK = xhkConditions.isRejectedUpSMHK; + conditions.isClosedOverSMHK = xhkConditions.isClosedOverSMHK; + conditions.isRejectedUpRawHK = xhkConditions.isRejectedUpRawHK; + conditions.isBreakedDownSMHK = xhkConditions.isBreakedDownSMHK; + conditions.isClosedUnderSMHK = xhkConditions.isClosedUnderSMHK; + conditions.isClosedOverRawHK = xhkConditions.isClosedOverRawHK; + conditions.isClosedUnderRawHK = xhkConditions.isClosedUnderRawHK; + conditions.isBreakedDownRawHK = xhkConditions.isBreakedDownRawHK; + conditions.isRejectedDownSMHK = xhkConditions.isRejectedDownSMHK; + conditions.isRejectedDownRawHK = xhkConditions.isRejectedDownRawHK; + conditions.isRawHKBreakedUpSMHK = xhkConditions.isRawHKBreakedUpSMHK; + conditions.isRawHKClosedOverSMHK = xhkConditions.isRawHKClosedOverSMHK; + conditions.isSMHKSwitchedToBearish = xhkConditions.isSMHKSwitchedToBearish; + conditions.isRawHKSwitchedToBearish = xhkConditions.isRawHKSwitchedToBearish; + conditions.isRawHKClosedUnderSMHK = xhkConditions.isRawHKClosedUnderSMHK; + conditions.isRawHKBreakedDownSMHK = xhkConditions.isRawHKBreakedDownSMHK; + conditions.isSMHKSwitchedToBullish = xhkConditions.isSMHKSwitchedToBullish; + conditions.isRawHKSwitchedToBullish = xhkConditions.isRawHKSwitchedToBullish; + + // + // XTREND ... + + // + // Buffers ... + + // + Copy( + xtrendConditions.upTrendBuffer, + conditions.upTrendBuffer // + ); + + // + Copy( + xtrendConditions.downTrendBuffer, + conditions.downTrendBuffer // + ); + + // + Copy( + xtrendConditions.maBuffer, + conditions.maBuffer // + ); + + // + Copy( + xtrendConditions.adxBuffer, + conditions.adxBuffer // + ); + + // + Copy( + xtrendConditions.adxPBuffer, + conditions.adxPBuffer // + ); + + // + Copy( + xtrendConditions.adxMBuffer, + conditions.adxMBuffer // + ); + + // + Copy( + xtrendConditions.upTBuffer, + conditions.upTBuffer // + ); + + // + Copy( + xtrendConditions.downTBuffer, + conditions.downTBuffer // + ); + + // + conditions.isTrendBullish = xtrendConditions.isTrendBullish; + conditions.isTrendBearish = xtrendConditions.isTrendBearish; + conditions.isTrendSwitchedToBullish = xtrendConditions.isTrendSwitchedToBullish; + conditions.isTrendSwitchedToBearish = xtrendConditions.isTrendSwitchedToBearish; + + // + // XATR ... + + // + // Buffers ... + + // + Copy( + xatrConditions.atrUpperBuffer, + conditions.atrUpperBuffer // + ); + + // + Copy( + xatrConditions.atrLowerBuffer, + conditions.atrLowerBuffer // + ); + + // + Copy( + xatrConditions.atrUpperRawBuffer, + conditions.atrUpperRawBuffer // + ); + + // + Copy( + xatrConditions.atrLowerRawBuffer, + conditions.atrLowerRawBuffer // + ); + + // + Copy( + xatrConditions.atrBuffer, + conditions.atrBuffer // + ); + + // + Copy( + xatrConditions.rsiBuffer, + conditions.rsiBuffer // + ); + + // + // Conditions ... + + // + conditions.isRsiOverSold = xatrConditions.isRsiOverSold; + conditions.isRsiOverBought = xatrConditions.isRsiOverBought; + conditions.isBreakedUpAtrUpper = xatrConditions.isBreakedUpAtrUpper; + conditions.isBreakedUpAtrLower = xatrConditions.isBreakedUpAtrLower; + conditions.isClosedOverAtrUpper = xatrConditions.isClosedOverAtrUpper; + conditions.isRejectedUpAtrUpper = xatrConditions.isRejectedUpAtrUpper; + conditions.isRejectedUpAtrLower = xatrConditions.isRejectedUpAtrLower; + conditions.isClosedOverAtrLower = xatrConditions.isClosedOverAtrLower; + conditions.isBreakedDownAtrUpper = xatrConditions.isBreakedDownAtrUpper; + conditions.isBreakedDownAtrLower = xatrConditions.isBreakedDownAtrLower; + conditions.isClosedUnderAtrUpper = xatrConditions.isClosedUnderAtrUpper; + conditions.isClosedUnderAtrLower = xatrConditions.isClosedUnderAtrLower; + conditions.isRejectedDownAtrUpper = xatrConditions.isRejectedDownAtrUpper; + conditions.isRejectedDownAtrLower = xatrConditions.isRejectedDownAtrLower; + conditions.isRsiCrossedOverOverSold = xatrConditions.isRsiCrossedOverOverSold; + conditions.isRsiCrossedUnderOverSold = xatrConditions.isRsiCrossedUnderOverSold; + conditions.isRsiCrossedOverOverBought = xatrConditions.isRsiCrossedOverOverBought; + conditions.isRsiCrossedUnderOverBought = xatrConditions.isRsiCrossedUnderOverBought; + + // + // XSTR ... + + // + // Buffers ... + + // + Copy( + xstrConditions.strBuffer, + conditions.strBuffer // + ); + + // + Copy( + xstrConditions.strPriceBuffer, + conditions.strPriceBuffer // + ); + + // + Copy( + xstrConditions.strUpBuffer, + conditions.strUpBuffer // + ); + + // + Copy( + xstrConditions.strDownBuffer, + conditions.strDownBuffer // + ); + + // + Copy( + xstrConditions.strStateBuffer, + conditions.strStateBuffer // + ); + + // + // Conditions ... + + // + conditions.isStrBullish = xstrConditions.isStrBullish; + conditions.isStrBearish = xstrConditions.isStrBearish; + conditions.isStrSwitchedToBullish = xstrConditions.isStrSwitchedToBullish; + conditions.isStrSwitchedToBearish = xstrConditions.isStrSwitchedToBearish; + + // + // XCHE ... + + // + // Buffers ... + + // + Copy( + xcheConditions.le1Buffer, + conditions.le1Buffer // + ); + + // + Copy( + xcheConditions.se1Buffer, + conditions.se1Buffer // + ); + + // + Copy( + xcheConditions.le2Buffer, + conditions.le2Buffer // + ); + + // + Copy( + xcheConditions.se2Buffer, + conditions.se2Buffer // + ); + + // + Copy( + xcheConditions.le1StartBuffer, + conditions.le1StartBuffer // + ); + + // + Copy( + xcheConditions.se1StartBuffer, + conditions.se1StartBuffer // + ); + + // + Copy( + xcheConditions.le2StartBuffer, + conditions.le2StartBuffer // + ); + + // + Copy( + xcheConditions.se2StartBuffer, + conditions.se2StartBuffer // + ); + + // + // Conditions ... + + conditions.isCheBullish = xcheConditions.isCheBullish; + conditions.isCheBearish = xcheConditions.isCheBearish; + conditions.isChe1Bullish = xcheConditions.isChe1Bullish; + conditions.isChe1Bearish = xcheConditions.isChe1Bearish; + conditions.isChe2Bullish = xcheConditions.isChe2Bullish; + conditions.isChe2Bearish = xcheConditions.isChe2Bearish; + conditions.isClosedOverCheMin = xcheConditions.isClosedOverCheMin; + conditions.isClosedOverCheMax = xcheConditions.isClosedOverCheMax; + conditions.isClosedUnderCheMin = xcheConditions.isClosedUnderCheMin; + conditions.isClosedUnderCheMax = xcheConditions.isClosedUnderCheMax; + conditions.isCheSwitchedToBullish = xcheConditions.isCheSwitchedToBullish; + conditions.isCheSwitchedToBearish = xcheConditions.isCheSwitchedToBearish; + conditions.isChe1SwitchedToBullish = xcheConditions.isChe1SwitchedToBullish; + conditions.isChe1SwitchedToBearish = xcheConditions.isChe1SwitchedToBearish; + conditions.isChe2SwitchedToBullish = xcheConditions.isChe2SwitchedToBullish; + conditions.isChe2SwitchedToBearish = xcheConditions.isChe2SwitchedToBearish; + + // + // XDON ... + + // + // Buffers ... + + // + Copy( + xdonConditions.donOpenUpperBuffer, + conditions.donOpenUpperBuffer // + ); + + // + Copy( + xdonConditions.donOpenLowerBuffer, + conditions.donOpenLowerBuffer // + ); + + // + Copy( + xdonConditions.donHighUpperBuffer, + conditions.donHighUpperBuffer // + ); + + // + Copy( + xdonConditions.donHighLowerBuffer, + conditions.donHighLowerBuffer // + ); + + // + Copy( + xdonConditions.donLowUpperBuffer, + conditions.donLowUpperBuffer // + ); + + // + Copy( + xdonConditions.donLowLowerBuffer, + conditions.donLowLowerBuffer // + ); + + // + Copy( + xdonConditions.donCloseUpperBuffer, + conditions.donCloseUpperBuffer // + ); + + // + Copy( + xdonConditions.donCloseLowerBuffer, + conditions.donCloseLowerBuffer // + ); + + // + // Conditions ... + + // + conditions.isBreakedDonLowUpper = xdonConditions.isBreakedDonLowUpper; + conditions.isBreakedDonLowLower = xdonConditions.isBreakedDonLowLower; + conditions.isRejectedDonLowUpper = xdonConditions.isRejectedDonLowUpper; + conditions.isRejectedDonLowLower = xdonConditions.isRejectedDonLowLower; + conditions.isBreakedDonOpenUpper = xdonConditions.isBreakedDonOpenUpper; + conditions.isBreakedDonHighUpper = xdonConditions.isBreakedDonHighUpper; + conditions.isBreakedDonOpenLower = xdonConditions.isBreakedDonOpenLower; + conditions.isBreakedDonHighLower = xdonConditions.isBreakedDonHighLower; + conditions.isRejectedDonOpenUpper = xdonConditions.isRejectedDonOpenUpper; + conditions.isRejectedDonHighUpper = xdonConditions.isRejectedDonHighUpper; + conditions.isRejectedDonOpenLower = xdonConditions.isRejectedDonOpenLower; + conditions.isRejectedDonHighLower = xdonConditions.isRejectedDonHighLower; + conditions.isBreakedDonCloseUpper = xdonConditions.isBreakedDonCloseUpper; + conditions.isBreakedDonCloseLower = xdonConditions.isBreakedDonCloseLower; + conditions.isRejectedDonCloseUpper = xdonConditions.isRejectedDonCloseUpper; + conditions.isRejectedDonCloseLower = xdonConditions.isRejectedDonCloseLower; + + // + // X3MA ... + + // + // Buffers ... + + // + Copy( + x3maConditions.x3maFastBuffer, + conditions.x3maFastBuffer // + ); + + // + Copy( + x3maConditions.x3maMidBuffer, + conditions.x3maMidBuffer // + ); + + // + Copy( + x3maConditions.x3maSlowBuffer, + conditions.x3maSlowBuffer // + ); + + // + Copy( + x3maConditions.x3maFastStateBuffer, + conditions.x3maFastStateBuffer // + ); + + // + Copy( + x3maConditions.x3maMidStateBuffer, + conditions.x3maMidStateBuffer // + ); + + // + Copy( + x3maConditions.x3maSlowStateBuffer, + conditions.x3maSlowStateBuffer // + ); + + // + // Conditions ... + + // + conditions.isX3MaMidBullish = x3maConditions.isX3MaMidBullish; + conditions.isX3MaMidBearish = x3maConditions.isX3MaMidBearish; + conditions.isX3MaFastBullish = x3maConditions.isX3MaFastBullish; + conditions.isX3MaFastBearish = x3maConditions.isX3MaFastBearish; + conditions.isX3MaMidNeutural = x3maConditions.isX3MaMidNeutural; + conditions.isX3MaSlowBullish = x3maConditions.isX3MaSlowBullish; + conditions.isX3MaSlowBearish = x3maConditions.isX3MaSlowBearish; + conditions.isX3MaFastOverMid = x3maConditions.isX3MaFastOverMid; + conditions.isX3MaMidOverSlow = x3maConditions.isX3MaMidOverSlow; + conditions.isX3MaFastNeutural = x3maConditions.isX3MaFastNeutural; + conditions.isX3MaSlowNeutural = x3maConditions.isX3MaSlowNeutural; + conditions.isX3MaFastUnderMid = x3maConditions.isX3MaFastUnderMid; + conditions.isX3MaMidUnderSlow = x3maConditions.isX3MaMidUnderSlow; + conditions.isX3MaBullishState = x3maConditions.isX3MaBullishState; + conditions.isX3MaBearishState = x3maConditions.isX3MaBearishState; + conditions.isX3MaNeuturalState = x3maConditions.isX3MaNeuturalState; + conditions.isX3MaBullishOrdered = x3maConditions.isX3MaBullishOrdered; + conditions.isX3MaBearishOrdered = x3maConditions.isX3MaBearishOrdered; + conditions.isX3MaSwitchedToBullishState = x3maConditions.isX3MaSwitchedToBullishState; + conditions.isX3MaSwitchedToBearishState = x3maConditions.isX3MaSwitchedToBearishState; + conditions.isX3MaSwitchedToNeuturalState = x3maConditions.isX3MaSwitchedToNeuturalState; + conditions.isX3MaSwitchedToBullishOrdered = x3maConditions.isX3MaSwitchedToBullishOrdered; + conditions.isX3MaSwitchedToBearishOrdered = x3maConditions.isX3MaSwitchedToBearishOrdered; + + // + // XVWAP ... + + // + // Buffers ... + + // + Copy( + xvwapConditions.vwapFastBuffer, + conditions.vwapFastBuffer // + ); + + // + Copy( + xvwapConditions.vwapMidBuffer, + conditions.vwapMidBuffer // + ); + + // + Copy( + xvwapConditions.vwapSlowBuffer, + conditions.vwapSlowBuffer // + ); + + // + Copy( + xvwapConditions.vwapVolumeBuffer, + conditions.vwapVolumeBuffer // + ); + + // + Copy( + xvwapConditions.vwapPriceBuffer, + conditions.vwapPriceBuffer // + ); + + // + Copy( + xvwapConditions.vwapFastStateBuffer, + conditions.vwapFastStateBuffer // + ); + + // + Copy( + xvwapConditions.vwapMidStateBuffer, + conditions.vwapMidStateBuffer // + ); + + // + Copy( + xvwapConditions.vwapSlowStateBuffer, + conditions.vwapSlowStateBuffer // + ); + + // + // Conditions ... + + // + conditions.isVWapMidBullish = xvwapConditions.isVWapMidBullish; + conditions.isVWapMidBearish = xvwapConditions.isVWapMidBearish; + conditions.isVWapFastBullish = xvwapConditions.isVWapFastBullish; + conditions.isVWapFastBearish = xvwapConditions.isVWapFastBearish; + conditions.isVWapMidNeutural = xvwapConditions.isVWapMidNeutural; + conditions.isVWapSlowBullish = xvwapConditions.isVWapSlowBullish; + conditions.isVWapSlowBearish = xvwapConditions.isVWapSlowBearish; + conditions.isVWapFastOverMid = xvwapConditions.isVWapFastOverMid; + conditions.isVWapMidOverSlow = xvwapConditions.isVWapMidOverSlow; + conditions.isVWapFastNeutural = xvwapConditions.isVWapFastNeutural; + conditions.isVWapSlowNeutural = xvwapConditions.isVWapSlowNeutural; + conditions.isVWapFastUnderMid = xvwapConditions.isVWapFastUnderMid; + conditions.isVWapMidUnderSlow = xvwapConditions.isVWapMidUnderSlow; + conditions.isVWapBullishState = xvwapConditions.isVWapBullishState; + conditions.isVWapBearishState = xvwapConditions.isVWapBearishState; + conditions.isVWapNeuturalState = xvwapConditions.isVWapNeuturalState; + conditions.isVWapBullishOrdered = xvwapConditions.isVWapBullishOrdered; + conditions.isVWapBearishOrdered = xvwapConditions.isVWapBearishOrdered; + conditions.isVWapSwitchedToBullishState = xvwapConditions.isVWapSwitchedToBullishState; + conditions.isVWapSwitchedToBearishState = xvwapConditions.isVWapSwitchedToBearishState; + conditions.isVWapSwitchedToNeuturalState = xvwapConditions.isVWapSwitchedToNeuturalState; + conditions.isVWapSwitchedToBullishOrdered = xvwapConditions.isVWapSwitchedToBullishOrdered; + conditions.isVWapSwitchedToBearishOrdered = xvwapConditions.isVWapSwitchedToBearishOrdered; + + // + // Slopes ... + + // + double rsiSlope = GetSlope(conditions.rsiBuffer, pIDX, cIDX); + double strSlope = GetSlope(conditions.strBuffer, pIDX, cIDX); + double atrUpperSlope = GetSlope(conditions.atrUpperBuffer, pIDX, cIDX); + double atrLowerSlope = GetSlope(conditions.atrLowerBuffer, pIDX, cIDX); + double vwapFastSlope = GetSlope(conditions.vwapFastBuffer, pIDX, cIDX); + double vwapMidSlope = GetSlope(conditions.vwapMidBuffer, pIDX, cIDX); + double vwapSlowSlope = GetSlope(conditions.vwapSlowBuffer, pIDX, cIDX); + + // + bool isRsiSlopeBullish = rsiSlope > 0; + bool isStrSlopeBullish = strSlope > 0; + bool isAtrUpperSlopeBullish = atrUpperSlope > 0; + bool isAtrLowerSlopeBullish = atrLowerSlope > 0; + bool isVwapFastSlopeBullish = vwapFastSlope > 0; + bool isVwapMidSlopeBullish = vwapMidSlope > 0; + bool isVwapSlowSlopeBullish = vwapSlowSlope > 0; + + // + bool isRsiSlopeBearish = rsiSlope < 0; + bool isStrSlopeBearish = strSlope < 0; + bool isAtrUpperSlopeBearish = atrUpperSlope < 0; + bool isAtrLowerSlopeBearish = atrLowerSlope < 0; + bool isVwapFastSlopeBearish = vwapFastSlope < 0; + bool isVwapMidSlopeBearish = vwapMidSlope < 0; + bool isVwapSlowSlopeBearish = vwapSlowSlope < 0; + + // + conditions.rsiSlope = rsiSlope; + conditions.strSlope = strSlope; + conditions.vwapMidSlope = vwapMidSlope; + conditions.vwapSlowSlope = vwapSlowSlope; + conditions.atrUpperSlope = atrUpperSlope; + conditions.atrLowerSlope = atrLowerSlope; + conditions.vwapFastSlope = vwapFastSlope; + conditions.isRsiSlopeBearish = isRsiSlopeBearish; + conditions.isStrSlopeBearish = isStrSlopeBearish; + conditions.isRsiSlopeBullish = isRsiSlopeBullish; + conditions.isStrSlopeBullish = isStrSlopeBullish; + conditions.isVwapMidSlopeBearish = isVwapMidSlopeBearish; + conditions.isVwapMidSlopeBullish = isVwapMidSlopeBullish; + conditions.isAtrUpperSlopeBearish = isAtrUpperSlopeBearish; + conditions.isAtrLowerSlopeBearish = isAtrLowerSlopeBearish; + conditions.isVwapFastSlopeBearish = isVwapFastSlopeBearish; + conditions.isVwapSlowSlopeBearish = isVwapSlowSlopeBearish; + conditions.isAtrUpperSlopeBullish = isAtrUpperSlopeBullish; + conditions.isAtrLowerSlopeBullish = isAtrLowerSlopeBullish; + conditions.isVwapFastSlopeBullish = isVwapFastSlopeBullish; + conditions.isVwapSlowSlopeBullish = isVwapSlowSlopeBullish; + + // + // Complex Conditions ... + + // + double x3maFast = conditions.x3maFastBuffer[cIDX]; + double x3maMid = conditions.x3maMidBuffer[cIDX]; + double x3maSlow = conditions.x3maSlowBuffer[cIDX]; + + // + double x3mas[3] = { + x3maFast, + x3maMid, + x3maSlow // + }; + + // + double x3maMin = GetMin(x3mas); + double x3maMax = GetMax(x3mas); + + // + bool isX3MaMinBreakedUp = IsBarBreak( + x3maMin, + X_DIRECTION_BULLISH, + cBar // + ); + bool isX3MaMinBreakedDown = IsBarBreak( + x3maMin, + X_DIRECTION_BEARISH, + cBar // + ); + + // + bool isX3MaMaxBreakedUp = IsBarBreak( + x3maMax, + X_DIRECTION_BULLISH, + cBar // + ); + bool isX3MaMaxBreakedDown = IsBarBreak( + x3maMax, + X_DIRECTION_BEARISH, + cBar // + ); + + // + bool isX3MaFatsOverMid = conditions.x3maFastBuffer[cIDX] > conditions.x3maMidBuffer[cIDX]; + bool isX3MaFatsOverMidPrev = conditions.x3maFastBuffer[pIDX] > conditions.x3maMidBuffer[pIDX]; + + // + bool isX3MaFatsUnderMid = conditions.x3maFastBuffer[cIDX] < conditions.x3maMidBuffer[cIDX]; + bool isX3MaFatsUnderMidPrev = conditions.x3maFastBuffer[pIDX] < conditions.x3maMidBuffer[pIDX]; + + // + bool isX3MaFatsOverSlow = conditions.x3maFastBuffer[cIDX] > conditions.x3maSlowBuffer[cIDX]; + bool isX3MaFatsOverSlowPrev = conditions.x3maFastBuffer[pIDX] > conditions.x3maSlowBuffer[pIDX]; + + // + bool isX3MaFatsUnderSlow = conditions.x3maFastBuffer[cIDX] < conditions.x3maSlowBuffer[cIDX]; + bool isX3MaFatsUnderSlowPrev = conditions.x3maFastBuffer[pIDX] < conditions.x3maSlowBuffer[pIDX]; + + // + bool isX3MaFastCrossedOverMid = isX3MaFatsOverMid && + !isX3MaFatsOverMidPrev; + bool isX3MaFastCrossedUnderMid = isX3MaFatsUnderMid && + !isX3MaFatsUnderMidPrev; + + // + bool isX3MaFastCrossedOverSlow = isX3MaFatsOverSlow && + !isX3MaFatsOverSlowPrev; + bool isX3MaFastCrossedUnderSlow = isX3MaFatsUnderSlow && + !isX3MaFatsUnderSlowPrev; + + // + bool isClosedOverX3MaMin = cBar.close > x3maMin; + bool isClosedUnderX3MaMin = cBar.close < x3maMin; + + // + bool isClosedOverX3MaMax = cBar.close > x3maMax; + bool isClosedUnderX3MaMax = cBar.close < x3maMax; + + // + // + // + + // + double vwapFast = conditions.vwapFastBuffer[cIDX]; + double vwapMid = conditions.vwapMidBuffer[cIDX]; + double vwapSlow = conditions.vwapSlowBuffer[cIDX]; + + // + double vwaps[3] = { + vwapFast, + vwapMid, + vwapSlow // + }; + + // + double vwapMin = GetMin(vwaps); + double vwapMax = GetMax(vwaps); + + // + bool isVWapMinBreakedUp = IsBarBreak( + vwapMin, + X_DIRECTION_BULLISH, + cBar // + ); + bool isVWapMinBreakedDown = IsBarBreak( + vwapMin, + X_DIRECTION_BEARISH, + cBar // + ); + + // + bool isVWapMaxBreakedUp = IsBarBreak( + vwapMax, + X_DIRECTION_BULLISH, + cBar // + ); + bool isVWapMaxBreakedDown = IsBarBreak( + vwapMax, + X_DIRECTION_BEARISH, + cBar // + ); + + // + bool isVWapFatsOverMid = conditions.vwapFastBuffer[cIDX] > conditions.vwapMidBuffer[cIDX]; + bool isVWapFatsOverMidPrev = conditions.vwapFastBuffer[pIDX] > conditions.vwapMidBuffer[pIDX]; + + // + bool isVWapFatsUnderMid = conditions.vwapFastBuffer[cIDX] < conditions.vwapMidBuffer[cIDX]; + bool isVWapFatsUnderMidPrev = conditions.vwapFastBuffer[pIDX] < conditions.vwapMidBuffer[pIDX]; + + // + bool isVWapFatsOverSlow = conditions.vwapFastBuffer[cIDX] > conditions.vwapSlowBuffer[cIDX]; + bool isVWapFatsOverSlowPrev = conditions.vwapFastBuffer[pIDX] > conditions.vwapSlowBuffer[pIDX]; + + // + bool isVWapFatsUnderSlow = conditions.vwapFastBuffer[cIDX] < conditions.vwapSlowBuffer[cIDX]; + bool isVWapFatsUnderSlowPrev = conditions.vwapFastBuffer[pIDX] < conditions.vwapSlowBuffer[pIDX]; + + // + bool isVWapFastCrossedOverMid = isVWapFatsOverMid && + !isVWapFatsOverMidPrev; + bool isVWapFastCrossedUnderMid = isVWapFatsUnderMid && + !isVWapFatsUnderMidPrev; + + // + bool isVWapFastCrossedOverSlow = isVWapFatsOverSlow && + !isVWapFatsOverSlowPrev; + bool isVWapFastCrossedUnderSlow = isVWapFatsUnderSlow && + !isVWapFatsUnderSlowPrev; + + // + bool isClosedOverVWapMin = cBar.close > vwapMin; + bool isClosedUnderVWapMin = cBar.close < vwapMin; + + // + bool isClosedOverVWapMax = cBar.close > vwapMax; + bool isClosedUnderVWapMax = cBar.close < vwapMax; + + // + bool isSarEqualsToPeak = + conditions.sarBuffer[cIDX] == conditions.peaksBuffer[cIDX]; + bool isSarEqualsToVale = + conditions.sarBuffer[cIDX] == conditions.valesBuffer[cIDX]; + + // + bool isSarIncreased = conditions.sarBuffer[cIDX] > conditions.sarBuffer[pIDX]; + bool isSarDecreased = conditions.sarBuffer[cIDX] < conditions.sarBuffer[pIDX]; + + // + double prevSar = conditions.sarBuffer[pIDX]; + double prevStr = conditions.strBuffer[pIDX]; + double prevCheLE1 = conditions.le1Buffer[pIDX]; + double prevCheLE2 = conditions.le2Buffer[pIDX]; + double prevCheSE1 = conditions.se1Buffer[pIDX]; + double prevCheSE2 = conditions.se2Buffer[pIDX]; + double prevAtrUpper = conditions.atrUpperBuffer[pIDX]; + double prevAtrLower = conditions.atrLowerBuffer[pIDX]; + + // + double ches[]; + if (prevCheLE1 != EMPTY_VALUE) + { + // + Add( + prevCheLE1, + ches // + ); + } + if (prevCheLE2 != EMPTY_VALUE) + { + // + Add( + prevCheLE2, + ches // + ); + } + if (prevCheSE1 != EMPTY_VALUE) + { + // + Add( + prevCheSE1, + ches // + ); + } + if (prevCheSE2 != EMPTY_VALUE) + { + // + Add( + prevCheSE2, + ches // + ); + } + + // + double cheMin = GetMin(ches); + double cheMax = GetMax(ches); + + // + bool isBreakedUpPrevSar = IsBarBreak( + prevSar, + X_DIRECTION_BULLISH, + cBar // + ); + bool isBreakedDownPrevSar = IsBarBreak( + prevSar, + X_DIRECTION_BEARISH, + cBar // + ); + + // + bool isBreakedUpPrevStr = IsBarBreak( + prevStr, + X_DIRECTION_BULLISH, + cBar // + ); + bool isBreakedDownPrevStr = IsBarBreak( + prevStr, + X_DIRECTION_BEARISH, + cBar // + ); + + // + bool isRejectedUpPrevAtrUpper = IsBarReject( + prevAtrUpper, + X_DIRECTION_BULLISH, + cBar // + ); + + // + bool isRejectedDownPrevAtrUpper = IsBarReject( + prevAtrUpper, + X_DIRECTION_BEARISH, + cBar // + ); + + // + bool isRejectedUpPrevAtrLower = IsBarReject( + prevAtrLower, + X_DIRECTION_BULLISH, + cBar // + ); + + // + bool isRejectedDownPrevAtrLower = IsBarReject( + prevAtrLower, + X_DIRECTION_BEARISH, + cBar // + ); + + // + bool isBreakedUpPrevAtrUpper = IsBarBreak( + prevAtrUpper, + X_DIRECTION_BULLISH, + cBar // + ); + bool isBreakedDownPrevAtrUpper = IsBarBreak( + prevAtrUpper, + X_DIRECTION_BEARISH, + cBar // + ); + + // + bool isBreakedUpPrevAtrLower = IsBarBreak( + prevAtrLower, + X_DIRECTION_BULLISH, + cBar // + ); + bool isBreakedDownPrevAtrLower = IsBarBreak( + prevAtrLower, + X_DIRECTION_BEARISH, + cBar // + ); + + // + bool isBreakedUpPrevCheLE1 = IsBarBreak( + prevCheLE1, + X_DIRECTION_BULLISH, + cBar // + ); + bool isBreakedUpPrevCheLE2 = IsBarBreak( + prevCheLE2, + X_DIRECTION_BULLISH, + cBar // + ); + bool isBreakedUpPrevCheSE1 = IsBarBreak( + prevCheSE1, + X_DIRECTION_BULLISH, + cBar // + ); + bool isBreakedUpPrevCheSE2 = IsBarBreak( + prevCheSE2, + X_DIRECTION_BULLISH, + cBar // + ); + + // + bool isBreakedDownPrevCheLE1 = IsBarBreak( + prevCheLE1, + X_DIRECTION_BEARISH, + cBar // + ); + bool isBreakedDownPrevCheLE2 = IsBarBreak( + prevCheLE2, + X_DIRECTION_BEARISH, + cBar // + ); + bool isBreakedDownPrevCheSE1 = IsBarBreak( + prevCheSE1, + X_DIRECTION_BEARISH, + cBar // + ); + bool isBreakedDownPrevCheSE2 = IsBarBreak( + prevCheSE2, + X_DIRECTION_BEARISH, + cBar // + ); + + // + bool isBreakedUpPrevCheMin = IsBarBreak( + cheMin, + X_DIRECTION_BULLISH, + cBar // + ); + bool isBreakedDownPrevCheMin = IsBarBreak( + cheMin, + X_DIRECTION_BEARISH, + cBar // + ); + + // + bool isBreakedUpPrevCheMax = IsBarBreak( + cheMax, + X_DIRECTION_BULLISH, + cBar // + ); + bool isBreakedDownPrevCheMax = IsBarBreak( + cheMax, + X_DIRECTION_BEARISH, + cBar // + ); + + // + bool isSarCrossedUnderPeak = + conditions.sarBuffer[cIDX] < conditions.peaksBuffer[cIDX] && + !(conditions.sarBuffer[pIDX] < conditions.peaksBuffer[pIDX]); + bool isSarCrossedOverVale = + conditions.sarBuffer[cIDX] > conditions.valesBuffer[cIDX] && + !(conditions.sarBuffer[pIDX] > conditions.valesBuffer[pIDX]); + + // + bool isStrEqualsToPeak = + conditions.strBuffer[cIDX] == conditions.peaksBuffer[cIDX]; + bool isStrEqualsToVale = + conditions.strBuffer[cIDX] == conditions.valesBuffer[cIDX]; + + // + bool isStrCrossedUnderPeak = + conditions.strBuffer[cIDX] < conditions.peaksBuffer[cIDX] && + !(conditions.strBuffer[pIDX] < conditions.peaksBuffer[pIDX]); + bool isStrCrossedOverVale = + conditions.strBuffer[cIDX] > conditions.valesBuffer[cIDX] && + !(conditions.strBuffer[pIDX] > conditions.valesBuffer[pIDX]); + + // + bool isPeakOverAtrUpper = + conditions.peaksBuffer[cIDX] > conditions.atrUpperBuffer[cIDX]; + bool isValeUnderAtrLower = + conditions.valesBuffer[cIDX] > conditions.atrLowerBuffer[cIDX]; + + // + bool isNewPeakOverAtrUpper = + isPeakOverAtrUpper && + conditions.isNewPeak; + bool isNewValeUnderAtrLower = + isValeUnderAtrLower && + conditions.isNewVale; + + // + bool isStrUpperOverPeak = + conditions.strBuffer[cIDX] > conditions.peaksBuffer[cIDX]; + bool isStrUpperOverPeakPrev = + conditions.strBuffer[pIDX] > conditions.peaksBuffer[pIDX]; + + // + bool isStrUpperUnderPeak = + conditions.strBuffer[cIDX] < conditions.peaksBuffer[cIDX]; + bool isStrUpperUnderPeakPrev = + conditions.strBuffer[pIDX] < conditions.peaksBuffer[pIDX]; + + // + bool isStrUpperCrossedOverPeak = isStrUpperOverPeak && + !isStrUpperOverPeakPrev; + bool isStrUpperCrossedUnderPeak = isStrUpperUnderPeak && + !isStrUpperUnderPeakPrev; + + // + bool isStrLowerOverVale = + conditions.strBuffer[cIDX] > conditions.valesBuffer[cIDX]; + bool isStrLowerOverValePrev = + conditions.strBuffer[pIDX] > conditions.valesBuffer[pIDX]; + + // + bool isStrLowerUnderVale = + conditions.strBuffer[cIDX] < conditions.valesBuffer[cIDX]; + bool isStrLowerUnderValePrev = + conditions.strBuffer[pIDX] < conditions.valesBuffer[pIDX]; + + // + bool isStrLowerCrossedOverVale = isStrLowerOverVale && + !isStrLowerOverValePrev; + bool isStrLowerCrossedUnderVale = isStrLowerUnderVale && + !isStrLowerUnderValePrev; + + // + bool isDonHighUpperEqualsToPeak = + conditions.donHighUpperBuffer[cIDX] == conditions.peaksBuffer[cIDX]; + bool isDonLowLowerEqualsToVale = + conditions.donLowLowerBuffer[cIDX] == conditions.valesBuffer[cIDX]; + + // + bool isStrUpperOverAtrUpper = + conditions.strUpBuffer[cIDX] > conditions.atrUpperBuffer[cIDX]; + bool isStrUpperOverAtrUpperPrev = + conditions.strUpBuffer[pIDX] > conditions.atrUpperBuffer[pIDX]; + bool isStrUpperCrossedOverAtrUpper = isStrUpperOverAtrUpper && + !isStrUpperOverAtrUpperPrev; + + // + bool isStrUpperUnderAtrUpper = + conditions.strUpBuffer[cIDX] < conditions.atrUpperBuffer[cIDX]; + bool isStrUpperUnderAtrUpperPrev = + conditions.strUpBuffer[pIDX] < conditions.atrUpperBuffer[pIDX]; + bool isStrUpperCrossedUnderAtrUpper = isStrUpperUnderAtrUpper && + !isStrUpperUnderAtrUpperPrev; + + // + bool isStrLowerOverAtrLower = + conditions.strDownBuffer[cIDX] > conditions.atrLowerBuffer[cIDX]; + bool isStrLowerOverAtrLowerPrev = + conditions.strDownBuffer[pIDX] > conditions.atrLowerBuffer[pIDX]; + bool isStrLowerCrossedOverAtrLower = isStrLowerOverAtrLower && + !isStrLowerOverAtrLowerPrev; + + // + bool isStrLowerUnderAtrLower = + conditions.strDownBuffer[cIDX] < conditions.atrLowerBuffer[cIDX]; + bool isStrLowerUnderAtrLowerPrev = + conditions.strDownBuffer[pIDX] < conditions.atrLowerBuffer[pIDX]; + bool isStrLowerCrossedUnderAtrLower = isStrLowerUnderAtrLower && + !isStrLowerUnderAtrLowerPrev; + + // + bool isStrUpperOverDonHighUpper = + conditions.strUpBuffer[cIDX] > conditions.donHighUpperBuffer[cIDX]; + bool isStrUpperOverDonHighUpperPrev = + conditions.strUpBuffer[pIDX] > conditions.donHighUpperBuffer[pIDX]; + bool isStrUpperCrossedOverDonHighUpper = isStrUpperOverDonHighUpper && + !isStrUpperOverDonHighUpperPrev; + + // + bool isStrUpperUnderDonHighUpper = + conditions.strUpBuffer[cIDX] < conditions.donHighUpperBuffer[cIDX]; + bool isStrUpperUnderDonHighUpperPrev = + conditions.strUpBuffer[pIDX] < conditions.donHighUpperBuffer[pIDX]; + bool isStrUpperCrossedUnderDonHighUpper = isStrUpperUnderDonHighUpper && + !isStrUpperUnderDonHighUpperPrev; + + // + bool isStrLowerOverDonLowLower = + conditions.strDownBuffer[cIDX] > conditions.donLowLowerBuffer[cIDX]; + bool isStrLowerOverDonLowLowerPrev = + conditions.strDownBuffer[pIDX] > conditions.donLowLowerBuffer[pIDX]; + bool isStrLowerCrossedOverDonLowLower = isStrLowerOverDonLowLower && + !isStrLowerOverDonLowLowerPrev; + + // + bool isStrLowerUnderDonLowLower = + conditions.strDownBuffer[cIDX] < conditions.donLowLowerBuffer[cIDX]; + bool isStrLowerUnderDonLowLowerPrev = + conditions.strDownBuffer[pIDX] < conditions.donLowLowerBuffer[pIDX]; + bool isStrLowerCrossedUnderDonLowLower = isStrLowerUnderDonLowLower && + !isStrLowerUnderDonLowLowerPrev; + + // + bool isAtrUpperOverPeak = conditions.atrUpperBuffer[cIDX] > conditions.peaksBuffer[cIDX]; + bool isAtrUpperEqualsToPeak = conditions.atrUpperBuffer[cIDX] == conditions.peaksBuffer[cIDX]; + + // + bool isAtrUpperCrossedUpPeak = conditions.atrUpperBuffer[cIDX] > conditions.peaksBuffer[cIDX] && + !(conditions.atrUpperBuffer[cIDX] > conditions.peaksBuffer[cIDX]); + bool isAtrUpperCrossedDownPeak = conditions.atrUpperBuffer[cIDX] < conditions.peaksBuffer[cIDX] && + !(conditions.atrUpperBuffer[cIDX] < conditions.peaksBuffer[cIDX]); + + // + bool isAtrLowerUnderVale = conditions.atrUpperBuffer[cIDX] < conditions.valesBuffer[cIDX]; + bool isAtrLowerEqualsToVale = conditions.atrUpperBuffer[cIDX] == conditions.valesBuffer[cIDX]; + + // + bool isAtrLowerCrossedUpVale = conditions.atrUpperBuffer[cIDX] > conditions.valesBuffer[cIDX] && + !(conditions.atrUpperBuffer[cIDX] > conditions.valesBuffer[cIDX]); + bool isAtrLowerCrossedDownVale = conditions.atrUpperBuffer[cIDX] < conditions.valesBuffer[cIDX] && + !(conditions.atrUpperBuffer[cIDX] < conditions.valesBuffer[cIDX]); + + // + conditions.cheMin = cheMin; + conditions.cheMax = cheMax; + conditions.x3maMin = x3maMin; + conditions.x3maMax = x3maMax; + conditions.vwapMin = vwapMin; + conditions.vwapMax = vwapMax; + + // + conditions.isSarIncreased = isSarIncreased; + conditions.isSarDecreased = isSarDecreased; + conditions.isSarEqualsToPeak = isSarEqualsToPeak; + conditions.isSarEqualsToVale = isSarEqualsToVale; + conditions.isStrEqualsToPeak = isStrEqualsToPeak; + conditions.isStrEqualsToVale = isStrEqualsToVale; + conditions.isX3MaFatsOverMid = isX3MaFatsOverMid; + conditions.isX3MaMinBreakedUp = isX3MaMinBreakedUp; + conditions.isX3MaMaxBreakedUp = isX3MaMaxBreakedUp; + conditions.isX3MaFatsUnderMid = isX3MaFatsUnderMid; + conditions.isX3MaFatsOverSlow = isX3MaFatsOverSlow; + conditions.isStrUpperOverPeak = isStrUpperOverPeak; + conditions.isPeakOverAtrUpper = isPeakOverAtrUpper; + conditions.isStrLowerOverVale = isStrLowerOverVale; + conditions.isVWapMinBreakedUp = isVWapMinBreakedUp; + conditions.isVWapMaxBreakedUp = isVWapMaxBreakedUp; + conditions.isBreakedUpPrevSar = isBreakedUpPrevSar; + conditions.isBreakedUpPrevStr = isBreakedUpPrevStr; + conditions.isAtrUpperOverPeak = isAtrUpperOverPeak; + conditions.isClosedOverX3MaMin = isClosedOverX3MaMin; + conditions.isClosedOverX3MaMax = isClosedOverX3MaMax; + conditions.isX3MaFatsUnderSlow = isX3MaFatsUnderSlow; + conditions.isAtrLowerUnderVale = isAtrLowerUnderVale; + conditions.isStrLowerUnderVale = isStrLowerUnderVale; + conditions.isStrUpperUnderPeak = isStrUpperUnderPeak; + conditions.isValeUnderAtrLower = isValeUnderAtrLower; + conditions.isClosedOverVWapMin = isClosedOverVWapMin; + conditions.isClosedOverVWapMax = isClosedOverVWapMax; + conditions.isClosedUnderX3MaMin = isClosedUnderX3MaMin; + conditions.isClosedUnderX3MaMax = isClosedUnderX3MaMax; + conditions.isX3MaMinBreakedDown = isX3MaMinBreakedDown; + conditions.isX3MaMaxBreakedDown = isX3MaMaxBreakedDown; + conditions.isClosedUnderVWapMin = isClosedUnderVWapMin; + conditions.isClosedUnderVWapMax = isClosedUnderVWapMax; + conditions.isVWapMinBreakedDown = isVWapMinBreakedDown; + conditions.isVWapMaxBreakedDown = isVWapMaxBreakedDown; + conditions.isSarCrossedOverVale = isSarCrossedOverVale; + conditions.isStrCrossedOverVale = isStrCrossedOverVale; + conditions.isBreakedDownPrevStr = isBreakedDownPrevStr; + conditions.isBreakedDownPrevSar = isBreakedDownPrevSar; + conditions.isX3MaFatsOverMidPrev = isX3MaFatsOverMidPrev; + conditions.isSarCrossedUnderPeak = isSarCrossedUnderPeak; + conditions.isStrCrossedUnderPeak = isStrCrossedUnderPeak; + conditions.isNewPeakOverAtrUpper = isNewPeakOverAtrUpper; + conditions.isBreakedUpPrevCheLE1 = isBreakedUpPrevCheLE1; + conditions.isBreakedUpPrevCheLE2 = isBreakedUpPrevCheLE2; + conditions.isBreakedUpPrevCheSE1 = isBreakedUpPrevCheSE1; + conditions.isBreakedUpPrevCheSE2 = isBreakedUpPrevCheSE2; + conditions.isBreakedUpPrevCheMin = isBreakedUpPrevCheMin; + conditions.isBreakedUpPrevCheMax = isBreakedUpPrevCheMax; + conditions.isX3MaFatsUnderMidPrev = isX3MaFatsUnderMidPrev; + conditions.isX3MaFatsOverSlowPrev = isX3MaFatsOverSlowPrev; + conditions.isAtrUpperEqualsToPeak = isAtrUpperEqualsToPeak; + conditions.isAtrLowerEqualsToVale = isAtrLowerEqualsToVale; + conditions.isNewValeUnderAtrLower = isNewValeUnderAtrLower; + conditions.isStrUpperOverAtrUpper = isStrUpperOverAtrUpper; + conditions.isStrLowerOverAtrLower = isStrLowerOverAtrLower; + conditions.isX3MaFatsUnderSlowPrev = isX3MaFatsUnderSlowPrev; + conditions.isBreakedDownPrevCheMin = isBreakedDownPrevCheMin; + conditions.isBreakedDownPrevCheMax = isBreakedDownPrevCheMax; + conditions.isBreakedDownPrevCheLE1 = isBreakedDownPrevCheLE1; + conditions.isBreakedDownPrevCheLE2 = isBreakedDownPrevCheLE2; + conditions.isBreakedDownPrevCheSE1 = isBreakedDownPrevCheSE1; + conditions.isBreakedDownPrevCheSE2 = isBreakedDownPrevCheSE2; + conditions.isStrUpperUnderAtrUpper = isStrUpperUnderAtrUpper; + conditions.isStrLowerUnderAtrLower = isStrLowerUnderAtrLower; + conditions.isBreakedUpPrevAtrUpper = isBreakedUpPrevAtrUpper; + conditions.isBreakedUpPrevAtrLower = isBreakedUpPrevAtrLower; + conditions.isAtrUpperCrossedUpPeak = isAtrUpperCrossedUpPeak; + conditions.isAtrLowerCrossedUpVale = isAtrLowerCrossedUpVale; + conditions.isX3MaFastCrossedOverMid = isX3MaFastCrossedOverMid; + conditions.isVWapFastCrossedOverMid = isVWapFastCrossedOverMid; + conditions.isRejectedUpPrevAtrUpper = isRejectedUpPrevAtrUpper; + conditions.isRejectedUpPrevAtrLower = isRejectedUpPrevAtrLower; + conditions.isX3MaFastCrossedUnderMid = isX3MaFastCrossedUnderMid; + conditions.isX3MaFastCrossedOverSlow = isX3MaFastCrossedOverSlow; + conditions.isAtrUpperCrossedDownPeak = isAtrUpperCrossedDownPeak; + conditions.isAtrLowerCrossedDownVale = isAtrLowerCrossedDownVale; + conditions.isBreakedDownPrevAtrUpper = isBreakedDownPrevAtrUpper; + conditions.isBreakedDownPrevAtrLower = isBreakedDownPrevAtrLower; + conditions.isVWapFastCrossedUnderMid = isVWapFastCrossedUnderMid; + conditions.isDonLowLowerEqualsToVale = isDonLowLowerEqualsToVale; + conditions.isStrUpperCrossedOverPeak = isStrUpperCrossedOverPeak; + conditions.isStrLowerCrossedOverVale = isStrLowerCrossedOverVale; + conditions.isStrLowerOverDonLowLower = isStrLowerOverDonLowLower; + conditions.isVWapFastCrossedOverSlow = isVWapFastCrossedOverSlow; + conditions.isX3MaFastCrossedUnderSlow = isX3MaFastCrossedUnderSlow; + conditions.isRejectedDownPrevAtrUpper = isRejectedDownPrevAtrUpper; + conditions.isRejectedDownPrevAtrLower = isRejectedDownPrevAtrLower; + conditions.isVWapFastCrossedUnderSlow = isVWapFastCrossedUnderSlow; + conditions.isStrUpperOverDonHighUpper = isStrUpperOverDonHighUpper; + conditions.isStrLowerUnderDonLowLower = isStrLowerUnderDonLowLower; + conditions.isDonHighUpperEqualsToPeak = isDonHighUpperEqualsToPeak; + conditions.isStrUpperCrossedUnderPeak = isStrUpperCrossedUnderPeak; + conditions.isStrLowerCrossedUnderVale = isStrLowerCrossedUnderVale; + conditions.isStrUpperUnderDonHighUpper = isStrUpperUnderDonHighUpper; + conditions.isStrLowerCrossedOverAtrLower = isStrLowerCrossedOverAtrLower; + conditions.isStrUpperCrossedOverAtrUpper = isStrUpperCrossedOverAtrUpper; + conditions.isStrUpperCrossedUnderAtrUpper = isStrUpperCrossedUnderAtrUpper; + conditions.isStrLowerCrossedUnderAtrLower = isStrLowerCrossedUnderAtrLower; + conditions.isStrLowerCrossedOverDonLowLower = isStrLowerCrossedOverDonLowLower; + conditions.isStrUpperCrossedOverDonHighUpper = isStrUpperCrossedOverDonHighUpper; + conditions.isStrLowerCrossedUnderDonLowLower = isStrLowerCrossedUnderDonLowLower; + conditions.isStrUpperCrossedUnderDonHighUpper = isStrUpperCrossedUnderDonHighUpper; + + // + xpvConditions.Clean(); + xhkConditions.Clean(); + xatrConditions.Clean(); + xstrConditions.Clean(); + xcheConditions.Clean(); + xdonConditions.Clean(); + x3maConditions.Clean(); + xvwapConditions.Clean(); + xtrendConditions.Clean(); + + // + Free(); + + // + return result; + } + + // + protected: + // + + // + private: + // + + // + string mSymbol; // Trading Symbol + ENUM_TIMEFRAMES mPeriod; // Trading Period + + // + // Inputs ... + X121Inputs mInputs; + X121XPVInputs xpvInputs; + X121XHKInputs xhkInputs; + X121XATRInputs xatrInputs; + X121XDONInputs xdonInputs; + X121XSTRInputs xstrInputs; + X121XCHEInputs xcheInputs; + X121X3MAInputs x3maInputs; + X121XVWAPInputs xvwapInputs; + X121XTRENDInputs xtrendInputs; + + // + int mRSIHandler; +}; + +// \ No newline at end of file diff --git a/BKPS/14031218/Helpers/x-saherelm.x121.x3ma.helper.mq5 b/BKPS/14031218/Helpers/x-saherelm.x121.x3ma.helper.mq5 new file mode 100644 index 0000000..8337273 --- /dev/null +++ b/BKPS/14031218/Helpers/x-saherelm.x121.x3ma.helper.mq5 @@ -0,0 +1,1339 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XCX121X3MAHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.x-helper.class.mq5" + +// +// Definitions ... + +// +// Definitions ... +enum ENUM_X121_X3MA_BUFFERS +{ + // + X121_X3MA_FAST_LINE = 0, + X121_X3MA_FAST_STATE_LINE = 6, + X121_X3MA_MID_LINE = 2, + X121_X3MA_MID_STATE_LINE = 7, + X121_X3MA_SLOW_LINE = 4, + X121_X3MA_SLOW_STATE_LINE = 8, +}; + +// +enum ENUM_X3MA_STATES +{ + X3MA_STATE_BULLISH = 1, + X3MA_STATE_BEARISH = 2, + X3MA_STATE_NEUTURAL = 3, +}; + +// +// Input Models ... +struct X121X3MAInputs +{ + // + // Props ... + int x3maFastMALength; // Fast MA Length + int x3maMidMALength; // Mid MA Length + int x3maSlowMALength; // Slow MA Length + ENUM_MA_METHOD x3maMaMethod; // MA Method + ENUM_APPLIED_PRICE x3maMaAppliedTo; // Applied To + + // + int startCalculationForLastBars; // Calculate Last n Bars + + // + bool showX3MaFast; // Show X3Ma Fast + bool showX3MaMid; // Show X3Ma Medium + bool showX3MaSlow; // Show X3Ma Slow + + // + // Constructor(s) ... + X121X3MAInputs() + { + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + x3maFastMALength = 0; + x3maMidMALength = 0; + x3maSlowMALength = 0; + x3maMaMethod = MODE_EMA; + x3maMaAppliedTo = PRICE_CLOSE; + startCalculationForLastBars = 0; + showX3MaFast = false; + showX3MaMid = false; + showX3MaSlow = false; + + // + ZeroMemory(this); + } + + // + // Default ... + void Default() + { + // + x3maFastMALength = 20; + x3maMidMALength = 50; + x3maSlowMALength = 200; + x3maMaMethod = MODE_EMA; + x3maMaAppliedTo = PRICE_CLOSE; + startCalculationForLastBars = 1000; + showX3MaFast = true; + showX3MaMid = true; + showX3MaSlow = true; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + x3maFastMALength > 2 && + x3maMidMALength > x3maFastMALength && + x3maSlowMALength > x3maMidMALength + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(x3maFastMALength, x3maMidMALength); + result = MathMax(result, x3maSlowMALength); + + // + return result; + } +}; + +// +// Conditions ... +struct X121X3MAConditions +{ + // + // Common ... + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + // Buffers ... + double x3maFastBuffer[]; + double x3maMidBuffer[]; + double x3maSlowBuffer[]; + double x3maFastStateBuffer[]; + double x3maMidStateBuffer[]; + double x3maSlowStateBuffer[]; + + // + // Conditions ... + + // + bool isX3MaFastBullish; + bool isX3MaFastBearish; + bool isX3MaFastNeutural; + + // + bool isX3MaMidBullish; + bool isX3MaMidBearish; + bool isX3MaMidNeutural; + + // + bool isX3MaSlowBullish; + bool isX3MaSlowBearish; + bool isX3MaSlowNeutural; + + // + bool isX3MaFastOverMid; + bool isX3MaMidOverSlow; + + // + bool isX3MaFastUnderMid; + bool isX3MaMidUnderSlow; + + // + bool isX3MaBullishState; + bool isX3MaBearishState; + bool isX3MaNeuturalState; + + // + bool isX3MaBullishOrdered; + bool isX3MaBearishOrdered; + + // + bool isX3MaSwitchedToBullishOrdered; + bool isX3MaSwitchedToBearishOrdered; + + // + bool isX3MaSwitchedToBullishState; + bool isX3MaSwitchedToBearishState; + bool isX3MaSwitchedToNeuturalState; + + // + // Constructor ... + X121X3MAConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + // Commons ... + symbol = NULL; + period = NULL; + time = NULL; + + // + // Buffers ... + + // + Clean(x3maFastBuffer); + Clean(x3maMidBuffer); + Clean(x3maSlowBuffer); + Clean(x3maFastStateBuffer); + Clean(x3maMidStateBuffer); + Clean(x3maSlowStateBuffer); + + // + ArraySetAsSeries(x3maFastBuffer, true); + ArraySetAsSeries(x3maMidBuffer, true); + ArraySetAsSeries(x3maSlowBuffer, true); + ArraySetAsSeries(x3maFastStateBuffer, true); + ArraySetAsSeries(x3maMidStateBuffer, true); + ArraySetAsSeries(x3maSlowStateBuffer, true); + + // + // Conditions ... + + // + isX3MaFastBullish = false; + isX3MaFastBearish = false; + isX3MaFastNeutural = false; + + // + isX3MaMidBullish = false; + isX3MaMidBearish = false; + isX3MaMidNeutural = false; + + // + isX3MaSlowBullish = false; + isX3MaSlowBearish = false; + isX3MaSlowNeutural = false; + + // + isX3MaFastOverMid = false; + isX3MaMidOverSlow = false; + + // + isX3MaFastUnderMid = false; + isX3MaMidUnderSlow = false; + + // + isX3MaBullishState = false; + isX3MaBearishState = false; + isX3MaNeuturalState = false; + + // + isX3MaBullishOrdered = false; + isX3MaBearishOrdered = false; + + // + isX3MaSwitchedToBullishOrdered = false; + isX3MaSwitchedToBearishOrdered = false; + + // + isX3MaSwitchedToBullishState = false; + isX3MaSwitchedToBearishState = false; + isX3MaSwitchedToNeuturalState = false; + + // + ZeroMemory(this); + } + + /** + * Generate Conditions Scores ... + * + * @param bullishScore: Double, Directional Scores Reference ... + * @param bearishScore: Double, Directional Scores Reference ... + */ + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + // + bullishScore = 0; + bearishScore = 0; + + // + // 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 // + ); + + // + string conditionsStr = + // + ToString("isX3MaFastBullish", isX3MaFastBullish, ignoreFalseConditions, separator) + + ToString("isX3MaFastBearish", isX3MaFastBearish, ignoreFalseConditions, separator) + + ToString("isX3MaFastNeutural", isX3MaFastNeutural, ignoreFalseConditions, separator) + + ToString("isX3MaMidBullish", isX3MaMidBullish, ignoreFalseConditions, separator) + + ToString("isX3MaMidBearish", isX3MaMidBearish, ignoreFalseConditions, separator) + + ToString("isX3MaMidNeutural", isX3MaMidNeutural, ignoreFalseConditions, separator) + + ToString("isX3MaSlowBullish", isX3MaSlowBullish, ignoreFalseConditions, separator) + + ToString("isX3MaSlowBearish", isX3MaSlowBearish, ignoreFalseConditions, separator) + + ToString("isX3MaSlowNeutural", isX3MaSlowNeutural, ignoreFalseConditions, separator) + + ToString("isX3MaFastOverMid", isX3MaFastOverMid, ignoreFalseConditions, separator) + + ToString("isX3MaMidOverSlow", isX3MaMidOverSlow, ignoreFalseConditions, separator) + + ToString("isX3MaFastUnderMid", isX3MaFastUnderMid, ignoreFalseConditions, separator) + + ToString("isX3MaMidUnderSlow", isX3MaMidUnderSlow, ignoreFalseConditions, separator) + + ToString("isX3MaBullishState", isX3MaBullishState, ignoreFalseConditions, separator) + + ToString("isX3MaBearishState", isX3MaBearishState, ignoreFalseConditions, separator) + + ToString("isX3MaNeuturalState", isX3MaNeuturalState, ignoreFalseConditions, separator) + + ToString("isX3MaBullishOrdered", isX3MaBullishOrdered, ignoreFalseConditions, separator) + + ToString("isX3MaBearishOrdered", isX3MaBearishOrdered, ignoreFalseConditions, separator) + + ToString("isX3MaSwitchedToBullishOrdered", isX3MaSwitchedToBullishOrdered, ignoreFalseConditions, separator) + + ToString("isX3MaSwitchedToBearishOrdered", isX3MaSwitchedToBearishOrdered, ignoreFalseConditions, separator) + + ToString("isX3MaSwitchedToBullishState", isX3MaSwitchedToBullishState, ignoreFalseConditions, separator) + + ToString("isX3MaSwitchedToBearishState", isX3MaSwitchedToBearishState, ignoreFalseConditions, separator) + + ToString("isX3MaSwitchedToNeuturalState", isX3MaSwitchedToNeuturalState, ignoreFalseConditions, separator) + + // + "" + // + ; + + // + result = + // + "[" + GetTag() + "]" + separator + + (onlyConditions + ? "" + : commonStr) + + (!includeScores + ? "" + : scoresStr) + + " " + separator + + (onlyCommons + ? "" + : conditionsStr) + + "" + // + ; + + // + return result; + } + + /** + * Retrieve nique Tag Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + return GetTypeName(this); + } + + // +}; + +// +// Class ... +class XCX121X3MAHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructors ... + XCX121X3MAHelper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCX121X3MAHelper() + { + // + mInputs.Clean(); + + // + Clean(x3maFastBuffer); + Clean(x3maMidBuffer); + Clean(x3maSlowBuffer); + Clean(x3maFastStateBuffer); + Clean(x3maMidStateBuffer); + Clean(x3maSlowStateBuffer); + } + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + X121X3MAInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + ArraySetAsSeries(x3maFastBuffer, true); + ArraySetAsSeries(x3maMidBuffer, true); + ArraySetAsSeries(x3maSlowBuffer, true); + ArraySetAsSeries(x3maFastStateBuffer, true); + ArraySetAsSeries(x3maMidStateBuffer, true); + ArraySetAsSeries(x3maSlowStateBuffer, true); + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.x3ma", + // + // Inputs ... + // + // Market ... + "", + mInputs.x3maFastMALength, + mInputs.x3maMidMALength, + mInputs.x3maSlowMALength, + mInputs.x3maMaMethod, + mInputs.x3maMaAppliedTo, + // + // Presentation ... + "", + // + mInputs.startCalculationForLastBars, + // + mInputs.showX3MaFast, + mInputs.showX3MaMid, + mInputs.showX3MaSlow + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + X121X3MAInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + X121X3MAInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Readers ... + + // + // FAST ... + + // + double GetX3MaFast( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(x3maFastBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return x3maFastBuffer[barIndex]; + } + + // + int CopyX3MaFast( + 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, + x3maFastBuffer, + buffer, + forceClean + // + ); + } + + // + // STATE FAST ... + + // + double GetX3MaFastState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(x3maFastStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return x3maFastStateBuffer[barIndex]; + } + + // + int CopyX3MaFastState( + 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, + x3maFastStateBuffer, + buffer, + forceClean + // + ); + } + + // + // MID ... + + // + double GetX3MaMid( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(x3maMidBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return x3maMidBuffer[barIndex]; + } + + // + int CopyX3MaMid( + 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, + x3maMidBuffer, + buffer, + forceClean + // + ); + } + + // + // STATE MID ... + + // + double GetX3MaMidState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(x3maMidStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return x3maMidStateBuffer[barIndex]; + } + + // + int CopyX3MaMidState( + 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, + x3maMidStateBuffer, + buffer, + forceClean + // + ); + } + + // + // SLOW ... + + // + double GetX3MaSlowBuffer( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(x3maSlowBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return x3maSlowBuffer[barIndex]; + } + + // + int CopyX3MaSlow( + 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, + x3maSlowBuffer, + buffer, + forceClean + // + ); + } + + // + // STATE SLOW ... + + // + double GetX3MaSlowState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(x3maSlowStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return x3maSlowStateBuffer[barIndex]; + } + + // + int CopyX3MaSlowState( + 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, + x3maSlowStateBuffer, + buffer, + forceClean + // + ); + } + + // + // Converts to State ... + ENUM_X3MA_STATES ToX3MAState(double value) + { + // + ENUM_X3MA_STATES result = + value == 1 + ? X3MA_STATE_BULLISH + : value == 2 + ? X3MA_STATE_BEARISH + : X3MA_STATE_NEUTURAL; + + // + return result; + } + + // + bool IsX3MABullish(double value) + { + // + bool result = false; + + // + result = ToX3MAState(value) == X3MA_STATE_BULLISH; + + // + return result; + } + + // + bool IsX3MABearish(double value) + { + // + bool result = false; + + // + result = ToX3MAState(value) == X3MA_STATE_BEARISH; + + // + return result; + } + + // + bool IsX3MANeutural(double value) + { + // + bool result = false; + + // + result = ToX3MAState(value) == X3MA_STATE_NEUTURAL; + + // + return result; + } + + // + void Free() override + { + Cleanup(10); + } + + // + bool GetConditions( + X121X3MAConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = true; + + // + if (loopback < 5) + { + loopback = 5; + } + + // + conditions.Clean(); + + // + conditions.symbol = mSymbol; + conditions.period = mPeriod; + conditions.time = TimeCurrent(); + + // + int zIndex = barIndex; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + XOHCL zBar; + result = zBar.Init( + mSymbol, + mPeriod, + zIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL cBar; + result = cBar.Init( + mSymbol, + mPeriod, + cIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL pBar; + result = pBar.Init( + mSymbol, + mPeriod, + pIndex // + ); + if (!result) + { + return result; + } + + // + // Buffers ... + + // + CopyX3MaFast( + zIndex, + loopback, + conditions.x3maFastBuffer // + ); + + // + CopyX3MaFastState( + zIndex, + loopback, + conditions.x3maFastStateBuffer // + ); + + // + CopyX3MaMid( + zIndex, + loopback, + conditions.x3maMidBuffer // + ); + + // + CopyX3MaMidState( + zIndex, + loopback, + conditions.x3maMidStateBuffer // + ); + + // + CopyX3MaSlow( + zIndex, + loopback, + conditions.x3maSlowBuffer // + ); + + // + CopyX3MaSlowState( + zIndex, + loopback, + conditions.x3maSlowStateBuffer // + ); + + // + // Conditions ... + + // + int cIDX = 1; + int pIDX = cIDX + 1; + + // + // SAR ... + + // + bool isX3MaFastBullish = IsX3MABullish(conditions.x3maFastStateBuffer[cIDX]); + bool isX3MaFastBullishPrev = IsX3MABullish(conditions.x3maFastStateBuffer[pIDX]); + + // + bool isX3MaFastBearish = IsX3MABearish(conditions.x3maFastStateBuffer[cIDX]); + bool isX3MaFastBearishPrev = IsX3MABearish(conditions.x3maFastStateBuffer[pIDX]); + + // + bool isX3MaFastNeutural = IsX3MANeutural(conditions.x3maFastStateBuffer[cIDX]); + bool isX3MaFastNeuturalPrev = IsX3MANeutural(conditions.x3maFastStateBuffer[pIDX]); + + // + bool isX3MaMidBullish = IsX3MABullish(conditions.x3maMidStateBuffer[cIDX]); + bool isX3MaMidBullishPrev = IsX3MABullish(conditions.x3maMidStateBuffer[pIDX]); + + // + bool isX3MaMidBearish = IsX3MABearish(conditions.x3maMidStateBuffer[cIDX]); + bool isX3MaMidBearishPrev = IsX3MABearish(conditions.x3maMidStateBuffer[pIDX]); + + // + bool isX3MaMidNeutural = IsX3MANeutural(conditions.x3maMidStateBuffer[cIDX]); + bool isX3MaMidNeuturalPrev = IsX3MANeutural(conditions.x3maMidStateBuffer[pIDX]); + + // + bool isX3MaSlowBullish = IsX3MABullish(conditions.x3maSlowStateBuffer[cIDX]); + bool isX3MaSlowBullishPrev = IsX3MABullish(conditions.x3maSlowStateBuffer[pIDX]); + + // + bool isX3MaSlowBearish = IsX3MABearish(conditions.x3maSlowStateBuffer[cIDX]); + bool isX3MaSlowBearishPrev = IsX3MABearish(conditions.x3maSlowStateBuffer[pIDX]); + + // + bool isX3MaSlowNeutural = IsX3MANeutural(conditions.x3maSlowStateBuffer[cIDX]); + bool isX3MaSlowNeuturalPrev = IsX3MANeutural(conditions.x3maSlowStateBuffer[pIDX]); + + // + bool isX3MaFastOverMid = conditions.x3maFastBuffer[cIDX] > conditions.x3maMidBuffer[cIDX]; + bool isX3MaFastOverMidPrev = conditions.x3maFastBuffer[pIDX] > conditions.x3maMidBuffer[pIDX]; + + // + bool isX3MaMidOverSlow = conditions.x3maMidBuffer[cIDX] > conditions.x3maSlowBuffer[cIDX]; + bool isX3MaMidOverSlowPrev = conditions.x3maMidBuffer[pIDX] > conditions.x3maSlowBuffer[pIDX]; + + // + bool isX3MaFastUnderMid = conditions.x3maFastBuffer[cIDX] < conditions.x3maMidBuffer[cIDX]; + bool isX3MaFastUnderMidPrev = conditions.x3maFastBuffer[pIDX] < conditions.x3maMidBuffer[pIDX]; + + // + bool isX3MaMidUnderSlow = conditions.x3maMidBuffer[cIDX] < conditions.x3maSlowBuffer[cIDX]; + bool isX3MaMidUnderSlowPrev = conditions.x3maMidBuffer[pIDX] < conditions.x3maSlowBuffer[pIDX]; + + // + bool isX3MaBullishState = isX3MaFastBullish && + isX3MaMidBullish && + isX3MaSlowBullish; + bool isX3MaBullishStatePrev = isX3MaFastBullishPrev && + isX3MaMidBullishPrev && + isX3MaSlowBullishPrev; + + // + bool isX3MaBearishState = isX3MaFastBearish && + isX3MaMidBearish && + isX3MaSlowBearish; + bool isX3MaBearishStatePrev = isX3MaFastBearishPrev && + isX3MaMidBearishPrev && + isX3MaSlowBearishPrev; + + // + bool isX3MaNeuturalState = isX3MaFastNeutural && + isX3MaMidNeutural && + isX3MaSlowNeutural; + bool isX3MaNeuturalStatePrev = isX3MaFastNeuturalPrev && + isX3MaMidNeuturalPrev && + isX3MaSlowNeuturalPrev; + + // + bool isX3MaBullishOrdered = isX3MaFastOverMid && + isX3MaMidOverSlow; + bool isX3MaBullishOrderedPrev = isX3MaFastOverMidPrev && + isX3MaMidOverSlowPrev; + + // + bool isX3MaBearishOrdered = isX3MaFastUnderMid && + isX3MaMidUnderSlow; + bool isX3MaBearishOrderedPrev = isX3MaFastUnderMidPrev && + isX3MaMidUnderSlowPrev; + + // + bool isX3MaSwitchedToBullishOrdered = isX3MaBullishOrdered && + !isX3MaBullishOrderedPrev; + bool isX3MaSwitchedToBearishOrdered = isX3MaBearishOrdered && + !isX3MaBearishOrderedPrev; + + // + bool isX3MaSwitchedToBullishState = isX3MaBullishState && + !isX3MaBullishStatePrev; + bool isX3MaSwitchedToBearishState = isX3MaBearishState && + !isX3MaBearishStatePrev; + bool isX3MaSwitchedToNeuturalState = isX3MaNeuturalState && + !isX3MaNeuturalStatePrev; + + // + conditions.isX3MaFastBullish = isX3MaFastBullish; + conditions.isX3MaFastBearish = isX3MaFastBearish; + conditions.isX3MaFastNeutural = isX3MaFastNeutural; + conditions.isX3MaMidBullish = isX3MaMidBullish; + conditions.isX3MaMidBearish = isX3MaMidBearish; + conditions.isX3MaMidNeutural = isX3MaMidNeutural; + conditions.isX3MaSlowBullish = isX3MaSlowBullish; + conditions.isX3MaSlowBearish = isX3MaSlowBearish; + conditions.isX3MaSlowNeutural = isX3MaSlowNeutural; + conditions.isX3MaFastOverMid = isX3MaFastOverMid; + conditions.isX3MaMidOverSlow = isX3MaMidOverSlow; + conditions.isX3MaFastUnderMid = isX3MaFastUnderMid; + conditions.isX3MaMidUnderSlow = isX3MaMidUnderSlow; + conditions.isX3MaBullishState = isX3MaBullishState; + conditions.isX3MaBearishState = isX3MaBearishState; + conditions.isX3MaNeuturalState = isX3MaNeuturalState; + conditions.isX3MaBullishOrdered = isX3MaBullishOrdered; + conditions.isX3MaBearishOrdered = isX3MaBearishOrdered; + conditions.isX3MaSwitchedToBullishOrdered = isX3MaSwitchedToBullishOrdered; + conditions.isX3MaSwitchedToBearishOrdered = isX3MaSwitchedToBearishOrdered; + conditions.isX3MaSwitchedToBullishState = isX3MaSwitchedToBullishState; + conditions.isX3MaSwitchedToBearishState = isX3MaSwitchedToBearishState; + conditions.isX3MaSwitchedToNeuturalState = isX3MaSwitchedToNeuturalState; + + // + Cleanup(); + + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + + // + return result; + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + X121X3MAInputs mInputs; // Inputs ... + + // + // Buffers ... + double x3maFastBuffer[]; + double x3maMidBuffer[]; + double x3maSlowBuffer[]; + double x3maFastStateBuffer[]; + double x3maMidStateBuffer[]; + double x3maSlowStateBuffer[]; + + // + void Calculate( + int maxRequiredBars = 100 // + ) + { + // + // Buffers ... + + // + // FAST ... + CopyBuffer( + mHandler, + X121_X3MA_FAST_LINE, + 0, + maxRequiredBars, + x3maFastBuffer + // + ); + + // + // FAST STATE ... + CopyBuffer( + mHandler, + X121_X3MA_FAST_STATE_LINE, + 0, + maxRequiredBars, + x3maFastStateBuffer + // + ); + + // + // MID ... + CopyBuffer( + mHandler, + X121_X3MA_MID_LINE, + 0, + maxRequiredBars, + x3maMidBuffer + // + ); + + // + // MID STATE ... + CopyBuffer( + mHandler, + X121_X3MA_MID_STATE_LINE, + 0, + maxRequiredBars, + x3maMidStateBuffer + // + ); + + // + // SLOW ... + CopyBuffer( + mHandler, + X121_X3MA_SLOW_LINE, + 0, + maxRequiredBars, + x3maSlowBuffer + // + ); + + // + // SLOW STATE ... + CopyBuffer( + mHandler, + X121_X3MA_SLOW_STATE_LINE, + 0, + maxRequiredBars, + x3maSlowStateBuffer + // + ); + } + + // + void Cleanup( + int maxAllowed = 100 // + ) + { + // + CleanupArray( + x3maFastBuffer, + maxAllowed // + ); + + // + CleanupArray( + x3maMidBuffer, + maxAllowed // + ); + + // + CleanupArray( + x3maSlowBuffer, + maxAllowed // + ); + + // + CleanupArray( + x3maFastStateBuffer, + maxAllowed // + ); + + // + CleanupArray( + x3maMidStateBuffer, + maxAllowed // + ); + + // + CleanupArray( + x3maSlowStateBuffer, + maxAllowed // + ); + + // + } + + // +}; + +// +// Tools ... \ No newline at end of file diff --git a/BKPS/14031218/Helpers/x-saherelm.x121.xatr.helper.mq5 b/BKPS/14031218/Helpers/x-saherelm.x121.xatr.helper.mq5 new file mode 100644 index 0000000..2c7b5c4 --- /dev/null +++ b/BKPS/14031218/Helpers/x-saherelm.x121.xatr.helper.mq5 @@ -0,0 +1,1273 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XCX121XATRHelper +// 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 ... + +// +// Definitions ... +enum ENUM_X121_XATR_BUFFERS +{ + // + X121_ATR_UPPER_LINE = 0, + X121_ATR_LOWER_LINE = 1, + X121_ATR_LINE = 2, + X121_ATR_UPPER_RAW_LINE = 3, + X121_ATR_LOWER_RAW_LINE = 4, + X121_RSI_LINE = 5, +}; + +// +// Input Models ... +struct X121XATRInputs +{ + // + // Props ... + + // + // RSI ... + int rsiLength; // Length + double rsiOverSoldLevel; // Over Sold Level + double rsiOverBoughtLevel; // Over Bought Level + ENUM_APPLIED_PRICE rsiAppliedTo; // Applied To + + // + // ATR Detection ... + int atrLength; // Length + double atrMultiplier; // Multiplier + ENUM_APPLIED_PRICE atrUpperAppliedTo; // Upper Zone Applied To + ENUM_APPLIED_PRICE atrLowerAppliedTo; // Lower Zone Applied To + ENUM_X_MA_METHOD atrSmoothingMode; // Smoothing Method + + // + int startCalculationForLastBars; // Calculate Last n Bars + + // + bool showATRUpper; // Show Upper Zone + bool showATRLower; // Show Lower Zone + + // + // Constructor(s) ... + X121XATRInputs() + { + // + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + // RSI ... + rsiLength = 0; + rsiOverSoldLevel = 0; + rsiOverBoughtLevel = 0; + rsiAppliedTo = PRICE_CLOSE; + + // + // ATR ... + atrLength = 0; // Length + atrMultiplier = 0; // Multiplier + atrUpperAppliedTo = PRICE_HIGH; // Upper Zone Applied To + atrLowerAppliedTo = PRICE_LOW; // Lower Zone Applied To + atrSmoothingMode = X_MA_MODE_NONE; // Smoothing Method + + // + startCalculationForLastBars = 0; + + // + showATRUpper = false; // Show Upper Zone + showATRLower = false; // Show Lower Zone + + // + ZeroMemory(this); + } + + // + // Default ... + void Default() + { + // + // RSI ... + rsiLength = 14; + rsiOverSoldLevel = 30; + rsiOverBoughtLevel = 70; + rsiAppliedTo = PRICE_CLOSE; + + // + // ATR ... + atrLength = 14; // Length + atrMultiplier = 1; // Multiplier + atrUpperAppliedTo = PRICE_HIGH; // Upper Zone Applied To + atrLowerAppliedTo = PRICE_LOW; // Lower Zone Applied To + atrSmoothingMode = X_MA_MODE_EMA; // Smoothing Method + + // + startCalculationForLastBars = 1500; + showATRUpper = true; // Show Upper Zone + showATRLower = true; // Show Lower Zone + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + atrLength > 0 && + rsiLength > 0 && + atrMultiplier > 0 && + rsiOverSoldLevel > 0 && + rsiOverBoughtLevel > 0 && + startCalculationForLastBars > 0 && + rsiOverSoldLevel < rsiOverBoughtLevel + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(atrLength, rsiLength); + + // + return result; + } +}; + +// +// Conditions ... +struct X121XATRConditions +{ + // + // Common ... + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + // Buffers ... + double atrUpperBuffer[]; + double atrLowerBuffer[]; + double atrUpperRawBuffer[]; + double atrLowerRawBuffer[]; + double rsiBuffer[]; + double atrBuffer[]; + + // + // Conditions ... + + // + // RSI ... + + // + bool isRsiOverBought; + bool isRsiCrossedOverOverBought; + bool isRsiCrossedUnderOverBought; + + // + bool isRsiOverSold; + bool isRsiCrossedUnderOverSold; + bool isRsiCrossedOverOverSold; + + // + // ATR ... + + // + bool isClosedOverAtrUpper; + bool isClosedOverAtrLower; + + // + bool isClosedUnderAtrUpper; + bool isClosedUnderAtrLower; + + // + bool isRejectedUpAtrUpper; + bool isRejectedDownAtrUpper; + + // + bool isRejectedUpAtrLower; + bool isRejectedDownAtrLower; + + // + bool isBreakedUpAtrUpper; + bool isBreakedDownAtrUpper; + + // + bool isBreakedUpAtrLower; + bool isBreakedDownAtrLower; + + // + // bool isCloseLower + + // + // Constructor ... + X121XATRConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + // Commons ... + symbol = NULL; + period = NULL; + time = NULL; + + // + // Buffers ... + + // + Clean(rsiBuffer); + Clean(atrBuffer); + Clean(atrUpperBuffer); + Clean(atrLowerBuffer); + Clean(atrUpperRawBuffer); + Clean(atrLowerRawBuffer); + + // + ArraySetAsSeries(rsiBuffer, true); + ArraySetAsSeries(atrBuffer, true); + ArraySetAsSeries(atrUpperBuffer, true); + ArraySetAsSeries(atrLowerBuffer, true); + ArraySetAsSeries(atrUpperRawBuffer, true); + ArraySetAsSeries(atrLowerRawBuffer, true); + + // + // Conditions ... + + // + // RSI ... + + // + isRsiOverBought = false; + isRsiCrossedOverOverBought = false; + isRsiCrossedUnderOverBought = false; + + // + isRsiOverSold = false; + isRsiCrossedUnderOverSold = false; + isRsiCrossedOverOverSold = false; + + // + // ATR ... + + // + isClosedOverAtrUpper = false; + isClosedOverAtrLower = false; + + // + isClosedUnderAtrUpper = false; + isClosedUnderAtrLower = false; + + // + isRejectedUpAtrUpper = false; + isRejectedDownAtrUpper = false; + + // + isRejectedUpAtrLower = false; + isRejectedDownAtrLower = false; + + // + isBreakedUpAtrUpper = false; + isBreakedDownAtrUpper = false; + + // + isBreakedUpAtrLower = false; + isBreakedDownAtrLower = false; + + // + ZeroMemory(this); + } + + /** + * Generate Conditions Scores ... + * + * @param bullishScore: Double, Directional Scores Reference ... + * @param bearishScore: Double, Directional Scores Reference ... + */ + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + // + bullishScore = 0; + bearishScore = 0; + + // + // 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 // + ); + + // + string conditionsStr = + // + // RSI ... + ToString("isRsiOverBought", isRsiOverBought, ignoreFalseConditions, separator) + + ToString("isRsiCrossedOverOverBought", isRsiCrossedOverOverBought, ignoreFalseConditions, separator) + + ToString("isRsiCrossedUnderOverBought", isRsiCrossedUnderOverBought, ignoreFalseConditions, separator) + + ToString("isRsiOverSold", isRsiOverSold, ignoreFalseConditions, separator) + + ToString("isRsiCrossedUnderOverSold", isRsiCrossedUnderOverSold, ignoreFalseConditions, separator) + + ToString("isRsiCrossedOverOverSold", isRsiCrossedOverOverSold, ignoreFalseConditions, separator) + + // + // ATR ... + ToString("isClosedOverAtrUpper", isClosedOverAtrUpper, ignoreFalseConditions, separator) + + ToString("isClosedOverAtrLower", isClosedOverAtrLower, ignoreFalseConditions, separator) + + ToString("isClosedUnderAtrUpper", isClosedUnderAtrUpper, ignoreFalseConditions, separator) + + ToString("isClosedUnderAtrLower", isClosedUnderAtrLower, ignoreFalseConditions, separator) + + ToString("isRejectedUpAtrUpper", isRejectedUpAtrUpper, ignoreFalseConditions, separator) + + ToString("isRejectedDownAtrUpper", isRejectedDownAtrUpper, ignoreFalseConditions, separator) + + ToString("isRejectedUpAtrLower", isRejectedUpAtrLower, ignoreFalseConditions, separator) + + ToString("isRejectedDownAtrLower", isRejectedDownAtrLower, ignoreFalseConditions, separator) + + ToString("isBreakedUpAtrUpper", isBreakedUpAtrUpper, ignoreFalseConditions, separator) + + ToString("isBreakedDownAtrUpper", isBreakedDownAtrUpper, ignoreFalseConditions, separator) + + ToString("isBreakedUpAtrLower", isBreakedUpAtrLower, ignoreFalseConditions, separator) + + ToString("isBreakedDownAtrLower", isBreakedDownAtrLower, ignoreFalseConditions, separator) + + // + "" + // + ; + + // + result = + // + "[" + GetTag() + "]" + separator + + (onlyConditions + ? "" + : commonStr) + + (!includeScores + ? "" + : scoresStr) + + " " + separator + + (onlyCommons + ? "" + : conditionsStr) + + "" + // + ; + + // + return result; + } + + /** + * Retrieve nique Tag Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + return GetTypeName(this); + } + + // +}; + +// +// Class ... +class XCX121XATRHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructors ... + XCX121XATRHelper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCX121XATRHelper() + { + // + Clean(rsiBuffer); + Clean(atrUpperBuffer); + Clean(atrLowerBuffer); + Clean(atrBuffer); + Clean(atrUpperRawBuffer); + Clean(atrLowerRawBuffer); + + // + mInputs.Clean(); + } + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + X121XATRInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + ArraySetAsSeries(rsiBuffer, true); + ArraySetAsSeries(atrUpperBuffer, true); + ArraySetAsSeries(atrLowerBuffer, true); + ArraySetAsSeries(atrBuffer, true); + ArraySetAsSeries(atrUpperRawBuffer, true); + ArraySetAsSeries(atrLowerRawBuffer, true); + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.xatr", + // + // Inputs ... + // + // Market ... + "", + // + // RSI Detection ... + "", + mInputs.rsiLength, + mInputs.rsiAppliedTo, + // + // ATR Detection ... + "", + mInputs.atrLength, + mInputs.atrMultiplier, + mInputs.atrUpperAppliedTo, + mInputs.atrLowerAppliedTo, + mInputs.atrSmoothingMode, + // + // Presentation ... + "", + mInputs.startCalculationForLastBars, + mInputs.showATRUpper, + mInputs.showATRLower + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + X121XATRInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + X121XATRInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Readers ... + + // + // RSI ... + + // + double GetRSI( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(rsiBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return rsiBuffer[barIndex]; + } + + // + int CopyRSI( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + rsiBuffer, + buffer, + forceClean + // + ); + } + + // + // ATR ... + + // + double GetATR( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(atrBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return atrBuffer[barIndex]; + } + + // + int CopyATR( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + atrBuffer, + buffer, + forceClean + // + ); + } + + // + double GetATRUpper( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(atrUpperBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return atrUpperBuffer[barIndex]; + } + + // + int CopyATRUpper( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + atrUpperBuffer, + buffer, + forceClean + // + ); + } + + // + double GetATRUpperRaw( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(atrUpperRawBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return atrUpperRawBuffer[barIndex]; + } + + // + int CopyATRUpperRaw( + 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, + atrUpperRawBuffer, + buffer, + forceClean + // + ); + } + + // + double GetATRLower( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(atrLowerBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return atrLowerBuffer[barIndex]; + } + + // + int CopyATRLower( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + atrLowerBuffer, + buffer, + forceClean + // + ); + } + + // + double GetATRLowerRaw( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(atrLowerRawBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return atrLowerRawBuffer[barIndex]; + } + + // + int CopyATRLowerRaw( + 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, + atrLowerRawBuffer, + buffer, + forceClean + // + ); + } + + // + void Free() override + { + Cleanup(10); + } + + // + bool GetConditions( + X121XATRConditions &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 ... + + // + CopyRSI( + zIndex, + loopback, + conditions.rsiBuffer // + ); + + // + CopyATR( + zIndex, + loopback, + conditions.atrBuffer // + ); + + // + CopyATRUpper( + zIndex, + loopback, + conditions.atrUpperBuffer // + ); + + // + CopyATRUpperRaw( + zIndex, + loopback, + conditions.atrUpperRawBuffer // + ); + + // + CopyATRLower( + zIndex, + loopback, + conditions.atrLowerBuffer // + ); + + // + CopyATRLowerRaw( + zIndex, + loopback, + conditions.atrLowerRawBuffer // + ); + + // + // Conditions ... + + // + int cIDX = 1; + int pIDX = cIDX + 1; + + // + // RSI ... + + // + bool isRsiOverBought = conditions.rsiBuffer[cIDX] > mInputs.rsiOverBoughtLevel; + bool isRsiOverBoughtPrev = conditions.rsiBuffer[pIDX] > mInputs.rsiOverBoughtLevel; + + // + bool isRsiCrossedOverOverBought = isRsiOverBought && + !isRsiOverBoughtPrev; + bool isRsiCrossedUnderOverBought = !isRsiOverBought && + isRsiOverBoughtPrev; + + // + bool isRsiOverSold = conditions.rsiBuffer[cIDX] < mInputs.rsiOverSoldLevel; + bool isRsiOverSoldPrev = conditions.rsiBuffer[pIDX] < mInputs.rsiOverSoldLevel; + + // + bool isRsiCrossedUnderOverSold = isRsiOverSold && + !isRsiOverSoldPrev; + bool isRsiCrossedOverOverSold = !isRsiOverSold && + isRsiOverSoldPrev; + + // + // ATR ... + + // + bool isClosedOverAtrUpper = cBar.close > conditions.atrUpperBuffer[cIDX]; + bool isClosedOverAtrLower = cBar.close > conditions.atrLowerBuffer[cIDX]; + + // + bool isClosedUnderAtrUpper = cBar.close < conditions.atrUpperBuffer[cIDX]; + bool isClosedUnderAtrLower = cBar.close < conditions.atrLowerBuffer[cIDX]; + + // + bool isRejectedUpAtrUpper = IsBarReject( + atrUpperBuffer[cIDX], + X_DIRECTION_BULLISH, + cBar // + ); + bool isRejectedDownAtrUpper = IsBarReject( + atrUpperBuffer[cIDX], + X_DIRECTION_BEARISH, + cBar // + ); + + // + bool isRejectedUpAtrLower = IsBarReject( + atrLowerBuffer[cIDX], + X_DIRECTION_BULLISH, + cBar // + ); + ; + bool isRejectedDownAtrLower = IsBarReject( + atrLowerBuffer[cIDX], + X_DIRECTION_BEARISH, + cBar // + ); + ; + + // + bool isBreakedUpAtrUpper = IsBarBreak( + atrUpperBuffer[cIDX], + X_DIRECTION_BULLISH, + cBar // + ); + bool isBreakedDownAtrUpper = IsBarBreak( + atrUpperBuffer[cIDX], + X_DIRECTION_BEARISH, + cBar // + ); + + // + bool isBreakedUpAtrLower = IsBarBreak( + atrLowerBuffer[cIDX], + X_DIRECTION_BULLISH, + cBar // + ); + bool isBreakedDownAtrLower = IsBarBreak( + atrLowerBuffer[cIDX], + X_DIRECTION_BEARISH, + cBar // + ); + + // + conditions.isRsiOverSold = isRsiOverSold; + conditions.isRsiOverBought = isRsiOverBought; + conditions.isRejectedUpAtrUpper = isRejectedUpAtrUpper; + conditions.isRejectedUpAtrLower = isRejectedUpAtrLower; + conditions.isBreakedUpAtrUpper = isBreakedUpAtrUpper; + conditions.isBreakedUpAtrLower = isBreakedUpAtrLower; + conditions.isRejectedDownAtrUpper = isRejectedDownAtrUpper; + conditions.isRejectedDownAtrLower = isRejectedDownAtrLower; + conditions.isClosedOverAtrUpper = isClosedOverAtrUpper; + conditions.isClosedOverAtrLower = isClosedOverAtrLower; + conditions.isBreakedDownAtrUpper = isBreakedDownAtrUpper; + conditions.isBreakedDownAtrLower = isBreakedDownAtrLower; + conditions.isClosedUnderAtrUpper = isClosedUnderAtrUpper; + conditions.isClosedUnderAtrLower = isClosedUnderAtrLower; + conditions.isRsiCrossedOverOverSold = isRsiCrossedOverOverSold; + conditions.isRsiCrossedUnderOverSold = isRsiCrossedUnderOverSold; + conditions.isRsiCrossedOverOverBought = isRsiCrossedOverOverBought; + conditions.isRsiCrossedUnderOverBought = isRsiCrossedUnderOverBought; + + // + Cleanup(); + + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + + // + return result; + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + X121XATRInputs mInputs; // Inputs ... + + // + // Buffers ... + double rsiBuffer[]; + double atrUpperBuffer[]; + double atrLowerBuffer[]; + double atrBuffer[]; + double atrUpperRawBuffer[]; + double atrLowerRawBuffer[]; + + // + void Calculate( + int maxRequiredBars = 100 // + ) + { + // + // Buffers ... + + // + // RSI ... + CopyBuffer( + mHandler, + X121_RSI_LINE, + 0, + maxRequiredBars, + rsiBuffer + // + ); + + // + // ATR ... + + // + CopyBuffer( + mHandler, + X121_ATR_UPPER_LINE, + 0, + maxRequiredBars, + atrUpperBuffer + // + ); + + // + CopyBuffer( + mHandler, + X121_ATR_LOWER_LINE, + 0, + maxRequiredBars, + atrLowerBuffer + // + ); + + // + CopyBuffer( + mHandler, + X121_ATR_LINE, + 0, + maxRequiredBars, + atrBuffer + // + ); + + // + CopyBuffer( + mHandler, + X121_ATR_UPPER_RAW_LINE, + 0, + maxRequiredBars, + atrUpperRawBuffer + // + ); + + // + CopyBuffer( + mHandler, + X121_ATR_LOWER_RAW_LINE, + 0, + maxRequiredBars, + atrLowerRawBuffer + // + ); + } + + // + void Cleanup( + int maxAllowed = 100 // + ) + { + // + CleanupArray( + rsiBuffer, + maxAllowed // + ); + + // + CleanupArray( + atrUpperBuffer, + maxAllowed // + ); + + // + CleanupArray( + atrLowerBuffer, + maxAllowed // + ); + + // + CleanupArray( + atrBuffer, + maxAllowed // + ); + + // + CleanupArray( + atrUpperRawBuffer, + maxAllowed // + ); + + // + CleanupArray( + atrLowerRawBuffer, + maxAllowed // + ); + + // + } + + // +}; + +// +// Tools ... \ No newline at end of file diff --git a/BKPS/14031218/Helpers/x-saherelm.x121.xcc.helper.mq5 b/BKPS/14031218/Helpers/x-saherelm.x121.xcc.helper.mq5 new file mode 100644 index 0000000..bcef12e --- /dev/null +++ b/BKPS/14031218/Helpers/x-saherelm.x121.xcc.helper.mq5 @@ -0,0 +1,252 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCX121XCCHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.x-helper.class.mq5" + +// +// Definitions ... + +// +// Input Models ... +struct X121XCCInputs +{ + // + // Props ... + + // + // Chart Style ... + ENUM_CHART_MODE mode; // Mode + color upColor; // Up Color + color downColor; // Down Color + color lineColor; // Line mode and Doji candlestick Color + color bearishColor; // Bullish Color + color bullishColor; // Bearish Color + color volumesColor; // Volumes Color + + // + // Presentation ... + bool showCandles; // Show Candles + + // + // Constructor(s) ... + X121XCCInputs() + { + // + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + mode = CHART_CANDLES; + + // + upColor = CLR_NONE; + downColor = CLR_NONE; + lineColor = CLR_NONE; + bearishColor = CLR_NONE; + bullishColor = CLR_NONE; + volumesColor = CLR_NONE; + + // + showCandles = false; + + // + ZeroMemory(this); + } + + // + // Default ... + void Default() + { + // + mode = CHART_CANDLES; + + // + upColor = clrLime; + downColor = clrRed; + lineColor = clrLime; + bearishColor = clrRed; + bullishColor = clrLime; + volumesColor = clrGreen; + // + showCandles = true; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + true + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(0, 0); + + // + return result; + } +}; + +// +// Class ... +class XCX121XCCHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructors ... + XCX121XCCHelper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCX121XCCHelper() + { + mInputs.Clean(); + } + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + X121XCCInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.xcc", + // + // Inputs ... + // + // Chart Style ... + "", + mInputs.mode, // Mode + mInputs.upColor, // Up Color + mInputs.downColor, // Down Color + mInputs.lineColor, // Line mode and Doji candlestick Color + mInputs.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 ... + + // + X121XCCInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + X121XCCInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + X121XCCInputs mInputs; // Inputs ... +}; + +// +// Tools ... \ No newline at end of file diff --git a/BKPS/14031218/Helpers/x-saherelm.x121.xche.helper.mq5 b/BKPS/14031218/Helpers/x-saherelm.x121.xche.helper.mq5 new file mode 100644 index 0000000..7f7cecd --- /dev/null +++ b/BKPS/14031218/Helpers/x-saherelm.x121.xche.helper.mq5 @@ -0,0 +1,1387 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XCX121XCHEHelper +// 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 ... + +// +// Definitions ... +enum ENUM_X121_XCHE_BUFFERS +{ + // + X121_XCHE_LE_1_LINE = 0, + X121_XCHE_SE_1_LINE = 1, + X121_XCHE_LE_2_LINE = 2, + X121_XCHE_SE_2_LINE = 3, + X121_XCHE_LE_1_S_LINE = 4, + X121_XCHE_SE_1_S_LINE = 5, + X121_XCHE_LE_2_S_LINE = 6, + X121_XCHE_SE_2_S_LINE = 7, +}; + +// +// Input Models ... +struct X121XCHEInputs +{ + // + // Props ... + + int cheLength; // Length + int cheLoopback; // Loopback + double cheMultiplier1; // 1st Multiplier + double cheMultiplier2; // 2nd Multiplier + ENUM_APPLIED_PRICE cheUpperAppliedTo; // Upper Zone Applied to + ENUM_APPLIED_PRICE cheLowerAppliedTo; // Lower Zone Applied to + + // + int cheArrowCode; // CHE Arrow Code + + // + bool showLE1; // Show 1st Long Exit + bool showSE1; // Show 1st Short Exit + bool showLE2; // Show 2st Long Exit + bool showSE2; // Show 2st Short Exit + + // + // Constructor(s) ... + X121XCHEInputs() + { + // + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + cheLength = 0; + cheLoopback = 0; + cheMultiplier1 = 0; + cheMultiplier2 = 0; + cheUpperAppliedTo = PRICE_HIGH; + cheLowerAppliedTo = PRICE_LOW; + + // + cheArrowCode = 0; + + // + showLE1 = false; + showSE1 = false; + showLE2 = false; + showSE2 = false; + + // + ZeroMemory(this); + } + + // + // Default ... + void Default() + { + // + cheLength = 35; + cheLoopback = 26; + cheMultiplier1 = 3.0; + cheMultiplier2 = 3.5; + cheUpperAppliedTo = PRICE_HIGH; + cheLowerAppliedTo = PRICE_LOW; + + // + cheArrowCode = 159; + + // + showLE1 = true; + showSE1 = true; + showLE2 = true; + showSE2 = true; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = true; + + // + result = + cheLength >= 9 && + cheLoopback >= 0; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(cheLength, cheLoopback); + + // + return result; + } +}; + +// +// Conditions ... +struct X121XCHEConditions +{ + // + // Common ... + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + // Buffers ... + double le1Buffer[]; + double se1Buffer[]; + double le2Buffer[]; + double se2Buffer[]; + double le1StartBuffer[]; + double se1StartBuffer[]; + double le2StartBuffer[]; + double se2StartBuffer[]; + + // + // Conditions ... + + // + bool isChe1Bullish; + bool isChe1Bearish; + + // + bool isChe1SwitchedToBullish; + bool isChe1SwitchedToBearish; + + // + bool isChe2Bullish; + bool isChe2Bearish; + + // + bool isChe2SwitchedToBullish; + bool isChe2SwitchedToBearish; + + // + bool isCheBullish; + bool isCheBearish; + + // + bool isCheSwitchedToBullish; + bool isCheSwitchedToBearish; + + // + bool isClosedOverCheMin; + bool isClosedOverCheMax; + + // + bool isClosedUnderCheMin; + bool isClosedUnderCheMax; + + // + // Constructor ... + X121XCHEConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + // Commons ... + symbol = NULL; + period = NULL; + time = NULL; + + // + // Buffers ... + + // + Clean(le1Buffer); + Clean(se1Buffer); + Clean(le2Buffer); + Clean(se2Buffer); + Clean(le1StartBuffer); + Clean(se1StartBuffer); + Clean(le2StartBuffer); + Clean(se2StartBuffer); + + // + ArraySetAsSeries(le1Buffer, true); + ArraySetAsSeries(se1Buffer, true); + ArraySetAsSeries(le2Buffer, true); + ArraySetAsSeries(se2Buffer, true); + ArraySetAsSeries(le1StartBuffer, true); + ArraySetAsSeries(se1StartBuffer, true); + ArraySetAsSeries(le2StartBuffer, true); + ArraySetAsSeries(se2StartBuffer, true); + + // + // Conditions ... + + // + isChe1Bullish = false; + isChe1Bearish = false; + + // + isChe1SwitchedToBullish = false; + isChe1SwitchedToBearish = false; + + // + isChe2Bullish = false; + isChe2Bearish = false; + + // + isChe2SwitchedToBullish = false; + isChe2SwitchedToBearish = false; + + // + isCheBullish = false; + isCheBearish = false; + + // + isCheSwitchedToBullish = false; + isCheSwitchedToBearish = false; + + // + isClosedOverCheMin = false; + isClosedOverCheMax = false; + + // + isClosedUnderCheMin = false; + isClosedUnderCheMax = false; + + // + ZeroMemory(this); + } + + /** + * Generate Conditions Scores ... + * + * @param bullishScore: Double, Directional Scores Reference ... + * @param bearishScore: Double, Directional Scores Reference ... + */ + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + // + bullishScore = 0; + bearishScore = 0; + + // + // 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 // + ); + + // + string conditionsStr = + // + ToString("isChe1Bullish", isChe1Bullish, ignoreFalseConditions, separator) + + ToString("isChe1Bearish", isChe1Bearish, ignoreFalseConditions, separator) + + ToString("isChe1SwitchedToBullish", isChe1SwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isChe1SwitchedToBearish", isChe1SwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isChe2Bullish", isChe2Bullish, ignoreFalseConditions, separator) + + ToString("isChe2Bearish", isChe2Bearish, ignoreFalseConditions, separator) + + ToString("isChe2SwitchedToBullish", isChe2SwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isChe2SwitchedToBearish", isChe2SwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isCheBullish", isCheBullish, ignoreFalseConditions, separator) + + ToString("isCheBearish", isCheBearish, ignoreFalseConditions, separator) + + ToString("isCheSwitchedToBullish", isCheSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isCheSwitchedToBearish", isCheSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isClosedOverCheMin", isClosedOverCheMin, ignoreFalseConditions, separator) + + ToString("isClosedOverCheMax", isClosedOverCheMax, ignoreFalseConditions, separator) + + ToString("isClosedUnderCheMin", isClosedUnderCheMin, ignoreFalseConditions, separator) + + ToString("isClosedUnderCheMax", isClosedUnderCheMax, ignoreFalseConditions, separator) + + // + "" + // + ; + + // + result = + // + "[" + GetTag() + "]" + separator + + (onlyConditions + ? "" + : commonStr) + + (!includeScores + ? "" + : scoresStr) + + " " + separator + + (onlyCommons + ? "" + : conditionsStr) + + "" + // + ; + + // + return result; + } + + /** + * Retrieve nique Tag Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + return GetTypeName(this); + } + + // +}; + +// +// Class ... +class XCX121XCHEHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructors ... + XCX121XCHEHelper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCX121XCHEHelper() + { + // + mInputs.Clean(); + + // + Clean(le1Buffer); + Clean(se1Buffer); + Clean(le2Buffer); + Clean(se2Buffer); + Clean(le1StartBuffer); + Clean(se1StartBuffer); + Clean(le2StartBuffer); + Clean(se2StartBuffer); + } + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + X121XCHEInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + ArraySetAsSeries(le1Buffer, true); + ArraySetAsSeries(se1Buffer, true); + ArraySetAsSeries(le2Buffer, true); + ArraySetAsSeries(se2Buffer, true); + ArraySetAsSeries(le1StartBuffer, true); + ArraySetAsSeries(se1StartBuffer, true); + ArraySetAsSeries(le2StartBuffer, true); + ArraySetAsSeries(se2StartBuffer, true); + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.xche", + // + // Inputs ... + // + // Market ... + "", + mInputs.cheLength, + mInputs.cheLoopback, + mInputs.cheMultiplier1, + mInputs.cheMultiplier2, + mInputs.cheUpperAppliedTo, + mInputs.cheLowerAppliedTo, + // + // Presentation ... + "", + mInputs.cheArrowCode, + mInputs.showLE1, + mInputs.showSE1, + mInputs.showLE2, + mInputs.showSE2 + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + X121XCHEInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + X121XCHEInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Readers ... + + // + double GetLE1( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(le1Buffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return le1Buffer[barIndex]; + } + + // + int CopyLE1( + 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, + le1Buffer, + buffer, + forceClean + // + ); + } + + // + double GetLE1Start( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(le1StartBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return le1StartBuffer[barIndex]; + } + + // + int CopyLE1Start( + 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, + le1StartBuffer, + buffer, + forceClean + // + ); + } + + // + double GetLE2( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(le2Buffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return le2Buffer[barIndex]; + } + + // + int CopyLE2( + 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, + le2Buffer, + buffer, + forceClean + // + ); + } + + // + double GetLE2Start( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(le2StartBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return le2StartBuffer[barIndex]; + } + + // + int CopyLE2Start( + 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, + le2StartBuffer, + buffer, + forceClean + // + ); + } + + // + double GetSE1( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(se1Buffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return se1Buffer[barIndex]; + } + + // + int CopySE1( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceCsean = true // Force To Csean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + se1Buffer, + buffer, + forceCsean + // + ); + } + + // + double GetSE1Start( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(se1StartBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return se1StartBuffer[barIndex]; + } + + // + int CopySE1Start( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceCsean = true // Force To Csean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + se1StartBuffer, + buffer, + forceCsean + // + ); + } + + // + double GetSE2( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(se2Buffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return se2Buffer[barIndex]; + } + + // + int CopySE2( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceCsean = true // Force To Csean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + se2Buffer, + buffer, + forceCsean + // + ); + } + + // + double GetSE2Start( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(se2StartBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return se2StartBuffer[barIndex]; + } + + // + int CopySE2Start( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceCsean = true // Force To Csean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + se2StartBuffer, + buffer, + forceCsean + // + ); + } + + // + void Free() override + { + Cleanup(10); + } + + // + bool GetConditions( + X121XCHEConditions &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 ... + + // + CopyLE1( + zIndex, + loopback, + conditions.le1Buffer // + ); + + // + CopySE1( + zIndex, + loopback, + conditions.se1Buffer // + ); + + // + CopyLE2( + zIndex, + loopback, + conditions.le2Buffer // + ); + + // + CopySE2( + zIndex, + loopback, + conditions.se2Buffer // + ); + + // + CopyLE1Start( + zIndex, + loopback, + conditions.le1StartBuffer // + ); + + // + CopySE1Start( + zIndex, + loopback, + conditions.se1StartBuffer // + ); + + // + CopyLE2Start( + zIndex, + loopback, + conditions.le2StartBuffer // + ); + + // + CopySE2Start( + zIndex, + loopback, + conditions.se2StartBuffer // + ); + + // + // Conditions ... + + // + int cIDX = 1; + int pIDX = cIDX + 1; + + // + bool isChe1Bullish = le1Buffer[cIDX] != EMPTY_VALUE && + se1Buffer[cIDX] == EMPTY_VALUE; + bool isChe1BullishPrev = le1Buffer[cIDX] != EMPTY_VALUE && + se1Buffer[pIDX] == EMPTY_VALUE; + + // + bool isChe1Bearish = se1Buffer[cIDX] != EMPTY_VALUE && + le1Buffer[cIDX] == EMPTY_VALUE; + bool isChe1BearishPrev = se1Buffer[pIDX] != EMPTY_VALUE && + le1Buffer[pIDX] == EMPTY_VALUE; + + // + bool isChe1SwitchedToBullish = isChe1Bullish && + !isChe1BullishPrev; + bool isChe1SwitchedToBearish = isChe1Bearish && + !isChe1BearishPrev; + + // + bool isChe2Bullish = le2Buffer[cIDX] != EMPTY_VALUE && + se2Buffer[cIDX] == EMPTY_VALUE; + bool isChe2BullishPrev = le2Buffer[pIDX] != EMPTY_VALUE && + se2Buffer[pIDX] == EMPTY_VALUE; + + // + bool isChe2Bearish = se2Buffer[cIDX] != EMPTY_VALUE && + le2Buffer[cIDX] == EMPTY_VALUE; + bool isChe2BearishPrev = se2Buffer[pIDX] != EMPTY_VALUE && + le2Buffer[pIDX] == EMPTY_VALUE; + + // + bool isChe2SwitchedToBullish = isChe2Bullish && + !isChe2BullishPrev; + bool isChe2SwitchedToBearish = isChe2Bearish && + !isChe2BearishPrev; + + // + bool isCheBullish = isChe1Bullish && + isChe2Bullish; + bool isCheBullishPrev = isChe1BullishPrev && + isChe2BullishPrev; + + // + bool isCheBearish = isChe1Bearish && + isChe2Bearish; + bool isCheBearishPrev = isChe1BearishPrev && + isChe2BearishPrev; + + // + bool isCheSwitchedToBullish = isCheBullish && + !isCheBullishPrev; + bool isCheSwitchedToBearish = isCheBearish && + !isCheBearishPrev; + + // + double ches[]; + double prevCheLE1 = le1Buffer[pIDX]; + double prevCheLE2 = le2Buffer[pIDX]; + double prevCheSE1 = se1Buffer[pIDX]; + double prevCheSE2 = se2Buffer[pIDX]; + if (prevCheLE1 != EMPTY_VALUE) + { + // + Add( + prevCheLE1, + ches // + ); + } + if (prevCheLE2 != EMPTY_VALUE) + { + // + Add( + prevCheLE2, + ches // + ); + } + if (prevCheSE1 != EMPTY_VALUE) + { + // + Add( + prevCheSE1, + ches // + ); + } + if (prevCheSE2 != EMPTY_VALUE) + { + // + Add( + prevCheSE2, + ches // + ); + } + + // + double cheMin = GetMin(ches); + double cheMax = GetMax(ches); + + // + bool isClosedOverCheMin = cBar.close > cheMin; + bool isClosedOverCheMax = cBar.close > cheMax; + bool isClosedUnderCheMin = cBar.close < cheMin; + bool isClosedUnderCheMax = cBar.close < cheMax; + + // + conditions.isChe1Bullish = isChe1Bullish; + conditions.isChe1Bearish = isChe1Bearish; + conditions.isChe1SwitchedToBullish = isChe1SwitchedToBullish; + conditions.isChe1SwitchedToBearish = isChe1SwitchedToBearish; + conditions.isChe2Bullish = isChe2Bullish; + conditions.isChe2Bearish = isChe2Bearish; + conditions.isChe2SwitchedToBullish = isChe2SwitchedToBullish; + conditions.isChe2SwitchedToBearish = isChe2SwitchedToBearish; + conditions.isCheBullish = isCheBullish; + conditions.isCheBearish = isCheBearish; + conditions.isCheSwitchedToBullish = isCheSwitchedToBullish; + conditions.isCheSwitchedToBearish = isCheSwitchedToBearish; + conditions.isClosedOverCheMin = isClosedOverCheMin; + conditions.isClosedOverCheMax = isClosedOverCheMax; + conditions.isClosedUnderCheMin = isClosedUnderCheMin; + conditions.isClosedUnderCheMax = isClosedUnderCheMax; + + // + Cleanup(); + + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + + // + return result; + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + X121XCHEInputs mInputs; // Inputs ... + + // + // Buffers ... + double le1Buffer[]; + double se1Buffer[]; + double le2Buffer[]; + double se2Buffer[]; + double le1StartBuffer[]; + double se1StartBuffer[]; + double le2StartBuffer[]; + double se2StartBuffer[]; + + // + void Calculate( + int maxRequiredBars = 100 // + ) + { + // + // Buffers ... + + // + // LE1 Start ... + CopyBuffer( + mHandler, + X121_XCHE_LE_1_S_LINE, + 0, + maxRequiredBars, + le1StartBuffer // + ); + + // + // LE1 ... + CopyBuffer( + mHandler, + X121_XCHE_LE_1_LINE, + 0, + maxRequiredBars, + le1Buffer // + ); + + // + // LE2 Start ... + CopyBuffer( + mHandler, + X121_XCHE_LE_2_S_LINE, + 0, + maxRequiredBars, + le2StartBuffer // + ); + + // + // LE2 ... + CopyBuffer( + mHandler, + X121_XCHE_LE_2_LINE, + 0, + maxRequiredBars, + le2Buffer // + ); + + // + // SE1 Start ... + CopyBuffer( + mHandler, + X121_XCHE_SE_1_S_LINE, + 0, + maxRequiredBars, + se1StartBuffer // + ); + + // + // SE1 ... + CopyBuffer( + mHandler, + X121_XCHE_SE_1_LINE, + 0, + maxRequiredBars, + se1Buffer // + ); + + // + // SE2 Start ... + CopyBuffer( + mHandler, + X121_XCHE_SE_2_S_LINE, + 0, + maxRequiredBars, + se2StartBuffer // + ); + + // + // SE2 ... + CopyBuffer( + mHandler, + X121_XCHE_SE_2_LINE, + 0, + maxRequiredBars, + se2Buffer // + ); + } + + // + void Cleanup( + int maxAllowed = 100 // + ) + { + // + CleanupArray( + le1Buffer, + maxAllowed // + ); + + // + CleanupArray( + se1Buffer, + maxAllowed // + ); + + // + CleanupArray( + le2Buffer, + maxAllowed // + ); + + // + CleanupArray( + se2Buffer, + maxAllowed // + ); + + // + CleanupArray( + le1StartBuffer, + maxAllowed // + ); + + // + CleanupArray( + se1StartBuffer, + maxAllowed // + ); + + // + CleanupArray( + le2StartBuffer, + maxAllowed // + ); + + // + CleanupArray( + se2StartBuffer, + maxAllowed // + ); + + // + } + + // +}; + +// +// Tools ... \ No newline at end of file diff --git a/BKPS/14031218/Helpers/x-saherelm.x121.xct.helper.mq5 b/BKPS/14031218/Helpers/x-saherelm.x121.xct.helper.mq5 new file mode 100644 index 0000000..c444481 --- /dev/null +++ b/BKPS/14031218/Helpers/x-saherelm.x121.xct.helper.mq5 @@ -0,0 +1,234 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XSCX121XCTHelper +// Description: provides all Indicator +// Helper requirements ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.x-helper.class.mq5" + +// +// Definitions ... + +// +// Input Models ... +struct X121XCTInputs +{ + // + // Props ... + + // + string font; // Font + int fontSize; // Font Size; + color clr; // Text Color + ENUM_BASE_CORNER corner; // Text Position + + // + // Presentation ... + bool showCandleTime; // Show Candle Time + + // + // Constructor(s) ... + X121XCTInputs() + { + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + font = NULL; + fontSize = 15; + clr = CLR_NONE; + corner = CORNER_RIGHT_LOWER; + + // + // Presentation ... + showCandleTime = false; + + // + ZeroMemory(this); + } + + // + // Default ... + void Default() + { + // + font = "Arial"; + fontSize = 15; + clr = clrYellow; + corner = CORNER_RIGHT_LOWER; + + // + // Presentation ... + showCandleTime = true; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + true + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(0, 0); + + // + return result; + } +}; + +// +// Class ... +class XCX121XCTHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructors ... + XCX121XCTHelper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCX121XCTHelper() + { + mInputs.Clean(); + } + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + X121XCTInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.xct", + // + // Inputs ... + mInputs.fontSize, // Font Size ... + mInputs.font, // Font ... + mInputs.clr, // Text Color ... + mInputs.corner, // Text Position ... + // + // Presentation ... + "", + mInputs.showCandleTime // Show Candle Time + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + X121XCTInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + X121XCTInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + X121XCTInputs mInputs; // Inputs ... +}; + +// +// Tools ... \ No newline at end of file diff --git a/BKPS/14031218/Helpers/x-saherelm.x121.xdon.helper.mq5 b/BKPS/14031218/Helpers/x-saherelm.x121.xdon.helper.mq5 new file mode 100644 index 0000000..639df23 --- /dev/null +++ b/BKPS/14031218/Helpers/x-saherelm.x121.xdon.helper.mq5 @@ -0,0 +1,1408 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XCX121XDONHelper +// 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 ... + +// +// Definitions ... +enum ENUM_X121_XDON_BUFFERS +{ + // + X121_XDON_OPEN_UPPER_LINE = 0, + X121_XDON_OPEN_LOWER_LINE = 1, + X121_XDON_HIGH_UPPER_LINE = 2, + X121_XDON_HIGH_LOWER_LINE = 3, + X121_XDON_LOW_UPPER_LINE = 4, + X121_XDON_LOW_LOWER_LINE = 5, + X121_XDON_CLOSE_UPPER_LINE = 6, + X121_XDON_CLOSE_LOWER_LINE = 7, +}; + +// +// Input Models ... +struct X121XDONInputs +{ + // + // Props ... + + // + int donchainLength; // Donchain Length + + // + int startCalculationForLastBars; // Calculate Last n Bars + + // + 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(s) ... + X121XDONInputs() + { + // + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + donchainLength = 0; + + // + startCalculationForLastBars = 0; + + // + showUpper = false; + showLower = false; + + // + showOpen = false; + showHigh = false; + showClose = false; + showLow = false; + + // + ZeroMemory(this); + } + + // + // Default ... + void Default() + { + // + donchainLength = 40; + + // + startCalculationForLastBars = 1000; + + // + showUpper = true; + showLower = true; + + // + showOpen = true; + showHigh = true; + showClose = true; + showLow = true; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + donchainLength > 0 + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(1, donchainLength); + + // + return result; + } +}; + +// +// Conditions ... +struct X121XDONConditions +{ + // + // Common ... + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + // Buffers ... + double donOpenUpperBuffer[]; + double donOpenLowerBuffer[]; + double donHighUpperBuffer[]; + double donHighLowerBuffer[]; + double donLowUpperBuffer[]; + double donLowLowerBuffer[]; + double donCloseUpperBuffer[]; + double donCloseLowerBuffer[]; + + // + // Conditions ... + + // + bool isRejectedDonOpenUpper; + bool isRejectedDonHighUpper; + bool isRejectedDonLowUpper; + bool isRejectedDonCloseUpper; + + // + bool isRejectedDonOpenLower; + bool isRejectedDonHighLower; + bool isRejectedDonLowLower; + bool isRejectedDonCloseLower; + + // + bool isBreakedDonOpenUpper; + bool isBreakedDonHighUpper; + bool isBreakedDonLowUpper; + bool isBreakedDonCloseUpper; + + // + bool isBreakedDonOpenLower; + bool isBreakedDonHighLower; + bool isBreakedDonLowLower; + bool isBreakedDonCloseLower; + + // + // Constructor ... + X121XDONConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + // Commons ... + symbol = NULL; + period = NULL; + time = NULL; + + // + // Buffers ... + + // + Clean(donOpenUpperBuffer); + Clean(donOpenLowerBuffer); + Clean(donHighUpperBuffer); + Clean(donHighLowerBuffer); + Clean(donLowUpperBuffer); + Clean(donLowLowerBuffer); + Clean(donCloseUpperBuffer); + Clean(donCloseLowerBuffer); + + // + ArraySetAsSeries(donOpenUpperBuffer, true); + ArraySetAsSeries(donOpenLowerBuffer, true); + ArraySetAsSeries(donHighUpperBuffer, true); + ArraySetAsSeries(donHighLowerBuffer, true); + ArraySetAsSeries(donLowUpperBuffer, true); + ArraySetAsSeries(donLowLowerBuffer, true); + ArraySetAsSeries(donCloseUpperBuffer, true); + ArraySetAsSeries(donCloseLowerBuffer, true); + + // + // Conditions ... + + // + isRejectedDonOpenUpper = false; + isRejectedDonHighUpper = false; + isRejectedDonLowUpper = false; + isRejectedDonCloseUpper = false; + + // + isRejectedDonOpenLower = false; + isRejectedDonHighLower = false; + isRejectedDonLowLower = false; + isRejectedDonCloseLower = false; + + // + isBreakedDonOpenUpper = false; + isBreakedDonHighUpper = false; + isBreakedDonLowUpper = false; + isBreakedDonCloseUpper = false; + + // + isBreakedDonOpenLower = false; + isBreakedDonHighLower = false; + isBreakedDonLowLower = false; + isBreakedDonCloseLower = false; + + // + ZeroMemory(this); + } + + /** + * Generate Conditions Scores ... + * + * @param bullishScore: Double, Directional Scores Reference ... + * @param bearishScore: Double, Directional Scores Reference ... + */ + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + // + bullishScore = 0; + bearishScore = 0; + + // + // 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 // + ); + + // + string conditionsStr = + // + ToString("isRejectedDonOpenUpper", isRejectedDonOpenUpper, ignoreFalseConditions, separator) + + ToString("isRejectedDonHighUpper", isRejectedDonHighUpper, ignoreFalseConditions, separator) + + ToString("isRejectedDonLowUpper", isRejectedDonLowUpper, ignoreFalseConditions, separator) + + ToString("isRejectedDonCloseUpper", isRejectedDonCloseUpper, ignoreFalseConditions, separator) + + // + ToString("isRejectedDonOpenLower", isRejectedDonOpenLower, ignoreFalseConditions, separator) + + ToString("isRejectedDonHighLower", isRejectedDonHighLower, ignoreFalseConditions, separator) + + ToString("isRejectedDonLowLower", isRejectedDonLowLower, ignoreFalseConditions, separator) + + ToString("isRejectedDonCloseLower", isRejectedDonCloseLower, ignoreFalseConditions, separator) + + // + ToString("isBreakedDonOpenUpper", isBreakedDonOpenUpper, ignoreFalseConditions, separator) + + ToString("isBreakedDonHighUpper", isBreakedDonHighUpper, ignoreFalseConditions, separator) + + ToString("isBreakedDonLowUpper", isBreakedDonLowUpper, ignoreFalseConditions, separator) + + ToString("isBreakedDonCloseUpper", isBreakedDonCloseUpper, ignoreFalseConditions, separator) + + // + ToString("isBreakedDonOpenLower", isBreakedDonOpenLower, ignoreFalseConditions, separator) + + ToString("isBreakedDonHighLower", isBreakedDonHighLower, ignoreFalseConditions, separator) + + ToString("isBreakedDonLowLower", isBreakedDonLowLower, ignoreFalseConditions, separator) + + ToString("isBreakedDonCloseLower", isBreakedDonCloseLower, ignoreFalseConditions, separator) + + // + "" + // + ; + + // + result = + // + "[" + GetTag() + "]" + separator + + (onlyConditions + ? "" + : commonStr) + + (!includeScores + ? "" + : scoresStr) + + " " + separator + + (onlyCommons + ? "" + : conditionsStr) + + "" + // + ; + + // + return result; + } + + /** + * Retrieve nique Tag Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + return GetTypeName(this); + } + + // +}; + +// +// Class ... +class XCX121XDONHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructors ... + XCX121XDONHelper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCX121XDONHelper() + { + // + mInputs.Clean(); + + // + Clean(donOpenUpperBuffer); + Clean(donOpenLowerBuffer); + Clean(donHighUpperBuffer); + Clean(donHighLowerBuffer); + Clean(donLowUpperBuffer); + Clean(donLowLowerBuffer); + Clean(donCloseUpperBuffer); + Clean(donCloseLowerBuffer); + } + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + X121XDONInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + ArraySetAsSeries(donOpenUpperBuffer, true); + ArraySetAsSeries(donOpenLowerBuffer, true); + ArraySetAsSeries(donHighUpperBuffer, true); + ArraySetAsSeries(donHighLowerBuffer, true); + ArraySetAsSeries(donLowUpperBuffer, true); + ArraySetAsSeries(donLowLowerBuffer, true); + ArraySetAsSeries(donCloseUpperBuffer, true); + ArraySetAsSeries(donCloseLowerBuffer, true); + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.xdon", + // + // Inputs ... + // + // Market ... + "", + mInputs.donchainLength, + // + // Presentation ... + "", + mInputs.startCalculationForLastBars, + // + mInputs.showUpper, + mInputs.showLower, + // + mInputs.showOpen, + mInputs.showHigh, + mInputs.showClose, + mInputs.showLow + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + X121XDONInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + X121XDONInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Readers ... + + // + // 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 + // + ); + } + + // + void Free() override + { + Cleanup(10); + } + + // + bool GetConditions( + X121XDONConditions &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 ... + + // + 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 // + ); + + // + // Conditions ... + + // + int cIDX = 1; + int pIDX = cIDX + 1; + + // + bool isRejectedDonOpenUpper = IsBarReject( + donOpenUpperBuffer[cIDX], + X_DIRECTION_BEARISH, + cBar // + ); + bool isRejectedDonHighUpper = IsBarReject( + donHighUpperBuffer[cIDX], + X_DIRECTION_BEARISH, + cBar // + ); + bool isRejectedDonLowUpper = IsBarReject( + donLowUpperBuffer[cIDX], + X_DIRECTION_BEARISH, + cBar // + ); + bool isRejectedDonCloseUpper = IsBarReject( + donCloseUpperBuffer[cIDX], + X_DIRECTION_BEARISH, + cBar // + ); + + // + bool isRejectedDonOpenLower = IsBarReject( + donOpenLowerBuffer[cIDX], + X_DIRECTION_BULLISH, + cBar // + ); + bool isRejectedDonHighLower = IsBarReject( + donHighLowerBuffer[cIDX], + X_DIRECTION_BULLISH, + cBar // + ); + bool isRejectedDonLowLower = IsBarReject( + donLowLowerBuffer[cIDX], + X_DIRECTION_BULLISH, + cBar // + ); + bool isRejectedDonCloseLower = IsBarReject( + donCloseLowerBuffer[cIDX], + X_DIRECTION_BULLISH, + cBar // + ); + + // + bool isBreakedDonOpenUpper = IsBarBreak( + donOpenUpperBuffer[cIDX], + X_DIRECTION_BEARISH, + cBar // + ); + bool isBreakedDonHighUpper = IsBarBreak( + donHighUpperBuffer[cIDX], + X_DIRECTION_BEARISH, + cBar // + ); + bool isBreakedDonLowUpper = IsBarBreak( + donLowUpperBuffer[cIDX], + X_DIRECTION_BEARISH, + cBar // + ); + bool isBreakedDonCloseUpper = IsBarBreak( + donCloseUpperBuffer[cIDX], + X_DIRECTION_BEARISH, + cBar // + ); + + // + bool isBreakedDonOpenLower = IsBarBreak( + donOpenLowerBuffer[cIDX], + X_DIRECTION_BULLISH, + cBar // + ); + bool isBreakedDonHighLower = IsBarBreak( + donHighLowerBuffer[cIDX], + X_DIRECTION_BULLISH, + cBar // + ); + bool isBreakedDonLowLower = IsBarBreak( + donLowLowerBuffer[cIDX], + X_DIRECTION_BULLISH, + cBar // + ); + bool isBreakedDonCloseLower = IsBarBreak( + donCloseLowerBuffer[cIDX], + X_DIRECTION_BULLISH, + cBar // + ); + + // + conditions.isBreakedDonLowUpper = isBreakedDonLowUpper; + conditions.isBreakedDonLowLower = isBreakedDonLowLower; + conditions.isRejectedDonLowUpper = isRejectedDonLowUpper; + conditions.isRejectedDonLowLower = isRejectedDonLowLower; + conditions.isBreakedDonOpenUpper = isBreakedDonOpenUpper; + conditions.isBreakedDonHighUpper = isBreakedDonHighUpper; + conditions.isBreakedDonOpenLower = isBreakedDonOpenLower; + conditions.isBreakedDonHighLower = isBreakedDonHighLower; + conditions.isRejectedDonOpenUpper = isRejectedDonOpenUpper; + conditions.isRejectedDonOpenLower = isRejectedDonOpenLower; + conditions.isRejectedDonHighUpper = isRejectedDonHighUpper; + conditions.isRejectedDonHighLower = isRejectedDonHighLower; + conditions.isBreakedDonCloseUpper = isBreakedDonCloseUpper; + conditions.isBreakedDonCloseLower = isBreakedDonCloseLower; + conditions.isRejectedDonCloseUpper = isRejectedDonCloseUpper; + conditions.isRejectedDonCloseLower = isRejectedDonCloseLower; + + // + Cleanup(); + + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + + // + return result; + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + X121XDONInputs mInputs; // Inputs ... + + // + // Buffers ... + double donOpenUpperBuffer[]; + double donOpenLowerBuffer[]; + double donHighUpperBuffer[]; + double donHighLowerBuffer[]; + double donLowUpperBuffer[]; + double donLowLowerBuffer[]; + double donCloseUpperBuffer[]; + double donCloseLowerBuffer[]; + + // + void Calculate( + int maxRequiredBars = 100 // + ) + { + // + // Upper ... + CopyBuffer( + mHandler, + X121_XDON_OPEN_UPPER_LINE, + 0, + maxRequiredBars, + donOpenUpperBuffer + // + ); + + // + // Lower ... + CopyBuffer( + mHandler, + X121_XDON_OPEN_LOWER_LINE, + 0, + maxRequiredBars, + donOpenLowerBuffer + // + ); + + // + // CLOSE ... + + // + // Upper ... + CopyBuffer( + mHandler, + X121_XDON_CLOSE_UPPER_LINE, + 0, + maxRequiredBars, + donCloseUpperBuffer + // + ); + + // + // Lower ... + CopyBuffer( + mHandler, + X121_XDON_CLOSE_LOWER_LINE, + 0, + maxRequiredBars, + donCloseLowerBuffer + // + ); + + // + // HIGH ... + + // + // Upper ... + CopyBuffer( + mHandler, + X121_XDON_HIGH_UPPER_LINE, + 0, + maxRequiredBars, + donHighUpperBuffer + // + ); + + // + // Lower ... + CopyBuffer( + mHandler, + X121_XDON_HIGH_LOWER_LINE, + 0, + maxRequiredBars, + donHighLowerBuffer + // + ); + + // + // LOW ... + + // + // Upper ... + CopyBuffer( + mHandler, + X121_XDON_LOW_UPPER_LINE, + 0, + maxRequiredBars, + donLowUpperBuffer + // + ); + + // + // Lower ... + CopyBuffer( + mHandler, + X121_XDON_LOW_LOWER_LINE, + 0, + maxRequiredBars, + donLowLowerBuffer + // + ); + } + + // + void Cleanup( + int maxAllowed = 100 // + ) + { + // + CleanupArray( + donOpenUpperBuffer, + maxAllowed // + ); + + // + CleanupArray( + donOpenLowerBuffer, + maxAllowed // + ); + + // + CleanupArray( + donHighUpperBuffer, + maxAllowed // + ); + + // + CleanupArray( + donHighLowerBuffer, + maxAllowed // + ); + + // + CleanupArray( + donLowUpperBuffer, + maxAllowed // + ); + + // + CleanupArray( + donLowLowerBuffer, + maxAllowed // + ); + + // + CleanupArray( + donCloseUpperBuffer, + maxAllowed // + ); + + // + CleanupArray( + donCloseLowerBuffer, + maxAllowed // + ); + + // + } + + // +}; + +// +// Tools ... \ No newline at end of file diff --git a/BKPS/14031218/Helpers/x-saherelm.x121.xhk.helper.mq5 b/BKPS/14031218/Helpers/x-saherelm.x121.xhk.helper.mq5 new file mode 100644 index 0000000..0a4e89a --- /dev/null +++ b/BKPS/14031218/Helpers/x-saherelm.x121.xhk.helper.mq5 @@ -0,0 +1,1524 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XCX121XHKHelper +// 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 ... + +// +// Definitions ... +enum ENUM_X121_XHK_BUFFERS +{ + // + X121_XHK_RAW_OPEN_LINE = 0, + X121_XHK_RAW_HIGH_LINE = 1, + X121_XHK_RAW_LOW_LINE = 2, + X121_XHK_RAW_CLOSE_LINE = 3, + // + X121_XHK_SM_OPEN_LINE = 5, + X121_XHK_SM_HIGH_LINE = 6, + X121_XHK_SM_LOW_LINE = 7, + X121_XHK_SM_CLOSE_LINE = 8, +}; + +// +// Input Models ... +struct X121XHKInputs +{ + // + // Props ... + int xhkSmoothingLength; // Length + ENUM_X_MA_METHOD xhkSmoothingMode; // Smoothing Method + bool xhkIgnoreSmoothingShadows; // Ignore Smoothed Bar Shadows + int startCalculationForLastBars; // Calculate Last n Bars + bool drawRawXHKCandles; // Draw Raw Candle + bool drawSmoothedXHKCandles; // Draw Smoothed Candle + + // + // Constructor(s) ... + X121XHKInputs() + { + // + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + xhkSmoothingLength = 0; + xhkSmoothingMode = X_MA_MODE_NONE; + xhkIgnoreSmoothingShadows = false; + startCalculationForLastBars = 1500; + drawRawXHKCandles = false; + drawSmoothedXHKCandles = false; + + // + ZeroMemory(this); + } + + // + // Default ... + void Default() + { + // + xhkSmoothingLength = 14; + xhkSmoothingMode = X_MA_MODE_EMA; + xhkIgnoreSmoothingShadows = false; + startCalculationForLastBars = 1500; + drawRawXHKCandles = true; + drawSmoothedXHKCandles = true; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + true + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(0, xhkSmoothingLength); + + // + return result; + } +}; + +// +// Conditions ... +struct X121XHKConditions +{ + // + // Common ... + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + // Buffers ... + + // + double xhkRawOpenBuffer[]; + double xhkRawHighBuffer[]; + double xhkRawLowBuffer[]; + double xhkRawCloseBuffer[]; + + // + double xhkSMOpenBuffer[]; + double xhkSMHighBuffer[]; + double xhkSMLowBuffer[]; + double xhkSMCloseBuffer[]; + + // + // Conditions ... + + // + bool isSMHKBullish; + bool isRawHKBullish; + bool isSMHKSwitchedToBullish; + bool isRawHKSwitchedToBullish; + + // + bool isSMHKBearish; + bool isRawHKBearish; + bool isSMHKSwitchedToBearish; + bool isRawHKSwitchedToBearish; + + // + bool isClosedOverSMHK; + bool isClosedUnderSMHK; + bool isClosedOverRawHK; + bool isClosedUnderRawHK; + + // + bool isRawHKClosedOverSMHK; + bool isRawHKClosedUnderSMHK; + + // + bool isBreakedUpSMHK; + bool isBreakedUpRawHK; + bool isRejectedUpSMHK; + bool isRejectedUpRawHK; + bool isRawHKBreakedUpSMHK; + + // + bool isBreakedDownSMHK; + bool isBreakedDownRawHK; + bool isRejectedDownSMHK; + bool isRejectedDownRawHK; + bool isRawHKBreakedDownSMHK; + + // + // Constructor ... + X121XHKConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + // Commons ... + symbol = NULL; + period = NULL; + time = NULL; + + // + // Buffers ... + + // + Clean(xhkRawOpenBuffer); + Clean(xhkRawHighBuffer); + Clean(xhkRawLowBuffer); + Clean(xhkRawCloseBuffer); + Clean(xhkSMOpenBuffer); + Clean(xhkSMHighBuffer); + Clean(xhkSMLowBuffer); + Clean(xhkSMCloseBuffer); + + // + ArraySetAsSeries(xhkRawOpenBuffer, true); + ArraySetAsSeries(xhkRawHighBuffer, true); + ArraySetAsSeries(xhkRawLowBuffer, true); + ArraySetAsSeries(xhkRawCloseBuffer, true); + ArraySetAsSeries(xhkSMOpenBuffer, true); + ArraySetAsSeries(xhkSMHighBuffer, true); + ArraySetAsSeries(xhkSMLowBuffer, true); + ArraySetAsSeries(xhkSMCloseBuffer, true); + + // + // Conditions ... + + // + isSMHKBullish = false; + isRawHKBullish = false; + isSMHKSwitchedToBullish = false; + isRawHKSwitchedToBullish = false; + + // + isSMHKBearish = false; + isRawHKBearish = false; + isSMHKSwitchedToBearish = false; + isRawHKSwitchedToBearish = false; + + // + isClosedOverSMHK = false; + isClosedUnderSMHK = false; + isClosedOverRawHK = false; + isClosedUnderRawHK = false; + + // + isRawHKClosedOverSMHK = false; + isRawHKClosedUnderSMHK = false; + + // + isBreakedUpSMHK = false; + isBreakedUpRawHK = false; + isRejectedUpSMHK = false; + isRejectedUpRawHK = false; + isRawHKBreakedUpSMHK = false; + + // + isBreakedDownSMHK = false; + isBreakedDownRawHK = false; + isRejectedDownSMHK = false; + isRejectedDownRawHK = false; + isRawHKBreakedDownSMHK = false; + + // + ZeroMemory(this); + } + + /** + * Generate Conditions Scores ... + * + * @param bullishScore: Double, Directional Scores Reference ... + * @param bearishScore: Double, Directional Scores Reference ... + */ + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + // + bullishScore = 0; + bearishScore = 0; + + // + // 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 // + ); + + // + string conditionsStr = + // + ToString("isSMHKBullish", isSMHKBullish, ignoreFalseConditions, separator) + + ToString("isRawHKBullish", isRawHKBullish, ignoreFalseConditions, separator) + + ToString("isSMHKSwitchedToBullish", isSMHKSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isRawHKSwitchedToBullish", isRawHKSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isSMHKBearish", isSMHKBearish, ignoreFalseConditions, separator) + + ToString("isRawHKBearish", isRawHKBearish, ignoreFalseConditions, separator) + + ToString("isSMHKSwitchedToBearish", isSMHKSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isRawHKSwitchedToBearish", isRawHKSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isClosedOverSMHK", isClosedOverSMHK, ignoreFalseConditions, separator) + + ToString("isClosedUnderSMHK", isClosedUnderSMHK, ignoreFalseConditions, separator) + + ToString("isClosedOverRawHK", isClosedOverRawHK, ignoreFalseConditions, separator) + + ToString("isClosedUnderRawHK", isClosedUnderRawHK, ignoreFalseConditions, separator) + + ToString("isRawHKClosedOverSMHK", isRawHKClosedOverSMHK, ignoreFalseConditions, separator) + + ToString("isRawHKClosedUnderSMHK", isRawHKClosedUnderSMHK, ignoreFalseConditions, separator) + + ToString("isBreakedUpSMHK", isBreakedUpSMHK, ignoreFalseConditions, separator) + + ToString("isBreakedUpRawHK", isBreakedUpRawHK, ignoreFalseConditions, separator) + + ToString("isRejectedUpSMHK", isRejectedUpSMHK, ignoreFalseConditions, separator) + + ToString("isRejectedUpRawHK", isRejectedUpRawHK, ignoreFalseConditions, separator) + + ToString("isRawHKBreakedUpSMHK", isRawHKBreakedUpSMHK, ignoreFalseConditions, separator) + + ToString("isBreakedDownSMHK", isBreakedDownSMHK, ignoreFalseConditions, separator) + + ToString("isBreakedDownRawHK", isBreakedDownRawHK, ignoreFalseConditions, separator) + + ToString("isRejectedDownSMHK", isRejectedDownSMHK, ignoreFalseConditions, separator) + + ToString("isRejectedDownRawHK", isRejectedDownRawHK, ignoreFalseConditions, separator) + + ToString("isRawHKBreakedDownSMHK", isRawHKBreakedDownSMHK, ignoreFalseConditions, separator) + + // + "" + // + ; + + // + result = + // + "[" + GetTag() + "]" + separator + + (onlyConditions + ? "" + : commonStr) + + (!includeScores + ? "" + : scoresStr) + + " " + separator + + (onlyCommons + ? "" + : conditionsStr) + + "" + // + ; + + // + return result; + } + + /** + * Retrieve nique Tag Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + return GetTypeName(this); + } + + // +}; + +// +// Class ... +class XCX121XHKHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructors ... + XCX121XHKHelper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCX121XHKHelper() + { + // + Clean(xhkRawOpenBuffer); + Clean(xhkRawHighBuffer); + Clean(xhkRawLowBuffer); + Clean(xhkRawCloseBuffer); + Clean(xhkSMOpenBuffer); + Clean(xhkSMHighBuffer); + Clean(xhkSMLowBuffer); + Clean(xhkSMCloseBuffer); + + // + mInputs.Clean(); + } + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + X121XHKInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + ArraySetAsSeries(xhkRawOpenBuffer, true); + ArraySetAsSeries(xhkRawHighBuffer, true); + ArraySetAsSeries(xhkRawLowBuffer, true); + ArraySetAsSeries(xhkRawCloseBuffer, true); + ArraySetAsSeries(xhkSMOpenBuffer, true); + ArraySetAsSeries(xhkSMHighBuffer, true); + ArraySetAsSeries(xhkSMLowBuffer, true); + ArraySetAsSeries(xhkSMCloseBuffer, true); + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.xhk", + // + // Inputs ... + // + // Market ... + "", + mInputs.xhkSmoothingLength, + mInputs.xhkSmoothingMode, + mInputs.xhkIgnoreSmoothingShadows, + // + // Presentation ... + "", + mInputs.startCalculationForLastBars, + mInputs.drawRawXHKCandles, + mInputs.drawSmoothedXHKCandles + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + X121XHKInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + X121XHKInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Readers ... + + // + double GetRawHKOpen( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(xhkRawOpenBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return xhkRawOpenBuffer[barIndex]; + } + + // + int CopyRawHKOpen( + 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, + xhkRawOpenBuffer, + buffer, + forceClean + // + ); + } + + // + double GetRawHKHigh( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(xhkRawHighBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return xhkRawHighBuffer[barIndex]; + } + + // + int CopyRawHKHigh( + 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, + xhkRawHighBuffer, + buffer, + forceClean + // + ); + } + + // + double GetRawHKLow( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(xhkRawLowBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return xhkRawLowBuffer[barIndex]; + } + + // + int CopyRawHKLow( + 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, + xhkRawLowBuffer, + buffer, + forceClean + // + ); + } + + // + double GetRawHKClose( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(xhkRawCloseBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return xhkRawCloseBuffer[barIndex]; + } + + // + int CopyRawHKClose( + 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, + xhkRawCloseBuffer, + buffer, + forceClean + // + ); + } + + // + double GetSMHKOpen( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(xhkSMOpenBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return xhkSMOpenBuffer[barIndex]; + } + + // + int CopySMHKOpen( + 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, + xhkSMOpenBuffer, + buffer, + forceClean + // + ); + } + + // + double GetSMHKHigh( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(xhkSMHighBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return xhkSMHighBuffer[barIndex]; + } + + // + int CopySMHKHigh( + 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, + xhkSMHighBuffer, + buffer, + forceClean + // + ); + } + + // + double GetSMHKLow( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(xhkSMLowBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return xhkSMLowBuffer[barIndex]; + } + + // + int CopySMHKLow( + 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, + xhkSMLowBuffer, + buffer, + forceClean + // + ); + } + + // + double GetSMHKClose( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(xhkSMCloseBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return xhkSMCloseBuffer[barIndex]; + } + + // + int CopySMHKClose( + 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, + xhkSMCloseBuffer, + buffer, + forceClean + // + ); + } + + // + bool GetRawHKAsXOHCL( + int barIndex, // Bar Index + XOHCL &bar // Bar Result + ) + { + // + bool result = false; + + // + bar.Clean(); + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + result = bar.Init( + GetSymbol(), + GetPeriod(), + barIndex // + ); + if (!result) + { + return result; + } + + // + bar.open = xhkRawOpenBuffer[barIndex]; + bar.high = xhkRawHighBuffer[barIndex]; + bar.low = xhkRawLowBuffer[barIndex]; + bar.close = xhkRawCloseBuffer[barIndex]; + + // + return result; + } + + // + bool GetSMHKAsXOHCL( + int barIndex, // Bar Index + XOHCL &bar // Bar Result + ) + { + // + bool result = false; + + // + bar.Clean(); + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + result = bar.Init( + GetSymbol(), + GetPeriod(), + barIndex // + ); + if (!result) + { + return result; + } + + // + bar.open = xhkSMOpenBuffer[barIndex]; + bar.high = xhkSMHighBuffer[barIndex]; + bar.low = xhkSMLowBuffer[barIndex]; + bar.close = xhkSMCloseBuffer[barIndex]; + + // + return result; + } + + // + void Free() override + { + Cleanup(10); + } + + // + bool GetConditions( + X121XHKConditions &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 ... + + // + CopyRawHKOpen( + zIndex, + loopback, + conditions.xhkRawOpenBuffer // + ); + + // + CopyRawHKHigh( + zIndex, + loopback, + conditions.xhkRawHighBuffer // + ); + + // + CopyRawHKLow( + zIndex, + loopback, + conditions.xhkRawLowBuffer // + ); + + // + CopyRawHKClose( + zIndex, + loopback, + conditions.xhkRawCloseBuffer // + ); + + // + CopySMHKOpen( + zIndex, + loopback, + conditions.xhkSMOpenBuffer // + ); + + // + CopySMHKHigh( + zIndex, + loopback, + conditions.xhkSMHighBuffer // + ); + + // + CopySMHKLow( + zIndex, + loopback, + conditions.xhkSMLowBuffer // + ); + + // + CopySMHKClose( + zIndex, + loopback, + conditions.xhkSMCloseBuffer // + ); + + // + // Conditions ... + + // + int cIDX = 1; + int pIDX = cIDX + 1; + + // + double smHKLow = conditions.xhkSMLowBuffer[cIDX]; + double smHKHigh = conditions.xhkSMHighBuffer[cIDX]; + double smHKOpen = conditions.xhkSMOpenBuffer[cIDX]; + double smHKClose = conditions.xhkSMCloseBuffer[cIDX]; + + // + double smHKLowPrev = conditions.xhkSMLowBuffer[pIDX]; + double smHKHighPrev = conditions.xhkSMHighBuffer[pIDX]; + double smHKOpenPrev = conditions.xhkSMOpenBuffer[pIDX]; + double smHKClosePrev = conditions.xhkSMCloseBuffer[pIDX]; + + // + double rawHKLow = conditions.xhkRawLowBuffer[cIDX]; + double rawHKHigh = conditions.xhkRawHighBuffer[cIDX]; + double rawHKOpen = conditions.xhkRawOpenBuffer[cIDX]; + double rawHKClose = conditions.xhkRawCloseBuffer[cIDX]; + + // + double rawHKLowPrev = conditions.xhkRawLowBuffer[pIDX]; + double rawHKHighPrev = conditions.xhkRawHighBuffer[pIDX]; + double rawHKOpenPrev = conditions.xhkRawOpenBuffer[pIDX]; + double rawHKClosePrev = conditions.xhkRawCloseBuffer[pIDX]; + + // + double smHKUp = MathMax(smHKOpen, smHKClose); + double smHKUpPrev = MathMax(smHKOpenPrev, smHKClosePrev); + + // + double smHKDown = MathMin(smHKOpen, smHKClose); + double smHKDownPrev = MathMin(smHKOpenPrev, smHKClosePrev); + + // + double rawHKUp = MathMax(rawHKOpen, rawHKClose); + double rawHKUpPrev = MathMax(rawHKOpenPrev, rawHKClosePrev); + + // + double rawHKDown = MathMin(rawHKOpen, rawHKClose); + double rawHKDownPrev = MathMin(rawHKOpenPrev, rawHKClosePrev); + + // + XOHCL rawHKCBar; + bool hasRawHKBar = GetRawHKAsXOHCL( + cIndex, + rawHKCBar // + ); + + // + // + // + + // + bool isSMHKBullish = smHKOpen < smHKClose; + bool isSMHKBullishPrev = smHKOpenPrev < smHKClosePrev; + + // + bool isRawHKBullish = rawHKOpen < rawHKClose; + bool isRawHKBullishPrev = rawHKOpenPrev < rawHKClosePrev; + + // + bool isSMHKSwitchedToBullish = isSMHKBullish && + !isSMHKBullishPrev; + bool isRawHKSwitchedToBullish = isRawHKBullish && + !isRawHKBullishPrev; + + // + bool isSMHKBearish = smHKOpen > smHKClose; + bool isSMHKBearishPrev = smHKOpenPrev > smHKClosePrev; + + // + bool isRawHKBearish = rawHKOpen > rawHKClose; + bool isRawHKBearishPrev = rawHKOpenPrev > rawHKClosePrev; + + // + bool isSMHKSwitchedToBearish = isSMHKBearish && + !isSMHKBearishPrev; + bool isRawHKSwitchedToBearish = isRawHKBearish && + !isRawHKBearishPrev; + + // + bool isClosedOverSMHK = cBar.close > smHKUp; + bool isClosedUnderSMHK = cBar.close < smHKDown; + + // + bool isClosedOverRawHK = cBar.close > rawHKUp; + bool isClosedUnderRawHK = cBar.close < rawHKDown; + + // + bool isRawHKClosedOverSMHK = rawHKClose > smHKUp; + bool isRawHKClosedUnderSMHK = rawHKClose < smHKDown; + + // + bool isBreakedUpSMHK = IsBarBreak( + smHKUp, + X_DIRECTION_BULLISH, + cBar // + ); + bool isBreakedUpRawHK = IsBarBreak( + rawHKUp, + X_DIRECTION_BULLISH, + cBar // + ); + bool isRejectedUpSMHK = IsBarReject( + smHKUp, + X_DIRECTION_BULLISH, + cBar // + ); + bool isRejectedUpRawHK = IsBarReject( + rawHKUp, + X_DIRECTION_BULLISH, + cBar // + ); + + // + bool isRawHKBreakedUpSMHK = + hasRawHKBar && + IsBarBreak( + smHKUp, + X_DIRECTION_BULLISH, + rawHKCBar // + ); + + // + bool isBreakedDownSMHK = IsBarBreak( + smHKDown, + X_DIRECTION_BEARISH, + cBar // + ); + bool isBreakedDownRawHK = IsBarBreak( + rawHKDown, + X_DIRECTION_BEARISH, + cBar // + ); + bool isRejectedDownSMHK = IsBarReject( + smHKDown, + X_DIRECTION_BEARISH, + cBar // + ); + bool isRejectedDownRawHK = IsBarReject( + rawHKDown, + X_DIRECTION_BEARISH, + cBar // + ); + + // + bool isRawHKBreakedDownSMHK = + hasRawHKBar && + IsBarBreak( + smHKDown, + X_DIRECTION_BEARISH, + rawHKCBar // + ); + + // + conditions.isSMHKBullish = isSMHKBullish; + conditions.isRawHKBullish = isRawHKBullish; + conditions.isSMHKSwitchedToBullish = isSMHKSwitchedToBullish; + conditions.isRawHKSwitchedToBullish = isRawHKSwitchedToBullish; + conditions.isSMHKBearish = isSMHKBearish; + conditions.isRawHKBearish = isRawHKBearish; + conditions.isSMHKSwitchedToBearish = isSMHKSwitchedToBearish; + conditions.isRawHKSwitchedToBearish = isRawHKSwitchedToBearish; + conditions.isClosedOverSMHK = isClosedOverSMHK; + conditions.isClosedUnderSMHK = isClosedUnderSMHK; + conditions.isClosedOverRawHK = isClosedOverRawHK; + conditions.isClosedUnderRawHK = isClosedUnderRawHK; + conditions.isRawHKClosedOverSMHK = isRawHKClosedOverSMHK; + conditions.isRawHKClosedUnderSMHK = isRawHKClosedUnderSMHK; + conditions.isBreakedUpSMHK = isBreakedUpSMHK; + conditions.isBreakedUpRawHK = isBreakedUpRawHK; + conditions.isRejectedUpSMHK = isRejectedUpSMHK; + conditions.isRejectedUpRawHK = isRejectedUpRawHK; + conditions.isRawHKBreakedUpSMHK = isRawHKBreakedUpSMHK; + conditions.isBreakedDownSMHK = isBreakedDownSMHK; + conditions.isBreakedDownRawHK = isBreakedDownRawHK; + conditions.isRejectedDownSMHK = isRejectedDownSMHK; + conditions.isRejectedDownRawHK = isRejectedDownRawHK; + conditions.isRawHKBreakedDownSMHK = isRawHKBreakedDownSMHK; + + // + Cleanup(); + + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + + // + rawHKCBar.Clean(); + + // + return result; + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + X121XHKInputs mInputs; // Inputs ... + + // + // Buffers ... + double xhkRawOpenBuffer[]; + double xhkRawHighBuffer[]; + double xhkRawLowBuffer[]; + double xhkRawCloseBuffer[]; + double xhkSMOpenBuffer[]; + double xhkSMHighBuffer[]; + double xhkSMLowBuffer[]; + double xhkSMCloseBuffer[]; + + // + void Calculate( + int maxRequiredBars = 100 // + ) + { + // + // Buffers ... + + // + // RAW Open ... + CopyBuffer( + mHandler, + X121_XHK_RAW_OPEN_LINE, + 0, + maxRequiredBars, + xhkRawOpenBuffer + // + ); + + // + // RAW High ... + CopyBuffer( + mHandler, + X121_XHK_RAW_HIGH_LINE, + 0, + maxRequiredBars, + xhkRawHighBuffer + // + ); + + // + // RAW Low ... + CopyBuffer( + mHandler, + X121_XHK_RAW_LOW_LINE, + 0, + maxRequiredBars, + xhkRawLowBuffer + // + ); + + // + // RAW Close ... + CopyBuffer( + mHandler, + X121_XHK_RAW_CLOSE_LINE, + 0, + maxRequiredBars, + xhkRawCloseBuffer + // + ); + + // + // SM Open ... + CopyBuffer( + mHandler, + X121_XHK_SM_OPEN_LINE, + 0, + maxRequiredBars, + xhkSMOpenBuffer + // + ); + + // + // SM High ... + CopyBuffer( + mHandler, + X121_XHK_SM_HIGH_LINE, + 0, + maxRequiredBars, + xhkSMHighBuffer + // + ); + + // + // SM Low ... + CopyBuffer( + mHandler, + X121_XHK_SM_LOW_LINE, + 0, + maxRequiredBars, + xhkSMLowBuffer + // + ); + + // + // SM Close ... + CopyBuffer( + mHandler, + X121_XHK_SM_CLOSE_LINE, + 0, + maxRequiredBars, + xhkSMCloseBuffer + // + ); + } + + // + void Cleanup( + int maxAllowed = 100 // + ) + { + // + CleanupArray( + xhkRawOpenBuffer, + maxAllowed // + ); + + // + CleanupArray( + xhkRawHighBuffer, + maxAllowed // + ); + + // + CleanupArray( + xhkRawLowBuffer, + maxAllowed // + ); + + // + CleanupArray( + xhkRawCloseBuffer, + maxAllowed // + ); + + // + CleanupArray( + xhkSMOpenBuffer, + maxAllowed // + ); + + // + CleanupArray( + xhkSMHighBuffer, + maxAllowed // + ); + + // + CleanupArray( + xhkSMLowBuffer, + maxAllowed // + ); + + // + CleanupArray( + xhkSMCloseBuffer, + maxAllowed // + ); + + // + } + + // +}; + +// +// Tools ... \ No newline at end of file diff --git a/BKPS/14031218/Helpers/x-saherelm.x121.xpv.helper.mq5 b/BKPS/14031218/Helpers/x-saherelm.x121.xpv.helper.mq5 new file mode 100644 index 0000000..993a184 --- /dev/null +++ b/BKPS/14031218/Helpers/x-saherelm.x121.xpv.helper.mq5 @@ -0,0 +1,2551 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XCX121XPVHelper +// 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 ... + +// +// Definitions ... +enum ENUM_X121_XPV_BUFFERS +{ + // + X121_XPV_PEAK_LINE = 0, + X121_XPV_VALE_LINE = 1, + X121_XPV_SAR_LINE = 2, + X121_XPV_PEAK_GOLDEN_ZONE_LINE = 3, + X121_XPV_VALE_GOLDEN_ZONE_LINE = 4, + X121_XPV_C_HH_LINE = 5, + X121_XPV_C_LL_LINE = 6, + X121_XPV_S_HH_LINE = 7, + X121_XPV_S_LL_LINE = 8, + X121_XPV_M_HH_LINE = 9, + X121_XPV_M_LL_LINE = 10, + X121_XPV_L_HH_LINE = 11, + X121_XPV_L_LL_LINE = 12, + X121_XPV_H_HH_LINE = 13, + X121_XPV_H_LL_LINE = 14, +}; + +// +// Input Models ... +struct X121XPVInputs +{ + // + // Props ... + + // + // Short ... + ENUM_X_PERIOD_METHOD scMethod; // How to Find Period + ENUM_TIMEFRAMES scPeriod; // Time Period + + // + // Medium ... + ENUM_X_PERIOD_METHOD mcMethod; // How to Find Period + ENUM_TIMEFRAMES mcPeriod; // Time Period + + // + // Long ... + ENUM_X_PERIOD_METHOD lcMethod; // How to Find Period + ENUM_TIMEFRAMES lcPeriod; // Time Period + + // + // Hind ... + ENUM_X_PERIOD_METHOD hcMethod; // How to Find Period + ENUM_TIMEFRAMES hcPeriod; // Time Period + + // + // Boundary Detection ... + ENUM_SERIESMODE hhMode; // Highest High Calculation Method + ENUM_SERIESMODE llMode; // Lowest Low Calculation Method + ENUM_X_FIBO_LEVELS goldenZoneLevel; // Golden Zone Detection + + // + // Parabolic Sar Detection ... + double sarStep; // Step + double sarMax; // Maximum + + // + int startCalculationForLastBars; // Calculate Last n Bars + + // + int sarArrowCode; // Parabolic Sar Arrow Code + int peaksArrowCode; // Peaks Arrow Code + int valesArrowCode; // Vales Arrow Code + + // + bool showSar; // Show Parabolic Sar + bool showPeaks; // Show Peaks + bool showVales; // Show Vales + bool showGoldenZones; // Show Golden Zones + + // + // Constructor(s) ... + X121XPVInputs() + { + // + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + // 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; + goldenZoneLevel = X_FIBO_LEVEL_382; + + // + sarStep = 0; + sarMax = 0; + + // + startCalculationForLastBars = 0; + + // + sarArrowCode = 0; + peaksArrowCode = 0; + valesArrowCode = 0; + + // + showSar = false; + showPeaks = false; + showVales = false; + showGoldenZones = true; + + // + ZeroMemory(this); + } + + // + // Default ... + void Default() + { + // + // 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; + goldenZoneLevel = X_FIBO_LEVEL_382; + + // + sarStep = 0.02; + sarMax = 0.2; + + // + startCalculationForLastBars = 1000; + + // + sarArrowCode = 159; + peaksArrowCode = 159; + valesArrowCode = 159; + + // + showSar = true; + showPeaks = true; + showVales = true; + showGoldenZones = true; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + // SAR ... + sarMax > 0 && + sarStep > 0 && + sarMax > sarStep && + // + // XPV ... + (IsValid(scMethod, scPeriod) && + IsValid(mcMethod, mcPeriod) && + IsValid(lcMethod, lcPeriod) && + IsValid(hcMethod, hcPeriod)) + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(1, 1); + + // + return result; + } +}; + +// +// Conditions ... +struct X121XPVConditions +{ + // + // Common ... + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + // Buffers ... + double peaksBuffer[]; + double valesBuffer[]; + double peaksGoldenBuffer[]; + double valesGoldenBuffer[]; + double sarBuffer[]; + double cHHBuffer[]; + double cLLBuffer[]; + double sHHBuffer[]; + double sLLBuffer[]; + double mHHBuffer[]; + double mLLBuffer[]; + double lHHBuffer[]; + double lLLBuffer[]; + double hHHBuffer[]; + double hLLBuffer[]; + + // + // Conditions ... + + // + // SAR ... + + // + bool isSarBullish; + bool isSarBearish; + + // + bool isSarSwitchedToBullish; + bool isSarSwitchedToBearish; + + // + // XPV ... + + // + bool isNewPeak; + bool isNewPeakOverLast; + bool isNewPeakUnderLast; + bool isRejectedPrevPeak; + bool isBreakedUpPrevPeak; + + // + bool isNewVale; + bool isNewValeOverLast; + bool isNewValeUnderLast; + bool isRejectedPrevVale; + bool isBreakedDownPrevVale; + + // + // Constructor ... + X121XPVConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + // Commons ... + symbol = NULL; + period = NULL; + time = NULL; + + // + // Buffers ... + + // + Clean(peaksBuffer); + Clean(valesBuffer); + Clean(peaksGoldenBuffer); + Clean(valesGoldenBuffer); + Clean(sarBuffer); + Clean(cHHBuffer); + Clean(cLLBuffer); + Clean(sHHBuffer); + Clean(sLLBuffer); + Clean(mHHBuffer); + Clean(mLLBuffer); + Clean(lHHBuffer); + Clean(lLLBuffer); + Clean(hHHBuffer); + Clean(hLLBuffer); + + // + // Clean(bullishTrendBuffer); + // Clean(bearishTrendBuffer); + + // + ArraySetAsSeries(peaksBuffer, true); + ArraySetAsSeries(valesBuffer, true); + ArraySetAsSeries(peaksGoldenBuffer, true); + ArraySetAsSeries(valesGoldenBuffer, true); + ArraySetAsSeries(sarBuffer, 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); + + // + // Conditions ... + + // + isSarBullish = false; + isSarBearish = false; + + // + isSarSwitchedToBullish = false; + isSarSwitchedToBearish = false; + + // + isNewPeak = false; + isNewPeakOverLast = false; + isNewPeakUnderLast = false; + isRejectedPrevPeak = false; + isBreakedUpPrevPeak = false; + // + isNewVale = false; + isNewValeOverLast = false; + isNewValeUnderLast = false; + isRejectedPrevVale = false; + isBreakedDownPrevVale = false; + + // + ZeroMemory(this); + } + + /** + * Generate Conditions Scores ... + * + * @param bullishScore: Double, Directional Scores Reference ... + * @param bearishScore: Double, Directional Scores Reference ... + */ + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + // + bullishScore = 0; + bearishScore = 0; + + // + // 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 // + ); + + // + string conditionsStr = + // + ToString("isSarBullish", isSarBullish, ignoreFalseConditions, separator) + + ToString("isSarBearish", isSarBearish, ignoreFalseConditions, separator) + + ToString("isSarSwitchedToBullish", isSarSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isSarSwitchedToBearish", isSarSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isNewPeak", isNewPeak, ignoreFalseConditions, separator) + + ToString("isNewPeakOverLast", isNewPeakOverLast, ignoreFalseConditions, separator) + + ToString("isNewPeakUnderLast", isNewPeakUnderLast, ignoreFalseConditions, separator) + + ToString("isRejectedPrevPeak", isRejectedPrevPeak, ignoreFalseConditions, separator) + + ToString("isBreakedUpPrevPeak", isBreakedUpPrevPeak, ignoreFalseConditions, separator) + + ToString("isNewVale", isNewVale, ignoreFalseConditions, separator) + + ToString("isNewValeOverLast", isNewValeOverLast, ignoreFalseConditions, separator) + + ToString("isNewValeUnderLast", isNewValeUnderLast, ignoreFalseConditions, separator) + + ToString("isRejectedPrevVale", isRejectedPrevVale, ignoreFalseConditions, separator) + + ToString("isBreakedDownPrevVale", isBreakedDownPrevVale, ignoreFalseConditions, separator) + + // + "" + // + ; + + // + result = + // + "[" + GetTag() + "]" + separator + + (onlyConditions + ? "" + : commonStr) + + (!includeScores + ? "" + : scoresStr) + + " " + separator + + (onlyCommons + ? "" + : conditionsStr) + + "" + // + ; + + // + return result; + } + + /** + * Retrieve nique Tag Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + return GetTypeName(this); + } + + // +}; + +// +// Class ... +class XCX121XPVHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructors ... + XCX121XPVHelper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCX121XPVHelper() + { + // + mInputs.Clean(); + + // + Clean(peaksBuffer); + Clean(valesBuffer); + Clean(peaksGoldenBuffer); + Clean(valesGoldenBuffer); + Clean(sarBuffer); + Clean(cHHBuffer); + Clean(cLLBuffer); + Clean(sHHBuffer); + Clean(sLLBuffer); + Clean(mHHBuffer); + Clean(mLLBuffer); + Clean(lHHBuffer); + Clean(lLLBuffer); + Clean(hHHBuffer); + Clean(hLLBuffer); + } + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + X121XPVInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + ArraySetAsSeries(peaksBuffer, true); + ArraySetAsSeries(valesBuffer, true); + ArraySetAsSeries(peaksGoldenBuffer, true); + ArraySetAsSeries(valesGoldenBuffer, true); + ArraySetAsSeries(sarBuffer, 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); + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.xpv", + // + // Inputs ... + // + // Market ... + "", + // + // Short ... + "", + mInputs.scMethod, + mInputs.scPeriod, + // + // Medium ... + "", + mInputs.mcMethod, + mInputs.mcPeriod, + // + // Long ... + "", + mInputs.lcMethod, + mInputs.lcPeriod, + // + // Hind ... + "", + mInputs.hcMethod, + mInputs.hcPeriod, + // + // Boundary Detection ... + "", + mInputs.hhMode, + mInputs.llMode, + mInputs.goldenZoneLevel, + // + // SAr Detection ... + "", + mInputs.sarStep, + mInputs.sarMax, + // + // Presentation ... + "", + // + mInputs.startCalculationForLastBars, + mInputs.sarArrowCode, + mInputs.peaksArrowCode, + mInputs.valesArrowCode, + // + mInputs.showSar, + mInputs.showPeaks, + mInputs.showVales, + mInputs.showGoldenZones + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + X121XPVInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + X121XPVInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Readers ... + + // + // SAR ... + + // + 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 + // + ); + } + + // + // PV ... + + // + // 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 + // + ); + } + + // + // GOLDEN PEAKS ... + + // + double GetPeakGoldenZone( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(peaksGoldenBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return peaksGoldenBuffer[barIndex]; + } + + // + int CopyPeakGoldenZone( + 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, + peaksGoldenBuffer, + buffer, + forceClean + // + ); + } + + // + // GOLDEN VALES ... + + // + double GetValeGoldenZone( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(valesGoldenBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return valesGoldenBuffer[barIndex]; + } + + // + int CopyValeGoldenZone( + 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, + valesGoldenBuffer, + buffer, + forceClean + // + ); + } + + // + // + // + + // + double GetHigherPeak( + int &index, // Bar Index + double peak, // Peak Source + int barIndex = 0, // Bar Index + int loopback = 576 // Max Allowed Loopback + ) + { + // + double result = 0; + + // + index = -1; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (loopback < 576) + { + loopback = 576; + } + + // + if (peak <= 0) + { + return result; + } + + // + double iValue = 0; + int sIndex = barIndex; + bool canContinue = true; + while (canContinue) + { + // + iValue = GetPeak(sIndex); + if (iValue > peak) + { + // + index = sIndex; + result = iValue; + break; + } + + // + canContinue = sIndex < barIndex + loopback; + sIndex++; + } + + // + return result; + } + + // + double GetLowerPeak( + int &index, // Bar Index + double peak, // Peak Source + int barIndex = 0, // Bar Index + int loopback = 576 // Max Allowed Loopback + ) + { + // + double result = 0; + + // + index = -1; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (loopback < 576) + { + loopback = 576; + } + + // + if (peak <= 0) + { + return result; + } + + // + double iValue = 0; + int sIndex = barIndex; + bool canContinue = true; + while (canContinue) + { + // + iValue = GetPeak(sIndex); + if (iValue < peak) + { + // + index = sIndex; + result = iValue; + break; + } + + // + canContinue = sIndex < barIndex + loopback; + sIndex++; + } + + // + return result; + } + + // + double GetHigherVale( + int &index, // Bar Index + double vale, // Vale Source + int barIndex = 0, // Bar Index + int loopback = 576 // Max Allowed Loopback + ) + { + // + double result = 0; + + // + index = -1; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (loopback < 576) + { + loopback = 576; + } + + // + if (vale <= 0) + { + return result; + } + + // + double iValue = 0; + int sIndex = barIndex; + bool canContinue = true; + while (canContinue) + { + // + iValue = GetVale(sIndex); + if (iValue > vale) + { + // + index = sIndex; + result = iValue; + break; + } + + // + canContinue = sIndex < barIndex + loopback; + sIndex++; + } + + // + return result; + } + + // + double GetLowerVale( + int &index, // Bar Index + double vale, // Vale Source + int barIndex = 0, // Bar Index + int loopback = 576 // Max Allowed Loopback + ) + { + // + double result = 0; + + // + index = -1; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (loopback < 576) + { + loopback = 576; + } + + // + if (vale <= 0) + { + return result; + } + + // + double iValue = 0; + int sIndex = barIndex; + bool canContinue = true; + while (canContinue) + { + // + iValue = GetVale(sIndex); + if (iValue < vale) + { + // + index = sIndex; + result = iValue; + break; + } + + // + canContinue = sIndex < barIndex + loopback; + sIndex++; + } + + // + return result; + } + + // + // 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 + // + ); + } + + // + // Tools Function ... + + // + double GetLowestPeak( + int barIndex, + int &index, + double &vale, + int loopback = 576 // + ) + { + // + double result = 0; + + // + index = -1; + vale = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (loopback < 576) + { + loopback = 576; + } + + // + Calculate(); + + // + for (int i = 0; i < barIndex + loopback; i++) + { + // + double iPeak = GetPeak(i); + if (iPeak == 0) + { + break; + } + + // + if (iPeak > 0 && (result == 0 || + result >= iPeak)) + { + // + index = i; + result = iPeak; + vale = GetVale(index); + } + } + + // + return result; + } + + // + double GetHighestPeak( + int barIndex, + int &index, + double &vale, + int loopback = 576 // + ) + { + // + double result = 0; + + // + index = -1; + vale = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (loopback < 576) + { + loopback = 576; + } + + // + Calculate(); + + // + for (int i = 0; i < barIndex + loopback; i++) + { + // + double iPeak = GetPeak(i); + if (iPeak == 0) + { + break; + } + + // + if (iPeak > 0 && (result == 0 || + result <= iPeak)) + { + // + index = i; + result = iPeak; + vale = GetVale(index); + } + } + + // + return result; + } + + // + double GetLowestVale( + int barIndex, + int &index, + double &peak, + int loopback = 576 // + ) + { + // + double result = 0; + + // + index = -1; + peak = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (loopback < 576) + { + loopback = 576; + } + + // + Calculate(); + + // + for (int i = 0; i < barIndex + loopback; i++) + { + // + double iPeak = GetVale(i); + if (iPeak == 0) + { + break; + } + + // + if (iPeak > 0 && (result == 0 || + result >= iPeak)) + { + // + index = i; + result = iPeak; + peak = GetPeak(index); + } + } + + // + return result; + } + + // + double GetHighestVale( + int barIndex, + int &index, + double &peak, + int loopback = 576 // + ) + { + // + double result = 0; + + // + index = -1; + peak = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (loopback < 576) + { + loopback = 576; + } + + // + Calculate(); + + // + for (int i = 0; i < barIndex + loopback; i++) + { + // + double iPeak = GetVale(i); + if (iPeak == 0) + { + break; + } + + // + if (iPeak > 0 && (result == 0 || + result <= iPeak)) + { + // + index = i; + result = iPeak; + peak = GetPeak(index); + } + } + + // + return result; + } + + // + void Free() override + { + Cleanup(10); + } + + // + bool GetConditions( + X121XPVConditions &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 // + ); + + // + CopyPeakGoldenZone( + zIndex, + loopback, + conditions.peaksGoldenBuffer // + ); + + // + CopyValeGoldenZone( + zIndex, + loopback, + conditions.valesGoldenBuffer // + ); + + // + 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 // + ); + + // + // Conditions ... + + // + int cIDX = 1; + int pIDX = cIDX + 1; + + // + // SAR ... + + // + 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 isRejectedPrevPeak = IsBarReject( + conditions.peaksBuffer[pIDX], + X_DIRECTION_BEARISH, + cBar // + ); + bool isBreakedUpPrevPeak = IsBarBreak( + conditions.peaksBuffer[pIDX], + X_DIRECTION_BULLISH, + cBar // + ); + + // + 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]; + bool isRejectedPrevVale = IsBarReject( + conditions.valesBuffer[pIDX], + X_DIRECTION_BULLISH, + cBar // + ); + bool isBreakedDownPrevVale = IsBarBreak( + conditions.valesBuffer[pIDX], + X_DIRECTION_BEARISH, + cBar // + ); + + // + conditions.isSarBullish = isSarBullish; + conditions.isSarBearish = isSarBearish; + conditions.isSarSwitchedToBullish = isSarSwitchedToBullish; + conditions.isSarSwitchedToBearish = isSarSwitchedToBearish; + conditions.isNewPeak = isNewPeak; + conditions.isNewPeakOverLast = isNewPeakOverLast; + conditions.isNewPeakUnderLast = isNewPeakUnderLast; + conditions.isRejectedPrevPeak = isRejectedPrevPeak; + conditions.isBreakedUpPrevPeak = isBreakedUpPrevPeak; + conditions.isNewVale = isNewVale; + conditions.isNewValeOverLast = isNewValeOverLast; + conditions.isNewValeUnderLast = isNewValeUnderLast; + conditions.isRejectedPrevVale = isRejectedPrevVale; + conditions.isBreakedDownPrevVale = isBreakedDownPrevVale; + + // + Cleanup(); + + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + + // + return result; + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + X121XPVInputs mInputs; // Inputs ... + + // + // Buffers ... + double peaksBuffer[]; + double valesBuffer[]; + double peaksGoldenBuffer[]; + double valesGoldenBuffer[]; + double sarBuffer[]; + double cHHBuffer[]; + double cLLBuffer[]; + double sHHBuffer[]; + double sLLBuffer[]; + double mHHBuffer[]; + double mLLBuffer[]; + double lHHBuffer[]; + double lLLBuffer[]; + double hHHBuffer[]; + double hLLBuffer[]; + + // + void Calculate( + int maxRequiredBars = 100 // + ) + { + // + // Buffers ... + + // + // SAR ... + CopyBuffer( + mHandler, + X121_XPV_SAR_LINE, + 0, + maxRequiredBars, + sarBuffer + // + ); + + // + // XPV ... + + // + // PEAKS ... + CopyBuffer( + mHandler, + X121_XPV_PEAK_LINE, + 0, + maxRequiredBars, + peaksBuffer + // + ); + + // + // VALES ... + CopyBuffer( + mHandler, + X121_XPV_VALE_LINE, + 0, + maxRequiredBars, + valesBuffer + // + ); + + // + // GOLDEN PEAKS ... + CopyBuffer( + mHandler, + X121_XPV_PEAK_GOLDEN_ZONE_LINE, + 0, + maxRequiredBars, + peaksGoldenBuffer + // + ); + + // + // GOLDEN VALES ... + CopyBuffer( + mHandler, + X121_XPV_VALE_GOLDEN_ZONE_LINE, + 0, + maxRequiredBars, + valesGoldenBuffer + // + ); + + // + // CURRENT ... + + // + // HH ... + CopyBuffer( + mHandler, + X121_XPV_C_HH_LINE, + 0, + maxRequiredBars, + cHHBuffer + // + ); + + // + // LL ... + CopyBuffer( + mHandler, + X121_XPV_C_LL_LINE, + 0, + maxRequiredBars, + cLLBuffer + // + ); + + // + // SHORT ... + + // + // HH ... + CopyBuffer( + mHandler, + X121_XPV_S_HH_LINE, + 0, + maxRequiredBars, + sHHBuffer + // + ); + + // + // LL ... + CopyBuffer( + mHandler, + X121_XPV_S_LL_LINE, + 0, + maxRequiredBars, + sLLBuffer + // + ); + + // + // MEDIUM ... + + // + // HH ... + CopyBuffer( + mHandler, + X121_XPV_M_HH_LINE, + 0, + maxRequiredBars, + mHHBuffer + // + ); + + // + // LL ... + CopyBuffer( + mHandler, + X121_XPV_M_LL_LINE, + 0, + maxRequiredBars, + mLLBuffer + // + ); + + // + // LONG ... + + // + // HH ... + CopyBuffer( + mHandler, + X121_XPV_L_HH_LINE, + 0, + maxRequiredBars, + lHHBuffer + // + ); + + // + // LL ... + CopyBuffer( + mHandler, + X121_XPV_L_LL_LINE, + 0, + maxRequiredBars, + lLLBuffer + // + ); + + // + // HIND ... + + // + // HH ... + CopyBuffer( + mHandler, + X121_XPV_H_HH_LINE, + 0, + maxRequiredBars, + hHHBuffer + // + ); + + // + // LL ... + CopyBuffer( + mHandler, + X121_XPV_H_LL_LINE, + 0, + maxRequiredBars, + hLLBuffer + // + ); + } + + // + void Cleanup( + int maxAllowed = 100 // + ) + { + // + CleanupArray( + peaksBuffer, + maxAllowed // + ); + + // + CleanupArray( + valesBuffer, + maxAllowed // + ); + + // + CleanupArray( + peaksGoldenBuffer, + maxAllowed // + ); + + // + CleanupArray( + valesGoldenBuffer, + maxAllowed // + ); + + // + CleanupArray( + sarBuffer, + maxAllowed // + ); + + // + CleanupArray( + cHHBuffer, + maxAllowed // + ); + + // + CleanupArray( + cLLBuffer, + maxAllowed // + ); + + // + CleanupArray( + sHHBuffer, + maxAllowed // + ); + + // + CleanupArray( + sLLBuffer, + maxAllowed // + ); + + // + CleanupArray( + mHHBuffer, + maxAllowed // + ); + + // + CleanupArray( + mLLBuffer, + maxAllowed // + ); + + // + CleanupArray( + lHHBuffer, + maxAllowed // + ); + + // + CleanupArray( + lLLBuffer, + maxAllowed // + ); + + // + CleanupArray( + hHHBuffer, + maxAllowed // + ); + + // + CleanupArray( + hLLBuffer, + maxAllowed // + ); + + // + } + + // +}; + +// +// Tools ... \ No newline at end of file diff --git a/BKPS/14031218/Helpers/x-saherelm.x121.xstr.helper.mq5 b/BKPS/14031218/Helpers/x-saherelm.x121.xstr.helper.mq5 new file mode 100644 index 0000000..31bf24f --- /dev/null +++ b/BKPS/14031218/Helpers/x-saherelm.x121.xstr.helper.mq5 @@ -0,0 +1,1112 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XCX121XSTRHelper +// 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 ... + +// +// Definitions ... +enum ENUM_X121_XSTR_BUFFERS +{ + // + X121_XSTR_LINE = 0, + X121_XSTR_UP_LINE = 2, + X121_XSTR_DOWN_LINE = 3, + X121_XSTR_ATR_LINE = 4, + X121_XSTR_PRICE_LINE = 5, + X121_XSTR_STATE_LINE = 6, +}; + +// +// Input Models ... +struct X121XSTRInputs +{ + // + // Props ... + + int strLength; // Length + double strMultiplier; // Multiplier + ENUM_APPLIED_PRICE strAppliedTo; // Applied To + + // + bool showStr; // Show Upper Zone + bool showStrUpper; // Show Str Upper + bool showStrLower; // Show Str Lower + + // + // Constructor(s) ... + X121XSTRInputs() + { + // + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + strLength = 0; + strMultiplier = 0.0; + strAppliedTo = PRICE_MEDIAN; + + // + showStr = false; + showStrUpper = false; + showStrLower = false; + + // + ZeroMemory(this); + } + + // + // Default ... + void Default() + { + // + strLength = 14; + strMultiplier = 3.0; + strAppliedTo = PRICE_MEDIAN; + + // + showStr = true; + showStrUpper = true; + showStrLower = true; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + strLength > 0 && + strMultiplier > 0 + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(1, strLength); + + // + return result; + } +}; + +// +// Conditions ... +struct X121XSTRConditions +{ + // + // Common ... + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + // Buffers ... + double strBuffer[]; + double atrBuffer[]; + double strPriceBuffer[]; + double strUpBuffer[]; + double strDownBuffer[]; + double strStateBuffer[]; + + // + // Conditions ... + + // + bool isStrBullish; + bool isStrBearish; + + // + bool isStrSwitchedToBullish; + bool isStrSwitchedToBearish; + + // + // bool isCloseLower + + // + // Constructor ... + X121XSTRConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + // Commons ... + symbol = NULL; + period = NULL; + time = NULL; + + // + // Buffers ... + + // + Clean(strBuffer); + Clean(atrBuffer); + Clean(strPriceBuffer); + Clean(strUpBuffer); + Clean(strDownBuffer); + Clean(strStateBuffer); + + // + ArraySetAsSeries(strBuffer, true); + ArraySetAsSeries(atrBuffer, true); + ArraySetAsSeries(strPriceBuffer, true); + ArraySetAsSeries(strUpBuffer, true); + ArraySetAsSeries(strDownBuffer, true); + ArraySetAsSeries(strStateBuffer, true); + + // + // Conditions ... + + // + isStrBullish = false; + isStrBearish = false; + + // + isStrSwitchedToBullish = false; + isStrSwitchedToBearish = false; + + // + ZeroMemory(this); + } + + /** + * Generate Conditions Scores ... + * + * @param bullishScore: Double, Directional Scores Reference ... + * @param bearishScore: Double, Directional Scores Reference ... + */ + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + // + bullishScore = 0; + bearishScore = 0; + + // + // 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 // + ); + + // + string conditionsStr = + // + ToString("isStrBullish", isStrBullish, ignoreFalseConditions, separator) + + ToString("isStrBearish", isStrBearish, ignoreFalseConditions, separator) + + ToString("isStrSwitchedToBullish", isStrSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isStrSwitchedToBearish", isStrSwitchedToBearish, ignoreFalseConditions, separator) + + // + "" + // + ; + + // + result = + // + "[" + GetTag() + "]" + separator + + (onlyConditions + ? "" + : commonStr) + + (!includeScores + ? "" + : scoresStr) + + " " + separator + + (onlyCommons + ? "" + : conditionsStr) + + "" + // + ; + + // + return result; + } + + /** + * Retrieve nique Tag Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + return GetTypeName(this); + } + + // +}; + +// +// Class ... +class XCX121XSTRHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructors ... + XCX121XSTRHelper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCX121XSTRHelper() + { + // + mInputs.Clean(); + + // + Clean(strBuffer); + Clean(atrBuffer); + Clean(strPriceBuffer); + Clean(strUpBuffer); + Clean(strDownBuffer); + Clean(strStateBuffer); + } + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + X121XSTRInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + ArraySetAsSeries(strBuffer, true); + ArraySetAsSeries(atrBuffer, true); + ArraySetAsSeries(strPriceBuffer, true); + ArraySetAsSeries(strUpBuffer, true); + ArraySetAsSeries(strDownBuffer, true); + ArraySetAsSeries(strStateBuffer, true); + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.xstr", + // + // Inputs ... + // + // Market ... + "", + mInputs.strLength, + mInputs.strMultiplier, + mInputs.strAppliedTo, + // + // Presentation ... + "", + mInputs.showStr, + mInputs.showStrUpper, + mInputs.showStrLower + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + X121XSTRInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + X121XSTRInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Readers ... + + // + // ATR ... + + // + double GetATR( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(atrBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return atrBuffer[barIndex]; + } + + // + int CopyATR( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + atrBuffer, + buffer, + forceClean + // + ); + } + + // + double GetSTR( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(strBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return strBuffer[barIndex]; + } + + // + int CopySTR( + 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, + strBuffer, + buffer, + forceClean + // + ); + } + + // + double GetSTRState( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(strStateBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return strStateBuffer[barIndex]; + } + + // + int CopySTRState( + 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, + strStateBuffer, + buffer, + forceClean + // + ); + } + + // + double GetSTRPrice( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(strPriceBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return strPriceBuffer[barIndex]; + } + + // + int CopySTRPrice( + 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, + strPriceBuffer, + buffer, + forceClean + // + ); + } + + // + double GetSTRUp( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(strUpBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return strUpBuffer[barIndex]; + } + + // + int CopySTRUp( + 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, + strUpBuffer, + buffer, + forceClean + // + ); + } + + // + double GetSTRDown( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(strDownBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return strDownBuffer[barIndex]; + } + + // + int CopySTRDown( + 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, + strDownBuffer, + buffer, + forceClean + // + ); + } + + // + double GetLastSTR( + ENUM_X_DIRECTION dir, + int barIndex = 0 // + ) + { + // + double result = 0; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (!HasDirection(dir)) + { + return result; + } + + // + int index = barIndex; + bool isBullish = IsBullish(dir); + + // + bool canContinue = true; + while (canContinue) + { + // + double iStr = GetSTR(index); + double iState = GetSTRState(index); + + // + canContinue = + isBullish + ? iState < 0 + : iState > 0; + if (!canContinue) + { + // + result = iStr; + break; + } + + // + index++; + } + + // + return result; + } + + // + void Free() override + { + Cleanup(10); + } + + // + bool GetConditions( + X121XSTRConditions &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 ... + + // + CopyATR( + zIndex, + loopback, + conditions.atrBuffer // + ); + + // + CopySTR( + zIndex, + loopback, + conditions.strBuffer // + ); + + // + CopySTRState( + zIndex, + loopback, + conditions.strStateBuffer // + ); + + // + CopySTRPrice( + zIndex, + loopback, + conditions.strPriceBuffer // + ); + + // + CopySTRUp( + zIndex, + loopback, + conditions.strUpBuffer // + ); + + // + CopySTRDown( + zIndex, + loopback, + conditions.strDownBuffer // + ); + + // + // Conditions ... + + // + int cIDX = 1; + int pIDX = cIDX + 1; + + // + bool isStrBullish = strStateBuffer[cIDX] > 0; + bool isStrBullishPrev = strStateBuffer[pIDX] > 0; + + // + bool isStrBearish = strStateBuffer[cIDX] < 0; + bool isStrBearishPrev = strStateBuffer[pIDX] < 0; + + // + bool isStrSwitchedToBullish = isStrBullish && + !isStrBullishPrev; + bool isStrSwitchedToBearish = isStrBearish && + !isStrBearishPrev; + + // + conditions.isStrBullish = isStrBullish; + conditions.isStrBearish = isStrBearish; + conditions.isStrSwitchedToBullish = isStrSwitchedToBullish; + conditions.isStrSwitchedToBearish = isStrSwitchedToBearish; + + // + Cleanup(); + + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + + // + return result; + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + X121XSTRInputs mInputs; // Inputs ... + + // + // Buffers ... + double strBuffer[]; + double atrBuffer[]; + double strPriceBuffer[]; + double strUpBuffer[]; + double strDownBuffer[]; + double strStateBuffer[]; + + // + void Calculate( + int maxRequiredBars = 100 // + ) + { + // + // Buffers ... + + // + // STR ... + CopyBuffer( + mHandler, + X121_XSTR_LINE, + 0, + maxRequiredBars, + strBuffer + // + ); + + // + // State ... + CopyBuffer( + mHandler, + X121_XSTR_STATE_LINE, + 0, + maxRequiredBars, + strStateBuffer + // + ); + + // + // Price ... + CopyBuffer( + mHandler, + X121_XSTR_PRICE_LINE, + 0, + maxRequiredBars, + strPriceBuffer + // + ); + + // + // Up ... + CopyBuffer( + mHandler, + X121_XSTR_UP_LINE, + 0, + maxRequiredBars, + strUpBuffer + // + ); + + // + // STR ... + CopyBuffer( + mHandler, + X121_XSTR_DOWN_LINE, + 0, + maxRequiredBars, + strDownBuffer + // + ); + + // + // ATR ... + + // + CopyBuffer( + mHandler, + X121_XSTR_ATR_LINE, + 0, + maxRequiredBars, + atrBuffer + // + ); + } + + // + void Cleanup( + int maxAllowed = 100 // + ) + { + // + CleanupArray( + strBuffer, + maxAllowed // + ); + + // + CleanupArray( + atrBuffer, + maxAllowed // + ); + + // + CleanupArray( + strPriceBuffer, + maxAllowed // + ); + + // + CleanupArray( + strUpBuffer, + maxAllowed // + ); + + // + CleanupArray( + strDownBuffer, + maxAllowed // + ); + + // + CleanupArray( + strStateBuffer, + maxAllowed // + ); + + // + } + + // +}; + +// +// Tools ... \ No newline at end of file diff --git a/BKPS/14031218/Helpers/x-saherelm.x121.xtrend.helper.mq5 b/BKPS/14031218/Helpers/x-saherelm.x121.xtrend.helper.mq5 new file mode 100644 index 0000000..1f5a7aa --- /dev/null +++ b/BKPS/14031218/Helpers/x-saherelm.x121.xtrend.helper.mq5 @@ -0,0 +1,1279 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XCX121XTRENDHelper +// 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 ... + +// +// Definitions ... +enum ENUM_X121_XTREND_BUFFERS +{ + // + X121_XTREND_UP_LINE = 0, + X121_XTREND_DOWN_LINE = 1, + X121_XTREND_MA_LINE = 2, + X121_XTREND_ADX_LINE = 3, + X121_XTREND_ADX_P_LINE = 4, + X121_XTREND_ADX_M_LINE = 5, + X121_XTREND_UP_T_LINE = 6, + X121_XTREND_DOWN_T_LINE = 7, +}; + +// +// Input Models ... +struct X121XTRENDInputs +{ + // + // Props ... + // + // Market ... + ENUM_APPLIED_PRICE trendPriceType; // Detect Trend Price Type + + // + // MA Detection ... + int maLength; // MA Length + ENUM_MA_METHOD maMethod; // MA Method + ENUM_APPLIED_PRICE maAppliedTo; // MA Applied To + + // + // ADX Detection ... + int adxLength; // ADX Length + double adxThreshold; // ADX Threshold for Strong Trends + + // + // Presentation ... + + // + int startCalculationForLastBars; // Calculate Last n Bars + int upTrendArrowCode; // Up Trend Arrow Code + int downTrendArrowCode; // Down Trend Arrow Code + + // + bool showOnlyTrendStart; // Show Only Trend Start + bool showUpTrend; // Show Up Trend + bool showDownTrend; // Show Down Trend + + // + // Constructor(s) ... + X121XTRENDInputs() + { + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + trendPriceType = PRICE_CLOSE; + maLength = 50; + maMethod = MODE_EMA; + maAppliedTo = PRICE_CLOSE; + adxLength = 14; + adxThreshold = 25; + startCalculationForLastBars = 1000; + upTrendArrowCode = 233; + downTrendArrowCode = 234; + showOnlyTrendStart = false; + showUpTrend = false; + showDownTrend = false; + + // + ZeroMemory(this); + } + + // + // Default ... + void Default() + { + // + trendPriceType = PRICE_CLOSE; + maLength = 50; + maMethod = MODE_EMA; + maAppliedTo = PRICE_CLOSE; + adxLength = 14; + adxThreshold = 25; + startCalculationForLastBars = 1000; + upTrendArrowCode = 233; + downTrendArrowCode = 234; + showOnlyTrendStart = true; + showUpTrend = true; + showDownTrend = true; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + // MA ... + maLength > 0 && + // + // ADX ... + adxLength > 0 && + adxThreshold > 0 + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(maLength, adxLength); + + // + return result; + } +}; + +// +// Conditions ... +struct X121XTRENDConditions +{ + // + // Common ... + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + // Buffers ... + double upTrendBuffer[]; + double downTrendBuffer[]; + double maBuffer[]; + double adxBuffer[]; + double adxPBuffer[]; + double adxMBuffer[]; + double upTBuffer[]; + double downTBuffer[]; + + // + // Conditions ... + + // + bool isTrendBullish; + bool isTrendBearish; + + // + bool isTrendSwitchedToBullish; + bool isTrendSwitchedToBearish; + + // + // bool isCloseLower + + // + // Constructor ... + X121XTRENDConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + // Commons ... + symbol = NULL; + period = NULL; + time = NULL; + + // + // Buffers ... + + // + Clean(upTrendBuffer); + Clean(downTrendBuffer); + Clean(maBuffer); + Clean(adxBuffer); + Clean(adxPBuffer); + Clean(adxMBuffer); + Clean(upTBuffer); + Clean(downTBuffer); + + // + ArraySetAsSeries(upTrendBuffer, true); + ArraySetAsSeries(downTrendBuffer, true); + ArraySetAsSeries(maBuffer, true); + ArraySetAsSeries(adxBuffer, true); + ArraySetAsSeries(adxPBuffer, true); + ArraySetAsSeries(adxMBuffer, true); + ArraySetAsSeries(upTBuffer, true); + ArraySetAsSeries(downTBuffer, true); + + // + // Conditions ... + + // + isTrendBullish = false; + isTrendBearish = false; + + // + isTrendSwitchedToBullish = false; + isTrendSwitchedToBearish = false; + + // + ZeroMemory(this); + } + + /** + * Generate Conditions Scores ... + * + * @param bullishScore: Double, Directional Scores Reference ... + * @param bearishScore: Double, Directional Scores Reference ... + */ + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + // + bullishScore = 0; + bearishScore = 0; + + // + // 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 // + ); + + // + string conditionsStr = + // + ToString("isTrendBullish", isTrendBullish, ignoreFalseConditions, separator) + + ToString("isTrendBearish", isTrendBearish, ignoreFalseConditions, separator) + + ToString("isTrendSwitchedToBullish", isTrendSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isTrendSwitchedToBearish", isTrendSwitchedToBearish, ignoreFalseConditions, separator) + + // + "" + // + ; + + // + result = + // + "[" + GetTag() + "]" + separator + + (onlyConditions + ? "" + : commonStr) + + (!includeScores + ? "" + : scoresStr) + + " " + separator + + (onlyCommons + ? "" + : conditionsStr) + + "" + // + ; + + // + return result; + } + + /** + * Retrieve nique Tag Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + return GetTypeName(this); + } + + // +}; + +// +// Class ... +class XCX121XTRENDHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructors ... + XCX121XTRENDHelper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCX121XTRENDHelper() + { + // + mInputs.Clean(); + + // + Clean(upTrendBuffer); + Clean(downTrendBuffer); + Clean(maBuffer); + Clean(adxBuffer); + Clean(adxPBuffer); + Clean(adxMBuffer); + Clean(upTBuffer); + Clean(downTBuffer); + } + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + X121XTRENDInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + ArraySetAsSeries(upTrendBuffer, true); + ArraySetAsSeries(downTrendBuffer, true); + ArraySetAsSeries(maBuffer, true); + ArraySetAsSeries(adxBuffer, true); + ArraySetAsSeries(adxPBuffer, true); + ArraySetAsSeries(adxMBuffer, true); + ArraySetAsSeries(upTBuffer, true); + ArraySetAsSeries(downTBuffer, true); + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.xtrend", + // + // Inputs ... + // + // Market ... + "", + mInputs.trendPriceType, + // + // MA Detection ... + "", + mInputs.maLength, + mInputs.maMethod, + mInputs.maAppliedTo, + // + // ADX Detection ... + "", + mInputs.adxLength, + mInputs.adxThreshold, + // + // Presentation ... + "", + mInputs.startCalculationForLastBars, + mInputs.upTrendArrowCode, + mInputs.downTrendArrowCode, + mInputs.showOnlyTrendStart, + mInputs.showUpTrend, + mInputs.showDownTrend + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + X121XTRENDInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + X121XTRENDInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Readers ... + + // + // Up Trend ... + + // + double GetUpTrend( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(upTrendBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return upTrendBuffer[barIndex]; + } + + // + int CopyUpTrend( + 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, + upTrendBuffer, + buffer, + forceClean + // + ); + } + + // + // Down Trend ... + + // + double GetDownTrend( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(downTrendBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return downTrendBuffer[barIndex]; + } + + // + int CopyDownTrend( + 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, + downTrendBuffer, + buffer, + forceClean + // + ); + } + + // + // Ma ... + + // + double GetMA( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(downTrendBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return downTrendBuffer[barIndex]; + } + + // + int CopyMA( + 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, + downTrendBuffer, + buffer, + forceClean + // + ); + } + + // + // ADX ... + + // + double GetADX( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(adxBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return adxBuffer[barIndex]; + } + + // + int CopyADX( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + adxBuffer, + buffer, + forceClean + // + ); + } + + // + // ADX P... + + // + double GetADXP( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(adxPBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return adxPBuffer[barIndex]; + } + + // + int CopyADXP( + int start, // Start + int count, // Number of Items for read + double &buffer[], // Dest Buffer + bool forceClean = true // Force To Clean buffer + ) + { + // + // Update Calculations ... + Calculate(); + + // + // Copy Items ... + return Copy( + start, + count, + adxPBuffer, + buffer, + forceClean + // + ); + } + + // + // ADX M ... + + // + double GetADXM( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(adxMBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return adxMBuffer[barIndex]; + } + + // + int CopyADXM( + 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, + adxMBuffer, + buffer, + forceClean + // + ); + } + + // + // Up Trend ... + + // + double GetUpT( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(upTBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return upTBuffer[barIndex]; + } + + // + int CopyUpT( + 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, + upTBuffer, + buffer, + forceClean + // + ); + } + + // + // Down Trend ... + + // + double GetDownT( + int barIndex // Bar Index + ) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + Calculate(); + + // + int count = ArraySize(downTBuffer); + if (barIndex >= count) + { + barIndex = count - 1; + } + + // + return downTBuffer[barIndex]; + } + + // + int CopyDownT( + 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, + downTBuffer, + buffer, + forceClean + // + ); + } + + // + void Free() override + { + Cleanup(10); + } + + // + bool GetConditions( + X121XTRENDConditions &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 ... + + // + CopyUpTrend( + zIndex, + loopback, + conditions.upTrendBuffer // + ); + + // + CopyDownTrend( + zIndex, + loopback, + conditions.downTrendBuffer // + ); + + // + CopyMA( + zIndex, + loopback, + conditions.maBuffer // + ); + + // + CopyADX( + zIndex, + loopback, + conditions.adxBuffer // + ); + + // + CopyADXP( + zIndex, + loopback, + conditions.adxPBuffer // + ); + + // + CopyADXM( + zIndex, + loopback, + conditions.adxMBuffer // + ); + + // + CopyUpT( + zIndex, + loopback, + conditions.upTBuffer // + ); + + // + CopyDownT( + zIndex, + loopback, + conditions.downTBuffer // + ); + + // + // Conditions ... + + // + int cIDX = 1; + int pIDX = cIDX + 1; + + // + bool isTrendBullish = upTBuffer[cIDX] != 0; + bool isTrendBullishPrev = upTBuffer[pIDX] != 0; + + // + bool isTrendBearish = downTBuffer[cIDX] != 0; + bool isTrendBearishPrev = downTBuffer[pIDX] != 0; + + // + bool isTrendSwitchedToBullish = isTrendBullish && + !isTrendBullishPrev; + bool isTrendSwitchedToBearish = isTrendBearish && + !isTrendBearishPrev; + + // + conditions.isTrendBullish = isTrendBullish; + conditions.isTrendBearish = isTrendBearish; + conditions.isTrendSwitchedToBullish = isTrendSwitchedToBullish; + conditions.isTrendSwitchedToBearish = isTrendSwitchedToBearish; + + // + Cleanup(); + + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + + // + return result; + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + X121XTRENDInputs mInputs; // Inputs ... + + // + // Buffers ... + double upTrendBuffer[]; + double downTrendBuffer[]; + double maBuffer[]; + double adxBuffer[]; + double adxPBuffer[]; + double adxMBuffer[]; + double upTBuffer[]; + double downTBuffer[]; + + // + void Calculate( + int maxRequiredBars = 100 // + ) + { + // + // Buffers ... + + // + // Up Trend ... + CopyBuffer( + mHandler, + X121_XTREND_UP_LINE, + 0, + maxRequiredBars, + upTrendBuffer + // + ); + + // + // Down Trend ... + CopyBuffer( + mHandler, + X121_XTREND_DOWN_LINE, + 0, + maxRequiredBars, + downTrendBuffer + // + ); + + // + // MA ... + CopyBuffer( + mHandler, + X121_XTREND_MA_LINE, + 0, + maxRequiredBars, + maBuffer + // + ); + + // + // ADX ... + CopyBuffer( + mHandler, + X121_XTREND_ADX_LINE, + 0, + maxRequiredBars, + adxBuffer + // + ); + + // + // ADX P ... + CopyBuffer( + mHandler, + X121_XTREND_ADX_P_LINE, + 0, + maxRequiredBars, + adxPBuffer + // + ); + + // + // ADX M ... + CopyBuffer( + mHandler, + X121_XTREND_ADX_M_LINE, + 0, + maxRequiredBars, + adxMBuffer + // + ); + + // + // Up T ... + CopyBuffer( + mHandler, + X121_XTREND_UP_T_LINE, + 0, + maxRequiredBars, + upTBuffer + // + ); + + // + // Down T ... + CopyBuffer( + mHandler, + X121_XTREND_DOWN_T_LINE, + 0, + maxRequiredBars, + downTBuffer + // + ); + } + + // + void Cleanup( + int maxAllowed = 100 // + ) + { + // + CleanupArray( + upTrendBuffer, + maxAllowed // + ); + + // + CleanupArray( + downTrendBuffer, + maxAllowed // + ); + + // + CleanupArray( + maBuffer, + maxAllowed // + ); + + // + CleanupArray( + adxBuffer, + maxAllowed // + ); + + // + CleanupArray( + adxPBuffer, + maxAllowed // + ); + + // + CleanupArray( + adxMBuffer, + maxAllowed // + ); + + // + CleanupArray( + upTBuffer, + maxAllowed // + ); + + // + CleanupArray( + downTBuffer, + maxAllowed // + ); + + // + } + + // +}; + +// +// Tools ... \ No newline at end of file diff --git a/BKPS/14031218/Helpers/x-saherelm.x121.xvwap.helper.mq5 b/BKPS/14031218/Helpers/x-saherelm.x121.xvwap.helper.mq5 new file mode 100644 index 0000000..4f7a4ef --- /dev/null +++ b/BKPS/14031218/Helpers/x-saherelm.x121.xvwap.helper.mq5 @@ -0,0 +1,1508 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XCX121XVWAPHelper +// 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 ... + +// +// Definitions ... +enum ENUM_X121_XVWAP_BUFFERS +{ + // + X121_XVWAP_FAST_LINE = 0, + X121_XVWAP_FAST_STATE_LINE = 8, + X121_XVWAP_MID_LINE = 2, + X121_XVWAP_MID_STATE_LINE = 9, + X121_XVWAP_SLOW_LINE = 4, + X121_XVWAP_SLOW_STATE_LINE = 10, + X121_XVWAP_VOLUME_LINE = 6, + X121_XVWAP_PRICE_LINE = 7, +}; + +// +enum ENUM_XVWAP_STATES +{ + XVWAP_STATE_BULLISH = 1, + XVWAP_STATE_BEARISH = 2, + XVWAP_STATE_NEUTURAL = 3, +}; + +// +// Input Models ... +struct X121XVWAPInputs +{ + // + // Props ... + + int vwapFastLength; // Fast Length + int vwapMidLength; // Mid Length + int vwapSlowLength; // Slow Length + ENUM_APPLIED_PRICE vwapAppliedTo; // Applied To + + // + int startCalculationForLastBars; // Calculate Last n Bars + + // + bool showVWapFast; // Show VWap Fast + bool showVWapMedium; // Show VWap Medium + bool showVWapSlow; // Show VWap Slow + + // + // Constructor(s) ... + X121XVWAPInputs() + { + // + Clean(); + } + + // + // Tools ... + + // + // Clean ... + void Clean() + { + // + vwapFastLength = 0; + vwapMidLength = 0; + vwapSlowLength = 0; + vwapAppliedTo = PRICE_CLOSE; + + // + startCalculationForLastBars = 0; + + // + showVWapFast = false; + showVWapMedium = false; + showVWapSlow = false; + + // + ZeroMemory(this); + } + + // + // Default ... + void Default() + { + // + vwapFastLength = 20; + vwapMidLength = 50; + vwapSlowLength = 100; + vwapAppliedTo = PRICE_CLOSE; + + // + startCalculationForLastBars = 1000; + + // + showVWapFast = true; + showVWapMedium = true; + showVWapSlow = true; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + vwapFastLength > 2 && + vwapMidLength > vwapFastLength && + vwapSlowLength > vwapMidLength + // + ; + + // + return result; + } + + // + // Retrieve MAx Length ... + int Max() + { + // + int result = 0; + + // + result = MathMax(vwapFastLength, vwapMidLength); + result = MathMax(result, vwapSlowLength); + + // + return result; + } +}; + +// +// Conditions ... +struct X121XVWAPConditions +{ + // + // Common ... + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + // Buffers ... + double vwapFastBuffer[]; + double vwapMidBuffer[]; + double vwapSlowBuffer[]; + double vwapVolumeBuffer[]; + double vwapPriceBuffer[]; + double vwapFastStateBuffer[]; + double vwapMidStateBuffer[]; + double vwapSlowStateBuffer[]; + + // + // Conditions ... + + // + 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; + + // + // Constructor ... + X121XVWAPConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + // Commons ... + symbol = NULL; + period = NULL; + time = NULL; + + // + // Buffers ... + + // + Clean(vwapFastBuffer); + Clean(vwapMidBuffer); + Clean(vwapSlowBuffer); + Clean(vwapVolumeBuffer); + Clean(vwapPriceBuffer); + Clean(vwapFastStateBuffer); + Clean(vwapMidStateBuffer); + Clean(vwapSlowStateBuffer); + + // + ArraySetAsSeries(vwapFastBuffer, true); + ArraySetAsSeries(vwapMidBuffer, true); + ArraySetAsSeries(vwapSlowBuffer, true); + ArraySetAsSeries(vwapVolumeBuffer, true); + ArraySetAsSeries(vwapPriceBuffer, true); + ArraySetAsSeries(vwapFastStateBuffer, true); + ArraySetAsSeries(vwapMidStateBuffer, true); + ArraySetAsSeries(vwapSlowStateBuffer, true); + + // + // Conditions ... + + // + 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; + + // + ZeroMemory(this); + } + + /** + * Generate Conditions Scores ... + * + * @param bullishScore: Double, Directional Scores Reference ... + * @param bearishScore: Double, Directional Scores Reference ... + */ + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + // + bullishScore = 0; + bearishScore = 0; + + // + // 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 // + ); + + // + string conditionsStr = + // + 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) + + // + "" + // + ; + + // + result = + // + "[" + GetTag() + "]" + separator + + (onlyConditions + ? "" + : commonStr) + + (!includeScores + ? "" + : scoresStr) + + " " + separator + + (onlyCommons + ? "" + : conditionsStr) + + "" + // + ; + + // + return result; + } + + /** + * Retrieve nique Tag Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + return GetTypeName(this); + } + + // +}; + +// +// Class ... +class XCX121XVWAPHelper : public XCBaseHelper +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructors ... + XCX121XVWAPHelper() + : XCBaseHelper(_Symbol, _Period) + { + } + + // + // Deconstructor ... + ~XCX121XVWAPHelper() + { + // + mInputs.Clean(); + + // + Clean(vwapFastBuffer); + Clean(vwapMidBuffer); + Clean(vwapSlowBuffer); + Clean(vwapVolumeBuffer); + Clean(vwapPriceBuffer); + Clean(vwapFastStateBuffer); + Clean(vwapMidStateBuffer); + Clean(vwapSlowStateBuffer); + } + + // + // Tools ... + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + X121XVWAPInputs &inputs // Inputs + ) + { + // + bool result = false; + + // + mSymbol = symbol; + mPeriod = period; + + // + result = inputs.IsValid(); + if (!result) + { + return result; + } + + // + ArraySetAsSeries(vwapFastBuffer, true); + ArraySetAsSeries(vwapMidBuffer, true); + ArraySetAsSeries(vwapSlowBuffer, true); + ArraySetAsSeries(vwapVolumeBuffer, true); + ArraySetAsSeries(vwapPriceBuffer, true); + ArraySetAsSeries(vwapFastStateBuffer, true); + ArraySetAsSeries(vwapMidStateBuffer, true); + ArraySetAsSeries(vwapSlowStateBuffer, true); + + // + mInputs = inputs; + + // + mHandler = iCustom( + mSymbol, + mPeriod, + "x-saherelm.x121.xvwap", + // + // Inputs ... + // + // Market ... + "", + mInputs.vwapFastLength, + mInputs.vwapMidLength, + mInputs.vwapSlowLength, + mInputs.vwapAppliedTo, + // + // Presentation ... + "", + // + mInputs.startCalculationForLastBars, + // + mInputs.showVWapFast, + mInputs.showVWapMedium, + mInputs.showVWapSlow + // + ); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + return result; + } + + // + // Inputs ... + + // + X121XVWAPInputs GetInputs() + { + return mInputs; + } + + // + bool SetInputs( + X121XVWAPInputs &inputs // Configs + ) + { + // + return Init( + mSymbol, + mPeriod, + inputs + // + ); + } + + // + // Readers ... + + // + 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; + } + + // + void Free() override + { + Cleanup(10); + } + + // + bool GetConditions( + X121XVWAPConditions &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 ... + + // + 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 // + ); + + // + // Conditions ... + + // + int cIDX = 1; + int pIDX = cIDX + 1; + + // + // SAR ... + + // + 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; + + // + 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; + + // + Cleanup(); + + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + + // + return result; + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + X121XVWAPInputs mInputs; // Inputs ... + + // + // Buffers ... + double vwapFastBuffer[]; + double vwapMidBuffer[]; + double vwapSlowBuffer[]; + double vwapVolumeBuffer[]; + double vwapPriceBuffer[]; + double vwapFastStateBuffer[]; + double vwapMidStateBuffer[]; + double vwapSlowStateBuffer[]; + + // + void Calculate( + int maxRequiredBars = 100 // + ) + { + // + // Buffers ... + + // + // FAST ... + CopyBuffer( + mHandler, + X121_XVWAP_FAST_LINE, + 0, + maxRequiredBars, + vwapFastBuffer + // + ); + + // + // FAST STATE ... + CopyBuffer( + mHandler, + X121_XVWAP_FAST_STATE_LINE, + 0, + maxRequiredBars, + vwapFastStateBuffer + // + ); + + // + // MID ... + CopyBuffer( + mHandler, + X121_XVWAP_MID_LINE, + 0, + maxRequiredBars, + vwapMidBuffer + // + ); + + // + // MID STATE ... + CopyBuffer( + mHandler, + X121_XVWAP_MID_STATE_LINE, + 0, + maxRequiredBars, + vwapMidStateBuffer + // + ); + + // + // SLOW ... + CopyBuffer( + mHandler, + X121_XVWAP_SLOW_LINE, + 0, + maxRequiredBars, + vwapSlowBuffer + // + ); + + // + // SLOW STATE ... + CopyBuffer( + mHandler, + X121_XVWAP_SLOW_STATE_LINE, + 0, + maxRequiredBars, + vwapSlowStateBuffer + // + ); + + // + // VOLUME ... + CopyBuffer( + mHandler, + X121_XVWAP_VOLUME_LINE, + 0, + maxRequiredBars, + vwapVolumeBuffer + // + ); + + // + // PRICE ... + CopyBuffer( + mHandler, + X121_XVWAP_PRICE_LINE, + 0, + maxRequiredBars, + vwapPriceBuffer + // + ); + } + + // + void Cleanup( + int maxAllowed = 100 // + ) + { + // + CleanupArray( + vwapFastBuffer, + maxAllowed // + ); + + // + CleanupArray( + vwapMidBuffer, + maxAllowed // + ); + + // + CleanupArray( + vwapSlowBuffer, + maxAllowed // + ); + + // + CleanupArray( + vwapVolumeBuffer, + maxAllowed // + ); + + // + CleanupArray( + vwapPriceBuffer, + maxAllowed // + ); + + // + CleanupArray( + vwapFastStateBuffer, + maxAllowed // + ); + + // + CleanupArray( + vwapMidStateBuffer, + maxAllowed // + ); + + // + CleanupArray( + vwapSlowStateBuffer, + maxAllowed // + ); + + // + } + + // +}; + +// +// Tools ... \ No newline at end of file diff --git a/BKPS/14031218/Indicators/x-saherelm.x121.x3ma.ex5 b/BKPS/14031218/Indicators/x-saherelm.x121.x3ma.ex5 new file mode 100644 index 0000000..9aace04 Binary files /dev/null and b/BKPS/14031218/Indicators/x-saherelm.x121.x3ma.ex5 differ diff --git a/BKPS/14031218/Indicators/x-saherelm.x121.x3ma.mq5 b/BKPS/14031218/Indicators/x-saherelm.x121.x3ma.mq5 new file mode 100644 index 0000000..a16b3ce --- /dev/null +++ b/BKPS/14031218/Indicators/x-saherelm.x121.x3ma.mq5 @@ -0,0 +1,658 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XWZ +// Description: XWZ ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121 XWZ Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121_X3MA" + +// +// Imports ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +// Market ... +input group "Market"; +input int fastMALength = 20; // Fast MA Length +input int midMALength = 50; // Mid MA Length +input int slowMALength = 200; // Slow MA Length +input ENUM_MA_METHOD maMethod = MODE_EMA; // MA Method +input ENUM_APPLIED_PRICE maAppliedTo = PRICE_CLOSE; // Applied To + +// +// Presentation ... +input group "Presentation"; + +// +input int startCalculationForLastBars = 1000; // Calculate Last n Bars +input bool showMaFast = true; // Show Fast MA +input bool showMaMid = true; // Show Mid MA +input bool showMaSlow = true; // Show Slow MA + +// +// Buffers ... + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#property indicator_chart_window + +// +#property indicator_buffers 9 +#property indicator_plots 3 + +// +// Plot Buffers ... + +// +// FAST ... +#define maFastBufferIndex 0 +double maFastBuffer[]; + +#define maFastColorBufferIndex 1 +double maFastColorBuffer[]; + +// +#define maFastPlotBufferIndex 0 +#property indicator_label1 "X121 MAF" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 CLR_NONE, clrAqua, clrMagenta, clrGray +#property indicator_style1 STYLE_SOLID +#property indicator_width1 2 + +// +// MID ... +#define maMidBufferIndex 2 +double maMidBuffer[]; + +#define maMidColorBufferIndex 3 +double maMidColorBuffer[]; + +// +#define maMidPlotBufferIndex 1 +#property indicator_label2 "X121 MAM" +#property indicator_type2 DRAW_COLOR_LINE +#property indicator_color2 CLR_NONE, clrGreen, clrRed, clrGray +#property indicator_style2 STYLE_SOLID +#property indicator_width2 2 + +// +// SLOW ... +#define maSlowBufferIndex 4 +double maSlowBuffer[]; + +#define maSlowColorBufferIndex 5 +double maSlowColorBuffer[]; + +// +#define maSlowPlotBufferIndex 2 +#property indicator_label3 "X121 MAS" +#property indicator_type3 DRAW_COLOR_LINE +#property indicator_color3 CLR_NONE, clrSteelBlue, clrDarkRed, clrGray +#property indicator_style3 STYLE_SOLID +#property indicator_width3 2 + +// +// Data Buffers ... + +// +int mLastBufferIndex = 5; + +// +// Fast State ... +#define maFastStateBufferIndex mLastBufferIndex + 1 +double maFastStateBuffer[]; + +// +// Mid State ... +#define maMidStateBufferIndex mLastBufferIndex + 2 +double maMidStateBuffer[]; + +// +// Slow State ... +#define maSlowStateBufferIndex mLastBufferIndex + 3 +double maSlowStateBuffer[]; + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +int maFastHandler = INVALID_HANDLE; +int maMidHandler = INVALID_HANDLE; +int maSlowHandler = INVALID_HANDLE; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + + // + // Fast MA ... + maFastHandler = iMA( + _Symbol, + _Period, + fastMALength, + 0, + maMethod, + maAppliedTo // + ); + bool isInited = maFastHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // Mid MA ... + maMidHandler = iMA( + _Symbol, + _Period, + midMALength, + 0, + maMethod, + maAppliedTo // + ); + isInited = maMidHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // Slow MA ... + maSlowHandler = iMA( + _Symbol, + _Period, + slowMALength, + 0, + maMethod, + maAppliedTo // + ); + isInited = maSlowHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + IndicatorSetInteger(INDICATOR_DIGITS, 2); + + // + // 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(maFastHandler); + IndicatorRelease(maMidHandler); + IndicatorRelease(maSlowHandler); +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // Validate Calculated Bars ... + + // + // Fast MA ... + int maFastCalculatedBars = BarsCalculated(maFastHandler); + + // + // Mid MA ... + int maMidCalculatedBars = BarsCalculated(maMidHandler); + + // + // Slow MA ... + int maSlowCalculatedBars = BarsCalculated(maSlowHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // Fast MA ... + maFastCalculatedBars >= maxLength && + // + // Slow MA ... + maMidCalculatedBars >= maxLength && + // + // Slow MA ... + maSlowCalculatedBars >= maxLength + // + ; + if (!isPassedRequiredCalculatedBars) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + + // + // Fast MA ... + int copiedFastMas = CopyBuffer(maFastHandler, 0, 0, limit, maFastBuffer); + + // + // Mid MA ... + int copiedMidMas = CopyBuffer(maMidHandler, 0, 0, limit, maMidBuffer); + + // + // Slow MA ... + int copiedSlowMas = CopyBuffer(maSlowHandler, 0, 0, limit, maSlowBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // Fast MA ... + copiedFastMas > 0 && + // + // Mid MA ... + copiedMidMas > 0 && + // + // Slow MA ... + copiedSlowMas > 0 + // + ; + if (!isPassedRequiredCopiedItems) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + // + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + result = fastMALength > 0 && + midMALength > 0 && + slowMALength > 0 && + midMALength > fastMALength && + slowMALength > midMALength; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(fastMALength, midMALength); + result = MathMax(result, slowMALength); + + // + return result; +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + + // + // Fast ... + ArraySetAsSeries(maFastBuffer, true); + ArraySetAsSeries(maFastColorBuffer, true); + SetIndexBuffer(maFastBufferIndex, maFastBuffer, INDICATOR_DATA); + SetIndexBuffer(maFastColorBufferIndex, maFastColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Mid ... + ArraySetAsSeries(maMidBuffer, true); + ArraySetAsSeries(maMidColorBuffer, true); + SetIndexBuffer(maMidBufferIndex, maMidBuffer, INDICATOR_DATA); + SetIndexBuffer(maMidColorBufferIndex, maMidColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Slow ... + ArraySetAsSeries(maSlowBuffer, true); + ArraySetAsSeries(maSlowColorBuffer, true); + SetIndexBuffer(maSlowBufferIndex, maSlowBuffer, INDICATOR_DATA); + SetIndexBuffer(maSlowColorBufferIndex, maSlowColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Data Buffers ... + + // + // Fast State ... + ArraySetAsSeries(maFastStateBuffer, true); + SetIndexBuffer(maFastStateBufferIndex, maFastStateBuffer, INDICATOR_CALCULATIONS); + + // + // Mid State ... + ArraySetAsSeries(maMidStateBuffer, true); + SetIndexBuffer(maMidStateBufferIndex, maMidStateBuffer, INDICATOR_CALCULATIONS); + + // + // Slow State ... + ArraySetAsSeries(maSlowStateBuffer, true); + SetIndexBuffer(maSlowStateBufferIndex, maSlowStateBuffer, INDICATOR_CALCULATIONS); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateBuffers( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + // + // bool canCalculate = true; + bool canCalculate = + barsLimit == 0 || + bar_index <= barsLimit; + if (canCalculate) + { + // + CalculateValues( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + else + { + FillBuffersZero(bar_index); + } +} + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + maMidBuffer[barIndex] = 0; + maFastBuffer[barIndex] = 0; + maSlowBuffer[barIndex] = 0; + + // + maFastColorBuffer[barIndex] = hideColorIDX; + maMidColorBuffer[barIndex] = hideColorIDX; + maSlowColorBuffer[barIndex] = hideColorIDX; + maFastStateBuffer[barIndex] = hideColorIDX; + maMidStateBuffer[barIndex] = hideColorIDX; + maSlowStateBuffer[barIndex] = hideColorIDX; +} + +/** + * Calculate Vales ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateValues( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // Implement Colorify Mechanism ... + + // + // Calculate Applied Price ... + double iPrice = GetAppliedPrice( + maAppliedTo, + open, + high, + low, + close, + bar_index // + ); + + // + double iFast = maFastBuffer[bar_index]; + double iMid = maMidBuffer[bar_index]; + double iSlow = maSlowBuffer[bar_index]; + + // + double iFastState = iPrice > iFast + ? bullishColorIDX + : iPrice < iFast + ? bearishColorIDX + : neuturalColorIDX; + double iMidState = iPrice > iMid + ? bullishColorIDX + : iPrice < iMid + ? bearishColorIDX + : neuturalColorIDX; + double iSlowState = iPrice > iSlow + ? bullishColorIDX + : iPrice < iSlow + ? bearishColorIDX + : neuturalColorIDX; + + // + maFastColorBuffer[bar_index] = + showMaFast + ? iFastState + : hideColorIDX; + maFastStateBuffer[bar_index] = iFastState; + + // + maMidColorBuffer[bar_index] = + showMaMid + ? iMidState + : hideColorIDX; + maMidStateBuffer[bar_index] = iMidState; + + // + maSlowColorBuffer[bar_index] = + showMaSlow + ? iSlowState + : hideColorIDX; + maSlowStateBuffer[bar_index] = iSlowState; +} + +// diff --git a/BKPS/14031218/Indicators/x-saherelm.x121.xatr.ex5 b/BKPS/14031218/Indicators/x-saherelm.x121.xatr.ex5 new file mode 100644 index 0000000..79117c0 Binary files /dev/null and b/BKPS/14031218/Indicators/x-saherelm.x121.xatr.ex5 differ diff --git a/BKPS/14031218/Indicators/x-saherelm.x121.xatr.mq5 b/BKPS/14031218/Indicators/x-saherelm.x121.xatr.mq5 new file mode 100644 index 0000000..d44a578 --- /dev/null +++ b/BKPS/14031218/Indicators/x-saherelm.x121.xatr.mq5 @@ -0,0 +1,648 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XATR +// Description: XATR ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121 XATR Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121 XATR" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +// Market ... +input group "Market"; + +// +input group "RSI Detection"; +input int rsiLength = 14; // Length +input ENUM_APPLIED_PRICE rsiAppliedTo = PRICE_CLOSE; // Applied To + +// +input group "ATR Detection"; +input int atrLength = 14; // Length +input double atrMultiplier = 1; // Multiplier +input ENUM_APPLIED_PRICE atrUpperAppliedTo = PRICE_HIGH; // Upper Zone Applied To +input ENUM_APPLIED_PRICE atrLowerAppliedTo = PRICE_LOW; // Lower Zone Applied To +input ENUM_X_MA_METHOD atrSmoothingMode = X_MA_MODE_EMA; // Smoothing Method + +// +input group "Presentation"; + +// +input int startCalculationForLastBars = 1000; // Calculate Last n Bars + +// +input bool showAtrUpper = true; // Show Upper Zone +input bool showAtrLower = true; // Show Lower Zone + +// +// Buffers ... + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#property indicator_chart_window + +// +#property indicator_buffers 6 +#property indicator_plots 2 + +// +// ATR ... + +// +// Upper ... + +// +#define atrUpperBufferIndex 0 +double atrUpperBuffer[]; + +#property indicator_label1 "X121 ATRU" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrYellow +#property indicator_style1 STYLE_SOLID +#property indicator_width1 2 + +// +// Lower ... + +// +#define atrLowerBufferIndex 1 +double atrLowerBuffer[]; + +#property indicator_label2 "X121 ATRL" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrYellow +#property indicator_style2 STYLE_SOLID +#property indicator_width2 2 + +// +// Data Buffers ... + +// +int mLastBufferIndex = 1; + +// +// ATR ... + +#define atrBufferIndex mLastBufferIndex + 1 +double atrBuffer[]; + +#define atrUpperRawBufferIndex mLastBufferIndex + 2 +double atrUpperRawBuffer[]; + +#define atrLowerRawBufferIndex mLastBufferIndex + 3 +double atrLowerRawBuffer[]; + +// +// RSI ... +#define rsiBufferIndex mLastBufferIndex + 4 +double rsiBuffer[]; + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +// RSI Handler ... +int rsiHandler = INVALID_HANDLE; + +// +// ATR Handler ... +int atrHandler = INVALID_HANDLE; + +// +bool isStrTrendChanged; +bool isStrStartBearishTrend; +bool isStrStartBullishTrend; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + + // + // RSI ... + rsiHandler = iRSI( + _Symbol, + _Period, + rsiLength, + rsiAppliedTo // + ); + bool isInited = rsiHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // ATR ... + atrHandler = iATR( + _Symbol, + _Period, + atrLength // + ); + isInited = atrHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + IndicatorRelease(rsiHandler); + IndicatorRelease(atrHandler); +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // Fill All Buffers by Zero ... + if (prev_calculated == 0) + { + } + + // + // Validate Calculated Bars ... + + // + // RSI ... + int rsiCalculatedBars = BarsCalculated(rsiHandler); + + // + // ATR ... + int atrCalculatedBars = BarsCalculated(atrHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // RSI ... + rsiCalculatedBars >= maxLength && + // + // ATR ... + atrCalculatedBars >= maxLength + // + ; + if (!isPassedRequiredCalculatedBars) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + + // + // RSI ... + int copiedRsis = CopyBuffer(rsiHandler, 0, 0, limit, rsiBuffer); + + // + // ATR ... + int copiedAtrs = CopyBuffer(atrHandler, 0, 0, limit, atrBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // + // RSI ... + copiedRsis > 0 && + // + // ATR ... + copiedAtrs > 0 + // + ; + if (!isPassedRequiredCopiedItems) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = + // + // RSI ... + rsiLength > 0 && + // + // ATR ... + atrLength > 0 && + atrMultiplier > 0 + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(rsiLength, atrLength); + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // ATR ... + + // + // UPPER ... + bool canShowAtrUpper = showAtrUpper; + ENUM_DRAW_TYPE atrUpperDrawType = canShowAtrUpper ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(atrUpperBuffer, true); + SetIndexBuffer(atrUpperBufferIndex, atrUpperBuffer, INDICATOR_DATA); + PlotIndexSetDouble(atrUpperBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(atrUpperBufferIndex, PLOT_SHOW_DATA, canShowAtrUpper); + PlotIndexSetInteger(atrUpperBufferIndex, PLOT_DRAW_TYPE, atrUpperDrawType); + + // + // LOWER ... + bool canShowAtrLower = showAtrLower; + ENUM_DRAW_TYPE atrLowerDrawType = canShowAtrLower ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(atrLowerBuffer, true); + SetIndexBuffer(atrLowerBufferIndex, atrLowerBuffer, INDICATOR_DATA); + PlotIndexSetDouble(atrLowerBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(atrLowerBufferIndex, PLOT_SHOW_DATA, canShowAtrLower); + PlotIndexSetInteger(atrLowerBufferIndex, PLOT_DRAW_TYPE, atrLowerDrawType); + + // + // Data Buffers ... + + // + // ATR ... + + // + ArraySetAsSeries(atrBuffer, true); + SetIndexBuffer(atrBufferIndex, atrBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(atrUpperRawBuffer, true); + SetIndexBuffer(atrUpperRawBufferIndex, atrUpperRawBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(atrLowerRawBuffer, true); + SetIndexBuffer(atrLowerRawBufferIndex, atrLowerRawBuffer, INDICATOR_CALCULATIONS); + + // + // RSI ... + + // + ArraySetAsSeries(rsiBuffer, true); + SetIndexBuffer(rsiBufferIndex, rsiBuffer, INDICATOR_CALCULATIONS); +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateBuffers( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + // + // bool canCalculate = true; + bool canCalculate = + barsLimit == 0 || + bar_index <= barsLimit; + if (canCalculate) + { + // + CalculateAtrZones( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low // + ); + } + else + { + FillBuffersZero(bar_index); + } +} + +// +// Custom ... + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + // RSIS ... + rsiBuffer[barIndex] = 0; + + // + // ATRS ... + atrBuffer[barIndex] = 0; + atrUpperBuffer[barIndex] = 0; + atrUpperRawBuffer[barIndex] = 0; + atrUpperBuffer[barIndex] = 0; + atrLowerRawBuffer[barIndex] = 0; +} + +/** + * Calculate ATR Zones ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + */ +void CalculateAtrZones( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[] // +) +{ + // + // Select ATr Value ... + double atrValue = atrBuffer[bar_index]; + double appliedAtrMultiplierValue = atrValue * atrMultiplier; + + // + // Select Upper Price ... + double upperPrice = GetAppliedPrice( + atrUpperAppliedTo, + open, + high, + low, + close, + bar_index // + ); + + // + // Select Lower Price ... + double lowerPrice = GetAppliedPrice( + atrLowerAppliedTo, + open, + high, + low, + close, + bar_index // + ); + + // + // Calculate Raw Atrs ... + + // + // Upper ... + double atrUpperRawValue = upperPrice + appliedAtrMultiplierValue; + atrUpperRawBuffer[bar_index] = atrUpperRawValue; + + // + // Lower ... + double atrLowerRawValue = lowerPrice - appliedAtrMultiplierValue; + atrLowerRawBuffer[bar_index] = atrLowerRawValue; + + // + bool canSmooth = atrSmoothingMode != X_MA_MODE_NONE; + if (canSmooth) + { + // + // Upper ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + atrLength, + atrUpperRawBuffer, + atrUpperBuffer, + atrSmoothingMode // + ); + + // + // Lower ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + atrLength, + atrLowerRawBuffer, + atrLowerBuffer, + atrSmoothingMode // + ); + } + else + { + // + // Use Raw Values ... + atrUpperBuffer[bar_index] = atrUpperRawValue; + atrLowerBuffer[bar_index] = atrLowerRawValue; + } +} + +// \ No newline at end of file diff --git a/BKPS/14031218/Indicators/x-saherelm.x121.xcc.ex5 b/BKPS/14031218/Indicators/x-saherelm.x121.xcc.ex5 new file mode 100644 index 0000000..4427a2a Binary files /dev/null and b/BKPS/14031218/Indicators/x-saherelm.x121.xcc.ex5 differ diff --git a/BKPS/14031218/Indicators/x-saherelm.x121.xcc.mq5 b/BKPS/14031218/Indicators/x-saherelm.x121.xcc.mq5 new file mode 100644 index 0000000..2f45b84 --- /dev/null +++ b/BKPS/14031218/Indicators/x-saherelm.x121.xcc.mq5 @@ -0,0 +1,437 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Candle Styles +// --------------------------------------------------- +// Name: X121 XCC +// Description: Candle Styles ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121 XCC Indicator" +#property strict + +// +// START Constants ... +// + +// +// Indicator Short Name ... +#define ShortName "X121 XCC" + +// +// Holds an SnapShot of Charts Configuration ... +struct XChartStyle +{ + // + // chart's ID ... + long chartId; + // + // chart's mode ... + ENUM_CHART_MODE mode; + // + // show bid line ... + bool showBidLine; + // + // show ask line ... + bool showAskLine; + // + // show grids on chart ... + bool showGrid; + // + // show volumes ... + bool showVolumes; + // + // Displaying trade levels in the chart (levels of open positions, Stop Loss, Take Profit and pending orders) ... + bool showTradeLevels; + // + // chart autoscroll ... + bool autoScroll; + // + // chart quick navigation state ... + bool quickNavigation; + // + // chart's foreground color ... + color foreGroundColor; + // + // chart's background color ... + color backGroundColor; + // + // Up Color ... + color upColor; + // + // Down Color ... + color downColor; + // + // Bullish color ... + color bullishColor; + // + // Bearish color ... + color bearishColor; + // + // grid color ... + color gridColor; + // + // bid line color ... + color bidLineColor; + // + // ask line color ... + color askLineColor; + // + // line mode and doji candlestick color ... + color lineColor; + // + // Color of stop order levels (Stop Loss and Take Profit) ... + color stopColor; + // + // volumes color ... + color volumesColor; +}; + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input group "Chart Style"; +input ENUM_CHART_MODE mode = CHART_CANDLES; // Mode +input color upColor = clrGreen; // Up Color +input color downColor = clrRed; // Down Color +input color lineColor = clrGreen; // Line mode and Doji candlestick Color +input color bullishColor = clrGreen; // Bullish Color +input color bearishColor = clrRed; // Bearish Color +input color volumesColor = clrGreen; // Volumes Color + +// +input group "Presentation"; +input bool showCandles = true; // Show Candles + +// +// END Inputs ... +// + +// +// START Includes and Imports ... +// + +// +// Includes Draw Library ... +#include "../Libraries/x-saherelm.draw.lib.mq5" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Includes and Imports ... +// + +// +// START Buffers ... +// + +// +#property indicator_chart_window + +// +#property indicator_buffers 0 +#property indicator_plots 0 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int maxLength; + +// +XChartStyle chartStyle; +XChartStyle clearStyle; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + drawPrefix = ShortName; + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Apply Chart Style ... + ApplyCustomChartStyle(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed +} + +// +// Calculating what we want ... +int OnCalculate( + const int rates_total, // Total Bars on Chart ... + const int prev_calculated, // Total Calculated Bars on Charts ... + const datetime &time[], // History of Open Time ... + const double &open[], // History of Open Price ... + const double &high[], // History of High Price ... + const double &low[], // History of Low Price ... + const double &close[], // History of Close Price ... + const long &tick_volume[], // History of Tick Volumes on Bar ... + const long &volume[], // History of Trade Volumes ... + const int &spread[] // History of Spread Price ... +) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + CalculateBuffers(i); + } + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = true; + + // + return result; +} + +// +// Retrieve all Exists Input Max Length ... +// use for Start Of Drawing ... +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index // Selected Bar Index +) +{ +} + +// +// Apply Custom Chart Style ... +void ApplyCustomChartStyle() +{ + // + // Read Current Chart Config and Store it ... + ReadChartStyle(); + + // + // After Reading Current Chart Style ... + // we have to Save Configs and Change Styles ... + clearStyle = chartStyle; + + // + clearStyle.upColor = CLR_NONE; + clearStyle.downColor = CLR_NONE; + clearStyle.lineColor = CLR_NONE; + clearStyle.bullishColor = CLR_NONE; + clearStyle.bearishColor = CLR_NONE; + + // + // Decide to Show or not Candles based on User Input ... + if (showCandles) + { + SetChartStyle(chartStyle); + } + else + { + SetChartStyle(clearStyle); + } +} + +// +// Read Previous Chart Style ... +void ReadChartStyle() +{ + // + // Retrieve Current Chart ID ... + long chartId = ChartID(); + chartStyle.chartId = chartId; + + // + // Retrieve Chart Mode ... + chartStyle.mode = (ENUM_CHART_MODE)ChartGetInteger(chartId, CHART_MODE); + + // + chartStyle.showBidLine = (bool)ChartGetInteger(chartId, CHART_SHOW_BID_LINE); + chartStyle.showAskLine = (bool)ChartGetInteger(chartId, CHART_SHOW_ASK_LINE); + chartStyle.showGrid = (bool)ChartGetInteger(chartId, CHART_SHOW_GRID); + chartStyle.showVolumes = (bool)ChartGetInteger(chartId, CHART_SHOW_VOLUMES); + chartStyle.showTradeLevels = (bool)ChartGetInteger(chartId, CHART_SHOW_TRADE_LEVELS); + chartStyle.autoScroll = (bool)ChartGetInteger(chartId, CHART_AUTOSCROLL); + chartStyle.quickNavigation = (bool)ChartGetInteger(chartId, CHART_QUICK_NAVIGATION); + + // + chartStyle.foreGroundColor = (color)ChartGetInteger(chartId, CHART_COLOR_FOREGROUND); + chartStyle.backGroundColor = (color)ChartGetInteger(chartId, CHART_COLOR_BACKGROUND); + chartStyle.upColor = (color)ChartGetInteger(chartId, CHART_COLOR_CHART_UP); + chartStyle.downColor = (color)ChartGetInteger(chartId, CHART_COLOR_CHART_DOWN); + chartStyle.bullishColor = (color)ChartGetInteger(chartId, CHART_COLOR_CANDLE_BULL); + chartStyle.bearishColor = (color)ChartGetInteger(chartId, CHART_COLOR_CANDLE_BEAR); + chartStyle.gridColor = (color)ChartGetInteger(chartId, CHART_COLOR_GRID); + chartStyle.bidLineColor = (color)ChartGetInteger(chartId, CHART_COLOR_BID); + chartStyle.askLineColor = (color)ChartGetInteger(chartId, CHART_COLOR_ASK); + chartStyle.stopColor = (color)ChartGetInteger(chartId, CHART_COLOR_STOP_LEVEL); + chartStyle.lineColor = (color)ChartGetInteger(chartId, CHART_COLOR_CHART_LINE); + chartStyle.volumesColor = (color)ChartGetInteger(chartId, CHART_COLOR_VOLUME); + + // + chartStyle.mode = mode; + chartStyle.upColor = upColor; + chartStyle.downColor = downColor; + chartStyle.lineColor = lineColor; + chartStyle.bearishColor = bearishColor; + chartStyle.bullishColor = bullishColor; + chartStyle.volumesColor = volumesColor; +} + +// +// Set Chart Style ... +void SetChartStyle( + XChartStyle &mChartStyle // Chart Style to Apply +) +{ + // + ApplyChartStyle( + mChartStyle.chartId, + mChartStyle.mode, + mChartStyle.showBidLine, + mChartStyle.showAskLine, + mChartStyle.showGrid, + mChartStyle.showVolumes, + mChartStyle.showTradeLevels, + mChartStyle.autoScroll, + mChartStyle.quickNavigation, + mChartStyle.foreGroundColor, + mChartStyle.backGroundColor, + mChartStyle.upColor, + mChartStyle.downColor, + mChartStyle.bullishColor, + mChartStyle.bearishColor, + mChartStyle.gridColor, + mChartStyle.bidLineColor, + mChartStyle.askLineColor, + mChartStyle.lineColor, + mChartStyle.stopColor, + mChartStyle.volumesColor); +} + +// +// END Functions ... +// diff --git a/BKPS/14031218/Indicators/x-saherelm.x121.xche.ex5 b/BKPS/14031218/Indicators/x-saherelm.x121.xche.ex5 new file mode 100644 index 0000000..6dbf4f7 Binary files /dev/null and b/BKPS/14031218/Indicators/x-saherelm.x121.xche.ex5 differ diff --git a/BKPS/14031218/Indicators/x-saherelm.x121.xche.mq5 b/BKPS/14031218/Indicators/x-saherelm.x121.xche.mq5 new file mode 100644 index 0000000..d8ed104 --- /dev/null +++ b/BKPS/14031218/Indicators/x-saherelm.x121.xche.mq5 @@ -0,0 +1,624 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XCHE +// Description: XCHE ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121 XCHE Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121 XCHE" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +// Market ... +input group "Market"; +input int cheLength = 35; // Length +input int cheLoopback = 26; // Loopback +input double cheMultiplier1 = 3.0; // 1st Multiplier +input double cheMultiplier2 = 3.5; // 2nd Multiplier +input ENUM_APPLIED_PRICE cheUpperAppliedTo = PRICE_HIGH; // Upper Zone Applied to +input ENUM_APPLIED_PRICE cheLowerAppliedTo = PRICE_LOW; // Lower Zone Applied to + +// +input group "Presentation"; + +// +input int cheArrowCode = 159; // CHE Arrow Code + +// +input bool showLE1 = true; // Show 1st Long Exit +input bool showSE1 = true; // Show 1st Short Exit +input bool showLE2 = true; // Show 2st Long Exit +input bool showSE2 = true; // Show 2st Short Exit + +// +// Buffers ... + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#property indicator_chart_window + +// +#property indicator_buffers 8 +#property indicator_plots 8 + +// +// Exit 1 ... + +// +// LONG ... + +// +#define le1BufferIndex 0 +double le1Buffer[]; + +#property indicator_label1 "X121 LE1" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrAqua +#property indicator_style1 STYLE_DOT +#property indicator_width1 1 + +// +// SHORT ... + +// +#define se1BufferIndex 1 +double se1Buffer[]; + +#property indicator_label2 "X121 SE1" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrMagenta +#property indicator_style2 STYLE_DOT +#property indicator_width2 1 + +// +// Exit 2 ... + +// +// LONG ... + +// +#define le2BufferIndex 2 +double le2Buffer[]; + +#property indicator_label3 "X121 LE2" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrAqua +#property indicator_style3 STYLE_SOLID +#property indicator_width3 1 + +// +// SHORT ... + +// +#define se2BufferIndex 3 +double se2Buffer[]; + +#property indicator_label4 "X121 SE2" +#property indicator_type4 DRAW_LINE +#property indicator_color4 clrMagenta +#property indicator_style4 STYLE_SOLID +#property indicator_width4 1 + +// +// Start Buffers ... + +// +#define le1StartBufferIndex 4 +double le1StartBuffer[]; + +// +#property indicator_label5 "X121 LE1 S" +#property indicator_type5 DRAW_ARROW +#property indicator_color5 clrLime + +// +#define se1StartBufferIndex 5 +double se1StartBuffer[]; + +// +#property indicator_label6 "X121 SE1 S" +#property indicator_type6 DRAW_ARROW +#property indicator_color6 clrRed + +// +#define le2StartBufferIndex 6 +double le2StartBuffer[]; + +// +#property indicator_label7 "X121 LE2 S" +#property indicator_type7 DRAW_ARROW +#property indicator_color7 clrLime + +// +#define se2StartBufferIndex 7 +double se2StartBuffer[]; + +// +#property indicator_label8 "X121 SE2 S" +#property indicator_type8 DRAW_ARROW +#property indicator_color8 clrRed + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +// Working Array ... +double work[][6]; +#define hi1Idx 0 +#define lo1Idx 1 +#define hi2Idx 2 +#define lo2Idx 3 +#define trend1Idx 4 +#define trend2Idx 5 + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input cheLength, here we get max Input cheLength + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + if (Bars(_Symbol, _Period) < rates_total) + { + return (prev_calculated); + } + + // + if (ArrayRange(work, 0) != rates_total) + { + ArrayResize(work, rates_total); + } + + // + // this counts Available Bars ... + + // + limit = prev_calculated - 1; + if (limit < 0) + { + limit = 0; + } + + // + // Main Loop ... + for (int i = limit; i < rates_total && !IsStopped(); i++) + { + CalculateBuffers( + i, + prev_calculated, + rates_total, + // + open, + high, + low, + close); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = true; + + // + result = + cheLength >= 9 && + cheLoopback >= 0; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(cheLength, cheLoopback); + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // LEVEL 1 ... + + // + // Long Exit 1 ... + + // + // Draw Type ... + ENUM_DRAW_TYPE le1DrawType = showLE1 ? DRAW_LINE : DRAW_NONE; + ENUM_DRAW_TYPE le1StartDrawType = showLE1 ? DRAW_ARROW : DRAW_NONE; + + // + // Buffer ... + SetIndexBuffer(le1BufferIndex, le1Buffer, INDICATOR_DATA); + PlotIndexSetInteger(le1BufferIndex, PLOT_SHOW_DATA, showLE1); + PlotIndexSetInteger(le1BufferIndex, PLOT_DRAW_TYPE, le1DrawType); + + // + // Start Buffer ... + SetIndexBuffer(le1StartBufferIndex, le1StartBuffer, INDICATOR_DATA); + PlotIndexSetInteger(le1StartBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(le1StartBufferIndex, PLOT_DRAW_TYPE, le1StartDrawType); + PlotIndexSetInteger(le1StartBufferIndex, PLOT_ARROW, cheArrowCode); + + // + // Short Exit 1 ... + + // + // Draw Type ... + ENUM_DRAW_TYPE se1DrawType = showSE1 ? DRAW_LINE : DRAW_NONE; + ENUM_DRAW_TYPE se1StartDrawType = showSE1 ? DRAW_ARROW : DRAW_NONE; + + // + // Buffer ... + SetIndexBuffer(se1BufferIndex, se1Buffer, INDICATOR_DATA); + PlotIndexSetInteger(se1BufferIndex, PLOT_SHOW_DATA, showSE1); + PlotIndexSetInteger(se1BufferIndex, PLOT_DRAW_TYPE, se1DrawType); + + // + // Start Buffer ... + SetIndexBuffer(se1StartBufferIndex, se1StartBuffer, INDICATOR_DATA); + PlotIndexSetInteger(se1StartBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(se1StartBufferIndex, PLOT_DRAW_TYPE, se1StartDrawType); + PlotIndexSetInteger(se1StartBufferIndex, PLOT_ARROW, cheArrowCode); + + // + // LEVEL 2 ... + + // + // Long Exit 2 ... + + // + // Draw Type ... + ENUM_DRAW_TYPE le2DrawType = showLE2 ? DRAW_LINE : DRAW_NONE; + ENUM_DRAW_TYPE le2StartDrawType = showLE2 ? DRAW_ARROW : DRAW_NONE; + + // + // Buffer ... + SetIndexBuffer(le2BufferIndex, le2Buffer, INDICATOR_DATA); + PlotIndexSetInteger(le2BufferIndex, PLOT_SHOW_DATA, showLE2); + PlotIndexSetInteger(le2BufferIndex, PLOT_DRAW_TYPE, le2DrawType); + + // + // Start Buffer ... + SetIndexBuffer(le2StartBufferIndex, le2StartBuffer, INDICATOR_DATA); + PlotIndexSetInteger(le2StartBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(le2StartBufferIndex, PLOT_DRAW_TYPE, le2StartDrawType); + PlotIndexSetInteger(le2StartBufferIndex, PLOT_ARROW, cheArrowCode); + + // + // Short Exit 2 ... + + // + // Draw Type ... + ENUM_DRAW_TYPE se2DrawType = showSE2 ? DRAW_LINE : DRAW_NONE; + ENUM_DRAW_TYPE se2StartDrawType = showSE2 ? DRAW_ARROW : DRAW_NONE; + + // + // Buffer ... + SetIndexBuffer(se2BufferIndex, se2Buffer, INDICATOR_DATA); + PlotIndexSetInteger(se2BufferIndex, PLOT_SHOW_DATA, showSE2); + PlotIndexSetInteger(se2BufferIndex, PLOT_DRAW_TYPE, se2DrawType); + + // + // Start Buffer ... + SetIndexBuffer(se2StartBufferIndex, se2StartBuffer, INDICATOR_DATA); + PlotIndexSetInteger(se2StartBufferIndex, PLOT_SHOW_DATA, false); + PlotIndexSetInteger(se2StartBufferIndex, PLOT_DRAW_TYPE, se2StartDrawType); + PlotIndexSetInteger(se2StartBufferIndex, PLOT_ARROW, cheArrowCode); +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Calculate Buffers ... + */ +void CalculateBuffers( + int bar_index, // Selected Bar Index + int prevCalculated, // Previous Calculated + int ratesTotal, // Total Rates + const double &open[], // Rates Open ... + const double &high[], // Rates High ... + const double &low[], // Rates Low ... + const double &close[] // Rates Close ... +) +{ + // + // Cleanup Buffers ... + le1Buffer[bar_index] = le1StartBuffer[bar_index] = se1Buffer[bar_index] = se1StartBuffer[bar_index] = EMPTY_VALUE; + le2Buffer[bar_index] = le2StartBuffer[bar_index] = se2Buffer[bar_index] = se2StartBuffer[bar_index] = EMPTY_VALUE; + + // + int start = MathMax(bar_index - cheLoopback, 0); + + // + // Calculate ATR Value ... + double atrValue = 0; + for (int k = 1; k <= cheLength && (bar_index - k - 1) >= 0; k++) + { + // + atrValue += MathMax(high[bar_index - k], close[MathMax(bar_index - k - 1, 0)]) - + MathMin(low[bar_index - k], close[MathMax(bar_index - k - 1, 0)]); + } + atrValue /= (double)cheLength; + + // + // Retrieve Highest High and Lowest Lows ... + double cheLoopbackMax = high[ArrayMaximum(high, start, cheLoopback)]; + double cheLoopbackMin = low[ArrayMinimum(low, start, cheLoopback)]; + + // + // Fill Multi Dimesional Working Array ... + work[bar_index][hi1Idx] = cheLoopbackMax - cheMultiplier1 * atrValue; + work[bar_index][lo1Idx] = cheLoopbackMin + cheMultiplier1 * atrValue; + work[bar_index][hi2Idx] = cheLoopbackMax - cheMultiplier2 * atrValue; + work[bar_index][lo2Idx] = cheLoopbackMin + cheMultiplier2 * atrValue; + work[bar_index][trend1Idx] = (bar_index > 0) ? work[bar_index - 1][trend1Idx] : 0; + work[bar_index][trend2Idx] = (bar_index > 0) ? work[bar_index - 1][trend2Idx] : 0; + + // + if (bar_index > 0) + { + // + // Calculate Trends ... + if (close[bar_index] > work[bar_index - 1][lo1Idx]) + { + work[bar_index][trend1Idx] = 1; + } + + // + if (close[bar_index] < work[bar_index - 1][hi1Idx]) + { + work[bar_index][trend1Idx] = -1; + } + + // + if (close[bar_index] > work[bar_index - 1][lo2Idx]) + { + work[bar_index][trend2Idx] = 1; + } + + // + if (close[bar_index] < work[bar_index - 1][hi2Idx]) + { + work[bar_index][trend2Idx] = -1; + } + + // + // Calculate Exit Values ... + + // + // Exit 1 ... + + // + // Long ... + if (cheMultiplier1 > 0 && work[bar_index][trend1Idx] == 1) + { + // + if (work[bar_index][hi1Idx] < work[bar_index - 1][hi1Idx]) + { + work[bar_index][hi1Idx] = work[bar_index - 1][hi1Idx]; + } + + // + le1Buffer[bar_index] = work[bar_index][hi1Idx]; + + // + if (le1Buffer[bar_index - 1] == EMPTY_VALUE) + { + le1StartBuffer[bar_index] = le1Buffer[bar_index]; + } + } + + // + // Short ... + if (cheMultiplier1 > 0 && work[bar_index][trend1Idx] == -1) + { + // + if (work[bar_index][lo1Idx] > work[bar_index - 1][lo1Idx]) + { + work[bar_index][lo1Idx] = work[bar_index - 1][lo1Idx]; + } + + // + se1Buffer[bar_index] = work[bar_index][lo1Idx]; + + // + if (se1Buffer[bar_index - 1] == EMPTY_VALUE) + { + se1StartBuffer[bar_index] = se1Buffer[bar_index]; + } + } + + // + // Exit 2 ... + + // + // Long ... + if (cheMultiplier2 > 0 && work[bar_index][trend2Idx] == 1) + { + if (work[bar_index][hi2Idx] < work[bar_index - 1][hi2Idx]) + { + work[bar_index][hi2Idx] = work[bar_index - 1][hi2Idx]; + } + + // + le2Buffer[bar_index] = work[bar_index][hi2Idx]; + + // + if (le2Buffer[bar_index - 1] == EMPTY_VALUE) + { + le2StartBuffer[bar_index] = le2Buffer[bar_index]; + } + } + + // + // Short ... + if (cheMultiplier2 > 0 && work[bar_index][trend2Idx] == -1) + { + // + if (work[bar_index][lo2Idx] > work[bar_index - 1][lo2Idx]) + { + work[bar_index][lo2Idx] = work[bar_index - 1][lo2Idx]; + } + + // + se2Buffer[bar_index] = work[bar_index][lo2Idx]; + + // + if (se2Buffer[bar_index - 1] == EMPTY_VALUE) + { + se2StartBuffer[bar_index] = se2Buffer[bar_index]; + } + } + } +} + +// \ No newline at end of file diff --git a/BKPS/14031218/Indicators/x-saherelm.x121.xct.ex5 b/BKPS/14031218/Indicators/x-saherelm.x121.xct.ex5 new file mode 100644 index 0000000..eb6cc3b Binary files /dev/null and b/BKPS/14031218/Indicators/x-saherelm.x121.xct.ex5 differ diff --git a/BKPS/14031218/Indicators/x-saherelm.x121.xct.mq5 b/BKPS/14031218/Indicators/x-saherelm.x121.xct.mq5 new file mode 100644 index 0000000..286882a --- /dev/null +++ b/BKPS/14031218/Indicators/x-saherelm.x121.xct.mq5 @@ -0,0 +1,262 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// --------------------------------------------- +// Name: X121 XCT +// Description: Trend Magic Indicator ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121 XCT Indicator" +#property strict + +// +// START Constants ... +// + +// +#define ShortName "X121 XCT" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input int fontSize = 15; // Font Size +input string font = "Arial"; // Font +input color clr = clrYellow; // Text Color +input ENUM_BASE_CORNER corner = CORNER_RIGHT_LOWER; // Text Position + +// +input group "Presentation"; +input bool showTimer = true; // Show Candle Time + +// +// END Inputs ... +// + +// +// START Buffers ... +// + +// +#property indicator_chart_window + +// +#property indicator_buffers 0 +#property indicator_plots 0 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +bool isCreatedObject; +string tag; +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + + // + tag = ShortName + _Symbol + ToString(_Period); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Delete Object ... + ObjectDelete(0, tag); + + // + Comment(""); +} + +// +// Calculating what we want ... +int OnCalculate( + const int rates_total, // Total Bars on Chart ... + const int prev_calculated, // Total Calculated Bars on Charts ... + const datetime &time[], // History of Open Time ... + const double &open[], // History of Open Price ... + const double &high[], // History of High Price ... + const double &low[], // History of Low Price ... + const double &close[], // History of Close Price ... + const long &tick_volume[], // History of Tick Volumes on Bar ... + const long &volume[], // History of Trade Volumes ... + const int &spread[] // History of Spread Price ... +) +{ + // + if (!showTimer) + { + return rates_total; + } + + // + XBarRemainsTime barRemains; + barRemains.Init( + _Symbol, + _Period + // + ); + + // + string msg = barRemains + .ToString( + "", + "", + "", + "", + "", + ":", + true + // + ); + + // + long mSpread = SymbolInfoInteger(Symbol(), SYMBOL_SPREAD); + + // + string _sp = ""; + if (mSpread < 10) + _sp = ".."; + else if (mSpread < 100) + _sp = "."; + + // + string objText = "Spread: " + IntegerToString(mSpread) + _sp + ", Next Bar in: " + msg; + + // + if (IsValid(tag) && !isCreatedObject) + { + CreateIndicatorObject(); + } + + // + if (isCreatedObject) + { + ObjectSetString(0, tag, OBJPROP_TEXT, objText); + } + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +void CreateIndicatorObject() +{ + // + if (!showTimer || + !IsValid(tag)) + { + return; + } + + // + isCreatedObject = ObjectCreate(0, tag, OBJ_LABEL, 0, 0, 0); + ObjectSetInteger(0, tag, OBJPROP_CORNER, corner); + ObjectSetInteger(0, tag, OBJPROP_XDISTANCE, 10); + ObjectSetInteger(0, tag, OBJPROP_YDISTANCE, 2); + + // + ENUM_ANCHOR_POINT Anchor = ANCHOR_LEFT_UPPER; + switch (corner) + { + case CORNER_LEFT_UPPER: + Anchor = ANCHOR_LEFT_UPPER; + break; + case CORNER_RIGHT_UPPER: + Anchor = ANCHOR_RIGHT_UPPER; + break; + case CORNER_LEFT_LOWER: + Anchor = ANCHOR_LEFT_LOWER; + break; + case CORNER_RIGHT_LOWER: + Anchor = ANCHOR_RIGHT_LOWER; + break; + } + + // + int mFontSize = fontSize > 0 + ? fontSize + : 10; + + // + string mFont = IsValid(font) + ? font + : "Arial"; + + // + ObjectSetString(0, tag, OBJPROP_FONT, mFont); + ObjectSetInteger(0, tag, OBJPROP_COLOR, clr); + ObjectSetInteger(0, tag, OBJPROP_ANCHOR, Anchor); + ObjectSetInteger(0, tag, OBJPROP_FONTSIZE, mFontSize); +} + +// +// END Functions ... +// diff --git a/BKPS/14031218/Indicators/x-saherelm.x121.xdon.ex5 b/BKPS/14031218/Indicators/x-saherelm.x121.xdon.ex5 new file mode 100644 index 0000000..979c4c1 Binary files /dev/null and b/BKPS/14031218/Indicators/x-saherelm.x121.xdon.ex5 differ diff --git a/BKPS/14031218/Indicators/x-saherelm.x121.xdon.mq5 b/BKPS/14031218/Indicators/x-saherelm.x121.xdon.mq5 new file mode 100644 index 0000000..49785d4 --- /dev/null +++ b/BKPS/14031218/Indicators/x-saherelm.x121.xdon.mq5 @@ -0,0 +1,692 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XDON +// Description: XDON ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121 XDON Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121 XDON" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +// Market ... +input group "Market"; +input int donchainLength = 40; // Donchain Length + +// +// Presentation ... +input group "Presentation"; + +// +input int startCalculationForLastBars = 1000; // Calculate Last n Bars + +// +input bool showUpper = true; // Show Upper Band +input bool showLower = true; // Show Lower Band + +// +input bool showOpen = true; // Show Open +input bool showHigh = true; // Show High +input bool showClose = true; // Show Close +input bool showLow = true; // Show Low + +// +// Buffers ... + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#property indicator_chart_window + +// +#property indicator_buffers 8 +#property indicator_plots 8 + +// +// Plot Buffers ... + +// +// Open ... + +// +#define donOpenUpperBufferIndex 0 +double donOpenUpperBuffer[]; + +// +#define donOpenUpperPlotBufferIndex 0 +#property indicator_label1 "X121 O U" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrCornflowerBlue +#property indicator_width1 1 + +// +#define donOpenLowerBufferIndex 1 +double donOpenLowerBuffer[]; + +// +#define donOpenLowerPlotBufferIndex 1 +#property indicator_label2 "X121 O L" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrCornflowerBlue +#property indicator_width2 1 + +// +// High ... + +// +#define donHighUpperBufferIndex 2 +double donHighUpperBuffer[]; + +// +#define donHighUpperPlotBufferIndex 2 +#property indicator_label3 "X121 H U" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrAquamarine +#property indicator_width3 1 + +// +#define donHighLowerBufferIndex 3 +double donHighLowerBuffer[]; + +// +#define donHighLowerPlotBufferIndex 3 +#property indicator_label4 "X121 H L" +#property indicator_type4 DRAW_LINE +#property indicator_color4 clrAquamarine +#property indicator_width4 1 + +// +// Low ... + +// +#define donLowUpperBufferIndex 4 +double donLowUpperBuffer[]; + +// +#define donLowUpperPlotBufferIndex 4 +#property indicator_label5 "X121 L U" +#property indicator_type5 DRAW_LINE +#property indicator_color5 clrDarkOrchid +#property indicator_width5 1 + +// +#define donLowLowerBufferIndex 5 +double donLowLowerBuffer[]; + +// +#define donLowLowerPlotBufferIndex 5 +#property indicator_label6 "X121 L L" +#property indicator_type6 DRAW_LINE +#property indicator_color6 clrDarkOrchid +#property indicator_width6 1 + +// +// Close ... + +// +#define donCloseUpperBufferIndex 6 +double donCloseUpperBuffer[]; + +// +#define donCloseUpperPlotBufferIndex 6 +#property indicator_label7 "X121 C U" +#property indicator_type7 DRAW_LINE +#property indicator_color7 clrCoral +#property indicator_width7 1 + +// +#define donCloseLowerBufferIndex 7 +double donCloseLowerBuffer[]; + +// +#define donCloseLowerPlotBufferIndex 7 +#property indicator_label8 "X121 C L" +#property indicator_type8 DRAW_LINE +#property indicator_color8 clrCoral +#property indicator_width8 1 + +// +// Data Buffers ... + +// +int mLastBufferIndex = 7; + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // Validate Calculated Bars ... + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + result = + // + donchainLength > 0 + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + // + // Open ... + + // + // UPPER ... + bool canShowCOpenUpper = showUpper && showOpen; + ENUM_DRAW_TYPE donOpenUpperDrawType = canShowCOpenUpper ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donOpenUpperBuffer, true); + SetIndexBuffer(donOpenUpperBufferIndex, donOpenUpperBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donOpenUpperPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donOpenUpperPlotBufferIndex, PLOT_SHOW_DATA, canShowCOpenUpper); + PlotIndexSetInteger(donOpenUpperPlotBufferIndex, PLOT_DRAW_TYPE, donOpenUpperDrawType); + + // + // LOWER ... + bool canShowCOpenLower = showLower && showOpen; + ENUM_DRAW_TYPE donOpenLowerDrawType = canShowCOpenLower ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donOpenLowerBuffer, true); + SetIndexBuffer(donOpenLowerBufferIndex, donOpenLowerBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donOpenLowerPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donOpenLowerPlotBufferIndex, PLOT_SHOW_DATA, canShowCOpenLower); + PlotIndexSetInteger(donOpenLowerPlotBufferIndex, PLOT_DRAW_TYPE, donOpenLowerDrawType); + + // + // Close ... + + // + // UPPER ... + bool canShowCCloseUpper = showUpper && showClose; + ENUM_DRAW_TYPE donCloseUpperDrawType = canShowCCloseUpper ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donCloseUpperBuffer, true); + SetIndexBuffer(donCloseUpperBufferIndex, donCloseUpperBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donCloseUpperPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donCloseUpperPlotBufferIndex, PLOT_SHOW_DATA, canShowCCloseUpper); + PlotIndexSetInteger(donCloseUpperPlotBufferIndex, PLOT_DRAW_TYPE, donCloseUpperDrawType); + + // + // LOWER ... + bool canShowCCloseLower = showLower && showClose; + ENUM_DRAW_TYPE donCloseLowerDrawType = canShowCCloseLower ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donCloseLowerBuffer, true); + SetIndexBuffer(donCloseLowerBufferIndex, donCloseLowerBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donCloseLowerPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donCloseLowerPlotBufferIndex, PLOT_SHOW_DATA, canShowCCloseLower); + PlotIndexSetInteger(donCloseLowerPlotBufferIndex, PLOT_DRAW_TYPE, donCloseLowerDrawType); + + // + // High ... + + // + // UPPER ... + bool canShowCHighUpper = showUpper && showHigh; + ENUM_DRAW_TYPE donHighUpperDrawType = canShowCHighUpper ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donHighUpperBuffer, true); + SetIndexBuffer(donHighUpperBufferIndex, donHighUpperBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donHighUpperPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donHighUpperPlotBufferIndex, PLOT_SHOW_DATA, canShowCHighUpper); + PlotIndexSetInteger(donHighUpperPlotBufferIndex, PLOT_DRAW_TYPE, donHighUpperDrawType); + + // + // LOWER ... + bool canShowCHighLower = showLower && showHigh; + ENUM_DRAW_TYPE donHighLowerDrawType = canShowCHighLower ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donHighLowerBuffer, true); + SetIndexBuffer(donHighLowerBufferIndex, donHighLowerBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donHighLowerPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donHighLowerPlotBufferIndex, PLOT_SHOW_DATA, canShowCHighLower); + PlotIndexSetInteger(donHighLowerPlotBufferIndex, PLOT_DRAW_TYPE, donHighLowerDrawType); + + // + // Low ... + + // + // UPPER ... + bool canShowCLowUpper = showUpper && showLow; + ENUM_DRAW_TYPE donLowUpperDrawType = canShowCLowUpper ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donLowUpperBuffer, true); + SetIndexBuffer(donLowUpperBufferIndex, donLowUpperBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donLowUpperPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donLowUpperPlotBufferIndex, PLOT_SHOW_DATA, canShowCLowUpper); + PlotIndexSetInteger(donLowUpperPlotBufferIndex, PLOT_DRAW_TYPE, donLowUpperDrawType); + + // + // LOWER ... + bool canShowCLowLower = showLower && showLow; + ENUM_DRAW_TYPE donLowLowerDrawType = canShowCLowLower ? DRAW_LINE : DRAW_NONE; + ArraySetAsSeries(donLowLowerBuffer, true); + SetIndexBuffer(donLowLowerBufferIndex, donLowLowerBuffer, INDICATOR_DATA); + PlotIndexSetDouble(donLowLowerPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(donLowLowerPlotBufferIndex, PLOT_SHOW_DATA, canShowCLowLower); + PlotIndexSetInteger(donLowLowerPlotBufferIndex, PLOT_DRAW_TYPE, donLowLowerDrawType); + + // + // Data Buffers ... +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateBuffers( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + // + // bool canCalculate = true; + bool canCalculate = + barsLimit == 0 || + bar_index <= barsLimit; + if (canCalculate) + { + // + CalculateDonchains( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + else + { + FillBuffersZero(bar_index); + } +} + +// +// Custom ... + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + donOpenUpperBuffer[barIndex] = EMPTY_VALUE; + donOpenLowerBuffer[barIndex] = EMPTY_VALUE; + donCloseUpperBuffer[barIndex] = EMPTY_VALUE; + donCloseLowerBuffer[barIndex] = EMPTY_VALUE; + donHighUpperBuffer[barIndex] = EMPTY_VALUE; + donHighLowerBuffer[barIndex] = EMPTY_VALUE; + donLowUpperBuffer[barIndex] = EMPTY_VALUE; + donLowLowerBuffer[barIndex] = EMPTY_VALUE; +} + +/** + * Calculate Donchain ... + * + * @param bar_index: Integer, Bar Index ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + * @param _length: Integer, Donchain Length ... + * @param _ouBuffer: Double Array Reference ... + * @param _olBuffer: Double Array Reference ... + * @param _huBuffer: Double Array Reference ... + * @param _hlBuffer: Double Array Reference ... + * @param _luBuffer: Double Array Reference ... + * @param _llBuffer: Double Array Reference ... + * @param _cuBuffer: Double Array Reference ... + * @param _clBuffer: Double Array Reference ... + */ +void CalculateDonchain( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + // + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[], + // + int _length, + // + double &_ouBuffer[], + double &_olBuffer[], + double &_huBuffer[], + double &_hlBuffer[], + double &_luBuffer[], + double &_llBuffer[], + double &_cuBuffer[], + double &_clBuffer[] // +) +{ + // + double iUpper = 0; + double iLower = 0; + + // + // OPEN ... + + // + int from = bar_index; + + // + iUpper = open[ArrayMaximum(open, from, _length)]; + iLower = open[ArrayMinimum(open, from, _length)]; + + // + _ouBuffer[bar_index] = iUpper; + _olBuffer[bar_index] = iLower; + + // + // HIGH ... + + // + iUpper = high[ArrayMaximum(high, from, _length)]; + iLower = high[ArrayMinimum(high, from, _length)]; + + // + _huBuffer[bar_index] = iUpper; + _hlBuffer[bar_index] = iLower; + + // + // LOW ... + + // + iUpper = low[ArrayMaximum(low, from, _length)]; + iLower = low[ArrayMinimum(low, from, _length)]; + + // + _luBuffer[bar_index] = iUpper; + _llBuffer[bar_index] = iLower; + + // + // CLOSE ... + + // + iUpper = close[ArrayMaximum(close, from, _length)]; + iLower = close[ArrayMinimum(close, from, _length)]; + + // + _cuBuffer[bar_index] = iUpper; + _clBuffer[bar_index] = iLower; +} + +/** + * Calculate Different VWaps ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateDonchains( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + CalculateDonchain( + // + bar_index, + prevCalculated, + ratesTotal, + // + open, + high, + close, + low, + tickVolume, + // + donchainLength, + // + donOpenUpperBuffer, + donOpenLowerBuffer, + donHighUpperBuffer, + donHighLowerBuffer, + donLowUpperBuffer, + donLowLowerBuffer, + donCloseUpperBuffer, + donCloseLowerBuffer // + ); +} + +// \ No newline at end of file diff --git a/BKPS/14031218/Indicators/x-saherelm.x121.xhk.ex5 b/BKPS/14031218/Indicators/x-saherelm.x121.xhk.ex5 new file mode 100644 index 0000000..e5c2bd3 Binary files /dev/null and b/BKPS/14031218/Indicators/x-saherelm.x121.xhk.ex5 differ diff --git a/BKPS/14031218/Indicators/x-saherelm.x121.xhk.mq5 b/BKPS/14031218/Indicators/x-saherelm.x121.xhk.mq5 new file mode 100644 index 0000000..c6a7cfe --- /dev/null +++ b/BKPS/14031218/Indicators/x-saherelm.x121.xhk.mq5 @@ -0,0 +1,616 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XHK +// Description: XHK ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121 XHK Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121 XHK" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +// Market ... +input group "Market"; +input int xhkSmoothingLength = 14; // Length +input ENUM_X_MA_METHOD xhkSmoothingMode = X_MA_MODE_EMA; // Smoothing Method +input bool xhkIgnoreSmoothingShadows = false; // Ignore Smoothed Bar Shadows + +// +input group "Presentation"; + +// +input int startCalculationForLastBars = 1000; // Calculate Last n Bars + +// +input bool drawRawXHKCandles = true; // Draw Raw Candle +input bool drawSmoothedXHKCandles = true; // Draw Smoothed Candle + +// +// Buffers ... + +// +#property indicator_chart_window + +// +#property indicator_buffers 10 +#property indicator_plots 2 + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +// PLOTTED Buffers ... + +// +#define openHKBufferIndex 0 +double openHKBuffer[]; + +// +#define highHKBufferIndex 1 +double highHKBuffer[]; + +// +#define lowHKBufferIndex 2 +double lowHKBuffer[]; + +// +#define closeHKBufferIndex 3 +double closeHKBuffer[]; + +// +#define rawHKColorBufferIndex 4 +double rawHKColorBuffer[]; + +// +#define rawHKBufferIndex 0 +#property indicator_label1 "X121 XHK Open;X121 XHK High;X121 XHK Low;X121 XHK Close" +#property indicator_type1 DRAW_COLOR_CANDLES +#property indicator_color1 CLR_NONE, clrDodgerBlue, clrDarkGoldenrod + +// +// Open ... +#define openBufferIndex 5 +double openBuffer[]; + +// +// High ... +#define highBufferIndex 6 +double highBuffer[]; + +// +// Low ... +#define lowBufferIndex 7 +double lowBuffer[]; + +// +// Close ... +#define closeBufferIndex 8 +double closeBuffer[]; + +// +// Candle Color ... +#define candleColorBufferIndex 9 +double candleColorBuffer[]; + +// +#define candlesBufferIndex 1 +#property indicator_label2 "X121 XHKSM Open;X121 XHKSM High;X121 XHKSM Low;X121 XHKSM Close" +#property indicator_type2 DRAW_COLOR_CANDLES +#property indicator_color2 CLR_NONE, clrAqua, clrMagenta + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // Fill All Buffers by Zero ... + if (prev_calculated == 0) + { + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = + // + true + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(0, xhkSmoothingLength); + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + + // + // RAW ... + + // + // Raw Candles Color ... + ArraySetAsSeries(rawHKColorBuffer, true); + SetIndexBuffer(rawHKColorBufferIndex, rawHKColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Set EMPTY_VALUE on Candles Buffer ... + PlotIndexSetDouble(rawHKBufferIndex, PLOT_EMPTY_VALUE, 0.0); + PlotIndexSetInteger(rawHKBufferIndex, PLOT_SHOW_DATA, false); + + // + // Open ... + ArraySetAsSeries(openHKBuffer, true); + SetIndexBuffer(openHKBufferIndex, openHKBuffer, INDICATOR_DATA); + + // + // High ... + ArraySetAsSeries(highHKBuffer, true); + SetIndexBuffer(highHKBufferIndex, highHKBuffer, INDICATOR_DATA); + + // + // Close ... + ArraySetAsSeries(closeHKBuffer, true); + SetIndexBuffer(closeHKBufferIndex, closeHKBuffer, INDICATOR_DATA); + + // + // Low ... + ArraySetAsSeries(lowHKBuffer, true); + SetIndexBuffer(lowHKBufferIndex, lowHKBuffer, INDICATOR_DATA); + + // + // SMOOTHED ... + + // + // Candles Color ... + ArraySetAsSeries(candleColorBuffer, true); + SetIndexBuffer(candleColorBufferIndex, candleColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Set EMPTY_VALUE on Candles Buffer ... + PlotIndexSetDouble(candlesBufferIndex, PLOT_EMPTY_VALUE, 0.0); + PlotIndexSetInteger(candlesBufferIndex, PLOT_SHOW_DATA, false); + + // + // Open ... + ArraySetAsSeries(openBuffer, true); + SetIndexBuffer(openBufferIndex, openBuffer, INDICATOR_DATA); + + // + // High ... + ArraySetAsSeries(highBuffer, true); + SetIndexBuffer(highBufferIndex, highBuffer, INDICATOR_DATA); + + // + // Close ... + ArraySetAsSeries(closeBuffer, true); + SetIndexBuffer(closeBufferIndex, closeBuffer, INDICATOR_DATA); + + // + // Low ... + ArraySetAsSeries(lowBuffer, true); + SetIndexBuffer(lowBufferIndex, lowBuffer, INDICATOR_DATA); +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateBuffers( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + // + bool canCalculate = + barsLimit == 0 || + bar_index <= barsLimit; + if (canCalculate) + { + // + CalculateXHK( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low // + ); + } + else + { + FillBuffersZero(bar_index); + } +} + +// +// Custom ... + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + lowHKBuffer[barIndex] = 0.0; + openHKBuffer[barIndex] = 0.0; + highHKBuffer[barIndex] = 0.0; + closeHKBuffer[barIndex] = 0.0; + rawHKColorBuffer[barIndex] = hideColorIDX; + + // + lowBuffer[barIndex] = 0.0; + openBuffer[barIndex] = 0.0; + highBuffer[barIndex] = 0.0; + closeBuffer[barIndex] = 0.0; + candleColorBuffer[barIndex] = hideColorIDX; +} + +/** + * Calculate ATR Zones ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + */ +void CalculateXHK( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[] // +) +{ + // + double mPrevHKOpenValue; + double mPrevHKCloseValue; + + // + if (ArraySize(open) <= bar_index + 1) + { + // + mPrevHKOpenValue = 0; + mPrevHKCloseValue = 0; + } + else + { + // + mPrevHKOpenValue = openHKBuffer[bar_index + 1]; + mPrevHKCloseValue = closeHKBuffer[bar_index + 1]; + } + + // + double mHKOpenValue = (mPrevHKOpenValue + mPrevHKCloseValue) / 2; + double mHKCloseValue = (open[bar_index] + high[bar_index] + close[bar_index] + low[bar_index]) / 4; + double mHKHighValue = MathMax(high[bar_index], MathMax(mHKOpenValue, mHKCloseValue)); + double mHKLowValue = MathMin(low[bar_index], MathMin(mHKOpenValue, mHKCloseValue)); + + // + double candleColorValue = + mHKOpenValue < mHKCloseValue ? bullishColorIDX : bearishColorIDX; + + // + // Raw HK Buffers ... + openHKBuffer[bar_index] = mHKOpenValue; + highHKBuffer[bar_index] = mHKHighValue; + lowHKBuffer[bar_index] = mHKLowValue; + closeHKBuffer[bar_index] = mHKCloseValue; + rawHKColorBuffer[bar_index] = drawRawXHKCandles ? candleColorValue : hideColorIDX; + + // + // Apply Smoothing ... + bool canSmooth = xhkSmoothingLength > 0 && + xhkSmoothingMode != X_MA_MODE_NONE; + if (!canSmooth) + { + // + double min = MathMin(mHKOpenValue, mHKCloseValue); + double max = MathMax(mHKOpenValue, mHKCloseValue); + + // + openBuffer[bar_index] = mHKOpenValue; + highBuffer[bar_index] = xhkIgnoreSmoothingShadows ? max : mHKHighValue; + lowBuffer[bar_index] = xhkIgnoreSmoothingShadows ? min : mHKLowValue; + closeBuffer[bar_index] = mHKCloseValue; + candleColorBuffer[bar_index] = drawSmoothedXHKCandles ? candleColorValue : hideColorIDX; + } + else + { + // + // Open ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + xhkSmoothingLength, + openHKBuffer, + openBuffer, + xhkSmoothingMode // + ); + + // + // Close ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + xhkSmoothingLength, + closeHKBuffer, + closeBuffer, + xhkSmoothingMode // + ); + + // + // Ignoring Shadows ... + if (!xhkIgnoreSmoothingShadows) + { + // + // High ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + xhkSmoothingLength, + highHKBuffer, + highBuffer, + xhkSmoothingMode // + ); + + // + // Low ... + iMAOnBuffer( + ratesTotal, + prevCalculated, + bar_index, + xhkSmoothingLength, + lowHKBuffer, + lowBuffer, + xhkSmoothingMode // + ); + } + else + { + // + double min = MathMin(closeBuffer[bar_index], openBuffer[bar_index]); + double max = MathMin(closeBuffer[bar_index], openBuffer[bar_index]); + + // + lowBuffer[bar_index] = min; + highBuffer[bar_index] = max; + } + + // + // Calculate Smoothed Color ... + candleColorValue = + openBuffer[bar_index] < closeBuffer[bar_index] ? bullishColorIDX : bearishColorIDX; + candleColorBuffer[bar_index] = drawSmoothedXHKCandles ? candleColorValue : hideColorIDX; + } +} + +// \ No newline at end of file diff --git a/BKPS/14031218/Indicators/x-saherelm.x121.xpv.ex5 b/BKPS/14031218/Indicators/x-saherelm.x121.xpv.ex5 new file mode 100644 index 0000000..32d3afb Binary files /dev/null and b/BKPS/14031218/Indicators/x-saherelm.x121.xpv.ex5 differ diff --git a/BKPS/14031218/Indicators/x-saherelm.x121.xpv.mq5 b/BKPS/14031218/Indicators/x-saherelm.x121.xpv.mq5 new file mode 100644 index 0000000..0af0a37 --- /dev/null +++ b/BKPS/14031218/Indicators/x-saherelm.x121.xpv.mq5 @@ -0,0 +1,1074 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XPV +// Description: XPV ... +// +// +// 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 XPV Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121 XPV" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +// Market ... +input group "Market"; + +// +input group "Short"; +input ENUM_X_PERIOD_METHOD scMethod = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES scPeriod = NULL; // Time Period + +// +input group "Medium"; +input ENUM_X_PERIOD_METHOD mcMethod = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES mcPeriod = NULL; // Time Period + +// +input group "Long"; +input ENUM_X_PERIOD_METHOD lcMethod = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES lcPeriod = NULL; // Time Period + +// +input group "Hind"; +input ENUM_X_PERIOD_METHOD hcMethod = X_PERIOD_AUTO; // How to Find Period +input ENUM_TIMEFRAMES hcPeriod = NULL; // Time Period + +// +input group "Boundary Detection"; +input ENUM_SERIESMODE hhMode = MODE_HIGH; // Highest High Calculation Method +input ENUM_SERIESMODE llMode = MODE_LOW; // Lowest Low Calculation Method +input ENUM_X_FIBO_LEVELS goldenZoneLevel = X_FIBO_LEVEL_382; // Golden Zone Detection + +// +input group "Sar Detection"; +input double sarStep = 0.02; // Step +input double sarMax = 0.2; // Maximum + +// +// Presentation ... +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 showGoldenZones = true; // Show Golden Zones + +// +// Buffers ... + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#property indicator_chart_window + +// +#property indicator_buffers 15 +#property indicator_plots 5 + +// +// Plot Buffers ... + +// +// 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 + +// +#define peaksGoldenZoneBufferIndex 3 +double peaksGoldenZoneBuffer[]; + +// +#property indicator_label4 "X121 PEAKGZ" +#property indicator_type4 DRAW_LINE +#property indicator_color4 clrGold +#property indicator_style4 STYLE_DOT +#property indicator_width4 1 + +// +#define valesGoldenZoneBufferIndex 4 +double valesGoldenZoneBuffer[]; + +// +#property indicator_label5 "X121 VALEGZ" +#property indicator_type5 DRAW_LINE +#property indicator_color5 clrGold +#property indicator_style5 STYLE_DOT +#property indicator_width5 1 + +// +// Data Buffers ... + +// +int mLastBufferIndex = 4; + +// +// 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[]; + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +// SAR Handler ... +int sarHandler = INVALID_HANDLE; + +// +// XMarketCycle sc; +int mSCLength = 0; +ENUM_TIMEFRAMES mSCPeriod = NULL; + +// +// XMarketCycle mc; +int mMCLength = 0; +ENUM_TIMEFRAMES mMCPeriod = NULL; + +// +// XMarketCycle lc; +int mLCLength = 0; +ENUM_TIMEFRAMES mLCPeriod = NULL; + +// +// XMarketCycle hc; +int mHCLength = 0; +ENUM_TIMEFRAMES mHCPeriod = NULL; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // 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); + + // + // 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 = false; + + // + result = + // + // SAR ... + sarMax > 0 && + sarStep > 0 && + sarMax > sarStep && + // + // 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; + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + + // + // 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); + + // + // Golden Zones ... + + // + ENUM_DRAW_TYPE goldenZonesDrawType = showGoldenZones ? DRAW_LINE : DRAW_NONE; + + // + // PEAK Golden Zone ... + + // + ArraySetAsSeries(peaksGoldenZoneBuffer, true); + SetIndexBuffer(peaksGoldenZoneBufferIndex, peaksGoldenZoneBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(peaksGoldenZoneBufferIndex, PLOT_SHOW_DATA, showGoldenZones); + PlotIndexSetInteger(peaksGoldenZoneBufferIndex, PLOT_DRAW_TYPE, goldenZonesDrawType); + + // + // VALE Golden Zone ... + + // + ArraySetAsSeries(valesGoldenZoneBuffer, true); + SetIndexBuffer(valesGoldenZoneBufferIndex, valesGoldenZoneBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(valesGoldenZoneBufferIndex, PLOT_SHOW_DATA, showGoldenZones); + PlotIndexSetInteger(valesGoldenZoneBufferIndex, PLOT_DRAW_TYPE, goldenZonesDrawType); + + // + // 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); +} + +/** + * 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); + } + 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] = EMPTY_VALUE; + cLLBuffer[barIndex] = EMPTY_VALUE; + + // + // SHORT ... + sHHBuffer[barIndex] = EMPTY_VALUE; + sLLBuffer[barIndex] = EMPTY_VALUE; + + // + // MEDIUM ... + mHHBuffer[barIndex] = EMPTY_VALUE; + mLLBuffer[barIndex] = EMPTY_VALUE; + + // + // LONG ... + lHHBuffer[barIndex] = EMPTY_VALUE; + lLLBuffer[barIndex] = EMPTY_VALUE; + + // + // HIND ... + hHHBuffer[barIndex] = EMPTY_VALUE; + hLLBuffer[barIndex] = EMPTY_VALUE; + + // + // PEAKS ... + peaksBuffer[barIndex] = EMPTY_VALUE; + + // + // VALES ... + valesBuffer[barIndex] = EMPTY_VALUE; + + // + // SARS ... + sarBuffer[barIndex] = EMPTY_VALUE; +} + +/** + * 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; + + // + // Peaks Golden Zone ... + double iPeakGoldenZone = GetFibonacciLevel( + iPeak, + iVale, + goldenZoneLevel, + X_DIRECTION_BULLISH // + ); + peaksGoldenZoneBuffer[barIndex] = iPeakGoldenZone; + + // + // Vales Golden Zone ... + double iValeGoldenZone = GetFibonacciLevel( + iPeak, + iVale, + goldenZoneLevel, + X_DIRECTION_BEARISH // + ); + valesGoldenZoneBuffer[barIndex] = iValeGoldenZone; +} + +// \ No newline at end of file diff --git a/BKPS/14031218/Indicators/x-saherelm.x121.xstr.ex5 b/BKPS/14031218/Indicators/x-saherelm.x121.xstr.ex5 new file mode 100644 index 0000000..03b3349 Binary files /dev/null and b/BKPS/14031218/Indicators/x-saherelm.x121.xstr.ex5 differ diff --git a/BKPS/14031218/Indicators/x-saherelm.x121.xstr.mq5 b/BKPS/14031218/Indicators/x-saherelm.x121.xstr.mq5 new file mode 100644 index 0000000..cccce4f --- /dev/null +++ b/BKPS/14031218/Indicators/x-saherelm.x121.xstr.mq5 @@ -0,0 +1,636 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XSTR +// Description: XSTR ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121 XSTR Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121 XSTR" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +// Market ... +input group "Market"; +input int strLength = 14; // Length +input double strMultiplier = 3; // Multiplier +input ENUM_APPLIED_PRICE strAppliedTo = PRICE_MEDIAN; // Applied To + +// +input group "Presentation"; + +// +input bool showStr = true; // Show Str +input bool showStrUpper = true; // Show Str Upper +input bool showStrLower = true; // Show Str Lower + +// +// Buffers ... + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#property indicator_chart_window + +// +#property indicator_buffers 7 +#property indicator_plots 3 + +// +// STR ... +#define strBufferIndex 0 +double strBuffer[]; + +#define strColorBufferIndex 1 +double strColorBuffer[]; + +// +#define strPlotBufferIndex 0 +#property indicator_label1 "X121 STR" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 CLR_NONE, clrLime, clrRed, clrGray +#property indicator_style1 STYLE_SOLID +#property indicator_width1 2 + +// +// Up ... +#define strUpBufferIndex 2 +double strUpBuffer[]; + +// +#define strUpPlotBufferIndex 1 +#property indicator_label2 "X121 STR U" +#property indicator_type2 DRAW_LINE +#property indicator_color2 C'255,106,0' +#property indicator_style2 STYLE_SOLID +#property indicator_width2 1 + +// +// Down ... +#define strDownBufferIndex 3 +double strDownBuffer[]; + +// +#define strDownPlotBufferIndex 2 +#property indicator_label3 "X121 STR D" +#property indicator_type3 DRAW_LINE +#property indicator_color3 C'255,106,0' +#property indicator_style3 STYLE_SOLID +#property indicator_width3 1 + +// +// Data Buffers ... + +// +int mLastBufferIndex = 3; + +// +// STR ... + +// +// Atr ... +#define atrBufferIndex mLastBufferIndex + 1 +double atrBuffer[]; + +// +// Price ... +#define strPriceBufferIndex mLastBufferIndex + 2 +double strPriceBuffer[]; + +// +// Trend ... +#define strStateBufferIndex mLastBufferIndex + 3 +double strStateBuffer[]; + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +// ATR Handler ... +int atrHandler = INVALID_HANDLE; + +// +bool isStrTrendChanged; +bool isStrStartBearishTrend; +bool isStrStartBullishTrend; + +// +int changeOfTrend; +int startBearishTrend; +int startBullishTrend; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + + // + // ATR ... + atrHandler = iATR( + _Symbol, + _Period, + strLength // + ); + bool isInited = atrHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + IndicatorRelease(atrHandler); +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // Prepare Buffers ... + + // + // Validate Calculated Bars ... + + // + // ATR ... + int atrCalculatedBars = BarsCalculated(atrHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // ATR ... + atrCalculatedBars >= 0 + // + ; + if (!isPassedRequiredCalculatedBars) + { + return prev_calculated; + } + + // + // + // checking for the limit start of calculation of an indicator ... + limit = + (prev_calculated > rates_total || prev_calculated <= 0) + ? maxLength + : prev_calculated - 1; + + // + // Buffers Copy ... + + // + // ATR ... + int copiedAtrs = CopyBuffer(atrHandler, 0, 0, rates_total, atrBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // ATR ... + copiedAtrs >= 0 + // + ; + if (!isPassedRequiredCopiedItems) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit; i < rates_total && !IsStopped(); i++) + { + // + CalculateBuffers( + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = + // + // STR ... + strLength > 0 && + strMultiplier > 0 + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(1, strLength); + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // STR ... + SetIndexBuffer(strBufferIndex, strBuffer, INDICATOR_DATA); + SetIndexBuffer(strColorBufferIndex, strColorBuffer, INDICATOR_COLOR_INDEX); + + // + ENUM_DRAW_TYPE strUpDrawType = showStrUpper ? DRAW_LINE : DRAW_NONE; + SetIndexBuffer(strUpBufferIndex, strUpBuffer, INDICATOR_DATA); + PlotIndexSetDouble(strUpPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(strUpPlotBufferIndex, PLOT_SHOW_DATA, showStrUpper); + PlotIndexSetInteger(strUpPlotBufferIndex, PLOT_DRAW_TYPE, strUpDrawType); + + // + ENUM_DRAW_TYPE strDownDrawType = showStrLower ? DRAW_LINE : DRAW_NONE; + SetIndexBuffer(strDownBufferIndex, strDownBuffer, INDICATOR_DATA); + PlotIndexSetDouble(strDownPlotBufferIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE); + PlotIndexSetInteger(strDownPlotBufferIndex, PLOT_SHOW_DATA, showStrLower); + PlotIndexSetInteger(strDownPlotBufferIndex, PLOT_DRAW_TYPE, strDownDrawType); + + // + // Data Buffers ... + + // + // STR ... + + // + SetIndexBuffer(strPriceBufferIndex, strPriceBuffer, INDICATOR_CALCULATIONS); + SetIndexBuffer(strStateBufferIndex, strStateBuffer, INDICATOR_CALCULATIONS); +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateBuffers( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + CalculateStr( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low // + ); +} + +// +// Custom ... + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + // STR ... + strBuffer[barIndex] = 0; + strUpBuffer[barIndex] = 0; + strDownBuffer[barIndex] = 0; + strPriceBuffer[barIndex] = 0; + strColorBuffer[barIndex] = hideColorIDX; + strStateBuffer[barIndex] = hideColorIDX; +} + +/** + * Calculate STR ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + */ +void CalculateStr( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[] // +) +{ + // + // Calculated Price ... + double price = GetAppliedPrice( + strAppliedTo, + open, + high, + low, + close, + bar_index // + ); + strPriceBuffer[bar_index] = price; + + // + double atr = atrBuffer[bar_index]; + + // + // Up ... + strUpBuffer[bar_index] = price + (strMultiplier * atr); + + // + // Down ... + strDownBuffer[bar_index] = price - (strMultiplier * atr); + + // + if (close[bar_index] > strUpBuffer[bar_index - 1]) + { + // + strStateBuffer[bar_index] = 1; + if (strStateBuffer[bar_index - 1] == -1) + { + changeOfTrend = 1; + } + } + else if (close[bar_index] < strDownBuffer[bar_index - 1]) + { + // + strStateBuffer[bar_index] = -1; + if (strStateBuffer[bar_index - 1] == 1) + { + changeOfTrend = 1; + } + } + else if (strStateBuffer[bar_index - 1] == 1) + { + // + strStateBuffer[bar_index] = 1; + changeOfTrend = 0; + } + else if (strStateBuffer[bar_index - 1] == -1) + { + // + strStateBuffer[bar_index] = -1; + changeOfTrend = 0; + } + + // + // Down Trend Starting ... + if (strStateBuffer[bar_index] < 0 && strStateBuffer[bar_index - 1] > 0) + { + startBearishTrend = 1; + } + else + { + startBearishTrend = 0; + } + + // + // Up Trend Starting ... + if (strStateBuffer[bar_index] > 0 && strStateBuffer[bar_index - 1] < 0) + { + startBullishTrend = 1; + } + else + { + startBullishTrend = 0; + } + + // + if (strStateBuffer[bar_index] > 0 && strDownBuffer[bar_index] < strDownBuffer[bar_index - 1]) + { + strDownBuffer[bar_index] = strDownBuffer[bar_index - 1]; + } + + // + if (strStateBuffer[bar_index] < 0 && strUpBuffer[bar_index] > strUpBuffer[bar_index - 1]) + { + strUpBuffer[bar_index] = strUpBuffer[bar_index - 1]; + } + + // + if (startBearishTrend == 1) + { + strUpBuffer[bar_index] = strPriceBuffer[bar_index] + (strMultiplier * atr); + } + + // + if (startBullishTrend == 1) + { + strDownBuffer[bar_index] = strPriceBuffer[bar_index] - (strMultiplier * atr); + } + + // + // Draw the indicator ... + + // + double colorIDX = hideColorIDX; + strColorBuffer[bar_index] = colorIDX; + + // + if (strStateBuffer[bar_index] == 1) + { + // + strBuffer[bar_index] = strDownBuffer[bar_index]; + if (changeOfTrend == 1) + { + strBuffer[bar_index - 1] = strBuffer[bar_index - 2]; + changeOfTrend = 0; + } + + // + colorIDX = bullishColorIDX; + } + else if (strStateBuffer[bar_index] == -1) + { + // + strBuffer[bar_index] = strUpBuffer[bar_index]; + if (changeOfTrend == 1) + { + // + strBuffer[bar_index - 1] = strBuffer[bar_index - 2]; + changeOfTrend = 0; + } + + // + colorIDX = bearishColorIDX; + } + + // + if (showStr) + { + strColorBuffer[bar_index] = colorIDX; + } +} + +// \ No newline at end of file diff --git a/BKPS/14031218/Indicators/x-saherelm.x121.xtrend.ex5 b/BKPS/14031218/Indicators/x-saherelm.x121.xtrend.ex5 new file mode 100644 index 0000000..9d4f424 Binary files /dev/null and b/BKPS/14031218/Indicators/x-saherelm.x121.xtrend.ex5 differ diff --git a/BKPS/14031218/Indicators/x-saherelm.x121.xtrend.mq5 b/BKPS/14031218/Indicators/x-saherelm.x121.xtrend.mq5 new file mode 100644 index 0000000..a9925c4 --- /dev/null +++ b/BKPS/14031218/Indicators/x-saherelm.x121.xtrend.mq5 @@ -0,0 +1,700 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XTREND +// Description: XTREND ... +// +// +// 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 XTREND Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121 XTREND" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +// Market ... +input group "Market"; + +input ENUM_APPLIED_PRICE trendPriceType = PRICE_CLOSE; // Detect Trend Price Type + +input group "MA Detection"; +input int maLength = 50; // MA Length +input ENUM_MA_METHOD maMethod = MODE_EMA; // MA Method +input ENUM_APPLIED_PRICE maAppliedTo = PRICE_CLOSE; // MA Applied To + +input group "ADX Detection"; +input int adxLength = 14; // ADX Length +input double adxThreshold = 25; // ADX Threshold for Strong Trends + +// +// Presentation ... +input group "Presentation"; + +// +input int startCalculationForLastBars = 1000; // Calculate Last n Bars +input int upTrendArrowCode = 233; // Up Trend Arrow Code +input int downTrendArrowCode = 234; // Down Trend Arrow Code + +// +input bool showOnlyTrendStart = true; // Show Only Trend Start +input bool showUpTrend = true; // Show Up Trend +input bool showDownTrend = true; // Show Down Trend + +// +#property indicator_chart_window + +// +#property indicator_buffers 8 +#property indicator_plots 2 + +// +// Plot Buffers ... + +// +#define upTrendBufferIndex 0 +double upTrendBuffer[]; + +// +#property indicator_label1 "X121 XTREND Up" +#property indicator_type1 DRAW_ARROW +#property indicator_color1 clrAqua +#property indicator_width1 1 + +// +#define downTrendBufferIndex 1 +double downTrendBuffer[]; + +// +#property indicator_label2 "X121 XTREND Down" +#property indicator_type2 DRAW_ARROW +#property indicator_color2 clrMagenta +#property indicator_width2 1 + +// +// Data Buffers ... + +// +int mLastBufferIndex = 1; + +// +#define maBufferIndex mLastBufferIndex + 1 +double maBuffer[]; + +// +#define adxBufferIndex mLastBufferIndex + 2 +double adxBuffer[]; + +// +#define adxPBufferIndex mLastBufferIndex + 3 +double adxPBuffer[]; + +// +#define adxMBufferIndex mLastBufferIndex + 4 +double adxMBuffer[]; + +// +#define upTBufferIndex mLastBufferIndex + 5 +double upTBuffer[]; + +// +#define downTBufferIndex mLastBufferIndex + 6 +double downTBuffer[]; + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +double lastValue = 0; +ENUM_X_DIRECTION lastTrendDir = X_DIRECTION_NONE; + +// +// MA Handler ... +int maHandler = INVALID_HANDLE; + +// +// ADX Handler ... +int adxHandler = INVALID_HANDLE; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + + // + // MA ... + maHandler = iMA( + _Symbol, + _Period, + maLength, + 0, + maMethod, + maAppliedTo // + ); + bool isInited = maHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // ADx ... + adxHandler = iADX( + _Symbol, + _Period, + adxLength // + ); + isInited = maHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + IndicatorSetInteger(INDICATOR_DIGITS, 2); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + IndicatorRelease(maHandler); + IndicatorRelease(adxHandler); +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // Validate Calculated Bars ... + + // + // MA ... + int maCalculatedBars = BarsCalculated(maHandler); + + // + // ADX ... + int adxCalculatedBars = BarsCalculated(adxHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // MA ... + maCalculatedBars >= maxLength && + // + // ADX ... + adxCalculatedBars >= maxLength + // + ; + if (!isPassedRequiredCalculatedBars) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + + // + // MA ... + int copiedMas = CopyBuffer(maHandler, 0, 0, limit, maBuffer); + + // + // ADX ... + int copiedAdxs = CopyBuffer(adxHandler, MAIN_LINE, 0, limit, adxBuffer); + int copiedAdxPs = CopyBuffer(adxHandler, PLUSDI_LINE, 0, limit, adxPBuffer); + int copiedAdxMs = CopyBuffer(adxHandler, MINUSDI_LINE, 0, limit, adxMBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // MA ... + copiedMas > 0 && + // + // ADX ... + copiedAdxs > 0 && + copiedAdxPs > 0 && + copiedAdxMs > 0 + // + ; + if (!isPassedRequiredCopiedItems) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + result = + // + // MA ... + maLength > 0 && + // + // ADX ... + adxLength > 0 && + adxThreshold > 0 + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(maLength, adxLength); + + // + return result; +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + + // + // UP Trend ... + + // + ENUM_DRAW_TYPE upTrendDrawType = showUpTrend ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(upTrendBuffer, true); + SetIndexBuffer(upTrendBufferIndex, upTrendBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(upTrendBufferIndex, PLOT_SHOW_DATA, showUpTrend); + PlotIndexSetInteger(upTrendBufferIndex, PLOT_DRAW_TYPE, upTrendDrawType); + + // + PlotIndexSetDouble(upTrendBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(upTrendBufferIndex, PLOT_ARROW, upTrendArrowCode); + + // + // DOWN Trend ... + + // + ENUM_DRAW_TYPE downTrendDrawType = showDownTrend ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(downTrendBuffer, true); + SetIndexBuffer(downTrendBufferIndex, downTrendBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(downTrendBufferIndex, PLOT_SHOW_DATA, showDownTrend); + PlotIndexSetInteger(downTrendBufferIndex, PLOT_DRAW_TYPE, downTrendDrawType); + + // + PlotIndexSetDouble(downTrendBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(downTrendBufferIndex, PLOT_ARROW, downTrendArrowCode); + + // + // Data Buffers ... + + // + ArraySetAsSeries(maBuffer, true); + SetIndexBuffer(maBufferIndex, maBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(adxBuffer, true); + SetIndexBuffer(adxBufferIndex, adxBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(adxPBuffer, true); + SetIndexBuffer(adxPBufferIndex, adxPBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(adxMBuffer, true); + SetIndexBuffer(adxMBufferIndex, adxMBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(upTBuffer, true); + SetIndexBuffer(upTBufferIndex, upTBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(downTBuffer, true); + SetIndexBuffer(downTBufferIndex, downTBuffer, INDICATOR_CALCULATIONS); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateBuffers( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + // + // bool canCalculate = true; + bool canCalculate = + barsLimit == 0 || + bar_index <= barsLimit; + if (canCalculate) + { + // + CalculateTrend( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + else + { + FillBuffersZero(bar_index); + } +} + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + upTrendBuffer[barIndex] = 0; + downTrendBuffer[barIndex] = 0; + + // + maBuffer[barIndex] = 0; + adxBuffer[barIndex] = 0; + adxPBuffer[barIndex] = 0; + adxMBuffer[barIndex] = 0; +} + +/** + * Calculate Trends ... + * + * @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 CalculateTrend( + 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 iPrice = GetAppliedPrice( + trendPriceType, + open, + high, + low, + close, + bar_index // + ); + + // + double iMa = maBuffer[bar_index]; + double iAdx = adxBuffer[bar_index]; + double points = GetPoints(_Symbol); + double points10 = 10 * points; + + // + bool isUpTrend = + iPrice > iMa && + iAdx > adxThreshold; + bool isDownTrend = + iPrice < iMa && + iAdx > adxThreshold; + + // + if (isUpTrend) + { + // + // double iLastValue = + // prevCalculated <= 0 + // ? 0 + // : upTrendBuffer[bar_index + 1]; + // if (iLastValue > 0 && + // iValue > iLastValue) + // { + // iValue = iLastValue; + // } + + // + double selectedValue = low[bar_index] - points10; + + // + double iValue = + !IsBullish(lastTrendDir) ? selectedValue + : !showOnlyTrendStart + ? lastValue + : 0; + + // + upTrendBuffer[bar_index] = iValue; + upTBuffer[bar_index] = selectedValue; + + // + downTrendBuffer[bar_index] = 0; + + // + lastValue = iValue; + lastTrendDir = X_DIRECTION_BULLISH; + } + else if (isDownTrend) + { + // + // double iLastValue = + // prevCalculated <= 0 + // ? 0 + // : downTrendBuffer[bar_index + 1]; + // if (iLastValue > 0 && + // iValue < iLastValue) + // { + // iValue = iLastValue; + // } + + // + double selectedValue = high[bar_index] + points10; + + // + double iValue = + !IsBearish(lastTrendDir) ? selectedValue + : !showOnlyTrendStart + ? lastValue + : 0; + + // + upTrendBuffer[bar_index] = 0; + downTrendBuffer[bar_index] = iValue; + downTBuffer[bar_index] = selectedValue; + + // + lastValue = iValue; + lastTrendDir = X_DIRECTION_BEARISH; + } + else + { + // + double iValue = + IsBullish(lastTrendDir) + ? showOnlyTrendStart + ? 0 + : lastValue + : IsBearish(lastTrendDir) + ? showOnlyTrendStart + ? 0 + : lastValue + : 0; + + // + upTrendBuffer[bar_index] = 0; + downTrendBuffer[bar_index] = 0; + + // + upTBuffer[bar_index] = 0; + downTBuffer[bar_index] = 0; + + // + lastValue = 0; + lastTrendDir = X_DIRECTION_NONE; + } +} \ No newline at end of file diff --git a/BKPS/14031218/Indicators/x-saherelm.x121.xvwap.ex5 b/BKPS/14031218/Indicators/x-saherelm.x121.xvwap.ex5 new file mode 100644 index 0000000..92c81d0 Binary files /dev/null and b/BKPS/14031218/Indicators/x-saherelm.x121.xvwap.ex5 differ diff --git a/BKPS/14031218/Indicators/x-saherelm.x121.xvwap.mq5 b/BKPS/14031218/Indicators/x-saherelm.x121.xvwap.mq5 new file mode 100644 index 0000000..6b63600 --- /dev/null +++ b/BKPS/14031218/Indicators/x-saherelm.x121.xvwap.mq5 @@ -0,0 +1,711 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XVWAP +// Description: XVWAP ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121 XVWAP Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121 XVWAP" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Inputs ... + +// +// Market ... +input group "Market"; +input int vwapFastLength = 20; // Fast Length +input int vwapMidLength = 40; // Mid Length +input int vwapSlowLength = 60; // Slow Length +input ENUM_APPLIED_PRICE vwapAppliedTo = PRICE_CLOSE; // Applied To + +// +// Presentation ... +input group "Presentation"; + +// +input int startCalculationForLastBars = 1000; // Calculate Last n Bars + +// +input bool showVWapFast = true; // Show VWap Fast +input bool showVWapMedium = true; // Show VWap Medium +input bool showVWapSlow = true; // Show VWap Slow + +// +// Buffers ... + +// +#define hideColorIDX 0 +#define bullishColorIDX 1 +#define bearishColorIDX 2 +#define neuturalColorIDX 3 + +// +#property indicator_chart_window + +// +#property indicator_buffers 11 +#property indicator_plots 3 + +// +// Plot Buffers ... + +// +// FAST ... +#define vwapFastBufferIndex 0 +double vwapFastBuffer[]; + +#define vwapFastColorBufferIndex 1 +double vwapFastColorBuffer[]; + +// +#define vwapFastPlotBufferIndex 0 +#property indicator_label1 "X121 VWF" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 CLR_NONE, clrAqua, clrMagenta, clrGray +#property indicator_style1 STYLE_SOLID +#property indicator_width1 2 + +// +// MID ... +#define vwapMidBufferIndex 2 +double vwapMidBuffer[]; + +#define vwapMidColorBufferIndex 3 +double vwapMidColorBuffer[]; + +// +#define vwapMidPlotBufferIndex 1 +#property indicator_label2 "X121 VWM" +#property indicator_type2 DRAW_COLOR_LINE +#property indicator_color2 CLR_NONE, clrGreen, clrRed, clrGray +#property indicator_style2 STYLE_SOLID +#property indicator_width2 2 + +// +// SLOW ... +#define vwapSlowBufferIndex 4 +double vwapSlowBuffer[]; + +#define vwapSlowColorBufferIndex 5 +double vwapSlowColorBuffer[]; + +// +#define vwapSlowPlotBufferIndex 2 +#property indicator_label3 "X121 VWS" +#property indicator_type3 DRAW_COLOR_LINE +#property indicator_color3 CLR_NONE, clrSteelBlue, clrDarkRed, clrGray +#property indicator_style3 STYLE_SOLID +#property indicator_width3 2 + +// +// Data Buffers ... + +// +int mLastBufferIndex = 5; + +// +// Volume ... +#define vwapVolumeBufferIndex mLastBufferIndex + 1 +double vwapVolumeBuffer[]; + +// +// Price ... +#define vwapPriceBufferIndex mLastBufferIndex + 2 +double vwapPriceBuffer[]; + +// +// Fast State ... +#define vwapFastStateBufferIndex mLastBufferIndex + 3 +double vwapFastStateBuffer[]; + +// +// Mid State ... +#define vwapMidStateBufferIndex mLastBufferIndex + 4 +double vwapMidStateBuffer[]; + +// +// Slow State ... +#define vwapSlowStateBufferIndex mLastBufferIndex + 5 +double vwapSlowStateBuffer[]; + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // Validate Calculated Bars ... + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + result = + // + vwapFastLength > 2 && + vwapMidLength > vwapFastLength && + vwapSlowLength > vwapMidLength + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + // XVWAP ... + result = MathMax(result, vwapFastLength); + result = MathMax(result, vwapMidLength); + result = MathMax(result, vwapSlowLength); + + // + return result; +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + + // + // Fast ... + ArraySetAsSeries(vwapFastBuffer, true); + ArraySetAsSeries(vwapFastColorBuffer, true); + SetIndexBuffer(vwapFastBufferIndex, vwapFastBuffer, INDICATOR_DATA); + SetIndexBuffer(vwapFastColorBufferIndex, vwapFastColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Mid ... + ArraySetAsSeries(vwapMidBuffer, true); + ArraySetAsSeries(vwapMidColorBuffer, true); + SetIndexBuffer(vwapMidBufferIndex, vwapMidBuffer, INDICATOR_DATA); + SetIndexBuffer(vwapMidColorBufferIndex, vwapMidColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Slow ... + ArraySetAsSeries(vwapSlowBuffer, true); + ArraySetAsSeries(vwapSlowColorBuffer, true); + SetIndexBuffer(vwapSlowBufferIndex, vwapSlowBuffer, INDICATOR_DATA); + SetIndexBuffer(vwapSlowColorBufferIndex, vwapSlowColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Data Buffers ... + + // + // Volumes ... + ArraySetAsSeries(vwapVolumeBuffer, true); + SetIndexBuffer(vwapVolumeBufferIndex, vwapVolumeBuffer, INDICATOR_CALCULATIONS); + + // + // Price ... + ArraySetAsSeries(vwapPriceBuffer, true); + SetIndexBuffer(vwapPriceBufferIndex, vwapPriceBuffer, INDICATOR_CALCULATIONS); + + // + // Fast State ... + ArraySetAsSeries(vwapFastStateBuffer, true); + SetIndexBuffer(vwapFastStateBufferIndex, vwapFastStateBuffer, INDICATOR_CALCULATIONS); + + // + // Mid State ... + ArraySetAsSeries(vwapMidStateBuffer, true); + SetIndexBuffer(vwapMidStateBufferIndex, vwapMidStateBuffer, INDICATOR_CALCULATIONS); + + // + // Slow State ... + ArraySetAsSeries(vwapSlowStateBuffer, true); + SetIndexBuffer(vwapSlowStateBufferIndex, vwapSlowStateBuffer, INDICATOR_CALCULATIONS); +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateBuffers( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + // + // bool canCalculate = true; + bool canCalculate = + barsLimit == 0 || + bar_index <= barsLimit; + if (canCalculate) + { + // + // Calculate Required VWAP Data Buffers ... + if (ratesTotal - bar_index <= maxLength) + { + // + CalculateVWAPDataBuffers( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + // Prevent Moving Forward ... + } + else + { + // + CalculateVWAPDataBuffers( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + + // + CalculateVWAPS( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + } + else + { + FillBuffersZero(bar_index); + } +} + +// +// Custom ... + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + vwapFastBuffer[barIndex] = EMPTY_VALUE; + vwapMidBuffer[barIndex] = EMPTY_VALUE; + vwapSlowBuffer[barIndex] = EMPTY_VALUE; + vwapVolumeBuffer[barIndex] = EMPTY_VALUE; + vwapPriceBuffer[barIndex] = EMPTY_VALUE; + + // + vwapFastColorBuffer[barIndex] = hideColorIDX; + vwapMidColorBuffer[barIndex] = hideColorIDX; + vwapSlowColorBuffer[barIndex] = hideColorIDX; + vwapFastStateBuffer[barIndex] = hideColorIDX; + vwapMidStateBuffer[barIndex] = hideColorIDX; + vwapSlowStateBuffer[barIndex] = hideColorIDX; +} + +/** + * Calculate VWAP Value for Specified Bar ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + * @param _length: Integer, Specified VWAP Length ... + * @param _show: Boolean, Specified Show Buffer or not ... + * @param _buffer: Double Array Reference, Points to Buffer ... + * @param _colorBuffer: Double Array Reference, Points to Color Buffer ... + * @param _stateBuffer: Double Array Reference, Points to State Buffer ... + */ +void CalculateVWAP( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[], + // + int _length, // Calculation Length + bool _show, + double &_buffer[], + double &_colorBuffer[], + double &_stateBuffer[] // +) +{ + // + double vSum = 0; + double pSum = 0; + double mSum = 0; + for (int x = 0; x < _length; x++) + { + // + pSum += vwapPriceBuffer[x + bar_index]; + vSum += vwapVolumeBuffer[x + bar_index]; + mSum += vwapPriceBuffer[x + bar_index] * vwapVolumeBuffer[x + bar_index]; + } + + // + double iValue = mSum / vSum; + iValue = NormalizeDouble(iValue, _Digits); + + // + _buffer[bar_index] = iValue; + + // + bool isBullish = low[bar_index] > iValue; + bool isBearish = high[bar_index] < iValue; + + // + double iColor = + isBullish + ? bullishColorIDX + : isBearish + ? bearishColorIDX + : neuturalColorIDX; + + // + _colorBuffer[bar_index] = hideColorIDX; + _stateBuffer[bar_index] = iColor; + if (_show) + { + _colorBuffer[bar_index] = iColor; + } +} + +/** + * Calculate VWAP Required Data Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateVWAPDataBuffers( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + 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 // + ); +} + +// \ No newline at end of file diff --git a/BKPS/14031218/Indicators/x-saherelm.x121.xwz.ex5 b/BKPS/14031218/Indicators/x-saherelm.x121.xwz.ex5 new file mode 100644 index 0000000..8c7c132 Binary files /dev/null and b/BKPS/14031218/Indicators/x-saherelm.x121.xwz.ex5 differ diff --git a/BKPS/14031218/Indicators/x-saherelm.x121.xwz.mq5 b/BKPS/14031218/Indicators/x-saherelm.x121.xwz.mq5 new file mode 100644 index 0000000..626ee8e --- /dev/null +++ b/BKPS/14031218/Indicators/x-saherelm.x121.xwz.mq5 @@ -0,0 +1,2780 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XWZ +// Description: XWZ ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Glzoneal Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm X121 XWZ Indicator" +#property strict + +// +// Definitions ... + +// +#define ShortName "X121_XWZ" + +// +// Includes Common Library ... +#include "../Classes/x-saherelm.x-alert.class.mq5" +#include "../Classes/x-saherelm.x-bar.analyser.class.mq5" +#include "../Classes/x-saherelm.x-poi.class.mq5" +#include "../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" +#include "../Libraries/x-saherelm.x-poi.extensions.lib.mq5" + +// +// Inputs ... + +// +// Market ... +input group "Market"; + +// +input group "Calculation"; +input ENUM_APPLIED_PRICE appliedTo = PRICE_CLOSE; // Detect Price Type + +// +input group "MA Detection"; +input int maLength = 20; // MA Length +input ENUM_MA_METHOD maMethod = MODE_EMA; // MA Method + +// +input group "ATR StopLoss"; +input int atrLength = 14; // ATR Length +input double atrMultiplier = 2; // ATR Multiplier + +// +input group "ADX Detection"; +input int adxLength = 14; // ADX Length +input double adxThreshold = 25; // ADX Threshold for Strong Trends + +// +input group "POI Detection"; +input ENUM_TIMEFRAMES orderBlockTF = PERIOD_H1; // Order Block Detection Time Frame +input ENUM_TIMEFRAMES fairValueGapTF = PERIOD_M15; // Fair Value Gap Detection Time Frame +input ENUM_TIMEFRAMES supDemTF = PERIOD_H4; // Supply and Demand Detection Time Frame + +// +input group "Alert"; +input bool mXWZEnableAlerts = true; // Enable Alerts +input bool mXWZPushAlerts = false; // Push Alerts +input bool mXWZMailAlerts = false; // Mail Alerts +input bool mXWZTerminalAlerts = false; // Terminal Alerts + +// +// Presentation ... +input group "Presentation"; + +// +input group "Buffer Presentation"; +input bool showMA = true; // Show Moving Average +input bool showPin = true; // Show Pin Bars +input bool showSwing = true; // Show Swing Bars +input bool showTrend = true; // Show Trend +input bool showEngulf = true; // Show Engulf Bars +input bool showLongSL = true; // Show Long SL +input bool showShortSL = true; // Show Short SL +input bool showMomentum = true; // Show Momentum Bars +input bool showRejection = true; // Show Rejection Bars + +// +input group "POI Presentation"; +input bool showPOIs = true; // Show POI(s) +input bool showOrderBlocks = true; // Show Order Blocks +input bool showFairValueGaps = true; // Show Fair Value Gaps +input bool showSupplyZones = true; // Show Supply Zones +input bool showDemandZones = true; // Show Demand Zones + +// +input group "Presentation Config"; +input int startCalculationForLastBars = 1000; // Calculate Last n Bars +input int upTrendArrowCode = 236; // Up Trend Arrow Code +input int downTrendArrowCode = 238; // Down Trend Arrow Code +input int swingLowArrowCode = 108; // Swing Low Arrow Code +input int swingHighArrowCode = 108; // Swing High Arrow Code +input int bullishPinArrowCode = 246; // Bullish Pin Arrow Code +input int bearishPinArrowCode = 248; // Bearish Pin Arrow Code +input int bullishEngulfArrowCode = 200; // Bullish Engulf Arrow Code +input int bearishEngulfArrowCode = 202; // Bearish Engulf Arrow Code +input int bullishMomentumArrowCode = 233; // Bullish Momentum Arrow Code +input int bearishMomentumArrowCode = 234; // Bearish Momentum Arrow Code +input int bullishRejectionArrowCode = 241; // Bullish Rejection Arrow Code +input int bearishRejectionArrowCode = 242; // Bearish Rejection Arrow Code + +// +#property indicator_chart_window + +// +#property indicator_buffers 17 +#property indicator_plots 15 + +// +// Plot Buffers ... + +// +#define maBufferIndex 0 +double maBuffer[]; + +// +#property indicator_label1 "X121-XWZ MA" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrLightSkyBlue +#property indicator_style1 STYLE_SOLID +#property indicator_width1 2 + +// +#define longSLBufferIndex 1 +double longSLBuffer[]; + +// +#property indicator_label2 "X121-XWZ Long SL" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrOrange +#property indicator_style2 STYLE_SOLID +#property indicator_width2 1 + +// +#define shortSLBufferIndex 2 +double shortSLBuffer[]; + +// +#property indicator_label3 "X121-XWZ Short SL" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrOrange +#property indicator_style3 STYLE_SOLID +#property indicator_width3 1 + +// +#define upTrendBufferIndex 3 +double upTrendBuffer[]; + +// +#property indicator_label4 "X121-XWZ Trend Up" +#property indicator_type4 DRAW_ARROW +#property indicator_color4 clrAqua +#property indicator_width4 3 + +// +#define downTrendBufferIndex 4 +double downTrendBuffer[]; + +// +#property indicator_label5 "X121-XWZ Trend Down" +#property indicator_type5 DRAW_ARROW +#property indicator_color5 clrMagenta +#property indicator_width5 3 + +// +#define bullishMomentumBufferIndex 5 +double bullishMomentumBuffer[]; + +// +#property indicator_label6 "X121-XWZ Bull Momentum" +#property indicator_type6 DRAW_ARROW +#property indicator_color6 clrAqua +#property indicator_width6 3 + +// +#define bearishMomentumBufferIndex 6 +double bearishMomentumBuffer[]; + +// +#property indicator_label7 "X121-XWZ Bear Momentum" +#property indicator_type7 DRAW_ARROW +#property indicator_color7 clrMagenta +#property indicator_width7 3 + +// +#define bullishRejectionBufferIndex 7 +double bullishRejectionBuffer[]; + +// +#property indicator_label8 "X121-XWZ Bull Rejection" +#property indicator_type8 DRAW_ARROW +#property indicator_color8 clrAqua +#property indicator_width8 3 + +// +#define bearishRejectionBufferIndex 8 +double bearishRejectionBuffer[]; + +// +#property indicator_label9 "X121-XWZ Bear Rejection" +#property indicator_type9 DRAW_ARROW +#property indicator_color9 clrMagenta +#property indicator_width9 3 + +// +#define bullishPinBufferIndex 9 +double bullishPinBuffer[]; + +// +#property indicator_label10 "X121-XWZ Bull Pin" +#property indicator_type10 DRAW_ARROW +#property indicator_color10 clrAqua +#property indicator_width10 3 + +// +#define bearishPinBufferIndex 10 +double bearishPinBuffer[]; + +// +#property indicator_label11 "X121-XWZ Bear Pin" +#property indicator_type11 DRAW_ARROW +#property indicator_color11 clrMagenta +#property indicator_width11 3 + +// +#define bullishEngulfBufferIndex 11 +double bullishEngulfBuffer[]; + +// +#property indicator_label12 "X121-XWZ Bull Engulf" +#property indicator_type12 DRAW_ARROW +#property indicator_color12 clrAqua +#property indicator_width12 3 + +// +#define bearishEngulfBufferIndex 12 +double bearishEngulfBuffer[]; + +// +#property indicator_label13 "X121-XWZ Bear Engulf" +#property indicator_type13 DRAW_ARROW +#property indicator_color13 clrMagenta +#property indicator_width13 3 + +// +#define swingLowBufferIndex 13 +double swingLowBuffer[]; + +// +#property indicator_label14 "X121-XWZ Swing Low" +#property indicator_type14 DRAW_ARROW +#property indicator_color14 clrAqua +#property indicator_width14 3 + +// +#define swingHighBufferIndex 14 +double swingHighBuffer[]; + +// +#property indicator_label15 "X121-XWZ Swing High" +#property indicator_type15 DRAW_ARROW +#property indicator_color15 clrMagenta +#property indicator_width15 3 + +// +// Data Buffers ... + +// +int mLastBufferIndex = 14; + +// +#define atrBufferIndex mLastBufferIndex + 1 +double atrBuffer[]; + +// +#define adxBufferIndex mLastBufferIndex + 2 +double adxBuffer[]; + +// +// Variables, Properties and etc ... + +// +// this counts Available Bars ... +int limit; + +// +int maxLength; + +// +// MA Handler ... +int maHandler = INVALID_HANDLE; + +// +// ATR Handler ... +int atrHandler = INVALID_HANDLE; + +// +// ADX Handler ... +int adxHandler = INVALID_HANDLE; + +// +XCAlert *mXWZAlert; +XBarTracker mXWZBarTracker; +CArrayObj mXWZDrawnObjects; +XCPOIDrawer *mXWZPOIDrawer; +XCBarAnalyser *mXWZBarAnalyser; + +// +// POI(s) ... + +// +bool mXWZDetectOrderBlocks = true; +bool mXWZDetectFairValueGaps = true; +bool mXWZDetectSupplyZones = true; +bool mXWZDetectDemandZones = true; + +// +bool mXWZIgnoreUnActivateds = true; + +// +bool mXWZForceStarteds = true; +bool mXWZForceUnBreaked = true; +bool mXWZForceActivation = true; + +// +int mXWZSuResRange = 21; +int mXWZOBFVGSameBars = 3; + +// +// Un Activated POI(s) ... +XCFVG *mXWZUnActivatedFVGs[]; +XCOrderBlock *mXWZUnActivatedOBs[]; +XCSupplyZone *mXWZUnActivatedSupplyZones[]; +XCDemandZone *mXWZUnActivatedDemandZones[]; + +// +// Activated POI(s) ... +XCFVG *mXWZActivatedFVGs[]; +XCOrderBlock *mXWZActivatedOBs[]; +XCSupplyZone *mXWZActivatedSupplyZones[]; +XCDemandZone *mXWZActivatedDemandZones[]; + +// +// Event Handlers ... + +/** + * Initialize Indicator ... + * + * @return ( int ) + */ +int OnInit() +{ + // + mXWZDrawnObjects.Clear(); + + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + // Initialize Indicator Handlers ... + + // + // MA ... + maHandler = iMA( + _Symbol, + _Period, + maLength, + 0, + maMethod, + appliedTo // + ); + bool isInited = maHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // ATR ... + atrHandler = iATR( + _Symbol, + _Period, + atrLength // + ); + isInited = maHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // ADX ... + adxHandler = iADX( + _Symbol, + _Period, + adxLength // + ); + isInited = maHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + maxLength = ExtractMaxLengthOfInputs(); + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + IndicatorSetInteger(INDICATOR_DIGITS, 2); + + // + // Initialize Bar Tracker ... + mXWZBarTracker.Init( + _Symbol, + _Period // + ); + + // + mXWZPOIDrawer = new XCPOIDrawer(); + ConfigurePOIDrawer(); + + // + mXWZAlert = new XCAlert(); + ConfigureAlert(); + + // + mXWZBarAnalyser = new XCBarAnalyser(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +/** + * De Initialize Indicator ... + * + * @param reason: Integer, De Initialization Reason ... + */ +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + IndicatorRelease(maHandler); + IndicatorRelease(atrHandler); + IndicatorRelease(adxHandler); + + // + mXWZDrawnObjects.Clear(); + + // + ZeroMemory(mXWZAlert); + ZeroMemory(mXWZPOIDrawer); + ZeroMemory(mXWZBarAnalyser); + + // + Clean(mXWZActivatedOBs); + Clean(mXWZActivatedFVGs); + Clean(mXWZActivatedSupplyZones); + Clean(mXWZActivatedDemandZones); + + // + Clean(mXWZUnActivatedOBs); + Clean(mXWZUnActivatedFVGs); + Clean(mXWZUnActivatedSupplyZones); + Clean(mXWZUnActivatedDemandZones); +} + +/** + * Calculate Bars ... + * + * @param rates_total: Integer, Total Bars on Chart ... + * @param prev_calculated: Integer, Total Calculated Bars on Charts ... + * @param time: DateTime Array, History of Open Time ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param low: Double Array, History of Low Prices ... + * @param close: Double Array, History of Close Prices ... + * @param tick_volume: Long, History of Tick Volumes on Bar ... + * @param volume: Long, History of Trade Volumes ... + * @param spread: Double, History of Spread Price ... + * + * @return ( int ) + */ +int OnCalculate( + const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[] // +) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // Validate Calculated Bars ... + + // + // MA ... + int maCalculatedBars = BarsCalculated(maHandler); + + // + // ATR ... + int atrCalculatedBars = BarsCalculated(atrHandler); + + // + // ADX ... + int adxCalculatedBars = BarsCalculated(adxHandler); + + // + bool isPassedRequiredCalculatedBars = + // + // MA ... + maCalculatedBars >= maxLength && + // + // ATR ... + atrCalculatedBars >= maxLength && + // + // ADX ... + adxCalculatedBars >= maxLength + // + ; + if (!isPassedRequiredCalculatedBars) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) + ? rates_total + : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + + // + // MA ... + int copiedMas = CopyBuffer(maHandler, 0, 0, limit, maBuffer); + + // + // ATR ... + int copiedAtr = CopyBuffer(atrHandler, MAIN_LINE, 0, limit, atrBuffer); + + // + // ADX ... + int copiedAdxs = CopyBuffer(adxHandler, MAIN_LINE, 0, limit, adxBuffer); + + // + // Validate Copied Items ... + bool isPassedRequiredCopiedItems = + // + // MA ... + copiedMas > 0 && + // + // ATR ... + copiedAtr > 0 && + // + // ADX ... + copiedAdxs > 0 + // + ; + if (!isPassedRequiredCopiedItems) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers( + // + i, + prev_calculated, + rates_total, + // + open, + high, + close, + low, + tick_volume // + ); + } + + // + return rates_total; +} + +// +// Functions ... + +/** + * Validate Input Args for Initialization ... + * + * @return ( bool ) + */ +bool ValidateInputs() +{ + // + bool result = false; + + // + result = + // + // MA ... + maLength > 0 && + // + // ATR ... + atrLength > 0 && + atrMultiplier > 0 && + // + // ADX ... + adxLength > 0 && + adxThreshold > 0 + // + ; + + // + return result; +} + +/** + * Extract Max Length of Inputs ... + * + * @return ( int ) + */ +int ExtractMaxLengthOfInputs() +{ + // + int result = 0; + + // + result = MathMax(maLength, atrLength); + result = MathMax(result, adxLength); + + // + return result; +} + +/** + * Set Indicator Short Name and also we can define Buffers Labels ... + */ +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +/** + * Define Required Buffers ... + */ +void DefineBuffers() +{ + // + // Plot Buffers ... + + // + // MA Buffer ... + + // + ENUM_DRAW_TYPE maDrawType = showMA ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(maBuffer, true); + SetIndexBuffer(maBufferIndex, maBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(maBufferIndex, PLOT_SHOW_DATA, showMA); + PlotIndexSetInteger(maBufferIndex, PLOT_DRAW_TYPE, maDrawType); + + // + PlotIndexSetDouble(maBufferIndex, PLOT_EMPTY_VALUE, 0); + + // + // LONG SL Buffer ... + + // + ENUM_DRAW_TYPE longSLDrawType = showLongSL ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(longSLBuffer, true); + SetIndexBuffer(longSLBufferIndex, longSLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(longSLBufferIndex, PLOT_SHOW_DATA, showLongSL); + PlotIndexSetInteger(longSLBufferIndex, PLOT_DRAW_TYPE, longSLDrawType); + + // + PlotIndexSetDouble(longSLBufferIndex, PLOT_EMPTY_VALUE, 0); + + // + // SHORT SL Buffer ... + + // + ENUM_DRAW_TYPE shortSLDrawType = showShortSL ? DRAW_LINE : DRAW_NONE; + + // + ArraySetAsSeries(shortSLBuffer, true); + SetIndexBuffer(shortSLBufferIndex, shortSLBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(shortSLBufferIndex, PLOT_SHOW_DATA, showShortSL); + PlotIndexSetInteger(shortSLBufferIndex, PLOT_DRAW_TYPE, shortSLDrawType); + + // + PlotIndexSetDouble(shortSLBufferIndex, PLOT_EMPTY_VALUE, 0); + + // + // UP Trend ... + + // + ENUM_DRAW_TYPE upTrendDrawType = showTrend ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(upTrendBuffer, true); + SetIndexBuffer(upTrendBufferIndex, upTrendBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(upTrendBufferIndex, PLOT_SHOW_DATA, showTrend); + PlotIndexSetInteger(upTrendBufferIndex, PLOT_DRAW_TYPE, upTrendDrawType); + + // + PlotIndexSetDouble(upTrendBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(upTrendBufferIndex, PLOT_ARROW, upTrendArrowCode); + + // + // DOWN Trend ... + + // + ENUM_DRAW_TYPE downTrendDrawType = showTrend ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(downTrendBuffer, true); + SetIndexBuffer(downTrendBufferIndex, downTrendBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(downTrendBufferIndex, PLOT_SHOW_DATA, showTrend); + PlotIndexSetInteger(downTrendBufferIndex, PLOT_DRAW_TYPE, downTrendDrawType); + + // + PlotIndexSetDouble(downTrendBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(downTrendBufferIndex, PLOT_ARROW, downTrendArrowCode); + + // + // Bullish Momentum ... + + // + ENUM_DRAW_TYPE bullishMomentumDrawType = showMomentum ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(bullishMomentumBuffer, true); + SetIndexBuffer(bullishMomentumBufferIndex, bullishMomentumBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(bullishMomentumBufferIndex, PLOT_SHOW_DATA, showMomentum); + PlotIndexSetInteger(bullishMomentumBufferIndex, PLOT_DRAW_TYPE, bullishMomentumDrawType); + + // + PlotIndexSetDouble(bullishMomentumBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(bullishMomentumBufferIndex, PLOT_ARROW, bullishMomentumArrowCode); + + // + // Bearish Momentum ... + + // + ENUM_DRAW_TYPE bearishMomentumDrawType = showMomentum ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(bearishMomentumBuffer, true); + SetIndexBuffer(bearishMomentumBufferIndex, bearishMomentumBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(bearishMomentumBufferIndex, PLOT_SHOW_DATA, showMomentum); + PlotIndexSetInteger(bearishMomentumBufferIndex, PLOT_DRAW_TYPE, bearishMomentumDrawType); + + // + PlotIndexSetDouble(bearishMomentumBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(bearishMomentumBufferIndex, PLOT_ARROW, bearishMomentumArrowCode); + + // + // Bullish Rejection ... + + // + ENUM_DRAW_TYPE bullishRejectionDrawType = showRejection ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(bullishRejectionBuffer, true); + SetIndexBuffer(bullishRejectionBufferIndex, bullishRejectionBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(bullishRejectionBufferIndex, PLOT_SHOW_DATA, showRejection); + PlotIndexSetInteger(bullishRejectionBufferIndex, PLOT_DRAW_TYPE, bullishRejectionDrawType); + + // + PlotIndexSetDouble(bullishRejectionBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(bullishRejectionBufferIndex, PLOT_ARROW, bullishRejectionArrowCode); + + // + // Bearish Rejection ... + + // + ENUM_DRAW_TYPE bearishRejectionDrawType = showRejection ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(bearishRejectionBuffer, true); + SetIndexBuffer(bearishRejectionBufferIndex, bearishRejectionBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(bearishRejectionBufferIndex, PLOT_SHOW_DATA, showRejection); + PlotIndexSetInteger(bearishRejectionBufferIndex, PLOT_DRAW_TYPE, bearishRejectionDrawType); + + // + PlotIndexSetDouble(bearishRejectionBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(bearishRejectionBufferIndex, PLOT_ARROW, bearishRejectionArrowCode); + + // + // Bullish Pin ... + + // + ENUM_DRAW_TYPE bullishPinDrawType = showPin ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(bullishPinBuffer, true); + SetIndexBuffer(bullishPinBufferIndex, bullishPinBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(bullishPinBufferIndex, PLOT_SHOW_DATA, showPin); + PlotIndexSetInteger(bullishPinBufferIndex, PLOT_DRAW_TYPE, bullishPinDrawType); + + // + PlotIndexSetDouble(bullishPinBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(bullishPinBufferIndex, PLOT_ARROW, bullishPinArrowCode); + + // + // Bearish Pin ... + + // + ENUM_DRAW_TYPE bearishPinDrawType = showPin ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(bearishPinBuffer, true); + SetIndexBuffer(bearishPinBufferIndex, bearishPinBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(bearishPinBufferIndex, PLOT_SHOW_DATA, showPin); + PlotIndexSetInteger(bearishPinBufferIndex, PLOT_DRAW_TYPE, bearishPinDrawType); + + // + PlotIndexSetDouble(bearishPinBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(bearishPinBufferIndex, PLOT_ARROW, bearishPinArrowCode); + + // + // Bullish Engulf ... + + // + ENUM_DRAW_TYPE bullishEngulfDrawType = showEngulf ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(bullishEngulfBuffer, true); + SetIndexBuffer(bullishEngulfBufferIndex, bullishEngulfBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(bullishEngulfBufferIndex, PLOT_SHOW_DATA, showEngulf); + PlotIndexSetInteger(bullishEngulfBufferIndex, PLOT_DRAW_TYPE, bullishEngulfDrawType); + + // + PlotIndexSetDouble(bullishEngulfBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(bullishEngulfBufferIndex, PLOT_ARROW, bullishEngulfArrowCode); + + // + // Bearish Engulf ... + + // + ENUM_DRAW_TYPE bearishEngulfDrawType = showEngulf ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(bearishEngulfBuffer, true); + SetIndexBuffer(bearishEngulfBufferIndex, bearishEngulfBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(bearishEngulfBufferIndex, PLOT_SHOW_DATA, showEngulf); + PlotIndexSetInteger(bearishEngulfBufferIndex, PLOT_DRAW_TYPE, bearishEngulfDrawType); + + // + PlotIndexSetDouble(bearishEngulfBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(bearishEngulfBufferIndex, PLOT_ARROW, bearishEngulfArrowCode); + + // + // Swing Low ... + + // + ENUM_DRAW_TYPE swingLowDrawType = showSwing ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(swingLowBuffer, true); + SetIndexBuffer(swingLowBufferIndex, swingLowBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(swingLowBufferIndex, PLOT_SHOW_DATA, showSwing); + PlotIndexSetInteger(swingLowBufferIndex, PLOT_DRAW_TYPE, swingLowDrawType); + + // + PlotIndexSetDouble(swingLowBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(swingLowBufferIndex, PLOT_ARROW, swingLowArrowCode); + + // + // Swing High ... + + // + ENUM_DRAW_TYPE swingHighDrawType = showSwing ? DRAW_ARROW : DRAW_NONE; + + // + ArraySetAsSeries(swingHighBuffer, true); + SetIndexBuffer(swingHighBufferIndex, swingHighBuffer, INDICATOR_DATA); + + // + PlotIndexSetInteger(swingHighBufferIndex, PLOT_SHOW_DATA, showSwing); + PlotIndexSetInteger(swingHighBufferIndex, PLOT_DRAW_TYPE, swingHighDrawType); + + // + PlotIndexSetDouble(swingHighBufferIndex, PLOT_EMPTY_VALUE, 0); + PlotIndexSetInteger(swingHighBufferIndex, PLOT_ARROW, swingHighArrowCode); + + // + // DATA Buffers ... + + // + ArraySetAsSeries(atrBuffer, true); + SetIndexBuffer(atrBufferIndex, atrBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(adxBuffer, true); + SetIndexBuffer(adxBufferIndex, adxBuffer, INDICATOR_CALCULATIONS); +} + +/** + * Calculate Custom Buffers ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateBuffers( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + int barsLimit = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : 0; + // + // bool canCalculate = true; + bool canCalculate = + barsLimit == 0 || + bar_index <= barsLimit; + if (canCalculate) + { + // + CalculatedPOIs( + // + bar_index, + prevCalculated, + ratesTotal, + // + open, + high, + close, + low, + tickVolume // + ); + + // + CalculateValues( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + } + else + { + FillBuffersZero(bar_index); + } +} + +/** + * Fill All Bufers to Zero Vlue for Specified Bar Index ... + * + * @param barIndex: Integer ... + */ +void FillBuffersZero(int barIndex) +{ + // + maBuffer[barIndex] = 0; + atrBuffer[barIndex] = 0; + adxBuffer[barIndex] = 0; + longSLBuffer[barIndex] = 0; + shortSLBuffer[barIndex] = 0; + upTrendBuffer[barIndex] = 0; + swingLowBuffer[barIndex] = 0; + swingHighBuffer[barIndex] = 0; + downTrendBuffer[barIndex] = 0; + bullishPinBuffer[barIndex] = 0; + bearishPinBuffer[barIndex] = 0; + bullishEngulfBuffer[barIndex] = 0; + bearishEngulfBuffer[barIndex] = 0; + bullishMomentumBuffer[barIndex] = 0; + bearishMomentumBuffer[barIndex] = 0; + bullishRejectionBuffer[barIndex] = 0; + bearishRejectionBuffer[barIndex] = 0; +} + +/** + * Calculate Vales ... + * + * @param bar_index: Integer, Represent Current Bar ... + * @param prevCalculated: Integer, Represent Previous Calculated Bars ... + * @param ratesTotal: Integer, Represents All Available Bars ... + * @param open: Double Array, History of Open Prices ... + * @param high: Double Array, History of High Prices ... + * @param close: Double Array, History of Close Prices ... + * @param low: Double Array, History of Low Prices ... + * @param tickVolume: Long, History of Tick Volumes on Bar ... + */ +void CalculateValues( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // Prepare Requirements ... + + // + XOHCL iBar; + bool isInited = iBar.Init( + _Symbol, + _Period, + bar_index // + ); + if (!isInited) + { + // + iBar.Clean(); + return; + } + + // + XOHCL pBar; + isInited = iBar.GetPreviousBar(pBar); + if (!isInited) + { + // + iBar.Clean(); + pBar.Clean(); + return; + } + int pIndex = pBar.Index(); + + // + // Calculate Applied Price ... + double iPrice = GetAppliedPrice( + appliedTo, + open, + high, + low, + close, + bar_index // + ); + + // + double iMa = maBuffer[bar_index]; + double iMaPrev = maBuffer[pIndex]; + double iAtr = atrBuffer[bar_index]; + double iAdx = adxBuffer[bar_index]; + double iAppliedAtr = iAtr * atrMultiplier; + + // + double points = GetPoints(_Symbol); + double points10 = 10 * points; + + // + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + + // + // SL Buffers ... + + // + double iLongSL = iPrice - iAppliedAtr; + double iShortSL = iPrice + iAppliedAtr; + + // + longSLBuffer[bar_index] = iLongSL; + shortSLBuffer[bar_index] = iShortSL; + + // + // Trend Buffers ... + + // + bool isUpTrend = + // + iPrice > iMa && + iBar.low < iMa && + iAdx > adxThreshold + // + ; + + // + bool isDownTrend = + // + iPrice < iMa && + iBar.high > iMa && + iAdx > adxThreshold + // + ; + + // + double upTrendValue = 0; + double downTrendValue = 0; + if (isUpTrend) + { + upTrendValue = iBar.low; + } + if (isDownTrend) + { + downTrendValue = iBar.high; + } + + // + upTrendBuffer[bar_index] = upTrendValue; + downTrendBuffer[bar_index] = downTrendValue; + + // + // Momentum Buffers ... + + // + bool isMomentum = mXWZBarAnalyser + .IsMomentumBar( + iBar, + iDir, + 1, // Extends ... + 70 // Body Percent ... + ); + bool isBullishMomentum = + isMomentum && + IsBullish(iDir); + bool isBearishMomentum = + isMomentum && + IsBearish(iDir); + if (isMomentum) + { + // + double iBullMomentumValue = 0; + double iBearMomentumValue = 0; + + // + if (isBullishMomentum) + { + // + double selectedValue = iBar.low; + + // + iBullMomentumValue = selectedValue; + } + + // + if (isBearishMomentum) + { + // + double selectedValue = iBar.high; + + // + iBearMomentumValue = selectedValue; + } + + // + bullishMomentumBuffer[bar_index] = iBullMomentumValue; + bearishMomentumBuffer[bar_index] = iBearMomentumValue; + } + + // + // Rejection Buffers ... + + // + bool isRejection = mXWZBarAnalyser + .IsRejectionBar( + iBar, + iDir, + 1, // Extends ... + 70 // Body Percent ... + ); + bool isBullishRejection = + isRejection && + IsBullish(iDir); + bool isBearishRejection = + isRejection && + IsBearish(iDir); + if (isRejection) + { + // + double iBullRejectionValue = 0; + double iBearRejectionValue = 0; + + // + if (isBullishRejection) + { + // + double selectedValue = iBar.low; + + // + iBullRejectionValue = selectedValue; + } + + // + if (isBearishRejection) + { + // + double selectedValue = iBar.high; + + // + iBearRejectionValue = selectedValue; + } + + // + bullishRejectionBuffer[bar_index] = iBullRejectionValue; + bearishRejectionBuffer[bar_index] = iBearRejectionValue; + } + + // + // Pin Buffers ... + + // + bool isPin = mXWZBarAnalyser + .IsPinBar( + iBar, + iDir, + 0, // Extends ... + 50, // Shadow Percent ... + 25 // Body Percent ... + ); + bool isBullishPin = + isPin && + IsBullish(iDir); + bool isBearishPin = + isPin && + IsBearish(iDir); + if (isPin) + { + // + double iBullPinValue = 0; + double iBearPinValue = 0; + + // + if (isBullishPin) + { + // + double selectedValue = iBar.low; + + // + iBullPinValue = selectedValue; + } + + // + if (isBearishPin) + { + // + double selectedValue = iBar.high; + + // + iBearPinValue = selectedValue; + } + + // + bullishPinBuffer[bar_index] = iBullPinValue; + bearishPinBuffer[bar_index] = iBearPinValue; + } + + // + // Engulf Buffers ... + + // + bool isEngulf = mXWZBarAnalyser + .IsEngulfBar( + iBar, + iDir, + 1, // Extends ... + 70 // Body Percent ... + ); + bool isBullishEngulf = + isEngulf && + IsBullish(iDir); + bool isBearishEngulf = + isEngulf && + IsBearish(iDir); + if (isEngulf) + { + // + double iBullEngulfValue = 0; + double iBearEngulfValue = 0; + + // + if (isBullishEngulf) + { + // + double selectedValue = iBar.low; + + // + iBullEngulfValue = selectedValue; + } + + // + if (isBearishEngulf) + { + // + double selectedValue = iBar.high; + + // + iBearEngulfValue = selectedValue; + } + + // + bullishEngulfBuffer[bar_index] = iBullEngulfValue; + bearishEngulfBuffer[bar_index] = iBearEngulfValue; + } + + // + // Swing Buffers ... + + // + bool isSwing = mXWZBarAnalyser + .IsSwing( + iBar, + iDir, + 2 // Range ... + ); + bool isSwingLow = + isSwing && + IsBullish(iDir); + bool isSwingHigh = + isSwing && + IsBearish(iDir); + if (isSwing) + { + // + double iSwingLowValue = 0; + double iSwingHighValue = 0; + + // + if (isSwingLow) + { + // + double selectedValue = iBar.low; + + // + iSwingLowValue = selectedValue; + } + + // + if (isSwingHigh) + { + // + double selectedValue = iBar.high; + + // + iSwingHighValue = selectedValue; + } + + // + swingLowBuffer[bar_index] = iSwingLowValue; + swingHighBuffer[bar_index] = iSwingHighValue; + } + + // + // Cleanup Resources ... + + // + iBar.Clean(); + pBar.Clean(); +} + +// +// POIS Functions ... + +// +void ConfigurePOIDrawer() +{ + // + if (mXWZPOIDrawer == NULL) + { + return; + } + + // + mXWZPOIDrawer.Prefix(ShortName); + mXWZPOIDrawer.ChartIdentification(ChartID()); + mXWZPOIDrawer.SubWindowIdentification(0); + + // + mXWZPOIDrawer.BullishFVGWidth(2); + mXWZPOIDrawer.BullishFVGStyle(STYLE_DOT); + mXWZPOIDrawer.BullishFVGColor(clrAqua); + + // + mXWZPOIDrawer.BearishFVGWidth(2); + mXWZPOIDrawer.BearishFVGStyle(STYLE_DOT); + mXWZPOIDrawer.BearishFVGColor(clrMagenta); + + // + mXWZPOIDrawer.SupportZoneWidth(1); + mXWZPOIDrawer.SupportZoneStyle(STYLE_DASHDOTDOT); + mXWZPOIDrawer.SupportZoneColor(clrLime); + + // + mXWZPOIDrawer.ResistanceZoneWidth(1); + mXWZPOIDrawer.ResistanceZoneStyle(STYLE_DASHDOTDOT); + mXWZPOIDrawer.ResistanceZoneColor(clrRed); + + // + mXWZPOIDrawer.BullishOrderBlockWidth(3); + mXWZPOIDrawer.BullishOrderBlockStyle(STYLE_DASH); + mXWZPOIDrawer.BullishOrderBlockColor(clrAqua); + + // + mXWZPOIDrawer.BearishOrderBlockWidth(3); + mXWZPOIDrawer.BearishOrderBlockStyle(STYLE_DASH); + mXWZPOIDrawer.BearishOrderBlockColor(clrMagenta); +} + +// +void ConfigureAlert() +{ + // + mXWZAlert.SetPrefix(ShortName); + + // + mXWZAlert.SetPushAlerts(mXWZPushAlerts); + mXWZAlert.SetMailAlerts(mXWZMailAlerts); + mXWZAlert.SetEnableAlerts(mXWZEnableAlerts); + mXWZAlert.SetTerminalAlerts(mXWZTerminalAlerts); +} + +// +void CalculatedPOIs( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + XOHCL iBar; + bool isInited = iBar.Init( + _Symbol, + _Period, + bar_index // + ); + if (!isInited) + { + // + iBar.Clean(); + return; + } + + // + XOHCL pBar; + isInited = iBar.GetPreviousBar(pBar); + if (!isInited) + { + // + iBar.Clean(); + pBar.Clean(); + return; + } + + // + // POI ... + DetectPOIs(iBar); + UpdatePOIs(iBar); + DrawPOIs(); + + // + iBar.Clean(); + pBar.Clean(); +} + +// +bool CanDetectPOIs() +{ + // + bool result = false; + + // + result = + // + mXWZDetectOrderBlocks || + mXWZDetectFairValueGaps || + mXWZDetectSupplyZones || + mXWZDetectDemandZones + // + ; + + // + return result; +} + +// +void DetectPOIs( + XOHCL &bar // +) +{ + // + if (!CanDetectPOIs()) + { + return; + } + + // + int barIndex = bar.Index(); + + // + if (barIndex <= 0) + { + return; + } + + // + DetectOrderBlock(bar); + DetectSupplyZone(bar); + DetectDemandZone(bar); + DetectFairValueGap(bar); + + // +} + +// +void UpdatePOIs( + XOHCL &bar // +) +{ + // + int count = 0; + bool has = false; + + // + // OrderBlock(s) ... + + // + has = HasChild(mXWZUnActivatedOBs); + if (has) + { + // + SpecifiedUpdateTo( + mXWZUnActivatedOBs, + bar.time // + ); + } + + // + // Fair Value Gaps ... + + // + has = HasChild(mXWZUnActivatedFVGs); + if (has) + { + // + SpecifiedUpdateTo( + mXWZUnActivatedFVGs, + bar.time // + ); + + // + count = ArraySize(mXWZUnActivatedFVGs); + } + + // + // Supply Zones ... + + // + has = HasChild(mXWZUnActivatedSupplyZones); + if (has) + { + // + SpecifiedUpdateTo( + mXWZUnActivatedSupplyZones, + bar.time // + ); + + // + count = ArraySize(mXWZUnActivatedSupplyZones); + } + + // + // Demand Zones ... + + // + has = HasChild(mXWZUnActivatedDemandZones); + if (has) + { + // + SpecifiedUpdateTo( + mXWZUnActivatedDemandZones, + bar.time // + ); + + // + count = ArraySize(mXWZUnActivatedDemandZones); + } +} + +// +void DrawPOIs() +{ + // + int count = 0; + bool has = false; + bool isCreated = false; + + // + if (!showPOIs) + { + return; + } + + // + // Order Blocks ... + if (showOrderBlocks) + { + // + bool showBullishOrderBlocks = true; + bool showBearishOrderBlocks = true; + + // + // UnActivated ... + count = ArraySize(mXWZUnActivatedOBs); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + bool isBullish = mXWZUnActivatedOBs[i].IsBullish(); + + // + if ((isBullish && + showBullishOrderBlocks) || + (!isBullish && + showBearishOrderBlocks)) + { + // + XCBaseObject *iObj; + isCreated = mXWZPOIDrawer + .CreateOrderBlock( + mXWZUnActivatedOBs[i], + iObj // + ); + if (isCreated) + { + mXWZDrawnObjects.Add(iObj); + } + } + } + } + } + + // + // Fair Value Gaps ... + if (showFairValueGaps) + { + // + bool showBullishFairValueGaps = true; + bool showBearishFairValueGaps = true; + + // + // UnActivated ... + count = ArraySize(mXWZUnActivatedFVGs); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + bool isBullish = mXWZUnActivatedFVGs[i].IsBullish(); + + // + if ((isBullish && + showBullishFairValueGaps) || + (!isBullish && + showBearishFairValueGaps)) + { + // + XCBaseObject *iObj; + isCreated = mXWZPOIDrawer + .CreateFairValueGap( + mXWZUnActivatedFVGs[i], + iObj // + ); + if (isCreated) + { + mXWZDrawnObjects.Add(iObj); + } + } + } + } + } + + // + // Supply Zones ... + if (showSupplyZones) + { + // + // UnActivated ... + count = ArraySize(mXWZUnActivatedSupplyZones); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + XCSupplyZoneObject *iObj; + isCreated = mXWZPOIDrawer + .CreateSupplyZone( + mXWZUnActivatedSupplyZones[i], + iObj // + ); + if (isCreated) + { + mXWZDrawnObjects.Add(iObj); + } + } + } + + // + // Activated ... + count = ArraySize(mXWZActivatedSupplyZones); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + } + } + } + + // + // Demand Zones ... + if (showDemandZones) + { + // + // UnActivated ... + count = ArraySize(mXWZUnActivatedDemandZones); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + XCDemandZoneObject *iObj; + isCreated = mXWZPOIDrawer + .CreateDemandZone( + mXWZUnActivatedDemandZones[i], + iObj // + ); + if (isCreated) + { + mXWZDrawnObjects.Add(iObj); + } + } + } + + // + // Activated ... + count = ArraySize(mXWZActivatedDemandZones); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + } + } + } + + // + ChartRedraw(); + + // +} + +// +// +// + +// +// Detect Order Block ... +void DetectOrderBlock(XOHCL &bar) +{ + // + int idx = -1; + int count = 0; + bool has = false; + + // + if (!mXWZDetectOrderBlocks) + { + return; + } + + // + int iBarIndex = bar.Index(orderBlockTF); + + // + XOHCL iBar; + bool isInited = iBar.Init( + bar.symbol, + orderBlockTF, + iBarIndex // + ); + if (!isInited) + { + return; + } + + // + XOHCL zoneBar; + ENUM_X_DIRECTION zoneDir; + has = mXWZBarAnalyser.HasOrderBlock( + iBar, + zoneBar, + zoneDir, + mXWZOBFVGSameBars // + ); + + // + if (!has) + { + // + zoneBar.Clean(); + return; + } + + // + XCOrderBlock *zone; + zone = new XCOrderBlock(); + has = zone.Init( + zoneBar, + zoneDir // + ); + + // + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + + // + return; + } + + // + // Check Start ... + if (mXWZForceStarteds) + { + // + XOHCL startedBar; + bool isBodyOut = false; + bool isStarted = zone.IsStarted( + zoneDir, + startedBar, + isBodyOut, + iBar.period // + ); + + // + has = isStarted; + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + startedBar.Clean(); + + // + return; + } + + // + startedBar.Clean(); + } + + // + // Check Activation ... + if (mXWZForceActivation) + { + // + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = zone.IsActivated( + zoneDir, + activationBar, + isActivationBarBodyIn, + false, + iBar.period // + ); + + // + has = !isActivated; + if (!has) + { + // + if (!mXWZIgnoreUnActivateds) + { + // + zone.To(activationBar.time); + + // + Add( + zone, + mXWZActivatedOBs // + ); + } + + // + zoneBar.Clean(); + ZeroMemory(zone); + activationBar.Clean(); + + // + return; + } + + // + activationBar.Clean(); + } + + // + // Check Breaktion ... + if (mXWZForceUnBreaked) + { + // + XOHCL breakedBar; + bool isBodyOut = false; + bool isBreaked = zone.IsBreaked( + zoneDir, + breakedBar, + isBodyOut, + false, + iBar.period // + ); + + // + has = !isBreaked; + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + breakedBar.Clean(); + + // + return; + } + + // + breakedBar.Clean(); + } + + // + // Check Indexes ... + + // + // UnActivateds ... + idx = FindIndex( + zone, + mXWZUnActivatedOBs // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + + // + return; + } + + // + // Activateds ... + idx = FindIndex( + zone, + mXWZActivatedOBs // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + + // + return; + } + + // + has = zone != NULL && + zone.IsValid(); + if (has) + { + // + zone.To(bar.time); + + // + Add( + zone, + mXWZUnActivatedOBs // + ); + } + + // + iBar.Clean(); + zoneBar.Clean(); +} + +// +// Detect Fair Value Gap ... +void DetectFairValueGap(XOHCL &bar) +{ + // + int idx = -1; + int count = 0; + bool has = false; + + // + if (!mXWZDetectFairValueGaps) + { + return; + } + + // + int iBarIndex = bar.Index(fairValueGapTF); + + // + XOHCL iBar; + bool isInited = iBar.Init( + bar.symbol, + fairValueGapTF, + iBarIndex // + ); + if (!isInited) + { + return; + } + + // + XOHCL zoneEndBar; + XOHCL zoneStartBar; + ENUM_X_DIRECTION zoneDir; + has = mXWZBarAnalyser.HasFairValueGap( + iBar, + zoneStartBar, + zoneEndBar, + zoneDir, + mXWZOBFVGSameBars // + ); + + // + if (!has) + { + // + zoneEndBar.Clean(); + zoneStartBar.Clean(); + return; + } + + // + XCFVG *zone; + zone = new XCFVG(); + has = zone.Init( + zoneStartBar, + zoneEndBar, + zoneDir // + ); + + // + if (!has) + { + // + ZeroMemory(zone); + zoneEndBar.Clean(); + zoneStartBar.Clean(); + + // + return; + } + + // + // Check Start ... + if (mXWZForceStarteds) + { + // + XOHCL startedBar; + bool isBodyOut = false; + bool isStarted = zone.IsStarted( + zoneDir, + startedBar, + isBodyOut, + iBar.period // + ); + + // + has = isStarted; + if (!has) + { + // + ZeroMemory(zone); + startedBar.Clean(); + zoneEndBar.Clean(); + zoneStartBar.Clean(); + + // + return; + } + + // + startedBar.Clean(); + } + + // + // Check Activation ... + if (mXWZForceActivation) + { + // + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = zone.IsActivated( + zoneDir, + activationBar, + isActivationBarBodyIn, + false, + iBar.period // + ); + + // + has = !isActivated; + if (!has) + { + // + ZeroMemory(zone); + zoneEndBar.Clean(); + zoneStartBar.Clean(); + activationBar.Clean(); + + // + return; + } + + // + activationBar.Clean(); + } + + // + // Check Breaktion ... + if (mXWZForceUnBreaked) + { + // + XOHCL breakedBar; + bool isBodyOut = false; + bool isBreaked = zone.IsBreaked( + zoneDir, + breakedBar, + isBodyOut, + false, + iBar.period // + ); + + // + has = !isBreaked; + if (!has) + { + // + ZeroMemory(zone); + breakedBar.Clean(); + zoneEndBar.Clean(); + zoneStartBar.Clean(); + + // + return; + } + + // + breakedBar.Clean(); + } + + // + // Check Indexes ... + + // + // UnActivateds ... + idx = FindIndex( + zone, + mXWZUnActivatedFVGs // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + ZeroMemory(zone); + zoneEndBar.Clean(); + zoneStartBar.Clean(); + + // + return; + } + + // + // Activateds ... + idx = FindIndex( + zone, + mXWZActivatedFVGs // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + ZeroMemory(zone); + zoneEndBar.Clean(); + zoneStartBar.Clean(); + + // + return; + } + + // + has = zone != NULL && + zone.IsValid(); + if (has) + { + // + zone.To(bar.time); + + // + Add( + zone, + mXWZUnActivatedFVGs // + ); + } + + // + iBar.Clean(); + zoneEndBar.Clean(); + zoneStartBar.Clean(); +} + +// +// Supply Zone ... +void DetectSupplyZone(XOHCL &bar) +{ + // + int idx = -1; + int count = 0; + bool has = false; + + // + if (!mXWZDetectSupplyZones) + { + return; + } + + // + int iBarIndex = bar.Index(supDemTF); + + // + XOHCL iBar; + bool isInited = iBar.Init( + bar.symbol, + supDemTF, + iBarIndex // + ); + if (!isInited) + { + return; + } + + // + int range = mXWZSuResRange * 2; + + // + XOHCL zoneBar; + ENUM_X_DIRECTION zoneDir = X_DIRECTION_BEARISH; + has = mXWZBarAnalyser.HasResistance( + iBar, + zoneBar, + range // + ); + + // + if (!has) + { + // + zoneBar.Clean(); + return; + } + + // + XCSupplyZone *zone; + zone = new XCSupplyZone(); + has = zone.Init( + zoneBar, + range, + true // + ); + + // + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + + // + return; + } + + // + // Check Start ... + if (mXWZForceStarteds) + { + // + XOHCL startedBar; + bool isBodyOut = false; + bool isStarted = zone.IsStarted( + zoneDir, + startedBar, + isBodyOut, + iBar.period // + ); + + // + has = isStarted; + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + startedBar.Clean(); + + // + return; + } + + // + startedBar.Clean(); + } + + // + // Check Activation ... + if (mXWZForceActivation) + { + // + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = zone.IsActivated( + zoneDir, + activationBar, + isActivationBarBodyIn, + false, + iBar.period // + ); + + // + has = !isActivated; + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + activationBar.Clean(); + + // + return; + } + + // + activationBar.Clean(); + } + + // + // Check Breaktion ... + if (mXWZForceUnBreaked) + { + // + XOHCL breakedBar; + bool isBodyOut = false; + bool isBreaked = zone.IsBreaked( + zoneDir, + breakedBar, + isBodyOut, + false, + iBar.period // + ); + + // + has = !isBreaked; + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + breakedBar.Clean(); + + // + return; + } + + // + breakedBar.Clean(); + } + + // + // Check Indexes ... + + // + // UnActivateds ... + idx = FindIndex( + zone, + mXWZUnActivatedSupplyZones // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + + // + return; + } + + // + // Activateds ... + idx = FindIndex( + zone, + mXWZActivatedSupplyZones // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + + // + return; + } + + // + has = zone != NULL && + zone.IsValid(); + if (has) + { + // + zone.To(bar.time); + + // + Add( + zone, + mXWZUnActivatedSupplyZones // + ); + } + + // + iBar.Clean(); + zoneBar.Clean(); +} + +// +// Demand Zone ... +void DetectDemandZone(XOHCL &bar) +{ + // + int idx = -1; + int count = 0; + bool has = false; + + // + if (!mXWZDetectDemandZones) + { + return; + } + + // + int iBarIndex = bar.Index(supDemTF); + + // + XOHCL iBar; + bool isInited = iBar.Init( + bar.symbol, + supDemTF, + iBarIndex // + ); + if (!isInited) + { + return; + } + + // + int range = mXWZSuResRange * 2; + + // + XOHCL zoneBar; + ENUM_X_DIRECTION zoneDir = X_DIRECTION_BULLISH; + has = mXWZBarAnalyser.HasSupport( + iBar, + zoneBar, + range // + ); + + // + if (!has) + { + // + zoneBar.Clean(); + return; + } + + // + XCDemandZone *zone; + zone = new XCDemandZone(); + has = zone.Init( + zoneBar, + range, + true // + ); + + // + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + + // + return; + } + + // + // Check Start ... + if (mXWZForceStarteds) + { + // + XOHCL startedBar; + bool isBodyOut = false; + bool isStarted = zone.IsStarted( + zoneDir, + startedBar, + isBodyOut, + iBar.period // + ); + + // + has = isStarted; + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + startedBar.Clean(); + + // + return; + } + + // + startedBar.Clean(); + } + + // + // Check Activation ... + if (mXWZForceActivation) + { + // + XOHCL activationBar; + bool isActivationBarBodyIn = false; + bool isActivated = zone.IsActivated( + zoneDir, + activationBar, + isActivationBarBodyIn, + false, + iBar.period // + ); + + // + has = !isActivated; + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + activationBar.Clean(); + + // + return; + } + + // + activationBar.Clean(); + } + + // + // Check Breaktion ... + if (mXWZForceUnBreaked) + { + // + XOHCL breakedBar; + bool isBodyOut = false; + bool isBreaked = zone.IsBreaked( + zoneDir, + breakedBar, + isBodyOut, + false, + iBar.period // + ); + + // + has = !isBreaked; + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + breakedBar.Clean(); + + // + return; + } + + // + breakedBar.Clean(); + } + + // + // Check Indexes ... + + // + // UnActivateds ... + idx = FindIndex( + zone, + mXWZUnActivatedDemandZones // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + + // + return; + } + + // + // Activateds ... + idx = FindIndex( + zone, + mXWZActivatedDemandZones // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + zoneBar.Clean(); + ZeroMemory(zone); + + // + return; + } + + // + has = zone != NULL && + zone.IsValid(); + if (has) + { + // + zone.To(bar.time); + + // + Add( + zone, + mXWZUnActivatedDemandZones // + ); + } + + // + iBar.Clean(); + zoneBar.Clean(); +} + +// \ No newline at end of file diff --git a/BKPS/14031218/Libraries/x-saherelm.common.lib.ex5 b/BKPS/14031218/Libraries/x-saherelm.common.lib.ex5 new file mode 100644 index 0000000..b843f89 Binary files /dev/null and b/BKPS/14031218/Libraries/x-saherelm.common.lib.ex5 differ diff --git a/BKPS/14031218/Libraries/x-saherelm.common.lib.mq5 b/BKPS/14031218/Libraries/x-saherelm.common.lib.mq5 new file mode 100644 index 0000000..423a96b --- /dev/null +++ b/BKPS/14031218/Libraries/x-saherelm.common.lib.mq5 @@ -0,0 +1,10893 @@ +/////////////////////////////////////////////////////// +// +// 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 +}; + +// +enum ENUM_X_FIBO_LEVELS +{ + X_FIBO_LEVEL_236, + X_FIBO_LEVEL_382, + X_FIBO_LEVEL_500, + X_FIBO_LEVEL_618, + X_FIBO_LEVEL_764, +}; + +// +double GetFiboLevelValue(ENUM_X_FIBO_LEVELS value) +{ + // + double result = 0; + + // + switch (value) + { + // + case X_FIBO_LEVEL_236: + result = 0.236; + break; + + // + case X_FIBO_LEVEL_382: + result = 0.382; + break; + + // + case X_FIBO_LEVEL_500: + result = 0.500; + break; + + // + case X_FIBO_LEVEL_618: + result = 0.618; + break; + + // + case X_FIBO_LEVEL_764: + result = 0.764; + break; + } + + // + return result; +} + +// +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, +}; + +// +string ToString(ENUM_X_SWING_TYPE value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_NO_SWING: + result = "NO_SWING"; + break; + + // + case X_SWING_LOW: + result = "SWING_LOW"; + break; + + // + case X_SWING_HIGH: + result = "SWING_HIGH"; + break; + } + + // + return result; +} + +// +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, + ENUM_TIMEFRAMES _volumePeriod = NULL // + ) + { + // + 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 = 0; + if (IsValid(_volumePeriod)) + { + _volume = iTickVolume(_symbol, _volumePeriod, 0); + } + + // + result = Init( + _symbol, + _time, + _bid, + _ask, + _spread, + _volume // + ); + + // + return result; + } + + /** + * Cleanup ... + */ + void Clean() + { + // + bid = 0; + ask = 0; + volume = 0; + time = NULL; + symbol = NULL; + + // + ZeroMemory(this); + } + + /** + * 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; + + // + ZeroMemory(this); + } + + // + // To String Representation ... + string ToString( + string dayId = "d", + string hourId = "h", + string minuteId = "m", + string secondId = "s", + string idSeparator = ": ", + string separator = ", ", + bool ignoreZeroValues = true + // + ) + { + // + string result = ""; + + // + // Days ... + if (!ignoreZeroValues || days > 0) + { + result += dayId + idSeparator + (string)days + separator; + } + + // + // Hours ... + if (!ignoreZeroValues || hours > 0) + { + // + string strHour = ToString(hours); + if (StringLen(strHour) == 1) + { + strHour = "0" + strHour; + } + + // + result += hourId + idSeparator + strHour + separator; + } + + // + // Minutes ... + if (!ignoreZeroValues || minutes > 0) + { + // + string strMinute = ToString(minutes); + if (StringLen(strMinute) == 1) + { + strMinute = "0" + strMinute; + } + + // + result += minuteId + idSeparator + strMinute + separator; + } + + // + // Seconds ... + if (!ignoreZeroValues || seconds > 0) + { + // + string strSec = ToString(seconds); + if (StringLen(strSec) == 1) + { + strSec = "0" + strSec; + } + + // + result += secondId + idSeparator + strSec; + } + + // + return result; + } +}; + +// +// 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; + + // + ZeroMemory(this); + } + + // + // 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; + } + + // + // Retrieve Required Price for Zone Checking ... + // For Bullish Zones => low; + // For Bearish Zones => high; + double GetZoneCheckValue(ENUM_X_DIRECTION forDir) + { + // + double result = 0; + + // + if (!IsValid() || + !HasDirection(forDir)) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + result = + isBullish + ? low + : high; + + 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; + } + + // + // Find Highest Bar Index ... + int FindHighestIndex( + int mLength, // Loopback ... + ENUM_SERIESMODE mMode // Calculation mode + ) + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + if (mLength < 2) + { + mLength = 2; + } + + // + result = iHighest( + symbol, + period, + mMode, + mLength, + Index()); + + // + return result; + } + + // + // Find Highest ... + double FindHighest( + int mLength, // Loopback ... + ENUM_SERIESMODE mMode // Calculation mode + ) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + int idx = FindHighestIndex( + mLength, + mMode); + if (idx <= -1) + { + return result; + } + + // + XOHCL iH; + result = iH.Init( + symbol, + period, + idx + // + ); + if (!result) + { + return result; + } + + // + result = iH.GetPrice(mMode); + + // + return result; + } + + // + // Find Highest ... + double FindHighestUp( + int mLength // Loopback ... + ) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = FindHighest(mLength, MODE_OPEN); + result = MathMax(mLength, FindHighest(mLength, MODE_CLOSE)); + + // + return result; + } + + // + // Find Lowest Bar Index ... + int FindLowestIndex( + int mLength, // Loopback ... + ENUM_SERIESMODE mMode // Calculation mode + ) + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + if (mLength < 2) + { + mLength = 2; + } + + // + result = iLowest( + symbol, + period, + mMode, + mLength, + Index()); + + // + return result; + } + + // + // Find Lowest ... + double FindLowest( + int mLength, // Loopback ... + ENUM_SERIESMODE mMode // Calculation mode + ) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + int idx = FindLowestIndex( + mLength, + mMode); + if (idx <= -1) + { + return result; + } + + // + XOHCL iL; + result = iL.Init( + symbol, + period, + idx + // + ); + if (!result) + { + return result; + } + + // + result = iL.GetPrice(mMode); + + // + return result; + } + + // + // Find Lowest ... + double FindLowesttDown( + int mLength // Loopback ... + ) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = FindLowest(mLength, MODE_OPEN); + result = MathMax(mLength, FindLowest(mLength, MODE_CLOSE)); + + // + return result; + } + + // + // Other ... + string GetTag(string prefix = "") + { + // + string result = NULL; + + // + result = + (IsValid(prefix) + ? prefix + "_" + : "") + + "XOHCL_" + symbol + "_" + ToString(period) + "_" + ToFormatString(time); + + // + return result; + } + + // + // Convert to String Representation ... + string ToString() + { + // + string result = ""; + + // + result = GetTypeName(this) + + "(O(" + ToString(open) + "),H(" + ToString(high) + "),C(" + ToString(close) + "),L(" + ToString(low) + "))"; + + // + return result; + } +}; + +// +// Tracking Times ... +struct XTimeTracker +{ + // + // Props ... + int xMonth; + int xDayOfWeek; + int xForWeekDay; + int xDay; + int xHour; + int xMinute; + + // + // Constructor ... + XTimeTracker() + { + Clean(); + } + + // + // Tools ... + + // + void Clean() + { + // + xDay = -1; + xHour = -1; + xMonth = -1; + xMinute = -1; + xDayOfWeek = -1; + xForWeekDay = -1; + + // + ZeroMemory(this); + } + + // + // Detecting New Minute ... + bool IsNewMinute() + { + // + bool result = false; + + // + // Retrieve Current Time as Struct ... + MqlDateTime timeStruct = GetCurrentTime(); + + // + // Check Houre ... + result = timeStruct.min != xMinute; + if (result) + { + xMinute = timeStruct.min; + } + + // + return result; + } + + // + // Detecting New Houre ... + bool IsNewHour() + { + // + bool result = false; + + // + // Retrieve Current Time as Struct ... + MqlDateTime timeStruct = GetCurrentTime(); + + // + // Check Houre ... + result = timeStruct.hour != xHour; + if (result) + { + xHour = timeStruct.hour; + } + + // + return result; + } + + // + // Detecting New Day ... + bool IsNewDay() + { + // + bool result = false; + + // + // Retrieve Current Time as Struct ... + MqlDateTime timeStruct = GetCurrentTime(); + + // + // Check Houre ... + result = timeStruct.day_of_year != xDay; + if (result) + { + xDay = timeStruct.day_of_year; + } + + // + return result; + } + + // + // Detecting New Week ... + bool IsNewWeek() + { + // + bool result = false; + + // + // Retrieve Current Time as Struct ... + MqlDateTime timeStruct = GetCurrentTime(); + + // + // Check Week ... + // Since Week Starts From Monday in Forex World ... + // we Calculate Start of Week by 1-Monday ... + result = + xDayOfWeek == -1 && + xForWeekDay == -1 + ? true + : timeStruct.day_of_week == 1 && + timeStruct.day_of_year > xForWeekDay; + + // + xForWeekDay = timeStruct.day_of_year; + xDayOfWeek = timeStruct.day_of_week; + + // + return result; + } + + // + // Detecting End Of Week ... + bool IsWeekEnd() + { + // + bool result = false; + + // + // Retrieve Current Time as Struct ... + MqlDateTime timeStruct = GetCurrentTime(); + + // + // Check WeekEnd ... + // Since Week Starts From Monday in Forex World ... + // we Calculate End of Week by 5-Friday ... + result = + xDayOfWeek != -1 && + timeStruct.day_of_week == 5 && + timeStruct.hour == 23 && + timeStruct.min == 59 && + timeStruct.sec == 59; + + // + return result; + } + + // + // Detecting New Month ... + bool IsNewMonth() + { + // + bool result = false; + + // + // Retrieve Current Time as Struct ... + MqlDateTime timeStruct = GetCurrentTime(); + + // + // Check Houre ... + result = timeStruct.mon != xMonth; + if (result) + { + xMonth = timeStruct.mon; + } + + // + return result; + } +}; + +// +// Tracking Bars on Specified Environment ... +struct XBarTracker +{ + // + string symbol; // Tracking Symbol + ENUM_TIMEFRAMES period; // Tracking Time Frame + + // + int lastTrackedBar; // Last Tracked Bar ... + + // + bool waitsUntilNext; // Waits Until Next Bar ... + + // + // Constructor ... + XBarTracker() + { + Clean(); + } + + // + // Initializer ... + bool Init( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL // Trading Period + ) + { + // + bool result = false; + + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + this.symbol = mSymbol; + this.period = mPeriod; + + // + this.lastTrackedBar = 0; + + // + result = true; + + // + return result; + } + + // + // Retrieve all Bars ... + int CountBars() + { + // + return iBars( + symbol, + period + // + ); + } + + // + // Check if it's New Bar ... + bool IsNewBar() + { + // + bool result = false; + + // + int currentBars = CountBars(); + + // + result = currentBars > lastTrackedBar; + if (result) + { + lastTrackedBar = currentBars; + } + + // + return result; + } + + // + bool CanProcessBar() + { + // + bool _isInTestMode = IsRunningOnTestMode(); + + // + bool isNewBar = IsNewBar(); + + // + bool result = + _isInTestMode + ? isNewBar + : !waitsUntilNext + ? true + : isNewBar; + if (result && waitsUntilNext) + { + waitsUntilNext = false; + } + + // + return result; + } + + // + void Waits() + { + this.waitsUntilNext = true; + } + + // + // Tools ... + void Clean() + { + // + symbol = NormalizeSymbol(NULL); + period = NormalizePeriod(NULL); + + // + ZeroMemory(this); + } + + // + bool GetBar( + XOHCL &bar, + int index = 0 // + ) + { + // + bool result = false; + + // + result = bar.Init( + symbol, + period, + index // + ); + + // + return result; + } + + // + bool GetBar( + XOHCL &bar, + datetime time = NULL // + ) + { + // + bool result = false; + + // + NormalizeTime(time); + + // + int barIndex = iBarShift( + symbol, + period, + time, + false // + ); + + // + result = barIndex >= 0; + if (!result) + { + return result; + } + + // + result = bar.Init( + symbol, + period, + barIndex // + ); + + // + return result; + } + + // + int Index(datetime time = NULL) + { + // + int result = 0; + + // + NormalizeTime(time); + + // + result = iBarShift( + symbol, + period, + time, + false // + ); + + // + return result; + } +}; + +// +// 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(); + + // + ZeroMemory(this); + } + + // + // 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; + } + + // +}; + +// +struct XPoint +{ + // + // Props ... + double value; + datetime at; + + // + XPoint() + { + Clean(); + } + + // + // Tools ... + + // + void Clean() + { + // + value = 0; + at = NULL; + + // + ZeroMemory(this); + } + + // + bool IsValid() + { + // + return value > 0 && + IsValid(at); + } + + // +}; + +// +// Specified Swing Point ... +struct XSwingPoint +{ + // + // Props ... + string symbol; + ENUM_TIMEFRAMES period; + + // + double swing; + datetime time; + ENUM_X_SWING_TYPE type; + + // + // Constructor ... + XSwingPoint() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup Model ... + */ + void Clean() + { + // + swing = 0; + time = NULL; + + // + symbol = NULL; + period = NULL; + + // + type = X_NO_SWING; + } + + /** + * Validate Model ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + swing > 0 && + IsValid(time) && + IsValid(symbol) && + IsValid(period) && + type != X_NO_SWING; + + // + return result; + } + + /** + * Check Swing is Low or not ... + * + * @return ( bool ) + */ + bool IsSwingLow() + { + return type == X_SWING_LOW; + } + + /** + * Check Swing is High or not ... + * + * @return ( bool ) + */ + bool IsSwingHigh() + { + return type == X_SWING_HIGH; + } +}; + +/** + * Extract values of swings from specified Collection ... + * + * @param swings: XSwingPoint instance Collection ... + * @param values: double Collection ... + * + * @return ( int ) + */ +int ExtractSwings( + XSwingPoint &swings[], + double &values[] // +) +{ + // + int result = 0; + + // + Clean(values); + + // + int count = ArraySize(swings); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + Add( + swings[i].swing, + values // + ); + } + + // + result = ArraySize(values); + + // + return result; +} + +// +// Consolidation Zone ... +struct XConsolidationZone +{ + // + // Props ... + + // + string symbol; // Symbol ... + ENUM_TIMEFRAMES period; // Period ... + + // + double upper; // Upper ... + double lower; // Lower ... + + // + datetime from; // Start Date + datetime to; // Breake Date + + // + ENUM_X_DIRECTION dir; // Break Direction ... + + // + // Constructor ... + XConsolidationZone() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + upper = 0; + lower = 0; + + // + to = NULL; + from = NULL; + symbol = NULL; + period = NULL; + dir = X_DIRECTION_NONE; + + // + ZeroMemory(this); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + // + upper > 0 && + lower > 0 && + IsValid(to) && + IsValid(from) && + IsValid(symbol) && + IsValid(period) && + HasDirection(dir) + // + ; + + // + return result; + } + + bool IsSameAs( + XConsolidationZone &item // + ) + { + // + bool result = false; + + // + result = IsValid() && + item.IsValid() && + dir == item.dir && + from == item.from && + upper == item.upper && + lower == item.lower && + symbol == item.symbol && + period == item.period; + + // + return result; + } + + /** + * Retrieve Unique Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + // + string result = + // + "XCZONE" + "_" + + ToString(dir) + "_" + + symbol + "_" + + ToString(period) + "_" + + ToString(upper) + "_" + + ToString(lower) + // + ; + + // + return result; + } + + // +}; + +// +// 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 < 1) + { + _mLoopback = 1; + } + + // + _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 ... + +// +// 0 => Sunday +// 1 => Monday +// 2 => Tuesday +// 3 => Wednesday +// 4 => Thursday +// 5 => Friday +// 6 => Saturday +enum ENUM_X_WEEK_DAYS +{ + X_WEEK_DAY_NONE = -1, + X_WEEK_DAY_SUNDAY = 0, + X_WEEK_DAY_MONDAY = 1, + X_WEEK_DAY_TUESDAY = 2, + X_WEEK_DAY_WEDNESDAY = 3, + X_WEEK_DAY_THURSDAY = 4, + X_WEEK_DAY_FRIDAY = 5, + X_WEEK_DAY_SATURDAY = 6, +}; + +// +// Retrieve Day of Week ... +ENUM_X_WEEK_DAYS GetDayOfWeek( + datetime time = NULL // +) +{ + // + ENUM_X_WEEK_DAYS result = X_WEEK_DAY_NONE; + + // + time = NormalizeTime(time); + MqlDateTime timeStruct; + bool hasDate = TimeToStruct( + time, + timeStruct // + ); + if (!hasDate) + { + return result; + } + + // + result = (ENUM_X_WEEK_DAYS)timeStruct.day_of_week; + + // + return result; +} + +// +// 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; +} + +/** + * Converts an String Represetation of Time (00:00) to Date Time .. + * + * @param value: String ... + * + * @return ( datetime ) + */ +datetime ParseDateTimeFromTimeString(string value) +{ + // + datetime result = NULL; + + // + if (!IsValid(value)) + { + return result; + } + + // + // Check Signalling Time ... + MqlDateTime cTime; + bool isTimeRecieved = TimeCurrent(cTime); + if (!isTimeRecieved) + { + return result; + } + + // + // Split ... + string parts[]; + int partsCount = SplitContent( + parts, + value, + ":" + // + ); + if (!IsValidSize(partsCount)) + { + return result; + } + + // + int hour = 0; + int minute = 0; + if (partsCount >= 1) + { + hour = (int)(parts[0]); + } + if (partsCount >= 2) + { + minute = (int)(parts[1]); + } + + // + cTime.day_of_week = 0; + cTime.day_of_year = 0; + + // + cTime.hour = hour; + cTime.min = minute; + + // + result = StructToTime(cTime); + + // + return result; +} + +// +// Check Specific Time in Range of another Time ... +bool IsTimeInRange( + datetime currentTime = NULL, + datetime startTime = NULL, + datetime stopTime = NULL // +) +{ + // + bool result = false; + + // + // Normallize Current Time ... + currentTime = NormalizeTime(currentTime); + + // + result = !IsValid(startTime) && + !IsValid(stopTime); + if (result) + { + return result; + } + + // + result = IsValid(startTime) && + IsValid(stopTime); + if (!result) + { + // + result = IsValid(startTime) && + currentTime >= startTime; + + // + return result; + } + + // + result = currentTime >= startTime && + currentTime < stopTime; + + // + return result; +} +bool IsTimeInRange( + datetime currentTime, + string startTime, + string endTime // +) +{ + // + bool result = false; + + // + result = IsValid(startTime) && + IsValid(endTime); + if (!result) + { + // + // Here Since there isnot provide any + // data source we pass result as true ... + result = true; + return result; + } + + // + // Converts String Representation to Time ... + datetime st = ParseDateTimeFromTimeString(startTime); + datetime et = ParseDateTimeFromTimeString(endTime); + + // + result = IsTimeInRange( + currentTime, + st, + et // + ); + + // + return result; +} + +// +// 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 double &buffer[], // the Buffer which required to search + int from = -1, // Last Time Index + int to = -1 // Fisrs Tima Index +) +{ + // + bool result = false; + + // + if (from == -1) + { + from = ArraySize(buffer) - 1; + } + + // + if (to == -1) + { + to = 0; + } + + // + // Validate Args ... + if ( + from <= to || + ArraySize(buffer) < from + 1) + { + return result; + } + + // + // Loop through Items ... + double toValue = buffer[to]; + double fromValue = buffer[from]; + result = toValue >= fromValue; + for (int i = to + 1; i <= from - 1; i++) + { + // + double iValue = buffer[i]; + bool isPassed = toValue >= iValue; + + // + bool isIIncreasing = IsIncreasing( + buffer, + from, + i // + ); + + // + // Check Result ... + result = result && isPassed && isIIncreasing; + if (!result) + { + break; + } + } + + // + return result; +} + +// +// Check if a Value Decreasing in Loopback ... +bool IsDecreasing( + const double &buffer[], // the Buffer which required to search + int from = -1, // Last Time Index + int to = -1 // Fisrs Tima Index +) +{ + // + bool result = false; + + // + if (from == -1) + { + from = ArraySize(buffer) - 1; + } + + // + if (to == -1) + { + to = 0; + } + + // + // Validate Args ... + if ( + from <= to || + ArraySize(buffer) < from + 1) + { + return result; + } + + // + // Loop through Items ... + double toValue = buffer[to]; + double fromValue = buffer[from]; + result = toValue <= fromValue; + for (int i = to + 1; i <= from - 1; i++) + { + // + double iValue = buffer[i]; + bool isPassed = toValue <= iValue; + + // + bool isIDecreasing = IsDecreasing( + buffer, + from, + i // + ); + + // + // Check Result ... + result = result && isPassed && isIDecreasing; + if (!result) + { + break; + } + } + + // + return result; +} + +// +bool IsTrendingUp( + const double &buffer1[], // First Buffer + const double &buffer2[] // Seccend Buffer +) +{ + // + bool result = false; + + // + int buffer1Count = ArraySize(buffer1); + int buffer2Count = ArraySize(buffer2); + if (buffer1Count <= 0 || buffer2Count <= 0) + { + return result; + } + + // + int count = MathMin(buffer1Count, buffer2Count); + if (count <= 1) + { + return result; + } + + // + int upCounts = 0; + int downCounts = 0; + double value = MathAbs(buffer1[0] - buffer2[0]); + for (int i = 1; i < count; i++) + { + // + double iValue = MathAbs(buffer1[i] - buffer2[i]); + + // + if (value > iValue) + { + upCounts++; + } + + // + if (value < iValue) + { + downCounts++; + } + } + + // + result = upCounts > 1 && upCounts > downCounts; + + // + return result; +} + +// +bool IsTrendingDown( + const double &buffer1[], // First Buffer + const double &buffer2[] // Seccend Buffer +) +{ + // + bool result = false; + + // + int buffer1Count = ArraySize(buffer1); + int buffer2Count = ArraySize(buffer2); + if (buffer1Count <= 0 || buffer2Count <= 0) + { + return result; + } + + // + int count = MathMin(buffer1Count, buffer2Count); + if (count <= 1) + { + return result; + } + + // + int upCounts = 0; + int downCounts = 0; + double value = MathAbs(buffer1[0] - buffer2[0]); + for (int i = 1; i < count; i++) + { + // + double iValue = MathAbs(buffer1[i] - buffer2[i]); + + // + if (value > iValue) + { + upCounts++; + } + + // + if (value < iValue) + { + downCounts++; + } + } + + // + result = downCounts > 1 && downCounts > upCounts; + + // + return result; +} + +// +// Calculate Slope of Specified Buffer at Specified Index ... +double GetSlope( + const double &buffer[], // Buffer + int from, // In Past Index ... + int to // In Past Index ... +) +{ + // + double result = 0; + + // + if (from > ArraySize(buffer) || to > ArraySize(buffer)) + { + return result; + } + + // + double toValue = buffer[to]; + double fromValue = buffer[from]; + double deltaValue = toValue - fromValue; + double deltaTime = from - to; + + // + result = deltaValue / deltaTime; + + // + return result; +} + +// +// Check Bar Reject Specified Value ... +bool IsBarReject( + double value, + ENUM_X_DIRECTION dir, + XOHCL &bar // +) +{ + // + bool result = false; + + // + result = value > 0 && + bar.IsValid() && + HasDirection(dir); + if (!result) + { + return result; + } + + // + bool isUp = IsBullish(dir); + bool isDown = IsBearish(dir); + + // + result = + // + isUp + ? bar.IsBullish() && + bar.low < value && + bar.GetDown() > value + : isDown + ? bar.IsBearish() && + bar.high > value && + bar.GetUp() < value + : false + // + ; + + // + return result; +} + +// +// Check Bar Break Specified Value ... +bool IsBarBreak( + double value, + ENUM_X_DIRECTION dir, + XOHCL &bar // +) +{ + // + bool result = false; + + // + result = value > 0 && + bar.IsValid() && + HasDirection(dir); + if (!result) + { + return result; + } + + // + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + bool isUp = IsBullish(dir); + bool isDown = IsBearish(dir); + + // + result = + isUp + ? bar.IsBullish() && + ((bar.GetDown() < value && + bar.GetUp() > value) || + (bar.close > value && + pBar.close < value)) + : isDown + ? bar.IsBearish() && + ((bar.GetUp() > value && + bar.GetDown() < value) || + (bar.close < value && + pBar.close > value)) + : false; + + // + 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; +} + +// +double GetFibonacciLevel( + double mUp, + double mDown, + ENUM_X_FIBO_LEVELS mLevel, + ENUM_X_DIRECTION mForDir // +) +{ + // + double result = 0; + + // + double levelValue = GetFiboLevelValue(mLevel); + + // + bool isValid = + // + mUp > 0 && + mDown > 0 && + levelValue > 0 && + mUp > mDown && + HasDirection(mForDir) + // + ; + if (!isValid) + { + return result; + } + + // + bool isBullish = IsBullish(mForDir); + + // + double ling = mUp - mDown; + double pLevel = (ling / 100) * (levelValue * 100); + + // + result = + isBullish + ? mUp - pLevel + : mDown + pLevel; + + // + return result; +} + +// +// 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; +} + +// +// Check Specified Array Has Childs or not ... +template +bool HasChild(T &buffer[]) +{ + return IsValidSize(ArraySize(buffer)); +} +template +bool SpecificHasChild(T &buffer[]) +{ + return HasChild(buffer); +} + +// +// Remove Specified Item from an Array ... +template +bool Remove( + T item, + T &buffer[]) +{ + // + bool result = false; + + // + int itemIndex = FindIndex( + item, + buffer); + if (itemIndex < 0) + { + return result; + } + + // + result = ArrayRemove( + buffer, + itemIndex, + 1); + + // + return result; +} + +// +// Clean Specified Array ... +template +void Clean(T &buffer[]) +{ + // + ArrayResize(buffer, 0); + ArrayFree(buffer); + ZeroMemory(buffer); +} +template +void SpecificClean(T &buffer[]) +{ + Clean(buffer); +} + +// +// Copy Whole Content of Source to Dest array ... +template +void Copy( + T &source[], // Source Buffer ... + T &dest[], // Dest Buffer ... + bool cleanDest = true // Force Clen Dest Buffer ... +) +{ + // + if (cleanDest) + { + Clean(dest); + } + + // + int sourceCount = ArraySize(source); + if (sourceCount <= 0) + { + return; + } + + // + for (int i = 0; i < sourceCount; i++) + { + // + T iSource = source[i]; + + // + AddRef( + iSource, + dest); + } +} + +// +// Copy Items from a Buffer ... +template +int Copy( + int start, // Start + int count, // Number of Items for read + T &source[], // Source Buffer + T &dest[], // Dest Buffer + bool forceClean = true, // Force To Clean buffer + bool forceStart = true // Force To Clean buffer +) +{ + // + int result = 0; + + // + if (forceClean) + { + Clean(dest); + } + + // + if (start < 0 && forceStart) + { + start = 0; + } + + // + if (start >= ArraySize(source)) + { + start = ArraySize(source) - 1; + } + + // + if (count == 0) + { + count = ArraySize(source) - 1 - start; + } + + // + if (start + count > ArraySize(source)) + { + return result; + } + + // + int beforeSize = ArraySize(dest); + + // + bool asSeriesDest = ArrayGetAsSeries(dest); + bool asSeriesSource = ArrayGetAsSeries(source); + + // + ArraySetAsSeries(dest, true); + ArraySetAsSeries(source, true); + + // + ArrayCopy( + dest, + source, + 0, + start, + count + // + ); + + // + int afterSize = ArraySize(dest); + + // + result = afterSize - beforeSize; + + // + ArraySetAsSeries(dest, asSeriesDest); + ArraySetAsSeries(source, asSeriesSource); + + // + return result; +} + +// +// Copy Items from a Buffer ... +template +int CopyRef( + int start, // Start + int count, // Number of Items for read + T &source[], // Source Buffer + T &dest[], // Dest Buffer + bool forceClean = true // Force To Clean buffer +) +{ + // + int result = 0; + + // + if (forceClean) + { + Clean(dest); + } + + // + if (start < 0) + { + start = 0; + } + + // + if (start >= ArraySize(source)) + { + start = ArraySize(source) - 1; + } + + // + int beforeSize = ArraySize(dest); + + // + bool asSeriesDest = ArrayGetAsSeries(dest); + bool asSeriesSource = ArrayGetAsSeries(source); + + // + ArraySetAsSeries(dest, true); + ArraySetAsSeries(source, true); + + // + for (int i = start; i < start + count; i++) + { + // + AddRef( + source[i], + dest + // + ); + } + + // + int afterSize = ArraySize(dest); + + // + result = afterSize - beforeSize; + + // + ArraySetAsSeries(dest, asSeriesDest); + ArraySetAsSeries(source, asSeriesSource); + + // + return result; +} + +// +// Retrive Last Item of Specified Buffer ... +template +bool GetLastItem( + T &item, // Holds Result + T &buffer[] // Specified Buffer +) +{ + // + bool result = false; + + // + int bufferSize = ArraySize(buffer); + if (bufferSize <= 0) + { + return result; + } + + // + item = buffer[bufferSize - 1]; + + // + result = true; + return result; +} + +// +// Remove Last Item of Specified Buffer ... +template +bool RemoveLastItem( + T &buffer[] // Specified Buffer +) +{ + // + bool result = false; + + // + int count = ArraySize(buffer); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + ArrayRemove( + buffer, + count - 1, + 1 // + ); + + // + return result; +} + +template +void CleanupArray( + T &buffer[], // Buffer to Cleanup ... + int maxAllowed = 0 // Max Allowed Number of items ... +) +{ + // + if (maxAllowed <= 0) + { + return; + } + + // + int count = ArraySize(buffer); + if (!IsValidSize(count) || + count <= maxAllowed) + { + return; + } + + // + int mustRemove = count - maxAllowed; + if (!IsValidSize(mustRemove)) + { + return; + } + + // + ArrayRemove( + buffer, + 0, + mustRemove // + ); +} + +template +void CleanupArray( + int &removedIndexes[], + T &buffer[] // Buffer to Cleanup ... +) +{ + // + bool isValid = HasChild(buffer) && + HasChild(removedIndexes); + if (!isValid) + { + return; + } + + // + for (int i = 0; i < ArraySize(removedIndexes); i++) + { + // + int idx = removedIndexes[i]; + if (IsValidIndex(idx) && ArraySize(buffer) > idx) + { + // + ArrayRemove( + buffer, + idx, + 1 // + ); + } + } + + // + Clean(removedIndexes); +} + +// +// Search Array For Specific Item ... +template +int FindIndex( + T item, // What is Search ... + T &buffer[] // Search in ... +) +{ + // + int result = -1; + + // + int count = ArraySize(buffer); + if (count <= 0) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + T iT = buffer[i]; + + // + if (iT == item) + { + // + result = i; + break; + } + } + + // + return result; +} +// +// Find Specific Item Index inside a Collection ... +template +int FindIndex( + T &item, // Item to Find + const T &items[] // Items for Search +) +{ + // + int result = -1; + + // + // Check Item Validation ... + if (!item.IsValid()) + { + return result; + } + + // + int itemsCount = ArraySize(items); + if (itemsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < itemsCount; i++) + { + // + T iItem = items[i]; + + // + // Validate Item ... + if (!iItem.IsValid()) + { + continue; + } + + // + bool isSame = item.IsSameAs(iItem); + if (isSame && result <= -1) + { + // + result = i; + break; + } + } + + // + return result; +} + +// +// Check an Array Contains Specified Value ... +template +bool Contains( + T item, // What is Search ... + T &buffer[] // Search in ... +) +{ + // + bool result = false; + + // + int idx = FindIndex( + item, + buffer); + result = idx > -1; + + // + return result; +} + +// +// Calculate a Buffer's Sum ... +template +double GetSum( + T &buffer[], // the Buffer which required to search + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + // + double result = 0; + + // + T tmp[]; + int tmpCount = Copy( + start, + count, + buffer, + tmp + // + ); + if (tmpCount <= 0) + { + return result; + } + + // + // Calculate Summary ... + for (int i = 0; i < tmpCount; i++) + { + result += buffer[i]; + } + + // + return result; +} + +// +// Calculate a Buffer's Average ... +template +double GetAverage( + T &buffer[], // the Buffer which required to search + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + // + double result = 0; + + // + T tmp[]; + int tmpCount = Copy( + start, + count, + buffer, + tmp + // + ); + if (tmpCount <= 0) + { + return result; + } + + // + // Calculate Summary ... + for (int i = 0; i < tmpCount; i++) + { + result += buffer[i]; + } + + // + // Calculate Average ... + result = result / tmpCount; + + // + return result; +} + +// +// Get Max of Specific Loopback of a Buffer ... +template +T GetMax( + T &buffer[], // the Buffer which required to search + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + // + T result = 0; + + // + if (count <= 0) + { + count = ArraySize(buffer); + } + + // + T tmp[]; + int tmpCount = Copy( + start, + count, + buffer, + tmp + // + ); + if (tmpCount <= 0) + { + return result; + } + + // + // Loop Through LoopBack ... + for (int i = 0; i < tmpCount; i++) + { + // + T iValue = tmp[i]; + + // + result = + // + result == 0 || result < iValue + // + ? iValue + // + : result + // + ; + } + + // + return result; +} +template +T GetMax( + T &buffer[], // the Buffer which required to search + int &index, // Item Index ... + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + // + T result = 0; + index = -1; + + // + if (count <= 0) + { + count = ArraySize(buffer); + } + + // + T tmp[]; + int tmpCount = Copy( + start, + count, + buffer, + tmp + // + ); + if (tmpCount <= 0) + { + return result; + } + + // + // Loop Through LoopBack ... + for (int i = 0; i < tmpCount; i++) + { + // + T iValue = tmp[i]; + + // + bool isNew = result == 0; + bool canSet = isNew || + (!isNew && + result < iValue); + if (canSet) + { + // + index = i; + result = iValue; + } + } + + // + return result; +} +template +T GetSpecifiedMax( + T &buffer[], // the Buffer which required to search + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + return GetMax( + buffer, + start, + count // + ); +} +template +T GetSpecifiedMax( + T &buffer[], // the Buffer which required to search + int &index, // Item Index ... + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + return GetMax( + buffer, + index, + start, + count // + ); +} + +// +// Get Min of Specific Loopback of a Buffer ... +template +T GetMin( + T &buffer[], // the Buffer which required to search + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + // + T result = 0; + + // + if (count <= 0) + { + count = ArraySize(buffer); + } + + // + T tmp[]; + int tmpCount = Copy( + start, + count, + buffer, + tmp + // + ); + if (tmpCount <= 0) + { + return result; + } + + // + // Loop Through LoopBack ... + for (int i = 0; i < tmpCount; i++) + { + // + T iValue = tmp[i]; + + // + result = + // + result == 0 || result > iValue + // + ? iValue + // + : result + // + ; + } + + // + return result; +} +template +T GetMin( + T &buffer[], // the Buffer which required to search + int &index, // Item Index ... + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + // + T result = 0; + index = -1; + + // + if (count <= 0) + { + count = ArraySize(buffer); + } + + // + T tmp[]; + int tmpCount = Copy( + start, + count, + buffer, + tmp + // + ); + if (tmpCount <= 0) + { + return result; + } + + // + // Loop Through LoopBack ... + for (int i = 0; i < tmpCount; i++) + { + // + T iValue = tmp[i]; + + // + bool isNew = result == 0; + bool canSet = isNew || + (!isNew && + result > iValue); + if (canSet) + { + // + index = i; + result = iValue; + } + } + + // + return result; +} +template +T GetSpecifiedMin( + T &buffer[], // the Buffer which required to search + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + return GetMin( + buffer, + start, + count // + ); +} +template +T GetSpecifiedMin( + T &buffer[], // the Buffer which required to search + int &index, // Item Index ... + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + return GetMin( + buffer, + index, + start, + count // + ); +} + +// +// Find a Value less than Specified ... +template +T FindLesserThan( + T value, // Specified Value ... + const T &source[], // Source ... + bool isDescend = false // Find Biggest Lesser Value ... +) +{ + // + T result = -1; + + // + int itemsCount = ArraySize(source); + if (itemsCount <= 0) + { + return result; + } + + // + // Make a Copy of source ... + T tmp[]; + + // + ArrayResize( + tmp, + ArraySize(source) // + ); + + // + ArrayCopy( + tmp, + source // + ); + + // + // Sort Temp Buffer ... + ArraySort(tmp); + if (isDescend) + { + ArrayReverse(tmp); + } + + // + int tmpCount = ArraySize(tmp); + for (int i = 0; i < tmpCount; i++) + { + // + T iValue = tmp[i]; + + // + if (iValue < value) + { + // + result = iValue; + break; + } + } + + // + return result; +} +template +T FindLesserThan( + T value, // Specified Value ... + int &index, // Item Index ... + const T &source[], // Source ... + bool isDescend = false // Find Biggest Lesser Value ... +) +{ + // + T result = -1; + index = -1; + + // + int itemsCount = ArraySize(source); + if (itemsCount <= 0) + { + return result; + } + + // + // Make a Copy of source ... + T tmp[]; + + // + ArrayResize( + tmp, + ArraySize(source) // + ); + + // + ArrayCopy( + tmp, + source // + ); + + // + // Sort Temp Buffer ... + ArraySort(tmp); + if (isDescend) + { + ArrayReverse(tmp); + } + + // + int tmpCount = ArraySize(tmp); + for (int i = 0; i < tmpCount; i++) + { + // + T iValue = tmp[i]; + + // + if (iValue < value) + { + // + index = i; + result = iValue; + break; + } + } + + // + return result; +} + +// +// Find a Value less than Specified ... +template +T FindBiggerThan( + T value, // Specified Value ... + const T &source[], // Source ... + bool isDescend = false // Find Smallest Bigger Value ... +) +{ + // + T result = -1; + + // + int itemsCount = ArraySize(source); + if (itemsCount <= 0) + { + return result; + } + + // + // Make a Copy of source ... + T tmp[]; + + // + ArrayResize( + tmp, + ArraySize(source) // + ); + + // + ArrayCopy( + tmp, + source // + ); + + // + // Sort Temp Buffer ... + ArraySort(tmp); + if (!isDescend) + { + ArrayReverse(tmp); + } + + // + int tmpCount = ArraySize(tmp); + for (int i = 0; i < tmpCount; i++) + { + // + T iValue = tmp[i]; + + // + if (iValue > value) + { + // + result = iValue; + break; + } + } + + // + return result; +} +template +T FindBiggerThan( + T value, // Specified Value ... + int &index, // Item Index ... + const T &source[], // Source ... + bool isDescend = false // Find Smallest Bigger Value ... +) +{ + // + T result = -1; + index = -1; + + // + int itemsCount = ArraySize(source); + if (itemsCount <= 0) + { + return result; + } + + // + // Make a Copy of source ... + T tmp[]; + + // + ArrayResize( + tmp, + ArraySize(source) // + ); + + // + ArrayCopy( + tmp, + source // + ); + + // + // Sort Temp Buffer ... + ArraySort(tmp); + if (!isDescend) + { + ArrayReverse(tmp); + } + + // + int tmpCount = ArraySize(tmp); + for (int i = 0; i < tmpCount; i++) + { + // + T iValue = tmp[i]; + + // + if (iValue > value) + { + // + index = i; + result = iValue; + break; + } + } + + // + return result; +} + +// +// Find Same Values in Array ... +template +void FindSames( + T &result[], // Holds Result ... + T &source[], // Source ... + int verifications = 3 // Number of Consequence Repeat ... +) +{ + // + Clean(result); + + // + // TenkanSen Flats ... + int sourceCount = ArraySize(source); + if (sourceCount > verifications) + { + // + T mLast = 0; + int mVerified = 0; + for (int i = 0; i < sourceCount; i++) + { + // + T iVal = source[i]; + if (mLast == 0) + { + mLast = iVal; + } + else if (mLast == iVal) + { + mVerified++; + } + else + { + mLast = iVal; + mVerified = 0; + } + + // + if (iVal == mLast && mVerified >= verifications) + { + // + Add( + iVal, + result); + + // + mLast = 0; + mVerified = 0; + } + } + } +} + +// +// Add an Item to a Buffer if not Exists ... +void AddIfNotExists( + double value, + double &values[], + double smoothingPoint = 3 // +) +{ + // + double smoothingValue = smoothingPoint * GetPoints(_Symbol); + + // + int valuesCount = ArraySize(values); + if (valuesCount <= 0) + { + // + Add(value, + values); + } + else + { + // + bool isExists = false; + for (int i = 0; i < valuesCount; i++) + { + // + double iVal = values[i]; + + // + double diff = MathAbs(iVal - value); + + // + if (iVal == value || diff < smoothingValue) + { + // + isExists = true; + break; + } + } + + // + if (!isExists) + { + // + Add(value, + values); + } + } +} + +// +// Add a Buffers Child to another Buffer +// if it's not Contains them ... +void AddsIfNotExists( + double &source[], + double &dest[], + double smoothingPoint = 3) +{ + // + double smoothingValue = smoothingPoint * GetPoints(_Symbol); + + // + int sourceCount = ArraySize(source); + if (sourceCount <= 0) + { + return; + } + + // + for (int i = 0; i < sourceCount; i++) + { + // + double iSource = source[i]; + + // + AddIfNotExists( + iSource, + dest, + smoothingPoint); + } +} + +// +// 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; +} + +// +ENUM_X_DIRECTION Opposit(ENUM_X_DIRECTION value) +{ + // + ENUM_X_DIRECTION result = X_DIRECTION_NONE; + + // + if (!HasDirection(value)) + { + return result; + } + + // + result = + IsBullish(value) + ? X_DIRECTION_BEARISH + : X_DIRECTION_BULLISH; + + // + return result; +} + +// +// Moving Average ... + +enum ENUM_X_MA_METHOD +{ + X_MA_MODE_NONE, // None + X_MA_MODE_SMA, // SMA + X_MA_MODE_EMA, // EMA + X_MA_MODE_LWMA, // LWMA + X_MA_MODE_SMMA, // SMMA +}; + +/** + * Calculate Sspecified Buffer's Moving Averages ... + * + * @param rates_total: Integer, number of items ... + * @param prev_calculated: Integer, Previous Calculate Items ... + * @param begin: Integer, Bar Index ... + * @param period: Integer, Moving Average Length ... + * @param source: Double Array, Specified Array for Calculating Moving Averages ... + * @param buffer: Double Array, Specified Array to Apply Calculated Moving Average on it ... + * @param method: ENUM_MA_METHOD member Specified Moving Average Calculation Method ... + * + * @return ( int ) + */ +int iMAOnBuffer( + const int _rates_total, + const int _prev_calculated, + const int _begin, + const int _period, + const double &_source[], + double &_buffer[], + ENUM_X_MA_METHOD _method = X_MA_MODE_SMA // +) +{ + // + int result = 0; + + // + if ( + _period < 0 || + _rates_total <= 0 || + _prev_calculated < 0 || + _method == X_MA_MODE_NONE || + _prev_calculated > _rates_total) + { + return result; + } + + // + switch (_method) + { + // + case X_MA_MODE_SMA: + result = SimpleMAOnBuffer( + _rates_total, + _prev_calculated, + _begin, + _period, + _source, + _buffer // + ); + break; + + // + case X_MA_MODE_EMA: + result = ExponentialMAOnBuffer( + _rates_total, + _prev_calculated, + _begin, + _period, + _source, + _buffer // + ); + break; + + // + case X_MA_MODE_LWMA: + result = LinearWeightedMAOnBuffer( + _rates_total, + _prev_calculated, + _begin, + _period, + _source, + _buffer // + ); + break; + + // + case X_MA_MODE_SMMA: + result = SmoothedMAOnBuffer( + _rates_total, + _prev_calculated, + _begin, + _period, + _source, + _buffer // + ); + break; + } + + // + return result; +} + +// \ No newline at end of file diff --git a/BKPS/14031218/Libraries/x-saherelm.draw.lib.mq5 b/BKPS/14031218/Libraries/x-saherelm.draw.lib.mq5 new file mode 100644 index 0000000..ab7f39b --- /dev/null +++ b/BKPS/14031218/Libraries/x-saherelm.draw.lib.mq5 @@ -0,0 +1,2626 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Draw Library +// -------------------------------------- +// Name: XDraw +// Description: provides Draw abilities ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Global Definitions: Variables, Properties and etc ... + +// +// Retrieve Chart Size in Pixel ... +struct XSize +{ + long width; + long height; + + // + int x; + int y; + int w; + int h; + + // + int wStep; + int hStep; +}; + +// +// Define a Draw Specifications ... +struct XDrawSpecifications +{ + // + // Props ... + + // + bool draw; // Draw or Not ... + + // + int width; // Draw Witdth ... + color clr; // Draw Color ... + ENUM_LINE_STYLE style; // Draw Style ... + + // + bool back; // in the background + bool fill; // fill object if supported + bool selection; // highlight to move + bool rayRight; // line's continuation to the right + bool hidden; // hidden in the object list + long zOrder; // priority for mouse click + + // + string label; // Label ... + color labelColor; // Label Color ... + double labelAngel; // Label Angle ... + string labelFont; // Label Font ... + int labelFontSize; // Label Font Size ... + ENUM_ANCHOR_POINT labelAnchor; // Label Anchor Point ... + + // + // Constructor ... + XDrawSpecifications() + { + Clean(); + } + + // + // Operator ... + void operator=(const XDrawSpecifications &value) + { + // + clr = value.clr; + draw = value.draw; + width = value.width; + style = value.style; + + // + back = value.back; + hidden = value.hidden; + zOrder = value.zOrder; + rayRight = value.rayRight; + selection = value.selection; + + // + fill = value.fill; + + // + label = value.label; + labelColor = value.labelColor; + labelAngel = value.labelAngel; + labelFont = value.labelFont; + labelFontSize = value.labelFontSize; + labelAnchor = value.labelAnchor; + } + + // + // Functions ... + + // + void Clean() + { + // + draw = false; + width = 1; + clr = CLR_NONE; + style = STYLE_SOLID; + + // + back = false; + hidden = false; + rayRight = false; + selection = false; + fill = false; + + // + zOrder = 0; + + // + label = ""; + labelColor = CLR_NONE; + labelAngel = 0; + labelFont = "Arial"; + labelFontSize = 20; + labelAnchor = ANCHOR_LEFT_UPPER; + + // + ZeroMemory(this); + } + + // + void Label( + string mLabel = "", // Label ... + color mLabelColor = CLR_NONE, // Label Color ... + string mLabelFont = "Arial", // Label Font ... + int mLabelFontSize = 20, // Label Font Size ... + ENUM_ANCHOR_POINT mLabelAnchor = ANCHOR_LEFT_UPPER, // Label Anchor Point ... + double mLabelAngel = 0 // Label Angle ... + ) + { + // + label = mLabel; + labelFont = mLabelFont; + labelColor = mLabelColor; + labelAngel = mLabelAngel; + labelAnchor = mLabelAnchor; + labelFontSize = mLabelFontSize; + } +}; + +// +// Candle Draw Specifications ... +struct XOHCLDrawSpecification +{ + // + // Props ... + XDrawSpecifications openStyle; + XDrawSpecifications highStyle; + XDrawSpecifications closeStyle; + XDrawSpecifications lowStyle; + + // + // Constructors ... + XOHCLDrawSpecification() + { + Clean(); + } + + // + // Operators ... + void operator=(const XOHCLDrawSpecification &value) + { + // + lowStyle = value.lowStyle; + openStyle = value.openStyle; + highStyle = value.highStyle; + closeStyle = value.closeStyle; + } + + // + // Functions ... + + // + void Clean() + { + // + lowStyle.Clean(); + openStyle.Clean(); + highStyle.Clean(); + closeStyle.Clean(); + + // + ZeroMemory(this); + } + + // + void Default() + { + // + // Open ... + openStyle.width = 1; + openStyle.draw = true; + openStyle.clr = clrLime; + openStyle.style = STYLE_SOLID; + openStyle.Label( + "O", + openStyle.clr); + + // + // High ... + highStyle.width = 1; + highStyle.draw = true; + highStyle.clr = clrAqua; + highStyle.style = STYLE_SOLID; + highStyle.Label( + "H", + highStyle.clr); + + // + // Close ... + closeStyle.width = 1; + closeStyle.draw = true; + closeStyle.clr = clrRed; + closeStyle.style = STYLE_SOLID; + closeStyle.Label( + "C", + closeStyle.clr); + + // + // Low ... + lowStyle.width = 1; + lowStyle.draw = true; + lowStyle.clr = clrMagenta; + lowStyle.style = STYLE_SOLID; + lowStyle.Label( + "L", + lowStyle.clr); + } + + // + void Width(int value) + { + // + lowStyle.width = value; + openStyle.width = value; + highStyle.width = value; + closeStyle.width = value; + } + + // + void Style(ENUM_LINE_STYLE value) + { + // + lowStyle.style = value; + openStyle.style = value; + highStyle.style = value; + closeStyle.style = value; + } + + // + void Color(color value) + { + // + lowStyle.clr = value; + openStyle.clr = value; + highStyle.clr = value; + closeStyle.clr = value; + } + + // + void RayRight(bool value) + { + // + lowStyle.rayRight = value; + openStyle.rayRight = value; + highStyle.rayRight = value; + closeStyle.rayRight = value; + } + + // + void Draw(bool value) + { + // + lowStyle.draw = value; + openStyle.draw = value; + highStyle.draw = value; + closeStyle.draw = value; + } + + // + void Back(bool value) + { + // + lowStyle.back = value; + openStyle.back = value; + highStyle.back = value; + closeStyle.back = value; + } + + // + void Fill(bool value) + { + // + lowStyle.fill = value; + openStyle.fill = value; + highStyle.fill = value; + closeStyle.fill = value; + } + + // + void Label(string value) + { + // + lowStyle.Label(value); + openStyle.Label(value); + highStyle.Label(value); + closeStyle.Label(value); + } + + // + void SetLabelPrefix(string value) + { + // + lowStyle.label = value + " " + lowStyle.label; + openStyle.label = value + " " + openStyle.label; + highStyle.label = value + " " + highStyle.label; + closeStyle.label = value + " " + closeStyle.label; + } +}; + +// +string drawPrefix = "X-OBJ"; + +// +// Common Draw Functions ... + +// +// remove drawn objects ... +void RemoveDraws( + string tag = NULL, + long chartId = -1, + int subWindow = -1 // +) +{ + // + // Normalize Args ... + // + if (tag == NULL) + { + tag = drawPrefix; + } + + // + if (chartId == -1) + { + chartId = 0; + } + + // + if (subWindow == -1) + { + subWindow = 0; + } + + // + for (int iObj = ObjectsTotal(chartId, subWindow) - 1; iObj >= 0; iObj--) + { + // + string on = ObjectName(chartId, iObj, subWindow); + if (StringFind(on, tag) >= 0) + { + ObjectDelete(chartId, on); + } + } + + // + // Redraw Chart ... + ChartRedraw(); +} + +// +bool RemoveDraw( + string name, + long chartId = -1, + int subWindow = -1 // +) +{ + // + bool result = false; + + // + if (chartId == -1) + { + chartId = 0; + } + + // + if (subWindow == -1) + { + subWindow = 0; + } + + // + string objName = ""; + for (int iObj = ObjectsTotal(chartId, subWindow) - 1; iObj >= 0; iObj--) + { + // + string on = ObjectName(chartId, iObj, subWindow); + if (StringFind(on, name) >= 0) + { + // + objName = on; + break; + } + } + + // + if (StringLen(objName) > 0) + { + result = ObjectDelete(chartId, objName); + } + + // + return result; +} + +// +// Deselect All Draws ... +void DeselectAllDraws() +{ + // + int objs = ObjectsTotal(ChartID(), 0); + for (int o = 0; o < objs; o++) + { + ObjectSetInteger(ChartID(), ObjectName(ChartID(), o, 0), OBJPROP_SELECTED, false); + } + + // + ChartRedraw(); +} + +// +// Check Object Exists ... +bool IsDrawExists( + string name, + long chartId = -1, + int subWindow = -1 // +) +{ + // + bool result = false; + + // + if (chartId == -1) + { + chartId = 0; + } + + // + if (subWindow == -1) + { + subWindow = 0; + } + + // + for (int iObj = ObjectsTotal(chartId, subWindow) - 1; iObj >= 0; iObj--) + { + // + string on = ObjectName(chartId, iObj, subWindow); + result = StringFind(on, name) >= 0; + if (result) + { + break; + } + } + + // + return result; +} + +// +// Find Specific Object Name ... +string FindObjectName( + string suggest, + long chartId = 0, + int subWindow = 0 // +) +{ + // + string result = NULL; + + // + int objectsCount = ObjectsTotal(chartId, subWindow); + if (objectsCount <= 0) + { + return result; + } + + // + for (int i = objectsCount - 1; i >= 0; i--) + { + // + string iObjectName = ObjectName(chartId, i, subWindow); + bool isExists = StringFind(iObjectName, suggest) >= 0; + if (isExists) + { + // + result = iObjectName; + break; + } + } + + // + return result; +} + +// +// Regular Draws ... + +// +// Arrow Functions ... + +// +// Draw an Arrow Object on Chart ... +bool DrawArrow( + const long chartID = 0, // chart's ID + const string name = "Arrow", // arrow name + const int subWindow = 0, // subwindow index + datetime time = 0, // anchor point time + double price = 0, // anchor point price + const uchar arrowCode = 252, // arrow code + const ENUM_ARROW_ANCHOR anchor = ANCHOR_BOTTOM, // anchor point position + const color clr = clrAqua, // arrow color + const ENUM_LINE_STYLE style = STYLE_SOLID, // border line style + const int width = 3, // arrow size + const bool back = false, // in the background + const bool selection = false, // highlight to move + const bool hidden = false, // hidden in the object list + const long zOrder = 0 // Order Object ... +) +{ + // + bool result = false; + + // + // set anchor point coordinates if they are not set ... + ChangeArrowEmptyPoint(time, price); + + // + // reset the error value ... + ResetLastError(); + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // create an arrow ... + result = ObjectCreate(chartID, objName, OBJ_ARROW, subWindow, time, price); + if (!result) + { + return result; + } + + // + // set the arrow code ... + ObjectSetInteger(chartID, objName, OBJPROP_ARROWCODE, arrowCode); + + // + // set anchor type ... + ObjectSetInteger(chartID, objName, OBJPROP_ANCHOR, anchor); + + // + // set the arrow color ... + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // set the border line style ... + ObjectSetInteger(chartID, objName, OBJPROP_STYLE, style); + + // + // set the arrow's size ... + ObjectSetInteger(chartID, objName, OBJPROP_WIDTH, width); + + // + // display in the foreground false or background true ... + ObjectSetInteger(chartID, objName, OBJPROP_BACK, back); + + // + // enable true or disable false the mode of moving the arrow by mouse + // when creating a graphical object using ObjectCreate function, the object cannot be + // highlighted and moved by default. Inside this method, selection parameter + // is false by default, if you want making it possible to highlight and move the object + // change it to true ... + ObjectSetInteger(chartID, objName, OBJPROP_SELECTABLE, true); + ObjectSetInteger(chartID, objName, OBJPROP_SELECTED, selection); + + // + // hide true or display false graphical object name in the object list ... + ObjectSetInteger(chartID, objName, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart ... + ObjectSetInteger(chartID, objName, OBJPROP_ZORDER, zOrder); + + // + // successful execution ... + return result; +} + +// +// Move the anchor point of Arrow ... +bool MoveArrow( + const long chartID = 0, // chart's ID + const string name = "Arrow", // object name + datetime time = 0, // anchor point time coordinate + double price = 0 // anchor point price coordinate +) +{ + // + bool result = false; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // if point position is not set, move it to the current bar having Bid price ... + if (!time) + { + time = TimeCurrent(); + } + + // + if (!price) + { + price = SymbolInfoDouble(_Symbol, SYMBOL_BID); + } + + // + // move the anchor point ... + result = ObjectMove(chartID, objName, 0, time, price); + + // + return result; +} + +// +// Delete an arrow ... +bool DeleteArrow( + const long chartID = 0, // chart's ID + const string name = "Arrow" // arrow name +) +{ + // + bool result = false; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // delete an arrow ... + result = !ObjectDelete(chartID, objName); + + // + return result; +} + +// +// Change the arrow code ... +bool ArrowCodeChange( + const long chartID = 0, // chart's ID + const string name = "Arrow", // object name + const uchar code = 252 // arrow code +) +{ + // + bool result = false; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // change the arrow code ... + result = ObjectSetInteger(chartID, objName, OBJPROP_ARROWCODE, code); + + // + return result; +} + +// +// Change anchor type ... +bool ArrowAnchorChange( + const long chartID = 0, // chart's ID + const string name = "Arrow", // object name + const ENUM_ARROW_ANCHOR anchor = ANCHOR_TOP // anchor type +) +{ + // + bool result = false; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // change anchor type ... + result = !ObjectSetInteger(chartID, objName, OBJPROP_ANCHOR, anchor); + + // + return result; +} + +// +// Check anchor point values and set default values +// for empty ones ... +void ChangeArrowEmptyPoint( + datetime &time, + double &price // +) +{ + // + // if the point's time is not set, it will be on the current bar ... + if (!time) + { + time = TimeCurrent(); + } + + // + // if the point's price is not set, it will have Bid value ... + if (!price) + { + price = SymbolInfoDouble(_Symbol, SYMBOL_BID); + } +} + +// +// Horizontal Line Functions ... + +// +// Create, Draw the horizontal line ... +bool DrawHorizontalLine( + const long chartID = 0, // chart's ID + const string name = "HLine", // line name + const int subWindow = 0, // subwindow index + double price = 0, // line price + const color clr = clrRed, // line color + const ENUM_LINE_STYLE style = STYLE_SOLID, // line style + const int width = 1, // line width + const bool back = false, // in the background + const bool selection = false, // highlight to move + const bool hidden = false, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + bool result = false; + + // + // if the price is not set, set it at the current Bid price level ... + if (!price) + { + price = SymbolInfoDouble(Symbol(), SYMBOL_BID); + } + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // create a horizontal line ... + result = ObjectCreate(chartID, objName, OBJ_HLINE, subWindow, 0, price); + if (!result) + { + return result; + } + + // + // set line color ... + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // set line display style ... + ObjectSetInteger(chartID, objName, OBJPROP_STYLE, style); + + // + // set line width ... + ObjectSetInteger(chartID, objName, OBJPROP_WIDTH, width); + + // + // display in the foreground false or background true ... + ObjectSetInteger(chartID, objName, OBJPROP_BACK, back); + + // + // enable true or disable false the mode of moving the line by mouse + // when creating a graphical object using ObjectCreate function, the object cannot be + // highlighted and moved by default. Inside this method, selection parameter + // is true by default making it possible to highlight and move the object + ObjectSetInteger(chartID, objName, OBJPROP_SELECTABLE, selection); + ObjectSetInteger(chartID, objName, OBJPROP_SELECTED, selection); + + // + // hide true or display false graphical object name in the object list ... + ObjectSetInteger(chartID, objName, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart ... + ObjectSetInteger(chartID, objName, OBJPROP_ZORDER, zOrder); + + // + // successful execution ... + return result; +} + +// +// Move horizontal line ... +bool MoveHorizontalLine( + const long chartID = 0, // chart's ID + const string name = "HLine", // line name + double price = 0 // line price +) +{ + // + bool result = false; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // if the line price is not set, move it to the current Bid price level ... + if (!price) + { + price = SymbolInfoDouble(Symbol(), SYMBOL_BID); + } + + // + // move a horizontal line ... + result = ObjectMove(chartID, objName, 0, 0, price); + + // + return result; +} + +// +// Delete a horizontal line ... +bool DeleteHorizontalLine( + const long chartID = 0, // chart's ID + const string name = "HLine" // line name +) +{ + // + bool result = false; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // delete a horizontal line ... + result = ObjectDelete(chartID, objName); + + // + return result; +} + +// +// Vertical Line Functions ... + +// +// Create the vertical line ... +bool DrawVerticalLine( + const long chartID = 0, // chart's ID + const string name = "VLine", // line name + const int subWindow = 0, // subwindow index + datetime time = 0, // line time + const color clr = clrRed, // line color + const ENUM_LINE_STYLE style = STYLE_SOLID, // line style + const int width = 1, // line width + const bool back = false, // in the background + const bool selection = false, // highlight to move + const bool hidden = false, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + bool result = false; + + // + // if the line time is not set, draw it via the last bar ... + if (!time) + { + time = TimeCurrent(); + } + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // create a vertical line ... + result = ObjectCreate(chartID, objName, OBJ_VLINE, subWindow, time, 0); + if (!result) + { + return result; + } + + // + // set line color ... + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // set line display style ... + ObjectSetInteger(chartID, objName, OBJPROP_STYLE, style); + + // + // set line width ... + ObjectSetInteger(chartID, objName, OBJPROP_WIDTH, width); + + // + // display in the foreground false or background true ... + ObjectSetInteger(chartID, objName, OBJPROP_BACK, back); + + // + // enable true or disable false the mode of moving the line by mouse + // when creating a graphical object using ObjectCreate function, the object cannot be + // highlighted and moved by default. Inside this method, selection parameter + // is true by default making it possible to highlight and move the object ... + ObjectSetInteger(chartID, objName, OBJPROP_SELECTABLE, true); + ObjectSetInteger(chartID, objName, OBJPROP_SELECTED, selection); + + // + // hide true or display false graphical object name in the object list ... + ObjectSetInteger(chartID, objName, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart + ObjectSetInteger(chartID, objName, OBJPROP_ZORDER, zOrder); + + // + // successful execution ... + return result; +} + +// +// Move the vertical line ... +bool MoveVerticalLine( + const long chartID = 0, // chart's ID + const string name = "VLine", // line name + datetime time = 0 // line time +) +{ + // + bool result = false; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // if line time is not set, move the line to the last bar ... + if (!time) + { + time = TimeCurrent(); + } + + // + // move the vertical line ... + result = ObjectMove(chartID, objName, 0, time, 0); + + // + return result; +} + +// +// Delete the vertical line ... +bool DeleteVerticalLine( + const long chartID = 0, // chart's ID + const string name = "VLine" // line name +) +{ + // + bool result = false; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // delete the vertical line ... + result = ObjectDelete(chartID, objName); + + // + return result; +} + +// +// Rectangle Functions ... + +// +// Create rectangle by the given coordinates ... +bool DrawRectangle( + const long chartID = 0, // chart's ID + const string name = "Rectangle", // rectangle name + const int subWindow = 0, // subwindow index + datetime time1 = 0, // down first point time + double price1 = 0, // down first point price + datetime time2 = 0, // up second point time + double price2 = 0, // up second point price + const color clr = clrRed, // rectangle color + const ENUM_LINE_STYLE style = STYLE_SOLID, // style of rectangle lines + const int width = 1, // width of rectangle lines + const bool fill = false, // filling rectangle with color + const bool back = false, // in the background + const bool selection = true, // highlight to move + const bool hidden = true, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + bool result = false; + + // + // Set anchor points' coordinates if they are not set ... + ChangeRectangleEmptyPoints(time1, price1, time2, price2); + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // Create a rectangle by the given coordinates ... + result = ObjectCreate( + chartID, + objName, + OBJ_RECTANGLE, + subWindow, + time1, + price1, + time2, + price2 // + ); + if (!result) + { + return result; + } + + // + // Set rectangle color ... + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // Set the style of rectangle lines + ObjectSetInteger(chartID, objName, OBJPROP_STYLE, style); + + // + // Set width of the rectangle lines ... + ObjectSetInteger(chartID, objName, OBJPROP_WIDTH, width); + + // + // Enable (true) or disable (false) the mode of filling the rectangle ... + ObjectSetInteger(chartID, objName, OBJPROP_FILL, fill); + + // + // Display in the foreground (false) or background (true) ... + ObjectSetInteger(chartID, objName, OBJPROP_BACK, back); + + // + // Enable (true) or disable (false) the mode of highlighting the rectangle for moving + // when creating a graphical object using ObjectCreate function, the object cannot be + // highlighted and moved by default. Inside this method, selection parameter + // is true by default making it possible to highlight and move the object + ObjectSetInteger(chartID, objName, OBJPROP_SELECTABLE, selection); + + // + ObjectSetInteger(chartID, objName, OBJPROP_SELECTED, selection); + + // + // Hide (true) or display (false) graphical object name in the object list ... + ObjectSetInteger(chartID, objName, OBJPROP_HIDDEN, hidden); + + // + // Set the priority for receiving the event of a mouse click in the chart ... + ObjectSetInteger(chartID, objName, OBJPROP_ZORDER, zOrder); + + // + // Successful execution + return result; +} + +// +// Move the rectangle anchor point ...s +bool RectanglePointChange( + const long chartID = 0, // chart's ID + const string name = "Rectangle", // rectangle name + const int pointIndex = 0, // anchor point index + datetime time = 0, // anchor point time coordinate + double price = 0 // anchor point price coordinate +) +{ + // + bool result = false; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // if point position is not set, move it to the current bar having Bid price ... + if (!time) + { + time = TimeCurrent(); + } + + // + if (!price) + { + price = SymbolInfoDouble(Symbol(), SYMBOL_BID); + } + + // + // Move the anchor point ... + result = ObjectMove(chartID, objName, pointIndex, time, price); + + // + return result; +} + +// +// Delete the rectangle ... +bool DeleteRectangle( + const long chartID = 0, // chart's ID + const string name = "Rectangle" // rectangle name +) +{ + // + bool result = false; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + result = ObjectDelete(chartID, objName); + + // + return result; +} + +// +// Check the values of rectangle's anchor points and set default +// values for empty ones +void ChangeRectangleEmptyPoints( + datetime &time1, double &price1, + datetime &time2, double &price2 // +) +{ + // + // if the first point's time is not set, it will be on the current bar ... + if (!time1) + { + time1 = TimeCurrent(); + } + + // + // if the first point's price is not set, it will have Bid value ... + if (!price1) + { + price1 = SymbolInfoDouble(Symbol(), SYMBOL_BID); + } + + // + // if the second point's time is not set, it is located 9 bars left from the second one ... + if (!time2) + { + // + // array for receiving the open time of the last 10 bars ... + datetime temp[10]; + CopyTime(Symbol(), Period(), time1, 10, temp); + + // + // set the second point 9 bars left from the first one ... + time2 = temp[0]; + } + + // + // if the second point's price is not set, move it 300 points lower than the first one ... + if (!price2) + { + price2 = price1 - 300 * SymbolInfoDouble(Symbol(), SYMBOL_POINT); + } +} + +// +// RectangleLabel Functions ... + +// +// Create Rectangle Label Object ... +bool DrawRectangleLabel( + const long chartID = 0, // chart's ID + const string name = "RectLabel", // label name + const int subWindow = 0, // subwindow index + const int x = 0, // X coordinate + const int y = 0, // Y coordinate + const int width = 50, // width + const int height = 18, // height + const color bgColor = clrWhiteSmoke, // background color + const ENUM_BORDER_TYPE border = BORDER_SUNKEN, // border type + const ENUM_BASE_CORNER corner = CORNER_LEFT_UPPER, // chart corner for anchoring + const color clr = clrRed, // flat border color (Flat) + const ENUM_LINE_STYLE style = STYLE_SOLID, // flat border style + const int lineWidth = 1, // flat border width + const bool back = false, // in the background + const bool selection = false, // highlight to move + const bool hidden = false, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + bool result = false; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // create a rectangle label + result = ObjectCreate(chartID, objName, OBJ_RECTANGLE_LABEL, subWindow, 0, 0); + if (!result) + { + return result; + } + + // + // set label coordinates ... + ObjectSetInteger(chartID, objName, OBJPROP_XDISTANCE, x); + ObjectSetInteger(chartID, objName, OBJPROP_YDISTANCE, y); + + // + // set label size ... + ObjectSetInteger(chartID, objName, OBJPROP_XSIZE, width); + ObjectSetInteger(chartID, objName, OBJPROP_YSIZE, height); + + // + // set background color ... + ObjectSetInteger(chartID, objName, OBJPROP_BGCOLOR, bgColor); + + // + // set border type ... + ObjectSetInteger(chartID, objName, OBJPROP_BORDER_TYPE, border); + + // + // set the chart's corner, relative to which point coordinates are defined ... + ObjectSetInteger(chartID, objName, OBJPROP_CORNER, corner); + + // + // set flat border color (in Flat mode) ... + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // set flat border line style ... + ObjectSetInteger(chartID, objName, OBJPROP_STYLE, style); + + // + // set flat border width ... + ObjectSetInteger(chartID, objName, OBJPROP_WIDTH, lineWidth); + + // + // display in the foreground false or background true ... + ObjectSetInteger(chartID, objName, OBJPROP_BACK, back); + + // + // enable true or disable false the mode of moving the label by mouse ... + ObjectSetInteger(chartID, objName, OBJPROP_SELECTABLE, selection); + ObjectSetInteger(chartID, objName, OBJPROP_SELECTED, selection); + + // + // hide true or display false graphical object name in the object list ... + ObjectSetInteger(chartID, objName, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart ... + ObjectSetInteger(chartID, objName, OBJPROP_ZORDER, zOrder); + + // + // successful execution ... + return result; +} + +// +// Move Rectangle Label .. +bool MoveRectangleLabel( + const long chartID = 0, // chart's ID + const string name = "RectLabel", // label name + const int x = 0, // X coordinate + const int y = 0 // Y coordinate +) +{ + // + bool result = false; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // move the rectangle label ... + result = ObjectSetInteger(chartID, objName, OBJPROP_XDISTANCE, x); + if (!result) + { + return result; + } + + // + result = ObjectSetInteger(chartID, objName, OBJPROP_YDISTANCE, y); + + // + return result; +} + +// +// Delete the rectangle label ... +bool DeleteRectangleLabel( + const long chartID = 0, // chart's ID + const string name = "RectLabel" // label name +) +{ + // + bool result = false; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // delete the label ... + result = ObjectDelete(chartID, objName); + + // + return result; +} + +// +// Change Rectangle Label Size ... +bool ChangeSizeRectangleLabel( + const long chartID = 0, // chart's ID + const string name = "RectLabel", // label name + const int width = 50, // label width + const int height = 18 // label height +) +{ + // + bool result = false; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // change label size ... + result = ObjectSetInteger(chartID, objName, OBJPROP_XSIZE, width); + if (!result) + { + return result; + } + + // + result = ObjectSetInteger(chartID, objName, OBJPROP_YSIZE, height); + + // + return result; +} + +// +// Change rectangle label border type ... +bool RectLabelChangeBorderType( + const long chartID = 0, // chart's ID + const string name = "RectLabel", // label name + const ENUM_BORDER_TYPE border = BORDER_SUNKEN // border type +) +{ + // + bool result = false; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // change border type ... + result = ObjectSetInteger(chartID, objName, OBJPROP_BORDER_TYPE, border); + + // + return result; +} + +// +// TrendLine Funcions ... + +// +// Create a trend line by the given coordinates ... +bool DrawTrendLine( + const long chartID = 0, // chart's ID + const string name = "TrendLine", // line name + const int subWindow = 0, // subwindow index + datetime time1 = 0, // first point time + double price1 = 0, // first point price + datetime time2 = 0, // second point time + double price2 = 0, // second point price + const color clr = clrYellow, // line color + const ENUM_LINE_STYLE style = STYLE_SOLID, // line style + const int width = 1, // line width + const bool back = false, // in the background + const bool selection = false, // highlight to move + const bool rayRight = false, // line's continuation to the right + const bool hidden = false, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + bool result = false; + + // + // set anchor points' coordinates if they are not set ... + ChangeTrendLineEmptyPoints( + time1, + price1, + time2, + price2); + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // create a trend line by the given coordinates ... + result = ObjectCreate(chartID, objName, OBJ_TREND, subWindow, time1, price1, time2, price2); + if (!result) + { + return result; + } + + // + // set line color ... + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // set line display style ... + ObjectSetInteger(chartID, objName, OBJPROP_STYLE, style); + + // + // set line width ... + ObjectSetInteger(chartID, objName, OBJPROP_WIDTH, width); + + // + // display in the foreground false or background true ... + ObjectSetInteger(chartID, objName, OBJPROP_BACK, back); + + // + // enable true or disable false the mode of moving the line by mouse + // when creating a graphical object using ObjectCreate function, the object cannot be + // highlighted and moved by default. Inside this method, selection parameter + // is true by default making it possible to highlight and move the object ... + ObjectSetInteger(chartID, objName, OBJPROP_SELECTABLE, true); + ObjectSetInteger(chartID, objName, OBJPROP_SELECTED, selection); + + // + // enable true or disable false the mode of continuation of the line's display to the right ... + ObjectSetInteger(chartID, objName, OBJPROP_RAY_RIGHT, rayRight); + + // + // hide true or display false graphical object name in the object list ... + ObjectSetInteger(chartID, objName, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart ... + ObjectSetInteger(chartID, objName, OBJPROP_ZORDER, zOrder); + + // + // successful execution ... + return result; +} + +// +// Move trend line anchor point ... | +bool ChangeTrendLinePoint( + const long chartID = 0, // chart's ID + const string name = "TrendLine", // line name + const int pointindex = 0, // anchor point index + datetime time = 0, // anchor point time coordinate + double price = 0 // anchor point price coordinate +) +{ + // + bool result = false; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // if point position is not set, move it to the current bar having Bid price ... + if (!time) + { + time = TimeCurrent(); + } + + // + if (!price) + { + price = SymbolInfoDouble(Symbol(), SYMBOL_BID); + } + + // + // move trend line's anchor point ... + result = ObjectMove(chartID, objName, pointindex, time, price); + + // + return result; +} + +// +// The function deletes the trend line from the chart ... +bool DeleteTrendLine( + const long chartID = 0, // chart's ID + const string name = "TrendLine" // line name +) +{ + // + bool result = false; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // delete a trend line ... + result = ObjectDelete(chartID, objName); + + // + return result; +} + +// +// Check the values of trend line's anchor points and set default ... +// values for empty ones ... +void ChangeTrendLineEmptyPoints( + datetime &time1, + double &price1, + datetime &time2, + double &price2 // +) +{ + // + // if the first point's time is not set, it will be on the current bar ... + if (!time1) + { + time1 = TimeCurrent(); + } + + // + // if the first point's price is not set, it will have Bid value ... + if (!price1) + { + price1 = SymbolInfoDouble(Symbol(), SYMBOL_BID); + } + + // + // if the second point's time is not set, it is located 9 bars left from the second one ... + if (!time2) + { + // + // array for receiving the open time of the last 10 bars ... + datetime temp[10]; + CopyTime(Symbol(), Period(), time1, 10, temp); + + // + // set the second point 9 bars left from the first one ... + time2 = temp[0]; + } + + // + // if the second point's price is not set, it is equal to the first point's one ... + if (!price2) + { + price2 = price1; + } +} + +// +// Text Functions ... + +// +// Create and Draw a Text Object ... +bool DrawText( + const long chartID = 0, // chart's ID + const string name = "Text", // object name + const int subWindow = 0, // subwindow index + datetime time = 0, // anchor point time + double price = 0, // anchor point price + const string text = "Text", // the text itself + const string font = "Arial", // font + const int fontSize = 10, // font size + const color clr = clrRed, // color + const double angle = 0.0, // text slope + const ENUM_ANCHOR_POINT anchor = ANCHOR_CENTER, // anchor type + const bool back = false, // in the background + const bool selection = false, // highlight to move + const bool hidden = true, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + bool result = false; + + // + // set anchor point coordinates if they are not set ... + ChangeTextEmptyPoint(time, price); + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // + // create Text object + result = ObjectCreate(chartID, objName, OBJ_TEXT, subWindow, time, price); + if (!result) + { + return result; + } + + // + // set the text ... + ObjectSetString(chartID, objName, OBJPROP_TEXT, text); + + // + // set text font ... + ObjectSetString(chartID, objName, OBJPROP_FONT, font); + + // + // set font size ... + ObjectSetInteger(chartID, objName, OBJPROP_FONTSIZE, fontSize); + + // + // set the slope angle of the text ... + ObjectSetDouble(chartID, objName, OBJPROP_ANGLE, angle); + + // + // set anchor type ... + ObjectSetInteger(chartID, objName, OBJPROP_ANCHOR, anchor); + + // + // set color ... + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // display in the foreground false or background true ... + ObjectSetInteger(chartID, objName, OBJPROP_BACK, back); + + // + // enable true or disable false the mode of moving the object by mouse ... + ObjectSetInteger(chartID, objName, OBJPROP_SELECTABLE, true); + ObjectSetInteger(chartID, objName, OBJPROP_SELECTED, selection); + + // + // hide true or display false graphical object name in the object list ... + ObjectSetInteger(chartID, objName, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart ... + ObjectSetInteger(chartID, objName, OBJPROP_ZORDER, zOrder); + + // + // successful execution ... + return result; +} + +// +// Move the anchor point ... +bool MoveText( + const long chartID = 0, // chart's ID + const string name = "Text", // object name + datetime time = 0, // anchor point time coordinate + double price = 0 // anchor point price coordinate +) +{ + // + bool result = false; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // + // if point position is not set, move it to the current bar having Bid price + if (!time) + { + time = TimeCurrent(); + } + + // + if (!price) + { + price = SymbolInfoDouble(_Symbol, SYMBOL_BID); + } + + // + // move the anchor point ... + result = ObjectMove(chartID, objName, 0, time, price); + + // + return result; +} + +// +// Change the object text ... +bool ChangeText( + const long chartID = 0, // chart's ID + const string name = "Text", // object name + const string text = "Text" // text +) +{ + // + bool result = false; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // change object text ... + result = ObjectSetString(chartID, objName, OBJPROP_TEXT, text); + + // + return result; +} + +// +// Delete Text object ... +bool DeleteText( + const long chartID = 0, // chart's ID + const string name = "Text" // object name +) +{ + // + bool result = false; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // delete the object ... + result = ObjectDelete(chartID, objName); + + // + return result; +} + +// +// Check anchor point values and set default values +// for empty ones ... +void ChangeTextEmptyPoint( + datetime &time, + double &price // +) +{ + // + // if the point's time is not set, it will be on the current bar ... + if (!time) + { + time = TimeCurrent(); + } + + // + // if the point's price is not set, it will have Bid value ... + if (!price) + { + price = SymbolInfoDouble(_Symbol, SYMBOL_BID); + } +} + +// +// Fibonacchi Functions ... + +// +// Create Fibonacci Retracement by the given coordinates ... +bool DrawFibonacci( + const long chartID = 0, // chart's ID + const string name = "Fibonacci", // object name + const int subWindow = 0, // subwindow index + datetime time1 = 0, // first point time + double price1 = 0, // first point price + datetime time2 = 0, // second point time + double price2 = 0, // second point price + const color clr = clrRed, // object color + const ENUM_LINE_STYLE style = STYLE_SOLID, // object line style + const int width = 1, // object line width + const bool back = false, // in the background + const bool selection = true, // highlight to move + const bool rayRight = false, // object's continuation to the right + const bool hidden = true, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + bool result = false; + + // + // set anchor points' coordinates if they are not set ... + ChangeFibonacciEmptyPoints(time1, price1, time2, price2); + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // Create Fibonacci Retracement by the given coordinates ... + result = ObjectCreate(chartID, objName, OBJ_FIBO, subWindow, time1, price1, time2, price2); + if (!result) + { + return result; + } + + // + // set color ... + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // set line style ... + ObjectSetInteger(chartID, objName, OBJPROP_STYLE, style); + + // + // set line width ... + ObjectSetInteger(chartID, objName, OBJPROP_WIDTH, width); + + // + // display in the foreground false or background true ... + ObjectSetInteger(chartID, objName, OBJPROP_BACK, back); + + // + // enable true or disable false the mode of highlighting the channel for moving + // when creating a graphical object using ObjectCreate function, the object cannot be + // highlighted and moved by default. Inside this method, selection parameter + // is true by default making it possible to highlight and move the object ... + ObjectSetInteger(chartID, objName, OBJPROP_SELECTABLE, true); + ObjectSetInteger(chartID, objName, OBJPROP_SELECTED, selection); + + // + // enable true or disable false the mode of continuation of the object's display to the right ... + ObjectSetInteger(chartID, objName, OBJPROP_RAY_RIGHT, rayRight); + + // + // hide true or display false graphical object name in the object list ... + ObjectSetInteger(chartID, objName, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart ... + ObjectSetInteger(chartID, objName, OBJPROP_ZORDER, zOrder); + + // + // successful execution ... + return result; +} + +// +// Create Fibonacci Retracement by the given coordinates ... +bool DrawCustomFibonacci( + // + int levels, // number of level lines + double &values[], // values of level lines + color &colors[], // color of level lines + ENUM_LINE_STYLE &styles[], // style of level lines + int &widths[], // width of level lines + string &descriptions[], // level Descriptions + // + const long chartID = 0, // chart's ID + const string name = "Fibonacci", // object name + const int subWindow = 0, // subwindow index + datetime time1 = 0, // first point time + double price1 = 0, // first point price + datetime time2 = 0, // second point time + double price2 = 0, // second point price + const color clr = clrAqua, // object color + const ENUM_LINE_STYLE style = STYLE_DOT, // object line style + const int width = 1, // object line width + const bool back = false, // in the background + const bool selection = true, // highlight to move + const bool rayRight = false, // object's continuation to the right + const bool hidden = true, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + bool result = false; + + // + // set anchor points' coordinates if they are not set ... + ChangeFibonacciEmptyPoints(time1, price1, time2, price2); + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // Create Fibonacci Retracement by the given coordinates ... + result = ObjectCreate(chartID, name, OBJ_FIBO, subWindow, time1, price1, time2, price2); + if (!result) + { + return result; + } + + // + // set color ... + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // set line style ... + ObjectSetInteger(chartID, objName, OBJPROP_STYLE, style); + + // + // set line width ... + ObjectSetInteger(chartID, objName, OBJPROP_WIDTH, width); + + // + // display in the foreground false or background true ... + ObjectSetInteger(chartID, objName, OBJPROP_BACK, back); + + // + // enable true or disable false the mode of highlighting the channel for moving + // when creating a graphical object using ObjectCreate function, the object cannot be + // highlighted and moved by default. Inside this method, selection parameter + // is true by default making it possible to highlight and move the object ... + ObjectSetInteger(chartID, objName, OBJPROP_SELECTABLE, true); + ObjectSetInteger(chartID, objName, OBJPROP_SELECTED, selection); + + // + // enable true or disable false the mode of continuation of the object's display to the right ... + ObjectSetInteger(chartID, objName, OBJPROP_RAY_RIGHT, rayRight); + + // + // hide true or display false graphical object name in the object list ... + ObjectSetInteger(chartID, objName, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart ... + ObjectSetInteger(chartID, objName, OBJPROP_ZORDER, zOrder); + + // + // Change Levels Of Fibonacci ... + result = FibonacciLevelsSet( + levels, + values, + colors, + styles, + widths, + descriptions, + chartID, + objName); + + // + // successful execution ... + return result; +} + +// +// Set number of levels and their parameters ... +bool FibonacciLevelsSet( + int levels, // number of level lines + double &values[], // values of level lines + color &colors[], // color of level lines + ENUM_LINE_STYLE &styles[], // style of level lines + int &widths[], // width of level lines + string &descriptions[], // level Descriptions + const long chartID = 0, // chart's ID + const string name = "Fibonacci" // object name +) +{ + // + bool result = false; + + // + // check array sizes ... + result = levels == ArraySize(colors) && + levels == ArraySize(styles) && + levels == ArraySize(widths) && + levels == ArraySize(widths); + if (!result) + { + return result; + } + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // set the number of levels ... + ObjectSetInteger(chartID, objName, OBJPROP_LEVELS, levels); + + // + // set the properties of levels in the loop ... + for (int i = 0; i < levels; i++) + { + // + // level value ... + ObjectSetDouble(chartID, objName, OBJPROP_LEVELVALUE, i, values[i]); + + // + // level color ... + ObjectSetInteger(chartID, objName, OBJPROP_LEVELCOLOR, i, colors[i]); + + // + // level style ... + ObjectSetInteger(chartID, objName, OBJPROP_LEVELSTYLE, i, styles[i]); + + // + // level width ... + ObjectSetInteger(chartID, objName, OBJPROP_LEVELWIDTH, i, widths[i]); + + // + // level description ... + // ObjectSetString(chartID, name, OBJPROP_LEVELTEXT, i, DoubleToString(100 * values[i], 1)); + ObjectSetString(chartID, objName, OBJPROP_LEVELTEXT, i, descriptions[i]); + } + + // + // successful execution ... + return result; +} + +// +// Move Fibonacci Retracement anchor point ... +bool FibonacciPointChange( + const long chartID = 0, // chart's ID + const string name = "Fibonacci", // object name + const int pointIndex = 0, // anchor point index + datetime time = 0, // anchor point time coordinate + double price = 0 // anchor point price coordinate +) +{ + // + bool result = false; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // if point position is not set, move it to the current bar having Bid price ... + if (!time) + { + time = TimeCurrent(); + } + + // + if (!price) + { + price = SymbolInfoDouble(_Symbol, SYMBOL_BID); + } + + // + // move the anchor point ... + result = ObjectMove(chartID, objName, pointIndex, time, price); + + // + return result; +} + +// +// Delete Fibonacci Retracement ... +bool DeleteFibonachi( + const long chartID = 0, // chart's ID + const string name = "Fibonacci" // object name +) +{ + // + bool result = false; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // delete the object ... + result = ObjectDelete(chartID, objName); + + // + return result; +} + +// +// Check the values of Fibonacci Retracement anchor points and set +// default values for empty ones ... +void ChangeFibonacciEmptyPoints( + datetime &time1, + double &price1, + datetime &time2, + double &price2 // +) +{ + // + // if the second point's time is not set, it will be on the current bar ... + if (!time2) + { + time2 = TimeCurrent(); + } + + // + // if the second point's price is not set, it will have Bid value ... + if (!price2) + { + price2 = SymbolInfoDouble(_Symbol, SYMBOL_BID); + } + + // + // if the first point's time is not set, it is located 9 bars left from the second one ... + if (!time1) + { + // + // array for receiving the open time of the last 10 bars ... + datetime temp[10]; + CopyTime(Symbol(), Period(), time2, 10, temp); + + // + // set the first point 9 bars left from the second one ... + time1 = temp[0]; + } + + // + // if the first point's price is not set, move it 200 points below the second one ... + if (!price1) + { + price1 = price2 - 200 * SymbolInfoDouble(_Symbol, SYMBOL_POINT); + } +} + +// +// Event Functions ... + +// +// Create an Event ... +bool EventCreate( + const long chartID = 0, // chart's ID + const string name = "Event", // object name + const int subWindow = 0, // subwindow index + const string text = "Content", // event text + datetime time = 0, // anchor point time + const color clr = clrRed, // color + const int width = 1, // point width when highlighted + const bool back = false, // in the background + const bool selection = false, // highlight to move + const bool hidden = true, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + bool result = false; + + // + if (!time) + { + time = TimeCurrent(); + } + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + result = ObjectCreate(chartID, objName, OBJ_EVENT, subWindow, time, 0); + if (!result) + { + return result; + } + + // + // set event text + ObjectSetString(chartID, objName, OBJPROP_TEXT, text); + + // + // set color + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // set anchor point width if the object is highlighted + ObjectSetInteger(chartID, objName, OBJPROP_WIDTH, width); + + // + // display in the foreground false or background true + ObjectSetInteger(chartID, objName, OBJPROP_BACK, back); + + // + // enable true or disable false the mode of moving event by mouse + ObjectSetInteger(chartID, objName, OBJPROP_SELECTABLE, selection); + ObjectSetInteger(chartID, objName, OBJPROP_SELECTED, selection); + + // + // hide true or display false graphical object name in the object list + ObjectSetInteger(chartID, objName, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart + ObjectSetInteger(chartID, objName, OBJPROP_ZORDER, zOrder); + + // + // successful execution + return result; +} + +// +// Change Event object text +bool EventTextChange( + const long chartID = 0, // chart's ID + const string name = "Event", // event name + const string text = "Content" // text +) +{ + // + bool result = false; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // change object text + result = ObjectSetString(chartID, objName, OBJPROP_TEXT, text); + + // + return result; +} + +// +// Move Event object +bool EventMove( + const long chartID = 0, // chart's ID + const string name = "Event", // event name + datetime time = 0 // time +) +{ + // + bool result = false; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // if time is not set, move event to the last bar + if (!time) + { + time = TimeCurrent(); + } + + // + // move the object + result = ObjectMove(chartID, objName, 0, time, 0); + + // + return result; +} + +// +// Delete Event object +bool EventDelete( + const long chartID = 0, // chart's ID + const string name = "Event" // event name +) +{ + // + bool result = false; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // delete the object + result = ObjectDelete(chartID, objName); + + // + return result; +} + +// +// Button Functions ... + +// +// Create the button ... +bool ButtonCreate( + const long chartID = 0, // chart's ID + const string name = "Button", // button name + const int subWindow = 0, // subwindow index + const int x = 0, // X coordinate + const int y = 0, // Y coordinate + const int width = 50, // button width + const int height = 15, // button height + const ENUM_BASE_CORNER corner = CORNER_LEFT_UPPER, // chart corner for anchoring + const string text = "Button", // text + const string font = "Arial", // font + const int fontSize = 8, // font size + const color clr = clrBlack, // text color + const color bgColor = clrLightGray, // background color + const color borderColor = clrNONE, // border color + const bool state = false, // pressed/released + const bool back = false, // in the background + const bool selection = false, // highlight to move + const bool hidden = true, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + bool result = false; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // create the button + result = ObjectCreate(chartID, objName, OBJ_BUTTON, subWindow, 0, 0); + if (!result) + { + return result; + } + + // + // set button coordinates + ObjectSetInteger(chartID, objName, OBJPROP_XDISTANCE, x); + ObjectSetInteger(chartID, objName, OBJPROP_YDISTANCE, y); + + // + // set button size + ObjectSetInteger(chartID, objName, OBJPROP_XSIZE, width); + ObjectSetInteger(chartID, objName, OBJPROP_YSIZE, height); + + // + // set the chart's corner, relative to which point coordinates are defined + ObjectSetInteger(chartID, objName, OBJPROP_CORNER, corner); + + // + // set the text + ObjectSetString(chartID, objName, OBJPROP_TEXT, text); + + // + // set text font + ObjectSetString(chartID, objName, OBJPROP_FONT, font); + + // + // set font size + ObjectSetInteger(chartID, objName, OBJPROP_FONTSIZE, fontSize); + + // + // set text color + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // set background color + ObjectSetInteger(chartID, objName, OBJPROP_BGCOLOR, bgColor); + + // + // set border color + ObjectSetInteger(chartID, objName, OBJPROP_BORDER_COLOR, borderColor); + + // + // display in the foreground false or background true + ObjectSetInteger(chartID, objName, OBJPROP_BACK, back); + + // + // set button state + ObjectSetInteger(chartID, objName, OBJPROP_STATE, state); + + // + // enable true or disable false the mode of moving the button by mouse + ObjectSetInteger(chartID, objName, OBJPROP_SELECTABLE, selection); + ObjectSetInteger(chartID, objName, OBJPROP_SELECTED, selection); + + // + // hide true or display false graphical object name in the object list + ObjectSetInteger(chartID, objName, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart + ObjectSetInteger(chartID, objName, OBJPROP_ZORDER, zOrder); + + // + return result; +} + +// +// Move the button ... +bool ButtonMove( + const long chartID = 0, // chart's ID + const string name = "Button", // button name + const int x = 0, // X coordinate + const int y = 0 // Y coordinate +) +{ + // + bool result = false; + + // + // move the button + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + result = ObjectSetInteger(chartID, objName, OBJPROP_XDISTANCE, x); + if (!result) + { + return result; + } + + // + result = ObjectSetInteger(chartID, objName, OBJPROP_YDISTANCE, y); + + // + return result; +} + +// +// Change button size ... +bool ButtonChangeSize( + const long chartID = 0, // chart's ID + const string name = "Button", // button name + const int width = 50, // button width + const int height = 18 // button height +) +{ + // + bool result = false; + + // + // change the button size + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + result = ObjectSetInteger(chartID, objName, OBJPROP_XSIZE, width); + if (!result) + { + return result; + } + + // + result = ObjectSetInteger(chartID, objName, OBJPROP_YSIZE, height); + + // + return result; +} + +// +// Change corner of the chart for binding the button ... +bool ButtonChangeCorner( + const long chartID = 0, // chart's ID + const string name = "Button", // button name + const ENUM_BASE_CORNER corner = CORNER_LEFT_UPPER // chart corner for anchoring +) +{ + // + bool result = false; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // change anchor corner + result = ObjectSetInteger(chartID, objName, OBJPROP_CORNER, corner); + + // + return result; +} + +// +// Change button text ... +bool ButtonTextChange( + const long chartID = 0, // chart's ID + const string name = "Button", // button name + const string text = "Text" // text +) +{ + // + bool result = false; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // change object text + result = ObjectSetString(chartID, objName, OBJPROP_TEXT, text); + + // + return result; +} + +// +// Delete the button ... +bool ButtonDelete( + const long chartID = 0, // chart's ID + const string name = "Button" // button name +) +{ + // + bool result = false; + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // delete the button + result = ObjectDelete(chartID, objName); + + // + return result; +} + +// +// Chart Style Drawers ... + +// +// Apply Styles On Chart ... +void ApplyChartStyle( + long mChartId = -1, // chart's ID + ENUM_CHART_MODE mMode = CHART_CANDLES, // chart's mMode + bool mShowBidLine = true, // show bid line + bool mShowAskLine = true, // show ask line + bool mShowGrid = false, // show grids on chart + bool mShowVolumes = false, // show volumes + bool mShowTradeLevels = true, // Displaying trade levels in the chart (levels of open positions, Stop Loss, Take Profit and pending orders) + bool mAutoScroll = true, // chart autoscroll + bool mQuickNavigation = true, // chart quick navigation state + color mForeGroundColor = clrWhite, // chart's foreground color + color mBackGroundColor = clrBlack, // chart's background color + color mUpColor = clrGreen, // Up Color + color mDownColor = clrRed, // Down Color + color mBullishColor = clrGreen, // Bullish color + color mBearishColor = clrRed, // Bearish color + color mGridColor = clrGray, // grid color + color mBidLineColor = clrGray, // bid line color + color mAskLineColor = clrRed, // ask line color + color mLineColor = clrLime, // line mMode and doji candlestick color + color mStopColor = clrGold, // Color of stop order levels (Stop Loss and Take Profit) + color mVolumesColor = clrGreen // volumes color +) +{ + // + // Validate Args ... + if (mChartId == -1) + { + mChartId = 0; + } + + // + ChartSetInteger(mChartId, CHART_MODE, mMode); + ChartSetInteger(mChartId, CHART_SHOW_BID_LINE, mShowBidLine); + ChartSetInteger(mChartId, CHART_SHOW_ASK_LINE, mShowAskLine); + ChartSetInteger(mChartId, CHART_SHOW_GRID, mShowGrid); + ChartSetInteger(mChartId, CHART_SHOW_VOLUMES, mShowVolumes); + ChartSetInteger(mChartId, CHART_SHOW_TRADE_LEVELS, mShowTradeLevels); + ChartSetInteger(mChartId, CHART_AUTOSCROLL, mAutoScroll); + ChartSetInteger(mChartId, CHART_QUICK_NAVIGATION, mQuickNavigation); + ChartSetInteger(mChartId, CHART_COLOR_FOREGROUND, mForeGroundColor); + ChartSetInteger(mChartId, CHART_COLOR_BACKGROUND, mBackGroundColor); + ChartSetInteger(mChartId, CHART_COLOR_CHART_UP, mUpColor); + ChartSetInteger(mChartId, CHART_COLOR_CHART_DOWN, mDownColor); + ChartSetInteger(mChartId, CHART_COLOR_CANDLE_BULL, mBullishColor); + ChartSetInteger(mChartId, CHART_COLOR_CANDLE_BEAR, mBearishColor); + ChartSetInteger(mChartId, CHART_COLOR_GRID, mGridColor); + ChartSetInteger(mChartId, CHART_COLOR_BID, mBidLineColor); + ChartSetInteger(mChartId, CHART_COLOR_ASK, mAskLineColor); + ChartSetInteger(mChartId, CHART_COLOR_STOP_LEVEL, mStopColor); + ChartSetInteger(mChartId, CHART_COLOR_CHART_LINE, mLineColor); + ChartSetInteger(mChartId, CHART_COLOR_VOLUME, mVolumesColor); +} + +// +// Tools ... + +// +// Retrieve Chart Size ... +bool GetChartSize( + XSize &result, // Holds Result ... + long chartID = 0 // Specified Chart ID ... +) +{ + // + bool mResult = false; + + // + mResult = ChartGetInteger(0, CHART_WIDTH_IN_PIXELS, 0, result.width); + if (!mResult) + { + return mResult; + } + + // + mResult = ChartGetInteger(0, CHART_HEIGHT_IN_PIXELS, 0, result.height); + + // + return mResult; +} diff --git a/BKPS/14031218/Libraries/x-saherelm.x-poi.extensions.lib.ex5 b/BKPS/14031218/Libraries/x-saherelm.x-poi.extensions.lib.ex5 new file mode 100644 index 0000000..f14d701 Binary files /dev/null and b/BKPS/14031218/Libraries/x-saherelm.x-poi.extensions.lib.ex5 differ diff --git a/BKPS/14031218/Libraries/x-saherelm.x-poi.extensions.lib.mq5 b/BKPS/14031218/Libraries/x-saherelm.x-poi.extensions.lib.mq5 new file mode 100644 index 0000000..12a6f82 --- /dev/null +++ b/BKPS/14031218/Libraries/x-saherelm.x-poi.extensions.lib.mq5 @@ -0,0 +1,3113 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Seriallize Library +// --------------------------------------- +// Name: XPOILib +// Description: All models related to POIs ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright `023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Libraries/x-saherelm.x-poi.lib.mq5" +#include "../Libraries/x-saherelm.x-poi.state.lib.mq5" + +// +// Extensions ... + +template +bool ToZone( + T *&source[], + XCZone *&dest[] // +) +{ + // + bool result = false; + + // + Clean(dest); + + // + int count = ArraySize(source); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + T *item = source[i]; + + // + if (item != NULL) + { + // + Add( + (XCZone *)item, + dest // + ); + } + } + + // + int destCount = ArraySize(dest); + result = IsValidSize(destCount); + + // + return result; +} + +template +bool ToBox( + T *&source[], + XBoxZone &dest[] // +) +{ + // + bool result = false; + + // + Clean(dest); + + // + int count = ArraySize(source); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + T *item = source[i]; + + // + if (item != NULL) + { + // + XBoxZone iBox; + bool hasBox = ToBox( + iBox, + item // + ); + + // + if (hasBox) + { + // + AddRef( + iBox, + dest // + ); + } + } + } + + // + int destCount = ArraySize(dest); + result = IsValidSize(destCount); + + // + return result; +} + +template +int GetOldest( + T *&source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone boxes[]; + bool isConverted = ToBox( + source, + boxes // + ); + if (!isConverted) + { + return result; + } + + // + int boxesCount = ArraySize(boxes); + + // + if (count != boxesCount) + { + return result; + } + + // + result = GetOldest(boxes); + + // + Clean(boxes); + + // + return result; +} + +template +int GetYoungest( + T *&source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone boxes[]; + bool isConverted = ToBox( + source, + boxes // + ); + if (!isConverted) + { + return result; + } + + // + int boxesCount = ArraySize(boxes); + + // + if (count != boxesCount) + { + return result; + } + + // + result = GetYoungest(boxes); + + // + Clean(boxes); + + // + return result; +} + +template +int GetLowest( + T *&source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone boxes[]; + bool isConverted = ToBox( + source, + boxes // + ); + if (!isConverted) + { + return result; + } + + // + int boxesCount = ArraySize(boxes); + + // + if (count != boxesCount) + { + return result; + } + + // + result = GetLowest(boxes); + + // + Clean(boxes); + + // + return result; +} + +template +int GetHighest( + T *&source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone boxes[]; + bool isConverted = ToBox( + source, + boxes // + ); + if (!isConverted) + { + return result; + } + + // + int boxesCount = ArraySize(boxes); + + // + if (count != boxesCount) + { + return result; + } + + // + result = GetHighest(boxes); + + // + Clean(boxes); + + // + return result; +} + +template +bool IsSame( + T *source, + T *dest // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = sourceBox.IsSame(destBox); + + // + return result; +} + +template +bool IsSameDiff( + T *source, + F *dest // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = sourceBox.IsSame(destBox); + + // + return result; +} + +template +bool IsBelow( + T *source, + T *dest, + bool ignoreInside = false // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = IsBoxBelow( + sourceBox, + destBox, + ignoreInside // + ); + + // + return result; +} + +template +bool IsBelowDiff( + T *source, + F *dest, + bool ignoreInside = false // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = IsBoxBelow( + sourceBox, + destBox, + ignoreInside // + ); + + // + return result; +} + +template +bool IsAbove( + T *source, + T *dest, + bool ignoreInside = false // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = IsBoxAbove( + sourceBox, + destBox, + ignoreInside // + ); + + // + return result; +} + +template +bool IsAboveDiff( + T *source, + F *dest, + bool ignoreInside = false // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = IsBoxAbove( + sourceBox, + destBox, + ignoreInside // + ); + + // + return result; +} + +template +bool IsInside( + T *source, + T *dest // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = IsBoxInside( + sourceBox, + destBox // + ); + + // + return result; +} + +template +bool IsInsideOr( + T *source, + T *dest // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = IsBoxInsideOr( + sourceBox, + destBox // + ); + + // + return result; +} + +template +bool IsInsideDiff( + T *source, + F *dest, + bool forceSideOut = false // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = IsBoxInside( + sourceBox, + destBox, + forceSideOut // + ); + + // + return result; +} + +template +bool IsInsideOrDiff( + T *source, + F *dest, + bool forceSideOut = false // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + XBoxZone destBox; + result = ToBox( + destBox, + dest // + ); + if (!result) + { + return result; + } + + // + result = IsBoxInsideOr( + sourceBox, + destBox // + ); + + // + return result; +} + +template +bool FindIndex( + int &index, + T *item, + T *&items[] // +) +{ + // + bool result = false; + + // + index = -1; + + // + XBoxZone itemBox; + result = ToBox( + itemBox, + item // + ); + if (!result) + { + return result; + } + + // + XBoxZone itemsBox[]; + result = ToBox( + items, + itemsBox // + ); + if (!result) + { + return result; + } + + // + result = FindBoxIndex( + index, + itemBox, + itemsBox // + ); + + // + return result; +} + +template +bool IsInside( + double value, + T *source // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + result = IsInsideBox( + value, + sourceBox // + ); + + // + return result; +} + +template +bool IsAbove( + double value, + T *source // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + result = IsAboveBox( + value, + sourceBox // + ); + + // + return result; +} + +template +bool IsBelow( + double value, + T *source // +) +{ + // + bool result = false; + + // + XBoxZone sourceBox; + result = ToBox( + sourceBox, + source // + ); + if (!result) + { + return result; + } + + // + result = IsBelowBox( + value, + sourceBox // + ); + + // + return result; +} + +/** + * Find Specified Box Index inside a Collection of Boxes ... + * + * @param box: XBoxZone instance Reference ... + * @param boxes: XBoxZone instance Reference Collection ... + * + * @return ( int ) + */ +bool FindBoxIndex( + int &index, + XBoxZone &box, + XBoxZone &boxes[] // +) +{ + // + bool result = false; + + // + index = -1; + + // + int count = ArraySize(boxes); + result = box.IsValid() && + IsValidSize(count); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = boxes[i]; + + // + bool isSame = box.IsSame(iBox); + if (isSame) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; +} + +/** + * Check Source Box is Below Dest ... + * + * @param source: XBoxZone instance Reference ... + * @param dest: XBoxZone instance Reference ... + * @param ignoreInside: bool ... + * + * @return ( bool ) + */ +bool IsBoxBelow( + XBoxZone &source, + XBoxZone &dest, + bool ignoreInside = false // +) +{ + // + bool result = false; + + // + result = source.IsValid() && + dest.IsValid() && + !source.IsSame(dest); + if (!result) + { + return result; + } + + // + if (!ignoreInside) + { + result = source.upper < dest.lower; + } + else + { + result = (source.upper < dest.lower || + source.upper >= dest.upper) && + source.lower < dest.lower; + } + + // + return result; +} + +/** + * Check Source Box is Above Dest ... + * + * @param source: XBoxZone instance Reference ... + * @param dest: XBoxZone instance Reference ... + * @param ignoreInside: bool ... + * + * @return ( bool ) + */ +bool IsBoxAbove( + XBoxZone &source, + XBoxZone &dest, + bool ignoreInside = false // +) +{ + // + bool result = false; + + // + result = source.IsValid() && + dest.IsValid() && + !source.IsSame(dest); + if (!result) + { + return result; + } + + // + if (!ignoreInside) + { + result = source.lower > dest.upper; + } + else + { + result = (source.lower > dest.upper || + source.lower <= dest.upper) && + source.upper > dest.upper; + } + + // + return result; +} + +/** + * Check Source Box is Inside Dest ... + * + * @param source: XBoxZone instance Reference ... + * @param dest: XBoxZone instance Reference ... + * @param forceSideOut: bool, force check Box has One Side Out ... + * @param ignoreSideOut: bool, Accept if source Box one Side is out of Dest Box ... + * + * @return ( bool ) + */ +bool IsBoxInside( + XBoxZone &source, + XBoxZone &dest, + bool forceSideOut = false, // + bool ignoreSideOut = true // +) +{ + // + bool result = false; + + // + result = source.IsValid() && + dest.IsValid() && + !source.IsSame(dest); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(dest.dir); + + // + if (!forceSideOut) + { + // + if (ignoreSideOut) + { + // + result = source.lower >= dest.lower && + source.upper <= dest.upper; + } + else + { + result = source.lower >= dest.lower || + source.upper <= dest.upper; + } + } + else + { + // + bool hasSideIn = + isBullish + ? source.lower >= dest.lower + : source.upper <= dest.upper; + bool hasSideOut = + isBullish + ? source.upper >= dest.upper + : source.lower <= dest.lower; + result = + hasSideIn && + hasSideOut; + } + + // + return result; +} + +/** + * Detect source BoX is Inside Dest Box or Have a Side Out on it ... + * + * @param source: XBoxZone instance, source box which checks by dest ... + * @param dest: XBoxZone instance, dest Box which compares source with it ... + * + * @return ( bool ) + */ +bool IsBoxInsideOr( + XBoxZone &source, + XBoxZone &dest // +) +{ + // + bool result = false; + + // + result = source.IsValid() && + dest.IsValid() && + !source.IsSame(dest); + if (!result) + { + return result; + } + + // + bool isLowerInside = + source.lower > dest.lower && + source.lower < dest.upper && + (source.upper < dest.upper || + source.upper > dest.upper); + bool isUpperInside = + source.upper < dest.upper && + source.upper > dest.lower && + (source.lower > dest.lower || + source.lower < dest.lower); + result = + isLowerInside || + isUpperInside; + + // + return result; +} + +/** + * Check Value is Inside Specified Box ... + * + * @param value: double ... + * @param box: XCBozZone instance Reference ... + * + * @return ( bool ) + */ +bool IsInsideBox( + double value, + XBoxZone &box // +) +{ + // + bool result = false; + + // + result = value > 0 && + box.IsValid() && + value <= box.upper && + value >= box.lower; + + // + return result; +} + +/** + * Check Value is Above Specified Box ... + * + * @param value: double ... + * @param box: XCBozZone instance Reference ... + * + * @return ( bool ) + */ +bool IsAboveBox( + double value, + XBoxZone &box // +) +{ + // + bool result = false; + + // + result = value > 0 && + box.IsValid() && + value > box.upper; + + // + return result; +} + +/** + * Check Value is Below Specified Box ... + * + * @param value: double ... + * @param box: XCBozZone instance Reference ... + * + * @return ( bool ) + */ +bool IsBelowBox( + double value, + XBoxZone &box // +) +{ + // + bool result = false; + + // + result = value > 0 && + box.IsValid() && + value < box.lower; + + // + return result; +} + +/** + * Check a Box is Used or not ... + * + * @param box: XBoxZone instance Reference ... + * @param fromIndex: int ... + * @param toIndex: int + * @param forPeriod: Specified Period ... + * + * @return ( bool ) + */ +bool IsBoxUsed( + XBoxZone &box, + int fromIndex, + int toIndex = 0, + ENUM_TIMEFRAMES forPeriod = NULL // +) +{ + // + bool result = false; + + // + if (toIndex < 0) + { + toIndex = 0; + } + + // + result = + // + box.IsValid() && + fromIndex > 0 && + fromIndex > toIndex + // + ; + if (!result) + { + return result; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = box.period; + } + + // + ENUM_X_DIRECTION forDir = box.dir; + bool isBullish = IsBullish(forDir); + + // + for (int i = fromIndex; i >= toIndex; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + box.symbol, + forPeriod, + i // + ); + + // + bool isTouched = + isBullish + ? iBar.high > box.lower + : iBar.low < box.upper; + if (!isTouched) + { + continue; + } + + // + iBar.Clean(); + result = false; + break; + } + + // + return result; +} + +/** + * Find an Inside Box of source in a Collection ... + * + * @param index: int, Founded Index ... + * @param source: XBoxZone instance ... + * @param dest: XBoxZone instance Collection ... + * + * @return ( bool ) + */ +bool HasInsideBox( + int &index, + XBoxZone &source, + XBoxZone &dest[] // +) +{ + // + bool result = false; + + // + index = -1; + + // + result = source.IsValid() && + HasChild(dest); + + // + int count = ArraySize(dest); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = dest[i]; + + // + bool isInside = !iBox.IsSameAs(source) && + IsBoxInsideOr( + iBox, + source // + ); + if (isInside) + { + // + index = i; + iBox.Clean(); + + // + break; + } + + // + iBox.Clean(); + } + + // + result = IsValidIndex(index); + + // + return result; +} + +bool IsValidBox( + XBoxZone &box, + int barIndex = 0, + ENUM_TIMEFRAMES forPeriod = NULL // +) +{ + // + bool result = false; + + // + result = box.IsValid(); + if (!result) + { + return result; + } + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = box.period; + } + + // + int fromIndex = iBarShift( + box.symbol, + forPeriod, + box.from // + ); + result = IsValidIndex(fromIndex); + if (!result) + { + return result; + } + + // + XOHCL iBar; + bool isBullish = box.IsBullish(); + for (int i = barIndex; i < fromIndex; i++) + { + // + result = iBar.Init( + box.symbol, + forPeriod, + i // + ); + if (!result) + { + break; + } + + // + result = + isBullish + ? iBar.GetDown() > box.lower + : iBar.GetUp() < box.upper; + if (!result) + { + break; + } + + // + iBar.Clean(); + } + + // + iBar.Clean(); + + // + return result; +} + +/** + * Converts to XBoxZone ... + * + * @return ( bool ) + */ +bool ToBox( + XBoxZone &box, + XCOrderBlock *item // +) +{ + // + bool result = false; + + // + box.Clean(); + + // + result = item != NULL && + item.IsValid(); + if (!result) + { + return result; + } + + // + box.to = item.To(); + box.from = item.From(); + box.upper = item.Upper(); + box.lower = item.Lower(); + box.symbol = item.GetSymbol(); + box.period = item.GetPeriod(); + box.type = item.TypeAsString(); + box.dir = item.IsBullish() + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = box.IsValid(); + + // + return result; +} + +/** + * Converts to XBoxZone ... + * + * @return ( bool ) + */ +bool ToBox( + XBoxZone &box, + XCFVG *item // +) +{ + // + bool result = false; + + // + box.Clean(); + + // + result = item != NULL && + item.IsValid(); + if (!result) + { + return result; + } + + // + box.to = item.To(); + box.from = item.From(); + box.upper = item.Upper(); + box.lower = item.Lower(); + box.symbol = item.GetSymbol(); + box.period = item.GetPeriod(); + box.type = item.TypeAsString(); + box.dir = item.IsBullish() + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = box.IsValid(); + + // + return result; +} + +/** + * Converts to XBoxZone ... + * + * @return ( bool ) + */ +bool ToBox( + XBoxZone &box, + XCSupportZone *item // +) +{ + // + bool result = false; + + // + box.Clean(); + + // + result = item != NULL && + item.IsValid(); + if (!result) + { + return result; + } + + // + box.to = item.To(); + box.from = item.From(); + box.upper = item.Upper(); + box.lower = item.Lower(); + box.symbol = item.GetSymbol(); + box.period = item.GetPeriod(); + box.type = item.TypeAsString(); + box.dir = X_DIRECTION_BULLISH; + + // + result = box.IsValid(); + + // + return result; +} + +/** + * Converts to XBoxZone ... + * + * @return ( bool ) + */ +bool ToBox( + XBoxZone &box, + XCResistanceZone *item // +) +{ + // + bool result = false; + + // + box.Clean(); + + // + result = item != NULL && + item.IsValid(); + if (!result) + { + return result; + } + + // + box.to = item.To(); + box.from = item.From(); + box.upper = item.Upper(); + box.lower = item.Lower(); + box.symbol = item.GetSymbol(); + box.period = item.GetPeriod(); + box.type = item.TypeAsString(); + box.dir = X_DIRECTION_BEARISH; + + // + result = box.IsValid(); + + // + return result; +} + +/** + * Converts to XBoxZone ... + * + * @return ( bool ) + */ +bool ToBox( + XBoxZone &box, + XCSupplyZone *item // +) +{ + // + bool result = false; + + // + box.Clean(); + + // + result = item != NULL && + item.IsValid(); + if (!result) + { + return result; + } + + // + box.to = item.To(); + box.from = item.From(); + box.upper = item.Upper(); + box.lower = item.Lower(); + box.symbol = item.GetSymbol(); + box.period = item.GetPeriod(); + box.type = item.TypeAsString(); + box.dir = X_DIRECTION_BEARISH; + + // + result = box.IsValid(); + + // + return result; +} + +/** + * Converts to XBoxZone ... + * + * @return ( bool ) + */ +bool ToBox( + XBoxZone &box, + XCDemandZone *item // +) +{ + // + bool result = false; + + // + box.Clean(); + + // + result = item != NULL && + item.IsValid(); + if (!result) + { + return result; + } + + // + box.to = item.To(); + box.from = item.From(); + box.upper = item.Upper(); + box.lower = item.Lower(); + box.symbol = item.GetSymbol(); + box.period = item.GetPeriod(); + box.type = item.TypeAsString(); + box.dir = X_DIRECTION_BULLISH; + + // + result = box.IsValid(); + + // + return result; +} + +/** + * Converts to XBoxZone ... + * + * @return ( bool ) + */ +bool ToBox( + XBoxZone &box, + XConsolidationZone &item // +) +{ + // + bool result = false; + + // + box.Clean(); + + // + result = item.IsValid(); + if (!result) + { + return result; + } + + // + box.to = item.to; + box.dir = item.dir; + box.from = item.from; + box.upper = item.upper; + box.lower = item.lower; + box.symbol = item.symbol; + box.period = item.period; + box.type = IsBullish(item.dir) + ? ToString(X_BULLISH_CONSOLIDATION_ZONE) + : ToString(X_BEARISH_CONSOLIDATION_ZONE); + + // + result = box.IsValid(); + + // + return result; +} + +/** + * Converts to XBoxZone ... + * + * @return ( bool ) + */ +int ToBox( + XConsolidationZone &source[], + XBoxZone &dest[] // +) +{ + // + int result = 0; + + // + Clean(dest); + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XConsolidationZone iZone = source[i]; + + // + XBoxZone iBox; + bool hasBox = ToBox( + iBox, + iZone // + ); + + // + if (hasBox) + { + // + AddRef( + iBox, + dest // + ); + } + + // + iBox.Clean(); + iZone.Clean(); + } + + // + result = ArraySize(dest); + + // + return result; +} + +/** + * Get Oldest Box Index ... + * + * @param source: XBoxZone instance Reference Collection ... + * + * @return ( int ) + */ +int GetOldest( + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = source[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.from > iBox.from; + if (canSet) + { + // + result = i; + selected = iBox; + } + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Get Youngest Box Index ... + * + * @param source: XBoxZone instance Reference Collection ... + * + * @return ( int ) + */ +int GetYoungest( + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = source[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.from < iBox.from; + if (canSet) + { + // + result = i; + selected = iBox; + } + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Get Highest Box Index ... + * + * @param source: XBoxZone instance Reference Collection ... + * + * @return ( int ) + */ +int GetHighest( + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = source[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.upper < iBox.upper; + if (canSet) + { + // + result = i; + selected = iBox; + } + } + + // + selected.Clean(); + + // + return result; +} + +/** + * Get Lowest Box Index ... + * + * @param source: XBoxZone instance Reference Collection ... + * + * @return ( int ) + */ +int GetLowest( + XBoxZone &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = source[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.lower > iBox.lower; + if (canSet) + { + // + result = i; + selected = iBox; + } + } + + // + selected.Clean(); + + // + return result; +} + +// +// +// + +/** + * Get Oldest Index ... + * + * @param source: XConsolidationZone instance Reference Collection ... + * + * @return ( int ) + */ +int GetOldest( + XConsolidationZone &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone tmpBoxes[]; + int boxesCount = ToBox( + source, + tmpBoxes // + ); + if (!IsValidSize(boxesCount)) + { + // + Clean(tmpBoxes); + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < boxesCount; i++) + { + // + XBoxZone iBox = tmpBoxes[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.from > iBox.from; + if (canSet) + { + // + result = i; + selected = iBox; + } + } + + // + Clean(tmpBoxes); + selected.Clean(); + + // + return result; +} + +/** + * Get Youngest Index ... + * + * @param source: XConsolidationZone instance Reference Collection ... + * + * @return ( int ) + */ +int GetYoungest( + XConsolidationZone &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone tmpBoxes[]; + int boxesCount = ToBox( + source, + tmpBoxes // + ); + if (!IsValidSize(boxesCount)) + { + // + Clean(tmpBoxes); + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < boxesCount; i++) + { + // + XBoxZone iBox = tmpBoxes[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.from < iBox.from; + if (canSet) + { + // + result = i; + selected = iBox; + } + } + + // + Clean(tmpBoxes); + selected.Clean(); + + // + return result; +} + +/** + * Get Highest Index ... + * + * @param source: XConsolidationZone instance Reference Collection ... + * + * @return ( int ) + */ +int GetHighest( + XConsolidationZone &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone tmpBoxes[]; + int boxesCount = ToBox( + source, + tmpBoxes // + ); + if (!IsValidSize(boxesCount)) + { + // + Clean(tmpBoxes); + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < boxesCount; i++) + { + // + XBoxZone iBox = tmpBoxes[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.upper < iBox.upper; + if (canSet) + { + // + result = i; + selected = iBox; + } + } + + // + Clean(tmpBoxes); + selected.Clean(); + + // + return result; +} + +/** + * Get Lowest Index ... + * + * @param source: XConsolidationZone instance Reference Collection ... + * + * @return ( int ) + */ +int GetLowest( + XConsolidationZone &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone tmpBoxes[]; + int boxesCount = ToBox( + source, + tmpBoxes // + ); + if (!IsValidSize(boxesCount)) + { + // + Clean(tmpBoxes); + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < boxesCount; i++) + { + // + XBoxZone iBox = tmpBoxes[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.lower > iBox.lower; + if (canSet) + { + // + result = i; + selected = iBox; + } + } + + // + Clean(tmpBoxes); + selected.Clean(); + + // + return result; +} + +// +// +// + +// +template +void SortZones( + T *&source[], + ENUM_X_DIRECTION forDir, + bool ignoreInside = true // +) +{ + // + int idx = -1; + int count = 0; + bool has = false; + + // + has = HasDirection(forDir); + if (!has) + { + return; + } + + // + bool isBullish = IsBullish(forDir); + + // + count = ArraySize(source); + has = IsValidSize(count); + if (!has) + { + return; + } + + // + T *tmpItems[]; + T *last = NULL; + bool hasLast = false; + while (HasChild(source)) + { + // + if (!hasLast) + { + // + idx = GetOldest(source); + hasLast = IsValidIndex(idx); + if (hasLast) + { + // + last = source[idx]; + ArrayRemove( + source, + idx, + 1 // + ); + + // + Add( + last, + tmpItems // + ); + } + + // + count = ArraySize(source); + has = IsValidSize(count); + if (!has) + { + // + ZeroMemory(last); + break; + } + } + if (!hasLast) + { + // + ZeroMemory(last); + break; + } + + // + T *item = NULL; + idx = GetOldest(source); + has = IsValidIndex(idx); + if (!has) + { + // + ZeroMemory(last); + ZeroMemory(item); + break; + } + item = source[idx]; + ArrayRemove( + source, + idx, + 1 // + ); + + // + bool isAbove = IsAbove( + item, + last, + ignoreInside // + ); + + // + bool isBelow = IsBelow( + item, + last, + ignoreInside // + ); + + // + has = + isBullish + ? isAbove + : isBelow; + if (has) + { + // + Add( + item, + tmpItems // + ); + + // + last = item; + hasLast = item != NULL; + } + } + + // + Clean(source); + Copy( + tmpItems, + source // + ); + + // + Clean(tmpItems); +} + +/** + * Extract all Zones Which provided bar is Inside it ... + * + * @return ( int ) + */ +template +int ExtractInsideZones( + XOHCL &bar, // Bar ... + T *&zones[], // Source of Zones ... + T *&dest[] // Dest (all inside Zones) ... +) +{ + // + int result = 0; + + // + Clean(dest); + + // + int count = ArraySize(zones); + bool isValid = bar.IsValid() && + IsValidSize(count); + if (!isValid) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + T *iZone = zones[i]; + + // + bool isHighInside = IsInside( + bar.high, + iZone // + ); + + // + bool isLowInside = IsInside( + bar.low, + iZone // + ); + + // + bool isInside = + isLowInside && + isHighInside; + + // + if (isInside) + { + // + Add( + iZone, + dest // + ); + } + + // + ZeroMemory(iZone); + } + + // + result = ArraySize(dest); + + // + return result; +} + +/** + * Add Specific Item into a Collection Reference only if it's not Exists ... + * + * @return ( bool ) + */ +template +bool AddIfNotExists( + T *item, + T *&items[] // +) +{ + // + bool result = false; + + // + result = item != NULL; + if (!result) + { + return result; + } + + // + int before = ArraySize(items); + + // + int idx = FindIndex( + item, + items // + ); + bool has = IsValidIndex(idx); + result = !has; + if (!result) + { + return result; + } + + // + Add( + item, + items // + ); + + // + int after = ArraySize(items); + + // + result = after > before; + + // + return result; +} +bool AddIfNotExists( + XConsolidationZone &item, + XConsolidationZone &items[] // +) +{ + // + bool result = false; + + // + result = item.IsValid(); + if (!result) + { + return result; + } + + // + int before = ArraySize(items); + + // + int idx = FindIndex( + item, + items // + ); + bool has = IsValidIndex(idx); + result = !has; + if (!result) + { + return result; + } + + // + AddRef( + item, + items // + ); + + // + int after = ArraySize(items); + + // + result = after > before; + + // + return result; +} + +/** + * Add items Collection reference Members into source Collection only if it's not Exists ...alignas + * @return ( int ) + */ +template +int AddIfNotExists( + T *&items[], + T *&sources[] // +) +{ + // + int result = 0; + + // + bool has = HasChild(items); + if (!has) + { + return result; + } + + // + int before = ArraySize(sources); + + // + int count = ArraySize(items); + for (int i = 0; i < count; i++) + { + // + has = AddIfNotExists( + items[i], + sources // + ); + } + + // + int after = ArraySize(sources); + + // + result = after > before; + + // + return result; +} +int AddIfNotExists( + XConsolidationZone &items[], + XConsolidationZone &sources[] // +) +{ + // + int result = 0; + + // + bool has = HasChild(items); + if (!has) + { + return result; + } + + // + int before = ArraySize(sources); + + // + int count = ArraySize(items); + for (int i = 0; i < count; i++) + { + // + has = AddIfNotExists( + items[i], + sources // + ); + } + + // + int after = ArraySize(sources); + + // + result = after > before; + + // + return result; +} + +/** + * Update to Time of Specifiex Collection ... + * + * @param items: XOBFVG instance Collection ... + * @param value: datetime ... + */ +template +void SpecifiedUpdateTo( + T *&items[], + datetime value = NULL // +) +{ + // + value = NormalizeTime(value); + + // + int count = ArraySize(items); + bool has = HasChild(items); + if (!has) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + items[i].To(value); + } +} + +// +template +int FilterZones( + // + T *&source[], + // + ENUM_X_DIRECTION forDir, + ENUM_TIMEFRAMES forPeriod = NULL, + datetime after = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false, + // + bool applySort = false, + // + bool ignoreInside = true + // +) +{ + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + has = HasDirection(forDir); + if (!has) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + count = ArraySize(source); + has = IsValidSize(count); + if (!has) + { + return result; + } + + // + T *tmpZones[]; + XOHCL passedBar; + bool isPassed = false; + for (int i = 0; i < count; i++) + { + // + T *iZone = source[i]; + + // + // Apply after Filter ... + isPassed = + !IsValid(after) + ? true + : iZone.From() >= after; + if (!isPassed) + { + // + ZeroMemory(iZone); + continue; + } + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + forDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + forDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + forDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + forDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + tmpZones // + ); + if (has) + { + // + ZeroMemory(iZone); + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + tmpZones // + ); + } + + // + Clean(source); + + // + has = HasChild(tmpZones); + if (!has) + { + // + Clean(tmpZones); + passedBar.Clean(); + return result; + } + + // + // Apply Sorting ... + if (applySort) + { + // + T *last = NULL; + bool hasLast = false; + while (HasChild(tmpZones)) + { + // + idx = GetYoungest(tmpZones); + hasLast = IsValidIndex(idx); + if (hasLast) + { + // + last = tmpZones[idx]; + ArrayRemove( + tmpZones, + idx, + 1 // + ); + + // + Add( + last, + source // + ); + } + + // + has = HasChild(tmpZones); + if (!has) + { + break; + } + + // + T *zone = NULL; + bool hasZone = false; + idx = GetYoungest(tmpZones); + hasZone = IsValidIndex(idx); + if (hasZone) + { + // + zone = tmpZones[idx]; + ArrayRemove( + tmpZones, + idx, + 1 // + ); + } + if (!hasZone) + { + // + ZeroMemory(zone); + continue; + } + + // + bool isAbove = IsAbove( + zone, + last, + ignoreInside // + ); + + // + bool isBelow = IsBelow( + zone, + last, + ignoreInside // + ); + + // + isPassed = + isBullish + ? isAbove + : isBelow; + if (!isPassed) + { + // + ZeroMemory(zone); + continue; + } + + // + Add( + zone, + source // + ); + } + } + else + { + // + Copy( + tmpZones, + source // + ); + } + + // + result = ArraySize(source); + + // + return result; +} + +// +// +// + +/** + * Detect Nearest Price Out of Specified Box ... + * + * @param box: XBoxZone instance Reference ... + * @param outSideBar: XOHCL instance Reference which Represents Out Side Bar if Exists ... + * @param forPeriod: ENUM_TIMEFRAMES member which provides time frame of Out Bar, if not Provides used box Period as Default ... + * @param forDir: ENUM_X_DIRECTION member which Specified outSide Direction, use Box Dir as Default ... + * @param forceBodyIn: bool value which Specifyed Body Breakes or not, Default is false ... + * @param barIndex: integer value which Specified Start Bar Index, Default is 0 ... + * + * @return ( bool ) + */ +bool DetectBoxNearestPriceOut( + XBoxZone &box, + XOHCL &outSideBar, + ENUM_TIMEFRAMES forPeriod = NULL, + ENUM_X_DIRECTION forDir = X_DIRECTION_NONE, + bool forceBodyIn = false, + int barIndex = 0 // +) +{ + // + bool result = false; + + // + outSideBar.Clean(); + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + result = box.IsValid(); + if (!result) + { + return result; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = box.period; + } + + // + if (!HasDirection(forDir)) + { + forDir = box.dir; + } + + // + bool isBullish = IsBullish(forDir); + + // + int fromIndex = iBarShift( + box.symbol, + box.period, + box.from // + ); + result = IsValidIndex(fromIndex); + if (!result) + { + return result; + } + + // + XOHCL iBar; + XOHCL iPBar; + bool has = false; + for (int i = barIndex; i < fromIndex; i++) + { + // + has = iBar.Init( + box.symbol, + forPeriod, + i // + ); + if (!has) + { + continue; + } + + // + has = iBar.GetPreviousBar(iPBar); + if (!has) + { + continue; + } + + // + bool isInsideFromLower = + iBar.high < box.lower && + iPBar.high > box.lower; + + // + bool isInsideFromUpper = + iBar.low > box.upper && + iPBar.low < box.upper; + + // + bool isInsideBodyFromLower = + iPBar.GetUp() > box.lower; + + // + bool isInsideBodyFromUpper = + iPBar.GetDown() < box.upper; + + // + result = + isBullish + ? (!forceBodyIn + ? isInsideFromLower + : isInsideFromLower && + isInsideBodyFromLower) + : (!forceBodyIn + ? isInsideFromUpper + : isInsideFromUpper && + isInsideBodyFromUpper); + if (result) + { + // + outSideBar = iBar; + break; + } + } + + // + iBar.Clean(); + iPBar.Clean(); + + // + return result; +} + +// \ No newline at end of file diff --git a/BKPS/14031218/Libraries/x-saherelm.x-poi.lib.ex5 b/BKPS/14031218/Libraries/x-saherelm.x-poi.lib.ex5 new file mode 100644 index 0000000..d995ce7 Binary files /dev/null and b/BKPS/14031218/Libraries/x-saherelm.x-poi.lib.ex5 differ diff --git a/BKPS/14031218/Libraries/x-saherelm.x-poi.lib.mq5 b/BKPS/14031218/Libraries/x-saherelm.x-poi.lib.mq5 new file mode 100644 index 0000000..def6c2c --- /dev/null +++ b/BKPS/14031218/Libraries/x-saherelm.x-poi.lib.mq5 @@ -0,0 +1,5365 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Seriallize Library +// --------------------------------------- +// Name: XPOILib +// Description: All models related to POIs ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright `023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.base.class.mq5" +#include + +// +// Definitions ... + +// +// All Available POI(s) ... +enum ENUM_XPOIS +{ + // + X_POI_NONE, + // + X_POI_TICKS_ZONES, // Ticks Zone ... + // + // Trading Day ... + X_POI_TRADING_DAY, // Trading Day ... + // + // Market Session ... + X_POI_MARKET_SESSION, // Market Session ... + // + // Momentum Bar ... + X_POI_MOMENTUM_BAR, // Momentum Bar ... + // + // Rejection Bar ... + X_POI_REJECTION_BAR, // Rejection Bar ... + // + // Swings ... + X_POI_SWING_HIGH, // Simple Swing High ... + X_POI_SWING_LOW, // Simple Swing Low ... + // + // Support nad Resistance ... + X_POI_SUPPORT_ZONE, // Support Zone ... + X_POI_RESISTANCE_ZONE, // Resistance Zone ... + // + // Supply and Demand Zones ... + X_POI_SUPPLY_ZONE, // Supply Zone ... + X_POI_DEMAND_ZONE, // Demand Zone ... + // + // Order Blocks ... + X_POI_BULLISH_ORDERBLOCK, // Bullish Order Block ... + X_POI_BEARISH_ORDERBLOCK, // Bearish Order Block ... + // + // Fair Value Gaps ... + X_POI_BULLISH_FVG, // Bullish Order Block ... + X_POI_BEARISH_FVG, // Bearish Order Block ... + // + X_BULLISH_CONSOLIDATION_ZONE, + X_BEARISH_CONSOLIDATION_ZONE, +}; + +// +// Event Types ... +enum ENUM_XPOI_EVENTS +{ + // + X_POI_EVENT_NONE, + // + // Trading Days ... + X_TRADE_DAY_FIRST_BAR, // Trading Day First Bar ... + X_TRADE_DAY_LAST_BAR, // Trading Day Last Bar ... + // + // Session ... + X_SESSION_FIRST_BAR, // Session First Bar ... + X_SESSION_LAST_BAR, // Session Last Bar ... + // + // Momentum Bar ... + X_BULLISH_MOMENTUM_BAR_DETECTED, + X_BEARISH_MOMENTUM_BAR_DETECTED, + // + // Rejection Bar ... + X_BULLISH_REJECTION_BAR_DETECTED, + X_BEARISH_REJECTION_BAR_DETECTED, + // + // Swings ... + X_SWING_HIGH_DETECTED, + X_SWING_LOW_DETECTED, + // + // Support nad Resistance ... + X_SUPPORT_ZONE_DETECTED, // Support Zone ... + X_RESISTANCE_ZONE_DETECTED, // Resistance Zone ... + // + // Supply nad Demand ... + X_SUPPLY_ZONE_DETECTED, // Supply Zone ... + X_DEMAND_ZONE_DETECTED, // Demand Zone ... + // + // Order Blocks ... + X_BULLISH_ORDERBLOCK_DETECTED, // Bullish Order Block ... + X_BEARISH_ORDERBLOCK_DETECTED, // Bearish Order Block ... + // + // Fair Value Gaps ... + X_BULLISH_FVG_DETECTED, // Bullish Fair Value GapÙ‘ ... + X_BEARISH_FVG_DETECTED, // Bearish Fair Value GapÙ‘ ... + X_BULLISH_CONSOLIDATION_ZONE_DETECTED, + X_BEARISH_CONSOLIDATION_ZONE_DETECTED, +}; + +// +enum ENUM_XZONE_STATE +{ + XZONE_STATE_NONE, + XZONE_STATE_PASSED, + XZONE_STATE_FAILED, + XZONE_STATE_IGNORED, +}; + +// +// Forext Sessions ... +enum ENUM_XSESSION +{ + X_TOKYO, + X_SYDNEY, + X_LONDON, + X_NEW_YORK, + X_FRANKFORT, +}; + +/** + * Converts ENUM_XPOI value to String Representation ... + * + * @param value: ENUM_XPOI member ... + * + * @return ( string ) + */ +string ToString(ENUM_XPOIS value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_POI_TRADING_DAY: + result = "XTDAY"; + break; + + // + case X_POI_MARKET_SESSION: + result = "XMSESS"; + break; + + // + case X_POI_MOMENTUM_BAR: + result = "XMNTMB"; + break; + + // + case X_POI_REJECTION_BAR: + result = "XRJCTB"; + break; + + // + case X_POI_SWING_HIGH: + result = "XSPH"; + break; + + // + case X_POI_SWING_LOW: + result = "XSPL"; + break; + + // + case X_POI_SUPPORT_ZONE: + result = "XSUP"; + break; + + // + case X_POI_RESISTANCE_ZONE: + result = "XRES"; + break; + + // + case X_POI_SUPPLY_ZONE: + result = "XSUPPLY"; + break; + + // + case X_POI_DEMAND_ZONE: + result = "XDEMAND"; + break; + + // + case X_POI_BULLISH_ORDERBLOCK: + result = "XBULLOB"; + break; + + // + case X_POI_BEARISH_ORDERBLOCK: + result = "XBEAROB"; + break; + + // + case X_POI_BULLISH_FVG: + result = "XBULLFVG"; + break; + + // + case X_POI_BEARISH_FVG: + result = "XBEARFVG"; + break; + + // + case X_POI_TICKS_ZONES: + result = "XTKSZ"; + break; + + // + case X_BULLISH_CONSOLIDATION_ZONE: + result = "XBULLCZ"; + break; + + // + case X_BEARISH_CONSOLIDATION_ZONE: + result = "XBEARCZ"; + break; + } + + // + return result; +} + +/** + * Converts ENUM_XSESSION value to String Representation ... + * + * @param value: ENUM_XSESSION member ... + * + * @return ( string ) + */ +string ToString(ENUM_XSESSION value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_SYDNEY: + result = "Sydney"; + break; + + // + case X_TOKYO: + result = "Tokyo"; + break; + + // + case X_FRANKFORT: + result = "FrankGurt"; + break; + + // + case X_LONDON: + result = "London"; + break; + + // + case X_NEW_YORK: + result = "NewYork"; + break; + } + + // + return result; +} + +/** + * Generate General Event Messages ... + * + * @param value: ENUM_XPOI_EVENTS member ... + * + * @return ( string ) + */ +string ToString(ENUM_XPOI_EVENTS value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_TRADE_DAY_FIRST_BAR: + result = "First Bar of Day"; + break; + + // + case X_TRADE_DAY_LAST_BAR: + result = "Last Bar of Day"; + break; + + // + case X_SESSION_FIRST_BAR: + result = "First Bar of Session"; + break; + + // + case X_SESSION_LAST_BAR: + result = "Last Bar of Session"; + break; + + // + case X_BULLISH_MOMENTUM_BAR_DETECTED: + result = "Bullish Momentum Bar Detected"; + break; + + // + case X_BEARISH_MOMENTUM_BAR_DETECTED: + result = "Bearish Momentum Bar Detected"; + break; + + // + case X_BULLISH_REJECTION_BAR_DETECTED: + result = "Bullish Rejection Bar Detected"; + break; + + // + case X_BEARISH_REJECTION_BAR_DETECTED: + result = "Bearish Rejection Bar Detected"; + break; + + // + case X_SWING_HIGH_DETECTED: + result = "Swing High Detected"; + break; + + // + case X_SWING_LOW_DETECTED: + result = "Swing Low Detected"; + break; + + // + case X_SUPPORT_ZONE_DETECTED: + result = "Support Zone Detected"; + break; + + // + case X_RESISTANCE_ZONE_DETECTED: + result = "Resistance Zone Detected"; + break; + + // + case X_SUPPLY_ZONE_DETECTED: + result = "Supply Zone Detected"; + break; + + // + case X_DEMAND_ZONE_DETECTED: + result = "Demand Zone Detected"; + break; + + // + case X_BULLISH_ORDERBLOCK_DETECTED: + result = "Bullish Order Block Detected"; + break; + + // + case X_BEARISH_ORDERBLOCK_DETECTED: + result = "Bearish Orer Block Detected"; + break; + + // + case X_BULLISH_FVG_DETECTED: + result = "Bullish FVG Detected"; + break; + + // + case X_BEARISH_FVG_DETECTED: + result = "Bearish FVg Detected"; + break; + } + + // + return result; +} + +// +// Implementation ... + +// +// Base POI Model Class ... +class XCBasePOI : public XCBase +{ + // + public: + // + + // + // Constructor ... + void XCBasePOI() + { + // + Clean(); + + // + mSep = "_"; + mLineSep = "\n"; + } + + // + // Deconstructor ... + void ~XCBasePOI() + { + Clean(); + } + + // + // Virtual ... + + /** + * Cleanup ... + */ + virtual void Clean() + { + mType = X_POI_NONE; + } + + /** + * Validate ... + * + * @return ( virtual bool ) + */ + virtual bool IsValid() + { + return false; + } + + /** + * Retrieve POI Type ... + * + * @return ( virtual ENUM_XPOIS member ) + */ + virtual ENUM_XPOIS Type() + { + return mType; + } + + /** + * Retrieve POI Type ... + * + * @return ( virtual string ) + */ + virtual string TypeAsString() + { + return ToString(mType); + } + + /** + * Retrieve POI Tag ... + * + * @return ( virtual string ) + */ + virtual string GetTag() + { + return NULL; + } + + /** + * Retrieve POI Tooltip ... + * + * @return ( virtual string ) + */ + virtual string GetTooltip() + { + return NULL; + } + + // + protected: + // + // Props ... + string mSep; // Separator ... + string mLineSep; // Line Separator ... + ENUM_XPOIS mType; // Type ... + + // + private: + // +}; + +// +typedef void (*TOnPOIEvent)(ENUM_XPOI_EVENTS event, + XCBasePOI *param // +); + +// +// Zone POI Class ... +class XCZone : public XCBasePOI +{ + // + public: + // + + // + // Constructor ... + void XCZone() + { + } + + // + // Deconstructor ... + void ~XCZone() + { + } + + // + // Tools ... + + // + // Getter(s) / Setter(s) ... + + /** + * Get Zone Upper Boundary ... + * + * @return ( double ) + */ + double Upper() + { + return mUpper; + } + + /** + * Set Zone Upper Boundary ... + */ + void Upper(double value) + { + mUpper = value; + } + + /** + * Get Zone Lower Boundary ... + * + * @return ( double ) + */ + double Lower() + { + return mLower; + } + + /** + * Set Zone Lower Boundary ... + */ + void Lower(double value) + { + mLower = value; + } + + /** + * Retrieve Zone Range ... + * + * @return ( double ) + */ + double Range() + { + // + double result = 0; + + // + double upper = Upper(); + double lower = Lower(); + + // + if (upper > 0 && lower > 0 && upper > lower) + { + result = upper - lower; + } + + // + return result; + } + + double RangePercent() + { + // + double result = 0; + + // + double range = Range(); + if (range > 0) + { + result = range / 100; + } + + // + return result; + } + + // + // Virtuals ... + + /** + * Get Zone Start Date ... + * + * @return ( virtual datetime ) + */ + virtual datetime From() + { + return NULL; + } + + /** + * Get Zone End Date ... + * + * @return ( virtual datetime ) + */ + virtual datetime To() + { + return NULL; + } + + // + // Getter(s) / Setter(s) ... + + // + // Overrides ... + + // + // Validators ... + + /** + * Validate Upper and Lower of Zone ... + * + * @return ( bool ) + */ + bool IsValidBoundary() + { + // + bool result = false; + + // + result = + // + mUpper > 0 && + mLower > 0 && + mUpper >= mLower + // + ; + + // + return result; + } + + /** + * Check From Date of Zone is Valid ... + * + * @return ( bool ) + */ + bool IsValidFrom() + { + // + bool result = false; + + // + datetime from = From(); + result = IsSpecifiedValid(from); + + // + return result; + } + + // + protected: + // + // Props ... + double mUpper; // Zone Upper ... + double mLower; // Zone Lower ... + + // + private: + // + // Props ... + + // +}; + +// +// From To Zone ... +class XCFromToZone : public XCBasePOI +{ + // + public: + // + + // + // Constructor ... + void XCFromToZone() + { + } + + // + // Deconstructor ... + void ~XCFromToZone() + { + } + + // + // Tools ... + + bool InitFromTo( + ENUM_XPOIS type, + string title, + datetime from // + ) + { + // + bool result = false; + + // + result = type != X_POI_NONE && + IsSpecifiedValid(from) && + IsSpecifiedValid(title); + + // + mType = type; + mFrom = from; + mTitle = title; + mTo = TimeCurrent(); + + // + result = IsValid(); + + // + return result; + } + + bool InitFromTo( + ENUM_XPOIS type, + string title, + datetime from, + datetime to // + ) + { + // + bool result = false; + + // + result = IsValid(); + + // + result = InitFromTo( + type, + title, + from // + ); + if (!result) + { + return result; + } + + // + to = NormalizeTime(to); + mTo = to; + + // + result = IsValid(); + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Get Zone Start Time ... + * + * @return ( datetime ) + */ + datetime From() + { + return mFrom; + } + + /** + * Set Zone Start Time ... + * + * @param value: Datetime + */ + void From(datetime value) + { + // + value = NormalizeTime(value); + + // + mFrom = value; + } + + /** + * Get Zone End Time ... + * + * @return ( datetime ) + */ + datetime To() + { + return mTo; + } + + /** + * Set Zone End Time ... + * + * @param value: Datetime + */ + void To(datetime value) + { + // + value = NormalizeTime(value); + + // + mTo = value; + } + + /** + * Get Title ... + * + * @return ( string ) + */ + string Title() + { + return mTitle; + } + + /** + * Set Title ... + * + * @param value: String ... + */ + // void Title(string value) + // { + // mTitle = value; + // } + + // + // Overrides ... + + void Clean() override + { + // + mTo = NULL; + mFrom = NULL; + mType = X_POI_NONE; + } + + bool IsValid() override + { + // + bool result = false; + + // + result = + // + mType != X_POI_NONE && + IsSpecifiedValid(mTo) && + IsSpecifiedValid(mFrom) && + IsSpecifiedValid(mTitle) + // + ; + + // + return result; + } + + string GetTag() override + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + string hash = TypeAsString() + mSep + ToString(From()) + mSep + Title(); + hash = ToMD5(hash); + + // + result = TypeAsString() + "[" + Title() + "]" + mSep + hash; + + // + return result; + } + + // + protected: + // + + // + private: + // + // Props ... + datetime mFrom; // Start Date + datetime mTo; // End Date + string mTitle; // Zone Title + + // +}; + +// +// Bar Zone ... +class XCBarZone : public XCZone +{ + // + public: + // + + // + // Constructor ... + void XCBarZone() + { + } + + // + // Deconstructor ... + void ~XCBarZone() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param bar: XOHCL instance ... + * @param type: ENUM_XPOIS member ... + * @param upperPrice: ENUM_X_PRICE member ... + * @param lowerPrice: ENUM_X_PRICE member ... + * + * @return ( bool ) + */ + bool InitBarZone( + XOHCL &bar, + ENUM_XPOIS type, + ENUM_X_PRICE upperPrice, + ENUM_X_PRICE lowerPrice // + ) + { + // + bool result = false; + + // + result = bar.IsValid() && + type != X_POI_NONE && + upperPrice != lowerPrice; + if (!result) + { + return result; + } + + // + mBar = bar; + mType = type; + mUpperPrice = upperPrice; + mLowerPrice = lowerPrice; + mUpper = bar.GetPrice(upperPrice); + mLower = bar.GetPrice(lowerPrice); + + // + result = IsValidBarZone(); + if (result) + { + // + From(bar.time); + To(TimeCurrent()); + } + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Fill Bar as XOHCL struct ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool FillBar( + XOHCL &bar // + ) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + bar = mBar; + result = mBar.IsValid(); + + // + return result; + } + + /** + * Set From Date ... + * + * @param value: DateTime ... + */ + void From(datetime value) + { + // + if (!IsValidBarZone()) + { + return; + } + + // + value = NormalizeTime(value); + + // + mFrom = value; + } + + /** + * Set To Date ... + * + * @param value: DateTime ... + */ + void To(datetime value) + { + // + if (!IsValidBarZone()) + { + return; + } + + // + value = NormalizeTime(value); + + // + mTo = value; + } + + /** + * Retrieve Bar Time ... + * + * @return ( datetime ) + */ + datetime BarTime() + { + return mBar.time; + } + + /** + * Get Symbol ... + * + * @return ( string ) + */ + string GetSymbol() + { + // + string result = NULL; + + // + if (!mBar.IsValid()) + { + return result; + } + + // + return mBar.symbol; + + // + return result; + } + + /** + * Get Period ... + * + * @return ( int ) + */ + ENUM_TIMEFRAMES GetPeriod() + { + // + ENUM_TIMEFRAMES result = NULL; + + // + if (!mBar.IsValid()) + { + return result; + } + + // + return mBar.period; + + // + return result; + } + + /** + * Check Zone Started or not ... + * First Exit in Direction of Zone after From ... + * + * @param forDir: exit direction ... + * @param startedBar: specified Start Bar ... + * @param isBodyOut: specified Start Bar Close is Out of Zone or not ... + * @param forPeriod: specified Period ... + * + * @return ( bool ) + */ + bool IsStarted( + ENUM_X_DIRECTION forDir, + XOHCL &startedBar, + bool &isBodyOut, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + isBodyOut = false; + startedBar.Clean(); + + // + result = HasDirection(forDir) && + IsValidBarZone(); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + // Detect From Bar Index ... + int fromIndex = iBarShift( + GetSymbol(), + forPeriod, + From() // + ); + + // + for (int i = fromIndex; i >= 0; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + result = isInited; + if (!result) + { + // + iBar.Clean(); + continue; + } + + // + bool isBreakedFromUpper = + // + iBar.low > Upper() || + (iBar.low <= Upper() && + iBar.high > Upper() && + iBar.close > Upper()) + // + ; + + // + bool isBreakedFromLower = + // + iBar.low < Lower() || + (iBar.high >= Lower() && + iBar.low < Lower() && + iBar.close < Lower()) + // + ; + + // + bool isBreaked = + isBreakedFromUpper || + isBreakedFromLower; + if (isBreaked) + { + // + result = isBreaked && + isBullish + ? isBreakedFromUpper + : isBreakedFromLower; + if (result) + { + // + startedBar = iBar; + iBar.Clean(); + break; + } + } + + // + iBar.Clean(); + } + + // + result = startedBar.IsValid(); + if (result) + { + // + isBodyOut = + isBullish + ? startedBar.IsBullish() && + startedBar.GetUp() > Upper() + : startedBar.IsBearish() && + startedBar.GetDown() < Lower(); + } + + // + return result; + } + + /** + * Check Zone Activated or not ... + * First Enter in Opposit Direction of Zone after Start ... + * + * @param forDir: exit direction ... + * @param activatedBar: specified Activation Bar ... + * @param isBodyIn: specified Activation Bar Close is Inside of Zone or not ... + * @param forPeriod: specified Period ... + * + * @return ( bool ) + */ + bool IsActivated( + ENUM_X_DIRECTION forDir, + XOHCL &activatedBar, + bool &isBodyIn, + bool forceBodyOutStarted = true, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + isBodyIn = false; + activatedBar.Clean(); + + // + result = HasDirection(forDir) && + IsValidBarZone(); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + XOHCL startedBar; + bool isBodyOut = false; + bool isStarted = IsStarted( + forDir, + startedBar, + isBodyOut, + forPeriod // + ); + result = + !forceBodyOutStarted + ? isStarted + : isStarted && + isBodyOut; + if (!result) + { + // + startedBar.Clean(); + return result; + } + + // + int fromIndex = startedBar.Index() - 1; + + // + for (int i = fromIndex; i >= 0; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + result = isInited; + if (!result) + { + // + iBar.Clean(); + continue; + } + + // + bool isInsideFromUpper = + // + iBar.high < Upper() || + (iBar.high > Upper() && + iBar.low <= Upper() && + iBar.close <= Upper()) + // + ; + + // + bool isInsideFromLower = + // + iBar.low > Lower() || + (iBar.low < Lower() && + iBar.high >= Lower() && + iBar.close >= Lower()) + // + ; + + // + bool isInside = + isInsideFromUpper || + isInsideFromLower; + if (isInside) + { + // + result = isInside && + isBullish + ? isInsideFromUpper + : isInsideFromLower; + if (result) + { + // + activatedBar = iBar; + iBar.Clean(); + startedBar.Clean(); + break; + } + } + + // + iBar.Clean(); + startedBar.Clean(); + } + + // + result = activatedBar.IsValid(); + if (result) + { + // + isBodyIn = + isBullish + ? activatedBar.IsBearish() && + activatedBar.GetDown() < Upper() + : activatedBar.IsBullish() && + activatedBar.GetUp() > Lower(); + } + + // + return result; + } + + /** + * Check Zone Breaked or not ... + * + * @param forDir: exit direction ... + * @param breakedBar: specified Breaked Bar ... + * @param isBodyOut: specified Breaked Bar Close is Out of Zone or not ... + * @param ignoreStart: Ignore Zone Start (Calculate from From()) ... + * @param startedBodyOut: Started Bar Body Close State, if use Start for Calculation ... + * @param forPeriod: specified Period ... + * + * @return ( bool ) + */ + bool IsBreaked( + ENUM_X_DIRECTION forDir, + XOHCL &breakedBar, + bool &isBodyOut, + bool ignoreStart = false, + bool startedBodyOut = false, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + isBodyOut = false; + breakedBar.Clean(); + + // + result = HasDirection(forDir) && + IsValidBarZone(); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + int fromIndex = -1; + if (!ignoreStart) + { + // + XOHCL startedBar; + bool isBodyOut = false; + bool isStarted = IsStarted( + forDir, + startedBar, + isBodyOut, + forPeriod // + ); + + // + bool isStartPassed = + !startedBodyOut + ? isStarted + : isStarted && + isBodyOut; + if (isStartPassed) + { + fromIndex = startedBar.Index() - 1; + } + + // + startedBar.Clean(); + } + else + { + // + fromIndex = iBarShift( + GetSymbol(), + forPeriod, + From() // + ); + } + + // + result = IsValidIndex(fromIndex); + if (!result) + { + return result; + } + + // + for (int i = fromIndex; i >= 0; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + result = isInited; + if (!result) + { + // + iBar.Clean(); + continue; + } + + // + bool isBreakedFromUpper = + // + iBar.low > Upper() || + (iBar.low <= Upper() && + iBar.high > Upper() && + iBar.close > Upper()) + // + ; + + // + bool isBreakedFromLower = + // + iBar.low < Lower() || + (iBar.high >= Lower() && + iBar.low < Lower() && + iBar.close < Lower()) + // + ; + + // + bool isBreaked = + isBreakedFromUpper || + isBreakedFromLower; + if (isBreaked) + { + // + result = isBreaked && + (isBullish + ? isBreakedFromLower + : isBreakedFromUpper); + if (result) + { + // + breakedBar = iBar; + iBar.Clean(); + break; + } + } + + // + iBar.Clean(); + } + + // + result = breakedBar.IsValid(); + if (result) + { + // + isBodyOut = + isBullish + ? breakedBar.IsBearish() && + breakedBar.GetDown() < Lower() + : breakedBar.IsBullish() && + breakedBar.GetUp() > Upper(); + } + + // + return result; + } + + /** + * Check Zone Worked or not ... + * + * @param forDir: exit direction ... + * @param workedBar: specified Worked Bar ... + * @param isBodyOut: specified Worked Bar Close is Out of Zone or not ... + * @param ignoreActivation: Ignore Zone Activation (Calculate from From()) ... + * @param activationStartedOut: Specified Zone Start Bar State ... + * @param activationBodyIn: Specified Zone Activation Bar State ... + * @param forPeriod: specified Period ... + * + * @return ( bool ) + */ + bool IsWorked( + ENUM_X_DIRECTION forDir, + XOHCL &workedBar, + bool &isBodyOut, + bool ignoreActivation = false, + bool activationStartedOut = false, + bool activationBodyIn = false, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + isBodyOut = false; + workedBar.Clean(); + + // + result = HasDirection(forDir) && + IsValidBarZone(); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + int fromIndex = -1; + if (!ignoreActivation) + { + // + XOHCL activatedBar; + bool isBodyIn = false; + bool isActivated = IsActivated( + forDir, + activatedBar, + isBodyIn, + activationStartedOut, + forPeriod // + ); + + // + bool isActivationPassed = + !activationBodyIn + ? isActivated + : isActivated && + isBodyIn; + if (isActivationPassed) + { + fromIndex = activatedBar.Index() - 1; + } + + // + activatedBar.Clean(); + } + else + { + // + fromIndex = iBarShift( + GetSymbol(), + forPeriod, + From() // + ); + } + + // + result = IsValidIndex(fromIndex); + if (!result) + { + return result; + } + + // + for (int i = fromIndex; i >= 0; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + result = isInited; + if (!result) + { + // + iBar.Clean(); + continue; + } + + // + bool isBreakedFromUpper = + // + iBar.low > Upper() || + (iBar.low <= Upper() && + iBar.high > Upper() && + iBar.close > Upper()) + // + ; + + // + bool isBreakedFromLower = + // + iBar.low < Lower() || + (iBar.high >= Lower() && + iBar.low < Lower() && + iBar.close < Lower()) + // + ; + + // + bool isBreaked = + isBreakedFromUpper || + isBreakedFromLower; + if (isBreaked) + { + // + result = isBreaked && + isBullish + ? isBreakedFromUpper + : isBreakedFromLower; + if (result) + { + // + workedBar = iBar; + iBar.Clean(); + break; + } + } + + // + iBar.Clean(); + } + + // + result = workedBar.IsValid(); + if (result) + { + // + isBodyOut = + isBullish + ? workedBar.IsBullish() && + workedBar.GetUp() > Upper() + : workedBar.IsBearish() && + workedBar.GetDown() < Lower(); + } + + // + return result; + } + + /** + * Check to Find Nearest Bar which Breakes Upper ... + * + * @param bar: XOHCL instance Reference, Breaker Bar ... + * @param forPeriod: ENUM_TIMEFRAMES member, Breaker Bar Detection Period, default is Zone Period ... + * + * @return ( bool ) + */ + bool FindNearestInsideBarFromUpper( + XOHCL &bar, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + bar.Clean(); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int from = 1; + int to = iBarShift( + GetSymbol(), + forPeriod, + From() // + ); + + // + for (int i = from; i < to; i++) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + if (!isInited) + { + break; + } + + // + bool isInside = iBar.low < Upper(); + if (isInside) + { + // + bar = iBar; + break; + } + } + + // + result = bar.IsValid(); + + // + return result; + } + + /** + * Check to Find Nearest Bar which Breakes Lower ... + * + * @param bar: XOHCL instance Reference, Breaker Bar ... + * @param forPeriod: ENUM_TIMEFRAMES member, Breaker Bar Detection Period, default is Zone Period ... + * + * @return ( bool ) + */ + bool FindNearestInsideBarFromLower( + XOHCL &bar, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + bar.Clean(); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int from = 1; + int to = iBarShift( + GetSymbol(), + forPeriod, + From() // + ); + + // + for (int i = from; i < to; i++) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + if (!isInited) + { + break; + } + + // + bool isInside = iBar.high > Lower(); + if (isInside) + { + // + bar = iBar; + break; + } + } + + // + result = bar.IsValid(); + + // + return result; + } + + // + // Overrides ... + + void Clean() override + { + // + mBar.Clean(); + mUpper = 0; + mLower = 0; + mType = X_POI_NONE; + } + + datetime From() override + { + return mFrom; + } + + datetime To() override + { + return mTo; + } + + string GetTag() override + { + // + string result = NULL; + + // + if (!IsValidBarZone()) + { + return result; + } + + // + string hash = ToMD5(mBar.GetTag()); + + // + result = + // + TypeAsString() + mSep + + ToString(mBar.period) + mSep + + hash + // + ; + + // + return result; + } + + string GetTooltip() override + { + // + string result = NULL; + + // + if (!IsValidBarZone()) + { + return result; + } + + // + return result; + } + + // + protected: + // + // Props ... + XOHCL mBar; // Bar ... + ENUM_X_PRICE mUpperPrice; // Upper Price Selection + ENUM_X_PRICE mLowerPrice; // Lower Price Selection + + /** + * Check Bar Zone Validation ... + * + * @return ( bool ) + */ + bool IsValidBarZone() + { + // + bool result = false; + + // + result = mBar.IsValid() && + mType != X_POI_NONE && + IsValidBoundary(); + + // + return result; + } + + // + private: + // + // Props ... + datetime mFrom; + datetime mTo; + + // +}; +class XCTwoBarZone : public XCZone +{ + // + public: + // + + // + // Constructor ... + void XCTwoBarZone() + { + } + + // + // Deconstructor ... + void ~XCTwoBarZone() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param bar: XOHCL instance ... + * @param type: ENUM_XPOIS member ... + * @param upperPrice: ENUM_X_PRICE member ... + * @param lowerPrice: ENUM_X_PRICE member ... + * + * @return ( bool ) + */ + bool InitTwoBarZone( + XOHCL &startBar, + XOHCL &endBar, + ENUM_XPOIS type, + ENUM_X_PRICE startPrice, + ENUM_X_PRICE endPrice // + ) + { + // + bool result = false; + + // + result = startBar.IsValid() && + endBar.IsValid() && + startBar.symbol == endBar.symbol && + startBar.period == endBar.period && + startBar.time < endBar.time && + type != X_POI_NONE; + if (!result) + { + return result; + } + + // + mType = type; + mEndBar = endBar; + mStartBar = startBar; + + // + int startIndex = startBar.Index(); + int endIndex = endBar.Index(); + + // + double mStartPrice = startBar.GetPrice(startPrice); + double mEndPrice = endBar.GetPrice(endPrice); + bool isStartOverEnd = mStartPrice > mEndPrice; + + // + if (isStartOverEnd) + { + // + mUpperPrice = startPrice; + mLowerPrice = endPrice; + } + else + { + // + mUpperPrice = endPrice; + mLowerPrice = startPrice; + } + + // + mUpper = MathMax(mStartPrice, mEndPrice); + mLower = MathMin(mStartPrice, mEndPrice); + + // + result = IsValidTwoBarZone(); + if (result) + { + // + From(startBar.time); + To(endBar.time); + } + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Set From Date ... + * + * @param value: DateTime ... + */ + void From(datetime value) + { + // + if (!IsValidTwoBarZone()) + { + return; + } + + // + value = NormalizeTime(value); + + // + mFrom = value; + } + + /** + * Set To Date ... + * + * @param value: DateTime ... + */ + void To(datetime value) + { + // + if (!IsValidTwoBarZone()) + { + return; + } + + // + value = NormalizeTime(value); + + // + mTo = value; + } + + /** + * Fill Start Bar ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool FillStartBar(XOHCL &bar) + { + // + bool result = false; + + // + result = IsValidTwoBarZone(); + if (!result) + { + return result; + } + + // + bar = mStartBar; + + // + return result; + } + + /** + * Fill End Bar ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool FillEndBar(XOHCL &bar) + { + // + bool result = false; + + // + result = IsValidTwoBarZone(); + if (!result) + { + return result; + } + + // + bar = mEndBar; + + // + return result; + } + + /** + * Get Symbol ... + * + * @return ( string ) + */ + string GetSymbol() + { + // + string result = NULL; + + // + if (!mStartBar.IsValid()) + { + return result; + } + + // + return mStartBar.symbol; + + // + return result; + } + + /** + * Get Period ... + * + * @return ( int ) + */ + ENUM_TIMEFRAMES GetPeriod() + { + // + ENUM_TIMEFRAMES result = NULL; + + // + if (!mStartBar.IsValid()) + { + return result; + } + + // + return mStartBar.period; + + // + return result; + } + + /** + * Check Zone Started or not ... + * First Exit in Direction of Zone after From ... + * + * @param forDir: exit direction ... + * @param startedBar: specified Start Bar ... + * @param isBodyOut: specified Start Bar Close is Out of Zone or not ... + * @param forPeriod: specified Period ... + * + * @return ( bool ) + */ + bool IsStarted( + ENUM_X_DIRECTION forDir, + XOHCL &startedBar, + bool &isBodyOut, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + isBodyOut = false; + startedBar.Clean(); + + // + result = HasDirection(forDir) && + IsValidTwoBarZone(); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + // Detect From Bar Index ... + int fromIndex = iBarShift( + GetSymbol(), + forPeriod, + From() // + ); + + // + for (int i = fromIndex; i >= 0; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + result = isInited; + if (!result) + { + // + iBar.Clean(); + continue; + } + + // + bool isBreakedFromUpper = + // + iBar.low > Upper() || + (iBar.low <= Upper() && + iBar.high > Upper() && + iBar.close > Upper()) + // + ; + + // + bool isBreakedFromLower = + // + iBar.low < Lower() || + (iBar.high >= Lower() && + iBar.low < Lower() && + iBar.close < Lower()) + // + ; + + // + bool isBreaked = + isBreakedFromUpper || + isBreakedFromLower; + if (isBreaked) + { + // + result = isBreaked && + isBullish + ? isBreakedFromUpper + : isBreakedFromLower; + if (result) + { + // + startedBar = iBar; + iBar.Clean(); + break; + } + } + + // + iBar.Clean(); + } + + // + result = startedBar.IsValid(); + if (result) + { + // + isBodyOut = + isBullish + ? startedBar.IsBullish() && + startedBar.GetUp() > Upper() + : startedBar.IsBearish() && + startedBar.GetDown() < Lower(); + } + + // + return result; + } + + /** + * Check Zone Activated or not ... + * First Enter in Opposit Direction of Zone after Start ... + * + * @param forDir: exit direction ... + * @param activatedBar: specified Activation Bar ... + * @param isBodyIn: specified Activation Bar Close is Inside of Zone or not ... + * @param forPeriod: specified Period ... + * + * @return ( bool ) + */ + bool IsActivated( + ENUM_X_DIRECTION forDir, + XOHCL &activatedBar, + bool &isBodyIn, + bool forceBodyOutStarted = true, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + isBodyIn = false; + activatedBar.Clean(); + + // + result = HasDirection(forDir) && + IsValidTwoBarZone(); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + XOHCL startedBar; + bool isBodyOut = false; + bool isStarted = IsStarted( + forDir, + startedBar, + isBodyOut, + forPeriod // + ); + result = + !forceBodyOutStarted + ? isStarted + : isStarted && + isBodyOut; + if (!result) + { + // + startedBar.Clean(); + return result; + } + + // + int fromIndex = startedBar.Index() - 1; + + // + for (int i = fromIndex; i >= 0; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + result = isInited; + if (!result) + { + // + iBar.Clean(); + continue; + } + + // + bool isInsideFromUpper = + // + iBar.high < Upper() || + (iBar.high > Upper() && + iBar.low <= Upper() && + iBar.close <= Upper()) + // + ; + + // + bool isInsideFromLower = + // + iBar.low > Lower() || + (iBar.low < Lower() && + iBar.high >= Lower() && + iBar.close >= Lower()) + // + ; + + // + bool isInside = + isInsideFromUpper || + isInsideFromLower; + if (isInside) + { + // + result = isInside && + isBullish + ? isInsideFromUpper + : isInsideFromLower; + if (result) + { + // + activatedBar = iBar; + iBar.Clean(); + startedBar.Clean(); + break; + } + } + + // + iBar.Clean(); + startedBar.Clean(); + } + + // + result = activatedBar.IsValid(); + if (result) + { + // + isBodyIn = + isBullish + ? activatedBar.IsBearish() && + activatedBar.GetDown() < Upper() + : activatedBar.IsBullish() && + activatedBar.GetUp() > Lower(); + } + + // + return result; + } + + /** + * Check Zone reaked or not ... + * + * @param forDir: exit direction ... + * @param breakedBar: specified Breaked Bar ... + * @param isBodyOut: specified Breaked Bar Close is Out of Zone or not ... + * @param ignoreStart: Ignore Zone Start (Calculate from From()) ... + * @param startedBodyOut: Started Bar Body Close State, if use Start for Calculation ... + * @param forPeriod: specified Period ... + * + * @return ( bool ) + */ + bool IsBreaked( + ENUM_X_DIRECTION forDir, + XOHCL &breakedBar, + bool &isBodyOut, + bool ignoreStart = false, + bool startedBodyOut = false, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + isBodyOut = false; + breakedBar.Clean(); + + // + result = HasDirection(forDir) && + IsValidTwoBarZone(); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + int fromIndex = -1; + if (!ignoreStart) + { + // + XOHCL startedBar; + bool isBodyOut = false; + bool isStarted = IsStarted( + forDir, + startedBar, + isBodyOut, + forPeriod // + ); + + // + bool isStartPassed = + !startedBodyOut + ? isStarted + : isStarted && + isBodyOut; + if (isStartPassed) + { + fromIndex = startedBar.Index() - 1; + } + + // + startedBar.Clean(); + } + else + { + // + fromIndex = iBarShift( + GetSymbol(), + forPeriod, + From() // + ); + } + + // + result = IsValidIndex(fromIndex); + if (!result) + { + return result; + } + + // + for (int i = fromIndex; i >= 0; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + result = isInited; + if (!result) + { + // + iBar.Clean(); + continue; + } + + // + bool isBreakedFromUpper = + // + iBar.low > Upper() || + (iBar.low <= Upper() && + iBar.high > Upper() && + iBar.close > Upper()) + // + ; + + // + bool isBreakedFromLower = + // + iBar.low < Lower() || + (iBar.high >= Lower() && + iBar.low < Lower() && + iBar.close < Lower()) + // + ; + + // + bool isBreaked = + isBreakedFromUpper || + isBreakedFromLower; + if (isBreaked) + { + // + result = isBreaked && + (isBullish + ? isBreakedFromLower + : isBreakedFromUpper); + if (result) + { + // + breakedBar = iBar; + iBar.Clean(); + break; + } + } + + // + iBar.Clean(); + } + + // + result = breakedBar.IsValid(); + if (result) + { + // + isBodyOut = + isBullish + ? breakedBar.IsBearish() && + breakedBar.GetDown() < Lower() + : breakedBar.IsBullish() && + breakedBar.GetUp() > Upper(); + } + + // + return result; + } + + /** + * Check Zone Worked or not ... + * + * @param forDir: exit direction ... + * @param workedBar: specified Worked Bar ... + * @param isBodyOut: specified Worked Bar Close is Out of Zone or not ... + * @param ignoreActivation: Ignore Zone Activation (Calculate from From()) ... + * @param activationStartedOut: Specified Zone Start Bar State ... + * @param activationBodyIn: Specified Zone Activation Bar State ... + * @param forPeriod: specified Period ... + * + * @return ( bool ) + */ + bool IsWorked( + ENUM_X_DIRECTION forDir, + XOHCL &workedBar, + bool &isBodyOut, + bool ignoreActivation = false, + bool activationStartedOut = false, + bool activationBodyIn = false, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + isBodyOut = false; + workedBar.Clean(); + + // + result = HasDirection(forDir) && + IsValidTwoBarZone(); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + int fromIndex = -1; + if (!ignoreActivation) + { + // + XOHCL activatedBar; + bool isBodyIn = false; + bool isActivated = IsActivated( + forDir, + activatedBar, + isBodyIn, + activationStartedOut, + forPeriod // + ); + + // + bool isActivationPassed = + !activationBodyIn + ? isActivated + : isActivated && + isBodyIn; + if (isActivationPassed) + { + fromIndex = activatedBar.Index() - 1; + } + + // + activatedBar.Clean(); + } + else + { + // + fromIndex = iBarShift( + GetSymbol(), + forPeriod, + From() // + ); + } + + // + result = IsValidIndex(fromIndex); + if (!result) + { + return result; + } + + // + for (int i = fromIndex; i >= 0; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + result = isInited; + if (!result) + { + // + iBar.Clean(); + continue; + } + + // + bool isBreakedFromUpper = + // + iBar.low > Upper() || + (iBar.low <= Upper() && + iBar.high > Upper() && + iBar.close > Upper()) + // + ; + + // + bool isBreakedFromLower = + // + iBar.low < Lower() || + (iBar.high >= Lower() && + iBar.low < Lower() && + iBar.close < Lower()) + // + ; + + // + bool isBreaked = + isBreakedFromUpper || + isBreakedFromLower; + if (isBreaked) + { + // + result = isBreaked && + isBullish + ? isBreakedFromUpper + : isBreakedFromLower; + if (result) + { + // + workedBar = iBar; + iBar.Clean(); + break; + } + } + + // + iBar.Clean(); + } + + // + result = workedBar.IsValid(); + if (result) + { + // + isBodyOut = + isBullish + ? workedBar.IsBullish() && + workedBar.GetUp() > Upper() + : workedBar.IsBearish() && + workedBar.GetDown() < Lower(); + } + + // + return result; + } + + /** + * Check to Find Nearest Bar which Breakes Upper ... + * + * @param bar: XOHCL instance Reference, Breaker Bar ... + * @param forPeriod: ENUM_TIMEFRAMES member, Breaker Bar Detection Period, default is Zone Period ... + * + * @return ( bool ) + */ + bool FindNearestInsideBarFromUpper( + XOHCL &bar, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + bar.Clean(); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int from = 1; + int to = iBarShift( + GetSymbol(), + forPeriod, + From() // + ); + + // + for (int i = from; i < to; i++) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + if (!isInited) + { + break; + } + + // + bool isInside = iBar.low < Upper(); + if (isInside) + { + // + bar = iBar; + break; + } + } + + // + result = bar.IsValid(); + + // + return result; + } + + /** + * Check to Find Nearest Bar which Breakes Lower ... + * + * @param bar: XOHCL instance Reference, Breaker Bar ... + * @param forPeriod: ENUM_TIMEFRAMES member, Breaker Bar Detection Period, default is Zone Period ... + * + * @return ( bool ) + */ + bool FindNearestInsideBarFromLower( + XOHCL &bar, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + bar.Clean(); + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = GetPeriod(); + } + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int from = 1; + int to = iBarShift( + GetSymbol(), + forPeriod, + From() // + ); + + // + for (int i = from; i < to; i++) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + GetSymbol(), + forPeriod, + i // + ); + if (!isInited) + { + break; + } + + // + bool isInside = iBar.high > Lower(); + if (isInside) + { + // + bar = iBar; + break; + } + } + + // + result = bar.IsValid(); + + // + return result; + } + + // + // Overrides ... + + void Clean() override + { + // + mStartBar.Clean(); + mEndBar.Clean(); + mUpper = 0; + mLower = 0; + mUseStartBarForUpper = false; + mType = X_POI_NONE; + } + + datetime From() override + { + return mFrom; + } + + datetime To() override + { + return mTo; + } + + string GetTag() override + { + // + string result = NULL; + + // + if (!IsValidTwoBarZone()) + { + return result; + } + + // + string hash = ToMD5(mStartBar.GetTag() + mSep + mEndBar.GetTag()); + + // + result = + // + TypeAsString() + mSep + + ToString(mStartBar.period) + mSep + + hash + // + ; + + // + return result; + } + + string GetTooltip() override + { + // + string result = NULL; + + // + if (!IsValidTwoBarZone()) + { + return result; + } + + // + return result; + } + + // + protected: + // + // Props ... + XOHCL mStartBar; // Start (Oldest) Bar ... + XOHCL mEndBar; // End (Newest) Bar ... + bool mUseStartBarForUpper; // Use Start Bar for Upper Calculation ... + ENUM_X_PRICE mUpperPrice; // Upper Price Selection + ENUM_X_PRICE mLowerPrice; // Lower Price Selection + + /** + * Check Two Bar Zone Validation ... + * + * @return ( bool ) + */ + bool IsValidTwoBarZone() + { + // + bool result = false; + + // + result = mStartBar.IsValid() && + mEndBar.IsValid() && + mStartBar.symbol == mEndBar.symbol && + mStartBar.period == mEndBar.period && + mStartBar.time < mEndBar.time && + mType != X_POI_NONE && + IsValidBoundary(); + + // + return result; + } + + // + private: + // + // Props ... + datetime mFrom; + datetime mTo; + + // +}; + +// +// Swing Class ... +class XCSwing : public XCBasePOI +{ + // + public: + // + + // + // Constructor ... + void XCSwing() + { + } + + // + // Deconstructor ... + void ~XCSwing() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param bar: XOHCL instance ... + * @param type: ENUM_XPOIS member ... + * + * @return ( bool ) + */ + bool Init( + XOHCL &bar, + ENUM_XPOIS type // + ) + { + // + bool result = false; + + // + result = bar.IsValid() && + (type == X_POI_SWING_HIGH || + type == X_POI_SWING_LOW); + if (!result) + { + return result; + } + + // + mBar = bar; + mType = type; + + // + result = IsValid(); + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Fill Bar as XOHCL struct ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool FillBar( + XOHCL &bar // + ) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + bar = mBar; + result = mBar.IsValid(); + + // + return result; + } + + /** + * Get Time of Swing ... + * + * @return ( datetime ) + */ + datetime GetTime() + { + // + datetime result = NULL; + + // + if (!IsValid() || !mBar.IsValid()) + { + return result; + } + + // + result = mBar.time; + + // + return result; + } + + ENUM_TIMEFRAMES GetPeriod() + { + // + ENUM_TIMEFRAMES result = NULL; + + // + XOHCL bar; + bool isFilled = FillBar(bar); + if (!isFilled) + { + return result; + } + + // + result = bar.period; + + // + return result; + } + + /** + * Check Swing High or not ... + * + * @return ( bool ) + */ + bool IsSwingHigh() + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + result = + Type() == X_POI_SWING_HIGH; + + // + return result; + } + + /** + * Check Swing Low or not ... + * + * @return ( bool ) + */ + bool IsSwingLow() + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + result = + Type() == X_POI_SWING_LOW; + + // + return result; + } + + /** + * Get Swing Value ... + * + * @return ( double ) + */ + double GetValue() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = + IsSwingHigh() + ? mBar.high + : mBar.low; + + // + return result; + } + + // + // Overrides ... + + void Clean() override + { + // + mBar.Clean(); + mType = X_POI_NONE; + } + + bool IsValid() override + { + // + bool result = false; + + // + result = mBar.IsValid() && + (mType == X_POI_SWING_HIGH || + mType == X_POI_SWING_LOW); + + // + return result; + } + + string GetTag() override + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + string hash = ToMD5(mBar.GetTag()); + + // + string subType = IsSwingHigh() + ? "High" + : "Low"; + + // + result = + // + TypeAsString() + mSep + + subType + mSep + + ToString(mBar.period) + mSep + + hash + // + ; + + // + return result; + } + + string GetTooltip() override + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + return result; + } + + // + protected: + // + // Props ... + XOHCL mBar; // Swing Bar ... + + // + private: + // +}; + +// +// Supply Zone ... +class XCSupplyZone : public XCBarZone +{ + // + public: + // + + // + // Constructor ... + void XCSupplyZone() + { + } + + // + // Deconstructor ... + void ~XCSupplyZone() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param bar: XOHCL instance ... + * @param range: Integer, Detection Range ... + * + * @return ( bool ) + */ + bool Init( + XOHCL &bar, + int range = 0, + bool useRangeAsStart = false // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + result = InitBarZone( + bar, + X_POI_SUPPLY_ZONE, + X_PRICE_HIGH, + X_PRICE_LOW // + ); + if (!result) + { + return result; + } + + // + result = IsValid(); + if (result && + range > 0) + { + // + datetime time = bar.time; + int periodSeconds = PeriodSeconds(bar.period); + + // + datetime from = + !useRangeAsStart + ? (datetime)((int)time - (range * periodSeconds)) + : time; + datetime to = (datetime)((int)time + (range * periodSeconds)); + + // + From(from); + To(to); + } + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + // + // Overrides ... + + bool IsValid() override + { + // + bool result = false; + + // + result = IsValidBarZone() && + mType == X_POI_SUPPLY_ZONE; + + // + return result; + } + + // + protected: + // + + // + private: + // + + // +}; + +// +// Demand Zone ... +class XCDemandZone : public XCBarZone +{ + // + public: + // + + // + // Constructor ... + void XCDemandZone() + { + } + + // + // Deconstructor ... + void ~XCDemandZone() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param bar: XOHCL instance ... + * @param range: Integer, Detection Range ... + * + * @return ( bool ) + */ + bool Init( + XOHCL &bar, + int range = 0, + bool useRangeAsStart = false // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + result = InitBarZone( + bar, + X_POI_DEMAND_ZONE, + X_PRICE_HIGH, + X_PRICE_LOW // + ); + if (!result) + { + return result; + } + + // + result = IsValid(); + if (result && + range > 0) + { + // + datetime time = bar.time; + int periodSeconds = PeriodSeconds(bar.period); + + // + datetime from = + !useRangeAsStart + ? (datetime)((int)time - (range * periodSeconds)) + : time; + datetime to = (datetime)((int)time + (range * periodSeconds)); + + // + From(from); + To(to); + } + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + // + // Overrides ... + + bool IsValid() override + { + // + bool result = false; + + // + result = IsValidBarZone() && + mType == X_POI_DEMAND_ZONE; + + // + return result; + } + + // + protected: + // + + // + private: + // + + // +}; + +// +// Support Zone ... +class XCSupportZone : public XCBarZone +{ + // + public: + // + + // + // Constructor ... + void XCSupportZone() + { + } + + // + // Deconstructor ... + void ~XCSupportZone() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param bar: XOHCL instance ... + * @param range: Integer, Detection Range ... + * + * @return ( bool ) + */ + bool Init( + XOHCL &bar, + int range = 0, + bool useRangeAsStart = false // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + result = InitBarZone( + bar, + X_POI_SUPPORT_ZONE, + X_PRICE_DOWN, + X_PRICE_LOW // + ); + if (!result) + { + return result; + } + + // + result = IsValid(); + if (result && + range > 0) + { + // + datetime time = bar.time; + int periodSeconds = PeriodSeconds(bar.period); + + // + datetime from = + !useRangeAsStart + ? (datetime)((int)time - (range * periodSeconds)) + : time; + datetime to = (datetime)((int)time + (range * periodSeconds)); + + // + From(from); + To(to); + } + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + // + // Overrides ... + + bool IsValid() override + { + // + bool result = false; + + // + result = IsValidBarZone() && + mType == X_POI_SUPPORT_ZONE; + + // + return result; + } + + // + protected: + // + + // + private: + // + + // +}; + +// +// Resistance Zone ... +class XCResistanceZone : public XCBarZone +{ + // + public: + // + + // + // Constructor ... + void XCResistanceZone() + { + } + + // + // Deconstructor ... + void ~XCResistanceZone() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param bar: XOHCL instance ... + * @param range: Integer, Detection Range ... + * + * @return ( bool ) + */ + bool Init( + XOHCL &bar, + int range = 0, + bool useRangeAsStart = false // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + result = InitBarZone( + bar, + X_POI_RESISTANCE_ZONE, + X_PRICE_HIGH, + X_PRICE_UP // + ); + if (!result) + { + return result; + } + + // + result = IsValid(); + if (result && + range > 0) + { + // + datetime time = bar.time; + int periodSeconds = PeriodSeconds(bar.period); + + // + datetime from = + !useRangeAsStart + ? (datetime)((int)time - (range * periodSeconds)) + : time; + datetime to = (datetime)((int)time + (range * periodSeconds)); + + // + From(from); + To(to); + } + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + // + // Overrides ... + + bool IsValid() override + { + // + bool result = false; + + // + result = IsValidBarZone() && + mType == X_POI_RESISTANCE_ZONE; + + // + return result; + } + + // + protected: + // + + // + private: + // + + // +}; + +// +// Order Block ... +class XCOrderBlock : public XCBarZone +{ + // + public: + // + + // + // Constructor ... + void XCOrderBlock() + { + } + + // + // Deconstructor ... + void ~XCOrderBlock() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param bar: XOHCL instance ... + * @param dir: ENUM_X_DIRECTION member ... + * + * @return ( bool ) + */ + bool Init( + XOHCL &bar, + ENUM_X_DIRECTION dir // + ) + { + // + bool result = false; + + // + result = bar.IsValid() && + (dir == X_DIRECTION_BULLISH || + dir == X_DIRECTION_BEARISH); + if (!result) + { + return result; + } + + // + ENUM_XPOIS mTT = + IsSpecifiedBullish(dir) + ? X_POI_BULLISH_ORDERBLOCK + : X_POI_BEARISH_ORDERBLOCK; + + // + result = InitBarZone( + bar, + mTT, + X_PRICE_HIGH, + X_PRICE_LOW // + ); + if (!result) + { + return result; + } + + // + result = IsValid(); + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Check is Bullish ... + * + * @return ( bool ) + */ + bool IsBullish() + { + // + bool result = false; + + // + result = IsValid() && + Type() == X_POI_BULLISH_ORDERBLOCK; + + // + return result; + } + + /** + * Check is Bearish ... + * + * @return ( bool ) + */ + bool IsBearish() + { + // + bool result = false; + + // + result = IsValid() && + Type() == X_POI_BEARISH_ORDERBLOCK; + + // + return result; + } + + ENUM_X_DIRECTION GetDirection() + { + // + ENUM_X_DIRECTION result = X_DIRECTION_NONE; + + // + if (!IsValid()) + { + return result; + } + + // + result = + IsBullish() + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; + } + + // + // Overrides ... + + bool IsValid() override + { + // + bool result = false; + + // + result = IsValidBarZone() && + (mType == X_POI_BULLISH_ORDERBLOCK || + mType == X_POI_BEARISH_ORDERBLOCK); + + // + return result; + } + + // + protected: + // + + // + private: + // + + // +}; + +// +// Rejection Bar ... +class XCRejectionBar : public XCBarZone +{ + // + public: + // + + // + // Constructor ... + void XCRejectionBar() + { + } + + // + // Deconstructor ... + void ~XCRejectionBar() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool Init( + XOHCL &bar // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + bool isBullish = + bar.GetLowShadow() > bar.GetHighShadow(); + bool isBearish = + bar.GetHighShadow() > bar.GetLowShadow(); + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + ENUM_X_PRICE upPrice = isBullish + ? X_PRICE_HIGH + : X_PRICE_DOWN; + // + ENUM_X_PRICE loPrice = isBullish + ? X_PRICE_UP + : X_PRICE_LOW; + + // + result = InitBarZone( + bar, + X_POI_REJECTION_BAR, + upPrice, + loPrice // + ); + if (!result) + { + return result; + } + + // + result = IsValid(); + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Check is Bullish ... + * + * @return ( bool ) + */ + bool IsBullish() + { + // + bool result = false; + + // + result = IsValid() && + Type() == X_POI_REJECTION_BAR && + mBar.GetLowShadow() > mBar.GetHighShadow(); + + // + return result; + } + + /** + * Check is Bearish ... + * + * @return ( bool ) + */ + bool IsBearish() + { + // + bool result = false; + + // + result = IsValid() && + Type() == X_POI_REJECTION_BAR && + mBar.GetHighShadow() > mBar.GetLowShadow(); + + // + return result; + } + + // + // Overrides ... + + bool IsValid() override + { + // + bool result = false; + + // + result = IsValidBarZone() && + mType == X_POI_REJECTION_BAR; + + // + return result; + } + + // + protected: + // + + // + private: + // + + // +}; + +// +// Momentum Bar ... +class XCMomentumBar : public XCBarZone +{ + // + public: + // + + // + // Constructor ... + void XCMomentumBar() + { + } + + // + // Deconstructor ... + void ~XCMomentumBar() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param bar: XOHCL instance ... + * + * @return ( bool ) + */ + bool Init( + XOHCL &bar // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + bool isBullish = bar.IsBullish(); + bool isBearish = bar.IsBearish(); + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + result = InitBarZone( + bar, + X_POI_MOMENTUM_BAR, + X_PRICE_HIGH, + X_PRICE_LOW // + ); + if (!result) + { + return result; + } + + // + result = IsValid(); + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Check is Bullish ... + * + * @return ( bool ) + */ + bool IsBullish() + { + // + bool result = false; + + // + result = IsValid() && + mBar.IsBullish() && + Type() == X_POI_MOMENTUM_BAR; + + // + return result; + } + + /** + * Check is Bearish ... + * + * @return ( bool ) + */ + bool IsBearish() + { + // + bool result = false; + + // + result = IsValid() && + mBar.IsBearish() && + Type() == X_POI_MOMENTUM_BAR; + + // + return result; + } + + // + // Overrides ... + + bool IsValid() override + { + // + bool result = false; + + // + result = IsValidBarZone() && + mType == X_POI_MOMENTUM_BAR; + + // + return result; + } + + // + protected: + // + + // + private: + // + + // +}; + +// +// Fair Value Gap ... +class XCFVG : public XCTwoBarZone +{ + // + public: + // + + // + // Constructor ... + void XCFVG() + { + } + + // + // Deconstructor ... + void ~XCFVG() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param startBar: XOHCL instance ... + * @param endBar: XOHCL instance ... + * @param dir: ENUM_X_DIRECTION member ... + * + * @return ( bool ) + */ + bool Init( + XOHCL &startBar, + XOHCL &endBar, + ENUM_X_DIRECTION dir // + ) + { + // + bool result = false; + + // + result = endBar.IsValid() && + startBar.IsValid() && + (dir == X_DIRECTION_BULLISH || + dir == X_DIRECTION_BEARISH); + if (!result) + { + return result; + } + + // + bool isDirBullish = IsSpecifiedBullish(dir); + ENUM_XPOIS mTT = + isDirBullish + ? X_POI_BULLISH_FVG + : X_POI_BEARISH_FVG; + + // + ENUM_X_PRICE startPrice = isDirBullish + ? X_PRICE_HIGH + : X_PRICE_LOW; + ENUM_X_PRICE endPrice = isDirBullish + ? X_PRICE_LOW + : X_PRICE_HIGH; + + // + result = InitTwoBarZone( + startBar, + endBar, + mTT, + startPrice, + endPrice // + ); + if (!result) + { + return result; + } + + // + result = IsValid(); + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Check is Bullish ... + * + * @return ( bool ) + */ + bool IsBullish() + { + // + bool result = false; + + // + result = IsValid() && + Type() == X_POI_BULLISH_FVG; + + // + return result; + } + + /** + * Check is Bearish ... + * + * @return ( bool ) + */ + bool IsBearish() + { + // + bool result = false; + + // + result = IsValid() && + Type() == X_POI_BEARISH_FVG; + + // + return result; + } + + ENUM_X_DIRECTION GetDirection() + { + // + ENUM_X_DIRECTION result = X_DIRECTION_NONE; + + // + if (!IsValid()) + { + return result; + } + + // + result = + IsBullish() + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; + } + + // + // Overrides ... + + bool IsValid() override + { + // + bool result = false; + + // + result = IsValidTwoBarZone() && + (mType == X_POI_BULLISH_FVG || + mType == X_POI_BEARISH_FVG); + + // + return result; + } + + // + protected: + // + + // + private: + // + + // +}; + +// +// Ticks Zones ... + +// +class XCTickZone : public CObject +{ + // + // Public ... + public: + // + // Props ... + string symbol; + ENUM_TIMEFRAMES period; + + // + double high; + double low; + int ticks; + double percent; + + // + ulong volume; + double volumePercent; + + // + // Compare Two Zone With Each Other ... + virtual int Compare( + const CObject *node, + const int mode = 0 // + ) const + { + // + const XCTickZone *other = (XCTickZone *)node; + + // + return other.ticks - ticks; + } + + // + bool IsValid() + { + // + bool result = false; + + // + result = high > 0 && + low > 0 && + high > low && + ticks > 0 && + percent > 0; + + // + return result; + } + + // + // Protected ... + protected: + // + // Private ... + private: + // +}; + +// +class XCTicksZone : public XCTwoBarZone +{ + // + public: + // + + // + // Constructor ... + void XCTicksZone() + { + Default(); + } + + // + // Deconstructor ... + void ~XCTicksZone() + { + } + + // + // Getter(s) / Setter(s) ... + + /** + * Get Number of Ticks Levels ... + * + * @return ( int ) + */ + int Levels() + { + return mLevels; + } + + /** + * Set Number of Ticks Levels ... + * + * @return ( int ) + */ + void Levels(int value) + { + // + if (value < 2) + { + value = 2; + } + + // + mLevels = value; + } + + /** + * Apply Default Config ... + */ + virtual void Default() + { + // + Levels(10); + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @param startBar: XOHCL instance ... + * @param endBar: XOHCL instance ... + * + * @return ( bool ) + */ + bool Init( + XOHCL &startBar, + XOHCL &endBar, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + result = endBar.IsValid() && + startBar.IsValid(); + if (!result) + { + return result; + } + + // + if (!IsSpecifiedValid(forPeriod)) + { + forPeriod = endBar.period; + } + + // + // Calculate Start and End Time ... + datetime from = startBar.time; + datetime to = endBar.time; + ulong fromM = ((ulong)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, + forPeriod, + from, + to, + mTickVolumes // + ); + if (IsValidSize(ticksVolumeCount)) + { + // + mVolumes = 0; + for (int i = 0; i < ticksVolumeCount; i++) + { + mVolumes += mTickVolumes[i]; + } + } + + // + // Retrieve Highs ... + SpecificClean(mHighs); + CopyHigh( + symbol, + period, + from, + to, + mHighs // + ); + + // + // Retrieve Lows ... + SpecificClean(mLows); + CopyLow( + symbol, + period, + from, + to, + mLows // + ); + + // + // Find Highest Value in Range ... + int highIDX = ArrayMaximum(mHighs); + mRangeHigh = mHighs[highIDX]; + + // + // Find Lowest Value in Range ... + int lowIDX = ArrayMinimum(mLows); + mRangeLow = mLows[lowIDX]; + + // + datetime mTimes[]; + CopyTime( + symbol, + period, + from, + to, + mTimes // + ); + mRangeHighTime = mTimes[highIDX]; + mRangeLowTime = mTimes[lowIDX]; + + // + double mRangeSize = mRangeHigh - mRangeLow; + + // + // Create Zones ... + for (int i = 0; i < Levels(); i++) + { + // + // Instance a New Zone ... + XCTickZone *iZone = new XCTickZone(); + + // + iZone.symbol = symbol; + iZone.period = period; + + // + // Calculate Each Zones High / Low based on Range ... + double iH = mRangeHigh - mRangeSize * i / Levels(); + double iL = mRangeHigh - mRangeSize * (i + 1) / Levels(); + + // + // Set Zone High Low Properties ... + iZone.low = iL; + iZone.high = iH; + + // + // Add Zone to Zone Array Objects ... + mZones.Add(iZone); + } + + // + // Calculate Each Zone Ticks ... + int ticksCount = ArraySize(mTicks); + for (int i = 0; i < ticksCount; i++) + { + // + // Retrieve Tick ... + MqlTick iTick = mTicks[i]; + + // + // Loop through Zones ... + for (int j = 0; j < Levels(); j++) + { + // + // Rejrieve j indexed Zone Object ... + XCTickZone *jZone = mZones.At(j); + + // + bool isInRange = IsTickInZoneRange( + iTick, + jZone // + ); + if (isInRange) + { + // + jZone.ticks++; + break; + } + } + } + + // + // Calculating Zone Percents ... + for (int i = 0; i < Levels(); i++) + { + // + XCTickZone *iZone = mZones.At(i); + + // + double percent = CalculateZoneTickPercent(iZone); + iZone.percent = percent; + } + + // + // Sort Zones Based on Percents ... + mZones.Sort(); + + // + mUpper = mRangeHigh; + mLower = mRangeLow; + mType = X_POI_TICKS_ZONES; + mEndBar = endBar; + mStartBar = startBar; + From(startBar.time); + To(endBar.time); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + // Try to Find Out PERIOD_1M times in each zone ... + datetime to1M = (datetime)((int)endBar.time + PeriodSeconds(period) - 60); + int to1MIndex = iBarShift( + symbol, + forPeriod, + to1M // + ); + int from1MIndex = iBarShift( + symbol, + forPeriod, + from // + ); + for (int i = from1MIndex; i > to1MIndex; i--) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + symbol, + forPeriod, + i // + ); + if (!isInited) + { + continue; + } + ulong iVolume = iTickVolume( + symbol, + forPeriod, + i // + ); + + // + // Loop through Zones ... + for (int j = 0; j < Levels(); j++) + { + // + XCTickZone *jZone = mZones.At(j); + if (!jZone.IsValid()) + { + continue; + } + + // + // Check iBar is Inside jZone ... + bool isIBarInside = + iBar.GetUp() < jZone.high && + iBar.GetDown() > jZone.low; + // iBar.low < jZone.high || + // iBar.high > jZone.low; + if (isIBarInside) + { + jZone.volume += iVolume; + } + } + } + + // + // Calculate Volume Percent ... + for (int i = 0; i < Levels(); i++) + { + // + XCTickZone *iZone = mZones.At(i); + + // + if (mVolumes > 0) + { + iZone.volumePercent = (double)(iZone.volume * 100 / mVolumes); + } + } + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Retrieve Zones Count ... + * + * @return ( int ) + */ + int Count() + { + return mZones.Total(); + } + + /** + * Retrieve Specified Sorted Zones ... + * + * @param index: Integer ... + * + * @return ( XCTickZone * ) + */ + XCTickZone *GetZone(int index) + { + // + if (!IsValidIndex(index)) + { + return NULL; + } + + // + return mZones.At(index); + } + + /** + * Calculate Liquidity Percent for Specified Direction ... + * + * @param forDirection: ENUM_X_DIRECTION member, Specified Liquidity ... + * @param price: Double, Specified Price ... + * + * @return ( double ) + */ + double CalculateLiquidityPercent( + ENUM_X_DIRECTION forDirection, + double price // + ) + { + // + double result = 0; + + // + int count = Count(); + if (price <= 0 || + !IsValid() || + !IsValidSize(count) || + forDirection == X_DIRECTION_ALL || + forDirection == X_DIRECTION_NONE) + { + return result; + } + + // + bool isBullish = forDirection == X_DIRECTION_BULLISH; + + // + for (int i = 0; i < count; i++) + { + // + XCTickZone *iZone = GetZone(i); + + // + if (iZone.IsValid()) + { + // + result += !isBullish && + price > iZone.high + ? iZone.percent + : isBullish && + price < iZone.low + ? iZone.percent + : 0; + } + } + + // + return result; + } + + // + // Overrides ... + bool IsValid() override + { + // + bool result = false; + + // + result = + IsValidFrom() && + IsValidTwoBarZone() && + Levels() > 0 && + mZones.Total() == Levels() && + mRangeHigh > 0 && + mRangeLow > 0; + + // + return result; + } + + // + protected: + // + + // + private: + // + // Props ... + + // + MqlTick mTicks[]; + double mHighs[]; + double mLows[]; + ulong mVolumes; + ulong mTickVolumes[]; + double mRangeHigh; + datetime mRangeHighTime; + double mRangeLow; + datetime mRangeLowTime; + + // + int mLevels; // Number of Ticks Levels ... + + // + CArrayObj mZones; + + /** + * Check a Tick is in a Zone rage or not ... + * + * @param tick: MqlTick instance ... + * @param zone: XCTickZone instance ... + * + * @return ( bool ) + */ + bool IsTickInZoneRange( + MqlTick &tick, + XCTickZone *zone // + ) + { + // + bool result = false; + + // + result = + // + tick.bid >= zone.low && + tick.bid <= zone.high + // + ; + + // + return result; + } + + /** + * Calculate Zone Tick Percent ... + * + * @param zone: XCTickZone instance ... + * @param normalizationDigits: Integer ... + * + * @return ( double ) + */ + double CalculateZoneTickPercent( + XCTickZone *zone, + int normalizationDigits = 2 // + ) + { + // + double result = 0; + + // + if (normalizationDigits < 2 || normalizationDigits > 5) + { + normalizationDigits = 2; + } + + // + int ticksCount = ArraySize(mTicks); + if (ticksCount <= 0) + { + return result; + } + + // + result = (double)zone.ticks / ticksCount * 100; + result = NormalizeDouble(result, normalizationDigits); + + // + return result; + } + + // +}; + +// +// Trading Day ... +class XCDay : public XCFromToZone +{ + // + public: + // + + // + // Constructor ... + void XCDay() + { + } + + // + // Deconstructor ... + void ~XCDay() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @return ( bool ) + */ + bool Init() + { + // + bool result = false; + + // + result = IsValid(); + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + // + // Overrides ... + + // + protected: + // + + // + private: + // + + // +}; + +// +// Trading Session ... +class XCSession : public XCFromToZone +{ + // + public: + // + + // + // Constructor ... + void XCSession() + { + } + + // + // Deconstructor ... + void ~XCSession() + { + } + + // + // Tools ... + + /** + * Initialize POI ... + * + * @return ( bool ) + */ + bool Init() + { + // + bool result = false; + + // + result = IsValid(); + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + // + // Overrides ... + + // + protected: + // + + // + private: + // + + // +}; + +// +struct XBoxZone +{ + // + // Props ... + string symbol; + ENUM_TIMEFRAMES period; + + // + double upper; + double lower; + + // + datetime from; + datetime to; + + // + string type; + ENUM_X_DIRECTION dir; + + // + // Constructor ... + XBoxZone() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup Model ... + */ + void Clean() + { + // + upper = 0; + lower = 0; + to = NULL; + from = NULL; + symbol = NULL; + period = NULL; + dir = X_DIRECTION_NONE; + + // + ZeroMemory(this); + } + + /** + * Validate Model ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + // + upper > 0 && + lower > 0 && + from < to && + IsValid(to) && + upper >= lower && + IsValid(from) && + IsValid(symbol) && + IsValid(period) + // + ; + + // + return result; + } + + bool IsBullish() + { + return IsValid() && + IsBullish(dir); + } + + bool IsBearish() + { + return IsValid() && + IsBearish(dir); + } + + bool IsSameAs(XBoxZone &item) + { + // + return IsValid() && + dir == item.dir && + from == item.from && + type == item.type && + lower == item.lower && + upper == item.upper && + symbol == item.symbol && + period == item.period; + } + + /** + * Check Box is Same as another ... + * + * @param box: XBoxZone instance Reference ... + * + * @return ( bool ) + */ + bool IsSame(XBoxZone &box) + { + // + bool result = false; + + // + result = IsValid() && + box.IsValid(); + if (!result) + { + return result; + } + + // + result = + // + dir == box.dir && + from == box.from && + type == box.type && + upper == box.upper && + lower == box.lower && + symbol == box.symbol && + period == box.period + // + ; + + // + return result; + } + + /** + * Retrieve Unique Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + // + string result = + // + "XBOX" + "_" + + ToString(dir) + "_" + + symbol + "_" + + ToString(period) + "_" + + ToString(upper) + "_" + + ToString(lower) + // + ; + + // + return result; + } +}; + +// diff --git a/BKPS/14031218/Libraries/x-saherelm.x-poi.state.lib.ex5 b/BKPS/14031218/Libraries/x-saherelm.x-poi.state.lib.ex5 new file mode 100644 index 0000000..83a5aa4 Binary files /dev/null and b/BKPS/14031218/Libraries/x-saherelm.x-poi.state.lib.ex5 differ diff --git a/BKPS/14031218/Libraries/x-saherelm.x-poi.state.lib.mq5 b/BKPS/14031218/Libraries/x-saherelm.x-poi.state.lib.mq5 new file mode 100644 index 0000000..f50bc12 --- /dev/null +++ b/BKPS/14031218/Libraries/x-saherelm.x-poi.state.lib.mq5 @@ -0,0 +1,4523 @@ + +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Seriallize Library +// --------------------------------------- +// Name: XPOILib +// Description: All models related to POIs ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright `023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Libraries/x-saherelm.x-poi.extensions.lib.mq5" +#include "../Libraries/x-saherelm.x-poi.lib.mq5" + +// +enum ENUM_X_OBFVG_FVG_FILTERS +{ + X_OBFVG_FVG_FILTER_NONE, + X_OBFVG_FVG_FILTER_INSIDE_OR, + X_OBFVG_FVG_FILTER_ABOVE_BELOW, +}; + +// +enum ENUM_X_OBFVG_FVG_SELECTION +{ + X_OBFVG_FVG_SELECT_NONE, + X_OBFVG_FVG_SELECT_OLDEST, + X_OBFVG_FVG_SELECT_LOWEST, + X_OBFVG_FVG_SELECT_HIGHEST, + X_OBFVG_FVG_SELECT_YOUNGEST, + X_OBFVG_FVG_SELECT_HIGHEST_LOWEST, + X_OBFVG_FVG_SELECT_LOWEST_HIGHEST, +}; + +// +struct XOBFVGPivot +{ + // + // Props ... + double value; + datetime at; + + // + // Constructor ... + XOBFVGPivot() + { + Clean(); + } + + // + // Tools ... + + // + void Clean() + { + // + value = 0; + at = NULL; + + // + ZeroMemory(this); + } + + // + bool IsValid() + { + // + bool result = false; + + // + result = + value > 0 && + IsValid(at); + + // + return result; + } +}; + +// +struct XOBFVG +{ + // + // Props ... + XCFVG *fvgs[]; + XCOrderBlock *ob; + + // + // Constructor ... + XOBFVG() + { + Clean(); + } + + // + // Tools ... + + // + void Clean() + { + // + Clean(fvgs); + ZeroMemory(ob); + + // + ZeroMemory(this); + } + + // + bool IsValid() + { + // + bool result = false; + + // + result = HasOB() && + HasFVGs(); + if (!result) + { + return result; + } + + // + XOHCL passedBar; + bool isBodyOut; + bool isOBStarted = ob.IsStarted( + ob.GetDirection(), + passedBar, + isBodyOut // + ); + + // + int idx = GetOldest(fvgs); + result = IsValidIndex(idx); + if (!result) + { + // + passedBar.Clean(); + return result; + } + + // + bool isFVGStarted = fvgs[idx].IsStarted( + ob.GetDirection(), + passedBar, + isBodyOut // + ); + + // + result = isOBStarted && + isFVGStarted; + + // + passedBar.Clean(); + + // + return result; + } + + // + bool HasOB() + { + return ob != NULL && + ob.IsValid(); + } + + // + bool HasFVGs() + { + return HasChild(fvgs); + } + + // + int CountFVGs() + { + return ArraySize(fvgs); + } + + // + ENUM_X_DIRECTION GetDirection() + { + // + ENUM_X_DIRECTION result = X_DIRECTION_NONE; + + // + bool isValid = IsValid(); + if (!isValid) + { + return result; + } + + // + result = ob.GetDirection(); + + // + return result; + } + + // + bool IsBullish() + { + return IsBullish(GetDirection()); + } + + // + bool IsBearish() + { + return IsBearish(GetDirection()); + } + + // + int GetSwings( + XOBFVGPivot &pivots[] // + ) + { + // + int result = 0; + + // + Clean(pivots); + + // + if (!IsValid()) + { + return result; + } + + // + ENUM_X_DIRECTION forDir = GetDirection(); + bool isBullish = IsBullish(forDir); + + // + XOHCL passedBar; + XOBFVGPivot iPivot; + bool isPassed = false; + double appliedPrice = 0; + bool isBodyState = false; + + // + // Start ... + isPassed = ob.IsStarted( + forDir, + passedBar, + isBodyState // + ); + if (isPassed) + { + // + appliedPrice = + isBullish + ? passedBar.low + : passedBar.high; + + // + iPivot.Clean(); + iPivot.value = appliedPrice; + iPivot.at = passedBar.time; + + // + AddRef( + iPivot, + pivots // + ); + + // + iPivot.Clean(); + } + + // + // Activation ... + isPassed = ob.IsActivated( + forDir, + passedBar, + isBodyState // + ); + if (isPassed) + { + // + appliedPrice = + isBullish + ? passedBar.low + : passedBar.high; + + // + iPivot.Clean(); + iPivot.value = appliedPrice; + iPivot.at = passedBar.time; + + // + AddRef( + iPivot, + pivots // + ); + + // + iPivot.Clean(); + } + + // + // Worked ... + isPassed = ob.IsWorked( + forDir, + passedBar, + isBodyState // + ); + if (isPassed) + { + // + appliedPrice = + isBullish + ? passedBar.low + : passedBar.high; + + // + iPivot.Clean(); + iPivot.value = appliedPrice; + iPivot.at = passedBar.time; + + // + AddRef( + iPivot, + pivots // + ); + + // + iPivot.Clean(); + } + + // + passedBar.Clean(); + + // + result = ArraySize(pivots); + + // + return result; + } + + // + bool GetMainFVG( + XCFVG *&fvg // + ) + { + // + bool result = false; + + // + fvg = NULL; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int idx = GetOldest(fvgs); + result = IsValidIndex(idx); + if (!result) + { + // + ZeroMemory(fvg); + return result; + } + + // + fvg = fvgs[idx]; + result = fvg != NULL && + fvg.IsValid(); + + // + return result; + } + + // + bool IsValidZone( + int barIndex = 0 // + ) + { + // + bool result = false; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + XCFVG *tmpFVGs[]; + Copy( + fvgs, + tmpFVGs // + ); + int count = CountFVGs(); + for (int i = 0; i < count; i++) + { + // + XCFVG *iFVG = tmpFVGs[i]; + + // + XOHCL startedBar; + bool isBodyOut = false; + result = iFVG.IsStarted( + iFVG.GetDirection(), + startedBar, + isBodyOut // + ); + if (!result) + { + // + ZeroMemory(iFVG); + startedBar.Clean(); + ArrayRemove( + fvgs, + i, + 1 // + ); + + // + continue; + } + + // + XOHCL bar; + bool isBullish = iFVG.IsBullish(); + datetime fromTime = startedBar.NextAt(); + + // + int fromIndex = iBarShift( + iFVG.GetSymbol(), + iFVG.GetPeriod(), + fromTime // + ); + result = IsValidIndex(fromIndex); + if (!result) + { + // + bar.Clean(); + ZeroMemory(iFVG); + startedBar.Clean(); + ArrayRemove( + fvgs, + i, + 1 // + ); + + // + continue; + } + + // + bool isInited = false; + bool isValidFVG = false; + for (int j = barIndex; j < fromIndex; j++) + { + // + isInited = bar.Init( + iFVG.GetSymbol(), + iFVG.GetPeriod(), + j // + ); + if (!isInited) + { + // + bar.Clean(); + continue; + } + + // + // bool isBarAbove = + // bar.low > iFVG.Upper(); + // bool isBarBelow = + // bar.high < iFVG.Lower(); + + // + bool isBarAbove = + bar.GetDown() > iFVG.Upper(); + bool isBarBelow = + bar.GetUp() < iFVG.Lower(); + + // + isValidFVG = + isBullish + ? isBarAbove + : isBarBelow; + if (!isValidFVG) + { + // + bar.Clean(); + + // + break; + } + + // + bar.Clean(); + } + + // + if (!isValidFVG) + { + // + ArrayRemove( + fvgs, + i, + 1 // + ); + } + + // + bar.Clean(); + ZeroMemory(iFVG); + startedBar.Clean(); + } + + // + Clean(tmpFVGs); + + // + result = HasFVGs(); + + // + return result; + } + + // + bool ToZone(XBoxZone &box) + { + // + bool result = false; + + // + result = ToZoneBox( + box, + this // + ); + + // + return result; + } + + // + void AddFVG(XCFVG *fvg) + { + // + int idx = -1; + bool has = false; + + // + has = + HasOB() && + fvg != NULL && + fvg.IsValid() && + ob.GetDirection() == fvg.GetDirection(); + if (!has) + { + return; + } + + // + idx = FindIndex( + fvg, + fvgs // + ); + has = !IsValidIndex(idx); + if (!has) + { + return; + } + + // + Add( + fvg, + fvgs // + ); + } + + // + bool IsSameAs(XOBFVG &item) + { + // + bool result = false; + + // + result = IsValid() && + IsSame(ob, item.ob); + + // + return result; + } + + // + void UpdateTo(datetime value = NULL) + { + // + value = NormalizeTime(value); + + // + int count = 0; + bool has = false; + + // + has = HasOB(); + if (has) + { + ob.To(value); + } + + // + has = HasFVGs(); + if (has) + { + // + count = CountFVGs(); + for (int i = 0; i < count; i++) + { + fvgs[i].To(value); + } + } + } +}; + +// +// +// Model Exists Founded POIs ... +struct XPOIState +{ + // + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + XCSwing *swings[]; // Holds Founded Swing ... + XCSwing *swingLows[]; // Holds Founded Swing Lows ... + XCSwing *swingHighs[]; // Holds Founded Swing Highs ... + + // + XCMomentumBar *momentumBars[]; // Holds Founded Momentum Bars ... + XCMomentumBar *bullishMomentumBars[]; // Holds Founded Bullish Momentum Bars ... + XCMomentumBar *bearishMomentumBars[]; // Holds Founded Bearish Momentum Bars ... + + // + XCRejectionBar *rejectionBars[]; // Holds Founded Rejection 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 *orderBlocks[]; // Holds Founded Order Blocks ... + XCOrderBlock *bullishOrderBlocks[]; // Holds Founded Bullish Order Blocks ... + XCOrderBlock *bearishOrderBlocks[]; // Holds Founded Bearish Order Blocks ... + + // + XCFVG *fairValueGaps[]; // Holds Founded Fair Value Gaps ... + XCFVG *bullishFairValueGaps[]; // Holds Founded Bullish Fair Value Gaps ... + XCFVG *bearishFairValueGaps[]; // Holds Founded Bearish Fair Value Gaps ... + + // + XConsolidationZone consolidationZones[]; // Holds Founded Consolidation Zones ... + XConsolidationZone bullishConsolidationZones[]; // Holds Founded Bullish Consolidation Zones ... + XConsolidationZone bearishConsolidationZones[]; // Holds Founded Bearih Consolidation Zones ... + + // + // Constructor ... + void XPOIState() + { + Clean(); + } + + // + // Actions ... + + /** + * Cleanup all props ... + */ + void Clean() + { + // + time = NULL; + symbol = NULL; + period = NULL; + + // + Clean(swings); + Clean(swingLows); + Clean(swingHighs); + + // + Clean(momentumBars); + Clean(bullishMomentumBars); + Clean(bearishMomentumBars); + + // + Clean(rejectionBars); + Clean(bullishRejectionBars); + Clean(bearishRejectionBars); + + // + Clean(supportZones); + Clean(resistanceZones); + + // + Clean(supplyZones); + Clean(demandZones); + + // + Clean(orderBlocks); + Clean(bullishOrderBlocks); + Clean(bearishOrderBlocks); + + // + Clean(fairValueGaps); + Clean(bullishFairValueGaps); + Clean(bearishFairValueGaps); + + // + Clean(consolidationZones); + Clean(bullishConsolidationZones); + Clean(bearishConsolidationZones); + + // + ZeroMemory(this); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + IsSpecifiedValid(symbol) && + IsSpecifiedValid(period) && + IsSpecifiedValid(time); + + // + return result; + } + + /** + * Check State has Childs or not ... + * + * @return ( bool ) + */ + bool HasChild() + { + // + bool result = false; + + // + result = + // + HasSwingLows() || + HasSwingHighs() || + HasSupplyZones() || + HasDemandZones() || + HasSupportZones() || + HasResistanceZones() || + HasBullishOrderBlocks() || + HasBearishOrderBlocks() || + HasBullishMomentumBars() || + HasBearishMomentumBars() || + HasBullishRejectionBars() || + HasBearishRejectionBars() || + HasBullishFairValueGaps() || + HasBearishFairValueGaps() || + HasBullishConsolidationZones() || + HasBearishConsolidationZones() + // + ; + + // + return result; + } + + // + // Counters ... + + // + int CountSwings() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(swings); + + // + return result; + } + + // + bool HasSwings() + { + return IsValidSize(CountSwings()); + } + + // + int CountSwingHighs() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(swingHighs); + + // + return result; + } + + // + bool HasSwingHighs() + { + return IsValidSize(CountSwingHighs()); + } + + // + int CountSwingLows() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(swingLows); + + // + return result; + } + + // + bool HasSwingLows() + { + return IsValidSize(CountSwingLows()); + } + + // + int CountMomentumBars() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(momentumBars); + + // + return result; + } + + // + bool HasMomentumBars() + { + return IsValidSize(CountMomentumBars()); + } + + // + int CountBullishMomentumBars() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(bullishMomentumBars); + + // + return result; + } + + // + bool HasBullishMomentumBars() + { + return IsValidSize(CountBullishMomentumBars()); + } + + // + int CountBearishMomentumBars() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(bearishMomentumBars); + + // + return result; + } + + // + bool HasBearishMomentumBars() + { + return IsValidSize(CountBearishMomentumBars()); + } + + // + int CountRejectionBars() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(rejectionBars); + + // + return result; + } + + // + bool HasRejectionBars() + { + return IsValidSize(CountRejectionBars()); + } + + // + int CountBullishRejectionBars() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(bullishRejectionBars); + + // + return result; + } + + // + bool HasBullishRejectionBars() + { + return IsValidSize(CountBullishRejectionBars()); + } + + // + int CountBearishRejectionBars() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(bearishRejectionBars); + + // + return result; + } + + // + bool HasBearishRejectionBars() + { + return IsValidSize(CountBearishRejectionBars()); + } + + // + int CountSupportZones() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(supportZones); + + // + return result; + } + + // + bool HasSupportZones() + { + return IsValidSize(CountSupportZones()); + } + + // + int CountResistanceZones() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(resistanceZones); + + // + return result; + } + + // + bool HasResistanceZones() + { + return IsValidSize(CountResistanceZones()); + } + + // + int CountSupplyZones() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(supplyZones); + + // + return result; + } + + // + bool HasSupplyZones() + { + return IsValidSize(CountSupplyZones()); + } + + // + int CountDemandZones() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(demandZones); + + // + return result; + } + + // + bool HasDemandZones() + { + return IsValidSize(CountDemandZones()); + } + + // + int CountOrderBlocks() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(orderBlocks); + + // + return result; + } + + // + bool HasOrderBlocks() + { + return IsValidSize(CountOrderBlocks()); + } + + // + int CountBullishOrderBlocks() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(bullishOrderBlocks); + + // + return result; + } + + // + bool HasBullishOrderBlocks() + { + return IsValidSize(CountBullishOrderBlocks()); + } + + // + int CountBearishOrderBlocks() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(bearishOrderBlocks); + + // + return result; + } + + // + bool HasBearishOrderBlocks() + { + return IsValidSize(CountBearishOrderBlocks()); + } + + // + int CountFairValueGaps() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(fairValueGaps); + + // + return result; + } + + // + bool HasFairValueGaps() + { + return IsValidSize(CountFairValueGaps()); + } + + // + int CountBullishFairValueGaps() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(bullishFairValueGaps); + + // + return result; + } + + // + bool HasBullishFairValueGaps() + { + return IsValidSize(CountBullishFairValueGaps()); + } + + // + int CountBearishFairValueGaps() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = ArraySize(bearishFairValueGaps); + + // + return result; + } + + // + bool HasBearishFairValueGaps() + { + return IsValidSize(CountBearishFairValueGaps()); + } + + // + bool HasConsolidationZones() + { + return HasChild(consolidationZones); + } + + // + int CountConsolidationZones() + { + return ArraySize(consolidationZones); + } + + // + bool HasBullishConsolidationZones() + { + return HasChild(bullishConsolidationZones); + } + + // + int CountBullishConsolidationZones() + { + return ArraySize(bullishConsolidationZones); + } + + // + bool HasBearishConsolidationZones() + { + return HasChild(bearishConsolidationZones); + } + + // + int CountBearishConsolidationZones() + { + return ArraySize(bearishConsolidationZones); + } + + // + void UpdateTo(datetime value = NULL) + { + // + value = NormalizeTime(value); + + // + int count = 0; + bool has = false; + + // + has = HasMomentumBars(); + if (has) + { + // + count = CountMomentumBars(); + for (int i = 0; i < count; i++) + { + momentumBars[i].To(value); + } + } + + // + has = HasBullishMomentumBars(); + if (has) + { + // + count = CountBullishMomentumBars(); + for (int i = 0; i < count; i++) + { + bullishMomentumBars[i].To(value); + } + } + + // + has = HasBearishMomentumBars(); + if (has) + { + // + count = CountBearishMomentumBars(); + for (int i = 0; i < count; i++) + { + bearishMomentumBars[i].To(value); + } + } + + // + has = HasRejectionBars(); + if (has) + { + // + count = CountRejectionBars(); + for (int i = 0; i < count; i++) + { + rejectionBars[i].To(value); + } + } + + // + has = HasBullishRejectionBars(); + if (has) + { + // + count = CountBullishRejectionBars(); + for (int i = 0; i < count; i++) + { + bullishRejectionBars[i].To(value); + } + } + + // + has = HasBearishRejectionBars(); + if (has) + { + // + count = CountBearishRejectionBars(); + for (int i = 0; i < count; i++) + { + bearishRejectionBars[i].To(value); + } + } + + // + has = HasSupportZones(); + if (has) + { + // + count = CountSupportZones(); + for (int i = 0; i < count; i++) + { + supportZones[i].To(value); + } + } + + // + has = HasResistanceZones(); + if (has) + { + // + count = CountResistanceZones(); + for (int i = 0; i < count; i++) + { + resistanceZones[i].To(value); + } + } + + // + has = HasSupplyZones(); + if (has) + { + // + count = CountSupplyZones(); + for (int i = 0; i < count; i++) + { + supplyZones[i].To(value); + } + } + + // + has = HasDemandZones(); + if (has) + { + // + count = CountDemandZones(); + for (int i = 0; i < count; i++) + { + demandZones[i].To(value); + } + } + + // + has = HasOrderBlocks(); + if (has) + { + // + count = CountOrderBlocks(); + for (int i = 0; i < count; i++) + { + orderBlocks[i].To(value); + } + } + + // + has = HasBullishOrderBlocks(); + if (has) + { + // + count = CountBullishOrderBlocks(); + for (int i = 0; i < count; i++) + { + bullishOrderBlocks[i].To(value); + } + } + + // + has = HasBearishOrderBlocks(); + if (has) + { + // + count = CountBearishOrderBlocks(); + for (int i = 0; i < count; i++) + { + bearishOrderBlocks[i].To(value); + } + } + + // + has = HasFairValueGaps(); + if (has) + { + // + count = CountFairValueGaps(); + for (int i = 0; i < count; i++) + { + fairValueGaps[i].To(value); + } + } + + // + has = HasBullishFairValueGaps(); + if (has) + { + // + count = CountBullishFairValueGaps(); + for (int i = 0; i < count; i++) + { + bullishFairValueGaps[i].To(value); + } + } + + // + has = HasBearishFairValueGaps(); + if (has) + { + // + count = CountBearishFairValueGaps(); + for (int i = 0; i < count; i++) + { + bearishFairValueGaps[i].To(value); + } + } + } + + // + // Filter Zones ... + + // + // Support ... + int FilterSupportZones( + XCSupportZone *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasSupportZones(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + passedDir = X_DIRECTION_BULLISH; + count = CountSupportZones(); + for (int i = 0; i < count; i++) + { + // + XCSupportZone *iZone = supportZones[i]; + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // Resistance ... + int FilterResistanceZones( + XCResistanceZone *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasResistanceZones(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + passedDir = X_DIRECTION_BEARISH; + count = CountResistanceZones(); + for (int i = 0; i < count; i++) + { + // + XCResistanceZone *iZone = resistanceZones[i]; + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // Supply ... + int FilterSupplyZones( + XCSupplyZone *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasSupplyZones(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + passedDir = X_DIRECTION_BEARISH; + count = CountSupplyZones(); + for (int i = 0; i < count; i++) + { + // + XCSupplyZone *iZone = supplyZones[i]; + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // Demand ... + int FilterDemandZones( + XCDemandZone *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasDemandZones(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + passedDir = X_DIRECTION_BULLISH; + count = CountDemandZones(); + for (int i = 0; i < count; i++) + { + // + XCDemandZone *iZone = demandZones[i]; + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // OrderBlock ... + int FilterOrderBlocks( + XCOrderBlock *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasOrderBlocks(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + count = CountOrderBlocks(); + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iZone = orderBlocks[i]; + passedDir = iZone.GetDirection(); + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // Bullish OrderBlock ... + int FilterBullishOrderBlocks( + XCOrderBlock *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasBullishOrderBlocks(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + passedDir = X_DIRECTION_BULLISH; + count = CountBullishOrderBlocks(); + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iZone = bullishOrderBlocks[i]; + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // Bearish OrderBlock ... + int FilterBearishOrderBlocks( + XCOrderBlock *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasBearishOrderBlocks(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + passedDir = X_DIRECTION_BEARISH; + count = CountBearishOrderBlocks(); + for (int i = 0; i < count; i++) + { + // + XCOrderBlock *iZone = bearishOrderBlocks[i]; + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // FairValueGap ... + int FilterFairValueGaps( + XCFVG *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasFairValueGaps(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + count = CountFairValueGaps(); + for (int i = 0; i < count; i++) + { + // + XCFVG *iZone = fairValueGaps[i]; + passedDir = iZone.GetDirection(); + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // Bullish FairValueGap ... + int FilterBullishFairValueGaps( + XCFVG *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasBullishFairValueGaps(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + passedDir = X_DIRECTION_BULLISH; + count = CountBullishFairValueGaps(); + for (int i = 0; i < count; i++) + { + // + XCFVG *iZone = bullishFairValueGaps[i]; + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + // Bearish FairValueGap ... + int FilterBearishFairValueGaps( + XCFVG *&dest[], + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int result = 0; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + Clean(dest); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasBearishFairValueGaps(); + if (!has) + { + return result; + } + + // + XOHCL passedBar; + ENUM_X_DIRECTION passedDir = X_DIRECTION_NONE; + passedDir = X_DIRECTION_BEARISH; + count = CountBearishFairValueGaps(); + for (int i = 0; i < count; i++) + { + // + XCFVG *iZone = bearishFairValueGaps[i]; + + // + // Check Started State ... + if (startState == XZONE_STATE_PASSED || + startState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isStarted = iZone.IsStarted( + passedDir, + passedBar, + isBodyOut, + forPeriod // + ); + + // + bool isPassed = + startState == XZONE_STATE_FAILED + ? !isStarted + : !forceStartedBodyOut + ? isStarted + : isStarted && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Activation State ... + if (activeState == XZONE_STATE_PASSED || + activeState == XZONE_STATE_FAILED) + { + // + bool isBodyIn = false; + bool isActivated = iZone.IsActivated( + passedDir, + passedBar, + isBodyIn, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + activeState == XZONE_STATE_FAILED + ? !isActivated + : !forceActivatedBodyIn + ? isActivated + : isActivated && + isBodyIn; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Break State ... + if (breakState == XZONE_STATE_PASSED || + breakState == XZONE_STATE_FAILED) + { + // + bool isBodyOut = false; + bool isBreaked = iZone.IsBreaked( + passedDir, + passedBar, + isBodyOut, + forceStartedBodyOut, + forPeriod // + ); + + // + bool isPassed = + breakState == XZONE_STATE_FAILED + ? !isBreaked + : !forceBreakedBodyOut + ? isBreaked + : isBreaked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Work State ... + if (workState == XZONE_STATE_PASSED || + workState == XZONE_STATE_FAILED) + { + // + bool ignoreActivation = activeState != XZONE_STATE_PASSED; + + // + bool isBodyOut = false; + bool isWorked = iZone.IsWorked( + passedDir, + passedBar, + isBodyOut, + ignoreActivation, + forceStartedBodyOut, + forceActivatedBodyIn, + forPeriod // + ); + + // + bool isPassed = + workState == XZONE_STATE_FAILED + ? !isWorked + : !forceWorkedBodyOut + ? isWorked + : isWorked && + isBodyOut; + + // + passedBar.Clean(); + if (!isPassed) + { + continue; + } + } + + // + // Check Filtered Zone Doesn't Exists ... + has = FindIndex( + idx, + iZone, + dest // + ); + if (has) + { + // + passedBar.Clean(); + continue; + } + + // + Add( + iZone, + dest // + ); + + // + // End For ... + } + + // + result = ArraySize(dest); + + // + return result; + } + + // + void Filter( + XPOIState &dest, + ENUM_TIMEFRAMES forPeriod = NULL, + // + // Start ... + ENUM_XZONE_STATE startState = XZONE_STATE_PASSED, + bool forceStartedBodyOut = false, + // + // Activation ... + ENUM_XZONE_STATE activeState = XZONE_STATE_FAILED, + bool forceActivatedBodyIn = false, + // + // Breaktion ... + ENUM_XZONE_STATE breakState = XZONE_STATE_FAILED, + bool forceBreakedBodyOut = false, + // + // Works ... + ENUM_XZONE_STATE workState = XZONE_STATE_FAILED, + bool forceWorkedBodyOut = false // + ) + { + // + int count = 0; + bool has = false; + + // + dest.Clean(); + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + has = IsValid() && + HasChild(); + if (!has) + { + return; + } + + // + dest = this; + + // + // Support Zones ... + FilterSupportZones( + dest.supportZones, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + // Resistance Zones ... + FilterResistanceZones( + dest.resistanceZones, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + // Supply Zones ... + FilterSupplyZones( + dest.supplyZones, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + // Demand Zones ... + FilterDemandZones( + dest.demandZones, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + // OrderBlocks ... + FilterOrderBlocks( + dest.orderBlocks, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + // Bullish OrderBlocks ... + FilterBullishOrderBlocks( + dest.bullishOrderBlocks, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + // Bearish OrderBlocks ... + FilterBearishOrderBlocks( + dest.bearishOrderBlocks, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + // FairValueGaps ... + FilterFairValueGaps( + dest.fairValueGaps, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + // Bullish FairValueGaps ... + FilterBullishFairValueGaps( + dest.bullishFairValueGaps, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + // Bearish FairValueGaps ... + FilterBearishFairValueGaps( + dest.bearishFairValueGaps, + forPeriod, + startState, + forceStartedBodyOut, + activeState, + forceActivatedBodyIn, + breakState, + forceBreakedBodyOut, + workState, + forceWorkedBodyOut // + ); + + // + } + + // +}; + +// +// Extensions Functions ... +// + +/** + * Update to Time of Specifiex Collection ... + * + * @param items: XOBFVG instance Collection ... + * @param value: datetime ... + */ +void SpecifiedUpdateTo( + XOBFVG &items[], + datetime value = NULL // +) +{ + // + value = NormalizeTime(value); + + // + int count = ArraySize(items); + bool has = HasChild(items); + if (!has) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + items[i].UpdateTo(value); + } +} + +/** + * Extract Box Zone's of Specified OBFVG ... + * + * @param box: XBoxZone instance, represent result ... + * @param obfvg: XOBFVG instance, specified Model ... + * + * @return ( bool ) + */ +bool ToZoneBox( + XBoxZone &box, + XOBFVG &obfvg // +) +{ + // + bool result = false; + + // + box.Clean(); + + // + // Check Model Validation ... + result = obfvg.IsValid(); + if (!result) + { + return result; + } + + // + // Retrieve Model Main Fair Value Gap ... + XCFVG *fvg; + result = obfvg.GetMainFVG(fvg); + if (!result) + { + // + box.Clean(); + ZeroMemory(fvg); + + // + return result; + } + + // + bool isBullish = fvg.IsBullish(); + + // + // Retrieve Main Fair Value Gap's Started Bar ... + XOHCL startedBar; + bool isBodyOut = false; + bool isStarted = fvg.IsStarted( + fvg.GetDirection(), + startedBar, + isBodyOut // + ); + result = isStarted; + if (!result) + { + // + box.Clean(); + ZeroMemory(fvg); + startedBar.Clean(); + + // + return result; + } + + // + // Converts Main Fair Value Gaps to Box ... + result = ToBox( + box, + fvg // + ); + if (!result) + { + // + box.Clean(); + ZeroMemory(fvg); + startedBar.Clean(); + + // + return result; + } + + // + // Validate Start Bar ... + result = + isBullish + ? startedBar.high >= fvg.Upper() && + startedBar.low < fvg.Upper() + : startedBar.low <= fvg.Lower() && + startedBar.high > fvg.Lower(); + if (!result) + { + // + box.Clean(); + ZeroMemory(fvg); + startedBar.Clean(); + + // + return result; + } + + // + // Update Box using Started Bar ... + box.lower = isBullish + ? box.lower + : startedBar.low; + box.upper = + isBullish + ? startedBar.high + : box.upper; + + // + box.from = startedBar.NextAt(); + + // + // Check Box Validation ... + result = box.IsValid(); + if (!result) + { + box.Clean(); + } + + // + // Cleanup Resources ... + ZeroMemory(fvg); + startedBar.Clean(); + + // + return result; +} + +/** + * Converts to XBoxZone ... + * + * @return ( bool ) + */ +bool ToBox( + XBoxZone &box, + XOBFVG &item // +) +{ + // + bool result = false; + + // + result = ToBox( + box, + item.ob // + ); + + // + return result; +} + +/** + * Converts to XBoxZone ... + * + * @return ( bool ) + */ +int ToBox( + XOBFVG &source[], + XBoxZone &dest[] // +) +{ + // + int result = 0; + + // + Clean(dest); + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XOBFVG iZone = source[i]; + + // + XBoxZone iBox; + bool hasBox = ToBox( + iBox, + iZone // + ); + + // + if (hasBox) + { + // + AddRef( + iBox, + dest // + ); + } + + // + iBox.Clean(); + iZone.Clean(); + } + + // + result = ArraySize(dest); + + // + return result; +} + +// +// +// + +/** + * Get Oldest Index ... + * + * @param source: XOBFVG instance Reference Collection ... + * + * @return ( int ) + */ +int GetOldest( + XOBFVG &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone tmpBoxes[]; + int boxesCount = ToBox( + source, + tmpBoxes // + ); + if (!IsValidSize(boxesCount)) + { + // + Clean(tmpBoxes); + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < boxesCount; i++) + { + // + XBoxZone iBox = tmpBoxes[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.from > iBox.from; + if (canSet) + { + // + result = i; + selected = iBox; + } + } + + // + Clean(tmpBoxes); + selected.Clean(); + + // + return result; +} + +/** + * Get Youngest Index ... + * + * @param source: XOBFVG instance Reference Collection ... + * + * @return ( int ) + */ +int GetYoungest( + XOBFVG &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone tmpBoxes[]; + int boxesCount = ToBox( + source, + tmpBoxes // + ); + if (!IsValidSize(boxesCount)) + { + // + Clean(tmpBoxes); + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < boxesCount; i++) + { + // + XBoxZone iBox = tmpBoxes[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.from < iBox.from; + if (canSet) + { + // + result = i; + selected = iBox; + } + } + + // + Clean(tmpBoxes); + selected.Clean(); + + // + return result; +} + +/** + * Get Highest Index ... + * + * @param source: XOBFVG instance Reference Collection ... + * + * @return ( int ) + */ +int GetHighest( + XOBFVG &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone tmpBoxes[]; + int boxesCount = ToBox( + source, + tmpBoxes // + ); + if (!IsValidSize(boxesCount)) + { + // + Clean(tmpBoxes); + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < boxesCount; i++) + { + // + XBoxZone iBox = tmpBoxes[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.upper < iBox.upper; + if (canSet) + { + // + result = i; + selected = iBox; + } + } + + // + Clean(tmpBoxes); + selected.Clean(); + + // + return result; +} + +/** + * Get Lowest Index ... + * + * @param source: XOBFVG instance Reference Collection ... + * + * @return ( int ) + */ +int GetLowest( + XOBFVG &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XBoxZone tmpBoxes[]; + int boxesCount = ToBox( + source, + tmpBoxes // + ); + if (!IsValidSize(boxesCount)) + { + // + Clean(tmpBoxes); + return result; + } + + // + XBoxZone selected; + for (int i = 0; i < boxesCount; i++) + { + // + XBoxZone iBox = tmpBoxes[i]; + + // + bool canSet = + !selected.IsValid() + ? true + : selected.lower > iBox.lower; + if (canSet) + { + // + result = i; + selected = iBox; + } + } + + // + Clean(tmpBoxes); + selected.Clean(); + + // + return result; +} + +bool AddIfNotExists( + XOBFVG &item, + XOBFVG &items[] // +) +{ + // + bool result = false; + + // + result = item.IsValid(); + if (!result) + { + return result; + } + + // + int before = ArraySize(items); + + // + int idx = FindIndex( + item, + items // + ); + bool has = IsValidIndex(idx); + result = !has; + if (!result) + { + return result; + } + + // + AddRef( + item, + items // + ); + + // + int after = ArraySize(items); + + // + result = after > before; + + // + return result; +} + +int AddIfNotExists( + XOBFVG &items[], + XOBFVG &sources[] // +) +{ + // + int result = 0; + + // + bool has = HasChild(items); + if (!has) + { + return result; + } + + // + int before = ArraySize(sources); + + // + int count = ArraySize(items); + for (int i = 0; i < count; i++) + { + // + has = AddIfNotExists( + items[i], + sources // + ); + } + + // + int after = ArraySize(sources); + + // + result = after > before; + + // + return result; +} + +// diff --git a/BKPS/14031218/Libraries/x-saherelm.x-trade.lib.ex5 b/BKPS/14031218/Libraries/x-saherelm.x-trade.lib.ex5 new file mode 100644 index 0000000..3cb7ff3 Binary files /dev/null and b/BKPS/14031218/Libraries/x-saherelm.x-trade.lib.ex5 differ diff --git a/BKPS/14031218/Libraries/x-saherelm.x-trade.lib.mq5 b/BKPS/14031218/Libraries/x-saherelm.x-trade.lib.mq5 new file mode 100644 index 0000000..0c515c8 --- /dev/null +++ b/BKPS/14031218/Libraries/x-saherelm.x-trade.lib.mq5 @@ -0,0 +1,6199 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Seriallize Library +// --------------------------------------- +// Name: XTradeLib +// Description: All models related to Trade ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Libraries/x-saherelm.common.lib.mq5" +#include + +// +// Definitions ... + +// +// a List of Used Tokens ... + +// +// Common ... +string XIDToken = "ID"; +string XTicketToken = "TK"; +string XModeToken = "MD"; +string XTypeToken = "TY"; +string XPeriodToken = "PR"; +string XProviderToken = "PRV"; +string XProfitToken = "PF"; + +// +string XTPToken = "TP"; +string XSLToken = "SL"; +string XTimeToken = "TM"; +string XEntryToken = "EN"; +string XVolumeToken = "VL"; +string XSymbolToken = "SMBL"; + +// +string XSupportToken = "SP"; +string XEQMSupportToken = "EQM"; +string XEQPToken = "EQP"; + +// +string XSLTrailToken = "SLT"; + +// +string XActionToken = "A"; + +// +string XDirectionalToken = "D"; +string XINDirectionalToken = "IND"; + +// +string XRecoveryToken = "XRCV"; + +// +// Available Order Modes ... +enum ENUM_X_ORDER_MODES +{ + X_ORDER_MODE_NOTHING, // Nothing + X_ORDER_MODE_MARKET, // Market Order + X_ORDER_MODE_STOP, // Pending Stop Order + X_ORDER_MODE_LIMIT, // Pending Limit Order + X_ORDER_MODE_STOP_LIMIT, // Pending Stop Limit Order +}; + +// +string ToString(ENUM_X_ORDER_MODES value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_ORDER_MODE_MARKET: + result = "Market"; + break; + + // + case X_ORDER_MODE_LIMIT: + result = "Limit"; + break; + + // + case X_ORDER_MODE_STOP: + result = "Stop"; + break; + + // + case X_ORDER_MODE_STOP_LIMIT: + result = "StopLimit"; + break; + } + + // + return result; +} + +// +// Select Positions Type ... +enum ENUM_X_POSITION_SELECT_METHODS +{ + X_POSITION_SELECT_NONE, // None + X_POSITION_SELECT_MAX, // Max + X_POSITION_SELECT_MIN, // Min + X_POSITION_SELECT_BOTH, // Min and Max + X_POSITION_SELECT_ALL, // All +}; + +// +// Signal Execution Result ... +// note that some of them must be handles in +// EA's ... +enum ENUM_X_SIGNAL_EXECUTION_RESULT +{ + // + X_SIGNAL_EXECUTION_UNKNOWN, // Unknown + X_SIGNAL_EXECUTION_SUCCEED, // Succed + X_SIGNAL_EXECUTION_FAILED_SPREAD, // Spread more than Max Allowed + X_SIGNAL_EXECUTION_FAILED_NOT_ALLOWED, // Not Allowed Trade Type + X_SIGNAL_EXECUTION_FAILED_NO_EQUITY, // No Equity for Trade + X_SIGNAL_EXECUTION_FAILED_PRICE_ERROR, // Price Error + X_SIGNAL_EXECUTION_FAILED_PREV_PROFIT_ERROR, // Prev Profit Error + X_SIGNAL_EXECUTION_FAILED_MAX_REACHED, // Max Allowed Positions Reached + X_SIGNAL_EXECUTION_FAILED_DELAY_NOT_PASSED, // Same Positions Delay Not Passed + X_SIGNAL_EXECUTION_FAILED_INVALID_PARAMS, // Invalid Params +}; + +// +// Available Guard Action ... +enum ENUM_X_GUARD_ACTIONS +{ + X_GUARD_ACTION_NOTHING, // Nothing + X_GUARD_ACTION_HEDGE, // Hedge + X_GUARD_PARTIAL_CLOSE, // Partial Close + X_GUARD_ACTION_TRAIL_STOP, // Trail StopLoss + X_GUARD_ACTION_FORCE_CLOSE, // Force Close + X_GUARD_ACTION_ADD_SUPPORT_SIGNAL, // Add Support Signal + X_GUARD_ACTION_CANCEL_PENDING_ORDERS, // Cancel Pending Orders +}; + +// +enum ENUM_X_POSITION_TYPES +{ + X_POSITION_TYPE_NONE = 0, + X_POSITION_TYPE_ALL = 1, + X_POSITION_TYPE_LONG = 2, + X_POSITION_TYPE_SHORT = 3, +}; + +// +string ToString(ENUM_X_POSITION_TYPES value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_POSITION_TYPE_ALL: + result = "All"; + break; + + // + case X_POSITION_TYPE_NONE: + result = "NONE"; + break; + + // + case X_POSITION_TYPE_SHORT: + result = "Short"; + break; + + // + case X_POSITION_TYPE_LONG: + result = "Long"; + break; + } + + // + return result; +} + +// +bool IsLong(ENUM_X_POSITION_TYPES value) +{ + return value == X_POSITION_TYPE_LONG; +} + +// +bool ToPositionType( + ENUM_POSITION_TYPE &dest, + ENUM_X_POSITION_TYPES source // +) +{ + // + bool result = false; + + // + result = source == X_POSITION_TYPE_LONG || + source == X_POSITION_TYPE_SHORT; + if (!result) + { + return result; + } + + // + dest = + source == X_POSITION_TYPE_LONG + ? POSITION_TYPE_BUY + : POSITION_TYPE_SELL; + + // + return result; +} + +// +ENUM_X_POSITION_TYPES ToPositionType(ENUM_POSITION_TYPE value) +{ + return IsLong(value) + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_SHORT; +} + +// +ENUM_X_POSITION_TYPES 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 ... + +// +struct XRR +{ + // + double tps[]; + + // + double sl; + double entry; + + // + string prefix; + string symbol; + datetime time; + ENUM_TIMEFRAMES period; + + // + ENUM_X_POSITION_TYPES type; + + // + // Constructor ... + XRR() + { + Clean(); + } + + // + // Tools ... + + // + void Clean() + { + // + sl = 0; + entry = 0; + + // + time = NULL; + prefix = NULL; + period = NULL; + symbol = NULL; + + // + type = X_POSITION_TYPE_NONE; + + // + Clean(tps); + } + + // + bool Init( + string _symbol, + ENUM_TIMEFRAMES _period, + double _sl, + double _entry, + ENUM_X_POSITION_TYPES _type, + string _prefix = NULL // + ) + { + // + bool result = false; + + // + result = + _sl > 0 && + _entry > 0 && + IsValid(_symbol) && + IsValid(_period) && + _type != X_POSITION_TYPE_ALL && + _type != X_POSITION_TYPE_NONE && + (_type == X_POSITION_TYPE_LONG + ? _entry > _sl + : _entry < _sl); + if (!result) + { + return result; + } + + // + Default(); + + // + sl = _sl; + type = _type; + entry = _entry; + symbol = _symbol; + period = _period; + prefix = _prefix; + + // + time = TimeCurrent(); + + // + result = IsValid(); + + // + return result; + } + + // + void Default() + { + // + Add( + 1.0, + tps // + ); + Add( + 1.5, + tps // + ); + Add( + 2.0, + tps // + ); + Add( + 3.0, + tps // + ); + Add( + 4.0, + tps // + ); + Add( + 5.0, + tps // + ); + Add( + 6.0, + tps // + ); + } + + // + bool IsValid() + { + // + bool result = false; + + // + result = + sl > 0 && + entry > 0 && + IsValid(time) && + IsValid(symbol) && + IsValid(period) && + IsValidSize(ArraySize(tps)) && + type != X_POSITION_TYPE_ALL && + type != X_POSITION_TYPE_NONE && + (type == X_POSITION_TYPE_LONG + ? entry > 0 + : entry < sl); + + // + return result; + } + + // + string GetTag() + { + // + string result = NULL; + + // + if (!IsValid()) + { + // + result = GetTypeName(this); + return result; + } + + // + string sep = "_"; + + // + result = + GetTypeName(this) + sep + (IsValid(prefix) ? prefix + sep : "") + symbol + sep + ToString(period) + sep + ToFormatString(time) + sep + ToString(type); + + // + return result; + } +}; + +// +// Model an Open Position ... +struct XPosition +{ + // + // Props ... + + // + // Magic Number ... + ulong magic; + + // + // Ticket ID ... + ulong ticket; + + // + // Tradinng Symbol ... + string symbol; + + // + // Trading Period ... + ENUM_TIMEFRAMES period; + + // + // Position Type ... + ENUM_POSITION_TYPE type; + + // + // Take Profit ... + double tp; + + // + // Stop Loss ... + double sl; + + // + // Position Current Profit ... + double profit; + + // + // Position Open Price ... + double entry; + + // + // Current Symbol Price ... + double price; + + // + // Position Swap ... + double swap; + + // + // Position Commission ... + double commission; + + // + // Volume ... + double volume; + + // + // Position Open Time ... + datetime openAt; + + // + // Sifnal Provider ... + string provider; + + // + // Position Comment ... + string comment; + + // + // Constructor ... + XPosition() + { + Clean(); + } + + // + // Initializers ... + + bool ByIndex(int index) + { + // + bool result = false; + + // + static CPositionInfo mPositionInfo; + + // + result = mPositionInfo.SelectByIndex(index); + if (!result) + { + return result; + } + + // + ulong mTicket = mPositionInfo.Ticket(); + + // + result = ByTicket(mTicket); + + // + return result; + } + + bool ByTicket(ulong mTicket) + { + // + bool result = false; + + // + static CPositionInfo mPositionInfo; + + // + result = mPositionInfo.SelectByTicket(mTicket); + if (!result) + { + return result; + } + + // + swap = mPositionInfo.Swap(); + magic = mPositionInfo.Magic(); + openAt = mPositionInfo.Time(); + sl = mPositionInfo.StopLoss(); + ticket = mPositionInfo.Ticket(); + symbol = mPositionInfo.Symbol(); + tp = mPositionInfo.TakeProfit(); + profit = mPositionInfo.Profit(); + volume = mPositionInfo.Volume(); + comment = mPositionInfo.Comment(); + entry = mPositionInfo.PriceOpen(); + type = mPositionInfo.PositionType(); + price = mPositionInfo.PriceCurrent(); + commission = mPositionInfo.Commission(); + + // + period = ExtractPeriod(comment); + provider = ExtractProvider(comment); + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + magic = 0; + ticket = 0; + tp = 0; + sl = 0; + swap = 0; + entry = 0; + price = 0; + profit = 0; + volume = 0; + openAt = 0; + commission = 0; + + // + type = NULL; + period = NULL; + + // + symbol = NULL; + comment = NULL; + provider = NULL; + + // + ZeroMemory(this); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsValid(symbol) && + NotEmpty(ticket) + // + ; + + // + return result; + } + + // + // Retrieve Entry Price ... + double GetEntry() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetEntry( + symbol, + type + // + ); + + // + return result; + } + + // + // Retrieve Exit ... + double GetExit() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetExit( + symbol, + type + // + ); + + // + return result; + } + + // + // Get Spread by Point ... + double GetSpread() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = PriceToPoint(GetSpread(symbol)); + + // + return result; + } + + // + double GetPointsValue() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetPoints(symbol); + + // + return result; + } + + // + double GetProfitInPoint() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + double tickSize = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE); // Tick size + double tickValue = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE); // Tick value + double pointSize = SymbolInfoDouble(symbol, SYMBOL_POINT); // Point size + double pointValue = tickValue * pointSize / tickSize; // Point value + + // + result = profit / (volume * tickValue); + + // + return result; + } + + // + // Find Risk ... + double GetRisk() + { + // + double result = 0; + + // + if (!IsValid()) + { + return 0; + } + + // + result = MathAbs(entry - sl); + + // + return result; + } + + // + // Find Reward ... + double GetReward() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = MathAbs(tp - entry); + + // + return result; + } + + // + double GetRewardInPoint() + { + // + double result = 0; + + // + result = GetReward() / GetPoints(); + + // + return result; + } + + // + // Find Risk Reward Ratio ... + double GetRiskRewardRatio() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetReward() / GetRisk(); + + // + return result; + } + + // + // Calculate TP Levels ... + int CalculateTPLevels(double &tps[]) + { + + // + int result = 0; + + // + Clean(tps); + + // + bool isValid = IsValid(); + if (!isValid) + { + return result; + } + + // + double risk = GetRisk(); + int r2r = (int)GetRiskRewardRatio(); + bool isLong = IsLong(type); + for (int i = 0; i < r2r; i++) + { + // + double iValue = + isLong + ? entry + risk + (i * risk) + : entry - risk - (i * risk); + // + Add( + iValue, + tps // + ); + } + + // + result = ArraySize(tps); + + // + return result; + } + + // + // Calculate Reached TP Levels ... + void CalculateReahedTP( + double &reachedLevel, + double &reachedPrice // + ) + { + // + reachedLevel = -1; + reachedPrice = 0; + double tps[]; + bool isLong = IsLong(type); + double exitPrice = GetExit(); + int tpLevels = CalculateTPLevels(tps); + if (!IsValidSize(tpLevels) || exitPrice <= 0) + { + return; + } + + // + for (int i = 0; i < tpLevels - 1; i++) + { + // + double cTP = tps[i]; + double nTP = tps[i + 1]; + + // + bool isReached = + isLong + ? exitPrice > cTP && + exitPrice < nTP + : exitPrice < cTP && + exitPrice > nTP; + if (isReached) + { + // + reachedLevel = i + 1; + reachedPrice = cTP; + } + } + } + + // + // Calculate Age ... + int GetAge( + ENUM_TIMEFRAMES mPeriod // Calculate Age based on this period + ) + { + return GetAge(this, mPeriod); + } + + // + // Check this instance is Same os Given instance or not ... + bool IsSameAs( + const XPosition &value // instance for Compare + ) + { + // + bool result = false; + + // + result = + // + type == value.type && + magic == value.magic && + entry == value.entry && + ticket == value.ticket && + volume == value.volume && + symbol == value.symbol && + provider == value.provider + // + ; + + // + return result; + } + + // + // Find index in a Collection ... + int FindIndex( + const XPosition &values[] // Collection to Find + ) + { + // + return FindIndex( + this, + values + // + ); + } + + // + // Check Items Passed Specific Filters or not ... + bool IsFiltersPassed( + string mSymbol = NULL, // Trading Symbol + string mProvider = NULL, // Signal Provider + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Timeframe + ENUM_X_POSITION_TYPES mType = NULL, // Long (Buy), Short (Sell) + ulong mMagic = NULL, // Magic Number + bool mFilterByMagic = true // Get Only Self Open Positions + ) + { + // + bool result = false; + + // + result = + // + // Magic Filter ... + IsMagicFilterPassed( + mMagic, + mFilterByMagic, + this + // + ) + // + && + // + // Symbol Filter ... + IsSymbolFilterPassed( + mSymbol, + this + // + ) + // + && + // + // Provider Filter ... + IsProviderFilterPassed( + mProvider, + this + // + ) + // + && + // + // Period Filter ... + IsPeriodFilterPassed( + mPeriod, + this + // + ) + // + && + // + // Type Filter ... + IsTypeFilterPassed( + mType, + this + // + ) + // + ; + + // + return result; + } +}; + +// +// Model a Signal ... +struct XSignal +{ + // + // Props ... + + // + ulong positionId; // if Executed this filled ... + + // + datetime time; // Issue Time ... + + // + double tp; // Take Profit ... + double sl; // Stop Loss ... + double entry; // Exntry or Execution Price ... + double volume; // Position Volume ... + + // + string symbol; // Trading Symbol ... + string comment; // Comment ... + string provider; // Signaller ... + + // + ENUM_TIMEFRAMES period; // Trading TimeFrame ... + ENUM_POSITION_TYPE type; // Long (Buy) or Short (Sell) ... + ENUM_X_ORDER_MODES mode; // Execution Mode ... + + // + XSignal supports[]; // a Collecion of Support Signals ... + + // + int pushers; // Signal Pushers ... + string conditions; // Signal Conditions ... + + // + // Additional ... + + // + // TP ... + double fullTPLevel; // Full TP ... + double partialCloseMultiplier; // Amount of Partial Close ... + double partialCloseOnTPLevel; // Do Partial Close on TP Level ... + + // + // RF ... + double tpLevelForBreakEven; // TP Level for Break Even ... + bool riskFreeOnBreakEven; // Risk Free Signal On Break Even ... + + // + // Traget ... + double targets[]; // Force Risk Free On Targets ... + bool ignoreEAVolume; // Ignore EA Volume ... + + // + // SL Trail ... + bool trailSL; // Do SL Trail ... + double trailSLStartOnReachTPLevel; // Start SL Trail After Reached TP Level ... + + // + // 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 PrepareComplex( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + ENUM_POSITION_TYPE mType, // Long (Buy) or Short (Sell) + ENUM_X_ORDER_MODES mMode, // Execution Mode + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + // + // TP ... + double mFullTPLevel = 0, // Full TP Level + double mPartialCloseOnTPLevel = 0, // Partial Close On TP Level + double mPartialCloseMultiplier = 0, // Partial Close Multiplier + // + // RF ... + bool mRiskFreeOnBreakEven = false, // Risk Free Signal On Break Even ... + double mTpLevelForBreakEven = 0, // TP Level for Break Even ... + // + // SL Trail ... + bool mTrailSL = false, // Trail SL + double mTrailSLStartOnReachTPLevel = 0 // Trail SL Starts after Reached TP Level + ) + { + // + bool result = false; + + // + // Validate Args ... + result = + // + // Common ... + mSL > 0 && + mEntry > 0 && + mVolume > 0 && + IsValid(mSymbol) && + IsValid(mPeriod) && + IsValid(mProvider) && + mMode != X_ORDER_MODE_NOTHING + // + && + // + // TP ... + mFullTPLevel > 0 + // + ; + if (!result) + { + return result; + } + + // + // Prepare Regular Signal Values ... + double _risk = MathAbs(mEntry - mSL); + double _reward = _risk * mFullTPLevel; + + // + bool isLong = IsLong(mType); + + // + sl = mSL; + type = mType; + mode = mMode; + entry = mEntry; + symbol = mSymbol; + period = mPeriod; + volume = mVolume; + provider = mProvider; + fullTPLevel = mFullTPLevel; + tp = isLong + ? mEntry + _reward + : mEntry - _reward; + + // + result = Normalize(); + if (!result) + { + return result; + } + + // + // Calculate Other Conditions ... + + // + bool canPartialClose = + // + mPartialCloseOnTPLevel > 0 && + mPartialCloseMultiplier > 0 && + mPartialCloseOnTPLevel < mFullTPLevel + // + ; + if (canPartialClose) + { + // + partialCloseOnTPLevel = mPartialCloseOnTPLevel; + partialCloseMultiplier = mPartialCloseMultiplier; + } + + // + bool canRFOnBEP = + // + mRiskFreeOnBreakEven && + mTpLevelForBreakEven > 0 + // + ; + if (canRFOnBEP) + { + // + riskFreeOnBreakEven = mRiskFreeOnBreakEven; + tpLevelForBreakEven = mTpLevelForBreakEven; + } + + // + bool canTrailSL = + // + mTrailSL && + mTrailSLStartOnReachTPLevel > 0 && + mTrailSLStartOnReachTPLevel < mFullTPLevel + // + ; + if (canTrailSL) + { + // + trailSL = mTrailSL; + trailSLStartOnReachTPLevel = mTrailSLStartOnReachTPLevel; + } + + // + result = IsValid(); + + // + return result; + } + + // + bool PrepareLong( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + ENUM_X_ORDER_MODES mMode, // Execution Mode + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + return Prepare( + mSymbol, + mProvider, + mPeriod, + POSITION_TYPE_BUY, + mMode, + mEntry, + mVolume, + mSL, + mTP + // + ); + } + + // + bool PrepareShort( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + ENUM_X_ORDER_MODES mMode, // Execution Mode + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + return Prepare( + mSymbol, + mProvider, + mPeriod, + POSITION_TYPE_SELL, + mMode, + mEntry, + mVolume, + mSL, + mTP + // + ); + } + + // + // Market Mode ... + + // + bool PrepareMarketLong( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + return PrepareLong( + mSymbol, + mProvider, + mPeriod, + X_ORDER_MODE_MARKET, + mEntry, + mVolume, + mSL, + mTP + // + ); + } + + // + bool PrepareMarketShort( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + return PrepareShort( + mSymbol, + mProvider, + mPeriod, + X_ORDER_MODE_MARKET, + mEntry, + mVolume, + mSL, + mTP + // + ); + } + + // + // Stop Mode ... + + // + bool PrepareStopLong( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + return PrepareLong( + mSymbol, + mProvider, + mPeriod, + X_ORDER_MODE_STOP, + mEntry, + mVolume, + mSL, + mTP + // + ); + } + + // + bool PrepareStopShort( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + return PrepareShort( + mSymbol, + mProvider, + mPeriod, + X_ORDER_MODE_STOP, + mEntry, + mVolume, + mSL, + mTP + // + ); + } + + // + // Limit Mode ... + + // + bool PrepareLimitLong( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + return PrepareLong( + mSymbol, + mProvider, + mPeriod, + X_ORDER_MODE_LIMIT, + mEntry, + mVolume, + mSL, + mTP + // + ); + } + + // + bool PrepareLimitShort( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + double mEntry, // Entry Price + double mVolume, // Volume + double mSL = 0, // Stop Loss + double mTP = 0 // Take Profit + ) + { + // + return PrepareShort( + mSymbol, + mProvider, + mPeriod, + X_ORDER_MODE_LIMIT, + mEntry, + mVolume, + mSL, + mTP + // + ); + } + + // + // Generate Opposit Direction ... + bool GenerateOpposit( + XSignal &mSignal // Oppsoit Signal + ) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + ENUM_POSITION_TYPE mType = 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(targets); + ignoreEAVolume = false; + + // + trailSL = false; + riskFreeOnBreakEven = false; + + // + fullTPLevel = 0; + tpLevelForBreakEven = 0; + partialCloseOnTPLevel = 0; + partialCloseMultiplier = 0; + trailSLStartOnReachTPLevel = 0; + + // + Clean(supports); + + // + ZeroMemory(this); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsValid(period) && + IsValid(symbol) && + NotEmpty(volume) && + NotEmpty(entry) + // + ; + + // + if (!result) + { + return result; + } + + // + return result; + } + + // + // DO All Calculations and Normalizations ... + bool Normalize() + { + // + bool result = false; + + // + // Normalizations ... + symbol = NormalizeSymbol(symbol); + period = NormalizePeriod(period); + + // + time = NormalizeTime(time); + + // + sl = NormalizePrice(sl, symbol); + tp = NormalizePrice(tp, symbol); + entry = NormalizePrice(entry, symbol); + volume = NormalizeVolume(volume, symbol); + + // + result = IsValid(); + + // + return result; + } + + // + // Check Signal Executed or not ... + bool IsExecuted() + { + // + bool result = false; + + // + result = + // + IsValid() && + NotEmpty(positionId) + // + ; + + // + return result; + } + + // + // Generate Comment for Signal ... + string GenerateComment() + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + if (IsValid(provider)) + { + // + // Generate Provider Tag ... + result += GenerateProviderTag(provider); + } + + // + if (IsValid(period)) + { + // + // Generate Period Tag ... + result += GeneratePeriodTag(period); + } + + // + return result; + } + + // + int GetAge() + { + // + return GetAge( + this, + this.period // + ); + } + + // + // Find Risk ... + double GetRisk() + { + // + double result = 0; + + // + if (!IsValid()) + { + return 0; + } + + // + result = MathAbs(entry - sl); + + // + return result; + } + + // + // Find Reward ... + double GetReward() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = MathAbs(tp - entry); + + // + return result; + } + + // + // Find Risk Reward Ratio ... + double GetRiskRewardRatio() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetReward() / GetRisk(); + + // + return result; + } + + // + // Check Can Partial Close on Specified TP Level ... + bool CanPartialClose() + { + // + bool result = false; + + // + result = + IsValid() && + fullTPLevel > 0 && + partialCloseOnTPLevel > 0 && + partialCloseMultiplier > 0 && + partialCloseOnTPLevel < fullTPLevel; + + // + return result; + } + + // + // Check Can Risk Free On Break Even Point ... + bool CanRiskFreeOnBreakEvenPoint() + { + // + bool result = false; + + // + result = + IsValid() && + riskFreeOnBreakEven && + tpLevelForBreakEven > 0; + + // + return result; + } + + // + // Check Can Trail SL ... + bool CanTrailSL() + { + // + bool result = false; + + // + result = + IsValid() && + trailSL && + fullTPLevel > 0 && + trailSLStartOnReachTPLevel > 0 && + trailSLStartOnReachTPLevel < fullTPLevel; + + // + return result; + } + + // + string GetTag() + { + // + string result = NULL; + + // + result = "XSignal_" + + symbol + "_" + + ToString(period) + "_" + + ToString(type) + "_" + + ToString(sl) + "_" + + ToString(tp) + "_" + + ToString(entry); + + // + return result; + } + + // + // Retrieve String Representation of Signal ... + string ToString() + { + // + string result = NULL; + + // + result = + // + ToString("Symbol", symbol) + + ToString("Period", period) + + ToString("Provider", provider) + + ToString("Type", type) + + ToString("Mode", mode) + + ToString("Volume", volume) + + ToString("Entry", entry) + + ToString("TP", tp) + + ToString("SL", sl) + + ToString("Time", time) + + ToString("Comment", comment) + + // + "" + // + ; + + // + return result; + } +}; + +// +// Model an Order ... +struct XOrder +{ + // + // Time of order placement ... + datetime setupAt; + + // + // Time of order expiration ... + datetime expiredAt; + + // + // Time of order execution or cancellation ... + datetime executedAt; + + // + // Order type ... + ENUM_ORDER_TYPE type; + + // + // Order state ... + ENUM_ORDER_STATE state; + + // + // Type of execution by remainder ... + ENUM_ORDER_TYPE_FILLING filling; + + // + // Order lifetime ... + ENUM_ORDER_TYPE_TIME lifetime; + + // + // Order ticket ... + ulong ticket; + + // + // Magic Number ... + long magic; + + // + // Position id, that is placed on order, + // when it is executed. Each executed order invokes a + // deal, that opens new or changes existing + // position. Id of that position is placed on + // executed order in this moment. + long positionId; + + // + // Initial volume on order placement ... + double initialVolume; + + // + // Unfilled volume ... + double currentVolume; + + // + // Price, specified in the order ... + double openPrice; + + // + // Current price by order symbol ... + double currentPrice; + + // + // Price of placing Limit order when StopLimit order is triggered ... + double stopLimitPrice; + + // + // Take Profit level ... + double tp; + + // + // Stop Loss level ... + double sl; + + // + // Trading Symbol ... + string symbol; + + // + // Signal Provider ... + string provider; + + // + // Order Comment ... + string comment; + + // + ENUM_TIMEFRAMES period; + + // + // Constructor ... + XOrder() + { + Clean(); + } + + // + // Initializers ... + bool ByIndex( + int index // Fill By Index ... + ) + { + // + bool result = false; + + // + int ordersCount = OrdersTotal(); + if (ordersCount <= 0) + { + return result; + } + + // + static COrderInfo mOrderInfo; + + // + result = mOrderInfo.SelectByIndex(index); + if (!result) + { + return result; + } + + // + // Reading Order Info ... + magic = mOrderInfo.Magic(); + sl = mOrderInfo.StopLoss(); + tp = mOrderInfo.TakeProfit(); + ticket = mOrderInfo.Ticket(); + openPrice = mOrderInfo.PriceOpen(); + positionId = mOrderInfo.PositionId(); + currentPrice = mOrderInfo.PriceCurrent(); + initialVolume = mOrderInfo.VolumeInitial(); + currentVolume = mOrderInfo.VolumeCurrent(); + stopLimitPrice = mOrderInfo.PriceStopLimit(); + + // + symbol = mOrderInfo.Symbol(); + comment = mOrderInfo.Comment(); + + // + state = mOrderInfo.State(); + type = mOrderInfo.OrderType(); + lifetime = mOrderInfo.TypeTime(); + filling = mOrderInfo.TypeFilling(); + + // + setupAt = mOrderInfo.TimeSetup(); + executedAt = mOrderInfo.TimeDone(); + expiredAt = mOrderInfo.TimeExpiration(); + + // + period = ExtractPeriod(comment); + provider = ExtractProvider(comment); + + // + result = IsValid(); + + // + return result; + } + + // + // Retrieve Specific History Order ... + bool HistoryByIndex( + int index // Fill By Index ... + ) + { + // + bool result = false; + + // + int ordersCount = HistoryOrdersTotal(); + if (ordersCount <= 0) + { + return result; + } + + // + static CHistoryOrderInfo mOrderInfo; + + // + result = mOrderInfo.SelectByIndex(index); + if (!result) + { + return result; + } + + // + // Reading Order Info ... + magic = mOrderInfo.Magic(); + sl = mOrderInfo.StopLoss(); + tp = mOrderInfo.TakeProfit(); + ticket = mOrderInfo.Ticket(); + openPrice = mOrderInfo.PriceOpen(); + positionId = mOrderInfo.PositionId(); + currentPrice = mOrderInfo.PriceCurrent(); + initialVolume = mOrderInfo.VolumeInitial(); + currentVolume = mOrderInfo.VolumeCurrent(); + stopLimitPrice = mOrderInfo.PriceStopLimit(); + + // + symbol = mOrderInfo.Symbol(); + comment = mOrderInfo.Comment(); + + // + state = mOrderInfo.State(); + type = mOrderInfo.OrderType(); + lifetime = mOrderInfo.TypeTime(); + filling = mOrderInfo.TypeFilling(); + + // + setupAt = mOrderInfo.TimeSetup(); + executedAt = mOrderInfo.TimeDone(); + expiredAt = mOrderInfo.TimeExpiration(); + + // + period = ExtractPeriod(comment); + provider = ExtractProvider(comment); + + // + result = IsValid(); + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + tp = 0; + sl = 0; + magic = 0; + ticket = 0; + positionId = 0; + openPrice = 0; + currentPrice = 0; + initialVolume = 0; + currentVolume = 0; + stopLimitPrice = 0; + + // + setupAt = NULL; + expiredAt = NULL; + executedAt = NULL; + + // + symbol = NULL; + comment = NULL; + provider = NULL; + + // + type = NULL; + state = NULL; + period = NULL; + filling = NULL; + lifetime = NULL; + + // + ZeroMemory(this); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsValid(symbol) && + NotEmpty(ticket) && + NotEmpty(positionId) + // + ; + + // + return result; + } + + // + // Calculate Age ... + int GetAge( + ENUM_TIMEFRAMES mPeriod // Calculate Age based on this period + ) + { + return GetAge(this, mPeriod); + } + + // + // Check this instance is Same os Given instance or not ... + bool IsSameAs( + const XOrder &value // instance for Compare + ) + { + // + bool result = false; + + // + result = + // + type == value.type && + state == value.state && + magic == value.magic && + ticket == value.ticket && + symbol == value.symbol && + provider == value.provider && + positionId == value.positionId + // + ; + + // + return result; + } + + // + // Find index in a Collection ... + int FindIndex( + const XOrder &values[] // Collection to Find + ) + { + // + return FindIndex( + this, + values + // + ); + } + + // + // Check Items Passed Specific Filters or not ... + bool IsFiltersPassed( + string mSymbol = NULL, // Trading Symbol + string mProvider = NULL, // Signal Provider + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Timeframe + ENUM_X_POSITION_TYPES mType = NULL, // Long (Buy), Short (Sell) + ENUM_ORDER_STATE mState = NULL, // Order State + ulong mMagic = NULL, // Magic Number + bool mFilterByMagic = true // Get Only Self Open Positions + ) + { + // + bool result = false; + + // + result = + // + // Magic Filter ... + IsMagicFilterPassed( + mMagic, + mFilterByMagic, + this + // + ) + // + && + // + // Symbol Filter ... + IsSymbolFilterPassed( + mSymbol, + this + // + ) + // + && + // + // Provider Filter ... + IsProviderFilterPassed( + mProvider, + this + // + ) + // + && + // + // Period Filter ... + IsPeriodFilterPassed( + mPeriod, + this + // + ) + // + && + // + // Type Filter ... + IsTypeFilterPassed( + mType, + this + // + ) + // + && + // + // State Filter ... + IsStateFilterPassed( + mState, + this + // + ) + // + ; + + // + return result; + } +}; + +// +// Model a Deal ... +struct XDeal +{ + // + // the ID of the Expert Advisor, that executed the deal ... + ulong magic; + + // + // the ID of position, in which the deal was involved ... + ulong positionId; + + // + // Ticket ... + ulong ticket; + + // + // the name of the deal symbol ... + string symbol; + + // + // order by which the deal is executed ... + ulong order; + + // + // the time of deal execution ... + datetime time; + + // + // Deal price ... + double price; + + // + // the financial result of the deal (in deposit currency) ... + double profit; + + // + // the amount of swap when position is closed ... + double swap; + + // + // the amount of commission of the deal ... + double commission; + + // + // the volume of deal ... + double volume; + + // + // the deal comment ... + string comment; + + // + string provider; + + // + ENUM_TIMEFRAMES period; + + // + // the deal type ... + // ------------------------------------------------------------------ + // DEAL_TYPE_BUY => Buy ... + // DEAL_TYPE_SELL => Sell ... + // DEAL_TYPE_BUY_CANCELED => Canceled buy deal ... + // There can be a situation when a previously executed buy deal is canceled. In this case, + // the type of the previously executed deal (DEAL_TYPE_BUY) is changed to DEAL_TYPE_BUY_CANCELED, + // and its profit/loss is zeroized. Previously obtained profit/loss is charged/withdrawn using a separated balance operation ... + // + // DEAL_TYPE_SELL_CANCELED => Canceled sell deal ... + // There can be a situation when a previously executed sell deal is canceled. In this case, + // the type of the previously executed deal (DEAL_TYPE_SELL) is changed to DEAL_TYPE_SELL_CANCELED, + // and its profit/loss is zeroized. Previously obtained profit/loss is charged/withdrawn using a separated balance operation + // + // DEAL_TYPE_BALANCE => Balance ... + // DEAL_TYPE_CREDIT => Credit ... + // DEAL_TYPE_CHARGE => Additional charge ... + // DEAL_TYPE_CORRECTION => Correction ... + // DEAL_TAX => Tax charges ... + // DEAL_TYPE_BONUS => Bonus ... + // DEAL_TYPE_INTEREST => Interest rate ... + // DEAL_DIVIDEND => Dividend operations... + // DEAL_DIVIDEND_FRANKED => Franked (non-taxable) dividend operations ... + // DEAL_TYPE_COMMISSION => Additional commission ... + // DEAL_TYPE_COMMISSION_DAILY => Daily commission ... + // DEAL_TYPE_COMMISSION_MONTHLY => Monthly commission ... + // DEAL_TYPE_COMMISSION_AGENT_DAILY => Daily agent commission ... + // DEAL_TYPE_COMMISSION_AGENT_MONTHLY => Monthly agent commission + ENUM_DEAL_TYPE type; + + // + // the deal direction ... + // ---------------------------------- + // DEAL_ENTRY_IN => Entry in ... + // DEAL_ENTRY_OUT => Entry out ... + // DEAL_ENTRY_INOUT => Reverse ... + // DEAL_ENTRY_OUT_BY => Close a position by an opposite one ... + ENUM_DEAL_ENTRY entry; + + // + // deal reson ... + // --------------------- + // DEAL_REASON_SL => The deal was executed as a result of Stop Loss activation ... + // DEAL_REASON_TP => The deal was executed as a result of Take Profit activation ... + // DEAL_REASON_SO => The deal was executed as a result of the Stop Out event ... + // DEAL_REASON_WEB => The deal was executed as a result of activation of an order placed from the web platform ... + // DEAL_REASON_SPLIT => The deal was executed after the split (price reduction) of an instrument, which had an open position during split announcement ... + // DEAL_REASON_CLIENT => The deal was executed as a result of activation of an order placed from a desktop terminal ... + // DEAL_REASON_MOBILE => The deal was executed as a result of activation of an order placed from a mobile application ... + // DEAL_REASON_EXPERT => The deal was executed as a result of activation of an order placed from an MQL5 program, i.e. an Expert Advisor or a script ... + // DEAL_REASON_VMARGIN => The deal was executed after charging the variation margin ... + // DEAL_REASON_ROLLOVER => The deal was executed due to a rollover ... + ENUM_DEAL_REASON reason; + + // + // Constructor ... + XDeal() + { + Clean(); + } + + // + // Initializers ... + bool ByIndex( + int index // Deal Index + ) + { + // + bool result = false; + + // + int dealsCount = HistoryDealsTotal(); + result = dealsCount > 0; + if (!result) + { + return result; + } + + // + static CDealInfo mDealInfo; + + // + result = mDealInfo.SelectByIndex(index); + if (!result) + { + // + return result; + } + + // + // Reading Order Info ... + swap = mDealInfo.Swap(); + magic = mDealInfo.Magic(); + order = mDealInfo.Order(); + ticket = mDealInfo.Ticket(); + time = mDealInfo.Time(); + price = mDealInfo.Price(); + symbol = mDealInfo.Symbol(); + profit = mDealInfo.Profit(); + volume = mDealInfo.Volume(); + comment = mDealInfo.Comment(); + positionId = mDealInfo.PositionId(); + entry = mDealInfo.Entry(); + commission = mDealInfo.Commission(); + type = mDealInfo.DealType(); + reason = (ENUM_DEAL_REASON)HistoryDealGetInteger( + ticket, + DEAL_REASON); + + // + period = ExtractPeriod(comment); + provider = ExtractProvider(comment); + + // + result = IsValid(); + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + magic = 0; + positionId = 0; + ticket = 0; + order = 0; + time = 0; + price = 0; + profit = 0; + swap = 0; + commission = 0; + volume = 0; + + // + symbol = NULL; + comment = NULL; + provider = NULL; + + // + type = NULL; + entry = NULL; + period = NULL; + reason = NULL; + + // + ZeroMemory(this); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsValid(symbol) && + NotEmpty(ticket) && + NotEmpty(positionId) + // + ; + + // + return result; + } + + // + // Calculate Age ... + int GetAge( + ENUM_TIMEFRAMES mPeriod // Calculate Age based on this period + ) + { + return GetAge(this, mPeriod); + } + + // + // Check this instance is Same os Given instance or not ... + bool IsSameAs( + const XDeal &value // instance for Compare + ) + { + // + bool result = false; + + // + result = + // + type == value.type && + magic == value.magic && + entry == value.entry && + reason == value.reason && + ticket == value.ticket && + volume == value.volume && + symbol == value.symbol && + provider == value.provider && + positionId == value.positionId + // + ; + + // + return result; + } + + // + // Find index in a Collection ... + int FindIndex( + const XDeal &values[] // Collection to Find + ) + { + // + return FindIndex( + this, + values + // + ); + } + + // + // Check Items Passed Specific Filters or not ... + bool IsFiltersPassed( + string mSymbol = NULL, // Trading Symbol + string mProvider = NULL, // Signal Provider + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Timeframe + ENUM_DEAL_TYPE mType = NULL, // Deal Type + ENUM_DEAL_ENTRY mEntry = NULL, // Deal Entry + ENUM_DEAL_REASON mReason = NULL, // Deal Reason + ulong mMagic = NULL, // Magic Number + bool mFilterByMagic = true // Get Only Self Open Positions + ) + { + // + bool result = false; + + // + result = + // + // Magic Filter ... + IsMagicFilterPassed( + mMagic, + mFilterByMagic, + this + // + ) + // + && + // + // Symbol Filter ... + IsSymbolFilterPassed( + mSymbol, + this + // + ) + // + && + // + // Provider Filter ... + IsProviderFilterPassed( + mProvider, + this + // + ) + // + && + // + // Period Filter ... + IsPeriodFilterPassed( + mPeriod, + this + // + ) + // + && + // + // Type Filter ... + IsTypeFilterPassed( + mType, + this + // + ) + // + && + // + // Entry Filter ... + IsEntryFilterPassed( + mEntry, + this + // + ) + // + && + // + // Reason Filter ... + IsReasonFilterPassed( + mReason, + this + // + ) + // + ; + + // + return result; + } +}; + +// +// Model OnTrade Event Handler Result on XCTrade Class ... +struct XOnTradeHandlerState +{ + // + bool hasNewDeal; + int newDeals; + + // + bool hasNewOrder; + int newOrders; + + // + bool hasNewPosition; + int newPositions; + + // + bool hasNewHistoryOrder; + int newHistoryOrders; + + // + // Constructor ... + XOnTradeHandlerState() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + hasNewDeal = false; + hasNewOrder = false; + hasNewPosition = false; + hasNewHistoryOrder = false; + + // + newDeals = 0; + newOrders = 0; + newPositions = 0; + newHistoryOrders = 0; + + // + ZeroMemory(this); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + ( + // + hasNewDeal + ? newDeals > 0 + : true + // + ) + // + && + // + ( + // + hasNewOrder + ? newOrders > 0 + : true + // + ) + // + && + // + ( + // + hasNewPosition + ? newPositions > 0 + : true + // + ) + // + && + // + ( + // + hasNewHistoryOrder + ? newHistoryOrders > 0 + : true + // + ) + // + ; + + // + return result; + } +}; + +// +// Model Guard Info ... +struct XGuard +{ + // + string symbol; // Trading Symbol ... + string provider; // Signal Provider ... + ENUM_TIMEFRAMES period; // Trading Timeframe ... + ENUM_X_POSITION_TYPES type; // Position Type ... + ENUM_X_GUARD_ACTIONS action; // Which Action to Do ... + + // + double dblPayLoad; + string strPayload; + + // + // Constructor ... + XGuard() + { + Clean(); + } + + // + // Initialize ... + + // + // Global Initializer ... + bool Init( + string mSymbol, // Trading Symbol ... + ENUM_TIMEFRAMES mPeriod, // Trading Timeframe ... + ENUM_X_GUARD_ACTIONS mAction, // Which Action to Do ... + ENUM_X_POSITION_TYPES mType = NULL, // Position Type ... + string mProvider = NULL, // Signal Provider ... + double mDblPayLoad = NULL, + string mStrPayload = NULL // + ) + { + // + type = mType; + symbol = mSymbol; + period = mPeriod; + action = mAction; + provider = mProvider; + dblPayLoad = mDblPayLoad; + strPayload = mStrPayload; + + // + bool result = IsValid(); + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + symbol = NULL; + provider = NULL; + period = NULL; + action = X_GUARD_ACTION_NOTHING; + + // + strPayload = NULL; + dblPayLoad = EMPTY_VALUE; + + // + ZeroMemory(this); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + action != X_GUARD_ACTION_NOTHING + // + ; + + // + return result; + } +}; + +// +// Model a Position with all of it's Supports ... +struct XPositionPack +{ + // + ulong ticket; // Main Position's Ticket + + // + XPosition position; // Main Position (if Exists) + + // + int supportOrdersCount; // Supported Orders (Untriggered) + int supportPositionsCount; // Supported Positions + + // + XOrder supportOrders[]; // Supported Orders (Untriggered) + XPosition supportPositions[]; // Supported Positions + + // + // Constructor ... + XPositionPack() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + ticket = 0; + + // + position.Clean(); + + // + supportOrdersCount = 0; + supportPositionsCount = 0; + + // + Clean(supportOrders); + Clean(supportPositions); + + // + ZeroMemory(this); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + NotEmpty(ticket) && + ( + // + supportOrdersCount > 0 + ? ArraySize(supportOrders) == supportOrdersCount + : true + // + ) + // + && + // + ( + // + supportPositionsCount > 0 + ? ArraySize(supportPositions) == supportPositionsCount + : true + // + ) + // + ; + + // + return result; + } +}; + +// +// Check Position SL Trails Structure ... +struct XTrail +{ + // + ulong ticket; // Position Ticket ... + ENUM_POSITION_TYPE type; // Type ... + datetime time; // Trail Time ... + double before; // SL Value Before Trailing ... + double after; // SL Value After Trailing ... + int level; // Number of Trails SL ... + double profit; // Profit in SL Time ... + + // + // Constructor ... + XTrail() + { + Clean(); + } + + // + // Tools ... + + // + bool Init( + ulong mTicket, // Ticket + ENUM_POSITION_TYPE mType, // Type + double mProfit, // Profit + double mBefore, // Before + double mAfter // After + ) + { + // + Clean(); + + // + type = mType; + after = mAfter; + ticket = mTicket; + before = mBefore; + profit = mProfit; + + // + level++; + + // + time = TimeCurrent(); + + // + return IsValid(); + } + + // + bool Update( + double mSl, // new SL ... + double mProfit // Profit + ) + { + // + bool result = false; + + // + time = TimeCurrent(); + + // + double cAfter = after; + after = mSl; + before = cAfter; + profit = mProfit; + + // + level++; + + // + result = IsValid(); + + // + return result; + } + + // + string GenerateTag() + { + // + string result = NULL; + + // + string ticketLevelStr = ToString(ticket) + "," + ToString(level); + + // + result = Surround( + XSLTrailToken, + ticketLevelStr // + ); + + // + return result; + } + + // + // Cleanup ... + void Clean() + { + // + ticket = 0; + time = 0; + before = 0; + after = 0; + level = 0; + + // + ZeroMemory(this); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + ticket > 0 && + time > 0 && + level > 0 + // + ; + + // + return result; + } +}; + +// +struct XSymbolPositions +{ + // + string symbol; + + // + double profit; + double volume; + + // + double longsProfit; + double longSupportsProfit; + + // + double shortsProfit; + double shortSupportsProfit; + + // + double longsVolume; + double longSupportsVolume; + + // + double shortsVolume; + double shortSupportsVolume; + + // + double requiredProfitForHedge; + + // + XPosition longs[]; + XPosition shorts[]; + XPosition supports[]; + XPosition positions[]; + XPosition longSupports[]; + XPosition shortSupports[]; + + // + bool forceHedge; + + // + XSymbolPositions() + { + Clean(); + } + + // + bool Update( + double mMinProfitPerTrade, + double mMinProfitPerVolumeFactor // + ) + { + // + bool result = false; + + // + bool hasChild = HasChild(); + if (!hasChild) + { + return result; + } + + // + XPosition _supports[]; + XPosition _positions[]; + + // + XPosition _tmp[]; + + // + Copy( + positions, + _tmp // + ); + + // + Clean(positions); + + // + int tmpsCount = ArraySize(_tmp); + for (int i = 0; i < tmpsCount; i++) + { + // + XPosition iPosition = _tmp[i]; + + // + bool isSupport = IsSupport(iPosition.comment); + if (!isSupport) + { + // + AddRef( + iPosition, + _positions // + ); + } + else + { + // + AddRef( + iPosition, + _supports // + ); + } + } + + // + Clean(_tmp); + + // + Copy( + _positions, + positions // + ); + Clean(_positions); + + // + // Extract Types ... + ExtractPositions( + positions, + longs, + shorts // + ); + + // + Copy( + _supports, + supports // + ); + Clean(_supports); + + // + // Extract Types ... + ExtractPositions( + supports, + longSupports, + shortSupports // + ); + + // + int numOfLongs = 0; + int numOfShorts = 0; + CountPositions( + positions, + numOfLongs, + longsProfit, + longsVolume, + numOfShorts, + shortsProfit, + shortsVolume // + ); + + // + numOfLongs = 0; + numOfShorts = 0; + CountPositions( + supports, + numOfLongs, + longSupportsProfit, + longSupportsVolume, + numOfShorts, + shortSupportsProfit, + shortSupportsVolume // + ); + + // + XPosition _allPositions[]; + Copy( + positions, + _allPositions, + false // + ); + Copy( + supports, + _allPositions, + false // + ); + + // + profit = longsProfit + shortsProfit + longSupportsProfit + shortSupportsProfit; + volume = longsVolume + shortsVolume + longSupportsVolume + shortSupportsVolume; + requiredProfitForHedge = SpecifiedCalculateRequiredProfitForHedge( + _allPositions, + mMinProfitPerTrade, + mMinProfitPerVolumeFactor // + ); + + // + Clean(_allPositions); + + // + result = true; + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + symbol = NULL; + forceHedge = false; + + // + profit = 0; + longsProfit = 0; + shortsProfit = 0; + + // + volume = 0; + longsVolume = 0; + shortsVolume = 0; + + // + requiredProfitForHedge = 0; + + // + Clean(longs); + Clean(shorts); + Clean(positions); + + // + ZeroMemory(this); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = IsValid(symbol); + + // + return result; + } + + // + // Has Child ... + bool HasChild() + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int count = Count(); + result = IsValidSize(count); + + // + return result; + } + + // + // Count ... + int Count() + { + return ArraySize(positions); + } + + // + int CountSupports() + { + return ArraySize(supports); + } + + // + int CountLongs() + { + return ArraySize(longs); + } + + // + int CountShorts() + { + return ArraySize(shorts); + } + + // + int CountLongSupports() + { + return ArraySize(longSupports); + } + + // + int CountShortSupports() + { + return ArraySize(shortSupports); + } + + // + int GetOldest( + XPosition &_oldest, // + ENUM_POSITION_TYPE _type // + ) + { + // + int result = -1; + + // + bool isLong = IsLong(_type); + + // + int count = + isLong + ? CountLongs() + : CountShorts(); + if (!IsValidSize(count)) + { + return result; + } + + // + if (isLong) + { + // + result = GetOldest( + _oldest, + longs // + ); + } + else + { + // + result = GetOldest( + _oldest, + shorts // + ); + } + + // + return result; + } + + // + int GetYoungest( + XPosition &_youngest, // + ENUM_POSITION_TYPE _type // + ) + { + // + int result = -1; + + // + bool isLong = IsLong(_type); + + // + int count = + isLong + ? CountLongs() + : CountShorts(); + if (!IsValidSize(count)) + { + return result; + } + + // + if (isLong) + { + // + result = GetYoungest( + _youngest, + longs // + ); + } + else + { + // + result = GetYoungest( + _youngest, + shorts // + ); + } + + // + return result; + } + + // + int GetMaxInProfit( + XPosition &_position, + ENUM_POSITION_TYPE _type // + ) + { + // + int result = -1; + + // + bool isLong = IsLong(_type); + + // + int count = + isLong + ? CountLongs() + : CountShorts(); + if (!IsValidSize(count)) + { + return result; + } + + // + if (isLong) + { + // + result = FindMaxProfitIndex( + longs // + ); + + // + if (IsValidIndex(result)) + { + _position = longs[result]; + } + } + else + { + // + result = FindMaxProfitIndex( + shorts // + ); + + // + if (IsValidIndex(result)) + { + _position = shorts[result]; + } + } + + // + return result; + } + + // + int GetMinInProfit( + XPosition &_position, + ENUM_POSITION_TYPE _type // + ) + { + // + int result = -1; + + // + bool isLong = IsLong(_type); + + // + int count = + isLong + ? CountLongs() + : CountShorts(); + if (!IsValidSize(count)) + { + return result; + } + + // + if (isLong) + { + // + result = FindMinProfitIndex( + longs // + ); + + // + if (IsValidIndex(result)) + { + _position = longs[result]; + } + } + else + { + // + result = FindMinProfitIndex( + shorts // + ); + + // + if (IsValidIndex(result)) + { + _position = shorts[result]; + } + } + + // + return result; + } + + // + int GetMaxInDrawdown( + XPosition &_position, + ENUM_POSITION_TYPE _type // + ) + { + // + int result = -1; + + // + bool isLong = IsLong(_type); + + // + int count = + isLong + ? CountLongs() + : CountShorts(); + if (!IsValidSize(count)) + { + return result; + } + + // + if (isLong) + { + // + result = FindMaxInDrawdownIndex( + longs // + ); + + // + if (IsValidIndex(result)) + { + _position = longs[result]; + } + } + else + { + // + result = FindMaxInDrawdownIndex( + shorts // + ); + + // + if (IsValidIndex(result)) + { + _position = shorts[result]; + } + } + + // + return result; + } + + // + int GetMinInDrawdown( + XPosition &_position, + ENUM_POSITION_TYPE _type // + ) + { + // + int result = -1; + + // + bool isLong = IsLong(_type); + + // + int count = + isLong + ? CountLongs() + : CountShorts(); + if (!IsValidSize(count)) + { + return result; + } + + // + if (isLong) + { + // + result = FindMinInDrawdownIndex( + longs // + ); + + // + if (IsValidIndex(result)) + { + _position = longs[result]; + } + } + else + { + // + result = FindMinInDrawdownIndex( + shorts // + ); + + // + if (IsValidIndex(result)) + { + _position = shorts[result]; + } + } + + // + return result; + } + + // +}; + +// +struct XSymbolLastPosition +{ + // + string symbol; + string provider; + datetime time; + + // + XSymbolLastPosition() + { + Clean(); + } + + // + // Tools ... + + void Clean() + { + // + time = NULL; + symbol = NULL; + provider = NULL; + + // + ZeroMemory(this); + } +}; + +// +// an Structure for Holding Positions Data ... +struct XTradeData +{ + // + datetime time; // Issue Time (Open Position) + string symbol; // Trading Symbol + double entry; // Entry Price + double volume; // Volume + string provider; // Signaller + ENUM_TIMEFRAMES period; // Trading Timeframe + ENUM_X_POSITION_TYPES type; // Position Type + + // + ulong ticket; // Position Ticket + double swap; // Swap + double profit; // Profit on Close + double commission; // Commission + double maxDrawdown; // Max Position Drawdown + string message; // Close Reason + datetime endTime; // End Time + + // + XSignal signal; // Signal Object + int pushers; // Signal Pushers + string conditions; // Signal Conditions + + // + // Constructor ... + void XTradeInfo() + { + Clean(); + } + + // + // Filling Trade Handler ... + bool Fill(XSignal &_signal) + { + // + bool result = false; + + // + Clean(); + + // + // Check Signal Validation ... + result = _signal.IsValid(); + if (!result) + { + return result; + } + + // + signal = _signal; + time = _signal.time; + entry = _signal.entry; + symbol = _signal.symbol; + volume = _signal.volume; + period = _signal.period; + pushers = _signal.pushers; + provider = _signal.provider; + conditions = _signal.conditions; + type = ToPositionType(_signal.type); + + // + if (_signal.IsExecuted()) + { + ticket = _signal.positionId; + } + + // + return result; + } + + // + // Filling Trade Handler ... + bool Fill(XPosition &_position) + { + // + bool result = false; + + // + Clean(); + + // + // Check Signal Validation ... + result = _position.IsValid(); + if (!result) + { + return result; + } + + // + time = _position.openAt; + symbol = _position.symbol; + entry = _position.entry; + volume = _position.volume; + provider = _position.provider; + period = _position.period; + type = ToPositionType(_position.type); + + // + ticket = _position.ticket; + + // + return result; + } + + // + // Update Data ... + bool Update(XPosition &_position) + { + // + bool result = false; + + // + result = _position.IsValid(); + if (!result) + { + return result; + } + + // + profit = _position.profit; + swap = _position.swap; + + // + if (profit < 0 && + (maxDrawdown == 0 || + MathAbs(profit) > MathAbs(maxDrawdown))) + { + maxDrawdown = profit; + } + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + time = NULL; + type = NULL; + symbol = NULL; + period = NULL; + endTime = NULL; + message = NULL; + provider = NULL; + + // + swap = 0; + entry = 0; + ticket = 0; + profit = 0; + volume = 0; + commission = 0; + maxDrawdown = 0; + + // + signal.Clean(); + + // + ResetTrail(); + ResetRecovery(); + + // + ZeroMemory(this); + } + + // + // Validation ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + ticket > 0 && + IsValid(time) && + IsValid(symbol) && + IsValid(period) + // + ; + + // + return result; + } + + // + // Retrieve Trade Data Age ... + int GetAge() + { + // + int result = -1; + + // + if (!IsValid(symbol) || + !IsValid(time) || + !IsValid(endTime) || + !IsValid(period)) + { + return result; + } + + // + int startIndex = iBarShift( + symbol, + period, + time, + false // + ); + + // + int endIndex = iBarShift( + symbol, + period, + endTime, + false // + ); + + // + result = MathAbs(startIndex - endIndex); + + // + return result; + } + + // + // Check Own of Trade Data ... + // based on Ticket ... + bool IsOwn( + ulong _ticket // + ) + { + // + bool result = false; + + // + result = _ticket == ticket; + + // + return result; + } + + // + // Check Own of Trade Data ... + // based on Symbol/Provider and Period ... + bool IsOwn( + string _symbol, + string _provider, + ENUM_TIMEFRAMES _period, + ENUM_X_POSITION_TYPES _type // + ) + { + // + bool result = false; + + // + result = + // + IsValid(_symbol) && + IsValid(_period) && + IsValid(_provider) && + type != X_POSITION_TYPE_ALL && + type != X_POSITION_TYPE_NONE && + // + type == _type && + period == _period && + symbol == _symbol && + provider == _provider + // + ; + + // + return result; + } + + // + // Data Collector ... + + // + // Get Data File Name ... + string GetFileName() + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + result = + // + symbol + "\\" + + ToString(type) + "\\" + + (profit >= 0 ? "Profit" : "Loss") + "\\" + + ToString(ticket) + "_" + + ToString(period) + "_" + + ToFormatString(time) + // + ; + + // + return result; + } + + // + // Get Signal File Name ... + string GetSignalFileName() + { + // + string result = NULL; + + // + result = + // + symbol + "\\" + + ToString(type) + "\\" + + provider + "_" + + ToFormatString(time) + // + ; + + // + return result; + } + + // + // Convert(s) To String Representation(s) ... + string ToString( + bool onlySignals = false // + ) + { + // + string result = NULL; + + // + int age = GetAge(); + + // + result = + // + (onlySignals + ? "" + : ToString("Ticket", ticket)) + + ToString("Symbol", symbol) + + ToString("Period", period) + + ToString("Entry", entry) + + ToString("Provider", provider) + + ToString("Type", ToString(type)) + + ToString("Time", time) + + // + // Attach Trade Info ... + (onlySignals + ? "" + : + // + "-------------" + "\n" + + ToString("Volume", volume) + + ToString("Profit", profit) + + ToString("Commission", commission) + + ToString("Swap", swap) + + ToString("Max Drawdown", maxDrawdown) + + ToString("End Time", endTime) + + ToString("Age", age) + + ToString("Message", message) + + "" + // + ) + + // + // Attach Conditions to Signals ... + (!onlySignals + ? "" + : + // + "-------------" + "\n" + + ToString("Pushers", pushers) + + "Conditions:" + "\n" + + "-------------" + "\n" + + conditions + + "" + // + ) + + // + "" + // + ; + + // + return result; + } + + // + // There are some Controlling Situations for each Trade + // which implemented here ... + + // + // Trailing Stop .... + + // + bool allowTrailStop; // Specified Position Can Trail Stop or not + bool ignoreTPOnTrail; // Ignore TP when SL Trailed + bool trailBasedOnProfit; // Do Trail Based on Profit Points + int trailLevel; // Last Trail Level + double trailStartInPoint; // Trail Starts When Profits Growing in Point + double trailStepInPoint; // Profit Must Grows Point to do Trailling + + // + // Reset all Trailing Configurations .... + void ResetTrail() + { + // + trailLevel = 0; + trailStepInPoint = 0; + trailStartInPoint = 0; + allowTrailStop = false; + ignoreTPOnTrail = false; + trailBasedOnProfit = false; + } + + // + // Recovery ... + + // + bool allowRecover; // Allow Recover Specified Position + double recoveryTPPoint; // Recovery TP Point + double recoverySLPoint; // Recovery SL Point + int maxAllowedRecover; // Max Allowed Recovery + int recoveryLevel; // Number of Recovery Signals + double recoveryVolumeMultiplier; // Recovery Volume Multiplier + double recoveryVolume; // Next Recovery Positioin Volume + ENUM_X_POSITION_TYPES recoveryLookingType; // Looking for Next Recovery Type + + // + void ResetRecovery() + { + // + allowRecover = false; + recoveryLevel = 0; + recoveryVolume = 0; + recoveryTPPoint = 0; + recoverySLPoint = 0; + recoveryVolumeMultiplier = 0; + recoveryLookingType = X_POSITION_TYPE_NONE; + } + + // +}; + +// +// TypeDefs ... + +// +typedef void (*TOnSignal)(XSignal &signal); + +// +typedef void (*TOnDealsChanged)(int count); + +// +typedef void (*TOnOrdersChanged)(int count); + +// +typedef void (*TOnPositionsChanged)(int count); + +// +typedef void (*TOnStopLoss)(const XDeal &deal); +typedef void (*TOnTakeProfit)(const XDeal &deal); + +// +typedef void (*TOnTradeStateChanged)(const XOnTradeHandlerState &state); + +// +typedef void (*TOnForceClose)( + const ulong ticket, + const XPosition &position, + const string comment // +); + +// +typedef void (*TOnPartialClose)( + const ulong ticket, + const double profit, + const string comment // +); + +// +typedef void (*TOnModify)( + const ulong ticket, + const double profit, + const string comment // +); + +// +// Classes ... + +// +// Tools ... + +// +bool IsValid(ENUM_X_ORDER_MODES value) +{ + return value != X_ORDER_MODE_NOTHING; +} + +// +// Ages ... + +// +// Retrieve a Position Age ... +int GetAge( + XSignal &signal, // Selected Signal ... + ENUM_TIMEFRAMES period = NULL // Dest Time Frame ... +) +{ + // + int result = -1; + + // + if (period == NULL) + { + period = _Period; + } + + // + result = iBarShift( + signal.symbol, + period, + signal.time); + + // + return result; +} + +// +// Retrieve a Position Age ... +int GetAge( + XPosition &position, // Selected Position ... + ENUM_TIMEFRAMES period = NULL // Dest Time Frame ... +) +{ + // + int result = -1; + + // + if (period == NULL) + { + period = _Period; + } + + // + result = iBarShift( + position.symbol, + period, + position.openAt); + + // + return result; +} + +// +// Retrieve an Order Age ... +int GetAge( + XOrder &order, // Selected Order ... + ENUM_TIMEFRAMES period = NULL // Dest Time Frame ... +) +{ + // + int result = -1; + + // + if (period == NULL) + { + period = _Period; + } + + // + result = iBarShift( + order.symbol, + period, + order.setupAt); + + // + return result; +} + +// +// Retrieve a Deal Age ... +int GetAge( + XDeal &deal, // Selected Deal ... + ENUM_TIMEFRAMES period = NULL // Dest Time Frame ... +) +{ + // + int result = -1; + + // + if (period == NULL) + { + period = _Period; + } + + // + result = iBarShift( + deal.symbol, + period, + deal.time); + + // + return result; +} + +// +// Get Oldest Deal ... +int GetOldest( + XDeal &item, // Hold Result ... + XDeal &items[] // Source Array ... +) +{ + // + int result = -1; + + // + int itemsCount = ArraySize(items); + if (itemsCount <= 0) + { + return result; + } + + // + int tmpAge = 0; + XDeal tmpItem; + for (int i = 0; i < itemsCount; i++) + { + // + XDeal iItem = items[i]; + + // + int iAge = GetAge(iItem); + if (iAge > 0 && + (tmpAge == 0 || tmpAge < iAge)) + { + // + tmpAge = iAge; + tmpItem = iItem; + } + } + + // + if (tmpAge > 0) + { + // + result = tmpAge; + item = tmpItem; + } + + // + return result; +} + +// +// Get Youngest Deal ... +int GetYoungest( + XDeal &item, // Hold Result ... + XDeal &items[] // Source Array ... +) +{ + // + int result = -1; + + // + int itemsCount = ArraySize(items); + if (itemsCount <= 0) + { + return result; + } + + // + int tmpAge = 0; + XDeal tmpItem; + for (int i = 0; i < itemsCount; i++) + { + // + XDeal iItem = items[i]; + + // + int iAge = GetAge(iItem); + if (iAge > 0 && + (tmpAge == 0 || tmpAge > iAge)) + { + // + tmpAge = iAge; + tmpItem = iItem; + } + } + + // + if (tmpAge > 0) + { + // + result = tmpAge; + item = tmpItem; + } + + // + return result; +} + +// +// Get Oldest Order ... +int GetOldest( + XOrder &item, // Hold Result ... + XOrder &items[] // Source Array ... +) +{ + // + int result = -1; + + // + int itemsCount = ArraySize(items); + if (itemsCount <= 0) + { + return result; + } + + // + int tmpAge = 0; + XOrder tmpItem; + for (int i = 0; i < itemsCount; i++) + { + // + XOrder iItem = items[i]; + + // + int iAge = GetAge(iItem); + if (iAge > 0 && + (tmpAge == 0 || tmpAge < iAge)) + { + // + tmpAge = iAge; + tmpItem = iItem; + } + } + + // + if (tmpAge > 0) + { + // + result = tmpAge; + item = tmpItem; + } + + // + return result; +} + +// +// Get Youngest Order ... +int GetYoungest( + XOrder &item, // Hold Result ... + XOrder &items[] // Source Array ... +) +{ + // + int result = -1; + + // + int itemsCount = ArraySize(items); + if (itemsCount <= 0) + { + return result; + } + + // + int tmpAge = 0; + XOrder tmpItem; + for (int i = 0; i < itemsCount; i++) + { + // + XOrder iItem = items[i]; + + // + int iAge = GetAge(iItem); + if (iAge > 0 && + (tmpAge == 0 || tmpAge > iAge)) + { + // + tmpAge = iAge; + tmpItem = iItem; + } + } + + // + if (tmpAge > 0) + { + // + result = tmpAge; + item = tmpItem; + } + + // + return result; +} + +// +// Get Oldes Position ... +int GetOldest( + XPosition &item, // Hold Result ... + XPosition &items[] // Source Array ... +) +{ + // + int result = -1; + + // + int itemsCount = ArraySize(items); + if (itemsCount <= 0) + { + return result; + } + + // + int tmpAge = 0; + XPosition tmpItem; + for (int i = 0; i < itemsCount; i++) + { + // + XPosition iItem = items[i]; + + // + int iAge = GetAge(iItem); + if (iAge > 0 && + (tmpAge == 0 || tmpAge < iAge)) + { + // + tmpAge = iAge; + tmpItem = iItem; + } + } + + // + if (tmpAge > 0) + { + // + result = tmpAge; + item = tmpItem; + } + + // + return result; +} + +// +// Get Youngest Position ... +int GetYoungest( + XPosition &item, // Hold Result ... + XPosition &items[] // Source Array ... +) +{ + // + int result = -1; + + // + int itemsCount = ArraySize(items); + if (itemsCount <= 0) + { + return result; + } + + // + int tmpAge = 0; + XPosition tmpItem; + for (int i = 0; i < itemsCount; i++) + { + // + XPosition iItem = items[i]; + + // + int iAge = GetAge(iItem); + if (iAge > 0 && + (tmpAge == 0 || tmpAge > iAge)) + { + // + tmpAge = iAge; + tmpItem = iItem; + } + } + + // + if (tmpAge > 0) + { + // + result = tmpAge; + item = tmpItem; + } + + // + return result; +} + +// +int FindMaxProfitIndex( + XPosition &positions[] // Position Collection +) +{ + // + int result = -1; + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + double max = 0; + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + if (iPosition.profit <= 0) + { + continue; + } + + // + if (max == 0 || + max < iPosition.profit) + { + // + result = i; + max = iPosition.profit; + } + } + + // + return result; +} + +// +int FindMinProfitIndex( + XPosition &positions[] // Position Collection +) +{ + // + int result = -1; + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + double min = 0; + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + if (iPosition.profit <= 0) + { + continue; + } + + // + if (min == 0 || + min > iPosition.profit) + { + // + result = i; + min = iPosition.profit; + } + } + + // + return result; +} + +// +int ExtractInProfitPositions( + XPosition &positions[], // Position Collection + XPosition &inProfits[] // Result +) +{ + // + int result = 0; + + // + Clean(inProfits); + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + if (iPosition.profit > 0) + { + // + AddRef( + iPosition, + inProfits // + ); + } + } + + // + result = ArraySize(inProfits); + + // + return result; +} + +// +int FindMaxInDrawdownIndex( + XPosition &positions[] // Position Collection +) +{ + // + int result = -1; + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + double max = 0; + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + if (iPosition.profit >= 0) + { + continue; + } + + // + if (max == 0 || + MathAbs(max) < MathAbs(iPosition.profit)) + { + // + result = i; + max = iPosition.profit; + } + } + + // + return result; +} + +// +int FindMinInDrawdownIndex( + XPosition &positions[] // Position Collection +) +{ + // + int result = -1; + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + double min = 0; + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + if (iPosition.profit >= 0) + { + continue; + } + + // + if (min == 0 || + min > iPosition.profit) + { + // + result = i; + min = iPosition.profit; + } + } + + // + return result; +} + +// +int ExtractInDrawdownPositions( + XPosition &positions[], // Position Collection + XPosition &inDradowns[] // Result +) +{ + // + int result = 0; + + // + Clean(inDradowns); + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + if (iPosition.profit < 0) + { + // + AddRef( + iPosition, + inDradowns // + ); + } + } + + // + result = ArraySize(inDradowns); + + // + return result; +} + +// +// Check Filters ... + +// +// Magic Filter ... +template +bool IsMagicFilterPassed( + ulong magic, + bool filterByMagic, + T &item + // +) +{ + // + return !filterByMagic + ? true + : !NotEmpty(magic) + ? false + : magic == item.magic; +} + +// +// Symbol Filter ... +template +bool IsSymbolFilterPassed( + string symbol, + T &item + // +) +{ + // + return !IsValid(symbol) + ? true + : symbol == item.symbol; +} + +// +// Provider Filter ... +template +bool IsProviderFilterPassed( + string provider, + T &item + // +) +{ + // + return !IsValid(provider) + ? true + : provider == item.provider; +} + +// +// Period Filter ... +template +bool IsPeriodFilterPassed( + ENUM_TIMEFRAMES period, + T &item + // +) +{ + // + return !IsValid(period) + ? true + : period == item.period; +} + +// +// Type Filter ... +template +bool IsTypeFilterPassed( + ENUM_POSITION_TYPE type, + T &item + // +) +{ + // + bool result = type == item.type; + + // + return result; +} +template +bool IsTypeFilterPassed( + ENUM_X_POSITION_TYPES type, + T &item + // +) +{ + // + bool result = type == NULL || type == X_POSITION_TYPE_ALL + ? true + : ((type == X_POSITION_TYPE_LONG && ((int)item.type == (int)POSITION_TYPE_BUY || (int)item.type == (int)ORDER_TYPE_BUY)) || + (type == X_POSITION_TYPE_SHORT && ((int)item.type == (int)POSITION_TYPE_SELL || (int)item.type == (int)ORDER_TYPE_SELL))); + + // + return result; +} +template +bool IsTypeFilterPassed( + ENUM_ORDER_TYPE type, + T &item + // +) +{ + // + return type == NULL + ? true + : type == item.type; +} +template +bool IsTypeFilterPassed( + ENUM_DEAL_TYPE type, + T &item + // +) +{ + // + return type == NULL + ? true + : type == item.type; +} + +// +// Mode Filter ... +template +bool IsModeFilterPassed( + ENUM_X_ORDER_MODES mode, + T &item + // +) +{ + // + return mode == NULL + ? true + : mode == item.mode; +} + +// +// Entry Filter ... +template +bool IsEntryFilterPassed( + ENUM_DEAL_ENTRY entry, + T &item + // +) +{ + // + return entry == NULL + ? true + : entry == item.entry; +} + +// +// Reason Filter ... +template +bool IsReasonFilterPassed( + ENUM_DEAL_REASON reason, + T &item + // +) +{ + // + return reason == NULL + ? true + : reason == item.reason; +} + +// +// State Filter ... +template +bool IsStateFilterPassed( + ENUM_ORDER_STATE state, + T &item + // +) +{ + // + return state == NULL + ? true + : state == item.state; +} + +// + + +// +// +// Calculate Positions Profit Summary ... +double SpecifiedCalculatePositionsProfit( + XPosition &positions[] // Source +) +{ + // + double result = 0; + + // + int positionsCount = ArraySize(positions); + if (positionsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + result += iPosition.profit; + } + + // + return result; +} + +// +// Calculate Required Profit for Hedging ... +double SpecifiedCalculateRequiredProfitForHedge( + XPosition &positions[], // Source + double mMinProfitPerTrade, + double mMinProfitPerVolumeFactor // +) +{ + // + double result = 0; + + // + int positionsCount = ArraySize(positions); + if (positionsCount <= 0) + { + return result; + } + + // + bool isHedgingEnable = mMinProfitPerTrade > 0 && mMinProfitPerVolumeFactor > 0; + if (!isHedgingEnable) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + if (mMinProfitPerTrade > 0 && mMinProfitPerVolumeFactor > 0) + { + // + result += + ((iPosition.volume / mMinProfitPerVolumeFactor) * + mMinProfitPerTrade) + + (-1 * iPosition.swap); + } + } + + // + return result; +} + +// +bool SpecifiedIsPositionsReadyForHedge( + XPosition &positions[], // Source + double mMinProfitPerTrade, + double mMinProfitPerVolumeFactor // +) +{ + // + double profit = SpecifiedCalculatePositionsProfit(positions); + double requiredProfit = SpecifiedCalculateRequiredProfitForHedge( + positions, + mMinProfitPerTrade, + mMinProfitPerVolumeFactor // + ); + + // + bool result = requiredProfit > 0 + ? profit >= requiredProfit + : profit > requiredProfit; + + // + return result; +} + +// +int FindCoverageDrawdownPosition( + XPosition &position, // In Drawdown Position + XPosition &inProfits[], // In Profit Positions + XPosition &coverage[], // Coverage Positons + double mMinProfitPerTrade, + double mMinProfitPerVolumeFactor // +) +{ + // + int result = 0; + + // + Clean(coverage); + + // + if (!position.IsValid() || position.profit >= 0) + { + return result; + } + + // + int inProfitsCount = ArraySize(inProfits); + if (!IsValidSize(inProfitsCount)) + { + return result; + } + + // + // Copy in Profits to TMP ... + XPosition tmp[]; + Copy( + inProfits, + tmp // + ); + + // + bool isCoverPassed = false; + while (!isCoverPassed || ArraySize(tmp) > 0) + { + // + XPosition max; + int idx = FindMaxProfitIndex(tmp); + if (idx >= 0) + { + // + if (tmp[idx].profit > 0) + { + AddRef( + tmp[idx], + coverage // + ); + + // + ArrayRemove( + tmp, + idx, + 1 // + ); + } + } + + // + // Check Cover Passed ... + XPosition tmpPositions[]; + Copy( + coverage, + tmpPositions // + ); + AddRef( + position, + tmpPositions // + ); + + // + double profits = SpecifiedCalculatePositionsProfit(tmpPositions); + double requiredProfit = SpecifiedCalculateRequiredProfitForHedge( + tmpPositions, + mMinProfitPerTrade, + mMinProfitPerVolumeFactor // + ); + isCoverPassed = profits >= requiredProfit; + if (isCoverPassed) + { + break; + } + + // + if (!isCoverPassed && ArraySize(tmp) == 0) + { + break; + } + } + + // + result = ArraySize(coverage); + + // + return result; +} + +// +// Extract a Collection of Positions SL ... +int ExtractSLs( + XPosition &positions[], + double &sls[] // +) +{ + // + int result = 0; + + // + Clean(sls); + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + if (iPosition.sl > 0) + { + // + Add( + iPosition.sl, + sls // + ); + } + } + + // + result = ArraySize(sls); + + // + return result; +} + +// +// Extract a Colletion of Positions TP ... +int ExtractTPs( + XPosition &positions[], + double &tps[] // +) +{ + // + int result = 0; + + // + Clean(tps); + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + if (iPosition.tp > 0) + { + // + Add( + iPosition.tp, + tps // + ); + } + } + + // + result = ArraySize(tps); + + // + return result; +} + +// +// Retrieve String Representation ... +string ToString(ENUM_X_SIGNAL_EXECUTION_RESULT value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_SIGNAL_EXECUTION_UNKNOWN: + result = "Unknown"; + break; + + // + case X_SIGNAL_EXECUTION_SUCCEED: + result = "Succed"; + break; + + // + case X_SIGNAL_EXECUTION_FAILED_SPREAD: + result = "Spread more than Max Allowed"; + break; + + // + case X_SIGNAL_EXECUTION_FAILED_NOT_ALLOWED: + result = "not Allowed"; + break; + + // + case X_SIGNAL_EXECUTION_FAILED_NO_EQUITY: + result = "No Equity for Trade"; + break; + + // + case X_SIGNAL_EXECUTION_FAILED_PRICE_ERROR: + result = "Price Error"; + break; + + // + case X_SIGNAL_EXECUTION_FAILED_PREV_PROFIT_ERROR: + result = "Previous Position Profit not Passed for Accept Next"; + break; + + // + case X_SIGNAL_EXECUTION_FAILED_MAX_REACHED: + result = "Max Allowed Positions Reached"; + break; + + // + case X_SIGNAL_EXECUTION_FAILED_DELAY_NOT_PASSED: + result = "Min Delay Between to Signal not Passed"; + break; + + // + case X_SIGNAL_EXECUTION_FAILED_INVALID_PARAMS: + result = "Invalid Params"; + break; + } + + // + return result; +} + +// +// Converts Position Type to Order Type ... +ENUM_ORDER_TYPE ToOrderType(ENUM_POSITION_TYPE value) +{ + // + bool isLong = IsLong(value); + + // + ENUM_ORDER_TYPE result = + isLong + ? ORDER_TYPE_BUY + : ORDER_TYPE_SELL; + + // + return result; +} +ENUM_ORDER_TYPE ToOrderType(ENUM_X_POSITION_TYPES value) +{ + // + ENUM_POSITION_TYPE mType = + value == X_POSITION_TYPE_SHORT + ? POSITION_TYPE_SELL + : POSITION_TYPE_BUY; + + // + bool isLong = IsLong(mType); + + // + ENUM_ORDER_TYPE result = + isLong + ? ORDER_TYPE_BUY + : ORDER_TYPE_SELL; + + // + return result; +} + +// +// Tagging ... + +// +// Generate Specified Tag for Using in Comments ... +string GeneratePeriodTag(ENUM_TIMEFRAMES period) +{ + // + string strPeriod = ToString(period); + return Surround( + XPeriodToken, + strPeriod + // + ); +} + +// +// Extract Period from a Tagged string ... +ENUM_TIMEFRAMES ExtractPeriod(string value) +{ + // + ENUM_TIMEFRAMES result = NULL; + + // + string pStr = ParseStringSurrounded( + value, + XPeriodToken + // + ); + if (!IsValid(pStr)) + { + return result; + } + + // + result = ToPeriod(pStr); + + // + return result; +} + +// Generate Specified Tag for Using in Comments ... +string GenerateProviderTag(string provider) +{ + // + return Surround( + XProviderToken, + provider + // + ); +} + +// +// Extract Provider from a Tagged string ... +string ExtractProvider(string value) +{ + // + return ParseStringSurrounded( + value, + XProviderToken + // + ); +} + +// +// Generate Support Comment Tag ... +string GenerateSupportTag(ulong ticket) +{ + // + return Surround( + XSupportToken, + ticket + // + ); +} + +// +// Extract Support Positions from a Tagged string ... +ulong ExtractSupportedTicket(string value) +{ + // + return ParseLongSurrounded( + value, + XSupportToken + // + ); +} + +// +// Extract Support ... +template +int ExtractSupports( + T &source[], + T &dest[] // Result ... +) +{ + // + int result = 0; + + // + Clean(dest); + + // + int sourceCount = ArraySize(source); + if (!IsValidSize(sourceCount)) + { + return result; + } + + // + for (int i = 0; i < sourceCount; i++) + { + // + T iSource = source[i]; + + // + ulong isSupport = ExtractSupportedTicket(iSource.comment) > 0; + ulong iEQMSupport = ExtractEQMSupportedTicket(iSource.comment) > 0; + if (isSupport || iEQMSupport) + { + // + AddRef( + iSource, + dest // + ); + } + } + + // + result = ArraySize(dest); + + // + return result; +} + +// +// Generate EQM Support Comment Tag ... +string GenerateEQMSupportTag(ulong ticket) +{ + // + return Surround( + XEQMSupportToken, + ticket + // + ); +} + +// +// Extract EQM Support Positions from a Tagged string ... +ulong ExtractEQMSupportedTicket(string value) +{ + // + return ParseLongSurrounded( + value, + XEQMSupportToken + // + ); +} + +// +bool IsSupport(string value) +{ + // + bool result = false; + + // + bool isSupport = ExtractSupportedTicket(value) > 0; + bool isEQMSupport = ExtractEQMSupportedTicket(value) > 0; + + // + result = + // + isSupport + // + || + // + isEQMSupport + // + ; + + // + return result; +} + +// +ulong ExtractParentTicket(string value) +{ + // + ulong result = 0; + + // + if (!IsSupport(value)) + { + return result; + } + + // + result = ExtractSupportedTicket(value); + if (result > 0) + { + return result; + } + + // + result = ExtractEQMSupportedTicket(value); + + // + return result; +} + +// +// XRecovery ... + +// +string GenerateRecoveryTag(ulong ticket) +{ + // + return Surround( + XRecoveryToken, + ticket // + ); +} + +// +ulong ExtractRecoveredTicket(string value) +{ + // + return ParseLongSurrounded( + value, + XRecoveryToken // + ); +} + +// +// Extract Recoveries ... +template +int ExtractRecoveries( + T &source[], + T &dest[] // Result ... +) +{ + // + int result = 0; + + // + Clean(dest); + + // + int sourceCount = ArraySize(source); + if (!IsValidSize(sourceCount)) + { + return result; + } + + // + for (int i = 0; i < sourceCount; i++) + { + // + T iSource = source[i]; + + // + ulong isRecovery = ExtractRecoveredTicket(iSource.comment) > 0; + if (isRecovery) + { + // + AddRef( + iSource, + dest // + ); + } + } + + // + result = ArraySize(dest); + + // + return result; +} + +// +// Extract Specified Position's Recoveries ... +int ExtractRecoveries( + ulong ticket, + XPosition &source[], + XPosition &dest[] // Result ... +) +{ + // + int result = 0; + + // + Clean(dest); + + // + int sourceCount = ArraySize(source); + if (!IsValidSize(sourceCount)) + { + return result; + } + + // + for (int i = 0; i < sourceCount; i++) + { + // + XPosition iSource = source[i]; + + // + ulong parentTicket = ExtractRecoveredTicket(iSource.comment); + bool isRecovery = parentTicket > 0; + if (isRecovery && parentTicket == ticket) + { + // + AddRef( + iSource, + dest // + ); + } + } + + // + result = ArraySize(dest); + + // + return result; +} + +// +// SL Trails ... + +// +// Extract SL Trail Level ... +int ExtractSLTrailLevel(string comment) +{ + // + int result = 0; + + // + if (!IsValid(comment)) + { + return result; + } + + // + result = ParseIntSurrounded( + comment, + XSLTrailToken + // + ); + + // + return result; +} + +// +// Generate SL Trail Comment Tag ... +string GenerateSLTrailTag(int level) +{ + // + string result = NULL; + + // + if (level <= 0) + { + return result; + } + + // + result = Surround( + XSLTrailToken, + level + // + ); + + // + return result; +} + +// +// Prepare SL Trail Comment ... +string PrepareSLTrailTag( + const string comment // Original Position Comment ... +) +{ + // + string result = NULL; + + // + int level = 0; + result = comment; + + // + // Check Comment Contains SL Trailing or not ... + int lastTrailLevel = ExtractSLTrailLevel(comment); + if (lastTrailLevel <= 0) + { + level++; + } + else + { + // + level = lastTrailLevel + 1; + string lastLevelStr = GenerateSLTrailTag(lastTrailLevel); + StringReplace( + result, + lastLevelStr, + "" + // + ); + } + + // + // Generate level Comment ... + string levelStr = GenerateSLTrailTag(level); + result += levelStr; + + // + return result; +} + +// +// Count Positions from a Collection ... +void CountPositions( + const XPosition &positions[], + int &longs, + double &longProfits, + double &longVolumes, // + // + int &shorts, + double &shortProfits, + double &shortVolumes // +) +{ + // + longs = 0; + longProfits = 0; + longVolumes = 0; + + // + shorts = 0; + shortProfits = 0; + shortVolumes = 0; + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return; + } + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + bool isLong = IsLong(iPosition.type); + if (isLong) + { + // + longs++; + longProfits += iPosition.profit; + longVolumes += iPosition.volume; + } + else + { + // + shorts++; + shortProfits += iPosition.profit; + shortVolumes += iPosition.volume; + } + } +} + +// +// Extract Positions based On Type ... +void ExtractPositions( + XPosition &positions[], + XPosition &longs[], + XPosition &shorts[] // +) +{ + // + int count = ArraySize(positions); + if (!IsValidSize(count)) + { + return; + } + + // + Clean(longs); + Clean(shorts); + + // + for (int i = 0; i < count; i++) + { + // + XPosition iPosition = positions[i]; + + // + bool isLong = IsLong(iPosition.type); + if (isLong) + { + AddRef( + iPosition, + longs // + ); + } + else + { + AddRef( + iPosition, + shorts // + ); + } + } +} + +// +int FindSymbolIndex( + string mSymbol, + XSymbolPositions &mItems[] // +) +{ + // + int result = -1; + + // + if (!IsValid(mSymbol)) + { + return result; + } + + // + int count = ArraySize(mItems); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XSymbolPositions iItem = mItems[i]; + + // + if (iItem.symbol == mSymbol) + { + // + result = i; + break; + } + } + + // + return result; +} + +// +int ExtractSymbolPositions( + XPosition &positions[], + XSymbolPositions &items[], // Holds Result + double mMinProfitPerTrade, + double mMinProfitPerVolumeFactor // +) +{ + // + int result = 0; + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + Clean(items); + + // + for (int i = 0; i < positionsCount; i++) + { + // + XPosition iPosition = positions[i]; + + // + if (!iPosition.IsValid()) + { + continue; + } + + // + int itemIDX = FindSymbolIndex( + iPosition.symbol, + items // + ); + if (!IsValidIndex(itemIDX)) + { + // + // Add New One ... + XSymbolPositions item; + item.symbol = iPosition.symbol; + + // + AddRef( + item, + items // + ); + itemIDX = FindSymbolIndex(iPosition.symbol, items); + } + + // + AddRef( + iPosition, + items[itemIDX].positions // + ); + } + + // + result = ArraySize(items); + if (IsValidSize(result)) + { + // + for (int i = 0; i < result; i++) + { + // + items[i].Update( + mMinProfitPerTrade, + mMinProfitPerVolumeFactor // + ); + } + } + + // + return result; +} + +// \ No newline at end of file diff --git a/BKPS/14031218/X121SMCEA/Classes/x-121.smc.base.strategy.class.mq5 b/BKPS/14031218/X121SMCEA/Classes/x-121.smc.base.strategy.class.mq5 new file mode 100644 index 0000000..fc5e824 --- /dev/null +++ b/BKPS/14031218/X121SMCEA/Classes/x-121.smc.base.strategy.class.mq5 @@ -0,0 +1,650 @@ +/////////////////////////////////////////////////////// +// +// 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: + // + XCAccount mAccount; + + // + // Constructor(s) ... + XCX121SMCBaseStrategy( + // + // Base ... + string _symbol, // Trading Symbol + ENUM_TIMEFRAMES _period // Trading TimeFrame + ) + { + // + mSymbol = _symbol; + mPeriod = _period; + + // + Init(); + } + + // + // Deconstructor ... + ~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 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 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 ... + * + * @param positions: XPosition instance Collection ... + */ + virtual void HandleTick() + { + // + DoUnwaitedTicksWork(); + + // + // 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; + + // + // 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 any Guards ... + * + * @param guards: X121SMCGuard instance Collection ... + * @param positions: XPosition instance Collection ... + * + * @return ( virtual bool ) + */ + virtual bool HandleGuard( + X121SMCGuard &guards[], + XPosition &positions[] // + ) + { + // + bool result = false; + + // + // Check State ... + if (IsDisabled()) + { + return result; + } + + // + // Check Signalling State ... + if (!AllowLong() && !AllowShort()) + { + return result; + } + + // + // Check Bar Tracker State ... + if (!mGuardBarTracker.CanProcessBar()) + { + return result; + } + + // + // Check For Guards ... + result = CheckGuard( + guards, + positions // + ); + + // + // Waits Until Next Candle if Current Tick has Guard ... + mGuardBarTracker.Waits(); + + // + Clean(positions); + + // + return result; + } + + /** + * 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; + } + + /** + * Check for any Guard Actions ... + * + * @param guards: X121SMCGuard instance Collection ... + * + * @return ( virtual bool ) + */ + virtual bool CheckGuard( + X121SMCGuard &guards[], + const XPosition &positions[] // Positions ... + ) + { + // + bool result = false; + + // + return result; + } + + /** + * Update all Requirements without waiting ... + */ + virtual void DoUnwaitedTicksWork() + { + } + + /** + * 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 ... + + // + MqlTick mLastTick; // Last Issued Tick ... + + // + XBarTracker mBarTracker; // Strategy Bar Tracker ... + XBarTracker mGuardBarTracker; // Strategy Guard Bar Tracker ... + XCBarAnalyser *mBarAnalyser; // Bar Analyser Instance + + // + // Actions ... + + /** + * 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 // + ); + } + } + + // + // 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 ... + + // + // 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); + + // + string symbol = Symbol(); + ENUM_TIMEFRAMES period = Period(); + + // + // Initialize Bar Tracker ... + mBarTracker.Init( + symbol, + period // + ); + + // + // Initialize Guard Bar Tracker ... + mGuardBarTracker.Init( + symbol, + period // + ); + + // + mBarAnalyser = new XCBarAnalyser(); + + // + } + + /** + * De Initialize all Tools ... + */ + void DeInit() + { + // + ZeroMemory(mBarAnalyser); + + // + delete mBarAnalyser; + + // + Clean(mSignalEventHandlers); + + // + Destroy(); + } + + /** + * Reste Bar Tracker ... + */ + void ResetBarTracker() + { + mBarTracker.Clean(); + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14031218/X121SMCEA/Classes/x-121.smc.cobjects.class.mq5 b/BKPS/14031218/X121SMCEA/Classes/x-121.smc.cobjects.class.mq5 new file mode 100644 index 0000000..3f37d87 --- /dev/null +++ b/BKPS/14031218/X121SMCEA/Classes/x-121.smc.cobjects.class.mq5 @@ -0,0 +1,35 @@ +/////////////////////////////////////////////////////// +// +// 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_121_NONE_OBJ +}; + +// +// Implementations ... diff --git a/BKPS/14031218/X121SMCEA/Classes/x-121.smc.ea.panel.class.mq5 b/BKPS/14031218/X121SMCEA/Classes/x-121.smc.ea.panel.class.mq5 new file mode 100644 index 0000000..47d16e0 --- /dev/null +++ b/BKPS/14031218/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/14031218/X121SMCEA/Classes/x-121.smc.market.cycle.helper.class.ex5 b/BKPS/14031218/X121SMCEA/Classes/x-121.smc.market.cycle.helper.class.ex5 new file mode 100644 index 0000000..661b447 Binary files /dev/null and b/BKPS/14031218/X121SMCEA/Classes/x-121.smc.market.cycle.helper.class.ex5 differ diff --git a/BKPS/14031218/X121SMCEA/Classes/x-121.smc.market.cycle.helper.class.mq5 b/BKPS/14031218/X121SMCEA/Classes/x-121.smc.market.cycle.helper.class.mq5 new file mode 100644 index 0000000..da8f365 --- /dev/null +++ b/BKPS/14031218/X121SMCEA/Classes/x-121.smc.market.cycle.helper.class.mq5 @@ -0,0 +1,1082 @@ +/////////////////////////////////////////////////////// +// +// 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_NONE, + X_CYCLE_TRIGGER, + X_CYCLE_DECISION, + X_CYCLE_ANALYSE, + X_CYCLE_VERIFICATION, + X_CYCLE_CONSOLIDATION, + X_CYCLE_VISION, +}; + +string ToString(ENUM_X_CYCLES value) +{ + // + string result = EnumToString(value); + + // + StringReplace(result, "X_CYCLE_", ""); + + // + return result; +} + +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, + PEAK_PIVOT_STARTED, + PEAK_PIVOT_ENDED, + VALE_PIVOT_STARTED, + VALE_PIVOT_ENDED, +}; + +// +class XC121SMCCycleHelper : public XCBase +{ + // + public: + // + // Props ... + + // + // X121 ... + XCX121Helper *mX121Helper; + + // + // POI Detector ... + XCPOIDrawer *mPOIDrawer; + XCPOIDetector *mPOIDetector; + + // + // Bar Analyser + XCBarAnalyser *mBarAnalyser; + + // + // Constructor(s) ... + XC121SMCCycleHelper() + { + Default(); + } + + // + // Deconstructor ... + ~XC121SMCCycleHelper() + { + DeInit(); + } + + // + // Getter/Setter(s) ... + + // + // 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, + int requiredPOIs = 50 // + ) + { + // + bool result = false; + + // + if (requiredPOIs < 0) + { + requiredPOIs = 0; + } + + // + result = IsValid(symbol) && + IsValid(period); + if (!result) + { + return result; + } + + // + mSymbol = symbol; + mPeriod = period; + + // + // X121 ... + mX121Helper = new XCX121Helper(); + result = mX121Helper.Init( + symbol, + period, + x121Inputs // + ); + if (!result) + { + return result; + } + + // + mPOIDetector = new XCPOIDetector( + symbol, + period // + ); + mPOIDetector.MaxRequiredPOIs(requiredPOIs); + + // + int maxLoopbackBars = mPOIDetector.MaxAllowedLoopbackForInit(); + int periodSeconds = PeriodSeconds(period); + if (periodSeconds > PeriodSeconds(PERIOD_M15)) + { + // + int multiplier = periodSeconds / PeriodSeconds(PERIOD_M15); + + // + if (multiplier >= 1) + { + maxLoopbackBars *= 2; + } + } + mPOIDetector.MaxAllowedLoopbackForInit(maxLoopbackBars); + mPOIDetector.Init(); + + // + // Initialize Bar Analyser Class Instance ... + mBarAnalyser = new XCBarAnalyser(); + + // + // Initial and 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); + + // + // Set Chart Style ... + ApplyChartStyle(); + + // + return result; + } + + /** + * Retrieve Symbol ... + * + * @return ( string ) + */ + string GetSymbol() + { + return mSymbol; + } + + /** + * Retrieve TimeFrame (Period) ... + * + * @return ( ENUM_TIMEFRAMES ) + */ + ENUM_TIMEFRAMES GetPeriod() + { + return mPeriod; + } + + /** + * 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 = GetSymbol(); + conditions.period = GetPeriod(); + conditions.time = TimeCurrent(); + + // + // Update(); + + // + result = conditions.IsValid(); + + // + return result; + } + + bool GeneratePVBox( + XBoxZone &box, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + box.Clean(); + box.symbol = GetSymbol(); + box.period = GetPeriod(); + + // + int index = barIndex; + + // + // Peak ... + datetime peaksSameFrom = NULL; + double peak = mX121Helper.xpvHelper.GetPeak(index); + double prevPeak = mX121Helper.xpvHelper.GetPeak(index + 1); + bool startsByPeak = peak == prevPeak; + + // + // Vale ... + datetime valesSameFrom = NULL; + double vale = mX121Helper.xpvHelper.GetVale(index); + double prevVale = mX121Helper.xpvHelper.GetVale(index + 1); + bool startsByVale = vale == prevVale; + + // + bool canBreak = false; + while (!canBreak) + { + // + index++; + + // + datetime cTime = iTime( + box.symbol, + box.period, + index // + ); + + // + // Peak ... + double iPeak = mX121Helper.xpvHelper.GetPeak(index); + + // + // Vale ... + double iVale = mX121Helper.xpvHelper.GetVale(index); + + // + // Start By Peak or Value ... + bool isSame = false; + if (startsByPeak) + { + // + isSame = iPeak == peak; + bool canSetVale = vale == 0 + ? true + : iVale > vale; + if (canSetVale) + { + vale = iVale; + } + } + else if (startsByVale) + { + // + isSame = iVale == vale; + bool canSetPeak = peak == 0 + ? true + : iPeak < peak; + if (canSetPeak) + { + peak = iPeak; + } + } + + // + if (isSame) + { + // + box.from = cTime; + box.upper = peak; + box.lower = vale; + } + else if (IsValid(box.from)) + { + // + // Complete Box ... + box.to = iTime( + box.symbol, + box.period, + barIndex // + ); + + // + box.type = "XPVBox"; + box.dir = startsByPeak + ? X_DIRECTION_BEARISH + : startsByVale + ? X_DIRECTION_BULLISH + : X_DIRECTION_NONE; + } + + // + canBreak = !isSame; + } + + // + result = box.IsValid(); + if (!result) + { + box.Clean(); + } + + // + return result; + } + + // + // Virtuals ... + + /** + * Set Default Properties Values ... + */ + virtual void Default() + { + } + + // + protected: + // + + // + private: + // + // Props ... + string mSymbol; + ENUM_TIMEFRAMES mPeriod; + + // + // Actions ... + + /** + * Release All Resources ... + */ + void DeInit() + { + // + ZeroMemory(mX121Helper); + ZeroMemory(mPOIDetector); + ZeroMemory(mBarAnalyser); + + // + delete mX121Helper; + delete mPOIDetector; + 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_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_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_VOLUME, mVolumesColor); + + // + // For Enabling XCC ... + // ChartSetInteger(chartId, CHART_MODE, mMode); + // 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_CHART_LINE, mLineColor); + } + + // +}; + +// +struct X121SMCStrategySignalProviderData +{ + // + // Props ... + + // + // Decision ... + XPOIState decisionState; + double decisionBullishScore; + double decisionBearishScore; + X121Conditions decisionXConditions; + ENUM_XPOI_EVENTS decisionPoiEvents[]; + XC121SMCCycleHelper *decisionCycleHelper; + ENUM_X_CYCLE_EVENTS decisionCycleEvents[]; + X121SMCCycleConditions decisionConditions; + + // + // Analyse ... + XPOIState analyseState; + double analyseBullishScore; + double analyseBearishScore; + X121Conditions analyseXConditions; + ENUM_XPOI_EVENTS analysePoiEvents[]; + XC121SMCCycleHelper *analyseCycleHelper; + ENUM_X_CYCLE_EVENTS analyseCycleEvents[]; + X121SMCCycleConditions analyseConditions; + + // + // Consolidation ... + XPOIState consolidationState; + double consolidationBullishScore; + double consolidationBearishScore; + X121Conditions consolidationXConditions; + ENUM_XPOI_EVENTS consolidationPoiEvents[]; + XC121SMCCycleHelper *consolidationCycleHelper; + ENUM_X_CYCLE_EVENTS consolidationCycleEvents[]; + X121SMCCycleConditions consolidationConditions; + + // + // Vision ... + XPOIState visionState; + double visionBullishScore; + double visionBearishScore; + X121Conditions visionXConditions; + ENUM_XPOI_EVENTS visionPoiEvents[]; + XC121SMCCycleHelper *visionCycleHelper; + ENUM_X_CYCLE_EVENTS visionCycleEvents[]; + X121SMCCycleConditions visionConditions; + + // + // Constructor ... + X121SMCStrategySignalProviderData() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + // Decision ... + decisionState.Clean(); + decisionBullishScore = 0; + decisionBearishScore = 0; + Clean(decisionPoiEvents); + Clean(decisionCycleEvents); + decisionConditions.Clean(); + decisionXConditions.Clean(); + + // + // Analyse ... + analyseState.Clean(); + analyseBullishScore = 0; + analyseBearishScore = 0; + Clean(analysePoiEvents); + Clean(analyseCycleEvents); + analyseConditions.Clean(); + analyseXConditions.Clean(); + + // + // Consolidation ... + consolidationState.Clean(); + consolidationBullishScore = 0; + consolidationBearishScore = 0; + Clean(consolidationPoiEvents); + Clean(consolidationCycleEvents); + consolidationConditions.Clean(); + consolidationXConditions.Clean(); + + // + // Vision ... + visionState.Clean(); + visionBullishScore = 0; + visionBearishScore = 0; + Clean(visionPoiEvents); + Clean(visionCycleEvents); + visionConditions.Clean(); + visionXConditions.Clean(); + } + + // + void Destroy() + { + // + Clean(); + + // + ZeroMemory(decisionCycleHelper); + ZeroMemory(analyseCycleHelper); + ZeroMemory(consolidationCycleHelper); + ZeroMemory(visionCycleHelper); + + // + ZeroMemory(this); + } + + // + bool IsValid() + { + // + bool result = false; + + // + result = + visionCycleHelper != NULL && + analyseCycleHelper != NULL && + decisionCycleHelper != NULL && + consolidationCycleHelper != NULL; + + // + return result; + } + + // + // Initialize ... + bool Init( + XC121SMCCycleHelper *_decisionCycleHelper, + XC121SMCCycleHelper *_analyseCycleHelper, + XC121SMCCycleHelper *_consolidationCycleHelper, + XC121SMCCycleHelper *_visionCycleHelper // + ) + { + // + bool result = false; + + // + // Validate Cycle Helpers ... + result = + // + _visionCycleHelper != NULL && + _analyseCycleHelper != NULL && + _decisionCycleHelper != NULL && + _consolidationCycleHelper != NULL + // + ; + if (!result) + { + return result; + } + + // + visionCycleHelper = _visionCycleHelper; + analyseCycleHelper = _analyseCycleHelper; + decisionCycleHelper = _decisionCycleHelper; + consolidationCycleHelper = _consolidationCycleHelper; + + // + result = IsValid(); + + // + return result; + } + + // + // Prepare all ... + bool Prepare( + int barIndex = 0, + int loopback = 10 // + ) + { + // + bool result = false; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (loopback < 7) + { + loopback = 7; + } + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + // Decision ... + result = decisionCycleHelper.GetConditions( + decisionCycleEvents, + decisionPoiEvents, + decisionConditions, + barIndex, + loopback // + ); + if (!result) + { + // + Clean(decisionPoiEvents); + Clean(decisionCycleEvents); + + // + decisionConditions.Clean(); + + // + return result; + } + + // + // Analyse ... + result = analyseCycleHelper.GetConditions( + analyseCycleEvents, + analysePoiEvents, + analyseConditions, + barIndex, + loopback // + ); + if (!result) + { + // + Clean(analysePoiEvents); + Clean(decisionPoiEvents); + + // + Clean(analyseCycleEvents); + Clean(decisionCycleEvents); + + // + analyseConditions.Clean(); + decisionConditions.Clean(); + + // + return result; + } + + // + // Consolidation ... + result = consolidationCycleHelper.GetConditions( + consolidationCycleEvents, + consolidationPoiEvents, + consolidationConditions, + barIndex, + loopback // + ); + if (!result) + { + // + Clean(analysePoiEvents); + Clean(decisionPoiEvents); + Clean(consolidationPoiEvents); + + // + Clean(analyseCycleEvents); + Clean(decisionCycleEvents); + Clean(consolidationCycleEvents); + + // + analyseConditions.Clean(); + decisionConditions.Clean(); + consolidationConditions.Clean(); + + // + return result; + } + + // + // Vision ... + result = visionCycleHelper.GetConditions( + visionCycleEvents, + visionPoiEvents, + visionConditions, + barIndex, + loopback // + ); + if (!result) + { + // + Clean(visionPoiEvents); + Clean(analysePoiEvents); + Clean(decisionPoiEvents); + Clean(consolidationPoiEvents); + + // + Clean(visionCycleEvents); + Clean(analyseCycleEvents); + Clean(decisionCycleEvents); + Clean(consolidationCycleEvents); + + // + visionConditions.Clean(); + analyseConditions.Clean(); + decisionConditions.Clean(); + consolidationConditions.Clean(); + + // + return result; + } + + // + // Cycles POI States ... + decisionState = decisionConditions.state; + analyseState = analyseConditions.state; + consolidationState = consolidationConditions.state; + visionState = visionConditions.state; + + // + // Cycle X121Conditions ... + decisionXConditions = decisionConditions.x121Conditions; + analyseXConditions = analyseConditions.x121Conditions; + consolidationXConditions = consolidationConditions.x121Conditions; + visionXConditions = visionConditions.x121Conditions; + + // + // Decision ... + decisionXConditions.GenerateScore( + decisionBullishScore, + decisionBearishScore // + ); + + // + // Analyse ... + analyseXConditions.GenerateScore( + analyseBullishScore, + analyseBearishScore // + ); + + // + // Consolidation ... + consolidationXConditions.GenerateScore( + consolidationBullishScore, + consolidationBearishScore // + ); + + // + // Vision ... + visionXConditions.GenerateScore( + visionBullishScore, + visionBearishScore // + ); + + // + return result; + } + + // + void MaxRequiredPOIs(int value) + { + // + if (!IsValid()) + { + return; + } + + // + visionCycleHelper.mPOIDetector.MaxRequiredPOIs(value); + analyseCycleHelper.mPOIDetector.MaxRequiredPOIs(value); + decisionCycleHelper.mPOIDetector.MaxRequiredPOIs(value); + consolidationCycleHelper.mPOIDetector.MaxRequiredPOIs(value); + } + + // + void MaxAllowedLoopbackForInit(int value) + { + // + if (!IsValid()) + { + return; + } + + // + visionCycleHelper.mPOIDetector.MaxAllowedLoopbackForInit(value); + analyseCycleHelper.mPOIDetector.MaxAllowedLoopbackForInit(value); + decisionCycleHelper.mPOIDetector.MaxAllowedLoopbackForInit(value); + consolidationCycleHelper.mPOIDetector.MaxAllowedLoopbackForInit(value); + } + + // +}; diff --git a/BKPS/14031218/X121SMCEA/Classes/x-121.smc.x-tradehandler.class.mq5 b/BKPS/14031218/X121SMCEA/Classes/x-121.smc.x-tradehandler.class.mq5 new file mode 100644 index 0000000..cae1bce --- /dev/null +++ b/BKPS/14031218/X121SMCEA/Classes/x-121.smc.x-tradehandler.class.mq5 @@ -0,0 +1,4400 @@ +/////////////////////////////////////////////////////// +// +// 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" +#include "../Libraries/x-121.smc.lib.mq5" + +// +// Definitions ... + +// +// Model a Trade Data ... +struct X121SMCTradeData +{ + // + double ask; // Ask Price on Start Time + double bid; // bid Price on Start Time + ulong ticket; // Position Ticket + double swap; // Swap + double profit; // Profit on Close + XSignal signal; // Signal Object + string message; // Message + datetime endTime; // End Time + datetime startTime; // Start Time + double commission; // Commission + string conditions; // Signal Conditions + double maxDrawdown; // Max Position Drawdown + double lastTarget; // Check Last Targetted + double lastTrailedTPLevel; // Hold Last Trailed TP Level + + // + // Constructor ... + X121SMCTradeData() + { + Clean(); + } + + /** + * Initialize Item ... + * + * @param _signal: XSignal instance Reference, Provides Source For Initializaion ... + * + * @return ( bool ) + */ + bool Init(XSignal &_signal) + { + // + bool result = false; + + // + Clean(); + + // + result = _signal.IsValid(); + if (!result) + { + return result; + } + + // + signal = _signal; + + // + result = IsValid(); + + // + return result; + } + + // + // Tools ... + + /** + * Cleaning Up Model ... + */ + void Clean() + { + // + ask = 0; + bid = 0; + swap = 0; + profit = 0; + ticket = 0; + commission = 0; + maxDrawdown = 0; + lastTrailedTPLevel = 0; + + // + endTime = NULL; + message = NULL; + startTime = NULL; + conditions = NULL; + + // + lastTarget = 0; + + // + signal.Clean(); + + // + ZeroMemory(this); + } + + /** + * Validate Model ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + // + signal.IsValid() + // + ; + + // + return result; + } + + /** + * Calculate Model Age ... + * + * @return ( int ) + */ + int GetAge() + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + int startIndex = iBarShift( + GetSymbol(), + GetPeriod(), + startTime, + false // + ); + + // + datetime mEndTime = IsValid(endTime) + ? endTime + : TimeCurrent(); + int endIndex = iBarShift( + GetSymbol(), + GetPeriod(), + mEndTime, + false // + ); + + // + result = MathAbs(startIndex - endIndex); + + // + return result; + } + + // + // Owner Functions ... + + /** + * Check a Ticket is Own to Model or not ... + * + * @param _ticket: ULONG, Position Ticket ... + * + * @return ( bool ) + */ + bool IsOwn( + ulong _ticket // + ) + { + // + bool result = false; + + // + result = IsValid() && + _ticket == ticket; + + // + return result; + } + + /** + * Check Specified Conditions is Own to Model or not ... + * + * @param _symbol: String, Specified Symbol ... + * @param _provider: String, Specified Provider ... + * @param _period: ENUM_TIMEFRAMES member, Specified Signal Period ... + * @param _type: ENUM_X_POSITION_TYPES member, Specified Signal Type ... + * + * @return ( bool ) + */ + bool IsOwnSignalTime( + string _symbol, + string _provider, + ENUM_TIMEFRAMES _period, + ENUM_X_POSITION_TYPES _type, + datetime _time // + ) + { + // + bool result = false; + + // + result = + // + IsValid(_time) && + Time() == _time && + IsValid(_symbol) && + IsValid(_period) && + XType() == _type && + IsValid(_provider) && + GetPeriod() == _period && + GetSymbol() == _symbol && + Provider() == _provider && + XType() != X_POSITION_TYPE_ALL && + XType() != X_POSITION_TYPE_NONE + // + ; + + // + return result; + } + + /** + * Check Specified Conditions is Own to Model or not ... + * + * @param _symbol: String, Specified Symbol ... + * @param _provider: String, Specified Provider ... + * @param _period: ENUM_TIMEFRAMES member, Specified Signal Period ... + * @param _type: ENUM_X_POSITION_TYPES member, Specified Signal Type ... + * + * @return ( bool ) + */ + bool IsOwnStartTime( + string _symbol, + string _provider, + ENUM_TIMEFRAMES _period, + ENUM_X_POSITION_TYPES _type, + datetime _time // + ) + { + // + bool result = false; + + // + result = + // + IsValid(_time) && + IsValid(_symbol) && + IsValid(_period) && + XType() == _type && + IsValid(startTime) && + startTime == _time && + IsValid(_provider) && + GetPeriod() == _period && + GetSymbol() == _symbol && + Provider() == _provider && + XType() != X_POSITION_TYPE_ALL && + XType() != X_POSITION_TYPE_NONE + // + ; + + // + return result; + } + + /** + * Check Specified Signal is Own to Model or not ... + * + * @param _signal: XSignal instance Reference ... + * + * @return ( bool ) + */ + bool IsOwn(XSignal &_signal) + { + // + bool result = false; + + // + result = + // + IsValid() && + _signal.IsValid() && + IsOwnSignalTime( + _signal.symbol, + _signal.provider, + _signal.period, + ToPositionType(_signal.type), + _signal.time) + // + ; + + // + return result; + } + + /** + * Check Specified Position is Own to Model or not ... + * + * @param _position: XPosition instance Reference ... + * + * @return ( bool ) + */ + bool IsOwn(XPosition &_position) + { + // + bool result = false; + + // + result = + // + IsValid() && + _position.IsValid() && + IsOwnStartTime( + _position.symbol, + _position.provider, + _position.period, + ToPositionType(_position.type), + _position.openAt) + // + ; + + // + return result; + } + + /** + * Check Specified Position is Own to Model or not ... + * + * @param _position: XPosition instance Reference ... + * + * @return ( bool ) + */ + bool IsOwnPosition(XPosition &_position) + { + // + bool result = false; + + // + double tp = TP(); + double sl = SL(); + double entry = Entry(); + double volume = Volume(); + string symbol = GetSymbol(); + string provider = Provider(); + ENUM_POSITION_TYPE type = Type(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + double pVolume = _position.volume; + double pSL = NormalizePrice(_position.sl, _position.symbol); + double pTP = NormalizePrice(_position.tp, _position.symbol); + double pEntry = NormalizePrice(_position.entry, _position.symbol); + + // + result = + // + IsValid() && + (sl == pSL || + tp == pTP) && + entry == pEntry && + pVolume == volume && + _position.IsValid() && + type == _position.type && + symbol == _position.symbol && + period == _position.period && + provider == _position.provider + // + ; + + // + if (!result) + { + // + result = + // + IsValid() && + _position.IsValid() && + _position.ticket == signal.positionId; + } + + // + return result; + } + + /** + * Update Model Data by Providing Specified Signal ... + * + * @param _signal: XSignal instance Reference ... + * + * @return ( bool ) + */ + bool Update(XSignal &_signal) + { + // + bool result = false; + + // + result = + // + IsValid() && + _signal.IsValid() && + IsOwn(_signal) + // + ; + if (!result) + { + return result; + } + + // + signal = _signal; + + // + return result; + } + + /** + * Update Model Data by Providing Specified Position ... + * + * @param _position: XPosition instance Reference ... + * + * @return ( bool ) + */ + bool Update(XPosition &_position) + { + // + bool result = false; + + // + result = + // + IsValid() && + _position.IsValid() && + IsOwn(_position) + // + ; + if (!result) + { + return result; + } + + // + swap = _position.swap; + ticket = _position.ticket; + profit = _position.profit; + message = _position.comment; + startTime = _position.openAt; + + // + // Set Once ... + if (commission == 0 && + _position.commission != 0) + { + commission = _position.commission; + } + + // + // Set Once ... + if (ask == 0) + { + ask = GetAsk(_position.symbol); + } + + // + // Set Once ... + if (bid == 0) + { + bid = GetBid(_position.symbol); + } + + // + if (profit < 0 && profit < maxDrawdown) + { + maxDrawdown = profit; + } + + // + return result; + } + + /** + * Update Model Data by Providing Specified Position ... + * + * @param _position: XPosition instance Reference ... + * + * @return ( bool ) + */ + bool UpdatePosition(XPosition &_position) + { + // + bool result = false; + + // + result = + // + IsValid() && + _position.IsValid() && + IsOwnPosition(_position) + // + ; + if (!result) + { + return result; + } + + // + swap = _position.swap; + ticket = _position.ticket; + profit = _position.profit; + message = _position.comment; + startTime = _position.openAt; + + // + // Set Once ... + if (commission == 0 && + _position.commission != 0) + { + commission = _position.commission; + } + + // + // Set Once ... + if (ask == 0) + { + ask = GetAsk(_position.symbol); + } + + // + // Set Once ... + if (bid == 0) + { + bid = GetBid(_position.symbol); + } + + // + if (profit < 0 && profit < maxDrawdown) + { + maxDrawdown = profit; + } + + // + return result; + } + + // + // Tools Extensions ... + + /** + * Get Model Symbol ... + * + * @return ( string ) + */ + string GetSymbol() + { + return signal.symbol; + } + + /** + * Get Model Period ... + * + * @return ( ENUM_TIMEFRAMES ) + */ + ENUM_TIMEFRAMES GetPeriod() + { + return signal.period; + } + + /** + * Get Model Provider ... + * + * @return ( string ) + */ + string Provider() + { + return signal.provider; + } + + /** + * Get Model Entry ... + * + * @return ( double ) + */ + double Entry() + { + return signal.entry; + } + + /** + * Get Model Stop Loss ... + * + * @return ( double ) + */ + double SL() + { + return signal.sl; + } + + /** + * Get Model Take Profit ... + * + * @return ( double ) + */ + double TP() + { + return signal.tp; + } + + /** + * Get Model Target ... + * + * @return ( double ) + */ + int Targets(double &targets[]) + { + // + int result = 0; + + // + Copy( + signal.targets, + targets // + ); + + // + result = ArraySize(targets); + + // + return result; + } + + /** + * Get Position Spread on Open Time ... + * + * @return ( double ) + */ + double Spread() + { + return MathAbs(ask - bid); + } + + /** + * Get Model Volume ... + * + * @return ( double ) + */ + double Volume() + { + return signal.volume; + } + + /** + * Get Model Point Value ... + * + * @return ( double ) + */ + double Points() + { + return GetPoints(GetSymbol()); + } + + /** + * Get Model Type ... + * + * @return ( ENUM_POSITION_TYPE ) + */ + ENUM_POSITION_TYPE Type() + { + return signal.type; + } + + /** + * Get Model Type ... + * + * @return ( ENUM_X_POSITION_TYPES ) + */ + ENUM_X_POSITION_TYPES XType() + { + // + ENUM_X_POSITION_TYPES result = X_POSITION_TYPE_NONE; + + // + if (!IsValid()) + { + return result; + } + + // + result = + IsLong(Type()) + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_SHORT; + + // + return result; + } + + /** + * Get Model Signal Mode ... + * + * @return ( ENUM_X_ORDER_MODES ) + */ + ENUM_X_ORDER_MODES Mode() + { + return signal.mode; + } + + /** + * Get Model Signal Time ... + * + * @return ( datetime ) + */ + datetime Time() + { + return signal.time; + } + + // + // Additional Helpers Extensions ... + + /** + * Get Signal Full TP Level ... + * + * @return ( double ) + */ + double FullTPLevel() + { + return signal.fullTPLevel; + } + + /** + * Check Can Partial Close Position or not ... + * + * @return ( bool ) + */ + bool CanPartialClose() + { + return signal.CanPartialClose(); + } + + /** + * Retrieve Partial Close Volume Multiplier ... + * + * @return ( double ) + */ + double PartialCloseMultiplier() + { + return signal.partialCloseMultiplier; + } + + /** + * Get Partial Close On TP Level ... + * + * @return ( double ) + */ + double PartialCloseOnTPLevel() + { + return signal.partialCloseOnTPLevel; + } + + /** + * Check Can Risk Free Position on Break Even Point or not ... + * + * @return ( bool ) + */ + bool CanRiskFreeOnBreakEvenPoint() + { + return signal.CanRiskFreeOnBreakEvenPoint(); + } + + /** + * Get Minimum Required Profit after Break Even Point for Risk Free ... + * + * @return ( double ) + */ + double TPLevelForBreakEven() + { + return signal.tpLevelForBreakEven; + } + + /** + * Calculate Break Even Point ... + * + * @return ( double ) + */ + double CalculateBreakEvenPoint() + { + // + double result = 0; + + // + bool isValid = + // + ask > 0 && + bid > 0 && + IsValid() && + ticket > 0 && + signal.IsValid() + // + ; + if (!isValid) + { + return result; + } + + // + // Calculate Spread ... + double spread = Spread(); + if (spread <= 0) + { + return result; + } + + // + // Calculate BEP ... + result = + // + spread + (-1 * swap) + MathAbs(commission) + // + ; + + // + return result; + } + + /** + * Check Can Trail Position Stop Loss or not ... + * + * @return ( bool ) + */ + bool CanTrailSL() + { + return signal.CanTrailSL(); + } + + /** + * Get Start Position SL Trailling on TP Level ... + * + * @return ( double ) + */ + double TrailSLStartOnReachTPLevel() + { + return signal.trailSLStartOnReachTPLevel; + } + + // + // Data Collector Extensions ... + + /** + * Get Data Collection File Name ... + * + * @return ( string ) + */ + string GetFileName() + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + result = + // + GetSymbol() + "\\" + + ToString(XType()) + "\\" + + (profit >= 0 ? "Profit" : "Loss") + "\\" + + ToString(ticket) + "_" + + ToString(GetPeriod()) + "_" + + ToFormatString(startTime) + // + ; + + // + return result; + } + + /** + * Get Signal Collectiong File Name ... + * + * @return ( string ) + */ + string GetSignalFileName() + { + // + string result = NULL; + + // + result = + // + GetSymbol() + "\\" + + ToString(XType()) + "\\" + + Provider() + "_" + + ToFormatString(startTime) + // + ; + + // + return result; + } + + /** + * Converts Model to String Representation ... + * + * @param onlySignals: Boolean, Specified Represent Only Signal or not ... + * + * @return ( string ) + */ + string ToString( + bool onlySignals = false // + ) + { + // + string result = NULL; + + // + int age = GetAge(); + + // + result = + // + (onlySignals ? "" : ToString("Ticket", ticket)) + + ToString("Symbol", GetSymbol()) + + ToString("Period", GetPeriod()) + + ToString("Entry", Entry()) + + ToString("Provider", Provider()) + + ToString("Type", ToString(XType())) + + ToString("Time", startTime) + + // + // 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", signal.pushers) + + "Conditions:" + "\n" + + "-------------" + "\n" + + conditions + + "" + // + ) + + // + "" + // + ; + + // + return result; + } + + // + // End Of X121SMCTradeData Model ... +}; + +// +// Model Specified Symbol's Positions States ... +struct X121SMCSymbolPositionInfo +{ + // + string symbol; + + // + datetime enableAt; + + // + int longSLs; + int longTPs; + + // + int shortSLs; + int shortTPs; + + // + int countedSLs; + + // + // Constructor ... + X121SMCSymbolPositionInfo() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + longSLs = 0; + longTPs = 0; + + // + shortSLs = 0; + shortTPs = 0; + + // + countedSLs = 0; + + // + enableAt = NULL; + + // + ZeroMemory(this); + } + + /** + * 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; + } + + // + // End of X121SMCSymbolPositionInfo Model ... +}; + +// +// Implementations ... + +// +// a Class For Read and Write Trade Info Data in Files ... +class X121SMCTradeCollector +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructor(s) ... + X121SMCTradeCollector( + string _path = NULL // Base Path + ) + { + // + mAccount = new XCAccount(); + + // + if (IsValid(_path)) + { + mPath = _path; + } + else + { + mPath = "X121SMCTradeData" + "\\" + mAccount.GetCompany(); + } + } + + // + // Deconstructor ... + ~X121SMCTradeCollector() + { + } + + /** + * Check Specified Model is Exists or not ... + * + * @param item: X121SMCTradeData instance Reference, Provides Source Model ... + * + * @return ( bool ) + */ + bool IsExists(X121SMCTradeData &item) + { + // + bool result = false; + + // + int mHandler = GetFileHandlerForRead(item); + result = mHandler != INVALID_HANDLE; + FileClose(mHandler); + + // + return result; + } + + /** + * Save Specified Model as Data ... + * + * @param item: X121SMCTradeData instance Reference, Provides Source Model ... + * + * @return ( bool ) + */ + 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; + } + + /** + * Save Specified Model as Signal ... + * + * @param item: X121SMCTradeData instance Reference, Provides Source Model ... + * + * @return ( bool ) + */ + 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; + } + + /** + * Save Specified Model Conditions ... + * Conditions only save for Loss Signals ... + * this means the profit must be Lower than Zero ... + * ans also message Contains SL ... + * + * @param item: X121SMCTradeData instance Reference, Provides Source Model ... + * + * @return ( bool ) + */ + 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.GetSymbol() + "\\" + + (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; + } + + // + // End of X121SMCTradeCollector Class ... +}; + +// +// Trade Handler Class ... +// a Class For Handling All Trade Requirements ... +class XC121SMCTradeHandler : public XCBaseAlert +{ + // + // Public ... + public: + // + + // + // Constructor(s) ... + XC121SMCTradeHandler(XCTrade *trader) + { + // + mTrader = trader; + mAdditionalVolume = 0; + mCollector = new X121SMCTradeCollector(); + } + + // + // Deconstructor ... + ~XC121SMCTradeHandler() + { + // + Clean(mData); + Clean(mSymbolInfos); + Clean(mLastExecutedSignals); + + // + delete mTrader; + delete mCollector; + } + + // + // ReadOnly Props ... + + /** + * Get Max Same Time Trades ... + * + * @return ( double ) + */ + double GetMaxSameTimeTrades() + { + return maxSameTimeTrades; + } + + /** + * Get Max Drawdown Happens ... + * + * @return ( double ) + */ + double GetMaxDrawdown() + { + return maxDrawdown; + } + + /** + * Get Currently Drawdown of Account ... + * + * @return ( double ) + */ + double GetCurrentDrawdown() + { + return currentDrawdown; + } + + /** + * Get Account Current Drawdown Percent ... + * + * @return ( double ) + */ + double GetDrawdownPercent() + { + return drawdownPercent; + } + + // + // Properties Getter(s) / Setter(s) ... + + // + // Saving Properties ... + + /** + * Get Save Signals State ... + * + * @return ( bool ) + */ + bool SaveSignals() + { + return mSaveSignals; + } + + /** + * Set Save Signals State ... + * + * @param value: Boolean ... + */ + void SaveSignals(bool value) + { + mSaveSignals = value; + } + + /** + * Get Save Trades State ... + * + * @return ( bool ) + */ + bool SaveTrades() + { + return mSaveTrades; + } + + /** + * Set Save Trades State ... + * + * @param value: Boolean ... + */ + void SaveTrades(bool value) + { + mSaveTrades = value; + } + + /** + * Get Save Conditions State ... + * + * @return ( bool ) + */ + bool SaveConditions() + { + return mSaveConditions; + } + + /** + * Set Save Conditions State ... + * + * @param value: Boolean ... + */ + void SaveConditions(bool value) + { + mSaveConditions = value; + } + + // + // Signalling Props ... + + /** + * Get Allow Long Signals State ... + * + * @return ( bool ) + */ + bool AllowLong() + { + return mAllowLong; + } + + /** + * Set Allow Long Signals State ... + * + * @param value: Boolean ... + */ + void AllowLong(bool value) + { + mAllowLong = value; + } + + /** + * Get Allow Short Signals State ... + * + * @return ( bool ) + */ + bool AllowShort() + { + return mAllowShort; + } + + /** + * Set Allow Short Signals State ... + * + * @param value: Boolean ... + */ + void AllowShort(bool value) + { + mAllowShort = value; + } + + /** + * Get Max Allowed Long Signals ... + * 0 => Unlimited ... + * + * @return ( int ) + */ + int MaxAllowedLongs() + { + return mMaxAllowedLongs; + } + + /** + * Set Max Allowed Long Signals ... + * + * @param value: Integer ... + * 0 => Unlimited ... + */ + void MaxAllowedLongs(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mMaxAllowedLongs = value; + } + + /** + * Get Max Allowed Short Signals ... + * 0 => Unlimited ... + * + * @return ( int ) + */ + int MaxAllowedShorts() + { + return mMaxAllowedShorts; + } + + /** + * Set Max Allowed Short Signals ... + * + * @param value: Integer ... + * 0 => Unlimited ... + */ + void MaxAllowedShorts(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mMaxAllowedShorts = value; + } + + /** + * Get Use Max Allowed Signal Types Per Symbol State ... + * + * @return ( bool ) + */ + bool UseMaxAllowedSignalsPerSymbol() + { + return mUseMaxAllowedSignalsPerSymbol; + } + + /** + * Set Use Max Allowed Signal Types Per Symbol State ... + * + * @param value: Boolean ... + */ + void UseMaxAllowedSignalsPerSymbol(bool value) + { + mUseMaxAllowedSignalsPerSymbol = false; + } + + /** + * Get Last Position Profit In Points for Accept new Signal ... + * 0 => Accept All ... + * + * @return ( double ) + */ + double LastPositionProfitForAcceptNextInPoint() + { + return mLastPositionProfitForAcceptNextInPoint; + } + + /** + * Set Last Position Profit In Points for Accept new Signal ... + * + * @param value: Double ... + * 0 => Accept All ... + */ + void LastPositionProfitForAcceptNextInPoint(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mLastPositionProfitForAcceptNextInPoint = value; + } + + /** + * Get Delay between two Signals in Bars ... + * 0 => Accept All ... + * + * @return ( int ) + */ + int DelaysBetweenTwoSignalsInBar() + { + return mDelaysBetweenTwoSignalsInBar; + } + + /** + * Set Delay between two Signals in Bars ... + * + * @param value: Integer ... + * 0 => Accept All ... + */ + void DelaysBetweenTwoSignalsInBar(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mDelaysBetweenTwoSignalsInBar = value; + } + + /** + * Get Max Allowed Spread for Signalling ... + * 0 => Accept All ... + * + * @return ( double ) + */ + double MaxAllowedSpread() + { + return mMaxAllowedSpread; + } + + /** + * Set Max Allowed Spread for Signalling ... + * + * @param value: Double ... + * 0 => Accept All ... + */ + void MaxAllowedSpread(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mMaxAllowedSpread = value; + } + + /** + * Get Additional Signal Volume ... + * + * @return ( double ) + */ + double AdditionalVolume() + { + return mAdditionalVolume; + } + + /** + * Set Additional Signal Volume ... + * + * @param value: Double ... + * min = 0.01 + */ + void AdditionalVolume(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + if (value > 0 && value < 0.01) + { + value = 0.01; + } + + // + mAdditionalVolume = value; + } + + // + // Risk Management Props ... + + /** + * Get Max Allowed Drawdown Percent for Open Trades ... + * 0 => Ignore ... + * min => 0 ... + * max => 100 ... + * + * @return ( double ) + */ + double MaxAllowedDrawdownToOpenTrades() + { + return mMaxAllowedDrawdownToOpenTrades; + } + + /** + * Set Max Allowed Drawdown Percent for Open Trades ... + * + * @param value: Double ... + * 0 => Ignore ... + * min => 0 ... + * max => 100 ... + */ + void MaxAllowedDrawdownToOpenTrades(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + if (value > 50) + { + value = 50; + } + + // + mMaxAllowedDrawdownToOpenTrades = value; + } + + /** + * Get Max Allowed SL for Pause Signalling Per Symbol ... + * 0 => Unlimited ... + * + * @return ( int ) + */ + int MaxAllowedSLToPauseSignallingPerSymbol() + { + return mMaxAllowedSLToPauseSignallingPerSymbol; + } + + /** + * Set Max Allowed SL for Pause Signalling Per Symbol ... + * + * @param value: Integer ... + * 0 => Unlimited ... + */ + void MaxAllowedSLToPauseSignallingPerSymbol(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mMaxAllowedSLToPauseSignallingPerSymbol = value; + } + + /** + * Get Pause Signalling Per Symbol afte Max Allowed SL Reached In Seconds ... + * 0 => Ignore ... + * + * @return ( int ) + */ + int PauseSignallingAfterReachesMaxAllowedSLInSecconds() + { + return mPauseSignallingAfterReachesMaxAllowedSLInSecconds; + } + + /** + * Set Pause Signalling Per Symbol afte Max Allowed SL Reached In Seconds ... + * + * @param value: Integer ... + * 0 => Ignore ... + */ + void PauseSignallingAfterReachesMaxAllowedSLInSecconds(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mPauseSignallingAfterReachesMaxAllowedSLInSecconds = value; + } + + // + // Protection Props ... + + /** + * Get Allow Hedge Positions State ... + * + * @return ( bool ) + */ + bool AllowHedging() + { + return mAllowHedging; + } + + /** + * Set Allow Hedge Positions State ... + * + * @param value: Boolean ... + */ + void AllowHedging(bool value) + { + mAllowHedging = value; + } + + /** + * Get Minimum Open Positions for Hedging ... + * 0 => Ignore ... + * + * @return ( int ) + */ + int MinOpenTradesFroHedging() + { + return mMinOpenTradesFroHedging; + } + + /** + * Set Minimum Open Positions for Hedging ... + * + * @param value: Integer ... + * 0 => Ignore ... + */ + void MinOpenTradesFroHedging(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mMinOpenTradesFroHedging = value; + } + + /** + * Get Minimum Volume Step for Hedging ... + * 0 => Ignore ... + * + * @return ( double ) + */ + double HedgingMinVolumeStep() + { + return mHedgingMinVolumeStep; + } + + /** + * Set Minimum Volume Step for Hedging ... + * + * @param value: Double ... + * 0 => Ignore ... + */ + void HedgingMinVolumeStep(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + if (value > 0 && value < 0.01) + { + value = 0.01; + } + + // + if (value > 0 && value > 0.1) + { + value = 0.1; + } + + // + mHedgingMinVolumeStep = value; + } + + /** + * Get Minimum Required Profit Per Volume Step for Hedging ... + * 0 => Ignore ... + * + * @return ( double ) + */ + double HedgeingMinRequiredProfitPerVolumeStep() + { + return mHedgeingMinRequiredProfitPerVolumeStep; + } + + /** + * Set Minimum Required Profit Per Volume Step for Hedging ... + * + * @param value: Double ... + * 0 => Ignore ... + */ + void HedgeingMinRequiredProfitPerVolumeStep(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mHedgeingMinRequiredProfitPerVolumeStep = value; + } + + // + // Actions ... + + // + // Data Collection Actions ... + + /** + * Add Executed Signal Data Model to Trade Datas ... + * + * @param signal: XSignal instance Reference, Issued Signal ... + */ + void Add(XSignal &signal) + { + // + // Check Signal is Valid and also not Exists + // in Datas ... + int idx = -1; + bool hasItem = HasItem( + signal, + idx // + ); + if (hasItem) + { + return; + } + + // + // Initialize Data Item and Add it to Collection of Datas + // if Everythings OK ... + X121SMCTradeData data; + bool isInited = data.Init(signal); + if (isInited) + { + // + Add(data); + SaveSignal(data); + } + } + + /** + * Update a Registered Data Model by Providing Specified Signal ... + * usually used When a signal Modified after Executed for Conditionally Signals ... + * + * @param signal: XSignal instance Reference, Issued Signal ... + */ + void Update(XSignal &signal) + { + // + // Validate Signal ... + if (!signal.IsValid()) + { + return; + } + + // + // Check Signal Registered Before ... + int idx = -1; + bool hasItem = HasItem( + signal, + idx // + ); + bool isUpdated = false; + if (!hasItem) + { + // + // Add New Item if not Exists ... + Add(signal); + isUpdated = true; + } + else + { + // + // Update Data Model in Datas Collection ... + isUpdated = mData[idx].Update(signal); + } + + // + if (isUpdated) + { + SaveSignal(mData[idx]); + } + } + + /** + * Update a Registered Data Model by Providing Specified Position ... + * used for Updating Positions Data or When a Conditional Order Executed as Position ... + * + * @param position: XPosition instance Referece ... + */ + void Update(XPosition &position) + { + // + // Validate Position ... + if (!position.IsValid()) + { + return; + } + + // + // Check Position Registered Before ... + int idx = -1; + bool hasItem = HasItem( + position, + idx // + ); + if (!hasItem) + { + return; + } + + // + // Update Data Model in Datas Collection ... + mData[idx].Update(position); + } + + /** + * Remove Specified Registered Signal from Data Collection ... + * + * @param signal: XSignal instance Reference ... + */ + void Remove(XSignal &signal) + { + // + // Validate Signal ... + if (!signal.IsValid()) + { + return; + } + + // + // Check Signal is Registered or not ... + int idx = -1; + bool hasItem = HasItem( + signal, + idx // + ); + if (!hasItem) + { + return; + } + + // + // Remove Data From Collection ... + ArrayRemove( + mData, + idx, + 1 // + ); + } + + /** + * Handle Position Execution Finished by Providing a Deal ... + * usually used when a Position TP/SL Triggered ... + * + * @param deal: XDeal instance Reference ... + */ + void Finish(const XDeal &deal) + { + // + // Validate Deal ... + // Check Specified Data Registered or not ... + int idx = -1; + bool hasItem = HasItem( + deal.positionId, + idx // + ); + if (!hasItem) + { + return; + } + + // + // Update Data Info ... + mData[idx].swap = deal.swap; + mData[idx].endTime = deal.time; + mData[idx].profit = deal.profit; + + // + // Check Deal Reason ... + bool isTP = deal.reason == DEAL_REASON_TP || + (deal.reason == DEAL_REASON_SL && deal.profit > 0); + bool isSL = deal.reason == DEAL_REASON_SL && deal.profit < 0; + + // + // Prepare Specified Message Based on Deal Reason ... + mData[idx].message = + isTP + ? "TP" + : isSL + ? "SL" + : ""; + + // + // Handle Symbol Positions TP or SL Actions ... + if (isTP || isSL) + { + // + // Check Symbol Position Info Model Exists ... + int symbolIDX = -1; + bool hasInfo = HasSymbol( + mData[idx].GetSymbol(), + symbolIDX // + ); + + // + // Try to Update or Add Symbol Position Info ... + X121SMCSymbolPositionInfo info; + if (!hasInfo) + { + // + // Add New One ... + info.symbol = mData[idx].GetSymbol(); + } + 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; + + // + // Call Propper TP / SL Handlers on Symbol Position Info Model ... + if (isTP) + { + info.HandleTP(xType); + } + else if (isSL) + { + info.HandleSL(xType); + } + + // + // Add Model to Symbol Positions Collection ... + AddRef( + info, + mSymbolInfos // + ); + + // + // Try to Check Symbol Positions Info Collection for Pause Specified Symbol ... + HandlePauseSymbol(mData[idx].GetSymbol()); + } + + // + // Save Collector Calss Data Model ... + Save(idx); + } + + /** + * Handle Position Execution Finished by Providing some Data ... + * usually used when a Position Force Closed Triggered ... + * + * @param ticket: ULong, Position ticket ... + * @param position: XPosition instance Reference ... + * @param comment: String, Force Closing Comment ... + */ + void Finish( + const ulong ticket, + const XPosition &position, + const string comment // + ) + { + // + // Validate and Check Data Registered or not ... + int idx = -1; + bool hasItem = HasItem( + ticket, + idx // + ); + if (!hasItem) + { + return; + } + + // + // Update Data Info ... + mData[idx].swap = position.swap; + mData[idx].endTime = TimeCurrent(); + mData[idx].profit = position.profit; + + // + mData[idx].message = comment; + + // + // Handle Force Closes as TP/SL for Updating + // Symbol Info Positions ... + bool handleForceClose = true; + if (handleForceClose) + { + // + // Simulate TP/SL based on Closing Profit ... + bool isTP = position.profit > 0; + bool isSL = position.profit <= 0; + + // + if (isTP || isSL) + { + // + // Check Symbol Position Info Model Exists ... + int symbolIDX = -1; + bool hasInfo = HasSymbol( + mData[idx].GetSymbol(), + symbolIDX // + ); + + // + // Try to Update or Add Symbol Position Info ... + X121SMCSymbolPositionInfo info; + if (!hasInfo) + { + // + // Add New One ... + info.symbol = mData[idx].GetSymbol(); + } + 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; + + // + // Call Propper TP / SL Handlers on Symbol Position Info Model ... + if (isTP) + { + info.HandleTP(xType); + } + else if (isSL) + { + info.HandleSL(xType); + } + + // + // Add Model to Symbol Positions Collection ... + AddRef( + info, + mSymbolInfos // + ); + + // + // Try to Check Symbol Positions Info Collection for Pause Specified Symbol ... + HandlePauseSymbol(mData[idx].GetSymbol()); + } + + // + // Save Collector Calss Data Model ... + Save(idx); + } + } + + /** + * Update New Open Positions Data on Collection ... + */ + void HandleNewPosition() + { + // + // Retrieve Last Open Position ... + ulong lastOpenPositionTicket = mTrader.GetLastOpenPositionTicket(); + if (lastOpenPositionTicket == 0) + { + return; + } + + // + XPosition position; + bool hasPosition = mTrader.GetPosition( + lastOpenPositionTicket, + position // + ); + if (!hasPosition) + { + return; + } + + // + // Calculate Position Commission ... + double commission = mTrader.GetPositionCommission(position.ticket); + position.commission = commission; + + // + // Apply Updates on Data Collection ... + int idx = -1; + bool hasItem = HasItemByPosition( + position, + idx // + ); + if (!hasItem) + { + return; + } + + // + mData[idx].UpdatePosition(position); + } + + // + // Symbol Position Info Actions ... + + /** + * 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; + } + + /** + * 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 = MaxAllowedSLToPauseSignallingPerSymbol(); + int pauseDelay = PauseSignallingAfterReachesMaxAllowedSLInSecconds(); + 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); + + // + } + + /** + * 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(); + + // + string message = "Reset " + symbol + ", Pause State ..."; + Alert(message); + } + + /** + * 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); + } + + // + // Signal Execution Actions ... + + /** + * Validate Signal For Execution ... + * + * @param signal: XSignal instance Reference ... + * @param state: ENUM_X_SIGNAL_EXECUTION_RESULT Reference for olding Signal Execution Result Reason ... + * + * @return ( bool ) + */ + bool CanExecute( + XSignal &signal, + ENUM_X_SIGNAL_EXECUTION_RESULT &state // Execution State + ) + { + // + bool result = false; + + // + state = X_SIGNAL_EXECUTION_UNKNOWN; + + // + // Validate Signal ... + result = signal.IsValid(); + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_INVALID_PARAMS; + return result; + } + + // + int symbolIDX = -1; + bool hasSymbolInfo = HasSymbol( + signal.symbol, + symbolIDX // + ); + + // + // Check rading Not Paused ... + result = + !hasSymbolInfo || + mSymbolInfos[symbolIDX].IsEnable(); + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_NOT_ALLOWED; + return result; + } + + // + bool isLong = IsLong(signal.type); + + // + // Chekc Signalling Enable or not ... + result = + isLong + ? mAllowLong + : mAllowShort; + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_NOT_ALLOWED; + return result; + } + + // + // Check Signal is Support or not ... + bool isSupport = IsSupport(signal.comment); + result = !isSupport; + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_NOT_ALLOWED; + return result; + } + + // + ENUM_X_POSITION_TYPES pType = ToPositionType(signal.type); + double requiredProfitForAcceptNext = LastPositionProfitForAcceptNextInPoint(); + + // + // 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); + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_PREV_PROFIT_ERROR; + return result; + } + + // + // Retrieve Longs and Shorts ... + XPosition longs[]; + XPosition shorts[]; + bool useMaxAllowedPositionsPerSymbol = UseMaxAllowedSignalsPerSymbol(); + + // + // Retrieve Positions ... + if (useMaxAllowedPositionsPerSymbol) + { + // + mTrader.GetPositions( + longs, + shorts, + signal.symbol, + signal.provider // + ); + } + else + { + // + mTrader.GetPositions( + longs, + shorts, + NULL, // All Symbols ... + signal.provider // + ); + } + + // + // Counting ... + int longsCount = ArraySize(longs); + int shortsCount = ArraySize(shorts); + + // + int maxAllowedLongs = MaxAllowedLongs(); + int maxAllowedShorts = MaxAllowedShorts(); + + // + // Check Max Allowed Positions ... + if (maxAllowedLongs > 0 || + maxAllowedShorts > 0) + { + // + if (isLong && maxAllowedLongs > 0 && longsCount > 0) + { + result = longsCount < maxAllowedLongs; + } + else if (!isLong && maxAllowedShorts > 0 && shortsCount > 0) + { + result = shortsCount < maxAllowedShorts; + } + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_MAX_REACHED; + return result; + } + } + + // + // Check Delays Bar if Provided ... + int delaysBarBetweenTwoSignal = DelaysBetweenTwoSignalsInBar(); + if (delaysBarBetweenTwoSignal > 0) + { + // + // Try To Detect Youngest Position ... + 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 // + ); + } + + // + // Check Delays When Youngest Position Exists ... + if (youngestAge > 0 && youngestPosition.IsValid()) + { + // + result = youngestAge >= delaysBarBetweenTwoSignal; + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_DELAY_NOT_PASSED; + return result; + } + } + + // + // Check Delays When Youngest Position is not Exists ... + if (!youngestPosition.IsValid()) + { + // + // Try to Detect Last Issued Signal in Model Collections ... + int symbolIDX = FindLastExecutedSignalItem(signal); + if (IsValidIndex(symbolIDX)) + { + // + // Calculate Requirements ... + datetime cTime = TimeCurrent(); + int signalPeriodSeconds = PeriodSeconds(signal.period); + datetime lastExecutedTime = mLastExecutedSignals[symbolIDX].time; + datetime passedTime = ((datetime)lastExecutedTime + + ((delaysBarBetweenTwoSignal * signalPeriodSeconds))); + + // + // Check Conditions ... + result = cTime >= passedTime; + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_DELAY_NOT_PASSED; + return result; + } + } + } + } + + // + // Check Max Drawdown Percent for Open Trades ... + double maxAllowedDrawdownPercent = MaxAllowedDrawdownToOpenTrades(); + if (maxAllowedDrawdownPercent > 0) + { + // + // Calculate and Update Drawdown Percent ... + double cdPercent = CalculateMaxDrawdownPercent(); + + // + result = cdPercent < maxAllowedDrawdownPercent; + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_NO_EQUITY; + return result; + } + } + + // + // Check Spread ... + double spread = GetSpread(signal.symbol); + double maxAllowedSpread = MaxAllowedSpread(); + if (maxAllowedSpread > 0) + { + // + result = spread <= maxAllowedSpread; + if (!result) + { + // + state = X_SIGNAL_EXECUTION_FAILED_SPREAD; + return result; + } + } + + // + return result; + } + + /** + * Execute Specific Signal using Trade Handler ... + * + * @param signal: XSignal instance Reference ... + * @param state: ENUM_X_SIGNAL_EXECUTION_RESULT Reference for olding Signal Execution Result Reason ... + * @param ignorePolicies: Boolean ... + * + * @return ( bool ) + */ + bool ExecuteSignal( + XSignal &signal, // Signal for Execution + ENUM_X_SIGNAL_EXECUTION_RESULT &state, // Execution State + bool ignorePolicies = false // Ignore Execution Policies + ) + { + // + bool result = false; + + // + // Check Signal Validation ... + result = signal.IsValid(); + if (!result) + { + return result; + } + + // + // Check Policies ... + if (!ignorePolicies) + { + // + // Filter Signals if Necessary ... + result = CanExecute( + signal, + state // + ); + if (!result) + { + // + AlertSignalExecutionFailed( + signal, + state // + ); + + // + return result; + } + } + + // + // Apply Additional Volume to Signal if Provided ... + double additionalVolume = AdditionalVolume(); + if (additionalVolume > 0) + { + signal.volume += mAdditionalVolume; + } + + // + // Execute Signal ... + result = mTrader.ExecuteSignal( + signal, + state // + ); + if (result) + { + // + // Add XTradeHandler Data ... + Add(signal); + + // + // Handle Last Executed Signal ... + HandleSignalExecuted(signal); + + // + // Alert Executed 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); + } + + // + if (!result) + { + // + AlertSignalExecutionFailed( + signal, + state // + ); + } + + // + return result; + } + + /** + * Execute Specific Signal using Trade Handler ... + * + * @param signal: XSignal instance Reference ... + * @param state: ENUM_X_SIGNAL_EXECUTION_RESULT Reference for olding Signal Execution Result Reason ... + * @param ignorePolicies: Boolean ... + * + * @return ( bool ) + */ + bool ExecuteSignal( + XSignal &signal, // Signal for Execution + X121SMCStrategyConditions &conditions, // Signal Conditions + ENUM_X_SIGNAL_EXECUTION_RESULT &state, // Execution State + bool ignorePolicies = false // Ignore Execution Policies + ) + { + // + bool result = false; + + // + // Check Signal Validation ... + result = signal.IsValid() && + conditions.IsValid(); + if (!result) + { + return result; + } + + // + // Check Policies ... + if (!ignorePolicies) + { + // + // Filter Signals if Necessary ... + result = CanExecute( + signal, + state // + ); + if (!result) + { + // + AlertSignalExecutionFailed( + signal, + state // + ); + + // + return result; + } + } + + // + // Apply Additional Volume to Signal if Provided ... + double additionalVolume = AdditionalVolume(); + if (additionalVolume > 0) + { + signal.volume += mAdditionalVolume; + } + + // + // Execute Signal ... + result = mTrader.ExecuteSignal( + signal, + state // + ); + if (result) + { + // + // Add XTradeHandler Data ... + Add(signal); + + // + // Handle Last Executed Signal ... + HandleSignalExecuted(signal); + + // + // Alert Executed 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); + } + + // + if (!result) + { + // + AlertSignalExecutionFailed( + signal, + state // + ); + } + + // + return result; + } + + /** + * Force Close Specified Positions ... + * + * @param symbol: String ... + * @param provider: String ... + * @param period: ENUM_TIMEFRAMES member ... + * @param type: ENUM_X_POSITION_TYPES member ... + * + * @return ( bool ) + */ + bool ForceClose( + string symbol = NULL, + string provider = NULL, + ENUM_TIMEFRAMES period = NULL, + ENUM_X_POSITION_TYPES type = NULL // + ) + { + // + bool result = false; + + // + XPosition positions[]; + int count = mTrader.GetPositions( + positions, + symbol, + provider, + period, + type // + ); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + datetime cTime = TimeCurrent(); + + // + string comment = "Force Close (" + ToString(count) + ") Positions At: " + ToFormatString(cTime) + "..."; + int closedPositionsCount = mTrader.Close( + positions, + comment // + ); + result = IsValidSize(closedPositionsCount); + if (result) + { + // + // Finish Positions and Clear Data ... + for (int i = 0; i < ArraySize(positions); i++) + { + // + XPosition iPosition = positions[i]; + Finish( + iPosition.ticket, + iPosition, + comment // + ); + } + + // + ResetProtections(); + + // + string message = "Force Close (" + ToString(count) + ") Positions At: " + + ToFormatString(cTime) + " Successfully ..."; + Alert(message); + } + + // + return result; + } + + /** + * Force Close Positions ... + * + * @return ( bool ) + */ + bool ForceClose( + XPosition &positions[], + string comment, + string notificationMessage // + ) + { + // + bool result = false; + + // + int count = ArraySize(positions); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + int closedPositionsCount = mTrader.Close( + positions, + comment // + ); + result = IsValidSize(closedPositionsCount); + if (result) + { + // + // Finish Positions and Clear Data ... + for (int i = 0; i < ArraySize(positions); i++) + { + // + XPosition iPosition = positions[i]; + Finish( + iPosition.ticket, + iPosition, + comment // + ); + } + + // + ResetProtections(); + + // + if (IsValid(notificationMessage)) + { + Alert(notificationMessage); + } + } + + // + return result; + + // + return result; + } + + // + // Timing Actions ... + + /** + * Update Currently Open Positions Info on Data Collection ... + */ + void UpdateData() + { + // + // Retrieve Positions ... + XPosition positions[]; + int count = mTrader.GetPositions(positions); + if (!IsValidSize(count)) + { + return; + } + + // + // Loop Through Positions ... + for (int i = 0; i < count; i++) + { + // + XPosition iPosition = positions[i]; + + // + // Check Position Registered as Data or not ... + int idx = -1; + bool isExists = HasItem( + iPosition.ticket, + idx // + ); + if (isExists) + { + // + // Update Position Data ... + mData[idx].Update(iPosition); + } + } + } + + /** + * Handle Positiona Protections + */ + void HandleProtection() + { + // + string prefix = "Protector: "; + + // + // Implement Protection Senario Here ... + int count = Count(); + if (!IsValidSize(count)) + { + // + currentDrawdown = 0; + return; + } + + // + // Calculate Max Same Time Trades ... + maxSameTimeTrades = + maxSameTimeTrades == 0 || + maxSameTimeTrades < count + ? count + : maxSameTimeTrades; + + // + double bepSummary = 0; + double volumeSummary = 0; + double profitSummary = 0; + XPosition positions[]; + bool isProtected = false; + + // + // Loop through Open Positions ... + for (int i = 0; i < count; i++) + { + // + X121SMCTradeData iData = mData[i]; + + // + XPosition iPosition; + bool hasPosition = mTrader.GetPosition( + iData.ticket, + iPosition // + ); + if (!hasPosition) + { + continue; + } + AddRef( + iPosition, + positions // + ); + + // + // Calculate Break Even Point ... + double entry = iPosition.entry; + double points = iData.Points(); + double volume = iPosition.volume; + bool isLong = IsLong(iData.Type()); + double spread = GetSpread(iData.GetSymbol()); + double bep = iData.CalculateBreakEvenPoint(); + double exitPrice = GetExit( + iPosition.symbol, + iPosition.type // + ); + + // + double tps[]; + int reachedTPIndex = -1; + double reachedTPPrice = 0; + double reachedTPLevel = -1; + int tpLevelsCount = iPosition.CalculateTPLevels(tps); + iPosition.CalculateReahedTP( + reachedTPLevel, + reachedTPPrice // + ); + if (reachedTPLevel > 0) + { + // + reachedTPIndex = FindIndex( + reachedTPPrice, + tps // + ); + } + + // + bepSummary += bep; + volumeSummary += volume; + profitSummary += iPosition.profit; + + // + // All Protections Done for InProfit Positions ... + if (iData.profit > 0) + { + // + // Check Break Even ... + bool canRFOnBEP = iData.CanRiskFreeOnBreakEvenPoint(); + if (canRFOnBEP && reachedTPLevel > 0) + { + // + double tpLevel = iData.TPLevelForBreakEven(); + int tpIDX = (int)tpLevel - 1; + double rfTPPrice = tps[tpIDX]; + bool isSLReady = isLong + ? iPosition.sl < rfTPPrice + : iPosition.sl > rfTPPrice; + if (isSLReady && tpLevel == reachedTPLevel - 1) + { + // + double sl = rfTPPrice; + double tp = iPosition.tp; + string comment = "RF on BEP ..."; + bool isModified = mTrader.Modify( + iData.ticket, + sl, + tp, + comment // + ); + if (isModified) + { + // + isProtected = true; + + // + string message = prefix + + ToString(iData.Type()) + + " Position: " + + ToString(iData.ticket) + + " RF On BEP Successfully ..."; + Alert(message); + } + } + } + + // + // Check Partial Close ... + bool canPartialClose = iData.CanPartialClose(); + if (canPartialClose && reachedTPLevel > 0) + { + // + double mainVolume = iData.Volume(); + double currentVolume = iPosition.volume; + double partialCloseOnTP = iData.PartialCloseOnTPLevel(); + double partialCloseVolumeMultiplier = iData.PartialCloseMultiplier(); + double closeVolume = currentVolume * partialCloseVolumeMultiplier; + closeVolume = NormalizeVolume(closeVolume, iPosition.symbol); + canPartialClose = + currentVolume == mainVolume && + reachedTPLevel == partialCloseOnTP; + if (canPartialClose) + { + // + string comment = "PC On TP Level: " + ToString(partialCloseOnTP) + " ..."; + bool isModified = mTrader.ClosePartial( + iData.ticket, + closeVolume, + comment // + ); + if (isModified) + { + // + isProtected = true; + + // + string message = prefix + + ToString(iData.Type()) + + " Position: " + + ToString(iData.ticket) + + " PC (" + ToString(closeVolume) + ") On TP Level: " + + ToString(partialCloseOnTP) + " Successfully ..."; + Alert(message); + + // + // Finish Position ... + if (closeVolume == mainVolume) + { + // + Finish( + iPosition.ticket, + iPosition, + comment // + ); + + // + break; + } + } + } + } + + // + // Check for SL Trail ... + bool canTrailSL = iData.CanTrailSL(); + if (canTrailSL && reachedTPLevel > 0) + { + // + double tSLTPPrice = 0; + + // + double startTrailTPLevel = iData.TrailSLStartOnReachTPLevel(); + if (iData.lastTrailedTPLevel > 0) + { + startTrailTPLevel = iData.lastTrailedTPLevel + 1; + } + + // + canTrailSL = IsValidIndex(reachedTPIndex) && + reachedTPLevel >= startTrailTPLevel; + if (canTrailSL) + { + // + tSLTPPrice = + reachedTPIndex == 0 + ? tps[reachedTPIndex] + : tps[reachedTPIndex - 1]; + + // + canTrailSL = + tSLTPPrice > 0 && + iPosition.sl == 0 + ? (isLong + ? tSLTPPrice > iPosition.entry && + tSLTPPrice < iPosition.price + : tSLTPPrice < iPosition.entry && + tSLTPPrice > iPosition.price) + : (isLong + ? tSLTPPrice > iPosition.sl && + tSLTPPrice > iPosition.entry && + tSLTPPrice < iPosition.price + : tSLTPPrice < iPosition.sl && + tSLTPPrice < iPosition.entry && + tSLTPPrice > iPosition.price); + } + + // + if (canTrailSL) + { + // + string comment = "Trail SL on Reached TP: " + ToString(reachedTPLevel) + " ..."; + double sl = tSLTPPrice; + double tp = iPosition.tp; + bool isModified = mTrader.Modify( + iData.ticket, + sl, + tp, + comment // + ); + if (isModified) + { + // + isProtected = true; + + // + // Update Last Trailed TP Level ... + mData[i].lastTrailedTPLevel = reachedTPLevel; + + // + string message = prefix + + ToString(iData.Type()) + + " Position: " + + ToString(iData.ticket) + + " Trailed SL On Reached TP: " + ToString(reachedTPLevel) + + " Successfully ..."; + Alert(message); + } + } + } + + // + // Handle RF On Target ... + double targets[]; + int targetsCount = iData.Targets(targets); + bool hasTargets = IsValidSize(targetsCount); + if (hasTargets) + { + // + for (int k = 0; k < targetsCount; k++) + { + // + double target = targets[k]; + bool isValidTarget = + iData.lastTarget == 0 + ? true + : isLong + ? target > iData.lastTarget + : target < iData.lastTarget; + if (!isValidTarget) + { + continue; + } + + // + double targetDelta = isLong + ? target + (15 * points) + : target - (15 * points); + bool canRF = + target > 0 && + (isLong ? target > entry + : target < entry) && + (isLong + ? iPosition.sl < target + : iPosition.sl > target) && + (isLong + ? iPosition.price > targetDelta + : iPosition.price < targetDelta); + if (canRF) + { + // + double sl = target; + double tp = iPosition.tp; + string comment = "RF On Target ..."; + bool isModified = mTrader.Modify( + iData.ticket, + sl, + tp, + comment // + ); + if (isModified) + { + // + isProtected = true; + + // + // Update mData ... + mData[i].lastTarget = target; + + // + string message = prefix + + ToString(iData.Type()) + + " Position: " + + ToString(iData.ticket) + + " RF On Traget: " + ToString(target) + + " Successfully ..."; + Alert(message); + } + } + } + } + } + } + + // + // Calculate Max Draw Down ... + maxDrawdown = + profitSummary < 0 && + (maxDrawdown == 0 || + maxDrawdown < profitSummary) + ? profitSummary + : maxDrawdown; + + // + // Calculate Current Drawdown ... + currentDrawdown = + profitSummary < 0 + ? profitSummary + : 0; + + // + // Checking Hedge ... + bool allowHedge = AllowHedging() && + !isProtected; + if (allowHedge) + { + // + double minHedgeVolumeStep = HedgingMinVolumeStep(); + int minRequiredPositionsForHedge = MinOpenTradesFroHedging(); + double minRequiredProfitPerVolumeStepForHedge = HedgeingMinRequiredProfitPerVolumeStep(); + + // + double minRequiredAdditionalProfit = + bepSummary + + ((volumeSummary / minHedgeVolumeStep) * minRequiredProfitPerVolumeStepForHedge); + + // + bool canHedge = AllowHedging() && + profitSummary > 0 && + minHedgeVolumeStep > 0 && + minRequiredProfitPerVolumeStepForHedge > 0 && + profitSummary >= minRequiredAdditionalProfit && + (minRequiredPositionsForHedge <= 0 + ? true + : count >= minRequiredPositionsForHedge); + if (canHedge) + { + // + string comment = "Hedge (" + ToString(ArraySize(positions)) + ") Positions By: " + ToString(profitSummary) + "..."; + int closedPositionsCount = mTrader.Close( + positions, + comment // + ); + if (IsValidSize(closedPositionsCount)) + { + // + // Finish Positions and Clear Data ... + for (int i = 0; i < ArraySize(positions); i++) + { + // + XPosition iPosition = positions[i]; + Finish( + iPosition.ticket, + iPosition, + comment // + ); + } + + // + ResetProtections(); + + // + string message = "Hedge (" + ToString(ArraySize(positions)) + ") Positions By: " + + ToString(profitSummary) + " Successfully ..."; + Alert(message); + } + } + } + } + + // + // Protected ... + protected: + // + XCTrade *mTrader; // Instance of Trader Class + X121SMCTradeCollector *mCollector; // Instance of Trade Collector Class + + // + X121SMCTradeData mData[]; // Hold Trade Data + X121SMCSymbolPositionInfo mSymbolInfos[]; // Symbol Positions Info + XSymbolLastPosition mLastExecutedSignals[]; // Last Executed Signals + + // + void AlertSignalExecutionFailed( + XSignal &signal, + ENUM_X_SIGNAL_EXECUTION_RESULT state // + ) + { + // + // Alert Signal Execution Failed ... + string msg = "Failed To Execute " + + (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) + + " due Reason: " + ToString(state) + " ..."; + Alert(msg); + } + + // + // Private ... + private: + // + // Props ... + + // + // Read Only ... + int maxSameTimeTrades; // Holds Max Same Time Trades + double maxDrawdown; // Max Drawdown + double currentDrawdown; // Current 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 + + // + // Signalling Props ... + bool mAllowLong; // Allow Long Signals ... + bool mAllowShort; // Allow Short Signals ... + int mMaxAllowedLongs; // Max Allowed Long Signals ... + int mMaxAllowedShorts; // Max Allowed Short Signals ... + bool mUseMaxAllowedSignalsPerSymbol; // Use Max Allowed Signal Types Per Symbol ... + double mLastPositionProfitForAcceptNextInPoint; // Last Position Profit In Points for Accept new Signal ... + int mDelaysBetweenTwoSignalsInBar; // Delay between two Signals in Bars ... + double mMaxAllowedSpread; // Max Allowed Spread for Signalling ... + double mAdditionalVolume; // Volume Additional ... + + // + // Risk Management Props ... + double mMaxAllowedDrawdownToOpenTrades; // Max Allowed Drawdown for Open Trades ... + int mMaxAllowedSLToPauseSignallingPerSymbol; // Max Allowed SL for Pause Signalling Per Symbol ... + int mPauseSignallingAfterReachesMaxAllowedSLInSecconds; // Pause Signalling Per Symbol afte Max Allowed SL Reached In Seconds ... + + // + // Protection Props ... + bool mAllowHedging; // Allow Hedge Positions ... + int mMinOpenTradesFroHedging; // Minimum Open Positions for Hedging ... + double mHedgingMinVolumeStep; // Minimum Volume Step for Hedging ... + double mHedgeingMinRequiredProfitPerVolumeStep; // Minimum Required Profit Per Volume Step for Hedging ... + + // + // 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.signal, + 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; + } + + // + bool HasItem( + XSignal &signal, + int &index // + ) + { + // + bool result = false; + + // + index = -1; + + // + int count = Count(); + result = signal.IsValid() && + IsValidSize(count); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + bool isOwn = mData[i].IsOwn(signal); + if (isOwn) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + // + bool HasItem( + XPosition &position, + int &index // + ) + { + // + bool result = false; + + // + index = -1; + + // + int count = Count(); + result = position.IsValid() && + IsValidSize(count); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + bool isOwn = mData[i].IsOwn(position); + if (isOwn) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + // + bool HasItemByPosition( + XPosition &position, + int &index // + ) + { + // + bool result = false; + + // + index = -1; + + // + int count = Count(); + result = position.IsValid() && + IsValidSize(count); + if (!result) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + bool isOwn = mData[i].IsOwnPosition(position); + if (isOwn) + { + // + index = i; + break; + } + } + + // + result = IsValidIndex(index); + + // + return result; + } + + /** + * 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; + } + + // + 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); + } + + // + // Find Last Signal Execution ... + 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; + } + + // + // Handle Last Signal Execution ... + 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 // + ); + } + } + + // + double CalculateMaxDrawdownPercent() + { + // + double result = 0; + + // + double mEquity = mTrader.mAccount.GetEquity(); + if (mEquity > currentDrawdown) + { + currentDrawdown = mEquity; + } + + // + if (currentDrawdown >= 0) + { + // + drawdownPercent = 0; + return result; + } + + // + drawdownPercent = (currentDrawdown - mEquity) / + (staticBalanceForCalculateDrawdown > 0 + ? staticBalanceForCalculateDrawdown + : currentDrawdown) * + 100; + drawdownPercent = NormalizeDouble(drawdownPercent, 3); + result = drawdownPercent; + + // + return result; + } + + // + void ResetProtections() + { + // + ResumePausedSymbols(); + Clean(mLastExecutedSignals); + } + + // + // End of XC121SMCTradeHandler Class ... +}; + +// \ No newline at end of file diff --git a/BKPS/14031218/X121SMCEA/Experts/x-121.smc.expert.class.mq5 b/BKPS/14031218/X121SMCEA/Experts/x-121.smc.expert.class.mq5 new file mode 100644 index 0000000..c79eaa1 --- /dev/null +++ b/BKPS/14031218/X121SMCEA/Experts/x-121.smc.expert.class.mq5 @@ -0,0 +1,2479 @@ +/////////////////////////////////////////////////////// +// +// 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 "../../Helpers/x-saherelm.x121.xcc.helper.mq5" +#include "../../Helpers/x-saherelm.x121.xct.helper.mq5" +#include "../Classes/x-121.smc.x-tradehandler.class.mq5" +#include "../Libraries/x-121.smc.lib.mq5" +#include "../Strategy/x-121.smc.strategy.class.mq5" + +// +// Definitions ... +string XC121SMCExpertToken = "XC121SMCEA"; + +// +// Implementation ... + +class XC121SMCExpert : public XCBaseExpert +{ + // + public: + // + XCX121XCCHelper *xccHelper; + XCX121XCTHelper *xctHelper; + + // + // Signal Event Listener ... + TOnStopLoss OnPositionSLEventListener; + TOnTakeProfit OnPositionTPEventListener; + TOnPartialClose OnPositionPartialCloseEventListener; + TOnModify OnPositionModifiedEventListener; + TOnForceClose OnPositionForceCloseEventListener; + + // + TOnDealsChanged OnDealsChangedEventListener; + TOnOrdersChanged OnOrdersChangedEventListener; + TOnPositionsChanged OnPositionsChangedEventListener; + + // + TOnX121SMCSignal OnSignalEventListener; + + // + // Constructor(s) ... + XC121SMCExpert() + { + mShowCandles = false; + } + + // + // Deconstructor(s) ... + ~XC121SMCExpert() + { + Clean(mStrategies); + } + + // + // Getter(s) / Setter(s) ... + + // + // Signalling Props ... + + /** + * Get Allow Long Signals State ... + * + * @return ( bool ) + */ + bool AllowLong() + { + return mAllowLong; + } + + /** + * Set Allow Long Signals State ... + * + * @param value: Boolean ... + */ + void AllowLong(bool value) + { + // + mAllowLong = value; + ReConfigure(); + } + + /** + * Get Allow Short Signals State ... + * + * @return ( bool ) + */ + bool AllowShort() + { + return mAllowShort; + } + + /** + * Set Allow Short Signals State ... + * + * @param value: Boolean ... + */ + void AllowShort(bool value) + { + // + mAllowShort = value; + ReConfigure(); + } + + /** + * Get Max Allowed Long Signals ... + * 0 => Unlimited ... + * + * @return ( int ) + */ + int MaxAllowedLongs() + { + return mMaxAllowedLongs; + } + + /** + * Set Max Allowed Long Signals ... + * + * @param value: Integer ... + * 0 => Unlimited ... + */ + void MaxAllowedLongs(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mMaxAllowedLongs = value; + ReConfigure(); + } + + /** + * Get Max Allowed Short Signals ... + * 0 => Unlimited ... + * + * @return ( int ) + */ + int MaxAllowedShorts() + { + return mMaxAllowedShorts; + } + + /** + * Set Max Allowed Short Signals ... + * + * @param value: Integer ... + * 0 => Unlimited ... + */ + void MaxAllowedShorts(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mMaxAllowedShorts = value; + ReConfigure(); + } + + /** + * Get Use Max Allowed Signal Types Per Symbol State ... + * + * @return ( bool ) + */ + bool UseMaxAllowedSignalsPerSymbol() + { + return mUseMaxAllowedSignalsPerSymbol; + } + + /** + * Set Use Max Allowed Signal Types Per Symbol State ... + * + * @param value: Boolean ... + */ + void UseMaxAllowedSignalsPerSymbol(bool value) + { + // + mUseMaxAllowedSignalsPerSymbol = false; + ReConfigure(); + } + + /** + * Get Last Position Profit In Points for Accept new Signal ... + * 0 => Accept All ... + * + * @return ( double ) + */ + double LastPositionProfitForAcceptNextInPoint() + { + return mLastPositionProfitForAcceptNextInPoint; + } + + /** + * Set Last Position Profit In Points for Accept new Signal ... + * + * @param value: Double ... + * 0 => Accept All ... + */ + void LastPositionProfitForAcceptNextInPoint(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mLastPositionProfitForAcceptNextInPoint = value; + ReConfigure(); + } + + /** + * Get Delay between two Signals in Bars ... + * 0 => Accept All ... + * + * @return ( int ) + */ + int DelaysBetweenTwoSignalsInBar() + { + return mDelaysBetweenTwoSignalsInBar; + } + + /** + * Set Delay between two Signals in Bars ... + * + * @param value: Integer ... + * 0 => Accept All ... + */ + void DelaysBetweenTwoSignalsInBar(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mDelaysBetweenTwoSignalsInBar = value; + ReConfigure(); + } + + /** + * Get Max Allowed Spread for Signalling ... + * 0 => Accept All ... + * + * @return ( double ) + */ + double MaxAllowedSpread() + { + return mMaxAllowedSpread; + } + + /** + * Set Max Allowed Spread for Signalling ... + * + * @param value: Double ... + * 0 => Accept All ... + */ + void MaxAllowedSpread(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mMaxAllowedSpread = value; + ReConfigure(); + } + + /** + * Get Minimum Spread Verification for Signalling ... + * 0 => Ignore ... + * + * @return ( int ) + */ + int MinRequiredVerificationForSpreadPass() + { + return mMinRequiredVerificationForSpreadPass; + } + + /** + * Set Minimum Spread Verification for Signalling ... + * + * @param value: Integer ... + * 0 => Ignore ... + */ + void MinRequiredVerificationForSpreadPass(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mMinRequiredVerificationForSpreadPass = value; + ReConfigure(); + } + + // + // Trade ... + + /** + * Get Allow Open Trade On Signals State ... + * + * @return ( bool ) + */ + bool AllowTrade() + { + return mAllowTrade; + } + + /** + * Set Allow Open Trade On Signals State ... + * + * @param value: Boolean ... + */ + void AllowTrade(bool value) + { + mAllowTrade = value; + } + + /** + * Get Enable Trade on Signals on Time ... + * + * @return ( string ) + */ + string StartTradeAt() + { + return mStartTradeAt; + } + + /** + * Set Enable Trade on Signals on Time ... + * + * @param value: String ... + */ + void StartTradeAt(string value) + { + mStartTradeAt = value; + } + + /** + * Get Enable Trade on Signals on Time ... + * + * @return ( string ) + */ + string StopTradeAt() + { + return mStopTradeAt; + } + + /** + * Set Enable Trade on Signals on Time ... + * + * @param value: String ... + */ + void StopTradeAt(string value) + { + mStopTradeAt = value; + } + + /** + * Get Enable Close All Trades on Signals on Time ... + * + * @return ( string ) + */ + string CloseAllTradesAt() + { + return mCloseAllTradesAt; + } + + /** + * Set Enable Close All Trades on Signals on Time ... + * + * @param value: String ... + */ + void CloseAllTradesAt(string value) + { + mCloseAllTradesAt = value; + } + + // + // Risk Management Props ... + + /** + * 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; + ReConfigure(); + } + + /** + * 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; + ReConfigure(); + } + + /** + * Get Static Balance for Calculate Trade Volume ... + * + * @return ( double ) + */ + double StaticBalance() + { + return mStaticBalance; + } + + /** + * Set Static Balance for Calculate Trade Volume ... + * + * @param value: Argument 1 + */ + void StaticBalance(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mStaticBalance = value; + } + + /** + * Get Balance Used In Each Trade ... + * + * @return ( double ) + */ + double BalancePerTrade() + { + return mBalancePerTrade; + } + + /** + * Set Balance Used In Each Trade ... + * + * @param value: Argument 1 + */ + void BalancePerTrade(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mBalancePerTrade = 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; + ReConfigure(); + } + + /** + * 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; + ReConfigure(); + } + + /** + * 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; + ReConfigure(); + } + + /** + * 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; + ReConfigure(); + } + + /** + * 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; + ReConfigure(); + } + + /** + * Get Max Allowed Drawdown Percent for Open Trades ... + * 0 => Ignore ... + * min => 0 ... + * max => 100 ... + * + * @return ( double ) + */ + double MaxAllowedDrawdownToOpenTrades() + { + return mMaxAllowedDrawdownToOpenTrades; + } + + /** + * Set Max Allowed Drawdown Percent for Open Trades ... + * + * @param value: Double ... + * 0 => Ignore ... + * min => 0 ... + * max => 100 ... + */ + void MaxAllowedDrawdownToOpenTrades(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + if (value > 50) + { + value = 50; + } + + // + mMaxAllowedDrawdownToOpenTrades = value; + ReConfigure(); + } + + /** + * Get Max Allowed SL for Pause Signalling Per Symbol ... + * 0 => Unlimited ... + * + * @return ( int ) + */ + int MaxAllowedSLToPauseSignallingPerSymbol() + { + return mMaxAllowedSLToPauseSignallingPerSymbol; + } + + /** + * Set Max Allowed SL for Pause Signalling Per Symbol ... + * + * @param value: Integer ... + * 0 => Unlimited ... + */ + void MaxAllowedSLToPauseSignallingPerSymbol(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mMaxAllowedSLToPauseSignallingPerSymbol = value; + ReConfigure(); + } + + /** + * Get Pause Signalling Per Symbol afte Max Allowed SL Reached In Seconds ... + * 0 => Ignore ... + * + * @return ( int ) + */ + int PauseSignallingAfterReachesMaxAllowedSLInSecconds() + { + return mPauseSignallingAfterReachesMaxAllowedSLInSecconds; + } + + /** + * Set Pause Signalling Per Symbol afte Max Allowed SL Reached In Seconds ... + * + * @param value: Integer ... + * 0 => Ignore ... + */ + void PauseSignallingAfterReachesMaxAllowedSLInSecconds(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mPauseSignallingAfterReachesMaxAllowedSLInSecconds = value; + ReConfigure(); + } + + // + // Protection Props ... + + /** + * Get Allow Hedge Positions State ... + * + * @return ( bool ) + */ + bool AllowHedging() + { + return mAllowHedging; + } + + /** + * Set Allow Hedge Positions State ... + * + * @param value: Boolean ... + */ + void AllowHedging(bool value) + { + // + mAllowHedging = value; + ReConfigure(); + } + + /** + * Get Minimum Open Positions for Hedging ... + * 0 => Ignore ... + * + * @return ( int ) + */ + int MinOpenTradesFroHedging() + { + return mMinOpenTradesFroHedging; + } + + /** + * Set Minimum Open Positions for Hedging ... + * + * @param value: Integer ... + * 0 => Ignore ... + */ + void MinOpenTradesFroHedging(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mMinOpenTradesFroHedging = value; + ReConfigure(); + } + + /** + * Get Minimum Volume Step for Hedging ... + * 0 => Ignore ... + * + * @return ( double ) + */ + double HedgingMinVolumeStep() + { + return mHedgingMinVolumeStep; + } + + /** + * Set Minimum Volume Step for Hedging ... + * + * @param value: Double ... + * 0 => Ignore ... + */ + void HedgingMinVolumeStep(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + if (value > 0 && value < 0.01) + { + value = 0.01; + } + + // + if (value > 0 && value > 0.1) + { + value = 0.1; + } + + // + mHedgingMinVolumeStep = value; + ReConfigure(); + } + + /** + * Get Minimum Required Profit Per Volume Step for Hedging ... + * 0 => Ignore ... + * + * @return ( double ) + */ + double HedgeingMinRequiredProfitPerVolumeStep() + { + return mHedgeingMinRequiredProfitPerVolumeStep; + } + + /** + * Set Minimum Required Profit Per Volume Step for Hedging ... + * + * @param value: Double ... + * 0 => Ignore ... + */ + void HedgeingMinRequiredProfitPerVolumeStep(double value) + { + // + if (value < 0) + { + value = 0; + } + + // + mHedgeingMinRequiredProfitPerVolumeStep = value; + ReConfigure(); + } + + // + // 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.Remove(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(); + + // + // Chack Allow Trades ... + bool allowTrade = AllowTrade(); + if (allowTrade) + { + // + string startTime = StartTradeAt(); + string endTime = StopTradeAt(); + bool isTimePassed = IsTimeInRange( + TimeCurrent(), + startTime, + endTime // + ); + + // + if (isTimePassed) + { + // + // Execute Signal Using Trade Handler ... + ENUM_X_SIGNAL_EXECUTION_RESULT state; + bool isExecuted = mTradeHandler.ExecuteSignal( + signal, + conditions, + state, + false // ignore Policies ... + ); + } + else + { + // + string msg = "Failed To Execute " + + (IsLong(signal.type) + ? "Long" + : "Short") + + " Signal Recieved: (" + + signal.provider + "," + + signal.symbol + "," + + ToString(signal.period) + + ") due Trading offTime ..."; + + // + Alert(msg); + } + } + else + { + // + // Only Alert Signals ... + string msg = (IsLong(signal.type) + ? "Long" + : "Short") + + " Signal Recieved: (" + + signal.provider + "," + + signal.symbol + "," + + ToString(signal.period) + + ") ..."; + + // + Alert(msg); + } + + // + signal.Clean(); + conditions.Clean(); + } + + // + // 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 = true; + + // + // Initialize Indicator Helpers ... + + // + X121XCCInputs xccInputs; + xccInputs.Default(); + xccInputs.showCandles = mShowCandles; + xccHelper = new XCX121XCCHelper(); + result = xccHelper.Init( + _Symbol, + _Period, + xccInputs // + ); + if (!result) + { + return result; + } + + // + X121XCTInputs xctInputs; + xctInputs.Default(); + xctHelper = new XCX121XCTHelper(); + result = xctHelper.Init( + _Symbol, + _Period, + xctInputs // + ); + 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.AddOnDealsChangedEventHandler(OnDealsChangedEventListener); + mTrader.AddOnOrdersChangedEventHandler(OnOrdersChangedEventListener); + mTrader.AddOnModifyPositionEventHandler(OnPositionModifiedEventListener); + mTrader.AddOnPositionsChangedEventHandler(OnPositionsChangedEventListener); + mTrader.AddOnForceClosePositionEventHandler(OnPositionForceCloseEventListener); + mTrader.AddOnPartialClosePositionEventHandler(OnPositionPartialCloseEventListener); + + // + // Initialize Trade Handler ... + mTradeHandler = new XC121SMCTradeHandler(mTrader); + mTradeHandler.SaveTrades(false); + mTradeHandler.SaveSignals(false); + mTradeHandler.SaveConditions(false); + + // + ReConfigureTradeHandler(); + + // + // Parsers ... + XSymbolParser _symbolParser; + + // + // Single Symbol ... + if (!MultiSymbol()) + { + // + // Register Strategy ... + + // + // Create Class Instance ... + XCX121SMCBaseStrategy *iX121SMCStrategy; + iX121SMCStrategy = new XCX121SMCStrategy( + _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 XCX121SMCStrategy( + iSymbol, + _Period // + ); + + // + iX121SMCStrategy.AddXSignalEventHandler(OnSignalEventListener); + + // + // Register Strategy ... + ConfigureStrategy(iX121SMCStrategy); + RegisterStrategy(iX121SMCStrategy); + } + } + + // + Clean(symbols); + } + + // + return result; + } + + /** + * Destroy all Initialized EA Requirements ... + */ + void DestroyEA() override + { + // + ZeroMemory(xccHelper); + ZeroMemory(xctHelper); + ZeroMemory(mTradeHandler); + + // + delete xccHelper; + delete xctHelper; + delete mTradeHandler; + + // + Clean(mStrategies); + } + + /** + * Call all Registered Strategies On Tick ... + */ + void HandleStrategiesOnTick() override + { + // + // Check Force Close ... + string forceCloseTimeStr = CloseAllTradesAt(); + if (IsValid(forceCloseTimeStr)) + { + // + datetime forceCloseTime = ParseDateTimeFromTimeString(forceCloseTimeStr); + bool canForceClose = IsTimeInRange( + TimeCurrent(), + forceCloseTime // + ) && + !mIsForceCloseAtTime; + if (canForceClose) + { + mIsForceCloseAtTime = mTradeHandler.ForceClose(); + } + } + + // + // Update Positions Data ... + mTradeHandler.UpdateData(); + + // + // Protect Positions ... + mTradeHandler.HandleProtection(); + + // + int count = ArraySize(mStrategies); + if (!IsValidSize(count)) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + // Call Tick Handler Function ... + mStrategies[i].HandleTick(); + } + } + + /** + * Handle Strategies Guards ... + */ + void HandleStrategiesGuard() override + { + // + int count = ArraySize(mStrategies); + if (!IsValidSize(count)) + { + return; + } + + // + XPosition positions[]; + int positionsCount = mTrader.GetPositions( + positions, // Result ... + NULL, // Symbol ... + NULL, // Provider ... + NULL, // Period ... + X_POSITION_TYPE_ALL // All Types ... + ); + if (!IsValidSize(positionsCount)) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + // Call Tick Handler Function ... + X121SMCGuard iGuards[]; + bool hasGuards = mStrategies[i].HandleGuard( + iGuards, + positions // + ); + if (hasGuards) + { + HandleGuards(iGuards); + } + } + + // + Clean(positions); + } + + // + // Event Handlers ... + + /** + * Calls When a Deals Changed Triggered ... + * + * @param count: Integer, Number of Changes ... + */ + void HandleOnDealsChanged(int count) override + { + } + + /** + * Calls When a Order Changed Triggered ... + * + * @param count: Integer, Number of Changes ... + */ + void HandleOnOrdersChanged(int count) override + { + } + + /** + * Calls When a Positions Changed Triggered ... + * + * @param count: Integer, Number of Changes ... + */ + void HandleOnPositionsChanged(int count) override + { + // + if (IsValidSize(count)) + { + mTradeHandler.HandleNewPosition(); + } + } + + /** + * 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 + { + // + mIsForceCloseAtTime = false; + mTradeHandler.ResumePausedSymbols(); + } + + /** + * Re Configure Materials on Properties Changed ... + */ + void ReConfigure() override + { + // + ReConfigureTradeHandler(); + ReConfigureAllStrategies(); + } + + /** + * 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 ... + + // + 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) + { + // + if (signal.ignoreEAVolume) + { + return; + } + + // + double staticVolume = Volume(); + double fVolume = staticVolume > 0 + ? staticVolume + : 0.01; + + // + double staticBalance = StaticBalance(); + double accountBalance = mTrader.mAccount.GetBalance(); + double balance = staticBalance > 0 + ? staticBalance + : accountBalance; + + // + bool useDynamicVolume = UseDynamicVolume(); + double balancePerTrade = BalancePerTrade(); + double dynamicVolumeStep = DynamicVolumeStep(); + double riskPercentPerBalance = RiskPercentPerBalance(); + bool allowDynamicRiskManagement = DynamicRiskManagement(); + double dynamicVolumeBalanceFactor = DynamicVolumeBalanceFactor(); + + // + // Apply Static Volume ... + bool allowStaticVolume = staticVolume > 0; + + // + // Apply Dynamic Volume ... + bool aloowApplyDynamicVolume = useDynamicVolume && + dynamicVolumeStep && + dynamicVolumeBalanceFactor; + + // + // Apply Risk Per Trade Volume ... + bool allowApplyRiskPerTradeVolume = + !aloowApplyDynamicVolume && + riskPercentPerBalance > 0; + + // + // Apply Balance Per Trade Volume ... + bool allowApplyBalacePerTradeVolume = + !aloowApplyDynamicVolume && + !allowApplyRiskPerTradeVolume && + balancePerTrade > 0; + + // + // First Check Dynamic Volume ... + if (aloowApplyDynamicVolume) + { + // + // Dynamic Volume ... + double dVolume = mTrader.GetDynamicVolume( + signal.symbol, + dynamicVolumeBalanceFactor, + dynamicVolumeStep // + ); + if (dVolume < fVolume) + { + dVolume = fVolume; + } + + // + signal.volume = dVolume; + } + else if (allowApplyRiskPerTradeVolume) + { + // + double riskAmountPerBalance = (riskPercentPerBalance * balance) / 100; + + // + double risk = signal.GetRisk(); + double points = GetPoints(signal.symbol); + double riskInPoints = risk / points; + + // + double volume = mTrader.mAccount.CalculateVolume( + signal.symbol, + riskAmountPerBalance, + riskInPoints // + ); + if (volume <= 0) + { + volume = fVolume; + } + + // + // 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; + } + + // + signal.volume = volume; + } + else if (allowApplyBalacePerTradeVolume) + { + // + double risk = signal.GetRisk(); + double points = GetPoints(signal.symbol); + double riskInPoints = risk / points; + + // + double volume = mTrader.mAccount.CalculateVolume( + signal.symbol, + balancePerTrade, + riskInPoints // + ); + if (volume <= 0) + { + volume = fVolume; + } + + // + signal.volume = volume; + } + else if (allowStaticVolume) + { + signal.volume = staticVolume; + } + else + { + signal.volume = fVolume; + } + + // + // Normalize Signal Volume ... + signal.volume = NormalizeVolume( + signal.volume, + signal.symbol // + ); + } + + /** + * 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]); + } + } + + /** + * Re Configure Trade Handler ... + */ + void ReConfigureTradeHandler() + { + // + if (mTradeHandler == NULL) + { + return; + } + + // + // Configure Alerts ... + mTradeHandler.SetAlertPrefix(GetTag()); + mTradeHandler.SetAlertEnableAlerts(GetAlertEnableAlerts()); + mTradeHandler.SetAlertLogAlerts(GetAlertLogAlerts()); + mTradeHandler.SetAlertMailAlerts(GetAlertMailAlerts()); + mTradeHandler.SetAlertPushAlerts(GetAlertPushAlerts()); + mTradeHandler.SetAlertTerminalAlerts(GetAlertTerminalAlerts()); + + // + mTradeHandler.AllowLong(AllowLong()); + mTradeHandler.AllowShort(AllowShort()); + mTradeHandler.MaxAllowedLongs(MaxAllowedLongs()); + mTradeHandler.MaxAllowedShorts(MaxAllowedShorts()); + mTradeHandler.UseMaxAllowedSignalsPerSymbol(UseMaxAllowedSignalsPerSymbol()); + mTradeHandler.LastPositionProfitForAcceptNextInPoint(LastPositionProfitForAcceptNextInPoint()); + mTradeHandler.DelaysBetweenTwoSignalsInBar(DelaysBetweenTwoSignalsInBar()); + mTradeHandler.MaxAllowedSpread(MaxAllowedSpread()); + mTradeHandler.MaxAllowedDrawdownToOpenTrades(MaxAllowedDrawdownToOpenTrades()); + mTradeHandler.MaxAllowedSLToPauseSignallingPerSymbol(MaxAllowedSLToPauseSignallingPerSymbol()); + mTradeHandler.PauseSignallingAfterReachesMaxAllowedSLInSecconds(PauseSignallingAfterReachesMaxAllowedSLInSecconds()); + mTradeHandler.AllowHedging(AllowHedging()); + mTradeHandler.MinOpenTradesFroHedging(MinOpenTradesFroHedging()); + mTradeHandler.HedgingMinVolumeStep(HedgingMinVolumeStep()); + mTradeHandler.HedgeingMinRequiredProfitPerVolumeStep(HedgeingMinRequiredProfitPerVolumeStep()); + } + + // + private: + // + + // + // Props ... + + // + bool mShowCandles; // Show Candles ... + + // + // Signalling Props ... + bool mAllowLong; // Allow Long Signals ... + bool mAllowShort; // Allow Short Signals ... + int mMaxAllowedLongs; // Max Allowed Long Signals ... + int mMaxAllowedShorts; // Max Allowed Short Signals ... + bool mUseMaxAllowedSignalsPerSymbol; // Use Max Allowed Signal Types Per Symbol ... + double mLastPositionProfitForAcceptNextInPoint; // Last Position Profit In Points for Accept new Signal ... + int mDelaysBetweenTwoSignalsInBar; // Delay between two Signals in Bars ... + double mMaxAllowedSpread; // Max Allowed Spread for Signalling ... + int mMinRequiredVerificationForSpreadPass; // Minimum Spread Verification for Signalling ... + + // + // Trade ... + bool mAllowTrade; // Allow Open Trade On Signals ... + string mStartTradeAt; // Enable Trade on Signals on Time ... + string mStopTradeAt; // Enable Trade on Signals on Time ... + string mCloseAllTradesAt; // Enable Close All Trades on Signals on Time ... + + // + bool mIsForceCloseAtTime; + + // + // Risk Management Props ... + double mR2R; // Signallers Risk to Reward Ratio ... + double mVolume; // Static Volume ... + double mStaticBalance; // Static Balance for Calculate Trade Volume ... + double mBalancePerTrade; // Balance Used in Each Trade ... + double mRiskPercentPerBalance; // Risk Percent Per Balance in Each Trade ... + bool mDynamicRiskManagement; // Dynamic Risk Management ... + bool mUseDynamicVolume; // Use Dynamic Volume ... + double mDynamicVolumeStep; // Increase Volume Step ... + double mDynamicVolumeBalanceFactor; // Balance Factor for Generate Dynamic Volume ... + double mMaxAllowedDrawdownToOpenTrades; // Max Allowed Drawdown for Open Trades ... + int mMaxAllowedSLToPauseSignallingPerSymbol; // Max Allowed SL for Pause Signalling Per Symbol ... + int mPauseSignallingAfterReachesMaxAllowedSLInSecconds; // Pause Signalling Per Symbol afte Max Allowed SL Reached In Seconds ... + + // + // Protection Props ... + bool mAllowHedging; // Allow Hedge Positions ... + int mMinOpenTradesFroHedging; // Minimum Open Positions for Hedging ... + double mHedgingMinVolumeStep; // Minimum Volume Step for Hedging ... + double mHedgeingMinRequiredProfitPerVolumeStep; // Minimum Required Profit Per Volume Step for Hedging ... + + // + 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; + } + + /** + * Handle Guard Actions ... + * + * @param guards: X121SMCGuard instance Collection ... + */ + void HandleGuards(X121SMCGuard &guards[]) + { + // + int count = ArraySize(guards); + if (!IsValidSize(guards)) + { + return; + } + + // + for (int i = 0; i < count; i++) + { + // + X121SMCGuard iGuard = guards[i]; + + // + if (!iGuard.IsValid()) + { + continue; + } + + // + // Here we Have to Handle Guard Actions ... + + // + // Close ... + bool canClose = + NotEmpty(iGuard.ticket) && + iGuard.action == X_121_SMC_GUARD_ACTION_CLOSE; + + // + // Close All ... + bool canCloseAll = iGuard.action == X_121_SMC_GUARD_ACTION_CLOSE_ALL; + + // + // Close Longs ... + bool canCloseLongs = iGuard.action == X_121_SMC_GUARD_ACTION_CLOSE_LONGS; + + // + // Close Shorts ... + bool canCloseShorts = iGuard.action == X_121_SMC_GUARD_ACTION_CLOSE_SHORTS; + + // + // Partial Close ... + bool canPartialClose = + NotEmpty(iGuard.ticket) && + iGuard.volumeMultiplier > 0 && + iGuard.action == X_121_SMC_GUARD_ACTION_PARTIAL_CLOSE; + + // + // Trail Stop ... + bool canTrailStop = + iGuard.sl > 0 && + NotEmpty(iGuard.ticket) && + iGuard.action == X_121_SMC_GUARD_ACTION_TRAIL_STOP; + + // + // Trail Target ... + bool canTrailTarget = + iGuard.tp > 0 && + NotEmpty(iGuard.ticket) && + iGuard.action == X_121_SMC_GUARD_ACTION_TRAIL_TARGET; + + // + // Hedge ... + bool canHedge = iGuard.action == X_121_SMC_GUARD_ACTION_HEDGE; + + // + // Check is Guard Valid ... + bool isValidGuardAction = + canHedge || + canClose || + canCloseAll || + canTrailStop || + canCloseLongs || + canTrailTarget || + canCloseShorts || + canPartialClose; + if (!isValidGuardAction) + { + continue; + } + + // + // Now we Sure to Have a Valid Guard ... + // Start to o Guard Actions ... + + // + // Close All ... + if (canCloseAll) + { + // + XPosition positions[]; + int positionsCount = + mTrader + .GetPositions( + positions, // Result ... + iGuard.symbol, + iGuard.provider, + NULL, // Period ... + X_POSITION_TYPE_ALL, // All Types ... + true // Filter by Magic ... + ); + if (IsValidSize(positionsCount)) + { + // + string comment = "Guard Close All ..."; + string message = "Guard Close All (" + ToString(positionsCount) + ") Positions Successfully ..."; + int forceClosed = mTradeHandler.ForceClose( + positions, + comment, + message // + ); + + // + if (forceClosed) + { + RestEA(120 * 60); + } + } + } + + // + // Close Longs ... + if (canCloseLongs) + { + // + XPosition longPositions[]; + XPosition shortPositions[]; + mTrader + .GetPositions( + longPositions, // Result ... + shortPositions, // Result ... + iGuard.symbol, + iGuard.provider, + NULL, // Period ... + true // Filter by Magic ... + ); + + // + int longPositionsCount = ArraySize(longPositions); + bool hasLongPositions = IsValidSize(longPositionsCount); + + // + int shortPositionsCount = ArraySize(shortPositions); + bool hasShortPositions = IsValidSize(shortPositionsCount); + + // + if (hasLongPositions) + { + // + string comment = "Guard Close Longs ..."; + string message = "Guard Close (" + ToString(longPositionsCount) + ") Long Positions Successfully ..."; + bool isClosed = mTradeHandler.ForceClose( + longPositions, + comment, + message // + ); + + // + if (isClosed) + { + RestEA(120 * 60); + } + } + } + + // + // Close Shorts ... + if (canCloseShorts) + { + // + XPosition longPositions[]; + XPosition shortPositions[]; + mTrader + .GetPositions( + longPositions, // Result ... + shortPositions, // Result ... + iGuard.symbol, + iGuard.provider, + NULL, // Period ... + true // Filter by Magic ... + ); + + // + int longPositionsCount = ArraySize(longPositions); + bool hasLongPositions = IsValidSize(longPositionsCount); + + // + int shortPositionsCount = ArraySize(shortPositions); + bool hasShortPositions = IsValidSize(shortPositionsCount); + + // + if (hasShortPositions) + { + // + string comment = "Guard Close Shorts ..."; + string message = "Guard Close (" + ToString(shortPositionsCount) + ") Short Positions Successfully ..."; + bool isClosed = mTradeHandler.ForceClose( + shortPositions, + comment, + message // + ); + + // + if (isClosed) + { + RestEA(120 * 60); + } + } + } + + // + // Close ... + if (canClose) + { + // + XPosition iPosition; + bool hasPosition = mTrader.GetPosition( + iGuard.ticket, + iPosition // + ); + + // + bool isLong = IsLong(iPosition.type); + + // + if (hasPosition) + { + // + XPosition positions[]; + AddRef( + iPosition, + positions // + ); + + // + string comment = "Guard Close ..."; + string message = "Guard Close " + (isLong ? "Long" : "Short") + " Position: (" + ToString(iGuard.ticket) + ") Successfully ..."; + bool isClosed = mTradeHandler.ForceClose( + positions, + comment, + message // + ); + + // + if (isClosed) + { + RestEA(120 * 60); + } + } + } + + // + // Partial Close ... + if (canPartialClose) + { + // + XPosition iPosition; + bool hasPosition = mTrader.GetPosition( + iGuard.ticket, + iPosition // + ); + + // + bool isLong = IsLong(iPosition.type); + + // + if (hasPosition) + { + // + // Normalize Volume Multiplier ... + double vMult = iGuard.volumeMultiplier; + if (vMult > 0.5) + { + vMult = 0.5; + } + if (vMult < 0) + { + vMult = 0.5; + } + + // + // Calculate and Normalize Volume ... + double volume = iPosition.volume * iGuard.volumeMultiplier; + volume = NormalizeVolume( + volume, + iPosition.symbol // + ); + + // + string comment = "Guard Partially Closed: " + ToString(volume) + " ..."; + string message = "Guard Partially Closed " + (isLong ? "Long" : "Short") + ": " + ToString(volume) + " Successfully ..."; + bool isModified = mTrader.ClosePartial( + iPosition.ticket, + volume, + comment // + ); + if (isModified) + { + // + mTradeHandler.Alert(message); + + // + if (volume == iPosition.volume) + { + // + mTradeHandler.Finish( + iPosition.ticket, + iPosition, + comment // + ); + + // + RestEA(120 * 60); + } + } + } + } + + // + // Hedge ... + if (canHedge) + { + // + XPosition positions[]; + int positionsCount = + mTrader + .GetPositions( + positions, // Result ... + iGuard.symbol, + iGuard.provider, + NULL, // Period ... + X_POSITION_TYPE_ALL, // All Types ... + true // Filter by Magic ... + ); + if (IsValidSize(positionsCount)) + { + // + int longs = 0; + double longProfits = 0; + double longVolumes = 0; + + // + int shorts = 0; + double shortProfits = 0; + double shortVolumes = 0; + CountPositions( + positions, + longs, + longProfits, + longVolumes, + shorts, + shortProfits, + shortVolumes // + ); + + // + int count = longs + shorts; + double profits = longProfits + shortProfits; + double volumes = longVolumes + shortVolumes; + + // + bool canDoHedge = + count > 0 && + profits > 0 && + volumes > 0; + if (canDoHedge) + { + // + string comment = "Guard Hedge ..."; + string message = "Guard Hedge (" + ToString(count) + ") Positions by: (" + ToString(profits) + ") Successfully ..."; + bool isClosed = mTradeHandler.ForceClose( + positions, + comment, + message // + ); + + // + if (isClosed) + { + RestEA(120 * 60); + } + } + } + } + + // + // Trail Stop ... + if (canTrailStop) + { + // + XPosition iPosition; + bool hasPosition = mTrader.GetPosition( + iGuard.ticket, + iPosition // + ); + + // + bool isLong = IsLong(iPosition.type); + + // + bool canDoTrail = + hasPosition && + iPosition.profit > 0 && + isLong + ? iPosition.price > iGuard.sl && + (iPosition.sl == 0 || + iPosition.sl < iGuard.sl) + : iPosition.price < iGuard.sl && + (iPosition.sl == 0 || + iPosition.sl > iGuard.sl); + if (canDoTrail) + { + // + string comment = "Guard Trail Stop ..."; + string message = "Guard Trail " + (isLong ? "Long" : "Short") + " Position: (" + ToString(iGuard.ticket) + ") Stop Successfully ..."; + bool isModified = mTrader.Modify( + iPosition.ticket, + iGuard.sl, + iPosition.tp, + comment // + ); + if (isModified) + { + mTradeHandler.Alert(message); + } + } + } + + // + // Trail Target ... + if (canTrailTarget) + { + // + XPosition iPosition; + bool hasPosition = mTrader.GetPosition( + iGuard.ticket, + iPosition // + ); + + // + bool isLong = IsLong(iPosition.type); + + // + bool canDoTrail = + hasPosition && + iGuard.tp != iPosition.tp && + isLong + ? iGuard.tp > iPosition.price + : iGuard.tp < iPosition.price; + if (canDoTrail) + { + // + string comment = "Guard Trail Target ..."; + string message = "Guard Trail " + (isLong ? "Long" : "Short") + " Position: (" + ToString(iGuard.ticket) + ") Target Successfully ..."; + bool isModified = mTrader.Modify( + iPosition.ticket, + iPosition.sl, + iGuard.tp, + comment // + ); + if (isModified) + { + mTradeHandler.Alert(message); + } + } + } + } + + // + Clean(guards); + Clean(guards); + } + + // + void RestEA(int seconds) + { + // + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14031218/X121SMCEA/Libraries/x-121.smc.guard.lib.ex5 b/BKPS/14031218/X121SMCEA/Libraries/x-121.smc.guard.lib.ex5 new file mode 100644 index 0000000..b6d7fc6 Binary files /dev/null and b/BKPS/14031218/X121SMCEA/Libraries/x-121.smc.guard.lib.ex5 differ diff --git a/BKPS/14031218/X121SMCEA/Libraries/x-121.smc.guard.lib.mq5 b/BKPS/14031218/X121SMCEA/Libraries/x-121.smc.guard.lib.mq5 new file mode 100644 index 0000000..864501d --- /dev/null +++ b/BKPS/14031218/X121SMCEA/Libraries/x-121.smc.guard.lib.mq5 @@ -0,0 +1,970 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 X121 SMC Signal Class +// ------------------------------------------------- +// Name: +// Description: provide all Global Guarding 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" + +// +bool DetectX121SMCGuards( + // + string signalProvider, // Provider ... + X121SMCGuard &guards[], + const XPosition &positions[], + X121SMCStrategySignalProviderData &provider, + // + // Guard Types ... + ENUM_X_121_SMC_GUARD_ACTIONS &ignoreGuards[], + // + // Required Configurations ... + double breakEvenTPLevel = 2.0 + // +) +{ + // + bool result = false; + + // // + // bool isCycleHelpersValid = + // // + // visionCycleHelper != NULL && + // analyseCycleHelper != NULL && + // decisionCycleHelper != NULL && + // consolidationCycleHelper != NULL + // // + // ; + + // // + // // Ignore Guards ... + // bool hasIgnoreGuards = HasChild(ignoreGuards); + // bool isColseIgnored = + // hasIgnoreGuards && + // Contains( + // X_121_SMC_GUARD_ACTION_CLOSE, + // ignoreGuards // + // ); + // bool isColseAllIgnored = + // hasIgnoreGuards && + // Contains( + // X_121_SMC_GUARD_ACTION_CLOSE_ALL, + // ignoreGuards // + // ); + // bool isColseLongsIgnored = + // hasIgnoreGuards && + // Contains( + // X_121_SMC_GUARD_ACTION_CLOSE_LONGS, + // ignoreGuards // + // ); + // bool isColseShortsIgnored = + // hasIgnoreGuards && + // Contains( + // X_121_SMC_GUARD_ACTION_CLOSE_SHORTS, + // ignoreGuards // + // ); + // bool isPartialColseIgnored = + // hasIgnoreGuards && + // Contains( + // X_121_SMC_GUARD_ACTION_PARTIAL_CLOSE, + // ignoreGuards // + // ); + // bool isTrailStopIgnored = + // hasIgnoreGuards && + // Contains( + // X_121_SMC_GUARD_ACTION_TRAIL_STOP, + // ignoreGuards // + // ); + // bool isTrailTargetIgnored = + // hasIgnoreGuards && + // Contains( + // X_121_SMC_GUARD_ACTION_TRAIL_TARGET, + // ignoreGuards // + // ); + // bool isHedgeIgnored = + // hasIgnoreGuards && + // Contains( + // X_121_SMC_GUARD_ACTION_HEDGE, + // ignoreGuards // + // ); + + // // + // bool isAllIgnores = + // // + // isColseIgnored && + // isHedgeIgnored && + // isColseAllIgnored && + // isTrailStopIgnored && + // isColseLongsIgnored && + // isColseShortsIgnored && + // isTrailTargetIgnored && + // isPartialColseIgnored + // // + // ; + // result = !isAllIgnores && + // isCycleHelpersValid; + // if (!result) + // { + // return result; + // } + + // // + // int count = ArraySize(positions); + // result = IsValidSize(count); + // if (!result) + // { + // return result; + // } + + // // + // string symbol = decisionCycleHelper.GetSymbol(); + // ENUM_TIMEFRAMES period = decisionCycleHelper.GetPeriod(); + + // // + // XPosition ownPositions[]; + // XPosition ownLongPositions[]; + // XPosition ownShortPositions[]; + // for (int i = 0; i < count; i++) + // { + // // + // XPosition iPosition = positions[i]; + // bool isOwn = iPosition + // .IsFiltersPassed( + // symbol, + // provider, + // NULL, + // X_POSITION_TYPE_ALL, + // iPosition.magic // + // ); + // if (isOwn) + // { + // // + // AddRef( + // iPosition, + // ownPositions // + // ); + + // // + // bool isLong = IsLong(positions[i].type); + // if (isLong) + // { + // // + // AddRef( + // iPosition, + // ownLongPositions // + // ); + // } + // else + // { + // // + // AddRef( + // iPosition, + // ownShortPositions // + // ); + // } + // } + // } + + // // + // count = ArraySize(ownPositions); + + // // + // int longsCount = ArraySize(ownLongPositions); + // bool hasLongs = IsValidSize(longsCount); + + // // + // int shortsCount = ArraySize(ownShortPositions); + // bool hasShorts = IsValidSize(shortsCount); + + // // + // result = IsValidSize(count); + // if (!result) + // { + // // + // Clean(ownPositions); + // Clean(ownLongPositions); + // Clean(ownShortPositions); + + // // + // return result; + // } + + // // + // // Here we Are Sure there is Positions to Guard ... + // // based on Current Provider ... + + // // + // // Detect Required Data for Analyse Market to Guard Positions ... + + // // + // int zIndex = 0; + // int cIndex = zIndex + 1; + // int pIndex = cIndex + 1; + // int ppIndex = pIndex + 1; + + // // + // int loopback = 10; + + // // + // XOHCL zBar; + // result = zBar.Init( + // symbol, + // period, + // zIndex // + // ); + // if (!result) + // { + // // + // zBar.Clean(); + // result = HasChild(guards); + // return result; + // } + + // // + // XOHCL cBar; + // result = cBar.Init( + // symbol, + // period, + // cIndex // + // ); + // if (!result) + // { + // // + // zBar.Clean(); + // cBar.Clean(); + // result = HasChild(guards); + // return result; + // } + + // // + // XOHCL pBar; + // result = pBar.Init( + // symbol, + // period, + // pIndex // + // ); + // if (!result) + // { + // // + // zBar.Clean(); + // cBar.Clean(); + // pBar.Clean(); + // result = HasChild(guards); + // return result; + // } + + // // + // XOHCL ppBar; + // result = ppBar.Init( + // symbol, + // period, + // ppIndex // + // ); + // if (!result) + // { + // // + // zBar.Clean(); + // cBar.Clean(); + // pBar.Clean(); + // ppBar.Clean(); + // result = HasChild(guards); + // return result; + // } + + // // + // double ask = GetAsk(symbol); + // double bid = GetBid(symbol); + // datetime cTime = TimeCurrent(); + // double points = GetPoints(symbol); + + // // + + // // + // // Cycles Conditions ... + + // // + // // Decision ... + // ENUM_XPOI_EVENTS decisionPoiEvents[]; + // ENUM_X_CYCLE_EVENTS decisionCycleEvents[]; + // X121SMCCycleConditions decisionConditions; + // result = decisionCycleHelper.GetConditions( + // decisionCycleEvents, + // decisionPoiEvents, + // decisionConditions, + // zIndex, + // loopback // + // ); + // if (!result) + // { + // // + // zBar.Clean(); + // cBar.Clean(); + // pBar.Clean(); + // ppBar.Clean(); + // result = HasChild(guards); + + // // + // Clean(decisionPoiEvents); + // Clean(decisionCycleEvents); + + // // + // decisionConditions.Clean(); + // return result; + // } + + // // + // // Analyse ... + // ENUM_XPOI_EVENTS analysePoiEvents[]; + // ENUM_X_CYCLE_EVENTS analyseCycleEvents[]; + // X121SMCCycleConditions analyseConditions; + // result = analyseCycleHelper.GetConditions( + // analyseCycleEvents, + // analysePoiEvents, + // analyseConditions, + // zIndex, + // loopback // + // ); + // if (!result) + // { + // // + // zBar.Clean(); + // cBar.Clean(); + // pBar.Clean(); + // ppBar.Clean(); + + // // + // Clean(decisionPoiEvents); + // Clean(decisionCycleEvents); + + // // + // decisionConditions.Clean(); + + // // + // Clean(analysePoiEvents); + // Clean(analyseCycleEvents); + + // // + // analyseConditions.Clean(); + + // // + // result = HasChild(guards); + // return result; + // } + + // // + // // Consolidation ... + // ENUM_XPOI_EVENTS consolidationPoiEvents[]; + // ENUM_X_CYCLE_EVENTS consolidationCycleEvents[]; + // X121SMCCycleConditions consolidationConditions; + // result = consolidationCycleHelper.GetConditions( + // consolidationCycleEvents, + // consolidationPoiEvents, + // consolidationConditions, + // zIndex, + // loopback // + // ); + // if (!result) + // { + // // + // zBar.Clean(); + // cBar.Clean(); + // pBar.Clean(); + // ppBar.Clean(); + + // // + // Clean(decisionPoiEvents); + // Clean(decisionCycleEvents); + + // // + // decisionConditions.Clean(); + + // // + // Clean(analysePoiEvents); + // Clean(analyseCycleEvents); + + // // + // analyseConditions.Clean(); + + // // + // Clean(consolidationPoiEvents); + // Clean(consolidationCycleEvents); + + // // + // consolidationConditions.Clean(); + + // // + // result = HasChild(guards); + // return result; + // } + + // // + // // Vision ... + // ENUM_XPOI_EVENTS visionPoiEvents[]; + // ENUM_X_CYCLE_EVENTS visionCycleEvents[]; + // X121SMCCycleConditions visionConditions; + // result = visionCycleHelper.GetConditions( + // visionCycleEvents, + // visionPoiEvents, + // visionConditions, + // zIndex, + // loopback // + // ); + // if (!result) + // { + // // + // zBar.Clean(); + // cBar.Clean(); + // pBar.Clean(); + // ppBar.Clean(); + + // // + // Clean(decisionPoiEvents); + // Clean(decisionCycleEvents); + + // // + // decisionConditions.Clean(); + + // // + // Clean(analysePoiEvents); + // Clean(analyseCycleEvents); + + // // + // analyseConditions.Clean(); + + // // + // Clean(consolidationPoiEvents); + // Clean(consolidationCycleEvents); + + // // + // consolidationConditions.Clean(); + + // // + // Clean(visionPoiEvents); + // Clean(visionCycleEvents); + + // // + // visionConditions.Clean(); + + // // + // result = HasChild(guards); + // return result; + // } + + // // + // // Cycles POI States ... + // XPOIState decisionState = decisionConditions.state; + // XPOIState analyseState = analyseConditions.state; + // XPOIState consolidationState = consolidationConditions.state; + // XPOIState visionState = visionConditions.state; + + // // + // // Cycle X121Conditions ... + // X121Conditions decisionXConditions = decisionConditions.x121Conditions; + // X121Conditions analyseXConditions = analyseConditions.x121Conditions; + // X121Conditions consolidationXConditions = consolidationConditions.x121Conditions; + // X121Conditions visionXConditions = visionConditions.x121Conditions; + + // // + // // + // // + + // // // + // // // Detect Consolidation Zone ... + + // // // + // // // Detect Consolidation Zones ... + + // // // + // // XBoxZone lastBullishBox; + // // XBoxZone prevLastBullishBox; + // // bool hasLastBullishBox = false; + // // bool hasPrevLastBullishBox = false; + // // XConsolidationZone lastBullishZone; + // // bool isLastBullishAbovePrev = false; + // // bool isLastBullishBelowPrev = false; + // // XConsolidationZone prevLastBullishZone; + + // // // + // // XBoxZone lastBearishBox; + // // XBoxZone prevLastBearishBox; + // // bool hasLastBearishBox = false; + // // bool hasPrevLastBearishBox = false; + // // XConsolidationZone lastBearishZone; + // // bool isLastBearishAbovePrev = false; + // // bool isLastBearishBelowPrev = false; + // // XConsolidationZone prevLastBearishZone; + + // // // + // // int bullishConsolidationZonesCount = 0; + // // int bearishConsolidationZonesCount = 0; + // // bool hasBullishConsolidationZones = false; + // // bool hasBearishConsolidationZones = false; + // // XConsolidationZone bullishConsolidationZones[]; + // // XConsolidationZone bearishConsolidationZones[]; + // // bool hasConsolidationZones = decisionCycleHelper.HasConsolidationZones(); + // // int consolidationZonesCount = decisionCycleHelper.CountConsolidationZones(); + // // if (hasConsolidationZones) + // // { + // // // + // // bullishConsolidationZonesCount = decisionCycleHelper + // // .FillConsolidationZones( + // // X_DIRECTION_BULLISH, + // // bullishConsolidationZones // + // // ); + // // hasBullishConsolidationZones = IsValidSize(bullishConsolidationZonesCount); + + // // // + // // bearishConsolidationZonesCount = decisionCycleHelper + // // .FillConsolidationZones( + // // X_DIRECTION_BEARISH, + // // bearishConsolidationZones // + // // ); + // // hasBearishConsolidationZones = IsValidSize(bearishConsolidationZonesCount); + + // // // + // // // + // // // + + // // // + // // if (hasBullishConsolidationZones && + // // bullishConsolidationZonesCount >= 2) + // // { + // // // + // // lastBullishZone = bullishConsolidationZones[bullishConsolidationZonesCount - 1]; + // // prevLastBullishZone = bullishConsolidationZones[bullishConsolidationZonesCount - 2]; + + // // // + // // hasLastBullishBox = ToBox( + // // lastBullishBox, + // // lastBullishZone // + // // ); + // // hasPrevLastBullishBox = ToBox( + // // prevLastBullishBox, + // // prevLastBullishZone // + // // ); + + // // // + // // isLastBullishAbovePrev = hasLastBullishBox && + // // hasPrevLastBullishBox && + // // IsBoxAbove( + // // lastBullishBox, + // // prevLastBullishBox // + // // ); + + // // // + // // isLastBullishBelowPrev = hasLastBullishBox && + // // hasPrevLastBullishBox && + // // IsBoxBelow( + // // lastBullishBox, + // // prevLastBullishBox // + // // ); + // // } + + // // // + // // if (hasBearishConsolidationZones && + // // bearishConsolidationZonesCount >= 2) + // // { + // // // + // // lastBearishZone = bearishConsolidationZones[bearishConsolidationZonesCount - 1]; + // // prevLastBearishZone = bearishConsolidationZones[bearishConsolidationZonesCount - 2]; + + // // // + // // hasLastBearishBox = ToBox( + // // lastBearishBox, + // // lastBearishZone // + // // ); + // // hasPrevLastBearishBox = ToBox( + // // prevLastBearishBox, + // // prevLastBearishZone // + // // ); + + // // // + // // isLastBearishAbovePrev = hasLastBearishBox && + // // hasPrevLastBearishBox && + // // IsBoxAbove( + // // lastBearishBox, + // // prevLastBearishBox // + // // ); + + // // // + // // isLastBearishBelowPrev = hasLastBearishBox && + // // hasPrevLastBearishBox && + // // IsBoxBelow( + // // lastBearishBox, + // // prevLastBearishBox // + // // ); + // // } + + // // // + // // } + + // // + // // Detect High Probability Swings ... + // // bool isSwingLow = + // // // + // // cBar.low > pBar.low && + // // ppBar.low > pBar.low && + // // // + // // zBar.low > pBar.low + // // // + // // ; + // // bool isSwingHigh = + // // // + // // cBar.high < pBar.high && + // // ppBar.high < pBar.high && + // // // + // // zBar.high < pBar.high + // // // + // // ; + // // bool isStrongSwingLow = + // // pBar.IsBullish() && + // // pBar.GetLowShadow() >= pBar.GetBody() * 2; + // // bool isStrongSwingHigh = + // // pBar.IsBearish() && + // // pBar.GetHighShadow() >= pBar.GetBody() * 2; + + // // // + // // bool isStrongSwingLowAboveLastBullishBox = + // // isStrongSwingLow && + // // hasLastBullishBox && + // // pBar.low > lastBullishBox.upper; + + // // // + // // bool isStrongSwingHighBelowLastBearishBox = + // // isStrongSwingHigh && + // // hasLastBearishBox && + // // pBar.high < lastBearishBox.lower; + + // // + // // Here We Have all Requirements for Guarding Positions ... + + // // + // // Available Guards: + // // X_121_SMC_GUARD_ACTION_NONE + // // X_121_SMC_GUARD_ACTION_CLOSE + // // X_121_SMC_GUARD_ACTION_CLOSE_ALL + // // X_121_SMC_GUARD_ACTION_CLOSE_LONGS + // // X_121_SMC_GUARD_ACTION_CLOSE_SHORTS + // // X_121_SMC_GUARD_ACTION_PARTIAL_CLOSE + // // X_121_SMC_GUARD_ACTION_TRAIL_STOP + // // X_121_SMC_GUARD_ACTION_TRAIL_TARGET + // // X_121_SMC_GUARD_ACTION_HEDGE + + // // + // // X_121_SMC_GUARD_ACTION_CLOSE: + // // Close Specified Position on Specified Conditions ... + // if (!isColseIgnored) + // { + // // + // // TODO: + // // - [] Implement Close on Nearest on TP ... + // } + + // // + // // X_121_SMC_GUARD_ACTION_CLOSE_ALL: + // // Close All Positions on Specified Conditions ... + // if (!isColseAllIgnored) + // { + // // + // // TODO: + // // - [] Implement Close All Positions on Weekend ... + // } + + // // + // // X_121_SMC_GUARD_ACTION_CLOSE_LONGS: + // // Close All Long Positions on Specified Conditions ... + // if (!isColseLongsIgnored) + // { + // // + // } + + // // + // // X_121_SMC_GUARD_ACTION_CLOSE_SHORTS: + // // Close All Short Positions on Specified Conditions ... + // if (!isColseShortsIgnored) + // { + // // + // } + + // // + // // X_121_SMC_GUARD_ACTION_PARTIAL_CLOSE: + // // Partial Close Specified Position on Specified Conditions ... + // if (!isPartialColseIgnored) + // { + // // + // // Breake Even ... + // // Usually Break Even Works on TP2 Reached ... + // // when tp reached to required Level, we Close 50% of Entered Volume ... + // bool canBreakEven = breakEvenTPLevel >= 0; + + // // + // for (int i = 0; i < count; i++) + // { + // // + // XPosition iPosition = ownPositions[i]; + + // // + // bool isInProfit = iPosition.profit > 0; + + // // + // double reachedTPLevel = 0; + // double reachedTPPrice = 0; + // if (isInProfit) + // { + // // + // iPosition.CalculateReahedTP( + // reachedTPLevel, + // reachedTPPrice // + // ); + // } + + // // + // // Break Event ... + // if (canBreakEven) + // { + // // + // // Position Must be In Profit ... + // if (!isInProfit) + // { + // continue; + // } + + // // + // bool canDoBreakEven = reachedTPLevel == breakEvenTPLevel && + // reachedTPPrice > 0; + // if (canDoBreakEven) + // { + // // + // X121SMCGuard iGuard; + + // // + // iGuard.time = cTime; + // iGuard.symbol = symbol; + // iGuard.provider = provider; + // iGuard.action = X_121_SMC_GUARD_ACTION_PARTIAL_CLOSE; + + // // + // iGuard.ticket = iPosition.ticket; + + // // + // iGuard.volumeMultiplier = 0.5; + + // // + // AddGuard( + // iGuard, + // guards // + // ); + // } + // } + // } + // } + + // // + // // X_121_SMC_GUARD_ACTION_TRAIL_STOP: + // // Trail Stop Specified Position on Specified Conditions ... + // if (!isTrailStopIgnored) + // { + // // + // for (int i = 0; i < count; i++) + // { + // // + // XPosition iPosition = ownPositions[i]; + + // // + // bool isLong = IsLong(iPosition.type); + // bool isInProfit = iPosition.profit > 0; + + // // + // double reachedTPLevel = 0; + // double reachedTPPrice = 0; + // if (isInProfit) + // { + // // + // iPosition.CalculateReahedTP( + // reachedTPLevel, + // reachedTPPrice // + // ); + // } + + // // + // // Trai Stop ... + // if (!isInProfit) + // { + // continue; + // } + + // // + // double trailedStop = 0; + + // // + // // Trail Stop Senarios ... + // // - occures two same type consolidation zones in order of positions type; + // // - occures a swing in order of consolidation zones ... + + // // // + // // bool canTrailBasedOnTwoZone = + // // isLong + // // ? isLastBullishAbovePrev + // // : isLastBearishBelowPrev; + // // if (canTrailBasedOnTwoZone) + // // { + // // // + // // trailedStop = + // // isLong + // // ? prevLastBullishBox.lower + // // : prevLastBearishBox.upper; + // // } + + // // // + // // bool canTrailBasedOnZoneSwing = + // // trailedStop <= 0 && + // // (isLong + // // ? isStrongSwingLowAboveLastBullishBox + // // : isStrongSwingHighBelowLastBearishBox); + // // if (canTrailBasedOnZoneSwing) + // // { + // // // + // // trailedStop = + // // isLong + // // ? pBar.low + // // : pBar.high; + // // } + + // // // + // // bool canDoTrailStop = + // // trailedStop > 0 && + // // ( + // // // + // // iPosition.sl == 0 + // // ? (isLong + // // ? trailedStop > iPosition.entry && + // // trailedStop < iPosition.price + // // : trailedStop < iPosition.entry && + // // trailedStop > iPosition.price) + // // : (isLong + // // ? trailedStop > iPosition.sl && + // // trailedStop > iPosition.entry && + // // trailedStop < iPosition.price + // // : trailedStop < iPosition.sl && + // // trailedStop < iPosition.entry && + // // trailedStop > iPosition.price) + // // // + // // ) + // // // + // // ; + + // // // + // // if (canDoTrailStop) + // // { + // // // + // // X121SMCGuard iGuard; + + // // // + // // iGuard.time = cTime; + // // iGuard.symbol = symbol; + // // iGuard.provider = provider; + // // iGuard.action = X_121_SMC_GUARD_ACTION_TRAIL_STOP; + + // // // + // // iGuard.ticket = iPosition.ticket; + + // // // + // // iGuard.sl = trailedStop; + + // // // + // // AddGuard( + // // iGuard, + // // guards // + // // ); + // // } + // } + // } + + // // + // // X_121_SMC_GUARD_ACTION_TRAIL_TARGET: + // // Trail Target Specified Position on Specified Conditions ... + // if (!isTrailTargetIgnored) + // { + // // + // } + + // // + // // X_121_SMC_GUARD_ACTION_HEDGE: + // // Hedge all Positions on Specified Conditions ... + // if (!isHedgeIgnored) + // { + // // + // } + + // // + // // Cleanup Collections ... + + // // + // Clean(ownPositions); + // Clean(ownLongPositions); + // Clean(ownShortPositions); + + // // + // zBar.Clean(); + // cBar.Clean(); + // pBar.Clean(); + // ppBar.Clean(); + + // // + // Clean(visionPoiEvents); + // Clean(analysePoiEvents); + // Clean(visionCycleEvents); + // Clean(decisionPoiEvents); + // Clean(analyseCycleEvents); + // Clean(decisionCycleEvents); + // Clean(consolidationPoiEvents); + // Clean(consolidationCycleEvents); + + // // + // visionState.Clean(); + // analyseState.Clean(); + // decisionState.Clean(); + // visionConditions.Clean(); + // analyseConditions.Clean(); + // visionXConditions.Clean(); + // decisionConditions.Clean(); + // consolidationState.Clean(); + // analyseXConditions.Clean(); + // decisionXConditions.Clean(); + // consolidationConditions.Clean(); + // consolidationXConditions.Clean(); + + // // + // // lastBullishBox.Clean(); + // // lastBearishBox.Clean(); + // // lastBullishZone.Clean(); + // // lastBearishZone.Clean(); + // // prevLastBullishBox.Clean(); + // // prevLastBearishBox.Clean(); + // // prevLastBullishZone.Clean(); + // // prevLastBearishZone.Clean(); + + // // + // count = ArraySize(guards); + // result = IsValidSize(count); + + // + return result; +} diff --git a/BKPS/14031218/X121SMCEA/Libraries/x-121.smc.lib.ex5 b/BKPS/14031218/X121SMCEA/Libraries/x-121.smc.lib.ex5 new file mode 100644 index 0000000..ee69879 Binary files /dev/null and b/BKPS/14031218/X121SMCEA/Libraries/x-121.smc.lib.ex5 differ diff --git a/BKPS/14031218/X121SMCEA/Libraries/x-121.smc.lib.mq5 b/BKPS/14031218/X121SMCEA/Libraries/x-121.smc.lib.mq5 new file mode 100644 index 0000000..b411b86 --- /dev/null +++ b/BKPS/14031218/X121SMCEA/Libraries/x-121.smc.lib.mq5 @@ -0,0 +1,737 @@ +/////////////////////////////////////////////////////// +// +// 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 "../../Classes/x-saherelm.x-poi.drawer.class.mq5" +#include "../../Helpers/x-saherelm.x121.helper.mq5" +#include "../../Libraries/x-saherelm.common.lib.mq5" +#include "../../Libraries/x-saherelm.x-poi.extensions.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 X121SMCXWZToken = "X121XWZ"; + +// +// X121 SMC Providers ... +enum ENUM_X_121_SMC_PROVIDERS +{ + // + X_121_SMC_PROVIDER_NONE, + X_121_SMC_PROVIDER_XWZ, +}; + +// +// Guard Actions ... +enum ENUM_X_121_SMC_GUARD_ACTIONS +{ + X_121_SMC_GUARD_ACTION_NONE, // Nothing to Do + X_121_SMC_GUARD_ACTION_CLOSE, // Close Specified Position + X_121_SMC_GUARD_ACTION_CLOSE_ALL, // Close All Positions + X_121_SMC_GUARD_ACTION_CLOSE_LONGS, // Close All Long Positions + X_121_SMC_GUARD_ACTION_CLOSE_SHORTS, // Close All Short Position + X_121_SMC_GUARD_ACTION_PARTIAL_CLOSE, // Partial Close Specified Position + X_121_SMC_GUARD_ACTION_TRAIL_STOP, // Trail Stop of Specified Position + X_121_SMC_GUARD_ACTION_TRAIL_TARGET, // Trail Target of Specified Position + X_121_SMC_GUARD_ACTION_HEDGE, // Hedge Specified Positions +}; + +// +// Each Market Cycle (Time Frame) Conditions +// Model as this Structure ... +struct X121SMCCycleConditions +{ + // + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + XPOIState state; + X121Conditions x121Conditions; + + // + void X121SMCStrategyConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + symbol = NULL; + period = NULL; + time = NULL; + + // + state.Clean(); + x121Conditions.Clean(); + + // + ZeroMemory(this); + } + + /** + * 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; + + // + double sl; + double tp; + string provider; + double targets[]; + ENUM_X_DIRECTION signalDir; + + // + void X121SMCStrategyConditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + time = NULL; + symbol = NULL; + period = NULL; + + // + sl = 0; + tp = 0; + provider = NULL; + signalDir = X_DIRECTION_NONE; + + // + Clean(targets); + + // + ZeroMemory(this); + } + + /** + * 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; + } + + // +}; + +// +// Model a Guard Action ... +struct X121SMCGuard +{ + // + // Props ... + ENUM_X_121_SMC_GUARD_ACTIONS action; + datetime time; + + // + string symbol; + string provider; + + // + // Specified Position ... + ulong ticket; + + // + // Partial Close ... + double volumeMultiplier; + + // + // SL Trial ... + double sl; + + // + // TP Trial ... + double tp; + + // + // Constructor ... + X121SMCGuard() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + time = NULL; + action = X_121_SMC_GUARD_ACTION_NONE; + + // + symbol = NULL; + provider = NULL; + + // + ticket = 0; + + // + volumeMultiplier = 0; + + // + sl = 0; + tp = 0; + + // + ZeroMemory(this); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsValid(time) && + IsValid(symbol) && + IsValid(provider) && + action != X_121_SMC_GUARD_ACTION_NONE + // + ; + if (!result) + { + return result; + } + + // + // Validate Model Based On Specified Guard Actions ... + + // + return result; + } +}; + +/** + * Add Guard to Collection ... + * + * @param guard: X121SMCGuard instance ... + * @param guards: X121SMCGuard instance Collection ... + * + * @return ( int ) + */ +int AddGuard( + X121SMCGuard &guard, + X121SMCGuard &guards[] // +) +{ + // + int result = 0; + + // + if (!guard.IsValid()) + { + return result; + } + + // + AddRef( + guard, + guards // + ); + + // + result = ArraySize(guards); + + // + return result; +} + +// +// +// + +typedef void (*TOnX121SMCSignal)( + XSignal &signal, + X121SMCStrategyConditions &conditions // +); + +// +// Extentions ... + +/** + * 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_XWZ: + result = X121SMCXWZToken; + 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(X121SMCXWZToken, value)) + { + result = X_121_SMC_PROVIDER_XWZ; + } + + // + return result; +} + +// diff --git a/BKPS/14031218/X121SMCEA/Signals/x-121.smc.xwz.signal.class.ex5 b/BKPS/14031218/X121SMCEA/Signals/x-121.smc.xwz.signal.class.ex5 new file mode 100644 index 0000000..4773c5c Binary files /dev/null and b/BKPS/14031218/X121SMCEA/Signals/x-121.smc.xwz.signal.class.ex5 differ diff --git a/BKPS/14031218/X121SMCEA/Signals/x-121.smc.xwz.signal.class.mq5 b/BKPS/14031218/X121SMCEA/Signals/x-121.smc.xwz.signal.class.mq5 new file mode 100644 index 0000000..ee6631b --- /dev/null +++ b/BKPS/14031218/X121SMCEA/Signals/x-121.smc.xwz.signal.class.mq5 @@ -0,0 +1,1765 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 X121 SMC Signal Class +// ------------------------------------------------- +// Name: XWZ +// 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.guard.lib.mq5" +#include "../Libraries/x-121.smc.lib.mq5" +#include "./x-121.smc.xwz.signal.lib.mq5" + +// +// Definition ... +class XCX121SMCXWZSignalDetector : public XCBase +{ + // + public: + // + // Props ... + X121SMCStrategyXWZWorkingZone workingZone; + X121SMCStrategyXWZSignalConditions mConditions; + X121SMCStrategyXWZSignalConditions mConditionsCollection[]; + + // + // Constructor(s) ... + XCX121SMCXWZSignalDetector( + string _symbol, + ENUM_TIMEFRAMES _period // + ) + { + // + symbol = _symbol; + period = _period; + Init(); + } + + // + // Deconstructor ... + ~XCX121SMCXWZSignalDetector() + { + DeInit(); + } + + // + // + // + + // + // Detect Setup Conditions ... + bool DetectSignalSetup( + // + X121SMCStrategySignalProviderData &provider, + // + double maxAllowedSLDistanceInPoint = 300 + // + ) + { + // + bool result = false; + + // + // Validate Cycle Helpers ... + result = provider.IsValid(); + if (!result) + { + // + mConditions.Clean(); + + // + return result; + } + + // + bool isBullish = false; + bool isBearish = false; + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + int loopback = 10; + + // + mConditions.symbol = symbol; + mConditions.period = period; + + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + double points = GetPoints(symbol); + + // + // Cycles Conditions ... + result = provider.Prepare( + zIndex, + loopback // + ); + if (!result) + { + // + mConditions.Clean(); + return result; + } + + // + // Select Drawer Class ... + XCPOIDrawer *drawer = provider.visionCycleHelper.mPOIDrawer; + + // + XOHCL consolidationZBar; + result = provider.consolidationCycleHelper.GetBar( + consolidationZBar, + zIndex // + ); + if (!result) + { + // + consolidationZBar.Clean(); + return result; + } + + // + bool drawBar = false; + if (drawBar) + { + // + DrawBar( + consolidationZBar, + drawer // + ); + } + + // + // + // + + // + // Setup Conditions ... + double sls[]; + double sl = 0; + double pivot = 0; + double point = 0; + double targets[]; + double reward = 0; + XBoxZone signalBox; + bool hasPriority = false; + int activatedFVGIDX = -1; + int activatedZoneIDX = -1; + double amountPercent = -1; + bool hasSignalBox = false; + bool hasWaitingZones = false; + bool hasWaitingBoxes = false; + bool hasRewardAmount = false; + bool isSignalBoxReversal = false; + bool hasWorkingZoneOveralDirection = false; + ENUM_X_DIRECTION wzOveralDir = X_DIRECTION_NONE; + ENUM_X_DIRECTION signalBoxDir = X_DIRECTION_NONE; + ENUM_X121SMC_XWZ_PRIORITY priority = X121SMC_XWZ_PRIORITY_NONE; + ENUM_X121SMC_XWZ_PROVIDERS signalProvider = X121SMC_XWZ_PROVIDER_NONE; + + // + // + // + + // + // First We Have to Has Working Zone ... + bool hasWorkingZone = workingZone.IsValid(); + if (!hasWorkingZone) + { + // + hasWorkingZone = workingZone.Init( + symbol, + period, + zIndex, + provider // + ); + } + + // + // Update Working Zone ... + if (hasWorkingZone) + { + // + // Reset POI Detector Required POI(s) ... + provider.MaxRequiredPOIs(50); + + // + // Reset POI Detector Allowed Loopback ... + provider.MaxAllowedLoopbackForInit(578); + + // + // Check Working Zone Overal Direction ... + hasWorkingZoneOveralDirection = workingZone + .DetectOveralDirection(wzOveralDir); + + // + // Detect Zones and Boxes ... + hasWaitingZones = workingZone.DetectZone( + provider // + ); + + // + hasWaitingBoxes = workingZone.HasWaitingBoxes(); + + // + // Checking Working Zone Destory or not ... + bool isWorkingZoneDestroyed = workingZone.IsDestroyed( + zIndex, + period // + ); + + // + // Cleanup WorkingZone and ignore all conditions ... + if (isWorkingZoneDestroyed) + { + // + result = false; + workingZone.Clean(); + hasWorkingZone = false; + + // + // Cleanup Resources ... + provider.Clean(); + + // + mConditions.Clean(); + consolidationZBar.Clean(); + + // + return result; + } + } + + // + // Start Draw ... + // + + // + UpdateTo(cTime); + + // + // Draw Working Zone ... + if (hasWorkingZone) + { + // + workingZone.Draw( + drawer, + // + true, // Draw Supply Zone ... + true, // Draw Demand Zone ... + true // Draw Waiting Zones ... + // + ); + } + + // + // End Draw ... + // + + // + // Detect Signal Box ... + + // + bool isZoneActivated = + hasWorkingZone && + hasWaitingZones && + workingZone.IsZoneActivated( + activatedZoneIDX, + activatedFVGIDX, + signalBoxDir, + signalProvider, + provider, + zIndex // + ); + + // + // hasSignalBox = + // hasWorkingZone && + // hasWaitingBoxes && + // workingZone.IsBoxActivated( + // signalBox, + // signalBoxDir, + // signalProvider, + // provider, + // zIndex // + // ); + + // + if (hasSignalBox) + { + // + if (hasWaitingBoxes) + { + // + int idx = FindIndex( + signalBox, + workingZone.waitingBoxes // + ); + bool has = IsValidIndex(idx); + if (has) + { + // + ArrayRemove( + workingZone.waitingBoxes, + idx, + 1 // + ); + } + } + + // + AddRef( + signalBox, + workingZone.unavailableBoxes // + ); + + // + signalBox.to = cTime; + } + + // + // + // + + // + // Remove Invalidate Zones ... + if (hasWaitingZones) + { + // + // Validate Waiting Zones ... + workingZone.ValidateWaitingZones(zIndex); + hasWaitingZones = workingZone.HasWaitingZones(); + } + + // + // Remove InValidate Boxes ... + if (hasWaitingBoxes) + { + // + // Validate Waiting Boxes ... + workingZone.ValidateWaitingBoxes(zIndex); + hasWaitingBoxes = workingZone.HasWaitingBoxes(); + } + + // + // + // + + // + // Cleanup Signal if UnApproved ... + if (!hasSignalBox) + { + // + signalBox.Clean(); + signalBoxDir = X_DIRECTION_NONE; + } + + // + // Check Priority Exists ... + hasPriority = workingZone + .DetectPriority( + priority, + signalBoxDir, + zIndex, + period // + ); + + // + // Check Price Reward and Amount Exists ... + hasRewardAmount = CalculateRiskReward( + priority, + reward, + amountPercent // + ); + + // + // Check Signal Conditions ... + if (hasSignalBox) + { + // + int idx = -1; + bool has = false; + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + signalBox, + iObj // + ); + if (has) + { + // + iObj.BoxWidth(1); + iObj.BoxColor(clrYellow); + iObj.BoxStyle(STYLE_SOLID); + + // + workingZone.mDrawnObjects.Add(iObj); + } + + // + isBullish = IsBullish(signalBoxDir); + isBearish = IsBearish(signalBoxDir); + + // + pivot = isBullish + ? signalBox.lower + : signalBox.upper; + + // + point = isBullish + ? signalBox.upper + : signalBox.lower; + + // + double entry = GetEntry( + signalBox.symbol, + signalBoxDir // + ); + + // + double iSL = 0; + + // + // Select and Provide SL Based on ... + if (signalProvider == X121SMC_XWZ_PROVIDER_ACTIVATED_MA) + { + // + // Default SL ... + iSL = pivot; + + // + Add( + iSL, + sls // + ); + } + else if (signalProvider == X121SMC_XWZ_PROVIDER_ACTIVATED_BOX) + { + // + // Default SL ... + iSL = pivot; + + // + Add( + iSL, + sls // + ); + } + else if (signalProvider == X121SMC_XWZ_PROVIDER_ACTIVATED_AREA) + { + // + // Default SL ... + iSL = pivot; + + // + Add( + iSL, + sls // + ); + } + + // + double iAtr = provider.decisionXConditions.atrBuffer[1]; + iAtr *= 1.5; + + // + // Select Condition SL ... + + // + double slsMin = GetMin(sls); + double slsMax = GetMax(sls); + + // + double longSL = slsMin - iAtr; + double shortSL = slsMax + iAtr; + + // + sl = isBullish + ? longSL + : shortSL; + + // + // Targets ... + + // + double risk = MathAbs(entry - sl); + + // + // Checking risk ... + if (risk >= maxAllowedSLDistanceInPoint) + { + // Print("Max Aloowed Risk Point Reached ..."); + } + + // + double reward2 = 2 * risk; + double reward3 = 3 * risk; + double iTP2 = isBullish + ? entry + reward2 + : entry - reward2; + double iTP3 = isBullish + ? entry + reward3 + : entry - reward3; + + // + Add( + iTP3, + targets // + ); + + // + // Based On Priority ... + has = priority != X121SMC_XWZ_PRIORITY_NONE; + if (has) + { + // + switch (priority) + { + // + case X121SMC_XWZ_PRIORITY_WEAK: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + } + break; + + // + case X121SMC_XWZ_PRIORITY_LOW: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter1, + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter3, + targets // + ); + } + break; + + // + case X121SMC_XWZ_PRIORITY_REGULAR: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter1, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter3, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + } + break; + + // + case X121SMC_XWZ_PRIORITY_HIGH: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter1, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + + // + // High ... + Add( + workingZone.quarter3, + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter3, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + + // + // High ... + Add( + workingZone.quarter1, + targets // + ); + } + break; + + // + case X121SMC_XWZ_PRIORITY_STRONG_HIGH: + // + if (isBullish) + { + // + // Weak ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter1, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + + // + // High ... + Add( + workingZone.quarter3, + targets // + ); + + // + // Strong High ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + } + else + { + // + // Weak ... + Add( + workingZone.demandZone.Upper(), + targets // + ); + + // + // Low ... + Add( + workingZone.quarter3, + targets // + ); + + // + // Regular ... + Add( + workingZone.quarter2, + targets // + ); + + // + // High ... + Add( + workingZone.quarter1, + targets // + ); + + // + // Strong High ... + Add( + workingZone.supplyZone.Lower(), + targets // + ); + } + break; + } + } + } + + // + // Summarize Results ... + result = hasPriority && + hasSignalBox && + hasRewardAmount; + + // + if (result) + { + // + Copy( + sls, + mConditions.sls // + ); + Copy( + targets, + mConditions.targets // + ); + + // + mConditions.sl = sl; + mConditions.pivot = pivot; + mConditions.point = point; + mConditions.reward = reward; + mConditions.setupTime = cTime; + mConditions.dir = signalBoxDir; + mConditions.priority = priority; + mConditions.signalBox = signalBox; + mConditions.provider = signalProvider; + mConditions.amountPercent = amountPercent; + } + + // + // + // + + // + // Cleanup Resources ... + + // + Clean(sls); + Clean(targets); + + // + provider.Clean(); + + // + signalBox.Clean(); + consolidationZBar.Clean(); + + // + return result; + } + + // + // Detect Trigger Conditions ... + bool DetectSignalTrigger( + // + X121SMCStrategyXWZSignalConditions &conditions, + // + X121SMCStrategySignalProviderData &provider, + // + int maxAllowedSetupAge = 60 + // + ) + { + // + bool result = false; + + // + result = + // + provider.IsValid() + // + ; + if (!result) + { + return result; + } + + // + result = conditions.IsSetuped(); + if (!result) + { + return result; + } + + // + datetime setupTime = conditions.setupTime; + ENUM_X_DIRECTION setupDir = conditions.dir; + + // + bool isBullish = IsBullish(setupDir); + bool isBearish = IsBearish(setupDir); + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + int loopback = 10; + + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + double points = GetPoints(symbol); + + // + // Cycles Conditions ... + result = provider.Prepare( + zIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + double iAtr = provider.decisionXConditions.atrBuffer[1]; + iAtr *= 1.5; + + // + // Check Signal Validation ... + // IMPORTANT: since all Validations done in SetUp Process ... + // here we only Execute Signal ... + + // + result = isBullish || + isBearish; + + // + if (result) + { + // + conditions.triggerTime = cTime; + conditions.type = isBullish + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_SHORT; + + // + } + + // + // Cleanup ... + + // + provider.Clean(); + + // + return result; + } + + // + // Detect Guards ... + bool DetectGuards( + // + X121SMCGuard &guards[], + const XPosition &positions[], + // + X121SMCStrategySignalProviderData &provider + // + ) + { + // + bool result = false; + + // + Clean(guards); + + // + // Set Provider for Common Guards ... + string signalProvider = ToString(X_121_SMC_PROVIDER_XWZ); + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + XOHCL cBar; + + // + int loopback = 10; + + // + double ask = GetAsk(symbol); + double bid = GetBid(symbol); + datetime cTime = TimeCurrent(); + double points = GetPoints(symbol); + + // + // Cycles Conditions ... + result = provider.IsValid(); + result = + result && + provider.Prepare( + zIndex, + loopback // + ); + if (!result) + { + // + provider.Clean(); + return result; + } + + // + // Select Own Positions ... + int count = ArraySize(positions); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + XPosition ownPositions[]; + XPosition ownLongPositions[]; + XPosition ownShortPositions[]; + for (int i = 0; i < count; i++) + { + // + XPosition iPosition = positions[i]; + bool isOwn = iPosition + .IsFiltersPassed( + symbol, + signalProvider, + NULL, + X_POSITION_TYPE_ALL, + iPosition.magic // + ); + if (isOwn) + { + // + AddRef( + iPosition, + ownPositions // + ); + + // + bool isLong = IsLong(positions[i].type); + if (isLong) + { + // + AddRef( + iPosition, + ownLongPositions // + ); + } + else + { + // + AddRef( + iPosition, + ownShortPositions // + ); + } + } + } + + // + // Check Extracted Positions ... + + // + count = ArraySize(ownPositions); + + // + int longsCount = ArraySize(ownLongPositions); + bool hasLongs = IsValidSize(longsCount); + + // + int shortsCount = ArraySize(ownShortPositions); + bool hasShorts = IsValidSize(shortsCount); + + // + // Validate Own Positions ... + result = IsValidSize(count); + if (!result) + { + // + Clean(ownPositions); + Clean(ownLongPositions); + Clean(ownShortPositions); + + // + return result; + } + + // + // + // + + // + // Get Global and Common Guards ... + + // + // ENUM_X_121_SMC_GUARD_ACTIONS ignoreGuards[1] = { + // X_121_SMC_GUARD_ACTION_TRAIL_STOP // + // }; + // result = DetectX121SMCGuards( + // signalProvider, + // guards, + // positions, + // provider, + // // + // ignoreGuards + // // + // ); + + // + // + // + + // + // Implement Custom Implemented Guards ... + + // + // Here we Are Sure there is Positions to Guard ... + // based on Current Provider ... + + // + // Selected Consolidation Zones ... + + // + int idx = -1; + bool has = false; + + // + bool hasBullishConsolidationZone = false; + XConsolidationZone bullishConsolidationZone; + has = provider.decisionState.HasBullishConsolidationZones(); + if (has) + { + // + idx = GetYoungest(provider.decisionState.bullishConsolidationZones); + hasBullishConsolidationZone = IsValidIndex(idx); + if (hasBullishConsolidationZone) + { + bullishConsolidationZone = provider.decisionState.bullishConsolidationZones[idx]; + } + } + + // + bool hasBearishConsolidationZone = false; + XConsolidationZone bearishConsolidationZone; + has = provider.decisionState.HasBearishConsolidationZones(); + if (has) + { + // + idx = GetYoungest(provider.decisionState.bearishConsolidationZones); + hasBearishConsolidationZone = IsValidIndex(idx); + if (hasBearishConsolidationZone) + { + bearishConsolidationZone = provider.decisionState.bearishConsolidationZones[idx]; + } + } + + // + XBoxZone bullishBox; + bool hasBullishBox = false; + bool isBullishBoxBreaked = false; + if (!hasBullishBox) + { + // + XCOrderBlock *ob = NULL; + idx = GetYoungest(provider.analyseState.bullishOrderBlocks); + has = IsValidIndex(idx); + if (has) + { + // + ob = provider.analyseState.bullishOrderBlocks[idx]; + + // + hasBullishBox = ToBox( + bullishBox, + ob // + ); + } + + // + if (!hasBullishBox) + { + bullishBox.Clean(); + } + + // + ZeroMemory(ob); + } + + // + XBoxZone bearishBox; + bool hasBearishBox = false; + bool isBearishBoxBreaked = false; + if (!hasBearishBox) + { + // + XCOrderBlock *ob = NULL; + idx = GetYoungest(provider.analyseState.bearishOrderBlocks); + has = IsValidIndex(idx); + if (has) + { + // + ob = provider.analyseState.bearishOrderBlocks[idx]; + + // + hasBearishBox = ToBox( + bearishBox, + ob // + ); + } + + // + if (!hasBearishBox) + { + bearishBox.Clean(); + } + + // + ZeroMemory(ob); + } + + // + // Here We Have all Requirements for Guarding Positions ... + + // + // Available Guards: + // X_121_SMC_GUARD_ACTION_NONE + // X_121_SMC_GUARD_ACTION_CLOSE + // X_121_SMC_GUARD_ACTION_CLOSE_ALL + // X_121_SMC_GUARD_ACTION_CLOSE_LONGS + // X_121_SMC_GUARD_ACTION_CLOSE_SHORTS + // X_121_SMC_GUARD_ACTION_PARTIAL_CLOSE + // X_121_SMC_GUARD_ACTION_TRAIL_STOP + // X_121_SMC_GUARD_ACTION_TRAIL_TARGET + // X_121_SMC_GUARD_ACTION_HEDGE + + // + // X_121_SMC_GUARD_ACTION_CLOSE: + // Close Specified Position on Specified Conditions ... + + // + // X_121_SMC_GUARD_ACTION_CLOSE_ALL: + // Close All Positions on Specified Conditions ... + + // + // X_121_SMC_GUARD_ACTION_CLOSE_LONGS: + // Close All Long Positions on Specified Conditions ... + + // + // X_121_SMC_GUARD_ACTION_CLOSE_SHORTS: + // Close All Short Positions on Specified Conditions ... + + // + // X_121_SMC_GUARD_ACTION_PARTIAL_CLOSE: + // Partial Close Specified Position on Specified Conditions ... + + // + // X_121_SMC_GUARD_ACTION_TRAIL_STOP: + // Trail Stop Specified Position on Specified Conditions ... + bool handleStoptrailingBasedOnBoxes = true; + bool handleStoptrailingBasedOnConsolidationZones = true; + for (int i = 0; i < count; i++) + { + // + XPosition iPosition = ownPositions[i]; + + // + bool isInited = cBar.Init( + iPosition.symbol, + iPosition.period, + cIndex // + ); + + // + isBullishBoxBreaked = + isInited && + hasBullishBox && + cBar.high < bullishBox.lower; + + // + isBearishBoxBreaked = + isInited && + hasBearishBox && + cBar.low > bearishBox.upper; + + // + bool isLong = IsLong(iPosition.type); + bool isInProfit = iPosition.profit > 0; + + // + double sl = iPosition.sl; + double tp = iPosition.tp; + + // + // Trail Stops Using Consolidation Zones ... + + // + bool canTraiLonglUsingCZone = + // + handleStoptrailingBasedOnConsolidationZones && + // + (isLong && + isInProfit && + hasBullishConsolidationZone && + bullishConsolidationZone.lower > iPosition.sl && + bullishConsolidationZone.lower > iPosition.entry) + // + ; + if (canTraiLonglUsingCZone) + { + sl = bullishConsolidationZone.lower; + } + + // + bool canTraiShortlUsingCZone = + // + handleStoptrailingBasedOnConsolidationZones && + // + (!isLong && + isInProfit && + hasBearishConsolidationZone && + bearishConsolidationZone.upper < iPosition.sl && + bearishConsolidationZone.upper < iPosition.entry) + // + ; + if (canTraiShortlUsingCZone) + { + sl = bearishConsolidationZone.upper; + } + + // + bool canTrailUsingCZone = + canTraiLonglUsingCZone || + canTraiShortlUsingCZone; + + // + // Trail Stop Using Boxes ... + + // + bool canTraiLonglUsingBox = + // + handleStoptrailingBasedOnBoxes && + // + (isLong && + isInProfit && + hasBullishBox && + bullishBox.lower > iPosition.sl && + bullishBox.lower > iPosition.entry) + // + ; + if (canTraiLonglUsingBox) + { + sl = bullishBox.lower; + } + + // + bool canTraiShortlUsingBox = + // + handleStoptrailingBasedOnBoxes && + // + (!isLong && + isInProfit && + hasBearishBox && + bearishBox.upper < iPosition.sl && + bearishBox.upper < iPosition.entry) + // + ; + if (canTraiShortlUsingBox) + { + sl = bearishBox.upper; + } + + // + bool canTrailUsingBox = + canTraiLonglUsingBox || + canTraiShortlUsingBox; + + // + bool canTraiLonglUsingBreakedBox = + // + handleStoptrailingBasedOnBoxes && + // + (isLong && + isInProfit && + isBearishBoxBreaked && + bearishBox.upper > iPosition.sl && + bearishBox.upper > iPosition.entry) + // + ; + if (canTraiLonglUsingBreakedBox) + { + sl = bearishBox.upper; + } + + // + bool canTraiShortlUsingBreakedBox = + // + handleStoptrailingBasedOnBoxes && + // + (!isLong && + isInProfit && + isBullishBoxBreaked && + bullishBox.lower < iPosition.sl && + bullishBox.lower < iPosition.entry) + // + ; + if (canTraiShortlUsingBreakedBox) + { + sl = bullishBox.lower; + } + + // + bool canTrailUsingBreakedBox = + canTraiLonglUsingBreakedBox || + canTraiShortlUsingBreakedBox; + + // + // Summarize SL ... + + // + bool isSLPassed = + sl > 0 && + (isLong + ? iPosition.price - sl >= points * 15 + : sl - iPosition.price >= points * 15); + + // + bool canTrail = + isSLPassed && + (canTrailUsingBox || + canTrailUsingCZone || + canTrailUsingBreakedBox); + if (canTrail) + { + // + X121SMCGuard iGuard; + + // + iGuard.time = cTime; + iGuard.symbol = symbol; + iGuard.provider = signalProvider; + iGuard.action = X_121_SMC_GUARD_ACTION_TRAIL_STOP; + + // + iGuard.ticket = iPosition.ticket; + + // + iGuard.sl = sl; + + // + AddGuard( + iGuard, + guards // + ); + } + } + + // + // X_121_SMC_GUARD_ACTION_TRAIL_TARGET: + // Trail Target Specified Position on Specified Conditions ... + + // + // X_121_SMC_GUARD_ACTION_HEDGE: + // Hedge all Positions on Specified Conditions ... + + // + // Cleanup Collections ... + + // + cBar.Clean(); + + // + provider.Clean(); + + // + bullishBox.Clean(); + bearishBox.Clean(); + + // + bullishConsolidationZone.Clean(); + bearishConsolidationZone.Clean(); + + // + count = ArraySize(guards); + result = IsValidSize(count); + + // + return result; + } + + // + // Add Conditions to Conditions Collection ... + int AddConditionsIfNotExists( + int maxAllowed = 10 // + ) + { + // + int result = 0; + + // + bool isSetuped = IsValid(mConditions.setupTime) && + HasDirection(mConditions.dir); + if (!isSetuped) + { + return result; + } + + // + int count = ArraySize(mConditionsCollection); + if (IsValidSize(count)) + { + // + // Copy Original Items ... + X121SMCStrategyXWZSignalConditions tmpItems[]; + Copy( + mConditionsCollection, + tmpItems // + ); + + // + // Prese Item Data ... + bool isBullish = IsBullish(mConditions.dir); + + // + for (int i = 0; i < count; i++) + { + // + X121SMCStrategyXWZSignalConditions iItem = tmpItems[i]; + + // + bool canRemove = mConditions.dir == iItem.dir && + mConditions.pivot == iItem.pivot; + if (canRemove) + { + // + ArrayRemove( + mConditionsCollection, + i, + 1 // + ); + } + } + + // + Clean(tmpItems); + } + + // + AddRef( + mConditions, + mConditionsCollection // + ); + + // + // Remove Olds ... + CleanupArray( + mConditionsCollection, + maxAllowed // + ); + + // + result = ArraySize(mConditionsCollection); + + // + return result; + } + + // + // Draw Functions ... + // + + // + void DrawBar( + XOHCL &bar, + XCPOIDrawer *drawer, + bool forceClean = true // + ) + { + // + if (forceClean) + { + mBarObjects.Clear(); + } + + // + if (drawer == NULL || + !bar.IsValid()) + { + return; + } + + // + bool isBullish = bar.IsBullish(); + + // + int widthBar = 2; + bool fillShadowsBar = true; + ENUM_LINE_STYLE styleBar = STYLE_SOLID; + color clrBar = + isBullish + ? clrAqua + : clrMagenta; + + // + datetime to = bar.NextAt(); + + // + XCOHCLObject *iObj; + bool isCreated = drawer + .CreateBar( + bar, + iObj, + to // + ); + if (isCreated) + { + // + iObj.BarSpes( + widthBar, + clrBar, + styleBar // + ); + + // + iObj.LowShadowFill(fillShadowsBar); + iObj.HighShadowFill(fillShadowsBar); + + // + mBarObjects.Add(iObj); + } + } + + // + protected: + // + + // + private: + // + // Props ... + string symbol; + ENUM_TIMEFRAMES period; + CArrayObj mObjects; + CArrayObj mBarObjects; + CArrayObj mWorkingZoneObjects; + + /** + * Initialize ... + */ + void Init() + { + } + + /** + * DeInitialize ... + */ + void DeInit() + { + // + mConditions.Clean(); + workingZone.Clean(); + Clean(mConditionsCollection); + + // + mBarObjects.Clear(); + } + + /** + * Update To Time of Exists Components ... + * + * @param value: updated time ... + */ + void UpdateTo( + datetime value = NULL // + ) + { + // + value = NormalizeTime(value); + + // + workingZone.UpdateTo(value); + } + + // + // Helpers ... + + // + bool CalculateRiskReward( + ENUM_X121SMC_XWZ_PRIORITY priority, + double &reward, + double &amountPercent // + ) + { + // + bool result = false; + + // + reward = 0; + amountPercent = 0; + + // + result = priority != X121SMC_XWZ_PRIORITY_NONE; + if (!result) + { + return result; + } + + // + switch (priority) + { + // + case X121SMC_XWZ_PRIORITY_STRONG_HIGH: + // + reward = 6; + amountPercent = 2; + break; + + // + case X121SMC_XWZ_PRIORITY_HIGH: + // + reward = 4; + amountPercent = 2; + break; + + // + case X121SMC_XWZ_PRIORITY_REGULAR: + // + reward = 3; + amountPercent = 1.5; + break; + + // + case X121SMC_XWZ_PRIORITY_LOW: + // + reward = 2; + amountPercent = 1; + break; + + // + case X121SMC_XWZ_PRIORITY_WEAK: + // + reward = 1; + amountPercent = 0.5; + break; + } + + // + result = + // + reward > 0 && + amountPercent > 0 + // + ; + + // + return result; + } + + // +}; + +// \ No newline at end of file diff --git a/BKPS/14031218/X121SMCEA/Signals/x-121.smc.xwz.signal.lib.ex5 b/BKPS/14031218/X121SMCEA/Signals/x-121.smc.xwz.signal.lib.ex5 new file mode 100644 index 0000000..4da0c5b Binary files /dev/null and b/BKPS/14031218/X121SMCEA/Signals/x-121.smc.xwz.signal.lib.ex5 differ diff --git a/BKPS/14031218/X121SMCEA/Signals/x-121.smc.xwz.signal.lib.mq5 b/BKPS/14031218/X121SMCEA/Signals/x-121.smc.xwz.signal.lib.mq5 new file mode 100644 index 0000000..9ff3873 --- /dev/null +++ b/BKPS/14031218/X121SMCEA/Signals/x-121.smc.xwz.signal.lib.mq5 @@ -0,0 +1,3034 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 X121 SMC Signal Class +// ------------------------------------------------- +// Name: XWZ +// 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 "../../Libraries/x-trade.lib" +#include "../Classes/x-121.smc.market.cycle.helper.class.mq5" +#include "../Libraries/x-121.smc.guard.lib.mq5" +#include "../Libraries/x-121.smc.lib.mq5" + +// +enum ENUM_X121SMC_XWZ_PROVIDERS +{ + X121SMC_XWZ_PROVIDER_NONE, + X121SMC_XWZ_PROVIDER_ACTIVATED_MA, + X121SMC_XWZ_PROVIDER_ACTIVATED_BOX, + X121SMC_XWZ_PROVIDER_ACTIVATED_AREA, + X121SMC_XWZ_PROVIDER_ACTIVATED_ZONE, +}; + +// +enum ENUM_X121SMC_XWZ_PRIORITY +{ + X121SMC_XWZ_PRIORITY_NONE, + X121SMC_XWZ_PRIORITY_WEAK, + X121SMC_XWZ_PRIORITY_LOW, + X121SMC_XWZ_PRIORITY_REGULAR, + X121SMC_XWZ_PRIORITY_HIGH, + X121SMC_XWZ_PRIORITY_STRONG_HIGH, +}; + +// +// Definitions ... + +// +struct X121SMCStrategyXWZWorkingZone +{ + // + // Props ... + + // + string symbol; + ENUM_TIMEFRAMES period; + + // + double quarter1; + double quarter2; + double quarter3; + + // + XCSupplyZone *supplyZone; + XCDemandZone *demandZone; + + // + XOBFVG waitingZones[]; + XOBFVG unavailableZones[]; + + // + XBoxZone waitingBoxes[]; + XBoxZone unavailableBoxes[]; + + // + CArrayObj mDrawnObjects; + CArrayObj mWorkingZoneObjects; + + // + // Constructor ... + X121SMCStrategyXWZWorkingZone() + { + Clean(); + } + + // + // Tools ... + + // + void Clean() + { + // + quarter1 = 0; + quarter2 = 0; + quarter3 = 0; + + // + symbol = NULL; + period = NULL; + + // + Clean(waitingZones); + Clean(unavailableZones); + + // + Clean(waitingBoxes); + Clean(unavailableBoxes); + + // + ZeroMemory(supplyZone); + ZeroMemory(demandZone); + + // + mDrawnObjects.Clear(); + mWorkingZoneObjects.Clear(); + } + + // + bool IsValid() + { + // + bool result = false; + + // + result = + // + quarter1 > 0 && + quarter2 > 0 && + quarter3 > 0 && + HasSupplyZone() && + HasDemandZone() && + quarter1 > quarter2 && + quarter2 > quarter3 + // + ; + + // + return result; + } + + // + bool Init( + string _symbol, + ENUM_TIMEFRAMES _period, + int barIndex, + X121SMCStrategySignalProviderData &provider // + ) + { + // + bool result = false; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + result = + // + IsValid(_symbol) && + IsValid(_period) && + // + provider.IsValid() + // + ; + if (!result) + { + return result; + } + + // + symbol = _symbol; + period = _period; + + // + int idx = -1; + int count = 0; + bool has = false; + + // + XOHCL zBar; + has = zBar.Init( + symbol, + period, + barIndex // + ); + result = has; + if (!result) + { + zBar.Clean(); + return result; + } + double ll5 = zBar.FindLowest(5, MODE_LOW); + double hh5 = zBar.FindHighest(5, MODE_HIGH); + zBar.Clean(); + + // + // Supply Zone ... + has = HasSupplyZone(); + if (!has) + { + // + idx = GetHighest(provider + .consolidationState + .supplyZones // + ); + has = IsValidIndex(idx); + if (has) + { + // + supplyZone = provider + .consolidationState + .supplyZones[idx]; + has = hh5 < supplyZone.Lower(); + if (!has) + { + supplyZone = NULL; + } + } + } + + // + // Demand Zone ... + has = HasDemandZone(); + if (!has) + { + // + idx = GetLowest(provider + .consolidationState + .demandZones // + ); + has = IsValidIndex(idx); + if (has) + { + // + demandZone = provider + .consolidationState + .demandZones[idx]; + has = ll5 > demandZone.Upper(); + if (!has) + { + demandZone = NULL; + } + } + } + + // + if (supplyZone != NULL && + demandZone != NULL && + supplyZone.IsValid() && + demandZone.IsValid()) + { + // + double upper = supplyZone.Lower(); + double lower = demandZone.Upper(); + + // + double delta = ((upper - lower) / 100) * 25; + + // + quarter1 = upper - (1 * delta); + quarter2 = upper - (2 * delta); + quarter3 = upper - (3 * delta); + } + + // + result = IsValid(); + if (!result) + { + Clean(); + } + + // + return result; + } + + // + bool DetectZone( + X121SMCStrategySignalProviderData &provider // + ) + { + // + bool result = false; + + // + result = IsValid() && + provider.IsValid(); + if (!result) + { + return result; + } + + // + int idx = -1; + int count = 0; + bool has = false; + datetime cTime = TimeCurrent(); + + // + XOBFVG obFVG; + XBoxZone obBox; + XBoxZone fvgBox; + XBoxZone supplyBox; + XBoxZone demandBox; + + // + XCFVG *fvg = NULL; + XCOrderBlock *ob = NULL; + XCSupplyZone *supply = NULL; + XCDemandZone *demand = NULL; + + // + // Check New Supply Zone Detection ... + bool hasNewSupply = + Contains( + X_SUPPLY_ZONE_DETECTED, + provider.consolidationPoiEvents // + ); + if (hasNewSupply) + { + // + idx = GetYoungest(provider + .consolidationState + .supplyZones // + ); + has = IsValidIndex(idx); + if (has) + { + // + supply = provider + .consolidationState + .supplyZones[idx]; + has = ToBox( + supplyBox, + supply // + ); + if (has) + { + // + supply.To(cTime); + supplyBox.to = cTime; + hasNewSupply = supplyBox.IsValid(); + } + } + } + + // + // Check New Demand Zone Detection ... + bool hasNewDemand = + Contains( + X_DEMAND_ZONE_DETECTED, + provider + .consolidationPoiEvents // + ); + if (hasNewDemand) + { + // + idx = GetYoungest(provider + .consolidationState + .demandZones // + ); + has = IsValidIndex(idx); + if (has) + { + // + demand = provider + .consolidationState + .demandZones[idx]; + has = ToBox( + demandBox, + demand // + ); + if (has) + { + // + demand.To(cTime); + demandBox.to = cTime; + hasNewDemand = demandBox.IsValid(); + } + } + } + + // + // Check New Fair Value Gap Detection ... + bool hasNewFairValueGap = + Contains( + X_BULLISH_FVG_DETECTED, + provider + .analysePoiEvents // + ) || + Contains( + X_BEARISH_FVG_DETECTED, + provider + .analysePoiEvents // + ); + if (hasNewFairValueGap) + { + // + idx = GetYoungest(provider + .analyseState + .fairValueGaps // + ); + has = IsValidIndex(idx); + if (has) + { + // + fvg = provider + .analyseState + .fairValueGaps[idx]; + has = ToBox( + fvgBox, + fvg // + ); + if (has) + { + // + fvg.To(cTime); + fvgBox.to = cTime; + hasNewFairValueGap = fvgBox.IsValid(); + } + } + } + + // + // Check New Order Block Detection ... + bool hasNewOrderBlock = + Contains( + X_BULLISH_ORDERBLOCK_DETECTED, + provider + .consolidationPoiEvents // + ) || + Contains( + X_BEARISH_ORDERBLOCK_DETECTED, + provider + .consolidationPoiEvents // + ); + if (hasNewOrderBlock) + { + // + idx = GetYoungest(provider + .consolidationState + .orderBlocks // + ); + has = IsValidIndex(idx); + if (has) + { + // + ob = provider + .consolidationState + .orderBlocks[idx]; + has = ToBox( + obBox, + ob // + ); + if (has) + { + // + ob.To(cTime); + obBox.to = cTime; + hasNewOrderBlock = obBox.IsValid(); + } + } + } + + // + // Detect OB FVG ... + if (hasNewOrderBlock) + { + // + XOHCL obStartedBar; + bool isOBStartedBodyOut = false; + bool isOBStarted = ob.IsStarted( + ob.GetDirection(), + obStartedBar, + isOBStartedBodyOut // + ); + + // + has = isOBStarted; + if (has) + { + // + obFVG.ob = ob; + + // + // Select FVGs ... + count = provider + .analyseState + .CountFairValueGaps(); + has = IsValidSize(count); + if (!has) + { + obFVG.Clean(); + } + else + { + // + // Select FVG ... + for (int i = 0; i < count; i++) + { + // + XCFVG *iFVG = provider + .analyseState + .fairValueGaps[i]; + bool isBullish = iFVG.IsBullish(); + + // + XOHCL iStartedBar; + bool isBodyOut = false; + bool isStarted = iFVG.IsStarted( + iFVG.GetDirection(), + iStartedBar, + isBodyOut // + ); + iStartedBar.Clean(); + + // + bool isKindPassed = isStarted && + isBodyOut; + bool isSameDir = iFVG.GetDirection() == ob.GetDirection(); + bool isFromPassed = iFVG.From() >= obStartedBar.time; + bool isPlacePassed = + // + IsInsideOrDiff( + iFVG, + ob // + ) + // + // || + // // + // (isBullish + // ? IsAboveDiff( + // iFVG, + // ob, + // true // Ignore Inside ... + // ) + // : IsBelowDiff( + // iFVG, + // ob, + // true // Ignore Inside ... + // ) + // // + // ) + // + ; + + // + has = isSameDir && + isKindPassed && + isFromPassed && + isPlacePassed; + if (has) + { + obFVG.AddFVG(iFVG); + } + + // + ZeroMemory(iFVG); + } + } + } + + // + has = obFVG.IsValid(); + if (has) + { + // + has = IsExists(obFVG); + if (!has) + { + // + // New Waiting Zone ... + AddRef( + obFVG, + waitingZones // + ); + } + else + { + // + // Check Item Is not Exists ... + idx = FindIndex( + obFVG, + waitingZones // + ); + has = !IsValidIndex(idx); + if (!has) + { + // + // Update Exists Waiting Zone ... + waitingZones[idx].AddFVG(fvg); + } + } + } + + // + obFVG.Clean(); + obStartedBar.Clean(); + } + + // + // + // + + // + bool lookingOthers = false; + if (lookingOthers) + { + // + // Check New Order Block Detection Analyse ... + XBoxZone analyseOBBox; + XCOrderBlock *analyseOB = NULL; + bool hasNewAnalyseOrderBlock = + Contains( + X_BULLISH_ORDERBLOCK_DETECTED, + provider + .analysePoiEvents // + ) || + Contains( + X_BEARISH_ORDERBLOCK_DETECTED, + provider + .analysePoiEvents // + ); + if (hasNewAnalyseOrderBlock) + { + // + idx = GetYoungest(provider + .analyseState + .orderBlocks // + ); + has = IsValidIndex(idx); + if (has) + { + // + analyseOB = provider + .analyseState + .orderBlocks[idx]; + has = ToBox( + analyseOBBox, + analyseOB // + ); + if (has) + { + // + analyseOB.To(cTime); + analyseOBBox.to = cTime; + hasNewAnalyseOrderBlock = analyseOBBox.IsValid(); + } + } + } + + // + // Checking Analyse Order Block ... + if (hasNewAnalyseOrderBlock) + { + // + XOHCL obStartedBar; + bool isOBStartedBodyOut = false; + bool isOBStarted = analyseOB.IsStarted( + analyseOB.GetDirection(), + obStartedBar, + isOBStartedBodyOut // + ); + + // + has = isOBStarted && + isOBStartedBodyOut; + if (has) + { + // + analyseOBBox.from = + obStartedBar.NextAt(); + + // + has = IsExists(analyseOBBox); + if (!has) + { + // + AddRef( + analyseOBBox, + waitingBoxes // + ); + } + } + } + + // + analyseOBBox.Clean(); + ZeroMemory(analyseOB); + } + + // + // + // + + // + result = HasWaitingZones(); + + // + // Cleanup Resources ... + + // + obFVG.Clean(); + obBox.Clean(); + fvgBox.Clean(); + supplyBox.Clean(); + demandBox.Clean(); + + // + ZeroMemory(ob); + ZeroMemory(fvg); + ZeroMemory(supply); + ZeroMemory(demand); + + // + return result; + } + + // + int ValidateWaitingZones( + int barIndex = 0 // + ) + { + // + int result = 0; + + // + bool has = false; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (barIndex == 0) + { + barIndex = 1; + } + + // + has = IsValid() && + HasWaitingZones(); + if (!has) + { + return result; + } + + // + int removeIDX[]; + result = CountWaitingZones(); + for (int i = 0; i < result; i++) + { + // + has = waitingZones[i].IsValidZone( + barIndex // + ); + if (!has) + { + // + Add( + i, + removeIDX // + ); + + // + AddRef( + waitingZones[i], + unavailableZones // + ); + } + } + + // + has = HasChild(removeIDX); + if (has) + { + // + CleanupArray( + removeIDX, + waitingZones // + ); + } + Clean(removeIDX); + + // + result = CountWaitingZones(); + + // + return result; + } + + // + int ValidateWaitingBoxes( + int barIndex = 0 // + ) + { + // + int result = 0; + + // + bool has = false; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (barIndex == 0) + { + barIndex = 1; + } + + // + has = IsValid() && + HasWaitingBoxes(); + if (!has) + { + return result; + } + + // + int removeIDX[]; + result = CountWaitingBoxes(); + for (int i = 0; i < result; i++) + { + // + has = IsValidBox( + waitingBoxes[i], + barIndex, + period // + ); + if (!has) + { + // + Add( + i, + removeIDX // + ); + + // + AddRef( + waitingBoxes[i], + unavailableBoxes // + ); + } + } + + // + has = HasChild(removeIDX); + if (has) + { + // + CleanupArray( + removeIDX, + waitingBoxes // + ); + } + Clean(removeIDX); + + // + result = CountWaitingBoxes(); + + // + return result; + } + + // + bool IsZoneActivated( + int &zoneIDX, + int &fvgIDX, + ENUM_X_DIRECTION &dir, + ENUM_X121SMC_XWZ_PROVIDERS &signalProvider, + X121SMCStrategySignalProviderData &provider, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + fvgIDX = -1; + zoneIDX = -1; + dir = X_DIRECTION_NONE; + signalProvider = X121SMC_XWZ_PROVIDER_NONE; + + // + // Normalize Bar Index ... + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (barIndex == 0) + { + barIndex = 1; + } + + // + // Validate ... + result = IsValid() && + HasWaitingZones(); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init( + symbol, + period, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + + // + return result; + } + + // + double peak = provider.decisionXConditions.peaksBuffer[1]; + double vale = provider.decisionXConditions.valesBuffer[1]; + + // + double analysePeak = provider.analyseXConditions.peaksBuffer[1]; + double analyseVale = provider.analyseXConditions.valesBuffer[1]; + + // + double consolidationPeak = provider.consolidationXConditions.peaksBuffer[1]; + double consolidationVale = provider.consolidationXConditions.valesBuffer[1]; + + // + double visionPeak = provider.visionXConditions.peaksBuffer[1]; + double visionVale = provider.visionXConditions.valesBuffer[1]; + + // + bool isPeaksSame = + peak == analysePeak && + analysePeak == consolidationPeak; + + // + bool isValesSame = + vale == analyseVale && + analyseVale == consolidationVale; + + // + // + // + + // + bool isDecisionScoreBullish = + provider.decisionBullishScore > provider.decisionBearishScore; + + // + bool isDecisionScoreBearish = + provider.decisionBearishScore > provider.decisionBullishScore; + + // + bool isAnalyseScoreBullish = + provider.analyseBullishScore > provider.analyseBearishScore; + + // + bool isAnalyseScoreBearish = + provider.analyseBearishScore > provider.analyseBullishScore; + + // + bool isConsolidationScoreBullish = + provider.consolidationBullishScore > provider.consolidationBearishScore; + + // + bool isConsolidationScoreBearish = + provider.consolidationBearishScore > provider.consolidationBullishScore; + + // + bool isVisionScoreBullish = + provider.visionBullishScore > provider.visionBearishScore; + + // + bool isVisionScoreBearish = + provider.visionBearishScore > provider.visionBullishScore; + + // + int count = CountWaitingZones(); + for (int i = 0; i < count; i++) + { + // + XOBFVG iOBFVG = waitingZones[i]; + + // + ENUM_X_DIRECTION iDir = iOBFVG.GetDirection(); + bool isBullish = iOBFVG.IsBullish(); + + // + int fvgsCount = iOBFVG.CountFVGs(); + bool has = IsValidSize(fvgsCount); + if (has) + { + // + for (int j = 0; j < fvgsCount; j++) + { + // + XCFVG *jFVG = iOBFVG.fvgs[j]; + + // + XBoxZone iBox; + has = ToBox( + iBox, + jFVG // + ); + if (has) + { + // + double iRange = iBox.lower + ((iBox.upper - iBox.lower) / 2); + + // + // Activate Zone Using PV ... + bool isPVPassed = + isBullish + ? vale <= iBox.upper && + vale >= iBox.lower + : peak <= iBox.upper && + peak >= iBox.lower; + bool isPV50Passed = + isBullish + ? vale < iBox.upper && + vale <= iRange && + vale > iBox.lower + : peak < iBox.upper && + peak >= iRange && + peak > iBox.lower; + + // + // Activate Zone using Rejection ... + bool isRejected = + isBullish + ? bar.low <= iBox.upper && + bar.GetDown() > iBox.upper + : bar.high >= iBox.lower && + bar.GetUp() < iBox.lower; + + // + // Combine Result ... + // result = isPVPassed; + // || isPVPassed + // || isPV50Passed + // || isRejected; + + // + result = isPVPassed; + + if (result) + { + // + fvgIDX = j; + iBox.Clean(); + zoneIDX = i; + + // + break; + } + } + + // + if (result) + { + // + iBox.Clean(); + ZeroMemory(jFVG); + + // + break; + } + + // + iBox.Clean(); + } + } + + // + if (result) + { + // + iOBFVG.Clean(); + break; + } + + // + iOBFVG.Clean(); + } + + // + result = + IsValidIndex(fvgIDX) && + IsValidIndex(zoneIDX); + + // + bar.Clean(); + + // + if (result) + { + bar.Clean(); + } + + // + return result; + } + + // + bool IsBoxActivated( + XBoxZone &box, + ENUM_X_DIRECTION &dir, + ENUM_X121SMC_XWZ_PROVIDERS &signalProviderl, + X121SMCStrategySignalProviderData &provider, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + box.Clean(); + dir = X_DIRECTION_NONE; + signalProviderl = X121SMC_XWZ_PROVIDER_NONE; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + result = IsValid() && + HasWaitingBoxes(); + if (!result) + { + return result; + } + + // + XOHCL bar; + XOHCL cBar; + XOHCL pBar; + result = bar.Init( + symbol, + period, + barIndex // + ); + result = + result && + bar.GetPreviousBar(cBar); + result = + result && + cBar.GetPreviousBar(pBar); + if (!result) + { + // + bar.Clean(); + cBar.Clean(); + + // + return result; + } + + // + // Retrieve Some Required Data ... + + // + double peakZ = provider.decisionXConditions.peaksBuffer[0]; + double valeZ = provider.decisionXConditions.valesBuffer[0]; + double peak = provider.decisionXConditions.peaksBuffer[1]; + double vale = provider.decisionXConditions.valesBuffer[1]; + + // + double analysePeak = provider.analyseXConditions.peaksBuffer[1]; + double analyseVale = provider.analyseXConditions.valesBuffer[1]; + + // + double consolidationPeak = provider.consolidationXConditions.peaksBuffer[1]; + double consolidationVale = provider.consolidationXConditions.valesBuffer[1]; + + // + double visionPeak = provider.visionXConditions.peaksBuffer[1]; + double visionVale = provider.visionXConditions.valesBuffer[1]; + + // + bool isPeaksSame = + peak == analysePeak && + analysePeak == consolidationPeak; + + // + bool isValesSame = + vale == analyseVale && + analyseVale == consolidationVale; + + // + // Calculate Scores Conditions ... + + // + bool isDecisionScoreBullish = + provider.decisionBullishScore > provider.decisionBearishScore; + + // + bool isDecisionScoreBearish = + provider.decisionBearishScore > provider.decisionBullishScore; + + // + bool isAnalyseScoreBullish = + provider.analyseBullishScore > provider.analyseBearishScore; + + // + bool isAnalyseScoreBearish = + provider.analyseBearishScore > provider.analyseBullishScore; + + // + bool isConsolidationScoreBullish = + provider.consolidationBullishScore > provider.consolidationBearishScore; + + // + bool isConsolidationScoreBearish = + provider.consolidationBearishScore > provider.consolidationBullishScore; + + // + bool isVisionScoreBullish = + provider.visionBullishScore > provider.visionBearishScore; + + // + bool isVisionScoreBearish = + provider.visionBearishScore > provider.visionBullishScore; + + // + bool isScoreBullish = + isVisionScoreBullish && + isAnalyseScoreBullish && + isConsolidationScoreBullish; + + // + bool isScoreBearish = + isVisionScoreBearish && + isAnalyseScoreBearish && + isConsolidationScoreBearish; + + // + // Waiting Boxes ... + int count = CountWaitingBoxes(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = waitingBoxes[i]; + bool isBullish = iBox.IsBullish(); + + // + // Check Score ... + + // + bool isScorePassed = + isBullish + ? isScoreBullish + : isScoreBearish; + + // + // Check Bar Insides ... + + // + bool isPBarInside = + (pBar.high <= iBox.upper && + pBar.low >= iBox.lower) || + (isBullish + ? pBar.low < iBox.upper && + pBar.GetDown() < iBox.upper + : pBar.high > iBox.lower && + pBar.GetUp() > iBox.lower); + + // + bool isCBarInside = + (cBar.high <= iBox.upper && + cBar.low >= iBox.lower) || + (isBullish + ? cBar.low < iBox.upper && + cBar.GetDown() < iBox.upper + : cBar.high > iBox.lower && + cBar.GetUp() > iBox.lower); + + // + // Checking Rejection ... + + // + // Bullish ... + bool isBullishRejected = + isBullish && + cBar.low <= iBox.upper && + cBar.GetDown() > iBox.upper; + + // + // Bearish ... + bool isBearishRejected = + !isBullish && + cBar.high >= iBox.lower && + cBar.GetUp() < iBox.lower; + + // + // Check Breaktion ... + + // + // Bullish ... + bool isBullishBreaked = + isBullish && + cBar.high > iBox.upper && + cBar.GetUp() > iBox.upper && + cBar.low >= iBox.lower; + + // + // Bearish ... + bool isBearishBreaked = + !isBullish && + cBar.low < iBox.lower && + cBar.GetDown() < iBox.lower && + cBar.high <= iBox.upper; + + // + // Checking PV Pass ... + + // + bool isBullishPVPassed = + isBullish && + vale == valeZ && + vale > iBox.lower && + vale < iBox.upper; + + // + bool isBearishPVPassed = + !isBullish && + peak == peakZ && + peak > iBox.lower && + peak < iBox.upper; + + // + // Summarise ... + + // + // Rejection ... + bool isRejected = isBullishRejected || + isBearishRejected; + + // + // Breaktion ... + bool isBreaked = + isPBarInside && + (isBullishBreaked || + isBearishBreaked); + + // + bool isPVPassed = + (isBullishPVPassed || + isBearishPVPassed); + + // + // Trend Conditions ... + + // + bool isX3MABullish = + provider.decisionXConditions.isX3MaFastOverMid && + provider.decisionXConditions.x3maMidBuffer[1] > provider.decisionXConditions.x3maSlowBuffer[1]; + + // + bool isX3MABearish = + provider.decisionXConditions.isX3MaFastUnderMid && + provider.decisionXConditions.x3maMidBuffer[1] < provider.decisionXConditions.x3maSlowBuffer[1]; + + // + bool isVWapBullish = + provider.decisionXConditions.isVWapFastOverMid && + provider.decisionXConditions.vwapMidBuffer[1] > provider.decisionXConditions.vwapSlowBuffer[1]; + + // + bool isVWapBearish = + provider.decisionXConditions.isX3MaFastUnderMid && + provider.decisionXConditions.vwapMidBuffer[1] < provider.decisionXConditions.vwapSlowBuffer[1]; + + // + bool isTrendBullish = + isX3MABullish && + isVWapBullish; + + // + bool isTrendBearish = + isX3MABearish && + isVWapBearish; + + // + bool isTrendPassed = + isBullish + ? isTrendBullish + : isTrendBearish; + + // + // Summarize Conditions ... + + // + result = + // + // isBreaked || + // isRejected || + isPVPassed && + isRejected && + isTrendPassed && + isScorePassed + // + ; + + // + if (result) + { + // + box = iBox; + dir = iBox.dir; + signalProviderl = X121SMC_XWZ_PROVIDER_ACTIVATED_BOX; + + // + iBox.Clean(); + break; + } + + // + iBox.Clean(); + + // + } + + // + // MA Trends ... + if (!result) + { + // + result = provider.analyseState.HasOrderBlocks(); + if (result) + { + // + // + // Trend Conditions ... + + // + bool isX3MABullish = + provider.decisionXConditions.isX3MaFastCrossedOverMid; + + // + bool isX3MABearish = + provider.decisionXConditions.isX3MaFastCrossedUnderMid; + + // + bool isVWapBullish = + provider.decisionXConditions.isVWapFastCrossedOverMid; + + // + bool isVWapBearish = + provider.decisionXConditions.isVWapFastCrossedUnderMid; + + // + // + // + + // + bool isTrendBullish = + (isX3MABullish || + isVWapBullish) && + provider.decisionXConditions.isNewPeakOverLast; + + // + bool isTrendBearish = + (isX3MABearish || + isVWapBearish) && + provider.decisionXConditions.isNewValeUnderLast; + + // + result = isTrendBullish || + isTrendBearish; + if (result) + { + // + // Select Signal Box ... + + // + bool isScorePassed = + isTrendBullish + ? isScoreBullish + : isScoreBearish; + + // + XBoxZone tmpBoxes[]; + ToBox( + provider.analyseState.orderBlocks, + tmpBoxes // + ); + Copy( + waitingBoxes, + tmpBoxes, + false // + ); + int idx = -1; + // bool has = false; + while (HasChild(tmpBoxes)) + { + // + if (isTrendBullish) + { + idx = GetHighest(tmpBoxes); + } + else + { + idx = GetLowest(tmpBoxes); + } + + // + result = IsValidIndex(idx); + if (!result) + { + break; + } + + // + XBoxZone iBox = tmpBoxes[idx]; + + // + ArrayRemove( + tmpBoxes, + idx, + 1 // + ); + + // + int insideIDX = -1; + bool hasInsideBox = HasInsideBox( + insideIDX, + iBox, + tmpBoxes // + ); + if (hasInsideBox) + { + // + hasInsideBox = + isTrendBullish + ? iBox.lower < tmpBoxes[insideIDX].lower + : iBox.upper > tmpBoxes[insideIDX].upper; + } + + // + bool isBullishPlacePassed = + // !hasInsideBox && + isTrendBullish && + iBox.IsBullish() && + bar.low >= iBox.upper && + cBar.low >= iBox.upper && + provider.decisionXConditions.x3maMin >= iBox.lower && + provider.decisionXConditions.vwapMin >= iBox.lower; + + // + bool isBearishPlacePassed = + // !hasInsideBox && + isTrendBearish && + iBox.IsBearish() && + bar.high <= iBox.lower && + cBar.high <= iBox.lower && + provider.decisionXConditions.x3maMax <= iBox.upper && + provider.decisionXConditions.vwapMax <= iBox.upper; + + // + result = isScorePassed && + (isBullishPlacePassed || + isBearishPlacePassed); + if (result) + { + // + box = iBox; + iBox.Clean(); + dir = + isTrendBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + signalProviderl = X121SMC_XWZ_PROVIDER_ACTIVATED_MA; + break; + } + + // + } + Clean(tmpBoxes); + } + } + } + + // + // Supply and Demand ... + if (false && !result) + { + // + int idx = -1; + bool has = false; + XBoxZone tmpBoxes[]; + + // + // Detecting Youngest Zones ... + + // + XBoxZone bullishBox; + bool hasBullishBox = false; + if (!hasBullishBox) + { + // + XCOrderBlock *ob = NULL; + idx = GetYoungest(provider.analyseState.bullishOrderBlocks); + has = IsValidIndex(idx); + if (has) + { + // + ob = provider.analyseState.bullishOrderBlocks[idx]; + + // + XOHCL startedBar; + bool isBodyOut = false; + bool isStarted = ob.IsStarted( + ob.GetDirection(), + startedBar, + isBodyOut // + ); + has = isStarted && + isBodyOut; + if (has) + { + // + hasBullishBox = ToBox( + bullishBox, + ob // + ); + } + } + + // + if (!hasBullishBox) + { + bullishBox.Clean(); + } + + // + ZeroMemory(ob); + } + + // + XBoxZone bearishBox; + bool hasBearishBox = false; + if (!hasBearishBox) + { + // + XCOrderBlock *ob = NULL; + idx = GetYoungest(provider.analyseState.bearishOrderBlocks); + has = IsValidIndex(idx); + if (has) + { + // + ob = provider.analyseState.bearishOrderBlocks[idx]; + + // + XOHCL startedBar; + bool isBodyOut = false; + bool isStarted = ob.IsStarted( + ob.GetDirection(), + startedBar, + isBodyOut // + ); + has = isStarted && + isBodyOut; + if (has) + { + // + hasBearishBox = ToBox( + bearishBox, + ob // + ); + } + } + + // + if (!hasBearishBox) + { + bearishBox.Clean(); + } + + // + ZeroMemory(ob); + } + + // + XBoxZone bullishCZBox; + bool hasBullishConsolidationZone = false; + XConsolidationZone bullishConsolidationZone; + hasBullishConsolidationZone = provider.decisionState.HasBullishConsolidationZones(); + if (hasBullishConsolidationZone) + { + // + idx = GetYoungest(provider.decisionState.bullishConsolidationZones); + hasBullishConsolidationZone = IsValidIndex(idx); + if (hasBullishConsolidationZone) + { + // + bullishConsolidationZone = provider.decisionState.bullishConsolidationZones[idx]; + if (hasBullishConsolidationZone) + { + // + hasBullishConsolidationZone = ToBox( + bullishCZBox, + bullishConsolidationZone // + ); + } + } + } + + // + XBoxZone bearishCZBox; + bool hasBearishConsolidationZone = false; + XConsolidationZone bearishConsolidationZone; + hasBearishConsolidationZone = provider.decisionState.HasBearishConsolidationZones(); + if (hasBearishConsolidationZone) + { + // + idx = GetYoungest(provider.decisionState.bearishConsolidationZones); + hasBearishConsolidationZone = IsValidIndex(idx); + if (hasBearishConsolidationZone) + { + // + bearishConsolidationZone = provider.decisionState.bearishConsolidationZones[idx]; + if (hasBearishConsolidationZone) + { + // + hasBearishConsolidationZone = ToBox( + bearishCZBox, + bearishConsolidationZone // + ); + } + } + } + + // + // + // + + // + // Supply Zone ... + has = provider.visionState.HasSupplyZones(); + if (has) + { + // + ToBox( + provider.visionState.supplyZones, + tmpBoxes // + ); + + // + while (HasChild(tmpBoxes)) + { + // + idx = GetYoungest(tmpBoxes); + has = IsValidIndex(idx); + if (!has) + { + break; + } + + // + XBoxZone iBox = tmpBoxes[idx]; + ArrayRemove( + tmpBoxes, + idx, + 1 // + ); + + // + // Price Must Be Inside a Zonne More Than 5 Bar ... + bool isPriceInside = + // + bar.high < iBox.upper && + bar.low > iBox.lower && + // + cBar.high < iBox.upper && + cBar.low > iBox.lower && + // + pBar.high < iBox.upper && + pBar.low > iBox.lower + // + ; + + // + bool isBearishBoxPassed = + hasBearishBox && + IsBoxInside( + bearishBox, + iBox // + ); + + // + bool isBearishCZBoxPassed = + hasBearishConsolidationZone && + IsBoxInside( + bearishCZBox, + iBox // + ); + + // + result = isPriceInside && + (isBearishBoxPassed || + isBearishCZBoxPassed); + if (result) + { + // + if (isBearishBoxPassed) + { + box = bearishBox; + } + else + { + box = bearishCZBox; + } + + // + iBox.to = TimeCurrent(); + XCBoxObject *iObj; + provider.visionCycleHelper.mPOIDrawer.DrawBox( + iBox, + iObj // + ); + + // + dir = X_DIRECTION_BEARISH; + signalProviderl = X121SMC_XWZ_PROVIDER_ACTIVATED_AREA; + + // + iBox.Clean(); + + // + break; + } + + // + iBox.Clean(); + } + + // + Clean(tmpBoxes); + } + + // + // Demand Zone ... + has = provider.visionState.HasDemandZones(); + if (!result && has) + { + // + ToBox( + provider.visionState.demandZones, + tmpBoxes // + ); + + // + while (HasChild(tmpBoxes)) + { + // + idx = GetYoungest(tmpBoxes); + has = IsValidIndex(idx); + if (!has) + { + break; + } + + // + XBoxZone iBox = tmpBoxes[idx]; + ArrayRemove( + tmpBoxes, + idx, + 1 // + ); + + // + // Price Must Be Inside a Zonne More Than 5 Bar ... + bool isPriceInside = + // + bar.high < iBox.upper && + bar.low > iBox.lower && + // + cBar.high < iBox.upper && + cBar.low > iBox.lower && + // + pBar.high < iBox.upper && + pBar.low > iBox.lower + // + ; + + // + bool isBullishBoxPassed = + hasBullishBox && + IsBoxInside( + bullishBox, + iBox // + ); + + // + bool isBullishCZBoxPassed = + hasBullishConsolidationZone && + IsBoxInside( + bullishCZBox, + iBox // + ); + + // + result = isPriceInside && + (isBullishBoxPassed || + isBullishCZBoxPassed); + if (result) + { + // + if (isBullishBoxPassed) + { + box = bullishBox; + } + else + { + box = bullishCZBox; + } + + // + iBox.to = TimeCurrent(); + XCBoxObject *iObj; + provider.visionCycleHelper.mPOIDrawer.DrawBox( + iBox, + iObj // + ); + + // + dir = X_DIRECTION_BULLISH; + signalProviderl = X121SMC_XWZ_PROVIDER_ACTIVATED_AREA; + + // + iBox.Clean(); + + // + break; + } + + // + iBox.Clean(); + } + + // + Clean(tmpBoxes); + } + + // + Clean(tmpBoxes); + + // + bullishBox.Clean(); + bearishBox.Clean(); + bullishCZBox.Clean(); + bearishCZBox.Clean(); + bullishConsolidationZone.Clean(); + bearishConsolidationZone.Clean(); + + // + } + + // + bar.Clean(); + cBar.Clean(); + pBar.Clean(); + + // + return result; + } + + // + bool IsExists(XOBFVG &zone) + { + // + bool result = false; + + // + // Check Validation ... + result = zone.IsValid() && + (HasWaitingZones() || + HasUnavailableZones()); + if (!result) + { + return result; + } + + // + int idx = -1; + + // + // Check Index in Waiting Zones ... + idx = FindIndex( + zone, + waitingZones // + ); + result = IsValidIndex(idx); + if (result) + { + return result; + } + + // + // Check Index in Unavailable Zones ... + idx = FindIndex( + zone, + unavailableZones // + ); + result = IsValidIndex(idx); + if (result) + { + return result; + } + + // + return result; + } + + // + bool IsExists(XBoxZone &box) + { + // + bool result = false; + + // + // Check Validation ... + result = box.IsValid() && + (HasWaitingBoxes() || + HasUnavailableBoxes()); + if (!result) + { + return result; + } + + // + int idx = -1; + + // + // Check Index in Waiting Zones ... + idx = FindIndex( + box, + waitingBoxes // + ); + result = IsValidIndex(idx); + if (result) + { + return result; + } + + // + // Check Index in Unavailable Zones ... + idx = FindIndex( + box, + unavailableBoxes // + ); + result = IsValidIndex(idx); + if (result) + { + return result; + } + + // + return result; + } + + // + bool IsDestroyed( + int barIndex = 0, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init( + symbol, + period, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + XOHCL cBar; + result = bar.GetPreviousBar(cBar); + if (!result) + { + // + bar.Clean(); + cBar.Clean(); + + // + return result; + } + + // + bool isSupplyZoneBreaked = + // + bar.low > supplyZone.Upper() && + cBar.low > supplyZone.Upper() + // + ; + + // + bool isDemandZoneBreaked = + // + bar.high < demandZone.Lower() && + cBar.high < demandZone.Lower() + // + ; + + // + bar.Clean(); + cBar.Clean(); + + // + result = isSupplyZoneBreaked || + isDemandZoneBreaked; + + // + return result; + } + + // + bool DetectPriority( + ENUM_X121SMC_XWZ_PRIORITY &priority, + ENUM_X_DIRECTION forDir, + int barIndex = 0, + ENUM_TIMEFRAMES forPeriod = NULL // + ) + { + // + bool result = false; + + // + priority = X121SMC_XWZ_PRIORITY_NONE; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + if (!IsValid(forPeriod)) + { + forPeriod = period; + } + + // + result = IsValid() && + HasDirection(forDir); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + XOHCL bar; + result = bar.Init( + symbol, + forPeriod, + barIndex // + ); + if (!result) + { + // + bar.Clean(); + return result; + } + + // + if (bar.high < supplyZone.Upper() && + bar.low > supplyZone.Lower()) + { + // + priority = + isBullish + ? X121SMC_XWZ_PRIORITY_NONE + : X121SMC_XWZ_PRIORITY_STRONG_HIGH; + } + else if (bar.high < supplyZone.Lower() && + bar.low > quarter1) + { + // + priority = + isBullish + ? X121SMC_XWZ_PRIORITY_WEAK + : X121SMC_XWZ_PRIORITY_HIGH; + } + else if (bar.high < quarter1 && + bar.low > quarter2) + { + // + priority = + isBullish + ? X121SMC_XWZ_PRIORITY_LOW + : X121SMC_XWZ_PRIORITY_REGULAR; + } + else if (bar.high < quarter2 && + bar.low > quarter3) + { + // + priority = + isBullish + ? X121SMC_XWZ_PRIORITY_REGULAR + : X121SMC_XWZ_PRIORITY_LOW; + } + else if (bar.high < quarter3 && + bar.low > demandZone.Upper()) + { + // + priority = + isBullish + ? X121SMC_XWZ_PRIORITY_HIGH + : X121SMC_XWZ_PRIORITY_WEAK; + } + else if (bar.high < demandZone.Upper() && + bar.low > demandZone.Lower()) + { + // + priority = + isBullish + ? X121SMC_XWZ_PRIORITY_STRONG_HIGH + : X121SMC_XWZ_PRIORITY_NONE; + } + + // + result = priority != X121SMC_XWZ_PRIORITY_NONE && + priority != X121SMC_XWZ_PRIORITY_WEAK; + + // + bar.Clean(); + + // + return result; + } + + // + bool DetectOveralDirection( + ENUM_X_DIRECTION &dir // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + result = IsValid() && + HasSupplyZone() && + HasDemandZone(); + if (!result) + { + return result; + } + + // + XBoxZone demBox; + XBoxZone supBox; + result = ToBox( + demBox, + demandZone // + ); + if (!result) + { + // + supBox.Clean(); + demBox.Clean(); + + // + return result; + } + result = ToBox( + supBox, + supplyZone // + ); + if (!result) + { + // + supBox.Clean(); + demBox.Clean(); + + // + return result; + } + + // + XOHCL supPriceOutBar; + XOHCL demPriceOutBar; + result = DetectBoxNearestPriceOut( + supBox, + supPriceOutBar, + period // + ); + if (!result) + { + // + demBox.Clean(); + supBox.Clean(); + supPriceOutBar.Clean(); + demPriceOutBar.Clean(); + + // + return result; + } + result = DetectBoxNearestPriceOut( + demBox, + demPriceOutBar, + period // + ); + if (!result) + { + // + demBox.Clean(); + supBox.Clean(); + supPriceOutBar.Clean(); + demPriceOutBar.Clean(); + + // + return result; + } + + // + // Specified Direction ... + dir = + (supPriceOutBar.IsValid() && + demPriceOutBar.IsValid()) + ? supPriceOutBar.time > demPriceOutBar.time + ? X_DIRECTION_BEARISH + : demPriceOutBar.time > supPriceOutBar.time + ? X_DIRECTION_BULLISH + : X_DIRECTION_NONE + : X_DIRECTION_NONE; + + // + result = HasDirection(dir); + + // + // Clean Up Resources ... + + // + demBox.Clean(); + supBox.Clean(); + supPriceOutBar.Clean(); + demPriceOutBar.Clean(); + + // + return result; + } + + // + void UpdateTo(datetime value = NULL) + { + // + value = NormalizeTime(value); + + // + int count = 0; + bool has = false; + + // + has = HasSupplyZone(); + if (has) + { + supplyZone.To(value); + } + + // + has = HasDemandZone(); + if (has) + { + demandZone.To(value); + } + + // + has = HasWaitingZones(); + if (has) + { + // + count = CountWaitingZones(); + for (int i = 0; i < count; i++) + { + waitingZones[i].UpdateTo(value); + } + } + + // + has = HasWaitingBoxes(); + if (has) + { + // + count = CountWaitingBoxes(); + for (int i = 0; i < count; i++) + { + waitingBoxes[i].to = value; + } + } + + // + } + + // + void Draw( + XCPOIDrawer *drawer, + bool drawSupplyZone = false, + bool drawDemandZone = false, + bool drawWaitingZones = false) + { + // + if (drawer == NULL) + { + return; + } + + // + int count = 0; + bool has = false; + bool isCreated = false; + + // + ulong chartID = drawer.ChartIdentification(); + int subWindow = drawer.SubWindowIdentification(); + color bullishColor = drawer.BarBullishColor(); + color bearishColor = drawer.BarBearishColor(); + + // + // Supply Zone ... + if (drawSupplyZone) + { + // + has = HasSupplyZone(); + if (has) + { + // + XCSupplyZoneObject *iObj; + isCreated = drawer.CreateSupplyZone( + supplyZone, + iObj // + ); + + // + if (isCreated) + { + mWorkingZoneObjects.Add(iObj); + } + } + } + + // + // Demand Zone ... + if (drawDemandZone) + { + // + has = HasDemandZone(); + if (has) + { + // + XCDemandZoneObject *iObj; + isCreated = drawer.CreateDemandZone( + demandZone, + iObj // + ); + + // + if (isCreated) + { + mWorkingZoneObjects.Add(iObj); + } + } + } + + // + // + // + + // + // Quarters ... + has = IsValid(); + if (has) + { + // + double zoneUpper = supplyZone.Upper(); + double upper = supplyZone.Lower(); + + // + double lower = demandZone.Upper(); + double zoneLower = demandZone.Lower(); + + // + string prefix = "X121WZone_" + symbol + "_" + ToString(period); + + // + // Zone Upper ... + CChartObjectHLine *zoneUpperLine; + zoneUpperLine = new CChartObjectHLine(); + isCreated = zoneUpperLine.Create( + chartID, + prefix + "_ZoneTop", + subWindow, + zoneUpper // + ); + if (isCreated) + { + // + zoneUpperLine.Color(clrRed); + + // + mWorkingZoneObjects.Add(zoneUpperLine); + } + + // + // Zone Lower ... + CChartObjectHLine *zoneLowerLine; + zoneLowerLine = new CChartObjectHLine(); + isCreated = zoneLowerLine.Create( + chartID, + prefix + "_ZoneDown", + subWindow, + zoneLower // + ); + if (isCreated) + { + // + zoneLowerLine.Color(clrRed); + + // + mWorkingZoneObjects.Add(zoneLowerLine); + } + + // + // Upper ... + CChartObjectHLine *upperLine; + upperLine = new CChartObjectHLine(); + isCreated = upperLine.Create( + chartID, + prefix + "_Upper", + subWindow, + upper // + ); + if (isCreated) + { + // + upperLine.Color(clrLime); + + // + mWorkingZoneObjects.Add(upperLine); + } + + // + // Lower ... + CChartObjectHLine *lowerLine; + lowerLine = new CChartObjectHLine(); + isCreated = lowerLine.Create( + chartID, + prefix + "_Lower", + subWindow, + lower // + ); + if (isCreated) + { + // + lowerLine.Color(clrLime); + + // + mWorkingZoneObjects.Add(lowerLine); + } + + // + // Quarters ... + + // + // Quarter 1 ... + CChartObjectHLine *q1Line; + q1Line = new CChartObjectHLine(); + isCreated = q1Line.Create( + chartID, + prefix + "_Q1", + subWindow, + quarter1 // + ); + if (isCreated) + { + // + q1Line.Color(clrYellow); + + // + mWorkingZoneObjects.Add(q1Line); + } + + // + // Quarter 2 ... + CChartObjectHLine *q2Line; + q2Line = new CChartObjectHLine(); + isCreated = q2Line.Create( + chartID, + prefix + "_Q2", + subWindow, + quarter2 // + ); + if (isCreated) + { + // + q2Line.Color(clrYellow); + + // + mWorkingZoneObjects.Add(q2Line); + } + + // + // Quarter 3 ... + CChartObjectHLine *q3Line; + q3Line = new CChartObjectHLine(); + isCreated = q3Line.Create( + chartID, + prefix + "_Q3", + subWindow, + quarter3 // + ); + if (isCreated) + { + // + q3Line.Color(clrYellow); + + // + mWorkingZoneObjects.Add(q3Line); + } + } + + // + // Waiting Zones ... + if (drawWaitingZones) + { + // + has = HasWaitingZones(); + if (has) + { + // + count = CountWaitingZones(); + for (int i = 0; i < count; i++) + { + // + XCBaseObject *iObjects[]; + int iObjectsCount = drawer.DrawOBFVG( + waitingZones[i], + iObjects, + true, // Draw Order Block ... + true, // Draw Fair Value Gaps ... + true, // Draw All Fair Value Gaps ... + // + true, // Draw OB StartedBar ... + true, // Draw OB ActivatedBar ... + true, // Draw OB BreakedBar ... + true, // Draw OB WorkedBar ... + // + true, // Draw FVG StartedBar ... + true, // Draw FVG ActivatedBar ... + true, // Draw FVG BreakedBar ... + true // Draw FVG WorkedBar ... + // + ); + has = IsValidSize(iObjectsCount); + if (has) + { + // + for (int j = 0; j < iObjectsCount; j++) + { + mDrawnObjects.Add(iObjects[j]); + } + } + + // + // if (drawWaitingZonesBoxArea) + // { + // // + // XBoxZone iBox; + // has = waitingZones[i].ToZone( + // iBox // + // ); + // if (has) + // { + // // + // XCBoxObject *iBoxObj; + // has = drawer.DrawBox( + // iBox, + // iBoxObj // + // ); + // if (has) + // { + // mDrawnObjects.Add(iBoxObj); + // } + // } + + // // + // iBox.Clean(); + // } + } + } + + // + has = HasWaitingBoxes(); + if (has) + { + // + count = CountWaitingBoxes(); + for (int i = 0; i < count; i++) + { + // + XCBoxObject *iBoxObj; + has = drawer.DrawBox( + waitingBoxes[i], + iBoxObj // + ); + if (has) + { + mDrawnObjects.Add(iBoxObj); + } + + // + ZeroMemory(iBoxObj); + } + } + } + + // + } + + // + // + // + + // + bool HasSupplyZone() + { + return supplyZone != NULL && + supplyZone.IsValid(); + } + + // + bool HasDemandZone() + { + return demandZone != NULL && + demandZone.IsValid(); + } + + // + bool HasWaitingZones() + { + return HasChild(waitingZones); + } + + // + int CountWaitingZones() + { + return ArraySize(waitingZones); + } + + // + bool HasUnavailableZones() + { + return HasChild(unavailableZones); + } + + // + int CounUnavailableZones() + { + return ArraySize(unavailableZones); + } + + // + bool HasWaitingBoxes() + { + return HasChild(waitingBoxes); + } + + // + int CountWaitingBoxes() + { + return ArraySize(waitingBoxes); + } + + // + bool HasUnavailableBoxes() + { + return HasChild(unavailableBoxes); + } + + // + int CountUnavailableBoxes() + { + return ArraySize(unavailableBoxes); + } + + // +}; + +// +struct X121SMCStrategyXWZSignalConditions +{ + // + // Props ... + + // + string symbol; + ENUM_TIMEFRAMES period; + + // + double sl; + double reward; + double amountPercent; + ENUM_X_DIRECTION dir; + ENUM_X_POSITION_TYPES type; + + // + // Setup Props ... + + // + datetime setupTime; + datetime triggerTime; + + // + double pivot; + double point; + double sls[]; + double targets[]; + + // + XBoxZone signalBox; + + // + ENUM_X121SMC_XWZ_PRIORITY priority; + ENUM_X121SMC_XWZ_PROVIDERS provider; + + // + // Constructor ... + X121SMCStrategyXWZSignalConditions() + { + 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; + + // + ExtensionClean(); + + // + ZeroMemory(this); + } + + /** + * 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 ... + + /** + * Clean Additional Properties ... + */ + void ExtensionClean() + { + // + pivot = 0; + point = 0; + + // + reward = 0; + amountPercent = 0; + + // + Clean(sls); + Clean(targets); + signalBox.Clean(); + + // + provider = X121SMC_XWZ_PROVIDER_NONE; + } + + // + // + // + + // + void UpdateTo(datetime value = NULL) + { + // + value = NormalizeTime(value); + + // + int count = 0; + bool has = false; + } + + // +}; + +// +// Extension Functions ... + +// \ No newline at end of file diff --git a/BKPS/14031218/X121SMCEA/Strategy/x-121.smc.strategy.class.ex5 b/BKPS/14031218/X121SMCEA/Strategy/x-121.smc.strategy.class.ex5 new file mode 100644 index 0000000..6f01d4a Binary files /dev/null and b/BKPS/14031218/X121SMCEA/Strategy/x-121.smc.strategy.class.ex5 differ diff --git a/BKPS/14031218/X121SMCEA/Strategy/x-121.smc.strategy.class.mq5 b/BKPS/14031218/X121SMCEA/Strategy/x-121.smc.strategy.class.mq5 new file mode 100644 index 0000000..eab17ad --- /dev/null +++ b/BKPS/14031218/X121SMCEA/Strategy/x-121.smc.strategy.class.mq5 @@ -0,0 +1,1064 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XCX121SMCStrategy +// 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-121.smc.base.strategy.class.mq5" +#include "../Classes/x-121.smc.market.cycle.helper.class.mq5" + +// +#include "../Signals/x-121.smc.xwz.signal.class.mq5" + +// +// Definitions ... + +// +// XStrategy Class Implementation(s) ... +class XCX121SMCStrategy : public XCX121SMCBaseStrategy +{ + // + // Public ... + public: + // + // Props ... + bool useXWZSignal; + XCX121SMCXWZSignalDetector *mXWZSignalDetector; + X121SMCStrategySignalProviderData cycleProvider; + + // + // Constructor(s) ... + void XCX121SMCStrategy( + // + // Base ... + string _symbol, // Trading Symbol + ENUM_TIMEFRAMES _period // Trading TimeFrame + ) + : XCX121SMCBaseStrategy(_symbol, _period) + { + // + InitialHelpers(); + + // + mXWZSignalDetector = new XCX121SMCXWZSignalDetector( + _symbol, + _period // + ); + } + + // + // Deconstructur ... + void ~XCX121SMCStrategy() + { + Destroy(); + } + + // + // Getter(s) / Setter(s) ... + + /** + * Get Max Allowed Required POI(s) to Find ... + * + * @return ( int ) + */ + int MaxAllowedRequiredPOIs() + { + return mMaxAllowedRequiredPOIs; + } + + /** + * Set Max Allowed Required POI(s) to Find ... + * + * @param value: number of Required POIs + */ + void MaxAllowedRequiredPOIs(int value) + { + // + if (value < 0) + { + value = 0; + } + + // + mMaxAllowedRequiredPOIs = value; + } + + // + // Overrides Actions ... + + /** + * Destroy All Class Implementations ... + */ + void Destroy() override + { + // + ZeroMemory(mDecisionCycleHelper); + ZeroMemory(mAnalyseCycleHelper); + ZeroMemory(mConsolidationCycleHelper); + ZeroMemory(mVisionCycleHelper); + + // + ZeroMemory(mXWZSignalDetector); + + // + cycleProvider.Destroy(); + } + + /** + * Check Conditions For Signal ... + */ + bool HasSignal( + XSignal &signal, + X121SMCStrategyConditions &conditions // + ) override + { + // + bool result = false; + + // + signal.Clean(); + conditions.Clean(); + + // + int pushers = 0; + + // + double sl = 0; + double tp = 0; + double risk = 0; + double entry = 0; + double reward = 0; + double r2r = R2R(); + string provider = ""; + double volume = Volume(); + ENUM_POSITION_TYPE type = POSITION_TYPE_BUY; + ENUM_X_ORDER_MODES mode = X_ORDER_MODE_MARKET; + + // + bool hasLong = false; + bool hasShort = false; + + // + double selectedSL = 0; + + // + // Start Calculations ... + + // + // Retrieve Common Data ... + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + datetime cTime = TimeCurrent(); + + // + // Required Value For SL/TP Calculations ... + double points = GetPoints(symbol); + double pip = GetPipPrice(symbol); + double pip2 = 2 * pip; + + // + conditions.time = cTime; + conditions.symbol = symbol; + conditions.period = period; + + // + // Check Spread for Signalling Conditions ... + // TODO: Uncomment this ... + // bool isSpreadPassed = IsSpreadPass(); + // result = isSpreadPassed; + // if (!result) + // { + // // + // conditions.Clean(); + // return result; + // } + + // + // Detect Signal Conditions ... + bool hasSignal = false; + + // + bool hasXWZSignal = false; + + // + // XSupDemOBS Signal ... + X121SMCStrategyXWZSignalConditions mXWZConditions; + if (useXWZSignal && !hasSignal) + { + // + hasXWZSignal = DetectXWZSignal( + conditions, + mXWZConditions // + ); + hasSignal = hasXWZSignal; + } + + // + result = hasSignal; + if (!result) + { + // + conditions.Clean(); + return result; + } + + // + // Combine all Signals Conditions ... + selectedSL = conditions.sl; + provider = conditions.provider; + + // + hasLong = + // + IsBullish(conditions.signalDir) + // + ; + + // + hasShort = + // + IsBearish(conditions.signalDir) + // + ; + + // + result = hasLong || + hasShort; + + // + // Rmove Signal Condition ... + if (result) + { + // + // TYPE ... + type = + hasLong + ? POSITION_TYPE_BUY + : POSITION_TYPE_SELL; + ENUM_X_POSITION_TYPES xType = + hasLong + ? X_POSITION_TYPE_LONG + : X_POSITION_TYPE_SHORT; + + // + entry = GetEntry( + conditions.symbol, + type // + ); + + // + double slAddition = 0; + sl = + hasLong + ? selectedSL - slAddition + : selectedSL + slAddition; + + // + // RISK Reward ... + risk = + hasLong + ? entry - sl + : sl - entry; + reward = risk * r2r; + tp = + hasLong + ? entry + reward + : entry - reward; + + // + signal.sl = sl; + signal.tp = tp; + signal.type = type; + signal.mode = mode; + signal.entry = entry; + signal.volume = volume; + signal.symbol = symbol; + signal.period = period; + signal.pushers = pushers; + signal.provider = provider; + signal.time = TimeCurrent(); + + // + Copy( + conditions.targets, + signal.targets // + ); + + // + result = PrepareSignal(signal); + + // + if (result) + { + // + if (useXWZSignal && + hasXWZSignal) + { + // + // Configuring Amount Percent and ETC ... + bool ignoreEAVolume = mXWZConditions.reward > 0 && + mXWZConditions.amountPercent > 0; + if (ignoreEAVolume) + { + // + double cReward = mXWZConditions.reward; + double cAmountPercent = mXWZConditions.amountPercent; + + // + double cRiskReward = risk * cReward; + double cTP = hasLong + ? entry + cRiskReward + : entry - cRiskReward; + + // + double balance = mAccount.GetBalance(); + double cRiskAmount = balance * cAmountPercent / 100; + double cRiskInPoints = risk / points; + double cVolume = mAccount.CalculateVolume( + signal.symbol, + cRiskAmount, + cRiskInPoints // + ); + cVolume = NormalizeVolume(cVolume, signal.symbol); + + // + if (cVolume > 0) + { + // + signal.ignoreEAVolume = ignoreEAVolume; + signal.volume = cVolume; + } + } + } + + // + // Draw Signal Oject ... + XCSignalObject *iSignalObj; + bool isCreated = mVisionCycleHelper + .mPOIDrawer + .DrawSignal(signal, iSignalObj); + if (isCreated) + { + // + mSignalDrawnObjects.Add(iSignalObj); + + // + int maxAllowedDrawnSignals = 15; + int count = mSignalDrawnObjects.Total(); + if (count > maxAllowedDrawnSignals) + { + // + int to = count - maxAllowedDrawnSignals; + mSignalDrawnObjects.DeleteRange( + 0, + to // + ); + } + } + } + + // + hasLong = false; + hasShort = false; + } + + // + mXWZConditions.Clean(); + + // + return result; + } + + /** + * Check for any Guard Actions ... + */ + bool CheckGuard( + X121SMCGuard &guards[], + const XPosition &positions[] // + ) override + { + // + bool result = false; + + // + Clean(guards); + + // + int count = ArraySize(positions); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + // XWZ Guard Detection ... + if (useXWZSignal) + { + // + X121SMCGuard xwzGuards[]; + bool hasGuard = mXWZSignalDetector.DetectGuards( + xwzGuards, + positions, + cycleProvider // + ); + + // + if (hasGuard) + { + // + Copy( + xwzGuards, + guards, + false // + ); + } + + // + Clean(xwzGuards); + } + + // + count = ArraySize(guards); + result = IsValidSize(count); + + // + return result; + } + + /** + * Update all Requirements without waiting ... + */ + void DoUnwaitedTicksWork() override + { + } + + /** + * Customize Strategy Identifier ... + */ + string GetTag() override + { + return X121SMCStrategyToken; + } + + // + // Protected ... + protected: + // + + // + // Props ... + CArrayObj mSignalDrawnObjects; + + // + // XC121SMCCycleHelper *mTriggerCycleHelper; + XC121SMCCycleHelper *mDecisionCycleHelper; + XC121SMCCycleHelper *mAnalyseCycleHelper; + XC121SMCCycleHelper *mVerificationCycleHelper; + XC121SMCCycleHelper *mConsolidationCycleHelper; + XC121SMCCycleHelper *mVisionCycleHelper; + + // + // Actions ... + + // + // Signalling Functions ... + + // + // XWZ Signal ... + bool DetectXWZSignal( + X121SMCStrategyConditions &conditions, + X121SMCStrategyXWZSignalConditions &xWZConditions // + ) + { + // + bool result = false; + + // + // Validate Cycle Helpers ... + result = + // + mVisionCycleHelper != NULL && + mAnalyseCycleHelper != NULL && + mDecisionCycleHelper != NULL && + mConsolidationCycleHelper != NULL + // + ; + if (!result) + { + return result; + } + + // + bool isBullish = false; + bool isBearish = false; + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + datetime cTime = TimeCurrent(); + + // + ENUM_X_121_SMC_PROVIDERS provider = X_121_SMC_PROVIDER_XWZ; + string providerStr = ToString(provider); + + // + // Detect Setup Conditions ... + datetime setupTime = mXWZSignalDetector.mConditions.setupTime; + bool isSetuped = mXWZSignalDetector.mConditions.IsSetuped(); + ENUM_X_DIRECTION setupDir = mXWZSignalDetector.mConditions.dir; + if (!isSetuped) + { + // + // Detect Signal Setup ... + isSetuped = mXWZSignalDetector.DetectSignalSetup( + cycleProvider // + ); + + // + setupDir = mXWZSignalDetector.mConditions.dir; + setupTime = mXWZSignalDetector.mConditions.setupTime; + + // + if (isSetuped) + { + // + int items = mXWZSignalDetector + .AddConditionsIfNotExists(); + + // + mXWZSignalDetector.mConditions.Clean(); + } + } + + // + int conditionsCount = ArraySize(mXWZSignalDetector.mConditionsCollection); + result = IsValidSize(conditionsCount); + if (!result) + { + return result; + } + + // + // Looking For Conditions ... + int selectedIndex = 0; + X121SMCStrategyXWZSignalConditions mTmpConditions[]; + Copy( + mXWZSignalDetector.mConditionsCollection, + mTmpConditions // + ); + X121SMCStrategyXWZSignalConditions mConditions; + for (int i = 0; i < conditionsCount; i++) + { + // + // Check Triggers ... + bool canTrigger = mTmpConditions[i].CanTrigger(); + datetime triggerTime = mTmpConditions[i].triggerTime; + if (!canTrigger) + { + // + // Detect Signal Trigger ... + canTrigger = mXWZSignalDetector + .DetectSignalTrigger( + mTmpConditions[i], + cycleProvider // + ); + + // + result = canTrigger; + if (!result) + { + // + bool isISetuped = mTmpConditions[i].IsSetuped(); + if (!isISetuped) + { + // + ArrayRemove( + mXWZSignalDetector.mConditionsCollection, + i, + 1 // + ); + } + continue; + } + + // + triggerTime = mTmpConditions[i].triggerTime; + } + + // + if (canTrigger) + { + // + selectedIndex = i; + mConditions = mTmpConditions[i]; + break; + } + } + + // + result = IsValid(mConditions.setupTime) && + HasDirection(mConditions.dir); + if (!result) + { + return result; + } + + // + // Remove Selected Index from Main Collection ... + ArrayRemove( + mXWZSignalDetector.mConditionsCollection, + selectedIndex, + 1 // + ); + + // + // Check Signal Direction ... + isBullish = IsBullish(mConditions.dir); + isBearish = IsBearish(mConditions.dir); + result = isBullish || + isBearish; + if (!result) + { + return result; + } + + // + // Issues Signal on Conditions ... + conditions.sl = mConditions.sl; + conditions.provider = providerStr; + conditions.signalDir = mConditions.dir; + + // + Copy( + mConditions.targets, + conditions.targets // + ); + + // + xWZConditions = mConditions; + + // + mConditions.Clean(); + + // + return result; + } + + // + // Private ... + private: + // + // Props ... + + // + int mMaxAllowedRequiredPOIs; // Max Allowed Required POI(s) to Find ... + + /** + * Initial Required Indicators Helper ... + */ + void InitialHelpers() + { + // + useXWZSignal = true; + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + if (mMaxAllowedRequiredPOIs <= 0) + { + mMaxAllowedRequiredPOIs = 0; + } + + // + // Short ... + ENUM_X_PERIOD_METHOD scMethod = X_PERIOD_AUTO; // How to Find Period + ENUM_TIMEFRAMES scPeriod = NULL; // Time Period + + // + // Medium ... + ENUM_X_PERIOD_METHOD mcMethod = X_PERIOD_AUTO; // How to Find Period + ENUM_TIMEFRAMES mcPeriod = NULL; // Time Period + + // + // Long ... + ENUM_X_PERIOD_METHOD lcMethod = X_PERIOD_AUTO; // How to Find Period + ENUM_TIMEFRAMES lcPeriod = NULL; // Time Period + + // + // Hind ... + ENUM_X_PERIOD_METHOD hcMethod = X_PERIOD_AUTO; // How to Find Period + ENUM_TIMEFRAMES hcPeriod = NULL; // Time Period + + // + // XPV ... + X121Inputs x121Inputs; + + // + x121Inputs.Default(); + + // + bool showAll = false; + + // + x121Inputs.showRSI = false; + + // + // XPV ... + + // + x121Inputs.xpvInputs.scMethod = scMethod; + x121Inputs.xpvInputs.scPeriod = scPeriod; + x121Inputs.xpvInputs.mcMethod = mcMethod; + x121Inputs.xpvInputs.mcPeriod = mcPeriod; + x121Inputs.xpvInputs.lcMethod = lcMethod; + x121Inputs.xpvInputs.lcPeriod = lcPeriod; + x121Inputs.xpvInputs.hcMethod = hcMethod; + x121Inputs.xpvInputs.hcPeriod = hcPeriod; + + // + x121Inputs.xhkInputs.xhkIgnoreSmoothingShadows = true; + + // + x121Inputs.xatrInputs.atrMultiplier = 1.5; + x121Inputs.xatrInputs.atrSmoothingMode = X_MA_MODE_EMA; + + // + // XTREND ... + x121Inputs.xtrendInputs.showUpTrend = showAll || false; + x121Inputs.xtrendInputs.showDownTrend = showAll || false; + x121Inputs.xtrendInputs.showOnlyTrendStart = showAll || false; + + // + // XPV ... + x121Inputs.xpvInputs.showSar = showAll || true; + x121Inputs.xpvInputs.showPeaks = showAll || true; + x121Inputs.xpvInputs.showVales = showAll || true; + x121Inputs.xpvInputs.showGoldenZones = showAll || true; + + // + // XHK ... + + // + x121Inputs.xhkInputs.drawRawXHKCandles = showAll || false; + x121Inputs.xhkInputs.drawSmoothedXHKCandles = showAll || true; + + // + // XATR ... + x121Inputs.xatrInputs.showATRUpper = showAll || false; + x121Inputs.xatrInputs.showATRLower = showAll || false; + + // + // XSTR ... + x121Inputs.xstrInputs.showStr = showAll || false; + x121Inputs.xstrInputs.showStrUpper = showAll || false; + x121Inputs.xstrInputs.showStrLower = showAll || false; + + // + // XCHE ... + x121Inputs.xcheInputs.showLE1 = showAll || false; + x121Inputs.xcheInputs.showLE2 = showAll || false; + x121Inputs.xcheInputs.showSE1 = showAll || false; + x121Inputs.xcheInputs.showSE2 = showAll || false; + + // + // XDON ... + x121Inputs.xdonInputs.showOpen = showAll || false; + x121Inputs.xdonInputs.showClose = showAll || false; + x121Inputs.xdonInputs.showLow = showAll || false; + x121Inputs.xdonInputs.showHigh = showAll || false; + + // + // XVWAP ... + x121Inputs.xvwapInputs.showVWapFast = showAll || false; + x121Inputs.xvwapInputs.showVWapMedium = showAll || false; + x121Inputs.xvwapInputs.showVWapSlow = showAll || false; + + // + // X3MA ... + x121Inputs.x3maInputs.showX3MaFast = showAll || false; + x121Inputs.x3maInputs.showX3MaMid = showAll || false; + x121Inputs.x3maInputs.showX3MaSlow = showAll || false; + + // + // Initialize Cycle Helpers ... + + // + bool isInited = false; + + // + int requiredPOIS = MaxAllowedRequiredPOIs(); + + // + // Decision Cycle ... + mDecisionCycleHelper = new XC121SMCCycleHelper(); + isInited = mDecisionCycleHelper.Init( + symbol, + PERIOD_M5, + x121Inputs, + requiredPOIS // + ); + if (isInited) + { + // + // Configure POI Drawer ... + color bullishColor = clrDodgerBlue; + color bearishColor = clrSienna; + + // + // Bars ... + mDecisionCycleHelper.mPOIDrawer.BarBullishColor(bullishColor); + mDecisionCycleHelper.mPOIDrawer.BarBearishColor(bearishColor); + + // + // Swings ... + mDecisionCycleHelper.mPOIDrawer.SwingLowColor(bullishColor); + mDecisionCycleHelper.mPOIDrawer.SwingHighColor(bearishColor); + + // + // Momentum ... + mDecisionCycleHelper.mPOIDrawer.BullishMomentumBarColor(bullishColor); + mDecisionCycleHelper.mPOIDrawer.BearishMomentumBarColor(bearishColor); + + // + // Rejection ... + mDecisionCycleHelper.mPOIDrawer.BullishRejectionBarColor(bullishColor); + mDecisionCycleHelper.mPOIDrawer.BearishRejectionBarColor(bearishColor); + + // + // Support and Resistance ... + mDecisionCycleHelper.mPOIDrawer.SupportZoneColor(bullishColor); + mDecisionCycleHelper.mPOIDrawer.ResistanceZoneColor(bearishColor); + + // + // Demand and Supply ... + mDecisionCycleHelper.mPOIDrawer.DemandZoneColor(bullishColor); + mDecisionCycleHelper.mPOIDrawer.SupplyZoneColor(bearishColor); + + // + // Order Blocks ... + mDecisionCycleHelper.mPOIDrawer.BullishOrderBlockColor(bullishColor); + mDecisionCycleHelper.mPOIDrawer.BearishOrderBlockColor(bearishColor); + + // + // Fair Value Gaps ... + mDecisionCycleHelper.mPOIDrawer.BullishFVGColor(bullishColor); + mDecisionCycleHelper.mPOIDrawer.BearishFVGColor(bearishColor); + } + + // + // Analyse Cycle ... + mAnalyseCycleHelper = new XC121SMCCycleHelper(); + isInited = mAnalyseCycleHelper.Init( + symbol, + PERIOD_M15, + x121Inputs, + requiredPOIS // + ); + if (isInited) + { + // + // Configure POI Drawer ... + color bullishColor = clrMediumSeaGreen; + color bearishColor = clrBlueViolet; + + // + // Bars ... + mAnalyseCycleHelper.mPOIDrawer.BarBullishColor(bullishColor); + mAnalyseCycleHelper.mPOIDrawer.BarBearishColor(bearishColor); + + // + // Swings ... + mAnalyseCycleHelper.mPOIDrawer.SwingLowColor(bullishColor); + mAnalyseCycleHelper.mPOIDrawer.SwingHighColor(bearishColor); + + // + // Momentum ... + mAnalyseCycleHelper.mPOIDrawer.BullishMomentumBarColor(bullishColor); + mAnalyseCycleHelper.mPOIDrawer.BearishMomentumBarColor(bearishColor); + + // + // Rejection ... + mAnalyseCycleHelper.mPOIDrawer.BullishRejectionBarColor(bullishColor); + mAnalyseCycleHelper.mPOIDrawer.BearishRejectionBarColor(bearishColor); + + // + // Support and Resistance ... + mAnalyseCycleHelper.mPOIDrawer.SupportZoneColor(bullishColor); + mAnalyseCycleHelper.mPOIDrawer.ResistanceZoneColor(bearishColor); + + // + // Demand and Supply ... + mAnalyseCycleHelper.mPOIDrawer.DemandZoneColor(bullishColor); + mAnalyseCycleHelper.mPOIDrawer.SupplyZoneColor(bearishColor); + + // + // Order Blocks ... + mAnalyseCycleHelper.mPOIDrawer.BullishOrderBlockColor(bullishColor); + mAnalyseCycleHelper.mPOIDrawer.BearishOrderBlockColor(bearishColor); + + // + // Fair Value Gaps ... + mAnalyseCycleHelper.mPOIDrawer.BullishFVGColor(bullishColor); + mAnalyseCycleHelper.mPOIDrawer.BearishFVGColor(bearishColor); + } + + // + // Consolidation Cycle ... + mConsolidationCycleHelper = new XC121SMCCycleHelper(); + isInited = mConsolidationCycleHelper.Init( + symbol, + PERIOD_H1, + x121Inputs, + requiredPOIS // + ); + if (isInited) + { + // + // Configure POI Drawer ... + color bullishColor = clrLime; + color bearishColor = clrRed; + + // + // Bars ... + mConsolidationCycleHelper.mPOIDrawer.BarBullishColor(bullishColor); + mConsolidationCycleHelper.mPOIDrawer.BarBearishColor(bearishColor); + + // + // Swings ... + mConsolidationCycleHelper.mPOIDrawer.SwingLowColor(bullishColor); + mConsolidationCycleHelper.mPOIDrawer.SwingHighColor(bearishColor); + + // + // Momentum ... + mConsolidationCycleHelper.mPOIDrawer.BullishMomentumBarColor(bullishColor); + mConsolidationCycleHelper.mPOIDrawer.BearishMomentumBarColor(bearishColor); + + // + // Rejection ... + mConsolidationCycleHelper.mPOIDrawer.BullishRejectionBarColor(bullishColor); + mConsolidationCycleHelper.mPOIDrawer.BearishRejectionBarColor(bearishColor); + + // + // Support and Resistance ... + mConsolidationCycleHelper.mPOIDrawer.SupportZoneColor(bullishColor); + mConsolidationCycleHelper.mPOIDrawer.ResistanceZoneColor(bearishColor); + + // + // Demand and Supply ... + mConsolidationCycleHelper.mPOIDrawer.DemandZoneColor(bullishColor); + mConsolidationCycleHelper.mPOIDrawer.SupplyZoneColor(bearishColor); + + // + // Order Blocks ... + mConsolidationCycleHelper.mPOIDrawer.BullishOrderBlockColor(bullishColor); + mConsolidationCycleHelper.mPOIDrawer.BearishOrderBlockColor(bearishColor); + + // + // Fair Value Gaps ... + mConsolidationCycleHelper.mPOIDrawer.BullishFVGColor(bullishColor); + mConsolidationCycleHelper.mPOIDrawer.BearishFVGColor(bearishColor); + } + + // + // Vision Cycle ... + mVisionCycleHelper = new XC121SMCCycleHelper(); + isInited = mVisionCycleHelper.Init( + symbol, + PERIOD_H4, + x121Inputs, + requiredPOIS // + ); + if (isInited) + { + // + // Configure POI Drawer ... + color bullishColor = clrAqua; + color bearishColor = clrMagenta; + + // + // Bars ... + mVisionCycleHelper.mPOIDrawer.BarBullishColor(bullishColor); + mVisionCycleHelper.mPOIDrawer.BarBearishColor(bearishColor); + + // + // Swings ... + mVisionCycleHelper.mPOIDrawer.SwingLowColor(bullishColor); + mVisionCycleHelper.mPOIDrawer.SwingHighColor(bearishColor); + + // + // Momentum ... + mVisionCycleHelper.mPOIDrawer.BullishMomentumBarColor(bullishColor); + mVisionCycleHelper.mPOIDrawer.BearishMomentumBarColor(bearishColor); + + // + // Rejection ... + mVisionCycleHelper.mPOIDrawer.BullishRejectionBarColor(bullishColor); + mVisionCycleHelper.mPOIDrawer.BearishRejectionBarColor(bearishColor); + + // + // Support and Resistance ... + mVisionCycleHelper.mPOIDrawer.SupportZoneColor(bullishColor); + mVisionCycleHelper.mPOIDrawer.ResistanceZoneColor(bearishColor); + + // + // Demand and Supply ... + mVisionCycleHelper.mPOIDrawer.DemandZoneColor(bullishColor); + mVisionCycleHelper.mPOIDrawer.SupplyZoneColor(bearishColor); + + // + // Order Blocks ... + mVisionCycleHelper.mPOIDrawer.BullishOrderBlockColor(bullishColor); + mVisionCycleHelper.mPOIDrawer.BearishOrderBlockColor(bearishColor); + + // + // Fair Value Gaps ... + mVisionCycleHelper.mPOIDrawer.BullishFVGColor(bullishColor); + mVisionCycleHelper.mPOIDrawer.BearishFVGColor(bearishColor); + } + + // + // Initial Cycle Provider ... + cycleProvider.Init( + mDecisionCycleHelper, + mAnalyseCycleHelper, + mConsolidationCycleHelper, + mVisionCycleHelper // + ); + } + + // +}; + +// \ No newline at end of file